Repository navigation
fix(control-plane): recover receipt-bound terminal lifecycle settlement - #6214
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=xhigh
Request changes conclusion (author-owned PR; GitHub blocks formal self-review)
精确 head:73d9100b14b8ad9c64de4a955522b80dcbc935cb。以下结论覆盖完整 PR;未查询或等待 CI。
动机
完成任务后执行生命周期复核的 CLI Agent。 Agent 完成任务并合法执行 no-follow-up 后,已经获准执行的复核 Turn 仍需回写和扣额。原来 guard 重入拒绝该身份;当前提交恢复单任务场景,但存在历史终止任务时仍拒绝。 单任务恢复链通过;加入一个早已终止的同 Agent 任务后,File/SQLite 都在 guard 重入失败。 不授予新工作权限、不改变原验证、不证明整个 Goal 已完成。
验收依据:docs/reference/protocols/goal-vision-replan-contract-v0.md,基线修订 dd49d917a64eba0ea9dc0709dab80d088a3d6d10,按已接受文本判断,未用本 PR 新增说明替代独立验收。
C-LANE:同 Agent/原身份边界的负例已验证。C-BOUND:原 Turn 在 frontier 变化后必须保持身份,本次历史终态反例未满足。C-DEBIT:单来源路径的 fresh Vision、回写、一次扣额及 replay 已验证,不代表 C-BOUND 被关闭。
改动思路
机制归属正确,但历史终态不是当前准入来源;完整恢复验收尚未成立。 TS replan owner 负责恢复判断,Python 仅传递和重建;当前 PR 边界是原 Turn 的回写与单次扣额,来源选择必须先修复。 相比替换 Turn 或放宽 spend,此方案的恢复方向合理,仍须修复真实来源重建。最强反例是多个累计任务,而不是 malformed input:历史终止状态不能成为新准入义务的来源。
具体改动
replan_semantics.ts:lifecycleSource/lifecycleObligation 用 actor、完成时间和规范终态重建来源,投影 settlement_only 与 evidence-linked Vision;preserveReceiptBoundObligation 在既有重入路径采用该候选。lifecycle_recovery.py:receipt_bound_lifecycle_candidate 通过 typed effect runtime 获取事实、调用原 frontier 派生器并比对 obligation id。
goal_frontier/__init__.py 增加候选传递;live_decision.py、should_run.py、should_run_prepare.py、公共 quota.py 与 state_refresh.py 传递原 guard 时间;semantic_replan_writeback.py 选择匹配候选并保留 Vision 门。autonomous_replan_obligation.py 为 lifecycle digest 增加 Todo/完成身份,文本变化不改身份。协议增加双语说明,三个测试文件覆盖实 CLI、TS 负例和身份区分。这是全 diff 评审;未继承旧 head 的证据或批准。
对主干的风险
[P1] 历史终止 Todo 污染当前准入来源。 replan_semantics.ts:111–113 接受所有完成时间早于 admission、带 lifecycle_reentry_terminal_closeout 的 no_followup 行,没有证明它们在 admission 时仍是未收尾来源。派生器因此把早已合法终止的同 Agent Todo 加进当前 source;digest 与原绑定不一致,Python 返回无候选,重复 guard 再次报 heartbeat_receipt_identity_conflict。
我在现有隔离 canonical fixture 增加一条同 Agent 的历史终态(完成及终止时间均早于本轮),其余实际 CLI 流程保持原测试的完成、原交付回写/扣额、新 lifecycle admission、合法 no-followup、重复 guard。File 与 SQLite 两项都在 recovered = call(*guard) 失败,错误一致。历史行是受控合成初始数据,未改动任何活跃 Goal;被审查的完成及恢复均走真实 CLI。该失败表示原恢复缺口仍未关闭,未声称它是相对 base 新引入的崩溃。
最小修复:在既有 typed owner 恢复实际准入时的确切来源,排除此前已终止的无关记录,保留原 Todo/完成身份和触发顺序;不能通过改 receipt、换 Turn id 或降低 Vision/记账门绕过。将这一历史终态案例加入真实 File/SQLite 回归,要求仍用原身份进入 evidence-linked writeback 并只扣额一次。
其余验证:84 项 Python、26 项 TS、tsc、Ruff、semantic advisory 后全 vocabulary smoke、diff check 通过。新增单来源 CLI 测试在不可变 base 两种 provider 上失败、在 head 通过;missing Vision、premature spend、错误 actor/identity、完成时间和归档负例已验证。advisory 不扫描动态构造,不是恢复语义证明。未查询 CI,未验证真实模型采用或长期运行。
我的整体评价
REQUEST_CHANGES。机制归属正确,但历史终态不是当前准入来源;完整恢复验收尚未成立。 TS replan owner 负责恢复判断,Python 仅传递和重建;当前 PR 边界是原 Turn 的回写与单次扣额,来源选择必须先修复。 原单任务正例和反例质量不错,失败来源也清晰,但在正常累计状态中仍不能回到有用工作。相关未来重构的 owner 选择已保持在 TS,下一步应收紧确切来源重建,而非增加平行 Python 判断或新的状态字段。
English verdict: REQUEST_CHANGES - 73d9100; a prior same-Agent terminal Todo contaminates lifecycle source reconstruction, reproducing heartbeat_receipt_identity_conflict in real File and SQLite CLI recovery; 84 Python/26 TS checks pass but this current blocker remains.
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>
|
Validation update at The historical-terminal counterexample from the previous review is now reproduced against The canonical reentry owner now updates only the transition timestamp alongside its continuation closeout, preserving original completion identity, validation and receipts. The typed recovery owner filters older terminal rows, restores original completion order and retains the exact obligation digest check. Ambiguous same-second sources still fail closed. Original validation is not repeated; fresh evidence-linked writeback remains necessary before a single debit. Current validation: 12 real File/SQLite CLI cases, 39 adjacent recovery/ACK tests, 126 vocabulary checks, 19 TS semantic checks and eight File/SQLite terminal conformance cases pass. Type checking, lint and boundary scans pass. Existing default-off/successor transition coverage remains green. The related refactor was bounded to the existing typed owner and canonical timestamp field; no parallel state owner was introduced. The new head is ready for independent re-review. Maintainer merge and future experimental admission remain separate. |
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
Request changes conclusion (author-owned PR; GitHub blocks formal self-review)
Exact head: 62c61a6
动机
已完成任务、需要恢复同一轮结算的 CLI 使用者和自动执行代理。
原先同一代理已有终态历史任务时,完成当前任务的收尾会改变恢复来源,原轮次被报身份冲突,无法回写或扣账;现在原轮次可恢复结算,旧历史不会成为新来源。
独立 File、SQLite CLI 验证确认历史任务累积后原轮次仍可回写和扣账,验证器只运行一次,结算回放不再重复扣账;当前维护预算检查仍失败。
本 PR 只恢复已准入轮次的终态收尾结算,不授予新任务执行权,不迁移旧回执,也不把无后续任务解释为 Goal 完成。
改动思路
恢复来源及义务留在现有 TypeScript 决策 owner,Python 只桥接已有回执事实;但新增时间戳投影把配额装配函数推过维护预算,需在该边界完成小范围整理。
当前 PR 的边界是原始回执绑定的终态操作能完整结算;保留历史任务反例及一次扣账验证,并在同一 PR 解决新增维护预算失败。
原始回执记录是不可变事实,新增恢复投影不重写它。完整 canonical Todo 来源先按原完成时间确定顺序,再收束到原触发集;后续终态时间来自已有共享 effect,避免新增手填声明。正常 frontier 和保留结算是同一 typed owner 的不同有效范围,不由 Python 复制第二套规则。
具体改动
全 PR 为 16 个文件,+369/-9。三个主要机制是 typed 来源/原义务恢复、已有 terminal effect 更新时间、Python guard/frontier/writeback 桥接;其余为双语协议披露及现有 File、SQLite、TS 验证。
关键代码讲解
lifecycleSource(replan_semantics.ts:101)从完整 canonical 来源过滤同一代理和原回执时界,排除不相关旧终态,按 completed_at 排序后才取原触发数;因此历史任务不会占掉当前来源。preserveReceiptBoundObligation(:166)校验来源摘要和原义务 id,返回 settlement_only 与空 todo_actions;恢复只允许本次欠下的结算,不提前执行新 frontier。prepareTerminalReentry(todo_terminal_reentry.ts:50)经过原权限、租约和字段保护后更新 continuation 与 updated_at,保留 completed_at、验证证据及 completion key;File/SQLite 共用该 effect。receipt_bound_lifecycle_candidate(lifecycle_recovery.py:10)调用 typed 来源/义务 owner,并使用原摘要构造约束;它是桥接,不是第二个权限决策源。
判断依据是 docs/reference/protocols/goal-vision-replan-contract-v0.md,不可变修订 dd49d91,不拿本 PR 修改后的文档反向定义验收。C-LANE、C-BOUND、C-DEBIT 在当前真实 File/SQLite 流程已实现:原代理、原义务、原完成审计,恢复后的新鲜证据路径与一次扣账均读回。此前 73d9100 的旧 P1 在同一历史任务反例中失败,当前 head 完整结算通过。
对主干的风险
[P2] 当前 head 新增维护预算失败(live_decision.py:635)。 同一 AST 扫描口径,不可变基线的 build_live_quota_should_run_decision 为 70 条语句、60 个决策点,维护检查退出 0;新增 receipt_bound_guard_recorded_at 的三元式和回退将决策点变成 62,超过现行 60,维护检查退出 1,风险验证记录一条 unreviewed oversized_decision_function。它不是预存失败,也不能被运行时恢复测试通过替代。
最低修复是在现有回执/参数投影边界整理一个有实际职责的局部组,保留时间戳和身份语义并做 parity;若保留确有价值,也可按预算决策流程给出同口径成本、合理有限例外及退役依据。不能只改全局阈值、改名或缩小扫描以消除红线。重跑 uv run --extra test python examples/control_plane/control-plane-maintainability-ratchet-smoke.py、原历史任务 File/SQLite CLI 用例及 loopx canary premerge --from-git-diff --git-diff-base dd49d917a64eba0ea9dc0709dab80d088a3d6d10。
58 Python tests, 19 TypeScript owner tests, 4 File and 4 SQLite conformance cases, two native done-update rejection/recovery cases, Ruff, tsc, semantic checks passed; canary 5 direct and 18/19 selected checks passed.
同时保留探索记录:尝试在准入后修改已完成历史任务备注,native CLI 在基线和 head 都拒绝,changed=false,因此这个输入不是合法的新增污染反例;按既有拒绝 oracle 再走完整恢复流程,两种 provider 均通过。最初一个 probe 缺少测试目录导入路径,修正调用后另存结果,不解释为产品回归。
同秒不确定来源仍保守拒绝,错误 actor、归档或 successor 不会取得新执行权;缺失 fresh vision 和提前扣账仍失败,修正后真正继续到 durable settlement。前端/Lark 注册和用户操作入口未变,当前验证针对已有原轮次 CLI 恢复旅程;没有安装行为、权限扩容、旧回执迁移或新任务表单。
语义与 CI 对齐
复用原共享词表、回执身份和 typed state owner;恢复新文案保留执行者、原范围、证据来源、顺序、一次扣账及新 frontier 下一轮执行的义务,不宣称模型采用已测。全树语义检查通过,但当前维护契约实际被新增分支越线,必须在本 PR 明确解决;本轮没有查询或等待远程 CI。
我的整体评价
REQUEST_CHANGES。原历史任务身份冲突已经独立验证修复,不能沿用那个旧 P1;新的全 PR 判断仍需保留现行维护预算失败。long_horizon 与 user_experience 在实际原轮次恢复中改善,但这个功能结果不覆盖结构契约。整体机制成本与严重的结算阻塞相称,无须整体生命周期框架或 unrelated frontend 改造;邻接未来维护整理应现在在回执参数装配边界完成,随后以相同负载复审。
English verdict: REQUEST_CHANGES - HEAD 62c61a6; historical-terminal identity defect resolved in real File/SQLite recovery; introduced maintainability regression (60 -> 62 decision points) still blocks approval.
…ifecycle-recovery Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
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)
Exact head: a8cb49a
动机
已完成任务、随后在同一轮复核其后续安排的 LoopX Agent。 任务合法声明无需后续后,旧代码会把本轮已准入的来源丢失或混入早已收尾的历史任务,回查失败,已做完的复核无法写回和记账;修复后原轮只进入收尾,保留原身份。 真实 File/SQLite 流程验证了历史任务存在时也能提交新的验收证据,随后只扣额一次;重试不重复原验证或扣额。 本批不授权新任务、不宣告 Goal 完成、不改写旧回执,也不完成 Host 自动调度和整个 SQLite 迁移验收。 真实 App 的等待显示与 backoff,以及整体迁移、默认资格和旧写入链退役仍由既有工作负责。
改动思路
必须由现有 TypeScript 语义 owner 恢复确切原义务;更换 Turn、删除历史或只放宽身份校验都会丢失原验收和防重复执行边界。 本 PR 交付原生命周期复核从合法终结到带证据写回和一次结算的完整恢复链,保留下一轮的新 frontier 与未完成验收。 原始回执提供准入身份和时间,完整 canonical Todo 提供合法终态与原完成身份;现有 TS owner 判断来源与摘要是否吻合,Python 只传输这些事实并复用现有 obligation 序列化。新来源不会被当作本轮可执行工作。没有新增开关、provider、CLI 动作或手工维护的第二份日志。
具体改动
独立规范依据:docs/reference/protocols/goal-vision-replan-contract-v0.md,不可变修订 dd49d917a64eba0ea9dc0709dab80d088a3d6d10,使用变更前约定。按原章节映射:Replan ACK freshness 的终态原轮扣额一次及拒绝新执行已实现;Ownership Boundary 的 kernel 统一规则由现有 TS 边界扩展,Python 没有新决策源;Acceptance 的 agent-scoped checkpoint 与 accepted typed delta 保留,并由真实拒绝用例验证。新增文档说明不能反向作为自证依据。
lifecycleSource(replan_semantics.ts:101)先检查同一 Agent、原完成时间、合法终态、未归档与 successor,再按原 completed_at/index 顺序构造完整来源,之后才应用三项触发边界;早已收尾的历史行不能污染来源。同秒时间不被猜测性放行,确切摘要仍须匹配。lifecycleObligation(:135)把确切义务恢复为仅结算投影,todo_actions 为空,fresh Vision 和证据仍是写回前置条件。
prepareTerminalReentry(todo_terminal_reentry.ts:50)只在新合法 closeout 更新 updated_at,保留原 completed_at、验证及 receipt;之后重放不修改该时间。qualify_replan_writeback(semantic_replan_writeback.py:188)与 quota 共用原候选和语义规则。新增 _receipt_bound_guard_fields(live_decision.py:44)整理同一组原回执参数;缺失可选 heartbeat_receipt 的旧 readback 保持安全默认,不绕过准入。
对主干的风险
最强反例是同一 Agent 的历史终态混入原来源。相同最终 harness 在不可变 73d9100b14b8ad9c64de4a955522b80dcbc935cb 的真实 File CLI 上复现 identity conflict,而当前 head 通过;当前 File/SQLite 的0/1/4历史行流程验证原身份、fresh Vision、提前扣额拒绝、一次扣额及重放。原 validator 只运行一次。typed negatives 覆盖原身份变更、Agent 错误、无效/后置时间、同秒歧义、归档及 successor,不从显示缺失推断授权。
本轮受影响 Python 共90个独立用例被验证:首轮89通过、1个缺失可选字段失败;修复后该文件完整32项重跑通过,断言没有修改。typed/File/SQLite384项及隔离真实 PostgreSQL16的349项通过,零跳过;测试实例已移除。typecheck、mypy19、Ruff、全树semantic smoke、16路径public scan和原生premerge通过。维护度量相同口径:main60、旧head62、当前57个决策点,预算仍60;没有改扫描、命名或门槛。前一轮P1历史来源和P2结构预算均由当前证据核实解决。CI按当前wait_for_ci=false未查询。
范围风险是旧模糊义务身份不能自动恢复;这次不改写它们或伪造来源。真实App等待/backoff、全迁移与发布默认资格仍未验收。没有新的前端配置或操作;已有full/thin投影消费同一事实,未声称实机安装或模型理解效果。
我的整体评价
APPROVE 当前精确head。本 PR 交付原生命周期复核从合法终结到带证据写回和一次结算的完整恢复链,保留下一轮的新 frontier 与未完成验收。 必须由现有 TypeScript 语义 owner 恢复确切原义务;更换 Turn、删除历史或只放宽身份校验都会丢失原验收和防重复执行边界。 该可回退切片解决实际原轮无法收尾的缺口,保留下一轮独立准入和广泛验收。邻接重构已应用于同一回执参数投影;原 terminal/receipt 兼容有真实消费者,不添加虚构框架。合并仍须原生approval-closeout和即时merge-readiness,并独立遵循已有维护者授权。
English review
Motivation
An Agent reviewing follow-through for already completed work could legally close it with no follow-up and then lose the source of its already admitted Turn. Earlier terminal history could also contaminate reconstruction. The original guard would reject identity conflict, stranding useful work and accounting. Real File/SQLite checks now retain the original identity, require fresh acceptance evidence, and debit once with replay. This PR does not authorize new work, declare Goal completion, rewrite old receipts, or finish live Host/backoff and broader SQLite retirement acceptance.
Design
Reuse the existing TypeScript semantic owner and canonical terminal lifecycle. Original stored admission time plus complete canonical completion facts reconstruct the exact source; the digest must still match. Python adapts those facts and reuses the existing serializer. Replacing the Turn, deleting history, or relaxing identity would violate the accepted boundary. The current PR delivers the complete bounded lifecycle-to-writeback-to-once-only-settlement recovery, with later frontier work independently admitted.
Changes and specification
Independent accepted specification: docs/reference/protocols/goal-vision-replan-contract-v0.md at dd49d917a64eba0ea9dc0709dab80d088a3d6d10. Replan ACK freshness maps original terminal debit/refusal of new work; Ownership Boundary maps the shared TS decision owner; Acceptance maps Agent-scoped fresh evidence and accepted typed delta. The new documentation is disclosure, not the source of its own acceptance.
lifecycleSource checks actor, original completion, terminal validity and original ordering before bounded triggers. Previously closed rows are excluded and ambiguous same-second sources fail closed. lifecycleObligation projects settlement only with no Todo actions. Terminal reentry updates only the continuation transition timestamp while preserving original completion/validation/receipts, including replay. The cohesive local guard projection preserves scope/time semantics and tolerates a readback without its optional receipt.
Main risks and validation
The identical final real-CLI harness fails with identity conflict on immutable 73d9100b14b8ad9c64de4a955522b80dcbc935cb and passes this exact head. Current0/1/4-history File/SQLite cases preserve identity, reject pathless writeback/early debit and settle once without repeating validation. Wrong actor/source/time, ambiguity, archive and successor negatives remain strict. Ninety unique affected Python cases are verified:89 first passed, one absent optional-field case failed, then all32 in that file passed after repair without assertion changes. Typed/File/SQLite384 and isolated real PostgreSQL16 integration349 passed without skips; the disposable instance was removed. Typecheck, mypy19, Ruff, full semantic smoke,16-file public boundary and native premerge passed. Unchanged maintainability workload: main60, previous62, current57 decisions under limit60. Both prior source and budget findings are resolved by current evidence. CI was not queried under wait_for_ci=false.
Old ambiguous persisted identities remain immutable and cannot silently recover. Live App/backoff, complete migration/retirement/default qualification and model adoption are not claimed. No frontend operation or setting is added; existing full/thin projections share the same facts.
Verdict
APPROVE a8cb49a. This is a useful independently reversible increment, not whole-Goal completion. The adjacent guard projection refactor was applied in the same boundary. Existing receipt compatibility and exact-head approval closeout/readiness remain required; maintainer merge authorization is separate from this review.
English verdict: APPROVE
Native premerge readback: all19 selected risk checks plus three diff checks and Python compile passed; no failures, skips or manual holds. Exact-scope qualification receipt gate passed. Changed surfaces: canonical terminal reentry, shared replan semantics, quota/refresh projections and public protocol disclosure. Real provider lifecycle and failure/replay coverage above addresses the changed risks.
A legal no-follow-up closeout could remove the source of an already admitted lifecycle review. Older terminal Todos could also contaminate reconstruction, so repeating the original guard failed with
heartbeat_receipt_identity_conflictand stranded writeback/accounting.Recover that exact source through the existing TypeScript replan owner, using the recorded admission time, original completion order and exact Todo/completion digest. Canonical reentry updates its transition time while preserving original completion identity, validation and receipts. The original Turn receives settlement only: fresh evidence-linked Vision/path writeback remains required before one debit. Ambiguous older receipts remain immutable and fail closed. No new schema, provider, setting or execution authority is added.
The adjacent refactor consolidates receipt guard parameters in the existing quota adapter. It also handles a readback without its optional heartbeat receipt. The assembly function has 57 decision points, down from 62 under the unchanged 60-point limit; no budget or scan scope was relaxed.
Validation at
a8cb49a892eff2c6c1113a20d65f38d91acdbf38:73d9100b14b8ad9c64de4a955522b80dcbc935cband passes at this head; original identity, fresh writeback, early-debit refusal and once-only replay are checked.CLI guard/writeback/spend and the shared canonical terminal owner change; existing full/thin projections consume the same facts, and no frontend/Lark operation or setting is added. Live Host/backoff adoption and the broader migration/retirement/default qualification remain separate acceptance. The future-facing refactor stays within the existing owner; no second receipt store or Python decision source is introduced. Independent review/merge readiness and maintainer merge authorization remain distinct gates.