--- id: CUST-WP-0040 type: workplan domain: custodian repo: the-custodian status: completed state_hub_workstream_id: d8ac100b-a844-46a5-9684-415df0d32539 tasks: - id: T01 title: Connect state hub event publisher to NATS JetStream state_hub_task_id: c4bfa299-54dd-4ede-b5fa-9ae27dce5b2c status: done - id: T02 title: Define NATS subject schema for state hub lifecycle events state_hub_task_id: 2ae236a4-8a16-4998-92dc-83bc48378d3d status: done - id: T03 title: Implement state hub lifecycle events as NATS EventEnvelopes state_hub_task_id: ccb5a3fb-d5e5-4781-9e5d-552ad09477f5 status: done - id: T04 title: Migrate state hub maintenance crons to activity-core ActivityDefinitions (design stub) state_hub_task_id: 933b2a80-cbd6-436f-b092-c39dc6f1c9c4 status: done - id: T05 title: Document state hub → activity-core delegation protocol state_hub_task_id: b261d4b8-4039-4610-aaad-eb45bf3a51de status: done - id: T06 title: Update SCOPE.md to reflect activity-core delegation state_hub_task_id: 356682e6-e608-4f58-b418-cdef2b9435f2 status: done created: "2026-05-14" --- # CUST-WP-0040: State Hub NATS / Activity-Core Integration ## Purpose The Custodian State Hub currently runs bespoke maintenance cron jobs and ad-hoc event handling internally. With activity-core established as the org-wide Event Bridge, the state hub should delegate maintenance automation to activity-core by publishing lifecycle events on NATS JetStream — rather than implementing task creation itself. This workplan makes the state hub an event *publisher* and removes it from the task-generation business. The result: maintenance automations are governed by ActivityDefinitions in activity-core (auditable, rule-based, testable) rather than scattered cron code in the-custodian. ## Context - **activity-core** (WP-0003 in progress): event loop that receives NATS events and evaluates rules/instructions to create tasks in issue-core. - **State hub**: tracks domain state, workstreams, decisions, and progress events. It knows when things happen (repo registered, workstream completed, stale task). - **The gap**: the state hub knows about org events but has no way to publish them to NATS so that activity-core can react. This workplan closes that gap. See: `docs/adr/adr-001-event-bridge-architecture.md` in activity-core for the delegation protocol design. ## Scope **In scope:** - NATS JetStream publisher client in the state hub - EventEnvelope schema for state hub lifecycle events - NATS subject naming convention for state hub events - Design stub for migrating existing maintenance crons to ActivityDefinitions - Protocol documentation **Out of scope:** - activity-core rule/instruction implementation (lives in activity-core WP-0003) - Removing existing state hub crons before activity-core is ready (sequencing risk) - project-core (future) ## Tasks ### T01 — Connect state hub event publisher to NATS JetStream Add a NATS JetStream publisher client to the state hub. It should: - Connect to the NATS server on startup (use existing NATS config pattern) - Expose a `publish_event(envelope: EventEnvelope)` function - Be disabled/no-op when `NATS_URL` is not set (for environments without NATS) - Log publish success/failure with event ID **Key file**: `state_hub/events/nats_publisher.py` (new) ### T02 — Define NATS subject schema for state hub lifecycle events Document and agree on the NATS subject naming convention for state hub events. Proposed pattern: `org.statehub.{noun}.{verb}` — e.g.: - `org.statehub.repo.registered` - `org.statehub.workstream.completed` - `org.statehub.task.stale` - `org.statehub.domain.goal.activated` Write the subject schema as a section in `docs/nats-event-subjects.md`. Cross-reference with activity-core's event-types registry. ### T03 — Implement state hub lifecycle events as NATS EventEnvelopes Wire the NATS publisher into state hub write operations. Candidate events: - `org.statehub.repo.registered` — when a repo is registered in the hub - `org.statehub.workstream.completed` — when a workstream status → completed - `org.statehub.task.stale` — periodic check, tasks not updated in 14+ days Each event must conform to the EventEnvelope schema defined in activity-core's event type registry. Write a stub event type definition file in activity-core at `event-types/org.statehub.repo.registered.md` (or coordinate with the activity-core agent to do so). ### T04 — Migrate state hub maintenance crons to activity-core ActivityDefinitions (design stub) **Design stub only — not yet implemented.** List the existing maintenance cron jobs in the state hub codebase. For each: - Identify the equivalent ActivityDefinition trigger (cron expression, event type) - Draft the rule/instruction that would replace the cron logic - Note any context sources required (state hub API, repo-scoping) - Flag blockers (e.g., activity-core WP-0003 phase not yet complete) Output: a markdown table in this workplan and/or in `docs/cron-migration.md`. ### T05 — Document state hub → activity-core delegation protocol Write `docs/activity-core-delegation.md` explaining: - Why state hub delegates maintenance automation to activity-core - Which lifecycle events the state hub publishes and why - How activity-core ActivityDefinitions react (cross-reference WP-0003) - What remains in the state hub vs. what moves to ActivityDefinitions - Operational checklist: what to verify when a maintenance cron is being migrated ### T06 — Update SCOPE.md to reflect activity-core delegation Update the state hub's SCOPE.md (or write one if missing): - Add activity-core as a downstream consumer of state hub lifecycle events - Clarify that maintenance task creation moves to activity-core - Note that the state hub remains the authoritative *read model* (not a task factory) ## Build Order ``` T01 (NATS publisher) → T03 (wire events) T02 (subject schema) → T03 T03 → T04 (migration stub, requires events to exist) T04 → T05 (docs, requires migration list) T06 (independent — SCOPE.md update) ``` ## Completion Criteria 1. State hub publishes at least one lifecycle event type to NATS on relevant writes 2. Subject naming convention documented and agreed with activity-core team 3. Migration stub completed — all existing crons listed with ActivityDefinition drafts 4. Delegation protocol documented 5. SCOPE.md updated ## Notes - **Sequencing**: complete T01–T03 before activity-core WP-0003 is done, so the first ActivityDefinitions that consume state hub events can be tested end-to-end. - **No removal yet**: do not remove existing state hub crons until activity-core ActivityDefinitions are validated in staging. Run both in parallel initially. - The state hub must never write directly to activity-core's database — only via NATS. ## Change History - v0.1 (2026-05-14): Stub created by activity-core agent during WP-0003 planning. Local agent to flesh out and implement. - v0.2 (2026-05-17): All tasks complete. NATS publisher landed at `state-hub/api/events/`, lifecycle events wired in repos/workstreams/ decisions/domain_goals routers + cleanup_stale_tasks.py. Subject schema, cron-migration design stub, delegation protocol docs, and SCOPE.md updates committed.