Skip to content

Epic: Interaction-weighted affinity clustering (AffinityEngine) #64

@rebelmachina

Description

@rebelmachina

Summary

Implement AffinityEngine — an interaction-weighted, hysteresis-stabilized IClusteringModel implementation that groups entities by predicted interaction probability rather than pure spatial proximity.

This is the hand-crafted clustering baseline described in the primer as the step between the current spatial-only RulesEngine and the future ML/RL model. It solves three known failure modes of RulesEngine:

  1. Boundary thrashing — entities on a spatial boundary oscillate between clusters every tick
  2. Interaction blindness — heavily interacting entities on opposite sides of a boundary incur cross-cluster RPCs for every interaction
  3. No temporal awareness — the model reacts to where entities are now, not where they're going

Architecture

New crate: arcane-affinity (sibling to arcane-rules), with four internal modules:

  • InteractionGraph — decaying pairwise interaction weights between entities
  • ClusterScorer — scores entity-to-cluster affinity (interaction sum + spatial tiebreaker)
  • MigrationState — per-entity cooldowns preventing oscillation
  • AffinityConfig — all tunable parameters with sensible defaults

Plus minimal integration changes in existing crates:

  • Extend IClusteringModel trait with per-entity assignment method (default impl, backward-compatible)
  • Add snapshot_entities() to SpatialIndex (expose entity data for WorldStateView)
  • Populate WorldStateView.players in ClusterManager (currently always empty)
  • Add arcane-affinity as optional dependency in arcane-infra with feature flag

Design documents

Full specs are in arcane-engine repo on branch feat/affinity-clustering-specs:

  • in_08_affinity_engine.md — main component spec
  • in_08_01_interaction_graph.md through in_08_04_affinity_config.md — module specs
  • in_08_05_trait_extension.md — trait extension spec
  • in_08_00_integration_report.md — code change analysis

Sub-issues

New crate implementation

Integration changes (existing crates)

Testing

Dependency graph

#65 (scaffold) ─┬─→ #66 (InteractionGraph) ──┐
                ├─→ #67 (MigrationState)      │
                ├─→ #68 (AffinityConfig) ─────┤
                └─────────────────────────────→ #69 (ClusterScorer)
                                                     │
    #66 + #67 + #68 + #69 ──────────────────────→ #70 (AffinityEngine core)
                                                     │
    #70 ─────────────────────────────────────────→ #74 (infra integration)
    #72 (SpatialIndex) ─────────────────────────→ #73 (populate players)
    #70 + #73 ──────────────────────────────────→ #76 (integration tests)
    #66 + #67 + #68 + #69 + #70 ───────────────→ #75 (unit tests)

    #71 (trait extension) — independent, no deps
    #72 (SpatialIndex accessor) — independent, no deps

Success criteria

AffinityEngine is better than RulesEngine if, under identical arcane-swarm workloads:

  • Cross-cluster interaction count is lower
  • Migration frequency is lower
  • Latency is equal or better
  • Throughput ceiling is equal or better

What this does NOT solve

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions