e818cfea8b
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>
64 lines
2.5 KiB
Bash
Executable File
64 lines
2.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Query the shared agent roster: which harness+model combos this box may spawn.
|
|
#
|
|
# Same config the PR daemon reads. Entries carry `roles` (who may pick it:
|
|
# "review" = PR reviewer rotation, "blitz" = milestone workers; absent = both)
|
|
# and `tiers` (blitz difficulty routing: execution | design | subtle).
|
|
#
|
|
# roster.sh # every enabled entry, one JSON per line
|
|
# roster.sh --role blitz --tier design # what blitz may spawn for design work
|
|
# roster.sh --id claude/opus@high # one entry
|
|
# roster.sh --role blitz --tier execution --format aoe
|
|
# --tool claude --extra-args "--model sonnet"
|
|
#
|
|
# Exit 3 means the config is missing, 4 means nothing matched. Both are
|
|
# survivable: fall back to the skill's own default table and say so.
|
|
set -euo pipefail
|
|
|
|
ROLE="" TIER="" ID="" FORMAT=json
|
|
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--role) ROLE="$2"; shift 2 ;;
|
|
--tier) TIER="$2"; shift 2 ;;
|
|
--id) ID="$2"; shift 2 ;;
|
|
--format) FORMAT="$2"; shift 2 ;;
|
|
--config) CONFIG="$2"; shift 2 ;;
|
|
-h|--help) sed -n '2,18p' "$0" | sed 's/^# \?//'; exit 0 ;;
|
|
*) echo "roster.sh: unknown argument $1" >&2; exit 2 ;;
|
|
esac
|
|
done
|
|
|
|
# Same resolution order as the daemon: the shared path wins, the reviewer-only
|
|
# path still works so a box migrates with a mv.
|
|
if [ -z "${CONFIG:-}" ]; then
|
|
for c in "${AGENTS_CONFIG:-}" "${REVIEWER_CONFIG:-}" \
|
|
"$HOME/.config/agent-skills/config.json" "$HOME/.config/reviewer/config.json"; do
|
|
[ -n "$c" ] && [ -f "$c" ] && { CONFIG="$c"; break; }
|
|
done
|
|
fi
|
|
[ -n "${CONFIG:-}" ] || { echo "roster.sh: no agent config found" >&2; exit 3; }
|
|
|
|
# `agents` is the current key; `reviewers` is what it was called when only the
|
|
# PR daemon read it.
|
|
MATCHES=$(jq -c \
|
|
--arg role "$ROLE" --arg tier "$TIER" --arg id "$ID" '
|
|
((.agents // .reviewers) // [])
|
|
| map(select(.enabled != false))
|
|
| map(select($id == "" or .id == $id))
|
|
| map(select($role == "" or ((.roles // ["review","blitz"]) | index($role))))
|
|
| map(select($tier == "" or ((.tiers // []) | index($tier))))
|
|
| .[]' "$CONFIG")
|
|
|
|
[ -n "$MATCHES" ] || exit 4
|
|
|
|
case "$FORMAT" in
|
|
json) printf '%s\n' "$MATCHES" ;;
|
|
id) printf '%s\n' "$MATCHES" | jq -r '.id' ;;
|
|
# Ready to paste into an `aoe add` line. args are joined into the single
|
|
# string --extra-args wants, quoted so a flag with spaces survives.
|
|
aoe) printf '%s\n' "$MATCHES" | jq -r '
|
|
"--tool \(.tool) --extra-args \"\((.args // []) | join(" "))\""' ;;
|
|
*) echo "roster.sh: unknown format $FORMAT" >&2; exit 2 ;;
|
|
esac
|