Skip to content

feat(agents): ship the first local producer of the peer agent directory - #4544

Merged
huangruiteng merged 1 commit into
mainfrom
codex/peer-agent-directory-producer
Sep 16, 2026
Merged

huangruiteng merged 1 commit into
mainfrom
codex/peer-agent-directory-producer

Conversation

@huangruiteng

Copy link
Copy Markdown
Collaborator

What And Why

peer_agent_directory_v0 (the contract) says one Agent must be able to discover which Agents exist for a Goal, observe one of them within bounds, and hand one a bounded request — the same three abilities for a peer inside the Goal and for the steward channel a person talks to. Until now the contract had no producer at all.

This ships the bounded local producer: loopx agent-directory --goal-id <goal> [--agent-id <caller>].

How It Works

  • Re-projection, not a second read. The rows come from the existing agent_management_projection_v0, so Agent identity, work, claims and claim staleness keep their current owners. No second read of the registry, the Todo index or a lease store, and no new source of truth.
  • One row per registered Agent, whether or not that Agent currently holds projected work.
  • No invented presence. No presence provider is registered, so rows carry no presence block; the packet states presence_coverage.state = "unavailable" with the reason, and names presence_provider_unavailable, presence_is_advisory and lease_state_not_projected in limitations. A reader cannot mistake "this machine cannot see it" for "it is not running", and the packet never claims a lease epoch the projection does not own.
  • Truncation is declared. registered_agent_count and omitted_row_count are published with the rows_truncated_at_cap limitation, so a capped directory cannot be read as a complete one.
  • Membership is proven, not asserted. --agent-id is resolved against the Goal's registered Agents. A caller that is not registered for that Goal gets a typed audience_not_authorized scope gap and zero rows — never a listing that caller has no scope over. An unknown Goal is refused with goal_not_registered.
  • A rollup that routes attention and assigns nothing. needs_decision, stale_claims and without_claim come from typed work state, with assigns_work: false; the packet also carries an explicit authority block (observation_grants: [], writes: false, scheduler: false).

The shipped manager skill (loopx/capabilities/manager_context/skills/loopx-manager/SKILL.md) now tells an in-space Agent to read this directory for "who else is working on this Goal" and to read its limitations before answering. The steward-intake RFC records the producer in English and Chinese.

Validation

Live reads against this machine's registry (13 registered Agents for loopx-meta):

  • registered caller → 13 rows, caller_membership: registered_agent, typed rollup needs_decision=2 stale_claims=8 without_claim=4, presence_coverage.state=unavailable, limitations as designed;
  • unregistered caller → rows: [], zero count, one audience_not_authorized gap;
  • unknown Goal → ok: false, goal_not_registered, exit 1, no rows.

Tests and gates:

  • pytest tests/control_plane/test_peer_agent_directory.py — 5 passed (rows without presence, rollup semantics, scope gap, missing caller identity, declared truncation). It also runs alongside test_manager_team_plan_guidance.py and test_agent_management_material_capability_gate.py — 13 passed total.
  • python3 examples/docs-governance-smoke.py — passed.
  • loopx canary premerge --from-git-diff — passed: diff hygiene, changed-file compile checks, catalog canaries (including peer-agent-runtime-v1-smoke.py, cli-control-plane-command-modularization-smoke.py, semantic-vocabulary-drift-smoke.py), 8 risk-profile smokes, and the public/private boundary scan over exactly the changed files.
  • One advisory, unchanged: control-plane-maintainability-ratchet-smoke.py reports its two known baseline findings.

Residual Gaps

  • Presence is still unimplemented. A presence provider (a terminal-space provider or an attached host) is the next slice; this PR deliberately ships the presence-less half, which the contract defines as the normal case for a prompt-only transport.
  • Delivery is not wired here. The packet carries delivery_refs, but handing a peer a bounded request stays context_handoff; this PR adds no delivery path.
  • The Chat manager read tool has no peers view. The steward reaches this through the CLI inside its space; a Chat-scoped read surface is not included.

`peer_agent_directory_v0` (docs/reference/protocols/
peer-agent-directory-and-observation-v0.md) is the contract for one Agent
discovering, observing and handing a bounded request to another, and it now
names both of its audiences: the manager-channel steward and a `peer_v1` Agent
inside a Goal. Until now it had no producer.

This adds the bounded local one, `loopx agent-directory --goal-id <goal>
[--agent-id <caller>]`:

- it re-projects the existing agent management projection, so identity, work,
  claims and claim staleness keep their current owners and nothing is read a
  second time from the registry or a lease store;
- one row per registered Agent, whether or not that Agent holds projected work;
- no `presence` block while no presence provider is registered, with
  `presence_coverage`, the typed `limitations`
  (`presence_provider_unavailable`, `presence_is_advisory`,
  `lease_state_not_projected`, `caller_identity_not_supplied`,
  `rows_truncated_at_cap`), and `registered_agent_count` / `omitted_row_count`
  so a truncated directory cannot be read as a complete one;
- membership is proven, not asserted: a caller that is not a registered Agent of
  the Goal receives a typed `audience_not_authorized` scope gap and zero rows,
  and an unknown Goal is refused with `goal_not_registered`;
- a typed-only rollup (`needs_decision`, `stale_claims`, `without_claim`) that
  orders attention and assigns no work, lease or priority;
- an explicit `authority` block: observation grants nothing and nothing is
  written.

The shipped manager skill now tells an in-space Agent to read this directory for
"who else is working on this Goal" and to read its limitations before answering,
and the steward-intake RFC records the producer in both languages.

Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>

@huangruiteng huangruiteng 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.

Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
Reviewed exact head: 8ecc1d3ea2c477c939bed29bb0f0ea740d543057

English verdict: APPROVE

动机

peer_agent_directory_v0(上一刀随 #4539 落地的契约)规定:一个 Agent 必须能发现同一 Goal 下还有哪些 Agent、在有界范围内观察其中一个、并把一条有界请求交给其中一个——peer Agent 与"人对着说话的管家"共用同一份能力。但契约当时没有任何 producer,管家被问"谁还在干活"时只能靠临时拼装。这一刀补上它的第一个(有界、本地、无 presence 的)producer。

改动思路

  • 复用而非第二次读取:行来自既有 agent_management_projection_v0,身份、工作、claim 与 claim 陈旧度仍归各自 owner,不新增 registry/Todo/lease 的第二次读取,也不新增事实源。
  • 不知道就说不存在之外的实话:没有 registered provider 就不编 presence,而是显式输出 presence_coverage 与 typed limitations(presence_provider_unavailable/presence_is_advisory/lease_state_not_projected),避免把"这台机器看不到"读成"它没在跑";也不假装拥有 projection 并不持有的 lease epoch。
  • 截断必须声明:发布 registered_agent_count 与 omitted_row_count 并加 rows_truncated_at_cap,让被截断的目录不会被当成完整目录。
  • membership 靠证明而非声明:--agent-id 与该 Goal 的已注册 Agent 比对;非注册调用方得到 typed audience_not_authorized scope gap 与零行;未知 Goal 直接 goal_not_registered。
  • rollup 只路由注意力:needs_decision/stale_claims/without_claim 全部来自 typed 工作状态,assigns_work: false,并有显式 authority 块(observation_grants: []、writes: false、scheduler: false)。
  • 接到 in-space skill 层:管家 skill 增加一段"用 loopx agent-directory 读 peer 目录,并先读 limitations 再回答",让这一层不是没有调用者的抽象。

具体改动

  • loopx/control_plane/agents/directory.py(+277):build_peer_agent_directory——复用 agent management projection,产出 peer_agent_directory_v0 packet(scope/caller membership/gaps、rows(含 work 块与 observation/delivery refs)、row_count/omitted_row_count/registered_agent_count、typed rollup、presence_coverage、authority、limitations)。
  • loopx/cli_commands/agent_directory.py(+119):CLI 命令与 markdown 渲染;未知 Goal 走 typed 拒绝,采集异常走 typed agent_directory_collection_failed。
  • loopx/cli.py(+8):注册与派发。
  • tests/control_plane/test_peer_agent_directory.py(+152):5 个测试覆盖"有行但无 presence""rollup 语义且不分配""非注册调用方拿到 scope gap""未提供 caller 身份被声明而非编造""截断被显式声明"。
  • loopx/capabilities/manager_context/skills/loopx-manager/SKILL.md(+10):in-space skill 层指引。
  • 协议文档(+28)与 steward-intake RFC(中英 +9):记录已在出货的本地 producer,中英同步。

对主干的风险

  1. 新增一条 CLI 读路径:默认 --scan-path 为当前目录,采集走既有 collect_status(与 status --goal-id 同一读模型),没有新写路径、没有新状态、没有默认行为变更。
  2. 无 presence 是刻意的:本 PR 只出货契约里"prompt-only transport 的常态"那一半;调用方若把它当成运行状态会误读,因此 limitation 与 presence_coverage 都在 packet 里显式声明,并且在 skill 指引里要求先读 limitations。
  3. 截断语义与上游 cap 一致:omitted_row_count 以 projection 发布的 registered_agent_count 为准(该计数是"声明注册 + 有 projected 工作的 claim 方"的并集,测试里明确断言了这个不变量而不是写死数字)。
  4. 既有环境红:本 worktree 中 test_quota_settlement_cli.py[*-sqlite] 因 TS authority fixture 起不来而失败,与上一刀同样、与本 diff 无关;本 PR 相关测试全部通过。
  5. 未做:presence provider、投递路径、Chat 侧 peers 读视图都不在本 PR(已在 PR body 的 residual gaps 点名)。

我的整体评价

正向且 proportional:一个 ~600 行的内聚切片,把一个已存在的契约从"只有规范"推进到"有可调用、可验证、边界清晰的本地 producer",并且把"不能假装知道的东西"(presence、lease、完整性)全部 typed 化。

验证:本机真实 registry 三种读法(注册调用方 13 行 + rollup;非注册调用方 scope gap 且零行;未知 Goal typed 拒绝)实测符合预期;pytest 5+8 passed;docs-governance-smoke 通过;canary premerge 通过(含 peer-agent-runtime-v1-smoke.py、cli-control-plane-command-modularization-smoke.py、semantic-vocabulary-drift-smoke.py 与公开/私有边界扫描)。唯一 advisory 是已知基线 maintainability ratchet。

作为作者自有 PR,GitHub 不允许正式 self-approve,故以本 COMMENTED review 作为放行结论。

@huangruiteng
huangruiteng merged commit 818db75 into main Sep 16, 2026
15 of 20 checks passed
@huangruiteng
huangruiteng deleted the codex/peer-agent-directory-producer branch September 16, 2026 12:07
huangruiteng added a commit to songoow/loopx that referenced this pull request Sep 17, 2026
`loopx agent-directory` shipped in loopx-project#4544 without a manual-visibility
decision, so `examples/cli-help-manpage-smoke.py` fails on every `main` head
with `{'unclassified': ['agent-directory']}` and takes the full public smoke
sweep down with it.

The command produces the local, goal-scoped peer agent directory this host
can hand work to, so it belongs with the other maintainer-facing agent
commands instead of the help-only surface. `man/loopx.1` is regenerated from
`render_manpage()`, because the smoke asserts the checked-in manual equals the
renderer output.

Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
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