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
+46 -7
View File
@@ -175,12 +175,36 @@ orphan either of them. The reviewer only hears about new commits and the PR
closing — replying to threads is the author's job, so comments aren't routed to
it.
### The agent roster
`agents` is one roster of harness+model combos for everything in this repo that
spawns a session — the reviewer rotation and blitz's worker sessions — so a
model added once is available to both. Each entry names a harness and whatever
flags pin its model and effort; consumers pass `args` through `--extra-args`
and know nothing about what they mean. Two fields say who may pick an entry:
- `roles``review` for the reviewer rotation, `blitz` for milestone workers.
Absent means both, which is the useful default for a general-purpose combo.
- `tiers` — blitz's difficulty routing (`execution`, `design`, `subtle`), and
meaningless to the daemon. An entry with no `tiers` is never auto-routed by
blitz, though the operator can still name it in an invocation.
Markdown skills query it through `scripts/roster.sh` (linked to
`~/.claude/scripts/roster.sh`) rather than parsing the config themselves:
```sh
~/.claude/scripts/roster.sh --role blitz --tier execution --format aoe
# --tool claude --extra-args "--model sonnet"
```
The key was `reviewers` when only the daemon read it; that name is still
accepted. A machine-wide `blitz` block (`maxSessions`, `notifyService`) lives
here too, overridden per repo by `.claude/tracker.json`.
### Reviewer rotation
`selfReview` exists so a PR is never reviewed by the agent that wrote it. The
`reviewers` list is the rotation pool, each entry naming a harness and whatever
flags pin its model and effort; the daemon passes `args` through `--extra-args`
and knows nothing about what they mean. Effort is per-harness — `--effort` on
rotation pool is every `agents` entry whose `roles` include `review`. Effort is per-harness — `--effort` on
claude, a `:high` suffix on pi's model pattern, and nothing usable on opencode,
whose `--variant` exists only under `opencode run`.
@@ -219,7 +243,7 @@ gated — no prompt, no approval, and a boundary the session cannot argue with:
| no prompts | `defaultMode: dontAsk` — a denial goes to the agent, not to you | `--ask-for-approval never` |
| writes | sandbox `allowWrite`: the worktree and `<main>/.git/worktrees` | `--sandbox workspace-write --add-dir <main>/.git/worktrees` |
| network | sandbox allowlist: the configured forge API hosts only | full egress (codex has no per-domain list) |
| reads | everything except `~/.ssh`, `~/.aws`, `~/.gnupg`, `~/.env`, `~/.env.claude`, `~/.config/reviewer` and the two agent credential files | same list, as sandbox `denyRead` |
| reads | everything except `~/.ssh`, `~/.aws`, `~/.gnupg`, `~/.env`, `~/.env.claude`, `~/.config/agent-skills`, `~/.config/reviewer` and the two agent credential files | same list, as sandbox `denyRead` |
| project config | no `--trust-hooks` | `trust_level = "untrusted"`, which also answers codex's trust prompt without granting it |
The grants are generated per repo in `sandboxArgs` — a settings file under
@@ -246,8 +270,10 @@ default list — but it carries no settings of its own.
### Setup
Config from `bin/reviewer-config.example.json` to `~/.config/reviewer/config.json`.
Secrets in `~/.config/reviewer/env`, never here:
Config from `bin/agents-config.example.json` to `~/.config/agent-skills/config.json`
(`~/.config/reviewer/config.json` still works — the daemon reads whichever
exists, so an old box migrates with a `mv`). Secrets in `env` next to it, never
here:
```sh
REVIEWER_GITEA_TOKEN=... # read-only
@@ -341,7 +367,7 @@ Vendored skills are excluded from all of it.
| `land` | drive a PR **you authored** to green + ready-to-merge; user clicks merge |
| `review-pr` | review a PR **someone else authored**; findings only, never pushes, never runs the branch's code |
| `pr-common` | shared PR-loop mechanics: hint format, seen file, state file, forge resolution (dependency of land/review-pr) |
| `blitz` | drive a whole milestone to done |
| `blitz` | drive a whole milestone to done; keeps model feedback in `~/.local/state/agent-skills/models.md` |
| `nightshift` | hours-long unattended build; architect delegating to subagents, backs off before the 5h limit |
| `tracker-common` | shared GitHub/Gitea/Linear tracker config, worktree conventions, and local verification budget (dependency of work/yolo/blitz/nightshift) |
| `week-review` | review the past week's sessions for recurring friction; reads open issues here as carry-over |
@@ -349,6 +375,19 @@ Vendored skills are excluded from all of it.
| `intercomms` | find and talk to other agent sessions on this machine via `aoe`; discovery is a query, nothing is tracked |
| `improve-codebase-architecture` | misc |
### Model notes
Blitz reads `~/.local/state/agent-skills/models.md` before routing issues to
worker sessions and rewrites it before the run ends. It is a compiled summary —
difficulty tiers, task fit, cost effectiveness, caveats — capped at ~60 lines
and edited in place, never appended to, so the next run reads a current belief
instead of a log. `skills/blitz/AOE-WORKERS.md` holds the rules.
Machine-local on purpose: the skill dirs are read-only nix store paths here, and
the notes describe runs on this box. The roster it draws models from is the PR
shared `agents` roster in `~/.config/agent-skills/config.json`; changes to the
roster go through `week-review`, not blitz.
## Vendored skills
`humanizer` and `impeccable` are third-party and copied in, not written here.