Features: the hunter member role (fleetd #568)

Dai Ha
2026-09-19 15:14:55 +07:00
parent 1d9bd1b993
commit 0595d976b6
+43
@@ -5609,3 +5609,46 @@ evidence about the producer.
null case, not a fault.
fleetd #562 (PRs #579, #584).
## `hunter` is a member role, not just a skill
The repo already shipped a `hunter` playbook skill: sweep a package, report several ranked
findings, change nothing. There was no matching **role**. A hunt was run by spawning a `dev` and
telling it not to behave like one.
**What it does.** `MemberRole.HUNTER` joins `ARCHITECT`, `DEV` and `REVIEWER`. It has the wire
token `hunter`, the config pool `fleet.hunters`, and the agent file `.claude/agents/hunter.md`.
`fleet_spawn{role: "hunter"}` now picks a contract instead of borrowing one.
**The knob.** `fleet.hunters` in `fleetd.yaml`, listing the profiles a hunter may run on — the
same shape as `fleet.developers` and `fleet.reviewers`:
```yaml
fleet:
hunters:
sonnet: {profile: sonnet}
terra: {profile: terra}
```
Optional. Leave it out and the role exists but no hunter can be placed.
**Why it exists.** A role carries prohibitions the brief should not have to repeat. `dev` is
allowed to edit, commit, push and open a pull request; a hunt must do none of those. Spawning a
`dev` for a hunt meant the only thing standing between the sweep and a surprise commit was a
sentence in the brief. Miss that sentence once and the member is inside its contract while doing
the wrong job. `hunter.md` forbids editing, committing, pushing and opening a PR, and — unlike
`reviewer.md` — explicitly **permits** running the build, because a hunter checks its findings.
**The gotcha — the role ships inert.** Merging the code does not create the pool. On a host whose
`fleetd.yaml` has no `fleet.hunters`, unknown nested keys are ignored rather than rejected, so
there is no warning at load and no error at merge: `fleet_spawn{role: "hunter"}` simply finds no
candidate profile. The sequence is merge, redeploy, add the pool, then **spawn one hunter and read
the spawn log**. Parsing the config proves nothing about placement.
**The second gotcha — `hunter` and `reviewer` are still not interchangeable.** `reviewer` caps its
answer at one finding; `hunter` reports several. Naming the wrong skill for the role hands the
member two contradictory output contracts, and the measured result is a member that writes a good
report to its terminal and ends the turn with no `fleet_reply`. The role does not fix that; the
brief still has to name the right skill.
fleetd #568 (PR #596).