Epic: #64 (AffinityEngine)
Depends on: #66 (InteractionGraph), #67 (MigrationState), #68 (AffinityConfig), #69 (ClusterScorer)
What
Implement the main AffinityEngine struct in crates/arcane-affinity/src/lib.rs:
Seven-phase algorithm
- Update interaction graph (decay + inject party/guild/proximity signals)
- Tick migration cooldowns
- Compute cluster centroids and membership from view
- Score each entity, determine reassignments (threshold + cooldown check)
- Spatial fallback for new entities
- Cleanup removed entities
- Convert per-entity assignments to merge/split
ClusterDecisions
Phase 7 translation heuristics
- Merge: ≥
merge_entity_threshold entities in A want to move to B → emit Merge(A, B)
- Split: cluster has two non-interacting subgroups (connected components in interaction graph restricted to cluster) → emit
Split(cluster, group_a, group_b)
Acceptance criteria
- Full
evaluate() implementation with all 7 phases
validate_view() warns on empty players
- Integration test with synthetic WorldStateView returning valid decisions
Spec
See arcane-engine repo: in_08_affinity_engine.md
Epic: #64 (AffinityEngine)
Depends on: #66 (InteractionGraph), #67 (MigrationState), #68 (AffinityConfig), #69 (ClusterScorer)
What
Implement the main
AffinityEnginestruct incrates/arcane-affinity/src/lib.rs:IClusteringModeltrait (evaluate(),get_model_info(),validate_view())compute_entity_assignments()(trait extension from Extend IClusteringModel trait with compute_entity_assignments() #71)MutexforInteractionGraph,MigrationState,current_assignmentsSeven-phase algorithm
ClusterDecisionsPhase 7 translation heuristics
merge_entity_thresholdentities in A want to move to B → emitMerge(A, B)Split(cluster, group_a, group_b)Acceptance criteria
evaluate()implementation with all 7 phasesvalidate_view()warns on empty playersSpec
See
arcane-enginerepo:in_08_affinity_engine.md