feat(hooks): PreToolUse gate enforcing swarm delegation for release ops#201
feat(hooks): PreToolUse gate enforcing swarm delegation for release ops#201markmhendrickson wants to merge 1 commit into
Conversation
The 'delegate through the swarm' rule (docs/agents/ateles.md) was prose in a prompt, so a session agent could hand-roll a swarm-owned operation just by not remembering it — which happened: a Neotoma release was cut by hand (manual PR/merge/tag/GitHub Release) instead of routing through phoenicurus-release (prepare.py -> operator approval -> publish.py), leaving publish.py unable to adopt it (its preflight refuses when the tag already exists). Root cause: no action-time enforcement. The only proactive-routing hook (agent_auto_invocation.py) is suggest-only, prompt-time, and wasn't even wired into settings.json. So nothing intercepts the actual irreversible action. This adds a fail-open PreToolUse hook that DENIES the specific swarm-owned Bash commands (npm publish, gh release create, git tag vX.Y.Z creation) with a redirect to the owning pipeline. Deterministic (regex on the command, not topic scoring, so it fires regardless of how the session got there), escapable via a '# SWARM_OVERRIDE' token for reviewed one-offs, stdlib-only. Selftest covers gated/allowed/override/read-only-vs-creation cases. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Loxia Review 🪶Verdict: APPROVE SummaryA focused, well-constructed PreToolUse gate that converts the prose "delegate through the swarm" rule into an action-time deny for the three deterministic release surfaces ( Findings
Notes (non-blocking, worth a follow-up)
Loxia automated review · commit cca19ab |
|
🤖 Lanius — Ateles swarm, PR gate inheritance Triage & Gate-Status BoardParent issue: none found.
Without a parent issue, no Gate status (pre-impl)
Resolution paths
Until one of these resolves, 📎 Neotoma: PR entity |
Why
The "delegate through the swarm — you are the orchestrator, not the workhorse" rule (docs/agents/ateles.md) was prose in a prompt, so a session agent could hand-roll a swarm-owned operation just by not remembering it. That happened: a Neotoma release (v0.18.8) was cut by hand (manual PR/merge/tag/GitHub Release) instead of routing through
phoenicurus-release(prepare.py → operator approval → publish.py), leaving publish.py unable to adopt it (its preflight refuses when the tag already exists).Root cause: no action-time enforcement. The only proactive-routing hook (
agent_auto_invocation.py) is suggest-only, prompt-time, and wasn't even wired into settings.json — so nothing intercepts the actual irreversible action.What
A fail-open PreToolUse hook that DENIES the specific swarm-owned Bash commands with a redirect to the owning pipeline:
npm publish→ route through phoenicurus-release publish.pygh release create→ samegit tag vX.Y.Z(creation) → publish.py owns taggingProperties:
# SWARM_OVERRIDEtoken to bypass.Selftest (
--selftest) covers gated / allowed / override / read-only-vs-creation (e.g.git tag --listis not blocked;git tag -a v…is).Follow-up
This gates the release surface, which is where it bit us. Same pattern extends to other swarm-owned surfaces (e.g. product-code
gh pr create→ route through the issue→Cicada pipeline) as separate entries once we agree the boundary.🤖 Generated with Claude Code