Repository navigation
fix(scheduler): dispatch executor-excluded handoffs instead of repolling origin monitor #4311
Description
问题 / Problem
当一个 continuous monitor 在 material transition 后创建 continuation_policy=independent_handoff 的 advancement Todo,并用 excluded_agents=[origin-agent] 禁止原作者自审时,Todo 会保持 unclaimed;但后续 heartbeat 仍持续唤醒 origin agent 轮询同一 monitor。即使 consecutive_no_change >= 2,当前行为也只建议调大轮询间隔,不会把真实可推进的 handoff 分派给同 Goal 的另一个 Agent。
When a continuous monitor emits an advancement Todo with continuation_policy=independent_handoff and excludes the origin agent, the Todo can remain unclaimed while later heartbeats repeatedly select the origin monitor. Even after multiple unchanged polls, the runtime only proposes polling backoff; it does not dispatch the real handoff to another agent in the same Goal.
可复现证据 / Reproduction evidence
- Origin agent owns a due
continuous_monitor. - A material transition creates one linked advancement Todo with
excluded_agents=[origin-agent]. - The projected priority list shows that unclaimed Todo, while the current-agent claim scope reports zero selectable unclaimed work.
manager.context_inboxis empty at turn start because no durable dispatch/receipt was produced for another agent.- The origin agent receives repeated monitor turns; unchanged polls increase
consecutive_no_change, but no peer claim or handoff occurs.
This is not a missing-work problem: actionable work exists, but the scheduler/claim/handoff bridge cannot route it to an eligible executor.
根因划分 / Root-cause split
- Agent-side: the origin agent must not equate a successful poll with whole-goal progress; it should verify that an independent successor has a receiver and return receipt.
- LoopX-side: the control plane lacks an idempotent broker from an unclaimed, executor-excluded successor to an eligible peer/session. Current projection also conflates “unclaimed globally” with “selectable by this agent”, hiding dispatch starvation.
期望 / Expected behavior
- A material monitor transition atomically links the successor and emits a durable dispatch obligation.
- Turn-start handoff/inbox logic claims the successor exactly once for a different registered agent in the same Goal, or projects an explicit
no_eligible_peerblocker. - The origin monitor may continue at its configured cadence, but it must not starve independent advancement work or force a second automation/source of truth.
- Codex message delivery alone is not acceptance; dispatch requires inbox visibility plus a return receipt.
验收 / Acceptance
- Frontier projection distinguishes
dispatchable_by_peerfromunclaimed_but_executor_excluded. -
agent_handoff -> turn_start hook -> inbox read -> return receiptsurvives restart and is idempotent under duplicate delivery. - After the configured unchanged threshold, origin-agent routing yields to a dispatch/replan action instead of only suggesting interval backoff.
- If no eligible peer exists, a typed blocker is projected without inventing a user gate.
- CLI/managed Turn, frontend, and Lark read the same typed dispatch/receipt projection.
- Tests cover duplicate heartbeats, stale claims, restart, and same-Goal agent identity isolation.
Activity
BigDataDZ commentedon Sep 17, 2026
Claiming this task. Plan: (1) split the projection so
dispatchable_by_peeris distinct fromunclaimed_but_executor_excluded; (2) add an idempotent turn-start dispatch step that lets exactly one other registered agent of the same Goal claim the excluded-executor successor, projecting a typedno_eligible_peerblocker when no peer qualifies; (3) keep the origin monitor on its existing cadence and make the handoff → hook → inbox read → receipt chain survive restarts. Tests will cover the acceptance list (repeat heartbeats, stale claims, restart, same-Goal agent identity isolation). I'll follow up with a PR linked here.YZJF commentedon Sep 17, 2026
Following the #4312 closing note, the retained acceptance obligations are now characterized on
mainin #4640 rather than re-proposed as a scheduler patch.Scope of #4640 (test-only, no production changes): an obligation ledger at
tests/fixtures/control_plane/manager_handoff_m2_characterization_v0.jsonplustests/control_plane/test_manager_handoff_m2_characterization.py, which pins against shipped code:dispatchable_by_peervsunclaimed_but_executor_excludedread from the sameclaim_scopeprojectionO9 (canonical Todo claim readback) is already pinned by
test_links_use_core_state_and_do_not_copy_progressand is only recorded to keep the retained set complete.The dispatch broker itself is left to the typed Core collaboration contract from RFC #4330; this PR is the compatibility baseline for that cutover, so it tracks #4311 as related rather than closing it.
test(handoff): characterize the #4311 peer-dispatch obligations for M2 (