Skip to content

Commit 03185d6

Browse files
committed
Mark assertCanTargetAgent as an unwired seam, not a live gate
It has no production call site yet — no verb today lets one live agent address another, so the subtree rule is exercised only by its test. Flagged in code and docs so it is not mistaken for enforced, the same trap writePaths/report.requiredSections/the --config comment/the thrash matcher fell into. assertTierMayMountFleetVerb is unaffected and remains wired at src/subagent/run.ts.
1 parent eeda728 commit 03185d6

2 files changed

Lines changed: 13 additions & 3 deletions

File tree

docs/ARCHITECTURE.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -239,9 +239,9 @@ Every director package carries a required `tier: SubagentTier` field (`src/agent
239239

240240
Enforcement is runtime code at the existing tool-mount point, not prompt wording — this is the fix for four prior mechanisms (`writePaths`, `report.requiredSections`, a `--config` comment, the thrash matcher) that were documented-as-enforced while enforcing nothing:
241241

242-
- **Mount-time gate.** `runSubAgent` (`src/subagent/run.ts`) resolves the spawned director's tier via `tierForDirectorId` (`src/agent/directors/registry.ts`) and calls `assertTierMayMountFleetVerb(tier, toolName)` (`src/subagent/authority.ts`) before installing `task` / `search_agents`. A Tier 3 leaf can never receive a fleet verb even if `orchestrator: true` is passed by mistake — the mount throws instead of silently installing the tool. `FLEET_VERBS` in `authority.ts` also names the not-yet-implemented verbs (`spawn_agent`, `wait_agents`, `list_agents`, `send_input`, `interrupt_agent`, `close_agent`, `resume_agent`, `read_agent_trace`, `followup_task`) so their future mount sites inherit the same gate.
243-
- **Subtree authority.** `assertCanTargetAgent(actor, targetId, nodes)` (`src/subagent/authority.ts`) implements the "root owns its tree; a child manages only its own descendants" rule: Tier 1 may target anyone, Tier 2 may target only its own descendants (walked over the same `{id, parentSessionId}` shape `SubAgentSessionStore` already tracks — no parallel tree), Tier 3 holds no fleet verbs and always fails closed. This is the authority primitive the fleet-targeting verbs land against in later child issues (CL-6942, CL-6951, CL-6945, CL-6946); CL-6941 lands the boundary and its tests, not the verbs.
244-
- `task()` is unaffected and remains the only spawn verb until the new verbs land beside it (deprecated-not-deleted per the CL-6940 epic).
242+
- **Mount-time gate — live today.** `runSubAgent` (`src/subagent/run.ts`) resolves the spawned director's tier via `tierForDirectorId` (`src/agent/directors/registry.ts`) and calls `assertTierMayMountFleetVerb(tier, toolName)` (`src/subagent/authority.ts`) before installing `task` / `search_agents`. A Tier 3 leaf can never receive a fleet verb even if `orchestrator: true` is passed by mistake — the mount throws instead of silently installing the tool. `FLEET_VERBS` in `authority.ts` also names the not-yet-implemented verbs (`spawn_agent`, `wait_agents`, `list_agents`, `send_input`, `interrupt_agent`, `close_agent`, `resume_agent`, `read_agent_trace`, `followup_task`) so their future mount sites inherit the same gate.
243+
- **Subtree authority — a seam, not yet wired.** `assertCanTargetAgent(actor, targetId, nodes)` (`src/subagent/authority.ts`) implements the "root owns its tree; a child manages only its own descendants" rule (Tier 1 may target anyone, Tier 2 may target only its own descendants over the same `{id, parentSessionId}` shape `SubAgentSessionStore` already tracks, Tier 3 always fails closed) — but **it has no production call site yet**. No verb today lets one live agent address another (`task` only spawns), so this rule is exercised only by `authority.test.ts` and is not enforced at runtime in this PR. It exists so CL-6942 (split spawn from wait) and CL-6944 (`send_input` steering) — the first verbs that make an agent addressable by another — can call it from day one instead of each inventing its own check. Treat it as unenforced until one of those wires a call site.
244+
- `task()` is unaffected and remains the only spawn verb until the new verbs land beside it (deprecated-not-deleted per the CL-6940 epic). Its argument schema and wire contract are unchanged; the tier check only gates which packages may have it mounted at all.
245245

246246
#### Closed director fleet (`src/agent/directors/`)
247247

src/subagent/authority.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,16 @@ function isDescendant(
8888
}
8989

9090
/**
91+
* SEAM, NOT YET A LIVE GATE: this function has no production call site today.
92+
* No verb in this codebase currently lets one live agent target another
93+
* (`task` only spawns; it never addresses an existing session), so the
94+
* subtree rule below is exercised only by authority.test.ts — it is not
95+
* enforced at runtime yet. It exists now so CL-6942 (split spawn from wait)
96+
* and CL-6944 (send_input steering) — the first two verbs that make one
97+
* agent addressable by another — can call it from day one instead of
98+
* inventing their own check. Until one of those wires a call site here, do
99+
* not describe this rule as enforced; only assertTierMayMountFleetVerb is.
100+
*
91101
* Authority rule (root owns its tree; a child manages only its own
92102
* descendants): throws unless `actor` is Tier 1, or `targetId` is `actor.id`
93103
* itself, or a descendant of `actor.id` in `nodes`. A Tier 3 leaf holds no

0 commit comments

Comments
 (0)