Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 82 additions & 33 deletions docs/architecture/rfcs/harness-selection-dsh-pi-v0.md
Original file line number Diff line number Diff line change
Expand Up @@ -474,13 +474,13 @@ Validation: `tests/capabilities/test_steward_executor_machine_defaults.py`,
`tests/capabilities/test_capability_configuration_ui.py`, and
`examples/loopx-steward-channel-binding-smoke.py`.

## Steward Team Intake (planned, 2026-09-16)
## Steward Team Intake (2026-09-16)

The steward answers questions today, and since `2026-09-16` its shipped
guidance carries one bounded procedure for a different request: one owner
sentence that asks for a *team* rather than a task. That procedure is guidance,
not machine enforcement, so this section records where the enforced contract
belongs and what it must validate before any implementation lands.
The steward answers questions. Since `2026-09-16` its shipped guidance also
carries one bounded procedure for a different request: one owner sentence that
asks for a *team* rather than a task. This section records the enforced contract
for that intake, which part of it is already shipped, and which part is still
missing.

The intake boundary is the canonical governed-proposal owner
(`loopx/control_plane/work_items/governed_transition_proposal.py`), not a new
Expand All @@ -492,37 +492,86 @@ beside the existing one. A command with no second caller, and a builder module
with no caller at all, both stay out: this repository keeps an uncalled
abstraction in design state until its call site exists.

The proposal payload is validated before anything may be applied, and it names:
A proposal of kind `steward_team_plan_preview` (`steward_team_plan_preview_v0`)
is validated before anything may be applied, and a validated preview names, and
may not invent:

- each lane and the Agent that runs it, resolved from Agents Core already
registers for the Goal;
- that lane's first bounded Todo, with its declared priority, task class and
action kind;
- the quota or cadence envelope that bounds the lanes;
- each lane and the Agent that runs it, resolved from the Agents Core already
registers for the Goal, at most 8 lanes;
- that lane's first bounded Todo, with its declared priority (P0..P3), task
class and action kind;
- the quota envelope that bounds the lanes;
- the acceptance signal that ends each lane;
- the stop condition that ends the team.

A requested lane that cannot be staffed is a typed gap naming the missing
registration or grant; it is never filled in by inventing an Agent, a Todo
capability, or a lane the machine cannot run. The plan is a preview: it creates
no Todo, registers no Agent, sets no quota, and spends none, and an owner's
confirmation of that exact preview is the only thing that admits an apply.
Apply routes to the canonical owners each effect already has -- Agent
registration, Todo creation, quota or goal policy -- reuses the identities the
preview named, and returns one readback of what exists. It may not widen the
confirmed scope, and a team plan is never settled as if the work were done.

Delivery is two slices, in this order:

1. **Preview slice (next).** The typed payload contract and its validator, with
focused tests, and no materializer registered, so a preview cannot apply
even by mistake.
2. **Apply slice.** A materializer for that kind, with its settlement phase and
readback, routed through the owners above.

What this planned contract does not authorize: the steward still only proposes
and delegates; selecting a steward executor or storing a credential grants none
of these effects; and nothing here widens OS, provider, audience or work-state
A requested lane that cannot be staffed is a typed gap -- `agent_not_registered`,
`capability_not_granted` or `audience_not_authorized` -- and the gap keeps the
work it did not staff under `declined_first_todo`, so the owner sees what was
asked for and what is missing instead of a lane that was quietly filled in or
dropped. A lane that declares a gap may not declare work. The plan is a preview:
the validated payload carries `applies: false`, and an owner's confirmation of
that exact preview is the only thing that admits an apply. Apply routes to the
canonical owners each effect already has -- Agent registration, Todo creation,
quota or goal policy -- reuses the identities the preview named, may not widen
the confirmed scope, and a team plan is never settled as if the work were done.

Shipped enforcement, in delivery order:

1. **Contract and validator** (`#4519`, `3acd07697`). The kind, its schema, the
lane limit, the priority and gap vocabularies, public-safe text, and the
refusal to invent staffing.
2. **Chat admission** (`#4522`, `3c8c832cb`). `normalize_agent_response` admits a
preview only when the host supplies `team_plan_context` -- this Goal's
registered Agents and this host's supported advancement action kinds -- and
drops it otherwise, exactly like any other proposal it cannot accept, while
the answer text still reaches the owner.
3. **Apply** (`#4524`, `c159a15b3`). The governed transition owner dispatches the
kind at `PRE_SETTLEMENT`. The apply re-validates the proposal against the
Goal's registered Agents and the shipped advancement action kinds, creates
the first bounded Todo of each *ready* lane through the canonical Todo owner,
creates nothing for a gap lane, and refuses an unknown Goal before any write.
The receipt records the proposal digest, so a replayed settlement reuses the
same lane Todo instead of adding a second row.

The intake is still inert in production, and this section does not claim
otherwise. Nothing yet supplies `team_plan_context`, so a model-authored preview
is dropped at admission instead of being surfaced for confirmation; the adapter
that supplies the admission facts and the settlement that re-derives them must
stay one contract rather than two; and the apply entry point today is a governed
capability execution journal, so a confirmed Chat preview needs that bridge
before an owner confirmation can materialize lanes. Two further gaps belong with
this work: the published receipt carries the first lane Todo's identity rather
than the identity of every lane it created (the apply result computes the full
`lane_todo_ids` set, and the receipt field set is closed and persisted, so
publishing it is a bounded compatibility change), and a multi-lane preview has
no frontend confirmation surface yet.

### Relationship to the multi-agent contracts

The intake is a user-layer affordance over the kernel the multi-agent contracts
already define; it adds no second team runtime.

- Against `multi_agent_three_layer_minimality_contract_v0`
(`docs/reference/protocols/multi-agent-three-layer-minimality-v0.md`), the
owner's one sentence is the user layer, the steward's bounded procedure is the
preset layer, and lanes, first bounded Todos, quota envelope, acceptance and
stop condition are declared data the kernel mechanics consume. The intake must
not own a runner, panes, per-agent vision budgets or evidence loops; it
materializes goal work lanes through the canonical Todo owner, which is what
keeps a team request from becoming a product-specific runner.
- Against `multi_agent_visible_launcher_v0`
(`docs/reference/protocols/multi-agent-visible-launcher-v0.md`), the launcher
starts visible local panes from a `generic_multi_agent_launch_spec_v0`, and
the intake is the same intent entered from Chat. They join by identity
(`goal_id`, `agent_id`, and the lane's first Todo), not by one calling the
other, and the launcher's own rule applies unchanged to the intake: no leader
agent, hidden scheduler, promotion authority or second source of truth. A plan
that needs visible panes, pane-local A2A ticks or promotion evidence has to
name that as a supported action kind instead of embedding it in the preview.

What this contract does not authorize: the steward still only proposes and
delegates; selecting a steward executor or storing a credential grants none of
these effects; and nothing here widens OS, provider, audience or work-state
authority.

## Steward Channel Readiness by Milestone (2026-09-15)
Expand Down
78 changes: 57 additions & 21 deletions docs/architecture/rfcs/harness-selection-dsh-pi-v0.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -373,11 +373,11 @@ journal 与配额语义;B 作为上游接口出现时的低成本替代;只
`tests/capabilities/test_capability_configuration_ui.py`,以及
`examples/loopx-steward-channel-binding-smoke.py`。

## 管家团队入端口径(规划中,2026-09-16)
## 管家团队入端口径(2026-09-16)

管家今天回答问题;自 2026-09-16 起,它的出厂指引里已带一段有界流程,用于另一类请求:
业主一句话要的是**团队**而不是单个任务。那段流程是指引,不是机器强制,因此本节记录被强制
的契约属于哪里、以及实现落地前必须校验什么。
管家负责回答问题。自 2026-09-16 起,它的出厂指引里还带了一段有界流程,用于另一类请求:
业主一句话要的是**团队**而不是单个任务。本节记录这条入端口径被强制的契约、其中已经落地的
部分,以及仍然缺失的部分。

入端口径是既有的受治理提案所有者
(`loopx/control_plane/work_items/governed_transition_proposal.py`),不是新的 CLI 命令,
Expand All @@ -386,27 +386,63 @@ Chat Turn 也早已把 `response.proposals` 投影成 `proposal.ready` 事件。
**一种新 kind 的提案**,而不是在既有路径旁再开一条入端口。没有第二个调用方的命令、以及
完全没有调用方的 builder 模块都不新增:本仓库要求未获调用的抽象先留在设计态。

在允许任何落地之前先校验提案载荷,它必须点名:
kind 为 `steward_team_plan_preview`(`steward_team_plan_preview_v0`)的提案,在任何落地
之前先被校验;校验通过的预览必须点名、且不得编造:

- 每条 lane 及其运行的 Agent,且只能来自 Core 已为该 Goal 注册的 Agent;
- 该 lane 的首个有界 Todo,含其声明优先级、task class 与 action kind;
- 约束这些 lane 的 quota 或节奏包络;
- 每条 lane 及其运行的 Agent,且只能来自 Core 已为该 Goal 注册的 Agent,最多 8 条 lane;
- 该 lane 的首个有界 Todo,含其声明优先级(P0..P3)、task class 与 action kind;
- 约束这些 lane 的 quota 包络;
- 结束每条 lane 的验收信号;
- 结束整个团队的终止条件。

配不齐的 lane 是类型化的 gap(缺哪个注册或授予),不允许靠编造 Agent、Todo 能力或本机跑不动
的 lane 来填。计划是**预览**:不建 Todo、不注册 Agent、不设 quota、不扣额度;只有业主对这
份确切预览的确认,才允许进入落地。落地只经各 effect 既有的 canonical owner——Agent 注册、
Todo 创建、quota 或 goal policy——复用预览点名的身份,并返回一份"现在存在什么"的回读;不得
扩大已确认范围,也不得把团队计划当作工作已完成的结算。

按此顺序分两片交付:

1. **预览片(下一步)**:类型化载荷契约与其校验器,配聚焦测试,且不注册 materializer,
使预览即使被误用也无法落地。
2. **落地片**:该 kind 的 materializer,含其结算相位与回读,并按上文经既有 owner 路由。

这条规划契约不授权什么:管家仍然只提议与委托;选择管家执行器或存凭据都不带来这些 effect;
配不齐的 lane 是类型化的 gap——`agent_not_registered`、`capability_not_granted` 或
`audience_not_authorized`——并且该 gap 会把没配上人的那份工作留在 `declined_first_todo`
里,让业主看到"要了什么、缺了什么",而不是一条被悄悄填上或被丢掉的 lane;声明 gap 的
lane 不得再声明工作。计划是**预览**:校验通过的载荷带 `applies: false`;只有业主对这份确切
预览的确认,才允许进入落地。落地只经各 effect 既有的 canonical owner——Agent 注册、
Todo 创建、quota 或 goal policy——复用预览点名的身份,不得扩大已确认范围,也不得把团队计划
当作工作已完成的结算。

按交付顺序,已经落地并受强制的部分:

1. **契约与校验器**(`#4519`,`3acd07697`):kind、schema、lane 上限、优先级与 gap 词表、
公开安全文本,以及"拒绝编造 staffing"的行为。
2. **聊天准入**(`#4522`,`3c8c832cb`):`normalize_agent_response` 只在宿主提供
`team_plan_context`(本 Goal 已注册 Agent + 本机支持的 advancement action kind)时才让
预览通过;否则与其它无法接受的提案一样被丢弃,而答案正文仍然到达业主。
3. **落地**(`#4524`,`c159a15b3`):受治理提案所有者在 `PRE_SETTLEMENT` 相位分派该 kind,
落地时重新按本 Goal 已注册 Agent 与本机 shipment 的 advancement action kind 校验,经
canonical Todo owner 为每条 **ready** lane 创建首个有界 Todo,gap lane 不创建任何东西,
未知 Goal 在任何写入前就被拒绝,回执记录 proposal digest,因此重放结算复用同一条 lane
Todo 而不会新增第二行。

这条入端口径目前在线上仍是**惰性**的,本节不作相反声明:还没有任何生产调用方传入
`team_plan_context`,因此模型产出的预览会在准入处被丢弃,而不会浮现给业主确认;提供准入事实
的适配器与重新推导这些事实的结算必须保持同一份契约而不是两份;而今天的落地入口是受治理能力
执行 journal,所以被确认的 Chat 预览还需要那座桥,业主确认才能真正建成 lane。另有两处缺口
属于这条工作线:已发布回执只带第一条 lane Todo 的身份,而不是它创建的全部 lane 身份(apply
结果里算了完整的 `lane_todo_ids`,但回执字段集是封闭且持久化的,发布它是一次有界的兼容性
变更);以及多 lane 预览还没有前端确认面。

### 与 multi-agent 契约的关系

这条入端口径是既有 multi-agent 契约所定义内核之上的**用户层**便利:它不新增第二套团队
runtime。

- 对应 `multi_agent_three_layer_minimality_contract_v0`
(`docs/reference/protocols/multi-agent-three-layer-minimality-v0.md`):业主那一句话是用户
层,管家那段有界流程是 preset 层,而 lanes、首个有界 Todo、quota 包络、验收与终止条件是
内核机制消费的声明数据。入端口径不得拥有 runner、pane、per-agent vision 预算或证据回路;
它只经 canonical Todo owner 建出 Goal 工作 lane,这正是它不会变成产品专用 runner 的原因。
- 对应 `multi_agent_visible_launcher_v0`
(`docs/reference/protocols/multi-agent-visible-launcher-v0.md`):launcher 从
`generic_multi_agent_launch_spec_v0` 启动可见本地 pane,而这条入端口径是同一意图从 Chat
进入。两者按身份相连(`goal_id`、`agent_id` 与该 lane 的首个 Todo),而不是互相调用;
launcher 自身那条规则对入端口径同样成立:不得成为 leader agent、隐藏调度器、晋升权威或
第二真源。需要可见 pane、pane 内 A2A tick 或晋升证据的计划,必须把它声明为受支持的
action kind,而不是塞进预览里。

这条契约不授权什么:管家仍然只提议与委托;选择管家执行器或存凭据都不带来这些 effect;
这里也不会扩大 OS、provider、受众或工作状态权限。

## 按里程碑看管家通道的就绪度(2026-09-15)
Expand Down
13 changes: 8 additions & 5 deletions loopx/control_plane/work_items/governed_transition_proposal.py
Original file line number Diff line number Diff line change
Expand Up @@ -448,11 +448,14 @@ def validate_steward_team_plan_preview(
) -> dict[str, Any]:
"""Validate one steward team preview, and refuse to invent its staffing.

The preview is the whole effect of this kind: it creates nothing, so it has
no materializer and no settlement phase. A lane whose Agent this Goal does
not register becomes a typed gap that keeps the work it did *not* staff
under ``declined_first_todo``, so the owner sees what was asked for and what
is missing instead of a lane that was quietly filled in or dropped.
Validation is the same contract at both ends: the Chat admission uses it to
decide whether a preview may be surfaced for confirmation, and the
``PRE_SETTLEMENT`` apply of that kind calls it again with the host's own
facts before it creates anything, so a proposal cannot become work by
bypassing admission. A lane whose Agent this Goal does not register becomes
a typed gap that keeps the work it did *not* staff under
``declined_first_todo``, so the owner sees what was asked for and what is
missing instead of a lane that was quietly filled in or dropped.
"""

plan = _mapping(payload, "steward_team_plan_preview")
Expand Down
Loading