Repository navigation
fix(turn): keep original settlement steps out of the next Todo - #6245
Conversation
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent | gpt-6.1-sol | OpenAI | runtime_reported | reasoning_effort=xhigh
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
动机
使用 heartbeat 或 CLI 完成任务的 Agent 会遇到这类问题:任务 A 等待依赖后,选择器选中任务 B;旧实现会把 A 的写回步骤保存到 B,覆盖 B 的独立计划。新实现拒绝这次跨任务步骤,保留 B 的原步骤,并允许 A 单独写回、只结算一次。
已通过真实 File/SQLite CLI 和隔离安装包验证:拒绝时不追加 run、不扣额,恢复后 A 单次结算,B 的步骤和等待条件保留。本 PR 不交付本机安装采用、宿主等待周期资格或完整 legacy 退役。安装采用、真实宿主等待周期及既有重规划缺口仍由现有 S7 验收推进。这个缺口会影响后续实际执行方向,继续保留它会让另一个任务承担原任务的步骤。
改动思路
绑定与步骤准入复用现有 TS owner,Python 只传递身份;不新增状态、配置或平行规则。本 PR 交付原 Turn 与后续 Todo 步骤隔离;本机采用和宿主调度仍是已有独立验收。
路径是 CLI 获取原结算身份和当前 canonical 任务事实,经已有 Python bridge 交给 TS lane writer;初次判断与追加前的 source-lock recheck 调用同一规则。原身份与当前选择不符时先拒绝,source-facts CAS 仍处理并发变化。有效匹配步骤和普通无 Turn 绑定步骤保留原注册、runnable、peer 和 CAS 约束。相比另加 Python 判断或新协议,这个直接守卫更小,也没有把修复拆成只有 serializer 的半成品。
具体改动
依据本改动前的 docs/quota-allocation.md,固定 revision c2044e3d0fda34cda73830db4b071dd88b65d844:
Task selection happens first:implemented。步骤只细化任务,不能通过文本或当前 B 的 basis 改写原 A 身份。source-facts fence:implemented。basis 仍是 source facts 的并发围栏,追加前复验保留;它不是任务或 Goal 的新权限。receipt-backed-settlement-progress:implemented。原写回可在 Todo 保持等待时单次结算,另一个 Todo 要经新的 guard 进入。
新双语文档明确披露此前错误接受的跨任务输入现被拒绝;它解释恢复动作,不能用改后的说明替代独立验收。S7 同一 checkpoint 保留 #6243 已有结算进展并补充步骤隔离,不把宿主周期或 fleet 资格写成完成。
关键代码讲解
resolveLaneRecommendation:沿用已有 identity codec 比较 Goal/Agent/Todo;不符返回next_action_task_unavailable和明确恢复文本,不创建 resolution。即使 B 的 read basis 是新的,也不能越过原任务身份。匹配绑定的 alignment 是exact;普通无绑定仍为not_applicable。resolve_refresh_recommendation:向现有 lane bridge 传递原生已验证的身份。state_refresh.py的初次解析和既有提交前锁内复验均走这里,Python 没有另建 eligibility 规则。lane_recommendation_context:只补请求数据,保留已有 TS error adaptation 和 source-facts 读取。普通 read/write 调用仍可省略身份。
对主干的风险
最强反例是“只加 helper 测试通过,但真实 Python relay 没带身份,或新 gate 误伤 B 的合法步骤”。真实 CLI 使用独立 File/SQLite stores:先原生准入 A,再原生更新 A 为依赖等待,给 B 保存自己的步骤;错误 A 写入拒绝且 index、显示、Todo/revision、扣额均无意外变化。随后去掉该 flag 的 A 写回、replay、重复 spend、same-Turn settled skip 和 fresh B guard 均通过。正常 wheel 安装后使用字节相同的测试再次通过;额外向错误写入提供 B 的最新 basis,两个后端仍拒绝且恢复成功。
最终 head 的 54 个 Python case 覆盖这组旅程及原有合法/并发/失效/source unavailable 路径;179 个 TS case、控制面 typecheck、Ruff、两适配器 scoped mypy 通过。native premerge 的 5 direct + 11 selected checks 和精确 scope quality receipt 均通过,无最终失败、skip 或 manual hold。早期 stale bundle 与 build cwd 失败保留,正式重建后正常 wheel 成功;dry-run 的 inherited ratchet advisory 被最终同一检查通过取代。没有用放宽规则或削减断言转绿。
语义与 CI 对齐
复用既有 SettlementIdentity、alignment 和错误词汇;没有新增共享 vocabulary、substring 分类或领域特定义务。admitted=false 是机器拒绝,恢复说明没有被称作可选“guidance”。没有 opt-in/default-off 声明或额外配置,因此 feature-off lens 不适用;普通无绑定路径另有 parity。最终语义 advisory 无支持的新载体,full semantic smoke 通过。按本次 capability policy,review 未查询、轮询或等待 GitHub CI,结论依据本地真实路径。
既有 canonical provider 在锁外并发提交仍可能让历史步骤过时,下次读取会丢弃;本 PR 没有增加 canonical Todo transaction lock。PostgreSQL、live install、宿主 backoff 和非 Todo 结算的步骤组合不在本轮资格内;这里没有存储重构或全局调度完成声明。
我的整体评价
没有阻塞发现。长程执行方面 improved:原任务结算不再污染后续任务步骤,重放不重复扣额;用户旅程方面 improved:拒绝给出合法恢复,省去修理 B 或清除 A 等待的错误操作。这是现有 S7 工作的 justified increment,有真实调用与可逆边界。新增生产逻辑集中在现有 owner,完整 diff 为七个文件、+198/-3,主要是独立反例和双语契约;体积与修复收益相称。
精确 head 6e385701c55fdd3fa5df3793a005c4609e7eda82 已复核。APPROVE 是此 head 的审查判断;本人使用 author-owned COMMENTED fallback,不是 GitHub 正式 self-approval,也不授予控制面自合并权限。维护者仍需按仓库规则合并;安装采用和宿主验收保持独立。
English review
The affected caller is an agent finishing a heartbeat/CLI task. Once original Todo A waits on a dependency, the selector can choose B. Previously A’s receipt-bound refresh-state --next-action could append a B step and replace B’s independent plan. The fix refuses that write before append, retains B, and lets A finish without the step and settle once. This is a justified S7 increment; installed adoption, actual host waiting cadence, other replan gaps and legacy retirement remain existing acceptance.
The accepted pre-change basis is docs/quota-allocation.md at c2044e3d0fda34cda73830db4b071dd88b65d844: Task selection happens first, source-facts fence and receipt-backed-settlement-progress are implemented. The new contract wording discloses a deliberate correction, not a self-defining oracle. The same S7 checkpoint retains #6243’s progress and separates host/fleet qualification.
resolveLaneRecommendation uses the existing identity codec and requires the original Goal/Agent/Todo for a bound task step. A fresh B basis cannot retarget A. Matching bound steps report exact alignment; ordinary unbound steps remain not_applicable. resolve_refresh_recommendation relays already validated identity to lane_recommendation_context; both initial resolution and the existing locked commit recheck call the same TS owner. There is no new Python decision, state, schema, configuration, capability or selector wrapper. A direct shared guard is smaller than a second Python policy.
The strongest failure direction is either a missing relay despite helper tests, or overblocking legitimate independent B. Real production CLI dispatch with disposable File/SQLite stores exercises native A admission, native wait, B’s existing step, rejected A step, no append/debit, correct A writeback/replay, one debit despite repeated spend, settled-skip and fresh B continuation. The frozen oracle fails on immutable old source because both providers wrongly accept/append the cross-Todo step. Source and a normally built/isolated installed wheel pass the byte-identical oracle; an additional wheel probe with B’s fresh basis also refuses and recovers on both providers.
At the reviewed head, 54 Python cases and 179 TS cases pass, including ordinary/matching task steps, concurrency/CAS, changed-source and canonical-unavailable paths. Control-plane typecheck, Ruff, scoped adapter mypy and native premerge (5 direct + 11 selected checks) pass with valid exact-scope quality receipt; the final gate has no failures/skips/manual holds. Earlier stale-bundle and wrong-cwd build attempts remain recorded; normal rebuild/package installation supersedes those preparation failures. The dry-run inherited ratchet advisory is superseded by that check passing in the final gate. No checks/assertions/budgets were weakened. Per capability policy, GitHub CI was not fetched, polled or awaited.
This reuses established identity/alignment/error vocabulary and enforces a domain-neutral admission invariant. No opt-in claim is made; ordinary unbound behavior is characterized. The diagnostic preserves ordering, authority and recovery; it does not grant another Turn or clear a dependency. Existing concurrent canonical writes can still leave a stale historical step discarded on later read; no canonical transaction lock is added. Live installation/host cadence, PostgreSQL and non-Todo settlement step combinations are not qualified here, and no global scheduler completion is claimed.
No blocking finding. Long-horizon execution and user experience improve within the scoped task-step defect. The seven-path +198/-3 diff is proportionate and reversible. Exact head was rechecked. This author-owned COMMENTED approval conclusion is neither formal GitHub self-approval nor merge authority; the control-plane change remains for maintainer merge. Runtime-reported reviewer identity is provenance, not proof of backend weights or active-turn liveness.
English verdict: APPROVE — the original Todo-bound task-step defect is corrected through the existing owner with real CLI and normal-wheel recovery evidence; broader installation and host qualification remain separate.
Goal And Delivered Outcome
When receipt-bound Todo A enters a dependency wait, the current selector can legitimately choose Todo B. Previously, A’s
refresh-state --next-actioncould append B’s step receipt, replacing B’s independent recommendation while finishing A.The existing TS recommendation owner now rejects a mismatch of original Goal, Agent or Todo before appending a run, including when the caller supplies B’s fresh read basis. The caller can finish A without
--next-action, settle it once, and enter B through a fresh guard. B’s prior step, task facts, CAS and dependencies remain intact.main, integrated throughc2044e3d0fda34cda73830db4b071dd88b65d844(includes fix(quota): finish original settlement after a later dependency wait #6243).Author Declaration
model_agent).docs/reference/protocols/turn-envelope-v0.md, original identity/replay contract at basec2044e3d0; this PR adds the explicit task-step binding and recovery clause.Scope And Continuation
Python only passes the already validated settlement identity to the current TS owner. No second decision owner, capability, configuration switch or new protocol vocabulary is introduced. Initial resolution and commit-time source recheck use the same rule. Matching bound steps report
settlement_alignment=exact; ordinary unbound steps retainnot_applicable.The future-facing pass reuses the existing identity codec and admission branch rather than adding selector exceptions or compatibility wrappers. This slice completes the cross-Todo step defect; install adoption, live waiting-state host readback and unrelated legacy retirement remain separate existing work. The roadmap’s same S7 checkpoint is reconciled with #6243.
Validation
6e385701c55fdd3fa5df3793a005c4609e7eda82.3699533301f65b5f17fe87956bb821c988decaaf(both File/SQLite wrongly accept the cross-Todo write); final source and normal wheel reject it, preserve B and recover A. New TS negative/positive tests also distinguish base/head.test_receipt_next_action_cli.py,test_declared_terminal_settlement_cli.py,test_superseded_turn_settlement_cli.py; production CLI dispatch, real TS process and local File/SQLite stores. Prior pre-integration targeted Python matrix: 54 passed.npm run typecheck:control-plane; Ruff on changed Python/test paths; scoped mypy on both changed adapters; diff hygiene. Whole-repository pytest/mypy were not rerun.uv build --wheel→ isolated installation; installed module provenance asserted; byte-identical CLI oracle passes both providers. A stale frontend bundle and a wrong build working directory were rejected before the final successful build; no gate bypass.canary premerge --from-git-diff: 5 direct checks + 11 selected checks pass; exact-scope change-quality receipt valid. Covers semantic vocabulary, quota pause/state-aware wake, canary tooling and public/private boundary. Dry-run inherited advisory is superseded by the final passing ratchet. No failures/skips/manual holds in the final gate.Visual Evidence
Type Of Change / Boundary
Bug fix, control-plane contract and focused tests/docs. Default behavior delta is explicit: mismatched receipt-bound task-step writes that used to succeed now fail with actionable recovery. Dependencies are not cleared and no extra Turn authority is granted. All three commits carry DCO sign-off; public/private scan is clean. No benchmark launches, private Goal state, raw evidence, credentials or local paths are included.
Validation and review do not authorize self-merge of this control-plane change; maintainer merge is required.