Rules of thumb, all enforced or exercised in this repo’s config:
- Bind when the artifact is the unit of work. This repo’s PR reviewer binds every PR lifecycle trigger to
github.pull_requestwithonUnmatched: spawn, so one reviewer session owns a PR across heads and re-reviews fold forward on push instead of spawning a fresh review per push. - Only some events can
bind. An event routes to a binding only if its payload carries a routing target (a PR, issue, or thread).github.pushandgithub.workflow_run.completedcarry none — abindroute can never match them; usespawnordeliver. - Suppress your own echoes. Chat deliver triggers routed by
attributedSessionsmust filter"$.auto.authored": false— validation rejects the trigger otherwise, because an agent that hears its own messages loops. - Make spawn/deliver pairs mutually exclusive. When the same event should spawn on first contact and deliver on follow-ups, split it on
$.auto.attributions: { exists: false }(spawn) versus{ exists: true }(deliver). Validation enforces this partition; the chat assistant example is the canonical demonstration. - Choose
onUnmatcheddeliberately.drop(the default) is right for optional signals like reactions;warnleaves an audit trail;errorrecords the unmatched event as a failure;spawnguarantees the event is handled even when no session matches. Reservespawnfor events that must never be lost.