docs(Service-Bus): document attribution.profile.* topics

Two new bus signals from the v0 attribution engine
(decnet.correlation.attribution_worker):

* attribution.profile.state_changed — per-(identity, primitive)
  state transition. State vocabulary frozen at five values:
  unknown / stable / drifting / conflicted / multi_actor. Phase 1
  ships the constants only; Phase 4 lights the producer.
* attribution.profile.multi_actor_suspected — cross-primitive
  correlator output. Single-primitive multi_actor is too noisy;
  fires when ≥ 2 primitives co-flag the same identity. Confidence
  capped at 0.6 (see _thresholds.MULTI_ACTOR_MAX_CONFIDENCE).

Co-commits with DECNET dev c2891d6c (feat(correlation/attribution):
substrate + idle handler).
2026-05-08 23:16:45 -04:00
parent 2b770e2c8e
commit de828ef07a

@@ -166,6 +166,8 @@ Current topic families:
| `identity.merged` | _reserved (clusterer)_ | `{winner_uuid, loser_uuid, observation_uuids: [...], confidence_after}` — two identities collapsed; subscribers re-key cached references to the winner |
| `identity.unmerged` | _reserved (clusterer)_ | `{resurrected_uuid, former_winner_uuid, observation_uuids: [...], reason}` — revocable-merge undo: contradicting evidence cleared `merged_into_uuid`; subscribers should re-split cached references back to the resurrected side |
| `identity.campaign.assigned` | Campaign clusterer | `{identity_uuid, campaign_uuid, prior_campaign_uuid?}` — cross-family signal so `identity.>` subscribers (e.g. IdentityDetail SSE) see the campaign-id change without needing to subscribe to `campaign.>` |
| `attribution.profile.state_changed` | `decnet.correlation.attribution_worker` | `{identity_uuid, primitive, old_state, new_state, current_value, confidence, observation_count, ts}` — per-(identity, primitive) state-machine transition (e.g. `stable``drifting`). Emitted only on transition; idempotent observations that don't change state produce no event. State vocabulary is fixed at five values: `unknown / stable / drifting / conflicted / multi_actor`. See `development/ATTRIBUTION-ENGINE.md`. v0 ships Phase 1 substrate only (worker logs, no transitions emitted yet); the topic constants ship now so SSE relays can subscribe ahead of Phase 4. |
| `attribution.profile.multi_actor_suspected` | `decnet.correlation.attribution_worker` | `{identity_uuid, primitives: [...], evidence_summary, confidence, ts}` — fires when ≥ 2 primitives independently flag the same identity as `multi_actor`. Single-primitive `multi_actor` is too noisy to alarm on (flapping primitive on flaky network looks like two operators); the cross-primitive correlator is the real signal. `confidence` is capped at 0.6 by convention — see `_thresholds.MULTI_ACTOR_MAX_CONFIDENCE`. |
| `campaign.formed` | Campaign clusterer | `{campaign_uuid, identity_uuids: [...], confidence, first_seen_at}` — clusterer creates a new campaign from one or more identities |
| `campaign.identity.assigned` | Campaign clusterer | `{campaign_uuid, identity_uuid}` — identity attached / re-attached to a campaign |
| `campaign.merged` | Campaign clusterer | `{winner_uuid, loser_uuid, identity_uuids: [...]}` — two campaigns collapsed; subscribers re-key cached references to the winner |