5 _roles/*.toml per locked §Initial role inventory:
- read-only → tools::read-only + output::report-format + severity-grade
- explorer → read-only caps + tools::cargo-only-bash
- edit-local → no-git-ops + scope::files-{white,deny}list + quality::*
+ safety::no-dep-bump + output::report-format
- edit-shared → edit-local caps + relaxed SSoT whitelist (task-time param)
+ escalation tightened to orchestrator-notify
- git-ops → spawnable = false, documentation-only
All 11 capability names referenced match phase-1 deliverable path
_capabilities/<cat>/<slug>/ (cross-ref verified before commit).
docs/AGENT-ROLES.md (223 LOC) — human-readable matrix: per-role sections
+ cross-role capability matrix + explicit non-spawnable-git-ops block.
Drift note for orchestrator integration review: edit-local/edit-shared
use inline bash-patterns-allowed = ['^cargo( |$)', '^mkdir( |$)',
'^rm -rf /tmp/'] instead of composing with tools::cargo-only-bash
capability (extra patterns not in that atom). Agent footnoted —
resolution deferred to post-integration (either parameterize the cap
or introduce tools::cargo-plus-basic-bash variant).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
223 lines
10 KiB
Markdown
223 lines
10 KiB
Markdown
# Agent Roles — Human-Readable Matrix
|
|
|
|
**SSoT:** `_roles/*.toml` (5 files).
|
|
**Schema:** [AGENT-SUBSTRATE-SCHEMA.md](./AGENT-SUBSTRATE-SCHEMA.md) §Role.
|
|
**Lock marker:** [AGENT-SCHEMA-LOCKED.md](./AGENT-SCHEMA-LOCKED.md).
|
|
|
|
Five roles compose locked capability atoms from `_capabilities/<category>/<slug>/` into prompt bundles for the Agent tool. Each role is a declarative TOML; the `kei-agent-runtime compose` step concatenates the listed capability `text.md` fragments in order to produce the final `prompt.md` for an agent invocation. Tool and bash-pattern allowlists are enforced at PreToolUse by `kei-capability check`; verify-class capabilities are enforced on agent return by `kei-capability verify`.
|
|
|
|
This document is derived from the 5 role TOMLs by hand. When `kei-agent-runtime` ships (phase 3), a `kei-agent-runtime doc-roles` subcommand will regenerate this file mechanically.
|
|
|
|
---
|
|
|
|
## 1. `read-only`
|
|
|
|
**Display name:** explorer (read-only analyst)
|
|
**Spawnable:** yes
|
|
**Escalation:** `ask-via-return`
|
|
|
|
Pure inspection agent. Reads code and docs, optionally fetches a URL, emits a structured report with severity grades. No shell, no edits, no git. Cheapest and safest role.
|
|
|
|
**Capabilities bundled:**
|
|
|
|
- [`tools::read-only`](../_capabilities/tools/read-only/text.md) — denies `Edit` and `Write` entirely at PreToolUse
|
|
- [`output::report-format`](../_capabilities/output/report-format/text.md) — verify: parse report, assert required fields present
|
|
- [`output::severity-grade`](../_capabilities/output/severity-grade/text.md) — verify: each finding tagged with E1-E6 evidence grade
|
|
|
|
**Tools allowed:**
|
|
|
|
| Tool | Allowed | Notes |
|
|
|---|---|---|
|
|
| Read | yes | — |
|
|
| Glob | yes | — |
|
|
| Grep | yes | — |
|
|
| WebFetch | yes | external references |
|
|
| Edit | no | blocked by `tools::read-only` |
|
|
| Write | no | blocked by `tools::read-only` |
|
|
| Bash | no | not in allowlist |
|
|
|
|
**Typical use cases:**
|
|
|
|
- Code audit / critic passes (anti-pattern sweep, Constructor Pattern compliance)
|
|
- Prior-art search, docs survey, dependency research
|
|
|
|
---
|
|
|
|
## 2. `explorer`
|
|
|
|
**Display name:** explorer + cargo-check (read-only analyst with build probe)
|
|
**Spawnable:** yes
|
|
**Escalation:** `ask-via-return`
|
|
|
|
Read-only baseline plus a single permitted shell family: `cargo` invocations. Use when an audit needs `cargo check`, `cargo test`, `cargo tree`, `cargo metadata` to ground findings in actual build state — still cannot edit, still cannot git.
|
|
|
|
**Capabilities bundled:**
|
|
|
|
- [`tools::read-only`](../_capabilities/tools/read-only/text.md)
|
|
- [`tools::cargo-only-bash`](../_capabilities/tools/cargo-only-bash/text.md) — PreToolUse:Bash denies unless command matches `^cargo( |$)`
|
|
- [`output::report-format`](../_capabilities/output/report-format/text.md)
|
|
- [`output::severity-grade`](../_capabilities/output/severity-grade/text.md)
|
|
|
|
**Tools allowed:**
|
|
|
|
| Tool | Allowed | Notes |
|
|
|---|---|---|
|
|
| Read | yes | — |
|
|
| Glob | yes | — |
|
|
| Grep | yes | — |
|
|
| WebFetch | yes | — |
|
|
| Bash | yes | only `^cargo( |$)` patterns |
|
|
| Edit | no | blocked by `tools::read-only` |
|
|
| Write | no | blocked by `tools::read-only` |
|
|
|
|
**Typical use cases:**
|
|
|
|
- Build-state-grounded audits (test counts, compile errors, workspace graph)
|
|
- Reproduction of integration-test failures without risk of edits
|
|
|
|
---
|
|
|
|
## 3. `edit-local`
|
|
|
|
**Display name:** code-implementer (local edit scope)
|
|
**Spawnable:** yes
|
|
**Escalation:** `ask-via-return`
|
|
|
|
The default code-writing role. Writes to task-whitelisted files, runs cargo-family commands, emits a required-field report. Cannot touch git, cannot bump deps, cannot edit files outside its whitelist or inside its denylist. On return, four verify-class capabilities run: Constructor Pattern limits, workspace cargo check, per-crate tests, and lock-file stability.
|
|
|
|
**Capabilities bundled:**
|
|
|
|
- [`policy::no-git-ops`](../_capabilities/policy/no-git-ops/text.md) — blocks `git`, `gh repo`, `gh api /repos` at PreToolUse:Bash
|
|
- [`scope::files-whitelist`](../_capabilities/scope/files-whitelist/text.md) — PreToolUse:Edit|Write denies paths outside whitelist; on-return git diff check
|
|
- [`scope::files-denylist`](../_capabilities/scope/files-denylist/text.md) — denies paths in denylist (overrides whitelist)
|
|
- [`quality::constructor-pattern`](../_capabilities/quality/constructor-pattern/text.md) — verify: no file > 200 LOC, no fn > 30 LOC
|
|
- [`quality::cargo-check-green`](../_capabilities/quality/cargo-check-green/text.md) — verify: `cargo check --workspace` from MAIN passes (simulated-merge)
|
|
- [`quality::tests-green`](../_capabilities/quality/tests-green/text.md) — verify: `cargo test -p <crate>` passes, count ≥ task min
|
|
- [`safety::no-dep-bump`](../_capabilities/safety/no-dep-bump/text.md) — PreToolUse:Edit on Cargo.toml denies unless task opts in
|
|
- [`output::report-format`](../_capabilities/output/report-format/text.md)
|
|
|
|
**Tools allowed:**
|
|
|
|
| Tool | Allowed | Notes |
|
|
|---|---|---|
|
|
| Read | yes | — |
|
|
| Write | yes | scope-gated |
|
|
| Edit | yes | scope-gated |
|
|
| Glob | yes | — |
|
|
| Grep | yes | — |
|
|
| Bash | yes | patterns: `^cargo( |$)`, `^mkdir( |$)`, `^rm -rf /tmp/` |
|
|
|
|
**Typical use cases:**
|
|
|
|
- Implement a new crate / feature within a bounded file whitelist
|
|
- Refactor inside one crate with dep-lock stability guaranteed
|
|
|
|
---
|
|
|
|
## 4. `edit-shared`
|
|
|
|
**Display name:** code-implementer (shared-SSoT edit scope)
|
|
**Spawnable:** yes
|
|
**Escalation:** `orchestrator-notify`
|
|
|
|
Same capabilities as `edit-local`. The difference is **operational, not declarative**: for `edit-shared`, the orchestrator parameterizes `scope::files-whitelist` in `task.toml` to include one or more SSoT paths (e.g. workspace `Cargo.toml`, a registry file, a cross-crate type definition). Escalation is tightened from `ask-via-return` to `orchestrator-notify` so SSoT edits surface immediately.
|
|
|
|
**Capabilities bundled:** identical to `edit-local` — the SSoT relaxation rides on per-task `scope::files-whitelist` parameterization, not on a different capability set.
|
|
|
|
**Tools allowed:** identical to `edit-local`.
|
|
|
|
**Typical use cases:**
|
|
|
|
- Workspace-level edits (add a member crate, bump a shared version)
|
|
- Cross-crate API changes where one type SSoT must be edited alongside its consumers
|
|
|
|
**Difference from `edit-local` at a glance:**
|
|
|
|
| Dimension | `edit-local` | `edit-shared` |
|
|
|---|---|---|
|
|
| Capability set | identical | identical |
|
|
| Whitelist (task.toml) | local crate paths only | local crate + one SSoT path |
|
|
| Escalation | `ask-via-return` | `orchestrator-notify` |
|
|
| Typical use | inside one crate | crosses a crate or workspace boundary |
|
|
|
|
---
|
|
|
|
## 5. `git-ops` — NON-SPAWNABLE (orchestrator-only)
|
|
|
|
**Display name:** git operator (orchestrator-only, NOT spawnable)
|
|
**Spawnable:** **no**
|
|
**Escalation:** `fail-fast` (not reachable at runtime)
|
|
|
|
Documented boundary of git authority — not a live role. Present in the inventory so that "who can run git" has an explicit declarative answer.
|
|
|
|
Per [RULE 0.13 — ORCHESTRATOR BRANCH FIRST](../../.claude/rules/orchestrator-branch-first.md), only the orchestrator (main session) holds git power:
|
|
|
|
- branch creation (`git checkout -b …`)
|
|
- commit (`git add <paths> && git commit -m …`)
|
|
- push (`git push <remote> <branch>`)
|
|
- merge (`git merge --no-ff`, `git merge --squash`)
|
|
- rebase, reset, tag
|
|
|
|
Agents running inside `.claude/worktrees/<agent>/` cannot invoke `git` — the sandbox denies Bash inside the worktree path. This role exists to make that boundary visible in the capability substrate, not to enable spawns.
|
|
|
|
`kei-agent-runtime spawn` MUST refuse any `task.toml` whose `[task].role = "git-ops"` with a pointer to RULE 0.13. The refusal is a hard error, not a warning.
|
|
|
|
**Rationale (why documented at all):**
|
|
|
|
- Future contributors see "git is a role" and "that role is unreachable" in the same place
|
|
- `kei-agent-runtime doc-roles` regeneration will surface the non-spawnable notice so it never goes stale
|
|
- Matches how `_roles/git-ops.toml` holds `spawnable = false` explicitly — declarative, greppable
|
|
|
|
---
|
|
|
|
## Cross-role capability matrix
|
|
|
|
Capabilities as rows, roles as columns. A ✓ means the role lists the capability in `[capabilities].required`; ✗ means it does not.
|
|
|
|
| Capability | `read-only` | `explorer` | `edit-local` | `edit-shared` | `git-ops` |
|
|
|---|:-:|:-:|:-:|:-:|:-:|
|
|
| `policy::no-git-ops` | ✗ | ✗ | ✓ | ✓ | ✗ |
|
|
| `scope::files-whitelist` | ✗ | ✗ | ✓ | ✓ | ✗ |
|
|
| `scope::files-denylist` | ✗ | ✗ | ✓ | ✓ | ✗ |
|
|
| `quality::constructor-pattern` | ✗ | ✗ | ✓ | ✓ | ✗ |
|
|
| `quality::cargo-check-green` | ✗ | ✗ | ✓ | ✓ | ✗ |
|
|
| `quality::tests-green` | ✗ | ✗ | ✓ | ✓ | ✗ |
|
|
| `safety::no-dep-bump` | ✗ | ✗ | ✓ | ✓ | ✗ |
|
|
| `output::report-format` | ✓ | ✓ | ✓ | ✓ | ✗ |
|
|
| `output::severity-grade` | ✓ | ✓ | ✗ | ✗ | ✗ |
|
|
| `tools::read-only` | ✓ | ✓ | ✗ | ✗ | ✗ |
|
|
| `tools::cargo-only-bash` | ✗ | ✓ | ✗ (¹) | ✗ (¹) | ✗ |
|
|
|
|
(¹) `edit-local` and `edit-shared` do not compose `tools::cargo-only-bash` as a capability atom; instead they carry an inline `bash-patterns-allowed` list in `[tools]` that encodes the same restriction. Both routes converge at the PreToolUse:Bash gate. Phase 3 runtime may later collapse the inline list into `tools::cargo-only-bash-plus-mkdir-and-tmp` capability atoms — non-breaking.
|
|
|
|
## Tool allowlist matrix
|
|
|
|
| Tool | `read-only` | `explorer` | `edit-local` | `edit-shared` | `git-ops` (²) |
|
|
|---|:-:|:-:|:-:|:-:|:-:|
|
|
| Read | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
| Glob | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
| Grep | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
| WebFetch | ✓ | ✓ | ✗ | ✗ | ✓ |
|
|
| Edit | ✗ | ✗ | ✓ | ✓ | ✓ |
|
|
| Write | ✗ | ✗ | ✓ | ✓ | ✓ |
|
|
| Bash | ✗ | cargo-only | cargo+mkdir+tmp | cargo+mkdir+tmp | any |
|
|
|
|
(²) `git-ops` values are documentation only — the role is non-spawnable.
|
|
|
|
## Escalation policy matrix
|
|
|
|
| Role | Policy | Meaning |
|
|
|---|---|---|
|
|
| `read-only` | `ask-via-return` | Surface questions in the final report; orchestrator reads them |
|
|
| `explorer` | `ask-via-return` | Same |
|
|
| `edit-local` | `ask-via-return` | Same |
|
|
| `edit-shared` | `orchestrator-notify` | Touching SSoT ⇒ notify orchestrator before completing |
|
|
| `git-ops` | `fail-fast` | Unreachable; any spawn attempt errors |
|
|
|
|
---
|
|
|
|
## Maintenance
|
|
|
|
- Changes to any `_roles/*.toml` require updating this file in the same commit.
|
|
- New roles are added as new sections 6+ with the same structure, and new columns added to the two matrices above.
|
|
- When `kei-agent-runtime doc-roles` ships in phase 3, it replaces the hand-authored matrix; the top-of-file "derived by hand" note is removed then.
|