Conversation
Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
…f-continuity Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
…f-continuity Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
|
Synced the latest Fresh local validation on that head:
CI is rerunning for the updated head. @huangruiteng Once it is green, this control-plane change is ready for maintainer review and merge. |
|
CI follow-up on exact head
This evidence points to an isolated concurrency failure, but I am not bypassing it. My account cannot rerun repository Actions ( |
…f-continuity Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
|
Synced current |
…f-continuity Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
…f-continuity Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
|
Synced latest |
huangruiteng
left a comment
There was a problem hiding this comment.
动机
这个 PR 修的是一个会稳定饿死后续协作请求的恢复缺口:manager inbox 只读取按 request id 排序后的前 20 条;只要这些条目仍处于 deferred,排在第 21 条之后的 pending request 就无法被 operator 看见,更谈不上决定或恢复。Issue #4339 允许把 reply/recovery 做成独立的 M3 切片;本 PR 没有把 review、claim 或 authority 扩进来,边界是成立的。
改动思路
实现选择了 live cursor pagination,而不是把整份 inbox 做快照:cursor 由 schema version、scope digest 和上一页最后一个 request id 组成;scope 同时绑定 runtime root、goal id 和 agent id。这样调用方可以逐页恢复已有请求,同时不能把另一个 goal/agent 的 cursor 当作本页授权。新到达且排序在 cursor 之前的请求不会被当前 traversal 自动吸收,文档明确要求从无 cursor 的第一页重新扫描,这个取舍是可观察且可恢复的。
具体改动
collaboration/inbox.py为 pending inbox 增加 cursor 解码、scope 校验、稳定的 20+1 分页以及has_more/next_cursor。manager_inbox.py将--cursor限定在 read action;decision/reply action 不能借 cursor 改变写入对象。- collaboration MCP 的
read_context(cursor=...)复用同一个 inbox contract,并在每次调用时重新校验 agent registration。 - manager-context 与 collaboration 文档说明 live traversal、restart 语义以及 cursor 不授予 authority。
- 新增覆盖多页读取、completed/deferred 混排、页间完成、页间新增、malformed cursor、scope mismatch、malformed filename 和 restart 的回归测试。
关键代码讲解
PendingRequestInbox.pending() 先用固定字段计算 scope digest,再对 cursor 做 exact schema/scope/64-hex 校验。遍历仍沿用 request id 的既有排序;只有在 entry identity 与文件名一致且 request 未完成时才计入候选页。收集到 21 条后只返回前 20 条,并以第 20 条生成下一页 cursor,因此不会靠全量 materialization 才能判断 has_more。更重要的是,read receipt 仍在 input readiness 与 peer return preparation 之后记录,分页没有把“看到了文件”偷换成“已成功处理请求”。
对主干的风险
主要残余风险来自 live pagination 本身:翻页过程中新增且排序在当前 anchor 之前的 request 不会出现在本次 traversal。但这不是静默丢失,文档明确了 restart 规则,测试也覆盖了该反例。cursor 只携带 navigation state,不携带 decision、claim 或 write authority;invalid scope、invalid filename 和 identity mismatch 都会在产生 read receipt 前 fail closed。当前 head 相对最新主干仅落后两个不相交提交,未发现相邻冲突。
验证结果:相关 Python suites 62 passed;changed Python files 的 Ruff 通过;补齐 TypeScript parser dependencies 后 semantic vocabulary smoke 通过;loopx canary premerge --from-git-diff 19/19 通过(10 catalog canaries、8 risk-profile smokes、public-boundary check),无 skip/failure。
我的整体评价
这是一组完整、可回滚且与 issue 边界相称的恢复修复。它解决的是可复现的 starvation,而不是引入新的协作 authority;状态、错误与重扫语义都有代码和文档双重约束。未发现需要阻塞合并的 correctness、authority、default-off 或 domain-neutrality 问题,我赞成在保持当前 exact head 的前提下合入。
English verdict: APPROVE - head 1c146ab; scoped live cursors recover pending requests beyond the first 20 without granting decision authority; 62 focused tests, Ruff, semantic vocabulary smoke, and all 19 selected premerge canaries passed.
Goal And Delivered Outcome
Deferred requests awaiting conclusions can fill the first 20 inbox slots indefinitely. Receivers see
has_morebut cannot retrieve request 21 through either the CLI or scoped MCP.This change adds
next_cursor,manager-inbox read --cursor, and optionalread_context(cursor=...). The integration regression retrieves 45 requests in pages of 20/20/5 after restart, preserves the later semantic brief, and returns one later conclusion to its requester without concluding the first 20 requests.Related to #4339 and challenge #4340. Intended base:
main.Scope And Continuation
Complete within the local receiver pagination scope. The existing collaboration inbox owns the cursor; it binds the resolved runtime root, Goal and Agent without adding storage or authority. Existing calls still return the first page, now with
next_cursor. Invalid cursors and unreadable directories fail explicitly. Read receipts follow response preparation and cover returned requests only.Pages are live, not snapshots. New arrivals before the cursor require a fresh scan. Peer-result consumption remains independent. The RFC checkpoint records this bounded A20 contribution and A5/A13 restart evidence; managed cross-day execution, live Lark qualification and the remaining M1–M4 work stay with #4339. No storage promotion, shared Goal amendment, worker scheduling or lease transfer is claimed.
Future-facing pass: keep cursor validation and position selection in
inbox.py, with thin CLI/MCP adapters and no parallel index.Validation
8506dbc8a1666c09228f3379686681b1579e5cc7.regression_paritypassedreal_entrypointpassedtests/test_inbox_pagination.py: CLI subprocesses and MCP stdio restart, 20/20/5 pages, exact read receipts, scope rejection, live revocation, stopped-Goal reads, removed anchor, new arrivals and conclusion return.integrationpassedstaticpassedgit diff --check; public/private candidate scan clean.integrationpassedThe first canary attempt lacked the locked TypeScript dependencies; those were installed before rerunning. Staging the new test during that run also triggered its worktree-change guard. Final qualification passed against the fixed commits with no concurrent repository writes.
Frontend / Visual Evidence
UI impact: none. This changes receiver CLI/MCP reads. Owner-facing handoff status already has offset pagination; its tracking and original-conversation return tests pass. No packaged frontend or live Lark journey was run, and neither is claimed qualified by this change.
Type of Change
LoopX Area
Technical Direction
Semantic handoff RFC: local receiver portion of A20; bounded A5/A13 restart evidence.
Shared-authority RFC fixture impact
N/A. Existing file-backed collaboration records remain in place; this does not claim TypeScript migration or shared-authority promotion.
Boundary Checklist
none.