ADR-0003: Content surfacing into protoContent
Context
protoContent is the Payload-CMS marketing hub + content pipeline (idea → outline → draft → cuts → schedule → publish → engage → capture). Brand voice lives there as data. We want fleet activity — shipped features, releases, milestones — to feed the content pipeline, without protoWorkstacean ever generating content (voice and authoring are protoContent's domain).
Decision
protoWorkstacean surfaces content ideas from fleet lifecycle events; it does not author content. It feeds protoContent's idea stage and stops there.
release.publishedis the first tap and a first-class fleet primitive. Sourced from GitHub's nativereleasewebhook (shipped in protoWorkstacean#644), so it fires regardless of how the release was cut (auto-release.yml, release-tools, or by hand). It is general-purpose — content is one subscriber among changelog aggregation, announce, and deploy verification.- A content-surfacing plugin subscribes to content-worthy topics, normalizes a
ContentIdea({ source, headline, whatHappened, links[], suggestedSurface, occurredAt }), and POSTs it to protoContent's intake endpoint — HTTP, fire-and-forget, the same boundary discipline as ADR-0002.
Which events to tap, tiered by signal strength:
- Tier 1 — "we shipped something":
release.published,feature.completed. Start here. - Tier 2 — narrative: narrative
ceremony.*.completed(weekly retro / standup digest),autonomous.outcome.*milestones (first autonomous merge, Nth feature). - Tier 3 — engage/capture: community signal (Discord threads, GitHub discussions). Gate hard.
- Do not tap:
security.incident.reported(sensitive),feature.failed/ red CI (internal), rawmessage.inbound.#(firehose).
Ideas are human-gated into the pipeline initially — brand-voice stakes outweigh full automation until the loop is proven.
Consequences
- Clean separation: protoWorkstacean surfaces, protoContent authors. No brand-voice logic leaks into the switchboard.
- Net-new work: a content intake endpoint on protoContent, and the content-surfacing plugin (gated on that endpoint).
- Operational: the GitHub App must subscribe to
releaseevents forrelease.publishedto fire. - The same
release.publishedprimitive is reusable well beyond content — treat it as a lifecycle event, not a content-specific hook.