hive-c0re: drop the subtree check from the scheduling verbs

The topology predicate `is_descendant_of` gated the four schedule-
managing verbs: a caller could only name a schedule owned by an agent at
or below itself in `topology.json`. Those gates now permit any requester,
so the predicate, its pure `_in` form and the `schedule_authorized`
wrapper built on it are gone rather than left returning a constant. The
other two wrappers went earlier with the verbs they served —
`require_descendant` with the lifecycle MCP verbs in 87970a8c, and
`resolve_agent_state_target` with `get_loose_ends`'s agent parameter.

`require_group(agent, "scheduling", ...)` is untouched and still fires at
dispatch for every one of the five scheduling verbs, so holding the tool
group remains the gate; what goes is the ownership restriction layered on
top of it.

The three schedule-mutating verbs keep their row lookup as a plain
existence check, so a caller naming a schedule that does not exist still
gets `not found` rather than a message from deeper in the cancel path.
`list_schedules` stops filtering per row: it would only have hidden rows
the requester may act on anyway.

Error messages, tool descriptions and docs that described the subtree
relation are reworded — a refusal message naming a topology that no
longer decides anything is worse than none.

The six `is_descendant_of_in` unit tests go with the function they test;
the permit behaviour they leave unasserted is picked up by the next
commit.

Refs #4472
This commit is contained in:
atlas 2026-09-17 19:27:15 +02:00 committed by mara
commit 4121e11d87
8 changed files with 67 additions and 277 deletions

View file

@ -10,10 +10,9 @@ targets only yourself — use `remind` for an unapproved self-wake. The
other four verbs need no approval: holding the `scheduling` tool group
is the whole gate.
Authorization is one rule for all four verbs: you reach schedules you own
and any owned by an agent in your topology subtree. `list_schedules`
applies it too, so the snapshot only ever shows schedules you could also
cancel.
Authorization is one rule for all four verbs: you reach every schedule in
the hive, whoever owns it. `list_schedules` shows the same set, so the
snapshot only ever shows schedules you could also cancel.
### `request_schedule_prompt(targets, body, first_fire_at_unix, interval_seconds?, description?)`
@ -61,13 +60,11 @@ consumes one-shot schedules and cancels them afterwards.
### `list_schedules()`
Snapshot the schedules you're authorized to see (active, and cancelled
but not yet reaped) — same read scope as the rest of this group: your
own, plus any owned by a sub-agent in your subtree (everything, for
the operator). Returns id, owner, body, per-target `last_fired_at`
and `last_result`, `next_fire_at_unix`, `interval_seconds`. Use to
look up an id before cancelling, or to audit upcoming wake-ups in
your subtree.
Snapshot every schedule in the hive (active, and cancelled but not yet
reaped) — same read scope as the rest of this group. Returns id, owner,
body, per-target `last_fired_at` and `last_result`,
`next_fire_at_unix`, `interval_seconds`. Use to look up an id before
cancelling, or to audit upcoming wake-ups across the hive.
## `read_host_journal` capability