Skip to content

manager: fan out unscoped global-todos and global-summary across peer_v1 agents - #7839

Open
loopx-agent wants to merge 2 commits into
mainfrom
codex/global-manager-peer-v1-agent-fanout-20261101
Open

loopx-agent wants to merge 2 commits into
mainfrom
codex/global-manager-peer-v1-agent-fanout-20261101

Conversation

@loopx-agent

Copy link
Copy Markdown
Collaborator

Goal / Source

Fix manager-level read-only projections (loopx global-todos, loopx global-summary, loopx global-gates) when called without --agent-id across peer_v1 multi-agent Goals.

Current Gap

  • Calling build_quota_should_run(..., agent_id=None) on a peer_v1 multi-agent Goal returns the unscoped heartbeat guard (recommended_mode="automation_prompt_upgrade", normal_delivery_allowed=False, selected_todo=None, recommended_action="Regenerate each installed heartbeat with its registered --agent-id...").
  • As a result, loopx global-todos without --agent-id reported runnable_count=0 across all peer_v1 Goals and attached the heartbeat upgrade prompt as every Todo's next_safe_action, while loopx global-summary showed the same heartbeat prompt for every peer_v1 lane.
  • In addition, loopx global-todos --agent-id <id> emitted quota_unavailable warnings for Goals where <id> is not registered instead of treating them as out of scope.

Observable Result & Owning Boundary

  • loopx/global_todos.py:
    • When agent_id is None and build_quota_should_run returns the unscoped peer_v1 prompt-upgrade guard, fan out across the Goal's registered agents (run_history.goals[].coordination.registered_agents and attention-queue lane owners, bounded to 8) so runnable selected_todo items are surfaced and non-runnable Todos bind their claimed_by owner's recommended_action.
    • When --agent-id is explicitly provided and a Goal does not register that agent, skip that Goal cleanly as out-of-scope rather than recording a quota_unavailable warning.
  • loopx/summary_all.py:
    • When agent_id is None and _build_goal_quota hits the unscoped peer_v1 guard, resolve the Goal's candidate registered agents (prioritizing agent_lane_recommendation.agent_id and runnable lanes) so loopx global-summary and loopx global-gates project accurate lane actions and top Todos.

Verification

  • pytest tests/test_global_todos.py tests/test_summary_all.py -q (38 passed).

@loopx-agent loopx-agent left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Reviewer: model_agent; gpt-6.1-sol; OpenAI; runtime_reported; reasoning effort: max

Request changes conclusion (author-owned PR; GitHub blocks formal self-review).

动机 / Motivation

多 Agent Goal 的维护者需要在一个总览中找出可继续的工作和需要本人处理的阻塞。
基线的未指定 Agent 查询会落入身份升级提示;候选尝试逐个查询,但九个 Agent 时漏掉第九个,且 A 可执行、B 被用户阻塞时总览把阻塞数从 1 改成 0。
目标是未指定 Agent 时保留全部可见工作与阻塞;当前真实 CLI 只证明部分 fanout 可用,完整性仍失败。
本 PR 只改变全局只读投影,不应修改领取、执行、配额、用户授权或原有阻塞语义。

改动思路 / Approach

当前 PR 边界:全局投影和回归测试。
status 提供注册身份与 attention queue,manager 调用现有 build_quota_should_run,把各 Agent 的权威资格投影成全局列表。这个方向能让普通只读查询不再被未指定身份的自动化升级提示挡住。保留 quota 作为每个 Agent 的决策 owner,让 manager 只聚合投影是合理边界;当前用单 lane 代替完整 Goal、隐藏八项截断和重复 legacy 分类需要在本 PR 修正。 本 PR 边界是全局投影和其回归测试,修复不应改变 quota 的执行授权。显示 limit 只限制返回行数,不能成为注册身份扫描或完整计数的上限。

下面是实际 File/SQLite CLI 对照结果,两个后端均相同,非示意图:

输入 基线 候选
九个 Agent,唯一工作在第九个;limit=100 漏项,0 仍为 0,且无 warning/truncation
只把第九个注册身份排到首位 仍为 0 变为 1
A runnable、B 有 scoped user_gate 总览 gate=1 总览 gate=0;global-gates=1

具体改动 / Changes

关键代码讲解

  • _registered_goal_agents 合并注册表和 lane 候选后在 L163 截为前八个;它没有返回遗漏数量,随后汇总仍宣称没有截断。
  • _quotas_for_goal 对未指定身份的 peer 查询做 fanout;每个候选的异常或非成功 payload 被丢弃,有一个成功就不再保留失败面。单身份与非 peer 路径仍调用现有 quota owner,但失败不能被健康 lane 掩盖。
  • _build_goal_quota 在 L187-L188 遇到首个可执行或带 selected_todo 的 lane 就返回;build_summary_all 随后仅用这个 quota 生成工作和 gate,因而丢掉其他 Agent 的用户阻塞。
  • 两个 _is_unscoped_peer_v1_quota 重复消费 legacy heartbeat 字段,并回退到英文 reason 子串;显式身份未注册也用 prose 判断跳过,措辞改变与真正上游故障可能被误分类。

规格基线是 docs/reference/protocols/global-manager-command-v0.md,补充 peer-agent-runtime-v1.md。准则 unscoped_all_visible 当前 not_met:省略 Agent 不代表前八项;complete_counts_and_failures 当前 not_met:完整计数和失败覆盖不能由显示切片决定;peer_registration_order_independence 当前 not_met:顺序改变不应决定工作能否发现;quota_remains_owner implemented:没有新增写入或执行 owner。原先一 Goal 一权威读取的成本边界也应由共享批量投影解释,不能只复制两个循环而不计读取成本。

对主干的风险 / Risks

P2:第九个 Agent 静默漏项。 真实 quota 明确允许唯一第九项,global-todos --limit 100 却返回 0、warning=0、truncated=false。这会让维护者误以为没有可做的工作。最小修复是完整枚举或显式报告未覆盖,并验证注册顺序置换和显示 limit 不改变完整计数。

P2:总览丢掉另一个 Agent 的用户阻塞。 同一个 A runnable/B gated 状态,基线总览有一个 gate,候选变为零,专门的 gates 查询仍有一个。最小修复是分别聚合 runnable lane 与完整 gate 集,保留真实身份去重;回归用例必须同时断言两者。

语义与 CI 对齐

P2:必检 legacy 消费范围回归。 uv run --extra test python examples/semantic-vocabulary-drift-smoke.py 在不可变基线通过(16/17),本头失败:legacy field heartbeat_recommendation grew to 18 .py modules; budget is 17。两个重复 classifier 是新增消费者。标准 canary premerge --from-git-diff --git-diff-base 3503d823256c02bc531558f4a3bc9ea7c963d6eb 因此失败;其他四个所选 canary、编译、diff 和双语检查通过。应复用 typed identity/prompt-upgrade owner,或按既有预算规则证明必要性后处理约束,不能直接把失败转记为通过。diff-scoped advisory 没发现新 closed-set,不证明没有语义或 legacy 扩散。

验证:PASS,完整 tests/test_global_todos.py tests/test_summary_all.py 38 项;PASS,真实 File/SQLite 独立 quota 与相同状态读取;FAIL,以上三个有独立预期的反例/原生检查。初次临时夹具缺 adapter/完整 state、未声明 scheduler profile 的失败仅作夹具诊断,补齐后才用于结论。未查询、轮询或等待远端 CI;没有修改源码、领取业务工作或执行 gate。显式 agent/普通查询的既有测试通过,但不能代替新的多 lane 完整性。

我的整体评价 / Verdict

REQUEST_CHANGES,审查头 0506196b403e08f671f541b3da1aec4567f88632。long_horizon=regression:已允许的工作被顺序相关的切片隐藏;user_experience=regression:待本人处理的阻塞从总览消失。保留 quota 作为每个 Agent 的决策 owner,让 manager 只聚合投影是合理边界;当前用单 lane 代替完整 Goal、隐藏八项截断和重复 legacy 分类需要在本 PR 修正。 385 additions/17 deletions 中有 221 行测试;fanout 投影值得保留,最高价值的有界简化是复用一个 typed peer 枚举/状态入口,分开推荐项与完整集合。没有新增持久状态,不能从 status 切片推导不存在。

无渲染界面改动;检查 global-todos/global-summary/global-gates 的 JSON、Markdown consumer 与完整四文件 diff,截图不适用于此只读 CLI 改动。 真实模型采用、持续多轮公平性和完整运行成本未测;没有用本次测试数推断长期收益。 修复后须重新运行完整模块、九 Agent/混合 lane 的真实 CLI、语义检查和 premerge;此结论不涉及 merge 或授权扩展。

English verdict: REQUEST_CHANGES — unscoped fanout silently omits agents, hides a scoped user gate, and introduces a required semantic validation failure.

Comment thread loopx/global_todos.py Outdated
continue
add_agent(as_dict(item.get("agent_lane_recommendation")).get("agent_id"))
add_agent(as_dict(as_dict(item.get("project_asset")).get("owner")).get("agent_id"))
return agents[:8]

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

[P2] 完整扫描注册 Agent,或明确返回未覆盖范围

九个注册 Agent;唯一可执行 Todo 属于第九个。 File/SQLite 真实 quota 对第九个 Agent 均 normal_delivery_allowed=true;global-todos --limit 100 返回 runnable_count=0、matched_todo_count=0、source_warning_count=0、truncated=false。仅将注册顺序改为第九个在前,结果变为 1;没有改变 Todo、配额或显示上限。 从完整注册表枚举或分页;若必须限制读取,显式携带 agent coverage/omitted/incomplete,不能把未读取判为无工作。同步检查 summary_all 的同类八项截断。 回归验证:真实 File/SQLite 九 Agent,唯一第九项;limit 100 与注册顺序置换应保持完整计数/结果,或明确报告未覆盖。

Comment thread loopx/summary_all.py Outdated
continue
if first_ok is None:
first_ok = scoped
if scoped.get("normal_delivery_allowed") is True or scoped.get("selected_todo"):

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

[P2] 汇总全部 peer 的阻塞,不要由首个可执行 lane 代替整 Goal

Agent A 可执行,Agent B 的 Todo 有 scoped user_gate。 候选在首个可执行 scoped quota 提前返回:相同真实 File/SQLite 状态下,global-summary.open_gate_count 从基线 1 变成 0,global-gates 与 --agent-id agent-b 仍报告 1;用户无法从总览发现待本人处理的 B 阻塞。 分别聚合每个 Agent 的工作与用户阻塞,并按真实 gate/Todo 身份去重;推荐执行 lane 与完整 gate 集不得共用单个选中 quota。 回归验证:两个 Agent 的真实 CLI 对照:A runnable/B gated,同时要求总览保留 A 的工作和 B 的 gate,并与 global-gates 一致。

Comment thread loopx/summary_all.py Outdated


def _is_unscoped_peer_v1_quota(payload: dict[str, Any]) -> bool:
heartbeat = _as_dict(payload.get("heartbeat_recommendation"))

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

[P2] 复用 typed peer 状态,修复新增 legacy 消费者造成的必检失败

两个新增 _is_unscoped_peer_v1_quota 直接读取 heartbeat_recommendation。 相同 semantic-vocabulary-drift-smoke 在不可变基线通过(heartbeat_recommendation.py=16/17),候选失败:legacy field heartbeat_recommendation grew to 18 .py modules; budget is 17。标准 premerge 因此失败;diff-scoped advisory 无新词并不能覆盖 legacy 消费者扩散。 优先共用现有 identity/prompt-upgrade typed owner,消除重复 legacy/prose 分类;如确需扩展消费范围,按现有预算决策规则给出必要性与完整成本证据后再调整约束,不能静默抬限或把失败记成通过。 回归验证:uv run --extra test python examples/semantic-vocabulary-drift-smoke.py;随后运行本 PR 的 canary premerge。

…_v1 agents

Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
…yped identity checks

Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
@loopx-agent
loopx-agent force-pushed the codex/global-manager-peer-v1-agent-fanout-20261101 branch from 6e8c750 to 2c9ce29 Compare November 2, 2026 03:54

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.

1 participant