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
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,44 @@ apply receipt returns; if the confirmation was refused, or the plan went stale
because the Agents it named changed, say exactly that instead. Never widen the
confirmed scope while applying it, and never charge quota for the preview itself.

The preview is machine-readable, so the product surface can offer it as one
typed action. Your prose answer stays the answer; the same team plan also rides
in the response envelope's `proposals` as exactly one item of kind
`steward_team_plan_preview`:

```json
{
"kind": "steward_team_plan_preview",
"schema_version": "steward_team_plan_preview_v0",
"goal_id": "<the exact Goal this plan staffs>",
"objective": "<one sentence>",
"lanes": [
{
"lane_id": "<short stable id>",
"agent_id": "<an Agent this Goal registers>",
"acceptance": "<the signal that ends this lane>",
"first_todo": {
"text": "<one bounded Todo>",
"priority": "P1",
"task_class": "advancement_task",
"action_kind": "<an action kind this host supports>"
}
}
],
"quota_envelope": { "<the bounded envelope this team may use>" },
"stop_condition": "<the condition that ends the team>"
}
```

At most 8 lanes, each with a distinct `lane_id`. A priority is `P0`, `P1`,
`P2` or `P3`. A lane you cannot staff keeps its `lane_id`, `agent_id` and
`acceptance`, declares `staffing_gap` with one of `agent_not_registered`,
`capability_not_granted` or `audience_not_authorized` plus a note, and declares
no `first_todo`. A preview that arrives without this item, names a Goal you are
not authorized for, or names an Agent that Goal does not register is dropped
rather than shown: the owner must never be offered a confirmation for work that
cannot be staffed.

Core owns truth and permissions. This skill supplies reasoning guidance, not
new authority. Keep front-end and group answers within their respective scopes;
give concise, concrete answers with source and coverage notes where they matter.
46 changes: 46 additions & 0 deletions tests/test_manager_team_plan_guidance.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,49 @@ class _Unknown(RuntimeError):
error_code = "some_future_code"

assert manager_failure_reply(_Unknown("x"))[0] == "processing_failed"


def test_manager_guidance_ships_the_machine_readable_preview_contract() -> None:
"""The preview the owner confirms is the one admission can validate.

Prose alone cannot reach the product surface: admission only surfaces a
team preview that arrives as this typed item, so guidance that never states
the item leaves a live steward answering correctly and still offering the
owner nothing to confirm. The guidance and the validator therefore share
their identifiers, and drift fails here instead of in a live answer.
"""

from loopx.control_plane.work_items.governed_transition_proposal import (
STEWARD_TEAM_PLAN_GAP_REASONS,
STEWARD_TEAM_PLAN_LANE_LIMIT,
STEWARD_TEAM_PLAN_PREVIEW_KIND,
STEWARD_TEAM_PLAN_PREVIEW_SCHEMA_VERSION,
)

text = manager_skill_text()

assert STEWARD_TEAM_PLAN_PREVIEW_KIND in text
assert STEWARD_TEAM_PLAN_PREVIEW_SCHEMA_VERSION in text
assert "proposals" in text
assert f"{STEWARD_TEAM_PLAN_LANE_LIMIT} lanes" in text
for field in (
'"goal_id"',
'"objective"',
'"lanes"',
'"lane_id"',
'"agent_id"',
'"acceptance"',
'"first_todo"',
'"action_kind"',
'"task_class"',
'"quota_envelope"',
'"stop_condition"',
):
assert field in text, field
assert "staffing_gap" in text
assert "declares\nno `first_todo`" in text
assert "advancement_task" in text
for reason in STEWARD_TEAM_PLAN_GAP_REASONS:
assert reason in text, reason
# The preview never claims an effect of its own.
assert "is dropped\nrather than shown" in text
Loading