Epic: #64 (AffinityEngine)
Depends on: #66, #67, #68, #69, #70 (all module implementations)
What
Comprehensive unit tests for each module in arcane-affinity:
interaction_graph.rs
record_interaction creates entry / adds to existing (not replaces)
EntityPair canonical ordering — (A,B) and (B,A) produce same key
tick() applies decay correctly
tick() GCs entries below threshold at correct interval
neighbors() returns all partners with correct weights
remove_entity() cleans up all pairs involving that entity
pair_count() accurate after insertions, removals, GC
hysteresis.rs
- New
MigrationState has no cooldowns
record_migration sets cooldown correctly
is_on_cooldown returns true during period
tick() decrements, entries removed at 0
- Cooldown expires after exactly
cooldown_ticks ticks
remove_entity clears cooldown
scorer.rs
- Entity with all interaction partners in cluster A scores highest for A
- Entity with no interactions falls back to spatial proximity
- Capacity penalty reduces score for full clusters
- Capacity penalty doesn't zero the score (allows overflow)
spatial_weight=0.0 → pure interaction scoring
spatial_weight=1.0 → pure spatial scoring
lib.rs (AffinityEngine)
evaluate() returns valid assignments for all entities
validate_view() warns on empty players
get_model_info() returns correct metadata
Acceptance criteria
cargo test -p arcane-affinity passes with all tests
- No tests depend on external state (Redis, SpacetimeDB, etc.)
Epic: #64 (AffinityEngine)
Depends on: #66, #67, #68, #69, #70 (all module implementations)
What
Comprehensive unit tests for each module in
arcane-affinity:interaction_graph.rs
record_interactioncreates entry / adds to existing (not replaces)EntityPaircanonical ordering — (A,B) and (B,A) produce same keytick()applies decay correctlytick()GCs entries below threshold at correct intervalneighbors()returns all partners with correct weightsremove_entity()cleans up all pairs involving that entitypair_count()accurate after insertions, removals, GChysteresis.rs
MigrationStatehas no cooldownsrecord_migrationsets cooldown correctlyis_on_cooldownreturns true during periodtick()decrements, entries removed at 0cooldown_ticksticksremove_entityclears cooldownscorer.rs
spatial_weight=0.0→ pure interaction scoringspatial_weight=1.0→ pure spatial scoringlib.rs (AffinityEngine)
evaluate()returns valid assignments for all entitiesvalidate_view()warns on empty playersget_model_info()returns correct metadataAcceptance criteria
cargo test -p arcane-affinitypasses with all tests