Repository navigation
Replies: 1 comment
|
按当前 有三处值得更新到这份 8 月提案里: 1. 统一调用入口时,保留领域决策的细节。 当前入口已经同时投影 2. 区分历史视图、权威事务日志,以及实际副作用的恢复。 现有 权威 store 已有一个可直接复用的反例(File/SQLite): 这里比较完整的 3. 事件驱动试点先测通知链,不重造 Task/Turn 规则。 可以先做提案里的 这个切片可以用同一组条件对照 timer 路径:唤醒延迟、重复通知、消费者重启/offset 恢复、准入后 lease 变化,以及 writeback 后响应丢失。验收应检查独立的当前 head、历史事务和副作用次数,不能只看队列消费成功。当前 R5 后续交付边界 也保留了安装态升级、恢复和 provider 资格的独立验收。 我为这次回复运行了 6 个 File/SQLite 历史/并发重试检查,以及 14 个结算故障/顺序用例 + 4 个隔离真实 CLI 检查:全部通过;运行目录的相关 control-plane/test 源码与上述 main 版本一致。它们覆盖原回执、后续状态不回退、单次提交/结算和 open Todo 的接续。它们没有执行这个事件总线试点,也没有测调度延迟、token 节省或跨 Host 可靠性。provider 反例、真实 CLI 接续用例 English: A useful first pilot is a dependency event that wakes the existing admission path. Keep event delivery, current execution authority and recovery of a committed operation separate. The pinned File/SQLite checks preserve later state when an older operation is retried; they do not establish external exactly-once execution or qualify an event-driven scheduler. This follow-up maps the proposal to current source and gives a bounded experiment, with its remaining acceptance explicit. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
RFC: 事件驱动控制面与统一策略决策架构
loopx/loopx/control_plane1. 摘要
本 RFC 提议围绕五项架构原则,对 LoopX 控制面进行增量演进:
本提案刻意保持增量。
前四项变更可以在不改变现有执行路径的前提下引入。事件驱动调度被单独视为行为变更阶段,需要专门评审。
首要目标不是替换现有控制面,而是引入更清晰的架构边界,并提供一条通向更简事件驱动模型的迁移路径。
2. 动机
当前
control_plane已经具备大部分所需能力:问题主要不是功能缺失。
问题是:若干架构职责目前分散在不同模块中,且经常由 heartbeat 路径组装。
例如,判定「Agent 是否应该运行」可能需要理解:
类似地,执行事实以事件形式存在,但决策历史、成本归因、恢复 Checkpoint 并未通过一致的投影暴露。
这带来若干问题:
3. 目标
本 RFC 的目标如下:
G1. 引入统一的策略决策契约
调用方应能直接询问:
而无需手动组装 quota、capability 与 scope 检查。
G2. 保留既有策略逻辑
新的 Policy 层应组装并归一化现有规则,而非重新实现。
G3. 让决策可审计
系统应能回答:
并且基于持久化事件回答。
G4. 提供可复用的用量/成本投影
现有 spend 事件应可按以下维度查询:
且不复制结算事实。
G5. 提供 Task 级恢复
长任务应能从 checkpoint 续跑,且不引入第二个权威状态存储。
G6. 建立事件驱动执行路径
状态变化应最终能唤醒调度器,而不依赖周期性的 heartbeat 轮询。
4. 非目标
本 RFC 不提议:
5. 设计原则
5.1 复用,不重写
现有实现仍然是各自领域的权威。
新层次起初只是门面(facade)、适配器(adapter)与投影(projection)。
5.2 单一事实源
事件仍是「发生了什么」的权威记录。
投影是派生的视图。
Checkpoint 是恢复快照,不是第二事实源。
5.3 策略做决策;调度器管时机;Worker 执行
职责应收敛为:
5.4 事件存储(Event Store)与事件总线(Event Bus)是不同关注点
事件存储回答:
事件总线 / 队列回答:
现有 rollout 事件日志不应被自动当作低延迟事件总线,除非其排序、投递、重试、消费偏移与扇出语义被明确验证充分。
6. 目标架构
目标架构为:
这是目标方向,而非要求一次性实现所有组件。
7. C1 —— 统一策略决策契约
7.1 当前问题
当前执行决策分散在:
quota/should_run.pyquota/should_run_packet.pyheartbeat_receipt.pyagents/capability_gate.pyagents/agent_scope.pyscheduler/execution_context.py不同层次使用不同的表示,例如:
对于「这个 Task 是否应该运行?」这一问题,没有单一稳定契约。
7.2 提议的变更
新增:
公开接口变为:
初始决策契约为:
示例:
{ "outcome": "wait", "reason": "quota_backoff", "source": "quota", "retry_at": "2026-08-13T12:30:00Z" }关键区分在于:
这避免了把
backoff、recovery、repair_bridge、ask_owner压扁成无法区分的状态。7.3 实现规则
PolicyEngine不得重复现有领域规则。它应组装现有纯函数:
策略引擎拥有的是组装与归一化,而非底层业务规则。
8. C2 —— 策略决策事件
8.1 当前问题
策略决策在调用方消费完返回值后即消失。
因此系统能记录「一次 Run 发生了」,却无法一致地回答:
8.2 提议的变更
新增:
带独立的记录器:
record_policy_decision(...)架构应为:
策略引擎本身应保持无持久化副作用。
8.3 决策事件
决策事件应包含稳定标识符,例如:
敏感的任务内容与凭据不得持久化。
8.4 去重
重复轮询不得产生无界的相同决策事件。
初始实现应支持以下任一方式:
例如:
通常应可表示为:
而不是四条相同事件。
9. C3 —— 用量与成本投影
9.1 当前问题
原始 spend 事实已存在,但调用方必须手动聚合。
现有结算层负责校验并产生 spend 事实,不负责回答分析型查询。
9.2 提议的变更
新增只读投影:
初始 API 可包括:
投影可提供:
9.3 术语
compute_units不得自动被当作货币成本。第一版应区分:
与:
若供应商定价可用,货币成本可在之后从用量推导。
因此架构应为:
而非假设:
9.4 扩展
第一版实现可直接从既有事件聚合。
若事件量变大,同一投影契约之后可物化(materialize):
本 RFC 不要求引入新的存储系统。
10. C4 —— Task Checkpoint 与重放
10.1 当前问题
运行历史与事件历史提供历史视图,但没有标准化的 Task 级恢复锚点。
长任务在中断后可能不得不从初始状态重新开始。
10.2 提议的模型
新增:
Checkpoint 是恢复优化,不是权威状态存储。
模型为:
恢复变为:
10.3 Checkpoint 契约
一个 checkpoint 至少应包含:
其中
last_event_id尤其重要,它确定了重放应从何处续起。10.4 重放要求
重放必须是:
重放应重建状态,而非执行外部副作用。
例如:
不得在重放过程中意外触发:
10.5 兼容性
Checkpoint/重放最初应与现有 migration 与兼容机制并存。
本 RFC 不要求立即移除
shadow、migration或legacy路径。一旦重放证明了等价恢复语义,可在单独的变更中评估这些机制的缩减或移除。
11. C5 —— 事件驱动调度
11.1 当前问题
Heartbeat 当前承担两个职责:
这导致即使状态毫无变化,周期性轮询仍反复检查状态。
11.2 提议的方向
把 heartbeat 视为若干触发源之一:
所有触发源汇聚到调度器:
因此 heartbeat 变成触发机制,而不再是控制面决策的拥有者。
11.3 事件驱动示例
一个依赖完成:
系统无需等待下一个 heartbeat 间隔。
11.4 重要约束
现有 rollout 事件日志不应自动成为执行事件总线。
若事件驱动调度需要:
则可能需要显式的队列/总线抽象。
事件存储仍负责持久事实与重放。
12. 迁移计划
迁移应分阶段进行。
阶段 1 —— 策略门面(Policy Facade)
新增:
不改动任何现有执行路径。
新增单元测试与契约测试。
阶段 2 —— 决策投影(Decision Projection)
新增:
记录保持可选(opt-in)。
验证:
阶段 3 —— 用量投影(Usage Projection)
新增:
对照现有 spend 事实验证聚合。
结算行为不变。
阶段 4 —— Checkpoint / 重放
新增:
验证:
阶段 5 —— 策略集成(Policy Integration)
评估用以下方式替换 heartbeat 决策组装:
这是现有控制路径可能发生行为变更的第一个阶段。
阶段 6 —— 事件驱动调度试点(Event-Driven Scheduling Pilot)
从一条狭窄的 Task 生命周期开始:
度量:
只有试点成功之后,才应迁移更广泛的 heartbeat 行为。
13. 向后兼容
初始阶段应保留现有行为。
兼容规则为:
新架构最初应表现为现有实现之上的适配器,而非替换它。
任何行为变更型迁移都必须单独评审。
14. 测试策略
每个阶段都应包含契约测试。
策略(Policy)
测试每一条现有决策映射:
并验证归一化后的:
契约。
决策事件(Decision Events)
测试:
用量投影(Usage Projection)
将投影结果与独立聚合的 spend 事件对照。
重放(Replay)
验证:
以及:
事件驱动调度(Event-Driven Scheduling)
测试:
15. 风险
R1. 决策语义丢失
缓解:
使用:
而非仅三个字符串。
R2. 决策事件爆炸
缓解:
使用状态迁移检测或确定性指纹。
R3. 把事件存储误当事件总线
缓解:
将持久事件存储与低延迟事件投递保持为独立抽象。
R4. 重放不兼容
缓解:
对 checkpoint 与状态 schema 做版本管理。
R5. 多事实源
缓解:
事件保持权威。
投影与 checkpoint 是派生产物。
R6. 迁移复杂度
缓解:
先用增量变更,推迟行为变更型重新接线,直到新组件有了独立的测试。
16. 曾考虑的备选方案
备选方案 A —— 继续扩展 heartbeat
作为长期方向被否决,因为 heartbeat 会继续累积:
备选方案 B —— 重写控制面
被否决,因为现有实现已包含大量领域逻辑与兼容行为。
重写会增加迁移风险,且不一定改善概念模型。
备选方案 C —— 引入全新的状态存储
暂被否决。
现有事件基础设施已提供所需的事实源语义。
首要目标应是在现有事实上暴露更好的投影与恢复机制。
备选方案 D —— 把事件存储当作执行队列
被否决,除非现有事件存储能提供显式队列语义。
持久历史与执行投递具有不同的需求。
17. 开放问题
以下问题应在 RFC 评审期间解决,而非藏在实施计划里。
Q1. 决策契约
wait是否应包含显式重试语义?例如:
Q2. 决策事件频率
应记录每一次决策,还是仅记录决策迁移?
Q3. 事件总线
LoopX 是否已有合适的队列/事件投递机制,还是应从事件存储中独立引入一个?
Q4. Checkpoint 存储
checkpoint 应放在:
还是作为被事件引用的独立快照产物?
Q5. 重放边界
哪些 Task 状态迁移被保证可重放?
Q6. 成本语义
第一版投影应只暴露:
还是同时引入货币定价?
Q7. Heartbeat 迁移
在不改变全局行为的前提下,可迁移到事件驱动调度的最小 Task 生命周期是什么?
18. 提议的验收标准
当满足以下条件时,本 RFC 应视为成功验证:
Decision。19. 结论
本提案架构是增量过渡而非重写。
关键的架构转变是:
转向:
最重要的边界不是任何一个新模块。
而是以下各层的分离:
一旦这些边界显式化,现有 LoopX 实现即可增量演进,而无需控制面重写。
因此推荐的实施顺序为:
前四个阶段主要是增量性的。
最后的调度迁移被刻意留作独立的行为变更提案,且只有在既有契约与测试稳定之后才应推进。
All reactions