Repository navigation
fix(todos): preserve terminal preview and lifecycle settlement identity - #7872
Conversation
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=max
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
HEAD: 06d31d78b0c60b17cc749715b7a41400a7388e0d
动机 / Motivation
受影响的是已完成声明验证、随后通过 CLI 收尾或恢复同一轮工作的 Agent 与维护者。例如一项工作已经验证、回写并扣过一次额度:旧实现的终态预览会与原回执指纹冲突,按原完成键恢复时又可能丢失结算身份,迫使调用者手工查找记录。本头让预览保持只读,并从已验证的原回执返回同一个身份;实际 CLI 能读回四步收据,重复恢复不会再运行验证器或再次扣账。本次不新增完成权限、额度、人工确认或前端配置,也不认证安装升级、跨主机采用或长期成本净收益。
改动思路 / Approach
保留 TS 对完成、权限和回执的唯一决策权,Python 只恢复既有身份并投影结果;这样无需新协议、第二份账本或调用者手工同步字段。当前 PR 的边界是同一原始完成身份的预览、恢复和终态读回,包含真实 CLI、持久化兼容和可选观察器隔离。旧的请求版本或另一份账本都不能替代原始验证与扣账事实。新的字段来自严格核验后的历史记录,不能作为新的执行授权。最强反例是:旧回执缺字段却仍能恢复到别人的轮次,或恢复过程再次触发观察器;本轮分别以真实后端的原记录不变断言和真实 CLI 加记录型可选消费者核对。流程用下表说明,表格来自源码,测试证据另列。
| 触发 | 本头行为 | 保留的约束 |
|---|---|---|
| 同轮终态预览 | 读取原提交意图,预览不带验证效果 | 无写入、无验证器、无再次扣账 |
| 原完成键恢复 | 从严格历史核验返回原身份 | 不解析键猜身份,不补造缺失收据 |
| 旧回执缺绑定字段 | 仅补齐本次返回投影 | 原 provider head 与 receipt 字节不变 |
具体改动 / Changes
先读不可变规范 docs/reference/canonical-terminal-review.md,版本 e9eda527afd5fcb262ee7c199e1822b1a936cc24,并对照同版 docs/quota-allocation.md 的 Receipt-backed settlement progress。按原有章节映射:Operate and recover 已实现原身份优先恢复与只读预览;Wire and migration boundary 已实现原提交指纹、ID 和持久回执保留;Quota-bound CLI completion 已实现原身份贯通验证、回写、单次扣账及最终收口。没有用本 PR 新增测试来定义原规范。
六个路径、+119/-15 的完整 diff 均已阅读。声明验证与 Todo 所有权仍由 TS 判断,Python 没有新增业务判定;历史兼容针对持久记录,不是保留另一套旧请求解码器。
关键代码讲解
terminalRequestSha:预览读取原提交意图,摘要保留已提交请求的dry_run=false;其余身份、lease 和验证声明字段仍参与约束。executeCoordinationTodoTerminalLifecycle:预览不给 reducer 传验证效果;旧回执缺绑定时仅派生返回值,缺少原结算仍拒绝,未改写既有回执。verifyReentrySettlement:读完整 Goal rollout/run 快照,按原 actor 与 effect 反推出 Turn 后严格重算同一身份;不从 opaque key 猜测,不允许 unbound 回退。handle_todo_command:采用 TS 已核验身份,终态事件和结算回读使用原 Turn;--completion-identity-key路径不重新派发可选 post-writeback hook。
对主干的风险 / Risks
未发现阻塞问题。主要风险是预览产生副作用、恢复误绑身份、重跑验证/扣账,以及历史兼容覆盖原记录。File/SQLite 的实际 CLI 流程会先尝试过早收口并确认拒绝,再执行返回的原命令,完成回写、一次扣账、两类终态预览/执行与所有阶段重放,最后独立列出 Todo 并读回完整四步收据。原声明、状态和验证器/扣账计数均受断言保护。相同当前四个案例放到不可变 base,全四项失败;当前头全四项通过。旧回执缺绑定、核验拒绝和完整记录不变也在真实 PostgreSQL 上执行。
本轮验证:
| 检查 | 结果 | 边界 |
|---|---|---|
| declared terminal + quota CLI 完整两模块 | 186 PASS / 1 FAIL | 22 个声明终态场景均通过;红项单独归因如下 |
| File/SQLite 原生 authority conformance | 791 PASS | 含历史回执、CAS、当前权限、声明与生命周期负例 |
| 真实 PostgreSQL 16.15 store 集成 | 385 PASS | 一次性合成数据库,已移除;另一个可选 service-URL 套件 1 SKIP |
| 实际 CLI 的可选观察器隔离 | 2 PASS | 只替换可选消费者为记录器,业务 owner/后端/验证和结算真实;普通入口仍到达观察器,生命周期入口不派发 |
| 既有 post-writeback 边界 | 4 PASS | 未调用真实外部 sink |
| TypeScript typecheck / 两个 Python 文件 Ruff | PASS | 源码版本与 DCO 已核对 |
保留红项 test_settlement_read_snapshot_is_explicit_and_preserves_complete_facts,不能写成全绿。它在相同 base 与 head 都于第 2255 行报 DID NOT RAISE EffectRuntimeRejected。同一个 2,550,303-byte 合成请求低于两边相同的 8 MiB 请求上限;完整普通/私有返回值及不支持方法的拒绝详情一致,transport、quota readback 和该测试文件的 Git blob 全部相同,且该 RPC 不进入本次终态路径。因此这是已有、与本变更无关的断言失败;未修改断言、样本或上限来消除它。当前变更的不变量由上面的独立通过证据覆盖。
语义与 CI 对齐
本头复用已有 typed completion/settlement vocabulary;不新增启用开关、状态账本或模糊文本分类。原结算核验是强制正确性要求,可选 hook 仍是观察器。没有抓取、轮询、等待或触发 CI,远端 CI 的未知状态与未知原因仅保留为诊断,不是本次评审的阻塞条件。Windows、完整 Python/TS 全量、安装/UI、真实外部 sink 与跨主机采用未获得本次认证,合并 readiness 和维护者权限仍需独立处理。
我的整体评价 / Verdict
APPROVE,绑定上述精确 head。保留 TS 对完成、权限和回执的唯一决策权,Python 只恢复既有身份并投影结果;这样无需新协议、第二份账本或调用者手工同步字段。当前 PR 的边界是同一原始完成身份的预览、恢复和终态读回,包含真实 CLI、持久化兼容和可选观察器隔离。长程维度的可验证收益是重复恢复时继续保留同一承诺与单次成本;用户体验维度是沿用既有命令恢复已知身份,没有再要求人工提供已存在的信息或新增确认轮次。这不代表已经证明长期总成本净收益。视觉审阅不适用:已检查 CLI 与未改的 dashboard 完成状态消费者,无页面或展示改动;安装 UI 和跨主机采用仍未验证。持久历史兼容有实际旧回执消费者,保留是必要的;再增加 wrapper、协议版本或新配置目前没有更小且等价的收益。已有红项、可选跳过与未测范围全部保留;本结论不替代正式 GitHub self-approval、合并授权或安装发布。
English verdict: APPROVE — exact head 06d31d7; terminal preview and original settlement recovery are verified on real backends, with the unchanged baseline transport-test failure disclosed separately.
Goal And Delivered Outcome
Repair two reproducible recovery gaps after a declared Todo has completed, written back and spent its slot:
The same File/SQLite CLI regression fails four cases on base
e9eda527afd5fcb262ee7c199e1822b1a936cc24. The fix makes preview and retry preserve the original identity, validation, evidence and once-only accounting. No synthetic successor or replacement Turn is needed.Author Declaration
Change And Continuation
dry_run=false) when previewing the same intent; do not treat a preview as a new committed operation.Complete as a source repair proposal. Review, merge, installed adoption and any operator-owned recovery remain distinct; no merge or install is performed by this PR.
Validation
06d31d78b0c60b17cc749715b7a41400a7388e0d.cqr_acdfa4454536b2bfee7dverified for the exact diff; six direct and eighteen selected checks passed. The baseline-failure row stays failed under the typed attribution; no merge readiness or full CI pass is claimedFull Python CI, Windows and installed release qualification have not been run locally. The matched baseline diagnostic exception cannot waive required CI, independent review or merge readiness. The two broad failing commands are disclosed above; neither is presented as an all-green validation run.
Frontend / Visual Evidence
UI impact: none. This repairs the existing CLI/host completion recovery path and its shared typed owner; it adds no settings or frontend capability. Existing reviewed Chat HTTP recovery is included in the adjacent suite. No rendered page or navigation changed; screenshots are not applicable.
Type / Area
Boundary