Skip to content

fix(scheduler): dispatch executor-excluded handoffs instead of repolling origin monitor #4311

Description

@huangruiteng

问题 / 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

  1. Origin agent owns a due continuous_monitor.
  2. A material transition creates one linked advancement Todo with excluded_agents=[origin-agent].
  3. The projected priority list shows that unclaimed Todo, while the current-agent claim scope reports zero selectable unclaimed work.
  4. manager.context_inbox is empty at turn start because no durable dispatch/receipt was produced for another agent.
  5. 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_peer blocker.
  • 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_peer from unclaimed_but_executor_excluded.
  • agent_handoff -> turn_start hook -> inbox read -> return receipt survives 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

  1. BigDataDZ commented on Sep 17, 2026

    @BigDataDZ
    Contributor

    Claiming this task. Plan: (1) split the projection so dispatchable_by_peer is distinct from unclaimed_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 typed no_eligible_peer blocker 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.

  2. YZJF commented on Sep 17, 2026

    @YZJF
    Contributor

    Following the #4312 closing note, the retained acceptance obligations are now characterized on main in #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.json plus tests/control_plane/test_manager_handoff_m2_characterization.py, which pins against shipped code:

    • O1 dispatchable_by_peer vs unclaimed_but_executor_excluded read from the same claim_scope projection
    • O2 an empty eligible-peer set fails closed on dispatch instead of projecting a user gate
    • O3/O5 a repeated dispatch replays one durable entry and never resets a recorded decision
    • O4 delivery/read/decision read back intact after a restart
    • O6 a conflicting acknowledgement is rejected, not overwritten
    • O7 a dispatch is filed under the recipient scope hash, so a same-Goal peer cannot reach it
    • O8 dispatch and successor handoff identities are pure functions of their tuples

    O9 (canonical Todo claim readback) is already pinned by test_links_use_core_state_and_do_not_copy_progress and 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.

  3. added a commit that references this issue on Sep 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions