Repository navigation
fix(automation): reject stale cadence confirmations - #6201
huangruiteng merged 1 commit into
Conversation
A confirmation could observe its reservation before taking the store lock, then find that a newer manual admission had replaced it. The locked path treated the missing request as an already-confirmed replay and allowed the stale Turn to start. Make the locked store authoritative: only a matching started record is an idempotent confirmation, while a missing request fails closed. Cover the replacement interleaving with a deterministic regression test. Signed-off-by: Duang777 <duangjl007@gmail.com>
|
@loopx-agent review |
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent; gpt-6.1-sol; OpenAI; runtime_reported; xhigh
Exact head: f53858e9e8d2bbe0365dc2dada9914dc50c36280; immutable base: 8d5a6fc170422ff4ff78818898b172064b1e1591. 全量2文件 +39/-0,未查询、轮询或等待CI。
动机
使用受最小调度间隔约束的 managed Turn(受管执行轮次)的操作者。 旧轮次先读到自己的预约,再等写锁时预约被新轮次替换;旧版本仍报告确认成功,新版本明确拒绝旧请求并保留新预约。 真实文件锁和实际 owner 的两次读取复现了旧版 confirmed=true、新版 confirmed=false/reservation_missing;新预约字节不变,合法确认和重放仍成功。 本 PR 只修复现有调度确认的竞态;不增加设置、权限、UI步骤或新状态格式,也不宣称所有宿主醒来前已阻止模型成本。
没有针对本竞态的书面spec或关联issue;先读变更前的预约/确认合同与managed调用方,再独立复现。已有缺请求时拒绝、合法相同请求可重放的语义是判断依据,未以新增测试输出定义正确行为。召回经验仅用于检查真实owner与后续调用者;不继承其他案例结论,不增加本修复无关的UI或付费模型前置。
改动思路
在已有锁内重新核对同一 Agent/request 的匹配集合即可修复误确认;无需第二调度器、Python规则或额外配置开关。 本 PR 只修复现有调度确认的竞态;不增加设置、权限、UI步骤或新状态格式,也不宣称所有宿主醒来前已阻止模型成本。
仍由 TypeScript cadence owner 决定准入,Python只发送已准入请求身份并检查 confirmed。确认观察成功的 ok:true 不等于确认获准:confirmed:false 会让既有调用方在启动host前抛出错误。没有复制Python规则或新增状态/配置。相邻未来维护检查覆盖快读与锁内读:它们已在同一个函数,四行修复足够,无需额外抽象。
具体改动
confirmAutomationStart的锁内record先检查同一Agent/request匹配集合;为空直接返回既有reservation_missing,在任何started写入之前结束。replacement regression通过实际A/B预约与第一读的旧快照,覆盖原先false-success;检查新预约仍为reserved,并恢复builtin读钩子。两处生产/测试改动均完整读过。- 不变的
managed_cadence_start保留request_id,拒绝false确认;现有journal恢复不受本补丁另造规则。
对主干的风险
独立反例通过真实文件、withFileMutationLock、实际load/decode及atomic writer安排“快读A→锁持有者写B→锁内读B”。读钩子只在真实读取完成后发屏障信号,返回原始实际字节,不伪造旧读取结果。B的fixture字节由真实admit owner生成,整个实验使用隔离合成Goal,未触碰活动Goal。
相同输入:base错误 true/already_confirmed,head正确 false/reservation_missing;B预约前后SHA一致,仍reserved。无配置/无文件、缺请求、外来Agent、精确确认与重放的全部响应相同;合法新请求随后 start_confirmed,重放 already_confirmed 且无字节写入。旧9个TS测试全部绿仍会漏掉此反例,因此并非只跑新增测试。
当前head 10 TS tests / 3 Python managed-start recovery tests通过;不可变base对应 9 TS / 3 Python通过。changed-source语义advisory先跑,0支持的新词表载体只表示扫描能力范围;完整semantic、typecheck、diff-check及当前native风险canary(3个直接检查、16个风险检查,0失败/警告/人工hold)通过。legacy store decode、90分钟floor、相同request重放、自动化scope与其它Agent拒绝保留。没有新frontend旅程或现有控制变化需要补UI;实际付费host、长期并发频率和fleet成本未测,不以合成consumer callback冒充真实模型执行。
我的整体评价
APPROVE。 当前有界身份修复有正向价值:关闭被替换旧请求的误确认路径,避免错误后续host尝试;新请求和合法恢复继续可用。增加一次已有锁内数组长度检查,没有额外IO/锁/状态或用户操作,因此机制成本很小。长期重复执行的可靠性预期正向;未测净延迟、token或收益比例,不能宣称全体Agent的长程效率已验证。合并仍由维护者执行。
English verdict: APPROVE - f53858e. An independent real-file/real-lock base/head counterexample reproduces false confirmation after request replacement and verifies the corrected refusal with unchanged replacement bytes. All non-race outputs and effects, default-off no-write behavior, exact replay and recovery are preserved; head10/base9 TS tests and3 Python managed-start tests per revision, typecheck/semantic/risk checks are recorded. No CI, paid host execution or fleet utility claim; maintainer merge remains separate.
Goal And Delivered Outcome
main@8d5a6fc17; no public issue exists for this defect.confirmAutomationStartused a pre-lock reservation hit to enter the mutation path, but its locked read reported success even when that request had been replaced.confirmed: trueand could start a second managed Turn; it now returnsconfirmed: falsewithreservation_missingand leaves the replacement reservation unchanged.main.Author Declaration
Implemented against
confirmAutomationStartnode --test tests/control_plane_ts/automation_cadence.test.tsrecordinautomation_cadence.tsconfirmation rejects a reservation replaced before its locked readconfirmAutomationStartScope And Continuation
Validation
f53858e9e8d2bbe0365dc2dada9914dc50c36280regression_paritypassedtrue !== false, then passed after the locked missing-request branch was added.unitpassednode --test tests/control_plane_ts/automation_cadence.test.ts: 10 passed, including replacement preservation and exact replay.integrationpassedtests/test_loopx_turn_executor.pymanaged-start tests passed through the real Python adapter and TypeScript cadence store.staticpassednpm run typecheck:control-planecompleted successfully.unitpassednpm run test:control-plane: 4,396 passed, 37 skipped, 0 failed.Frontend / Visual Evidence
Type of Change
LoopX Area
Technical Direction
Shared-authority RFC fixture impact
N/A. This change does not modify shared Goal Authority providers, schemas, routing, promotion, or compatibility projections.
Boundary Checklist
.loopx/,.codex/goals/, and liveACTIVE_GOAL_STATE.md).none.Signed-off-bytrailer (git commit -s).