Spoke Artifact Pipeline¶
How project-management artifacts that spoke agents produce as pull requests — spikes, research notes, and ADRs — flow automatically into the hub Project board and the hub docs/Pages, without a human shuttling them across repos.
This complements the generic Spoke → Hub Callback (an activity log of every merge/close/comment). The artifact pipeline is path-triggered and fires early, so a draft spike shows up on the board the moment it opens.
What triggers it¶
A spoke PR that touches any of these paths is an "artifact" PR:
| Path | Board Type |
|---|---|
spikes/** |
Spike |
docs/research/** |
Spike (research) |
docs/decisions/** |
Decision |
Detection is by changed path — no labels or title prefixes required. (If a PR touches both, precedence is decision → spike → research.)
The flow¶
spoke PR opened/ready (incl. draft)
└─ notify-hub-artifacts.yml (synced into every spoke)
detects artifact paths → repository_dispatch `spoke-artifact` → hub
└─ spoke-artifact.yml (hub receiver)
• adds the spoke PR to Project #1 as a card
• sets Type (Spike/Decision) + Status = In progress
spoke PR merged
└─ same dispatch with state=merged
└─ spoke-artifact.yml
• sets Status = Done
• clones the spoke at the merge commit, copies the artifact files
into docs/spokes/<repo>/… , regenerates the rollup index,
commits to main → Pages republishes
The board is owner-level (users/nickpclarke/projects/1), so it can hold PRs from any
of your repos directly — the card is the spoke PR, not a mirror issue. The harvested copy
exists because spokes are private: a Pages reader can't follow a link into a private repo,
so the content is copied in. See the result at Spoke Artifacts.
Setup (per spoke)¶
The spoke side is inert until the spoke has a PROJECT_TOKEN secret (classic PAT with
repo + project scope on the hub) — the same token the activity-log callback uses. Without
it the step skips and never fails spoke CI. notify-hub-artifacts.yml is delivered by the
hub→spoke helper sync; the hub receiver (spoke-artifact.yml) lives only in the hub.
Files¶
| File | Where | Role |
|---|---|---|
.github/workflows/notify-hub-artifacts.yml |
hub → synced to spokes | detect + dispatch |
.github/workflows/spoke-artifact.yml |
hub only | board track + docs harvest |
scripts/gen_spoke_index.py |
hub | regenerate docs/spokes/index.md |
docs/spokes/<repo>/… |
hub | harvested artifact content (published) |
Notes & limits¶
- Harvest commits to
mainwithPROJECT_TOKEN. If branch protection rejects a direct push, switch the final step to open a PR instead. - Provenance lives in
docs/spokes/<repo>/.harvest-<n>.json(a dotfile — MkDocs ignores it, so it never ships to Pages but the index generator can read it). - Non-markdown artifacts (
.py,.ttl,.json) are copied as static assets — linkable and downloadable from the index, but only.mdrenders as a page.