Skip to content

feat(collaboration): bind inbox continuity to GoalRef - #5106

Open
Duang777 wants to merge 4 commits into
mainfrom
codex/goal-instance-m3-collaboration
Open

Duang777 wants to merge 4 commits into
mainfrom
codex/goal-instance-m3-collaboration

Conversation

@Duang777

@Duang777 Duang777 commented Sep 26, 2026 •

Copy link
Copy Markdown
Collaborator

Goal And Delivered Outcome

  • Goal/source and gap: Continue the App-first conversation continuity direction from fix(app): preserve conversational intent and plan App-first continuity #5064. Collaboration inbox records previously used the reusable goal_id alias, so a deleted and recreated Goal could observe or mutate work from the prior Goal instance.
  • Observable before -> after, with the validation row that proves it: Under source_session_v1, requests, decisions, links, peer returns, and delivery receipts now bind to {goal_id, goal_instance_id}. A long-lived worker can still publish a late result for the original instance through its saved route, but the recreated Goal cannot read or change that work.
  • Issue/task and intended base: Related to fix(app): preserve conversational intent and plan App-first continuity #5064. Base: main.

Scope And Continuation

  • Completed scope and remaining work: This PR adds the TypeScript lifecycle decision owner, Python storage and lock adapters, CLI and MCP propagation, durable return admission and readback, and legacy byte-parity coverage. Activation remains disabled. The shadow outbox is not instance-bound yet.
  • Slice boundary / successor: The next slice should bind the shadow outbox before updating the combined handoff_inbox_outbox inventory row.

Validation

  • Tested revision: d3363009a7bee30ac37b8acde3ac93fb04009260
  • Run state: finished
  • Input classes: synthetic, public_fixture
Check kind Result Public-safe evidence / limitation
unit passed pytest collaboration and manager-context suite: 94 passed.
unit passed TypeScript lifecycle, peer orchestration, and projection envelope tests: 19 passed.
integration passed source_session_v1 tests cover A-to-B recreation isolation, late A result routing, concurrent drain admission, provider readback without resend, MCP capture, and the real manager-inbox CLI subprocess.
regression_parity passed Legacy request ID, path, schema, and serialized JSON bytes remain unchanged.
static passed Control-plane TypeScript typecheck and Ruff checks passed.
unit passed Full TypeScript control-plane suite: 3112 passed, 30 skipped, 0 failed.
static passed loopx.canary.premerge and loopx.canary.maintainability_ratchet passed.
static not_applicable scripts/ci/review_gate.py verify requires the CI-only NEEDS_JSON environment value.
  • Coverage and gaps: The tests exercise the changed TypeScript policy, Python adapters, file-backed concurrency, CLI entry point, MCP lifetime capture, external provider verification, and legacy format. PostgreSQL-only control-plane tests remain skipped by the repository test command because they require an isolated PostgreSQL URL; this change does not alter a provider implementation.

Frontend / Visual Evidence

  • UI impact: none
  • Before: N/A
  • After: N/A
  • States and viewports shown: N/A
  • Source data: none
  • Attention review: No Desktop, dashboard, or web presentation files changed.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Refactoring (no functional changes)
  • Documentation update
  • Test update

LoopX Area

  • Control plane (goals, todos, quota, scheduler, registry, runtime)
  • Benchmark boundary (adapters, runners, verifiers, scoring, evidence)
  • Capability or extension (providers, adapters, skills)
  • Public docs or presentation surface (README, protocols, dashboard)
  • Build, packaging, installer, or CI
  • Host or runtime integration

Technical Direction

Shared-authority RFC fixture impact

  • Production-scale fixture schema: unchanged.
  • Semantic dimensions changed, or reviewed no-impact rationale: Collaboration lifecycle decisions now use exact GoalRef facts. The combined handoff inbox and outbox inventory remains unchanged because the outbox is outside this slice.
  • Provider conformance arms run: File-backed collaboration integration and the full TypeScript control-plane suite passed. PostgreSQL-specific tests stayed skipped because no isolated backend URL was configured.
  • Read-only legacy/file/PostgreSQL three-arm rehearsal (required for promotion, runtime-routing, or compatibility-projection changes): Not applicable. This PR does not promote or route the shared authority provider.

Boundary Checklist

  • Neither the diff nor this PR body/comments/attachments disclose private state, credentials, raw traces or verifier output, internal links, or local machine paths (including .loopx/, .codex/goals/, and live ACTIVE_GOAL_STATE.md).
  • I did not duplicate maintainer-owned benchmark work unless a maintainer split out a public issue for it.
  • I kept the change scoped to the linked issue/task.
  • I completed the visual evidence section for UI changes, or marked UI impact none.
  • Every commit includes a DCO Signed-off-by trailer (git commit -s).

Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
@Duang777

Copy link
Copy Markdown
Collaborator Author

Exact-head self-review for 61fb7c74fd89fec413ee977bc96d4cbb3e98532b:

  • Confirmed current-only operations reject or omit stale Goal instances after A-to-B recreation.
  • Confirmed late A-bound results use the saved A route and cannot be claimed by B.
  • Confirmed provider I/O runs without the Goal lifetime or request lock. A concurrent drainer cannot duplicate the send.
  • Confirmed an uncertain provider write with a locator performs readback after recreation and does not resend.
  • Confirmed legacy request paths, IDs, schemas, and serialized JSON bytes remain unchanged.
  • Confirmed the diff does not change Desktop or dashboard files and does not enable collaboration activation.

Validation at this head: 122 focused Python tests passed; 3104 TypeScript control-plane tests passed with 30 environment-dependent skips; TypeScript typecheck, Ruff, premerge, and maintainability checks passed.

Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
@Duang777

Duang777 commented Sep 26, 2026 •

Copy link
Copy Markdown
Collaborator Author

CI follow-up at d118c7752353e5d45d379390ad918c40d955d52c:

The Python 3.11 adapter-contract failure came from Delegations reading a registry during construction. The negative operation-ID tests intentionally construct the service before any registry exists.

The fix keeps eager GoalRef capture when the registry exists. If the registry does not exist yet, the service captures and caches the GoalRef under a lock on the first real collaboration operation. Invalid worker arguments still fail before file or process I/O.

Local validation:

  • Exact failed cases plus lazy-capture regression: 6 passed.
  • Source-session GoalRef suite: 8 passed.
  • CI-equivalent Optional Ark Turn command: 313 passed.
  • Ruff and diff checks passed.

…3-collaboration

Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
@Duang777

Copy link
Copy Markdown
Collaborator Author

Synced origin/main@a5546afd1 with signed merge commit a190377366c1a2d3e3ab8fedfb7ff7bde7d2e762. The merge resolved cleanly. Post-merge checks passed locally: 113 focused Python tests, 11 TypeScript tests, control-plane typecheck, Ruff, premerge, and maintainability.

…3-collaboration

Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
@Duang777

Copy link
Copy Markdown
Collaborator Author

Synced origin/main@96892b71c with signed merge commit d3363009a7bee30ac37b8acde3ac93fb04009260. The shared effect-handler registry merged cleanly. Exact-head local checks passed: 94 focused Python tests; 19 targeted TypeScript lifecycle, peer, and projection tests; 3112 full TypeScript control-plane tests with 30 environment-dependent skips; control-plane typecheck; Ruff; premerge; maintainability; and git diff --check.

@huangruiteng huangruiteng left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

动机

本次评审 exact head:d3363009a7bee30ac37b8acde3ac93fb04009260,不可变 base:96892b71cbf2a46328653fbc0c425969f2ab4865。覆盖完整 14 文件(+2822/-241)。依据是 Goal instance identity and orphan recovery RFC:alias 不是 lifetime identity;A 删除/重建成 B 后,B 不应收取或修改 A 的 request/result,但 A 的合法迟到结果仍可返回原来保存的对话。这不是通过 GoalRef 给 peer 更多权限,既有 receiver/grant/Todo ownership 校验必须继续存在。

本 PR 是 source_session_v1 的 collaboration adoption 切片,不是默认启用、完整 activation/migration/outbox 交付。切片有明确使用价值和可逆边界;然而 feature-off continuity 和慢发送下的重复 effect 都未满足其当前承诺。

改动思路

TS lifecycle decision 统一判断 current、historical、missing instance 的操作资格;Python scope adapter 持 source lifetime fence,I/O 层给 request、read/ack/link/report/consume/history 带 exact GoalRef。manager initial delivery 与 peer request 使用 instance-scoped identity;MCP 注册/Delegations 捕获 caller lifetime,避免旧 worker 重新按 alias 绑定 B。

返回链路拆成短 admission、provider I/O、短 settlement,以免远端 I/O 一直占 Goal lifetime lock。这个方向合理,但 request effect 本身不能因为 admission 时间到期就被另一个 drainer再次发送。

关键代码讲解

  • goal_instance_lifecycle.ts::decideCollaborationLifecycle:操作枚举与 GoalRef 对照决定 new work、historical inspection、original-route return 是否允许;typed owner 没有给 alias-only caller 隐式权限。
  • goal_instance_scope.py::collaboration_goal_scope:读取 source codec、登记/active 状态,在 exact mode 捕获或使用 caller GoalRef;把资格判断交给 TS,并由 lifetime fence 保护文件操作。
  • inbox.py::pending 与 peers.py::read_inbox:实例目录和 request receipt隔离是正确边界,但 cursor 的共享构造同时改了 legacy 模式,见下面 P2。
  • roundtrip.py::_exact_return_context/_write_exact_return_state/_drain_exact:读取保存的 conversation/initial delivery evidence,短锁下发 admission token,释放锁再调用 transport,回写时检查 token;token 检查发生在 external effect 之后,见下面 P1。
  • collaboration_mcp.py::register_collaboration_tools/Delegations 与 manager-inbox CLI:把捕获的 caller identity 贯穿实际入口;没有另造前端配置项。现有 UI/Lark 使用这些共用 backend,identity adoption 本身不需要新开关,但 Lark transport 的 effect/retry 顺序仍是验收边界。

具体改动

全部生产变化包括 manager authority/deliver/hook、roundtrip return、tracking/link/query、inbox/peer request/read/ack/return/consume、CLI strict registry load、MCP/delegation caller binding、TS handler 注册,以及 TS/Python 生命周期与 delegation 测试。既有 brief normalizer、项目 registry codec、chat store、delivery-attempt/verification contract被复用。无需强制完整 TS 重构才能评审,但 effect admission 的存活与恢复必须有一个明确 owner,而非只靠过期时间和事后 token 检查。

[P1] admission 到期不能证明首个 external send 已结束。 位置:_exact_return_context,L450–L495,provider call,L755–L760。

独立 real-filesystem/ChatSessionStore 探针创建已验证 initial manager delivery、adopt 与 conclusion,首次 drain(now=t) 进入 sender 后保持未完成;第二次 drain(now=t+61s) 在释放首次 sender 前完成。实际观测是 sender 调用两次,两个 drain 各 processed=1,最终 state=delivered。第一次 settlement 的 token 检查失败,也不能撤回已经发生的调用。时间通过 drain 的公开 now 参数注入,不靠睡眠制造竞态。

现有“释放 lifetime lock”用例只检查 admission 尚未到期的第二次 drain,因而全套绿色仍会漏这个情况。实际 Lark send/attempt recorder 也是先调用发送再持久化 attempt;provider I/O、preflight/readback 可以跨过该时窗。探针证明的是两个 sender invocation,不冒充 live Lark 双消息证据。

最小修复:释放 Goal lifetime lock 的同时保持同一 request effect 的互斥或可证幂等性;过期 takeover 必须先处理 active writer/uncertain external write,不能把 TTL 等同“没发送”。可在不持 Goal lock 的情况下保留 per-request effect fence,或用真实 provider idempotency 与不确定发送的 reconciliation。补“首个仍在飞行且跨 TTL、竞争 drainer、restart/reconcile 不盲目重发”的负例,保留 Goal recreate 不受慢 I/O 阻塞的正例。

[P2] feature-off 的 legacy v1 cursor 被升级拒绝。 位置:pending cursor scope,L127–L142。

base scope 是 ["pending_requests_v1", runtime, goal_id, agent_id];head 无条件变成 ["pending_requests_v1", runtime, _target(...)],连 scope=None/legacy 也改 hash。独立探针在 base 实际创建 21 个 peer requests,从第一页保存 v1 cursor,再把同一份未改的 registry/runtime/entries/cursor交给 head:

  • base resume:accepted=true、second_count=1、duplicate=false。
  • head resume:pending request cursor scope mismatch。

这是未激活 source_session_v1 时的真实 continuation regression,不是新 profile 的有意隔离。保留 legacy/None 的原 v1 scope;exact profile 才用实例维度。增加“旧 revision 发出的 cursor → 新 revision 续页”测试,并保留跨 GoalRef cursor 拒绝,不能通过放宽 scope 校验修复。

对主干的风险

正向链路:A request → A adopt/report → A return;recreate B 后默认 inbox 不见 A,明确 A 的历史结果只返回已保存、已证明的旧 conversation。负向链路:B 不能 ack/link/report A、同 operation_id 在 A/B 生成不同 request、缺 route/initial-delivery evidence 拒绝旧返回。新增资格检查可阻止 ABA,但必须同时保证不让既有 legacy 工作丢 continuation、不让原对话承担重复 effect。

语义与 CI 对齐

  • exact-head focused Python:45 passed;相同 legacy 四个 suite在不可变 base:36 passed。
  • 新 TS lifecycle tests:8 passed;control-plane typecheck 通过。
  • 两项独立 oracle 都反驳了共享当前承诺:旧 cursor 在 base 通过而 head 失败;head 的 slow-send at-most-one oracle 失败。
  • 原生外部 Lark API 没有执行,使用真实文件/Chat store加受控 provider callback;因此报告边界是 sender invocation 与 durable state,不声称已覆盖 live provider 幂等/reconciliation。
  • 当前 capability 为 wait_for_ci=false,没有查询/轮询远端 CI;REQUEST_CHANGES 只依据本 PR 改动直接引起的反例,不因无关红 CI。
  • 未来维护性检查:围绕本次修复将 exact-return effect admission/reconciliation 收敛到最近的 collaboration/return-delivery owner,保持 typed lifetime decision 与文件 effect adapter 的职责分离。不能用单纯提取 helper 掩盖 TTL 规则错误;更大的 roundtrip 模块拆分可非阻塞后续处理。

我的整体评价

instance-aware identity 和原对话迟到结果回传是合理、可独立验证的 adoption 切片;它不授权更广的 actor lifecycle,也不要求把尚未启用的 parent RFC 一次全部实现。但 legacy 默认路径已经漂移,external-return effect 的 lease expiry 有实质重复窗口。请修复这两个边界,再重跑整个切片的正向/负向与 base-issued cursor 对照。未执行合并。

English verdict: REQUEST_CHANGES - exact head d336300. A slow in-flight return can invoke the sender twice after admission expiry, and feature-off upgrades reject existing legacy cursors. Focused tests/typecheck pass; both defects were independently reproduced.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants