diff --git a/11-Features.md b/11-Features.md index a3ee8ae..358e083 100644 --- a/11-Features.md +++ b/11-Features.md @@ -1983,6 +1983,37 @@ Still to catalogue: consequence to write up: the cap bounds nudges *about one item*, so a lead with a steady arrival of new work keeps being nudged — which is correct, but is not what the knob's name suggests +### Role agent definitions — how a member learns its role (CB-617) + +**What it does.** The `architect`, `dev` and `reviewer` contracts live as files in the repo, at both +`.claude/agents/.md` and `.opencode/agent/.md`. A member's worktree is a checkout of this +repo, so it arrives with its own contract. At spawn the launcher passes `--agent ` when the +matching file exists. + +**The knob.** Nothing to turn on. The role you pass to `bridge_spawn` selects the file. Absent file ⇒ +no `--agent` flag and the member still spawns, so this degrades rather than breaks. + +**Why it exists.** The contract used to travel as an inline argv flag, +`--append-system-prompt `. herdr refuses to shell-encode a multi-line argument, so **every +claude-code member with a configured role charter failed to spawn** (CB-616) — measured as an +architect that started on `sol` and died on `opus`. opencode escaped only because it already wrote +its charter to a file. Files fix that for both backends and make the contract reviewable in git. + +**The gotchas.** + +- **Both directories, every time.** Neither tool reads the other's: a `.claude/agents/` file is + invisible to opencode. Measured — a probe agent in `.claude/agents/` never appeared in + `opencode agent list`. The two copies of a role must carry identical bodies or the backends work + from different contracts. +- **Never put `model:` in an agent file.** Both CLIs honour it *only* when no launch flag is passed, + and bridged always passes one (`--model` for claude-code, `-m` for opencode). Measured both ways: + an agent pinned to `openai/gpt-5.6-terra` run with `-m opencode/x-preview-f-free` reported + `> pin · x-preview-f-free`. A `model:` here is silently overridden on every spawn. The model stays + in `bridged.yaml`, which also keeps role and backend as the separate axes the role pools need. +- **The reply charter is still injected, not filed.** "End every turn with `bridge_reply`" must reach + a member that has no repo checkout, so it keeps its inline delivery. Verified that `--agent` and + `--append-system-prompt` compose: both the agent body and the appended rule are in force. + ### Found while cataloguing, not by looking for bugs Two of these are filed as their own tickets. They are recorded here because both are the same shape: diff --git a/7-Use-Cases.md b/7-Use-Cases.md index 69e1745..1b4cb73 100644 --- a/7-Use-Cases.md +++ b/7-Use-Cases.md @@ -461,12 +461,14 @@ you. |---|---|---| | the launcher's reply charter | the one rule that must survive with no repo: *end every turn with `bridge_reply`* | every spawned member, at launch, every peer kind — never a lead | | **this section** | protocol + orchestration policy | primary **and** every member that reads the repo — tracked in git, so worktrees inherit it | +| role agent definition files | role contract and per-job procedure | a member whose launcher binds its role to the matching file in its worktree | | role playbook skills | per-job procedure (commit/PR recipe, finding format) | a member told to load one | | the bridge's own docs | design detail, flows, error model | on demand | -A rule belongs in **exactly one** layer — the outermost one that must obey it. Peers that don't read -`CLAUDE.md` (non-Claude adapters) get the charter only, so any rule *they* must obey belongs in the -charter, not here. +A rule belongs in **exactly one** layer — the outermost one that must obey it. A member without a +repo checkout still gets the launcher's reply charter, which is why that one rule stays there. +Peers that don't read `CLAUDE.md` (non-Claude adapters) get the charter only, so any rule *they* +must obey belongs in the charter, not here. ``` Two rules keep this portable, and both were learned by getting them wrong first: