feat(config): one agent roster for daemon and blitz
ci / lint (push) Successful in 1m12s
ci / nix (push) Successful in 18s

The reviewer pool was the only place naming harness+model combos, and
blitz kept its own table inline. `reviewers` becomes `agents`, gains
`roles` and `tiers`, and blitz routes from it via scripts/roster.sh.

Config path moves to ~/.config/agent-skills/; the reviewer path stays
readable so a box migrates with a mv.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Miguel Palhas
2026-08-25 12:37:04 +01:00
parent d6265b0fbe
commit e818cfea8b
11 changed files with 398 additions and 104 deletions
+71 -17
View File
@@ -11,20 +11,46 @@ babysitting and cleanup.
## Model routing
**Assess each issue at spawn time.** You have just read its body to write the
prompt — use that read to pick the model. The question is not "how big is
this" but **how much judgment does the session still have to exercise**:
Two inputs decide who runs an issue: the **roster** (what this box may spawn)
and the **notes** (what previous blitzes learned about them).
- Body settles the approach (root cause named, fix shape decided, numbers
suggested, files pointed at) — the thinking happened at filing time; the
session executes. **Sonnet** (`--tool claude --extra-args "--model
claude-sonnet-5"`), regardless of size: a large mechanical CRUD issue is
still execution.
- Body states the goal but the session must design the interface, choose the
data model, or amend the design doc — **Opus** (`--model claude-opus-5`).
- The design doc itself is thin or contradictory where this issue lives,
correctness is subtle, or the change is cross-cutting with unclear blast
radius — **Fable** (`--model claude-fable-5`).
### The roster
`~/.config/agent-skills/config.json` — the same file the PR daemon reads, so a
model added once is available to both. Query it rather than parsing it:
```sh
~/.claude/scripts/roster.sh --role blitz --tier execution --format aoe
# --tool claude --extra-args "--model sonnet"
```
Entries carry `roles` (`blitz` entries are yours; `review`-only ones are not)
and `tiers`. Exit 3 means no config on this box and exit 4 means the tier is
empty — in both cases fall back to the defaults below and say so in the run
summary, since an empty tier is usually a config gap worth fixing.
### Picking a tier
**Read `~/.local/state/agent-skills/models.md` first** — it carries what
previous blitzes learned (see "Model notes" below). A note that contradicts
the tier definitions here wins, because it was written against real runs.
**Assess each issue at spawn time.** You have just read its body to write the
prompt — use that read. The question is not "how big is this" but **how much
judgment does the session still have to exercise**:
- **`execution`** — body settles the approach (root cause named, fix shape
decided, numbers suggested, files pointed at); the thinking happened at
filing time. Regardless of size: a large mechanical CRUD issue is still
execution.
- **`design`** — body states the goal, but the session must design the
interface, choose the data model, or amend the design doc.
- **`subtle`** — the design doc is thin or contradictory where this issue
lives, correctness is subtle, or the change is cross-cutting with unclear
blast radius.
Defaults if the roster is unreachable: `claude --model sonnet`, `--model opus`,
`--model fable` for the three tiers in that order.
A `difficulty/` label is one input — a filing-time guess that cannot see how
much the body scaffolds. Trust your read of the body over it; the label is a
@@ -33,10 +59,38 @@ on failure is cheap, and a failed cheap run teaches something a successful
expensive run does not.
The operator overrides any of this by just saying so in the invocation ("run
these on codex", "use ox alpha for the easy ones") — no config file. When
routing across peer models, alternate rather than draining one first — a bad
run should be visible early. Escalate *sideways* (a peer model) before
escalating up, and never de-escalate mid-issue.
these on codex", "use ox alpha for the easy ones") — no config edit needed.
When a tier holds several entries, alternate rather than draining one first —
a bad run should be visible early. Escalate *sideways* (a peer in the same
tier) before escalating up, and never de-escalate mid-issue.
## Model notes: `~/.local/state/agent-skills/models.md`
The shared memory across blitzes. Read it at spawn time, **update it before the
run ends** — including a run that ends blocked, since a model failing is the
evidence that's hardest to come by.
It is a compiled summary, not a log. Four sections, fixed: difficulty tiers,
task fit, cost effectiveness, caveats. Rules:
- **Under ~60 lines, always.** If an edit pushes past that, something in there
has stopped earning its line — cut it in the same edit.
- **Rewrite in place.** Merge new evidence into the claim that already exists;
never append a dated entry or a per-run section. The next blitz should read
the current belief, not reconstruct it from history.
- **Record what would change a routing decision.** Something that repeated
across sessions, or that was decisive once (a model that couldn't finish an
issue the tier below finished). Mark a single-run claim `(1 run)`.
- Caveats are for annoyances that don't veto a model — "the free 0x endpoint
times out often, retry and it lands" belongs there; it is not a reason to
route around it.
- Contradicted by a newer run? Replace the line, don't stack a qualifier on it.
- If the file is missing, create it with those four sections and note that the
tiers are seeded from this doc rather than measured.
Bounce anything with wider reach than blitz — an entry that should leave the
roster, change tiers, or drop a role — to `week-review`, which owns config
changes. These notes stay advisory; the roster is the config.
## Spawning