Spoke → hub callback¶
Spoke repos report key events back to the AgentArmy hub so cross-repo activity is visible in one place — the reverse of the hub→spoke epic handoff. It automates the "close the loop with the hub" step from the spoke work-intake model.
How it works¶
spoke: PR merged / issue closed / PR-issue comment (non-bot)
└─ .github/workflows/notify-hub.yml (synced to every spoke)
└─ repository_dispatch event_type=spoke-update --> nickpclarke/AgentArmy
└─ .github/workflows/spoke-callback.yml (hub receiver)
└─ appends to the hub "Spoke Activity Log" issue + the run summary
- Spoke side (
notify-hub.yml, synced viaspoke_sync.config.json): fires aspoke-updaterepository_dispatchto the hub on a PR merged into the default branch (main), a closed issue, or a comment on a PR/issue, with{repo, kind, number, title, url, author, snippet}. Guards keep it sane: it reports only default-branch merges (a merge into a release/hotfix/feature branch isn't "shipped"), it skips bot comments (so Gemini's quota notices don't flood the hub), and it skips the hub repo itself (which would otherwise loop on the Spoke Activity Log). NeedsPROJECT_TOKENin the spoke's secrets; if absent the step skips (never fails the spoke's CI). - Hub side (
spoke-callback.yml): listens forrepository_dispatch: [spoke-update]and records the event on aSpoke Activity Logissue (created on first event) + the run summary, using the built-inGITHUB_TOKEN.
Untrusted client_payload is read through env: vars and used only as quoted shell variables
— never interpolated into the run: script (GitHub Actions injection-safety). The receiver also
neutralizes @mentions (inserts a zero-width space after each @) and flattens newlines
in the spoke-supplied fields before posting them, so a spoke PR/issue/comment can't spam-mention
hub users or teams via the Spoke Activity Log.
"Both" mechanisms¶
repository_dispatch is the default (decoupled, one shared token, easy to add event types).
A spoke can also write to the hub directly when it already knows the target — e.g. comment
on the linked hub epic via gh issue comment with PROJECT_TOKEN. Use direct writes for the
specific "this epic is done" case; use repository_dispatch for general activity.
Follow-ups¶
- v2 routing: carry a
hub_ref(the originating hub epic) in the payload so the receiver comments on that epic instead of the central log. - Board nudge: extend the receiver to move the linked hub Project item to Done.