fix(collaboration): commit inbox reads after response validation - #5563
Conversation
read_inbox recorded request and peer-return deliveries before response enrichment completed. Enrichment then re-resolved a reusable Goal alias, so recreation could read a replacement workspace while leaving success receipts behind.\n\nCapture the admitted Goal snapshot for readiness checks, then re-enter that Goal lifetime before committing receipts. Regression tests cover recreation and enrichment failures. Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.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
Exact reviewed head: 9be3e23
动机
需要持续读取同伴请求和结论的 Agent,以及通过 CLI/MCP 跟进委托的操作者,会遇到一次失败读取被记成已成功提供结果的问题。
读取响应在补充 followthrough 时失败:此前仍写成功回执,调用方可确认消费而让后续重试丢失结果;现在失败不写回执、拒绝消费,修复后重试能读回同一个结果。
真实 File 后端的 exact 与 legacy 场景都保留失败后的结论;普通 MCP/CLI 读取、20+3 分页及重试保持正常,实例重建和 Agent 撤权在提交前拒绝,恢复注册后同一请求继续成功。
本增量限定本地协作读回执、原实例与注册检查;不授予 Todo、claim/lease、跨 Goal、外部账户或执行权限,也不关闭完整 Goal 实例激活与真实业务效果验收。
改动思路
把“收集响应内容”和“记录本次已提供给调用方”拆开,先完成 followthrough 和输入版本检查,再用原 GoalRef 与 Agent 注册状态重新进入短提交 guard。文件输入读取复用第一次准入的 Goal snapshot;Python 负责 IO 和响应组合,TS collaboration.goal_instance.decide 继续拥有生命周期规则。既有直接 returns(mark_read=True) 本身就是完整读取,仍保留它的原语义。
具体改动
整份 diff 只有两个现有文件(+231/-35):peers.py 提取 collection/writer 和 pinned input helper,延迟 request/result read receipts;测试文件增加读取期间实例重建、return enrichment failure 和 return-only recreation 三个负例。没有新 schema、选项、权限、模型调用或前端操作。公开 CLI 和 MCP 使用同一真实 read owner;既有 result_key、20-item overflow 和显式消费机制保留。
关键代码讲解
_collect_returns(loopx/control_plane/collaboration/peers.py:230):Collect bounded unconsumed results with corresponding receipt candidates; 21st item detects overflow, never marked read._record_return_reads(loopx/control_plane/collaboration/peers.py:337):Reuse request lock and immutable result-key/GoalRef receipt shape after qualified composite response._input_readiness_for_goal(loopx/control_plane/collaboration/peers.py:513):Resolve material versions using admitted Goal workspace rather than fresh alias lookup.read_inbox(loopx/control_plane/collaboration/peers.py:600):Enrich response, then reacquire original lifetime/registration guard before writing request and return read receipts.
验收依据 docs/architecture/rfcs/goal-instance-identity-and-orphan-recovery-v0.md 固定版本 69ad89c7fe214e3fb67d1fe894b65b17e6040461:5.5 implemented,原实例与提交 guard 相连,重建中间态拒绝且不留 read receipt;5.2 implemented,exact identity 不代替权限,Agent 撤权拒绝,恢复注册后同一请求继续,legacy 和 direct mark_read 兼容。
对主干的风险
同一独立 harness 在 immutable base 与当前 head 实测真实 File registry/TS owner:exact 与 legacy 两类 enrichment failure,base 均允许 failed-response 后消费,重试返回 0;head 均拒绝消费,恢复后重试返回 1。同名实例重建时 base 返回成功并留 receipt,head 返回 historical_mutation_forbidden 且无 receipt;两边这次实际输入观察均来自 A,不能把本实验说成 base 已读 B。Agent 中途撤权的 base 同样留成功回执,head 拒绝,重新注册后读回原请求。正常 MCP/CLI、23 条请求的 20+3 分页、同 Goal 另一 Agent、后续新请求、cross-Agent cursor 和结果重放均核验。
tests/test_peer_collaboration.py tests/test_collaboration_mcp.py 34 passed / 2 Windows-only skipped;source-instance 整套在 head 20 passed / 46 failed,base 17 passed / 46 failed。我逐个比较失败 node 与错误详情,完全一致,全部在未改动的 manager_context.deliver source recipient 授权 setup 失败,尚未进入本 PR 的 read_inbox;新增 3 个测试和独立 exact peer 路径通过。因此这是已证实的 pre_existing_unrelated,不能据此宣称整套绿色;相关合并检查仍需独立处理。10 项 premerge 选择检查、diff/compile/module ratchet/full-tree semantic 均通过,advisory 零受支持新增 vocabulary;未查、轮询或等待 CI。
本修复不承诺多份 File receipt 在磁盘故障下原子提交,也不证明 receipt commit 后客户端必然收到网络响应。最终多一次短 source scope 检查有本地读取/锁成本,未做吞吐或延迟 profiler;没有新增外部网络/模型回合或人工参数。此次 scope 未涉及 PostgreSQL authority provider。没有真实外部账户或 packaged UI rendering 声明。
我的整体评价
APPROVE 这个精确 head 的有界读取修复,goal_achieved 指该读回执缺陷。long_horizon=improved:失败结果保留并能原请求重试,防止一次错误在后续轮次被误消费丢失;user_experience=improved:用户使用原命令和原绑定即可继续,没有新确认或重复输入。效果与避免返工的效率正向,吞吐提升未实测。typed vocabulary/authority/default setting 复用,followthrough advice 不被包装成执行授权。future-facing pass 已落实 collection/writer 与 pinned input seam;已有双次 return collection 如要再优化,应先测量,当前无需新框架。46 个既有 source-manager setup 失败保留为集成/merge-readiness 风险,批准不代表合并,本角色不合并此 PR。
English verdict: APPROVE - 9be3e23; real base/head CLI/MCP/File qualification prevents false consumption after failed reads and preserves same-request recovery. 34 peer/MCP tests and 20 source tests passed; 46 identical pre-existing manager setup failures and 2 platform skips remain disclosed; 10 premerge checks passed.
Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
Goal And Delivered Outcome
read_inboxpersisted request and peer-return read receipts before response enrichment completed. Enrichment then resolved a reusable Goal alias again, so a same-name Goal recreation could inspect a replacement workspace while the failed call left success receipts for the original instance.main.Author Declaration
Implemented against
loopx/control_plane/collaboration/peers.py::_input_readiness_for_goaltest_inbox_read_rejects_recreation_before_response_commitloopx/control_plane/collaboration/peers.py::read_inboxtest_inbox_read_does_not_commit_peer_return_before_response_succeedsreturns(mark_read=True)behavior remains availableloopx/control_plane/collaboration/peers.py::returnstests/test_peer_collaboration.pymain. No unrelated refactor or generated file is included.Scope And Continuation
Validation
e54dd67dfa1fe7b70184ff1d8418140fb4162e95staticpassedunitpassedregression_paritypassedreal_entrypointpassedpython -m loopx.cli canary premerge --from-git-diff: 10 selected checks passed against the two-file diff with no failures or manual holds.tests/test_collaboration_goal_instance.pyfile has 46 pre-existing manager-authorization fixture failures that also reproduce on the unmodified baseline. The changed scenarios and adjacent inbox, peer collaboration, MCP, tracking, pagination, and host-route suites pass.See validation disclosure guidance.
Frontend / Visual Evidence
Type of Change
LoopX Area
Technical Direction
Shared-authority RFC fixture impact
Boundary Checklist
.loopx/,.codex/goals/, and liveACTIVE_GOAL_STATE.md).none.Signed-off-bytrailer (git commit -s).