use std::cmp::Ordering;
use std::collections::BTreeMap;
use crate::adapter::net::behavior::capability::{CapabilityFilter, CapabilitySet};
use crate::adapter::net::behavior::fold::{capability_bridge, CapabilityFold, Fold};
use crate::adapter::net::behavior::predicate::Predicate;
use crate::adapter::net::behavior::required_capability::RequiredCapability;
use crate::adapter::net::behavior::tag::{Tag, TagKey, TaxonomyAxis};
use crate::adapter::net::channel::ChannelName;
pub type NodeId = u64;
#[derive(Debug)]
pub enum Artifact<'a> {
Chain {
origin_hash: [u8; 32],
capabilities: &'a CapabilitySet,
},
Replica {
channel: &'a ChannelName,
capabilities: &'a CapabilitySet,
},
Daemon {
daemon_id: [u8; 32],
required: &'a CapabilitySet,
optional: &'a CapabilitySet,
},
Blob {
blob_hash: [u8; 32],
size_bytes: u64,
},
}
pub trait PlacementFilter: Send + Sync {
fn placement_score(&self, target: &NodeId, artifact: &Artifact<'_>) -> Option<f32>;
}
pub struct LegacyPlacement<'a> {
filter: CapabilityFilter,
fold: &'a Fold<CapabilityFold>,
}
impl<'a> LegacyPlacement<'a> {
pub fn new(filter: CapabilityFilter, fold: &'a Fold<CapabilityFold>) -> Self {
Self { filter, fold }
}
pub fn permissive(fold: &'a Fold<CapabilityFold>) -> Self {
Self {
filter: CapabilityFilter::default(),
fold,
}
}
}
impl<'a> PlacementFilter for LegacyPlacement<'a> {
fn placement_score(&self, target: &NodeId, _artifact: &Artifact<'_>) -> Option<f32> {
if capability_bridge::target_matches_filter(self.fold, *target, &self.filter) {
Some(1.0)
} else {
None
}
}
}
use std::time::Duration;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ScopeLabel(String);
impl ScopeLabel {
pub fn new(label: impl Into<String>) -> Self {
Self(label.into())
}
pub fn as_str(&self) -> &str {
&self.0
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ResourceAxis {
Storage,
Compute,
Both,
}
#[derive(Debug, Clone)]
pub struct PlacementMetadataKeys {
pub intent: String,
pub colocate_with: String,
pub colocate_with_strict: String,
}
impl Default for PlacementMetadataKeys {
fn default() -> Self {
Self {
intent: "intent".to_string(),
colocate_with: "colocate-with".to_string(),
colocate_with_strict: "colocate-with-strict".to_string(),
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct AntiAffinityConfig {
pub leadership_concentration_threshold: f32,
pub leadership_concentration_penalty: f32,
}
impl Default for AntiAffinityConfig {
fn default() -> Self {
Self {
leadership_concentration_threshold: 0.30,
leadership_concentration_penalty: 0.4,
}
}
}
#[derive(Debug, Clone, Default)]
pub enum IntentMatchPolicy {
#[default]
Disabled,
AnyOfLocalCapabilities,
Strict,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum ColocationPolicy {
#[default]
Ignore,
SoftPreference,
StrictRequired,
}
pub struct StandardPlacement<'a> {
fold: &'a Fold<CapabilityFold>,
pub scope_filter: Option<Vec<ScopeLabel>>,
pub proximity_max_rtt: Option<Duration>,
pub rtt_lookup: Option<&'a dyn RttLookup>,
pub intent_match: IntentMatchPolicy,
pub intent_registry: IntentRegistry,
pub colocation_policy: ColocationPolicy,
pub resource_axis: ResourceAxis,
pub metadata_keys: PlacementMetadataKeys,
pub anti_affinity: AntiAffinityConfig,
pub leadership_stats: Option<&'a dyn LeadershipStatsLookup>,
pub custom_filter_id: Option<String>,
}
impl<'a> StandardPlacement<'a> {
pub fn new(fold: &'a Fold<CapabilityFold>) -> Self {
Self {
fold,
scope_filter: None,
proximity_max_rtt: None,
rtt_lookup: None,
intent_match: IntentMatchPolicy::default(),
intent_registry: IntentRegistry::default(),
colocation_policy: ColocationPolicy::default(),
resource_axis: ResourceAxis::Compute,
metadata_keys: PlacementMetadataKeys::default(),
anti_affinity: AntiAffinityConfig::default(),
leadership_stats: None,
custom_filter_id: None,
}
}
pub fn with_scope_filter(mut self, labels: Vec<ScopeLabel>) -> Self {
self.scope_filter = Some(labels);
self
}
pub fn with_proximity_max_rtt(mut self, max: Duration) -> Self {
self.proximity_max_rtt = Some(max);
self
}
pub fn with_rtt_lookup(mut self, lookup: &'a dyn RttLookup) -> Self {
self.rtt_lookup = Some(lookup);
self
}
pub fn with_leadership_stats(mut self, lookup: &'a dyn LeadershipStatsLookup) -> Self {
self.leadership_stats = Some(lookup);
self
}
pub fn with_intent_match(mut self, policy: IntentMatchPolicy) -> Self {
self.intent_match = policy;
self
}
pub fn with_intent_registry(mut self, registry: IntentRegistry) -> Self {
self.intent_registry = registry;
self
}
pub fn with_colocation_policy(mut self, policy: ColocationPolicy) -> Self {
self.colocation_policy = policy;
self
}
pub fn with_resource_axis(mut self, axis: ResourceAxis) -> Self {
self.resource_axis = axis;
self
}
pub fn with_custom_filter_id(mut self, id: impl Into<String>) -> Self {
self.custom_filter_id = Some(id.into());
self
}
}
pub fn compose_axis_scores(scores: impl IntoIterator<Item = f32>) -> f32 {
let mut product: f32 = 1.0;
for s in scores {
let clamped = if s.is_nan() { 0.0 } else { s.clamp(0.0, 1.0) };
product *= clamped;
if product == 0.0 {
return 0.0;
}
}
product
}
impl<'a> PlacementFilter for StandardPlacement<'a> {
fn placement_score(&self, target: &NodeId, artifact: &Artifact<'_>) -> Option<f32> {
let custom = self.score_custom_filter_axis(target, artifact)?;
let known = self
.fold
.with_state(|state| state.by_node.contains_key(target));
if !known {
return None;
}
let target_caps = capability_bridge::synthesize_capability_set(self.fold, *target);
(|target_caps: &CapabilitySet| -> Option<f32> {
if let Artifact::Daemon { required, .. } = artifact {
if !required.tags.iter().all(|t| target_caps.tags.contains(t)) {
return None;
}
}
if let Artifact::Blob { size_bytes, .. } = artifact {
use super::dataforts_capabilities::{is_blob_storage_unhealthy, BlobCapability};
let blob_caps = BlobCapability::from_capability_set(target_caps);
if !blob_caps.storage {
return None;
}
if is_blob_storage_unhealthy(target_caps) {
return None;
}
let required_gb = size_bytes.div_ceil(1 << 30);
if blob_caps.disk_free_gb < required_gb {
return None;
}
}
let scope = self.score_scope_axis(target_caps);
let proximity = self.score_proximity_axis(target);
let intent = self.score_intent_axis(target_caps, artifact);
let colocation = self.score_colocation_axis(target_caps, artifact);
let resource = self.score_resource_axis(target_caps, artifact);
let anti_affinity = self.score_anti_affinity_axis(target);
Some(compose_axis_scores([
scope,
proximity,
intent,
colocation,
resource,
anti_affinity,
custom,
]))
})(&target_caps)
}
}
impl<'a> StandardPlacement<'a> {
fn score_scope_axis(&self, target_caps: &CapabilitySet) -> f32 {
let Some(filter) = self.scope_filter.as_ref() else {
return 1.0;
};
if filter.is_empty() {
return 1.0;
}
let target_scope_bodies: Vec<&str> = target_caps
.tags
.iter()
.filter_map(|t| match t {
Tag::Reserved { prefix, body } if prefix.as_str() == "scope:" => {
Some(body.as_str())
}
_ => None,
})
.collect();
if target_scope_bodies.is_empty() {
return 0.0;
}
let any_match = filter.iter().any(|label| {
let raw = label.as_str();
let body = raw.strip_prefix("scope:").unwrap_or(raw);
target_scope_bodies.contains(&body)
});
if any_match {
1.0
} else {
0.0
}
}
fn score_proximity_axis(&self, target: &NodeId) -> f32 {
let Some(max_rtt) = self.proximity_max_rtt else {
return 1.0;
};
let Some(lookup) = self.rtt_lookup else {
return 1.0;
};
let Some(rtt_us) = lookup(*target) else {
return 1.0;
};
let target_rtt = Duration::from_micros(rtt_us);
if target_rtt <= max_rtt {
1.0
} else {
0.0
}
}
fn score_intent_axis(&self, target_caps: &CapabilitySet, artifact: &Artifact<'_>) -> f32 {
match self.intent_match {
IntentMatchPolicy::Disabled => 1.0,
IntentMatchPolicy::Strict => {
let Some(intent) = artifact_intent(artifact, &self.metadata_keys.intent) else {
return 1.0; };
let Some(reqs) = self.intent_registry.lookup(intent) else {
return 1.0;
};
evaluate_required_caps(target_caps, reqs)
}
IntentMatchPolicy::AnyOfLocalCapabilities => {
if self.intent_registry.is_empty() {
return 1.0;
}
let any_satisfied = self
.intent_registry
.iter()
.any(|(_, reqs)| evaluate_required_caps(target_caps, reqs) >= 1.0);
if any_satisfied {
1.0
} else {
0.0
}
}
}
}
fn score_colocation_axis(&self, target_caps: &CapabilitySet, artifact: &Artifact<'_>) -> f32 {
if self.colocation_policy == ColocationPolicy::Ignore {
return 1.0;
}
let strict_chain = artifact_metadata(artifact, &self.metadata_keys.colocate_with_strict);
let soft_chain = artifact_metadata(artifact, &self.metadata_keys.colocate_with);
if strict_chain.is_none() && soft_chain.is_none() {
return 1.0; }
if let Some(chain) = strict_chain {
if !target_holds_chain(target_caps, chain) {
return 0.0;
}
}
if let Some(chain) = soft_chain {
let does_host = target_holds_chain(target_caps, chain);
match self.colocation_policy {
ColocationPolicy::Ignore => unreachable!("handled above"),
ColocationPolicy::SoftPreference => {
return if does_host { 1.0 } else { 0.7 };
}
ColocationPolicy::StrictRequired => {
if !does_host {
return 0.0;
}
}
}
}
1.0
}
fn score_resource_axis(&self, target_caps: &CapabilitySet, _artifact: &Artifact<'_>) -> f32 {
match self.resource_axis {
ResourceAxis::Compute => score_compute_axis(target_caps),
ResourceAxis::Storage => score_storage_axis(target_caps),
ResourceAxis::Both => {
let c = score_compute_axis_with_data(target_caps);
let s = score_storage_axis_with_data(target_caps);
match (c, s) {
(None, None) => 1.0,
(Some(score), None) | (None, Some(score)) => score,
(Some(cs), Some(ss)) => (cs + ss) / 2.0,
}
}
}
}
fn score_anti_affinity_axis(&self, target: &NodeId) -> f32 {
let Some(lookup) = self.leadership_stats else {
return 1.0;
};
let Some(concentration) = lookup(*target) else {
return 1.0;
};
if !concentration.is_finite() {
return 1.0;
}
if concentration <= self.anti_affinity.leadership_concentration_threshold {
1.0
} else {
let p = self.anti_affinity.leadership_concentration_penalty;
if p.is_nan() {
0.0
} else {
p.clamp(0.0, 1.0)
}
}
}
fn score_custom_filter_axis(&self, target: &NodeId, artifact: &Artifact<'_>) -> Option<f32> {
let Some(id) = self.custom_filter_id.as_deref() else {
return Some(1.0);
};
let registry = super::placement_registry::global_placement_filter_registry();
let Some(filter) = registry.get(id) else {
eprintln!(
"StandardPlacement: custom_filter_id {id:?} not registered in \
global_placement_filter_registry; vetoing target {target:#x}. \
Did the SDK call mesh.registerPlacementFilter before placement?",
);
return None;
};
filter.placement_score(target, artifact)
}
}
fn artifact_metadata<'a>(artifact: &'a Artifact<'_>, key: &str) -> Option<&'a str> {
let try_caps = |caps: &'a CapabilitySet| caps.metadata.get(key).map(|s| s.as_str());
match artifact {
Artifact::Daemon {
required, optional, ..
} => try_caps(required).or_else(|| try_caps(optional)),
Artifact::Chain { capabilities, .. } => try_caps(capabilities),
Artifact::Replica { capabilities, .. } => try_caps(capabilities),
Artifact::Blob { .. } => None,
}
}
fn artifact_intent<'a>(artifact: &'a Artifact<'_>, intent_key: &str) -> Option<&'a str> {
artifact_metadata(artifact, intent_key)
}
fn target_axis_value_numeric(caps: &CapabilitySet, axis: TaxonomyAxis, key: &str) -> Option<f64> {
caps.tags.iter().find_map(|t| match t {
Tag::AxisValue {
axis: a,
key: k,
value,
..
} if *a == axis && k == key => {
let v = value.parse::<f64>().ok()?;
if !(0.0..=MAX_RESOURCE_VALUE).contains(&v) || !v.is_finite() {
return None;
}
Some(v)
}
_ => None,
})
}
const MAX_RESOURCE_VALUE: f64 = 1e15;
fn saturating_score(value: f32, reference: f32) -> f32 {
if value <= 0.0 || reference <= 0.0 || !value.is_finite() || !reference.is_finite() {
return 0.0;
}
value / (value + reference)
}
fn score_compute_axis(caps: &CapabilitySet) -> f32 {
let mut sum = 0.0_f32;
let mut count = 0u32;
if let Some(c) = target_axis_value_numeric(caps, TaxonomyAxis::Hardware, "cpu_cores") {
sum += saturating_score(c as f32, 8.0);
count += 1;
}
if let Some(m) = target_axis_value_numeric(caps, TaxonomyAxis::Hardware, "memory_gb") {
sum += saturating_score(m as f32, 16.0);
count += 1;
}
if let Some(v) = target_axis_value_numeric(caps, TaxonomyAxis::Hardware, "gpu.vram_gb") {
sum += saturating_score(v as f32, 16.0);
count += 1;
}
if count == 0 {
return 1.0;
}
sum / count as f32
}
fn score_storage_axis(caps: &CapabilitySet) -> f32 {
if let Some(s) = target_axis_value_numeric(caps, TaxonomyAxis::Dataforts, "capacity_gb") {
saturating_score(s as f32, 1000.0)
} else {
1.0
}
}
fn score_compute_axis_with_data(caps: &CapabilitySet) -> Option<f32> {
let mut sum = 0.0_f32;
let mut count = 0u32;
if let Some(c) = target_axis_value_numeric(caps, TaxonomyAxis::Hardware, "cpu_cores") {
sum += saturating_score(c as f32, 8.0);
count += 1;
}
if let Some(m) = target_axis_value_numeric(caps, TaxonomyAxis::Hardware, "memory_gb") {
sum += saturating_score(m as f32, 16.0);
count += 1;
}
if let Some(v) = target_axis_value_numeric(caps, TaxonomyAxis::Hardware, "gpu.vram_gb") {
sum += saturating_score(v as f32, 16.0);
count += 1;
}
if count == 0 {
return None;
}
Some(sum / count as f32)
}
fn score_storage_axis_with_data(caps: &CapabilitySet) -> Option<f32> {
let s = target_axis_value_numeric(caps, TaxonomyAxis::Dataforts, "capacity_gb")?;
Some(saturating_score(s as f32, 1000.0))
}
fn target_holds_chain(target_caps: &CapabilitySet, chain_hash: &str) -> bool {
target_caps.tags.iter().any(|t| match t {
Tag::Reserved { prefix, body } if prefix.as_str() == "causal:" => {
let hash_end = body.find([':', '[']).unwrap_or(body.len());
&body[..hash_end] == chain_hash
}
_ => false,
})
}
fn evaluate_required_caps(target_caps: &CapabilitySet, reqs: &[RequiredCapability]) -> f32 {
if reqs.is_empty() {
return 1.0;
}
let tags: Vec<Tag> = target_caps.tags.iter().cloned().collect();
let ctx =
crate::adapter::net::behavior::predicate::EvalContext::new(&tags, &target_caps.metadata);
if reqs.iter().all(|r| r.evaluate(&ctx)) {
1.0
} else {
0.0
}
}
#[derive(Debug, Clone, Default)]
pub struct IntentRegistry {
map: BTreeMap<String, Vec<RequiredCapability>>,
}
impl IntentRegistry {
pub fn new() -> Self {
Self::default()
}
pub fn defaults() -> Self {
let mut map: BTreeMap<String, Vec<RequiredCapability>> = BTreeMap::new();
map.insert(
"ml-training".to_string(),
vec![
RequiredCapability::Tag(Tag::AxisPresent {
axis: TaxonomyAxis::Hardware,
key: "gpu".to_string(),
}),
RequiredCapability::Predicate(Predicate::numeric_at_least(
TagKey::new(TaxonomyAxis::Hardware, "gpu.vram_gb"),
24.0,
)),
],
);
map.insert(
"inference".to_string(),
vec![
RequiredCapability::Tag(Tag::AxisPresent {
axis: TaxonomyAxis::Hardware,
key: "gpu".to_string(),
}),
RequiredCapability::AxisKey(TagKey::new(
TaxonomyAxis::Software,
"model".to_string(),
)),
],
);
map.insert(
"cpu-bound".to_string(),
vec![RequiredCapability::Predicate(Predicate::numeric_at_least(
TagKey::new(TaxonomyAxis::Hardware, "cpu_cores"),
4.0,
))],
);
map.insert(
"sensor-telemetry".to_string(),
vec![RequiredCapability::AxisAny(TaxonomyAxis::Devices)],
);
Self { map }
}
pub fn register(
&mut self,
intent: impl Into<String>,
requirements: Vec<RequiredCapability>,
) -> Option<Vec<RequiredCapability>> {
self.map.insert(intent.into(), requirements)
}
pub fn lookup(&self, intent: &str) -> Option<&[RequiredCapability]> {
self.map.get(intent).map(|v| v.as_slice())
}
pub fn iter(&self) -> impl Iterator<Item = (&str, &[RequiredCapability])> {
self.map.iter().map(|(k, v)| (k.as_str(), v.as_slice()))
}
pub fn len(&self) -> usize {
self.map.len()
}
pub fn is_empty(&self) -> bool {
self.map.is_empty()
}
}
pub trait RttLookup: Fn(NodeId) -> Option<u64> + Sync {}
impl<F: Fn(NodeId) -> Option<u64> + Sync> RttLookup for F {}
pub trait LeadershipStatsLookup: Fn(NodeId) -> Option<f32> + Sync {}
impl<F: Fn(NodeId) -> Option<f32> + Sync> LeadershipStatsLookup for F {}
pub struct TieBreakContext<'a> {
pub rtt_lookup: Option<&'a dyn RttLookup>,
pub resource_axis: ResourceAxis,
}
pub fn tie_break_compare(a: NodeId, b: NodeId, ctx: &TieBreakContext<'_>) -> Ordering {
if a == b {
return Ordering::Equal;
}
if let Some(lookup) = ctx.rtt_lookup {
let a_rtt = lookup(a);
let b_rtt = lookup(b);
match (a_rtt, b_rtt) {
(Some(ar), Some(br)) if ar != br => return ar.cmp(&br),
(Some(_), None) => return Ordering::Less,
(None, Some(_)) => return Ordering::Greater,
_ => {} }
}
let a_free = free_resource_for(a, ctx);
let b_free = free_resource_for(b, ctx);
if a_free != b_free {
return b_free.cmp(&a_free);
}
a.cmp(&b)
}
fn free_resource_for(_node: NodeId, _ctx: &TieBreakContext<'_>) -> u64 {
0
}
#[cfg(test)]
mod tests {
use super::*;
use crate::adapter::net::behavior::capability::{CapabilityAnnouncement, CapabilitySet};
use crate::adapter::net::identity::EntityId;
use std::sync::Arc;
fn index_with(nodes: &[(NodeId, CapabilitySet)]) -> Arc<Fold<CapabilityFold>> {
let fold: Arc<Fold<CapabilityFold>> =
Arc::new(Fold::with_sweep_interval(std::time::Duration::ZERO));
let eid = EntityId::from_bytes([0u8; 32]);
for (node_id, caps) in nodes {
capability_bridge::apply_legacy_announcement(
&fold,
CapabilityAnnouncement::new(*node_id, eid.clone(), 1, caps.clone()),
)
.expect("apply legacy announcement in fixture");
}
fold
}
fn empty_caps() -> CapabilitySet {
CapabilitySet::default()
}
fn daemon_artifact<'a>(
required: &'a CapabilitySet,
optional: &'a CapabilitySet,
) -> Artifact<'a> {
Artifact::Daemon {
daemon_id: [0u8; 32],
required,
optional,
}
}
#[test]
fn legacy_permissive_scores_all_indexed_nodes() {
let fold = index_with(&[(0x1111, empty_caps()), (0x2222, empty_caps())]);
let filter = LegacyPlacement::permissive(&fold);
let req = empty_caps();
let opt = empty_caps();
let artifact = daemon_artifact(&req, &opt);
assert_eq!(filter.placement_score(&0x1111, &artifact), Some(1.0));
assert_eq!(filter.placement_score(&0x2222, &artifact), Some(1.0));
}
#[test]
fn legacy_returns_none_for_unindexed_candidate() {
let fold = index_with(&[(0x1111, empty_caps())]);
let filter = LegacyPlacement::permissive(&fold);
let req = empty_caps();
let opt = empty_caps();
let artifact = daemon_artifact(&req, &opt);
assert_eq!(filter.placement_score(&0xDEAD, &artifact), None);
}
#[test]
fn legacy_filter_vetoes_non_matching_candidates() {
let caps_with_tag = empty_caps().add_tag("hardware.gpu");
let fold = index_with(&[(0x1111, caps_with_tag), (0x2222, empty_caps())]);
let required = CapabilityFilter::default().require_tag("hardware.gpu".to_string());
let filter = LegacyPlacement::new(required, &fold);
let req = empty_caps();
let opt = empty_caps();
let artifact = daemon_artifact(&req, &opt);
assert_eq!(filter.placement_score(&0x1111, &artifact), Some(1.0));
assert_eq!(
filter.placement_score(&0x2222, &artifact),
None,
"candidate without the required tag must veto via None"
);
}
#[test]
fn placement_filter_is_dyn_compatible() {
let fold = index_with(&[(0x1111, empty_caps())]);
let filter = LegacyPlacement::permissive(&fold);
let dyn_filter: &dyn PlacementFilter = &filter;
let req = empty_caps();
let opt = empty_caps();
let artifact = daemon_artifact(&req, &opt);
let _ = dyn_filter.placement_score(&0x1111, &artifact);
}
#[test]
fn placement_filter_requires_send_sync() {
fn assert_send_sync<T: Send + Sync>() {}
assert_send_sync::<&dyn PlacementFilter>();
}
#[test]
fn compose_empty_returns_one() {
assert_eq!(compose_axis_scores(std::iter::empty::<f32>()), 1.0);
}
#[test]
fn compose_zero_anywhere_zeroes_final_score() {
assert_eq!(compose_axis_scores([1.0, 1.0, 0.0, 1.0]), 0.0);
assert_eq!(compose_axis_scores([0.0, 0.5, 0.7]), 0.0);
assert_eq!(compose_axis_scores([0.5, 0.7, 0.0]), 0.0);
}
#[test]
fn compose_multiplies_per_axis_scores() {
let got = compose_axis_scores([0.5, 0.5, 0.5]);
assert!((got - 0.125).abs() < 1e-6, "got {got}, want 0.125");
}
#[test]
fn compose_clamps_out_of_range_and_nan_inputs() {
assert_eq!(compose_axis_scores([1.0, -0.5, 1.0]), 0.0);
assert_eq!(compose_axis_scores([1.0, 1.5, 1.0]), 1.0);
assert_eq!(compose_axis_scores([1.0, f32::NAN, 1.0]), 0.0);
}
#[test]
fn standard_default_config_matches_legacy_permissive() {
let fold = index_with(&[(0x1111, empty_caps()), (0x2222, empty_caps())]);
let placement = StandardPlacement::new(&fold);
let req = empty_caps();
let opt = empty_caps();
let artifact = daemon_artifact(&req, &opt);
assert_eq!(placement.placement_score(&0x1111, &artifact), Some(1.0));
assert_eq!(placement.placement_score(&0x2222, &artifact), Some(1.0));
}
#[test]
fn standard_returns_none_for_unindexed_target() {
let fold = index_with(&[(0x1111, empty_caps())]);
let placement = StandardPlacement::new(&fold);
let req = empty_caps();
let opt = empty_caps();
let artifact = daemon_artifact(&req, &opt);
assert_eq!(placement.placement_score(&0xDEAD, &artifact), None);
}
#[test]
fn standard_vetoes_candidates_missing_required_caps() {
let caps_with_gpu = empty_caps().add_tag("hardware.gpu");
let fold = index_with(&[(0x1111, caps_with_gpu), (0x2222, empty_caps())]);
let placement = StandardPlacement::new(&fold);
let required = empty_caps().add_tag("hardware.gpu");
let opt = empty_caps();
let artifact = daemon_artifact(&required, &opt);
assert_eq!(placement.placement_score(&0x1111, &artifact), Some(1.0));
assert_eq!(
placement.placement_score(&0x2222, &artifact),
None,
"candidate without required hardware.gpu must veto"
);
}
#[test]
fn standard_builder_setters_populate_fields() {
let fold = index_with(&[]);
let placement = StandardPlacement::new(&fold)
.with_scope_filter(vec![ScopeLabel::new("scope:tenant:foo")])
.with_proximity_max_rtt(Duration::from_millis(50))
.with_intent_match(IntentMatchPolicy::Strict)
.with_colocation_policy(ColocationPolicy::SoftPreference)
.with_resource_axis(ResourceAxis::Storage);
assert_eq!(placement.scope_filter.as_ref().unwrap().len(), 1);
assert_eq!(
placement.scope_filter.as_ref().unwrap()[0].as_str(),
"scope:tenant:foo"
);
assert_eq!(placement.proximity_max_rtt, Some(Duration::from_millis(50)));
assert!(matches!(placement.intent_match, IntentMatchPolicy::Strict));
assert_eq!(
placement.colocation_policy,
ColocationPolicy::SoftPreference
);
assert_eq!(placement.resource_axis, ResourceAxis::Storage);
}
#[test]
fn standard_default_axis_configs_disable_each_axis() {
let fold = index_with(&[]);
let placement = StandardPlacement::new(&fold);
assert!(placement.scope_filter.is_none());
assert!(placement.proximity_max_rtt.is_none());
assert!(matches!(
placement.intent_match,
IntentMatchPolicy::Disabled
));
assert_eq!(placement.colocation_policy, ColocationPolicy::Ignore);
}
#[test]
fn intent_registry_defaults_include_all_baseline_intents() {
let r = IntentRegistry::defaults();
assert!(r.lookup("ml-training").is_some());
assert!(r.lookup("inference").is_some());
assert!(r.lookup("cpu-bound").is_some());
assert!(r.lookup("sensor-telemetry").is_some());
assert_eq!(r.len(), 4);
}
#[test]
fn intent_registry_defaults_ml_training_requires_gpu_plus_vram_threshold() {
let r = IntentRegistry::defaults();
let reqs = r.lookup("ml-training").expect("ml-training present");
assert_eq!(reqs.len(), 2, "ml-training requires gpu + vram threshold");
let has_gpu_tag = reqs.iter().any(|rc| {
matches!(
rc,
RequiredCapability::Tag(Tag::AxisPresent { axis, key })
if *axis == TaxonomyAxis::Hardware && key == "gpu"
)
});
assert!(has_gpu_tag, "ml-training must include hardware.gpu tag");
let has_vram_predicate = reqs
.iter()
.any(|rc| matches!(rc, RequiredCapability::Predicate(_)));
assert!(
has_vram_predicate,
"ml-training must include vram numeric predicate"
);
}
#[test]
fn intent_registry_register_adds_lookup() {
let mut r = IntentRegistry::new();
assert!(r.is_empty());
let prev = r.register(
"custom-intent",
vec![RequiredCapability::AxisAny(TaxonomyAxis::Hardware)],
);
assert!(prev.is_none());
assert_eq!(r.len(), 1);
assert_eq!(r.lookup("custom-intent").expect("just registered").len(), 1);
}
#[test]
fn intent_registry_register_replaces_returns_previous() {
let mut r = IntentRegistry::defaults();
let prev = r.register(
"ml-training",
vec![RequiredCapability::AxisAny(TaxonomyAxis::Software)],
);
assert!(prev.is_some(), "previous mapping returned");
assert_eq!(prev.unwrap().len(), 2, "old ml-training had 2 requirements");
assert_eq!(r.lookup("ml-training").expect("re-registered").len(), 1);
}
#[test]
fn intent_registry_lookup_unknown_returns_none() {
let r = IntentRegistry::defaults();
assert!(r.lookup("nonexistent-intent").is_none());
}
#[test]
fn intent_registry_iter_is_lex_ordered() {
let mut r = IntentRegistry::new();
r.register("zebra", vec![]);
r.register("alpha", vec![]);
r.register("middle", vec![]);
let names: Vec<&str> = r.iter().map(|(k, _)| k).collect();
assert_eq!(names, vec!["alpha", "middle", "zebra"]);
}
#[test]
fn intent_registry_defaults_evaluation_round_trip() {
use crate::adapter::net::behavior::predicate::EvalContext;
let r = IntentRegistry::defaults();
let reqs = r.lookup("ml-training").unwrap();
let satisfying_caps = empty_caps()
.add_tag("hardware.gpu")
.add_tag("hardware.gpu.vram_gb=32");
let tags_a: Vec<Tag> = satisfying_caps.tags.iter().cloned().collect();
let meta_a = satisfying_caps.metadata.clone();
let ctx_a = EvalContext::new(&tags_a, &meta_a);
assert!(
reqs.iter().all(|rc| rc.evaluate(&ctx_a)),
"candidate with gpu + 32GB vram satisfies ml-training"
);
let partial_caps = empty_caps().add_tag("hardware.gpu");
let tags_b: Vec<Tag> = partial_caps.tags.iter().cloned().collect();
let meta_b = partial_caps.metadata.clone();
let ctx_b = EvalContext::new(&tags_b, &meta_b);
assert!(
!reqs.iter().all(|rc| rc.evaluate(&ctx_b)),
"candidate without vram threshold doesn't satisfy ml-training"
);
}
fn rtt_map(entries: &'static [(NodeId, u64)]) -> impl Fn(NodeId) -> Option<u64> + Sync {
|id: NodeId| entries.iter().find(|(n, _)| *n == id).map(|(_, rtt)| *rtt)
}
#[test]
fn tie_break_step_1_rtt_lower_wins() {
let _fold = index_with(&[(0x1111, empty_caps()), (0x2222, empty_caps())]);
let lookup = rtt_map(&[(0x1111, 5_000), (0x2222, 50_000)]);
let ctx = TieBreakContext {
rtt_lookup: Some(&lookup),
resource_axis: ResourceAxis::Compute,
};
assert_eq!(tie_break_compare(0x1111, 0x2222, &ctx), Ordering::Less);
assert_eq!(tie_break_compare(0x2222, 0x1111, &ctx), Ordering::Greater);
}
#[test]
fn tie_break_step_1_present_rtt_beats_missing() {
let _fold = index_with(&[(0x1111, empty_caps()), (0x2222, empty_caps())]);
let lookup = rtt_map(&[(0x1111, 10_000)]);
let ctx = TieBreakContext {
rtt_lookup: Some(&lookup),
resource_axis: ResourceAxis::Compute,
};
assert_eq!(
tie_break_compare(0x1111, 0x2222, &ctx),
Ordering::Less,
"candidate with RTT data must sort before one without",
);
assert_eq!(tie_break_compare(0x2222, 0x1111, &ctx), Ordering::Greater,);
}
#[test]
fn tie_break_falls_through_to_lex_node_id_when_no_rtt_lookup() {
let _fold = index_with(&[(0x1111, empty_caps()), (0x2222, empty_caps())]);
let ctx = TieBreakContext {
rtt_lookup: None,
resource_axis: ResourceAxis::Compute,
};
assert_eq!(tie_break_compare(0x1111, 0x2222, &ctx), Ordering::Less);
assert_eq!(tie_break_compare(0x2222, 0x1111, &ctx), Ordering::Greater);
}
#[test]
fn tie_break_self_compare_is_equal() {
let _fold = index_with(&[(0x1111, empty_caps())]);
let ctx = TieBreakContext {
rtt_lookup: None,
resource_axis: ResourceAxis::Compute,
};
assert_eq!(tie_break_compare(0x1111, 0x1111, &ctx), Ordering::Equal);
}
#[test]
fn tie_break_is_deterministic_across_repeated_calls() {
let _fold = index_with(&[(0x1111, empty_caps()), (0x2222, empty_caps())]);
let lookup = rtt_map(&[(0x1111, 5_000), (0x2222, 50_000)]);
let ctx = TieBreakContext {
rtt_lookup: Some(&lookup),
resource_axis: ResourceAxis::Compute,
};
let first = tie_break_compare(0x1111, 0x2222, &ctx);
for _ in 0..16 {
assert_eq!(tie_break_compare(0x1111, 0x2222, &ctx), first);
}
}
#[test]
fn tie_break_equal_rtt_falls_through_to_lex_node_id() {
let _fold = index_with(&[(0x1111, empty_caps()), (0x2222, empty_caps())]);
let lookup = rtt_map(&[(0x1111, 10_000), (0x2222, 10_000)]);
let ctx = TieBreakContext {
rtt_lookup: Some(&lookup),
resource_axis: ResourceAxis::Compute,
};
assert_eq!(tie_break_compare(0x1111, 0x2222, &ctx), Ordering::Less);
}
#[test]
fn nearest_rtt_returns_lowest_matching_peer() {
use crate::adapter::net::behavior::proximity::{
EnhancedPingwave, ProximityConfig, ProximityGraph,
};
use std::net::SocketAddr;
use std::time::{SystemTime, UNIX_EPOCH};
fn now_us() -> u64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_micros() as u64
}
fn nid(n: u8) -> [u8; 32] {
let mut id = [0u8; 32];
id[0] = n;
id
}
let my = nid(0xFF);
let graph = ProximityGraph::new(my, ProximityConfig::default());
let addr: SocketAddr = "127.0.0.1:9000".parse().unwrap();
let now = now_us();
let mut pw_a = EnhancedPingwave::new(nid(1), 1, 3);
pw_a.origin_timestamp_us = now.saturating_sub(5_000);
graph.on_pingwave(pw_a, addr);
let mut pw_b = EnhancedPingwave::new(nid(2), 1, 3);
pw_b.origin_timestamp_us = now.saturating_sub(50_000);
graph.on_pingwave(pw_b, addr);
let nearest = graph.nearest_rtt(|_| true).expect("at least one peer");
assert!(
nearest.as_micros() < 30_000,
"expected the lower-latency peer (~5 ms), got {nearest:?}",
);
let only_b = graph.nearest_rtt(|n| n.node_id == nid(2));
assert!(only_b.is_some());
let none = graph.nearest_rtt(|_| false);
assert!(none.is_none());
}
fn daemon_with_intent<'a>(
required: &'a CapabilitySet,
optional: &'a CapabilitySet,
) -> Artifact<'a> {
Artifact::Daemon {
daemon_id: [0u8; 32],
required,
optional,
}
}
#[test]
fn intent_axis_disabled_always_returns_one() {
let mut required = empty_caps();
required = with_metadata_pair(required, "intent", "ml-training");
let optional = empty_caps();
let artifact = daemon_with_intent(&required, &optional);
let fold = index_with(&[(0x1111, empty_caps())]);
let placement = StandardPlacement::new(&fold)
.with_intent_match(IntentMatchPolicy::Disabled)
.with_intent_registry(IntentRegistry::defaults());
let target_caps = empty_caps();
let score = placement.score_intent_axis(&target_caps, &artifact);
assert_eq!(score, 1.0);
}
#[test]
fn intent_axis_strict_no_intent_metadata_returns_one() {
let required = empty_caps();
let optional = empty_caps();
let artifact = daemon_with_intent(&required, &optional);
let fold = index_with(&[(0x1111, empty_caps())]);
let placement = StandardPlacement::new(&fold)
.with_intent_match(IntentMatchPolicy::Strict)
.with_intent_registry(IntentRegistry::defaults());
let target_caps = empty_caps();
let score = placement.score_intent_axis(&target_caps, &artifact);
assert_eq!(score, 1.0, "no intent declared → no constraint");
}
#[test]
fn intent_axis_strict_unknown_intent_returns_one_forward_compat() {
let mut required = empty_caps();
required = with_metadata_pair(required, "intent", "future-intent-not-in-registry");
let optional = empty_caps();
let artifact = daemon_with_intent(&required, &optional);
let fold = index_with(&[(0x1111, empty_caps())]);
let placement = StandardPlacement::new(&fold)
.with_intent_match(IntentMatchPolicy::Strict)
.with_intent_registry(IntentRegistry::defaults());
let target_caps = empty_caps();
let score = placement.score_intent_axis(&target_caps, &artifact);
assert_eq!(score, 1.0, "unknown intent passes through");
}
#[test]
fn intent_axis_strict_satisfied_returns_one() {
let mut required = empty_caps();
required = with_metadata_pair(required, "intent", "ml-training");
let optional = empty_caps();
let artifact = daemon_with_intent(&required, &optional);
let fold = index_with(&[(0x1111, empty_caps())]);
let placement = StandardPlacement::new(&fold)
.with_intent_match(IntentMatchPolicy::Strict)
.with_intent_registry(IntentRegistry::defaults());
let target_caps = empty_caps()
.add_tag("hardware.gpu")
.add_tag("hardware.gpu.vram_gb=32");
let score = placement.score_intent_axis(&target_caps, &artifact);
assert_eq!(score, 1.0);
}
#[test]
fn intent_axis_strict_unsatisfied_returns_zero() {
let mut required = empty_caps();
required = with_metadata_pair(required, "intent", "ml-training");
let optional = empty_caps();
let artifact = daemon_with_intent(&required, &optional);
let fold = index_with(&[(0x1111, empty_caps())]);
let placement = StandardPlacement::new(&fold)
.with_intent_match(IntentMatchPolicy::Strict)
.with_intent_registry(IntentRegistry::defaults());
let target_caps = empty_caps()
.add_tag("hardware.gpu")
.add_tag("hardware.gpu.vram_gb=8");
let score = placement.score_intent_axis(&target_caps, &artifact);
assert_eq!(score, 0.0);
}
#[test]
fn intent_axis_any_of_with_empty_registry_is_pass_through() {
let required = empty_caps();
let optional = empty_caps();
let artifact = daemon_with_intent(&required, &optional);
let fold = index_with(&[(0x1111, empty_caps())]);
let placement = StandardPlacement::new(&fold)
.with_intent_match(IntentMatchPolicy::AnyOfLocalCapabilities);
let target_caps = empty_caps()
.add_tag("hardware.gpu")
.add_tag("hardware.gpu.vram_gb=32");
let score = placement.score_intent_axis(&target_caps, &artifact);
assert_eq!(
score, 1.0,
"empty registry must pass through (axis-disabled identity), \
not hard-veto every candidate cluster-wide"
);
}
#[test]
fn intent_axis_any_of_satisfies_via_one_intent() {
let required = empty_caps();
let optional = empty_caps();
let artifact = daemon_with_intent(&required, &optional);
let fold = index_with(&[(0x1111, empty_caps())]);
let placement = StandardPlacement::new(&fold)
.with_intent_match(IntentMatchPolicy::AnyOfLocalCapabilities)
.with_intent_registry(IntentRegistry::defaults());
let target_caps = empty_caps()
.add_tag("hardware.gpu")
.add_tag("hardware.gpu.vram_gb=32");
let score = placement.score_intent_axis(&target_caps, &artifact);
assert_eq!(score, 1.0, "ml-training reqs satisfy → axis passes");
}
#[test]
fn intent_axis_any_of_target_useful_for_nothing_returns_zero() {
let required = empty_caps();
let optional = empty_caps();
let artifact = daemon_with_intent(&required, &optional);
let fold = index_with(&[(0x1111, empty_caps())]);
let placement = StandardPlacement::new(&fold)
.with_intent_match(IntentMatchPolicy::AnyOfLocalCapabilities)
.with_intent_registry(IntentRegistry::defaults());
let target_caps = empty_caps().add_tag("hardware.cpu_cores=2");
let score = placement.score_intent_axis(&target_caps, &artifact);
assert_eq!(score, 0.0);
}
#[test]
fn intent_axis_zero_zeros_final_score_via_composition() {
let mut required = empty_caps();
required = with_metadata_pair(required, "intent", "ml-training");
let optional = empty_caps();
let artifact = daemon_with_intent(&required, &optional);
let target_caps = empty_caps();
let fold = {
let f = Fold::<CapabilityFold>::with_sweep_interval(std::time::Duration::ZERO);
let eid = crate::adapter::net::identity::EntityId::from_bytes([0u8; 32]);
let ad = CapabilityAnnouncement::new(0x1111, eid.clone(), 1, target_caps.clone());
capability_bridge::apply_legacy_announcement(&f, ad)
.expect("apply legacy announcement in fixture");
f
};
let placement = StandardPlacement::new(&fold)
.with_intent_match(IntentMatchPolicy::Strict)
.with_intent_registry(IntentRegistry::defaults());
let score = placement
.placement_score(&0x1111, &artifact)
.expect("hard-constraint check passes (required tag set is empty)");
assert_eq!(score, 0.0, "intent axis vetoes — final score 0.0");
}
fn with_metadata_pair(mut caps: CapabilitySet, key: &str, value: &str) -> CapabilitySet {
caps.metadata.insert(key.to_string(), value.to_string());
caps
}
#[test]
fn scope_axis_none_filter_returns_one() {
let fold = index_with(&[]);
let placement = StandardPlacement::new(&fold);
let target_caps = empty_caps().with_tenant_scope("foo");
assert_eq!(placement.score_scope_axis(&target_caps), 1.0);
}
#[test]
fn scope_axis_empty_filter_returns_one() {
let fold = index_with(&[]);
let placement = StandardPlacement::new(&fold).with_scope_filter(vec![]);
let target_caps = empty_caps().with_tenant_scope("foo");
assert_eq!(placement.score_scope_axis(&target_caps), 1.0);
}
#[test]
fn scope_axis_matches_full_form() {
let fold = index_with(&[]);
let placement = StandardPlacement::new(&fold)
.with_scope_filter(vec![ScopeLabel::new("scope:tenant:foo")]);
let target_caps = empty_caps().with_tenant_scope("foo");
assert_eq!(placement.score_scope_axis(&target_caps), 1.0);
}
#[test]
fn scope_axis_matches_body_form() {
let fold = index_with(&[]);
let placement =
StandardPlacement::new(&fold).with_scope_filter(vec![ScopeLabel::new("tenant:foo")]);
let target_caps = empty_caps().with_tenant_scope("foo");
assert_eq!(
placement.score_scope_axis(&target_caps),
1.0,
"body-form label must match the full scope tag"
);
}
#[test]
fn scope_axis_unscoped_target_returns_zero() {
let fold = index_with(&[]);
let placement =
StandardPlacement::new(&fold).with_scope_filter(vec![ScopeLabel::new("tenant:foo")]);
let target_caps = empty_caps().add_tag("hardware.gpu");
assert_eq!(placement.score_scope_axis(&target_caps), 0.0);
}
#[test]
fn scope_axis_matches_any_of_multiple_labels() {
let fold = index_with(&[]);
let placement = StandardPlacement::new(&fold).with_scope_filter(vec![
ScopeLabel::new("tenant:bar"),
ScopeLabel::new("region:us-east"),
ScopeLabel::new("tenant:foo"),
]);
let target_caps = empty_caps().with_tenant_scope("foo");
assert_eq!(placement.score_scope_axis(&target_caps), 1.0);
}
#[test]
fn scope_axis_no_match_returns_zero() {
let fold = index_with(&[]);
let placement =
StandardPlacement::new(&fold).with_scope_filter(vec![ScopeLabel::new("tenant:foo")]);
let target_caps = empty_caps().with_tenant_scope("bar");
assert_eq!(placement.score_scope_axis(&target_caps), 0.0);
}
#[test]
fn proximity_axis_no_threshold_returns_one() {
let fold = index_with(&[]);
let placement = StandardPlacement::new(&fold);
assert_eq!(placement.score_proximity_axis(&0x1111), 1.0);
}
#[test]
fn proximity_axis_threshold_without_lookup_returns_one() {
let fold = index_with(&[]);
let placement =
StandardPlacement::new(&fold).with_proximity_max_rtt(Duration::from_millis(50));
assert_eq!(placement.score_proximity_axis(&0x1111), 1.0);
}
#[test]
fn proximity_axis_unmeasured_target_returns_one() {
let fold = index_with(&[]);
let lookup = |_id: NodeId| -> Option<u64> { None };
let placement = StandardPlacement::new(&fold)
.with_proximity_max_rtt(Duration::from_millis(50))
.with_rtt_lookup(&lookup);
assert_eq!(placement.score_proximity_axis(&0x1111), 1.0);
}
#[test]
fn proximity_axis_rtt_under_threshold_returns_one() {
let fold = index_with(&[]);
let lookup = |_id: NodeId| -> Option<u64> { Some(10_000) }; let placement = StandardPlacement::new(&fold)
.with_proximity_max_rtt(Duration::from_millis(50))
.with_rtt_lookup(&lookup);
assert_eq!(placement.score_proximity_axis(&0x1111), 1.0);
}
#[test]
fn proximity_axis_rtt_at_threshold_returns_one_inclusive() {
let fold = index_with(&[]);
let lookup = |_id: NodeId| -> Option<u64> { Some(50_000) }; let placement = StandardPlacement::new(&fold)
.with_proximity_max_rtt(Duration::from_millis(50))
.with_rtt_lookup(&lookup);
assert_eq!(
placement.score_proximity_axis(&0x1111),
1.0,
"threshold is inclusive (≤)",
);
}
#[test]
fn proximity_axis_rtt_over_threshold_returns_zero() {
let fold = index_with(&[]);
let lookup = |_id: NodeId| -> Option<u64> { Some(100_000) }; let placement = StandardPlacement::new(&fold)
.with_proximity_max_rtt(Duration::from_millis(50))
.with_rtt_lookup(&lookup);
assert_eq!(placement.score_proximity_axis(&0x1111), 0.0);
}
#[test]
fn proximity_axis_per_candidate_via_lookup() {
let fold = index_with(&[]);
let lookup = |id: NodeId| -> Option<u64> {
match id {
0x1111 => Some(10_000), 0x2222 => Some(80_000), _ => None,
}
};
let placement = StandardPlacement::new(&fold)
.with_proximity_max_rtt(Duration::from_millis(50))
.with_rtt_lookup(&lookup);
assert_eq!(placement.score_proximity_axis(&0x1111), 1.0);
assert_eq!(placement.score_proximity_axis(&0x2222), 0.0);
}
#[test]
fn proximity_axis_zero_zeros_final_score() {
let target_caps = empty_caps();
let fold = {
let f = Fold::<CapabilityFold>::with_sweep_interval(std::time::Duration::ZERO);
let eid = crate::adapter::net::identity::EntityId::from_bytes([0u8; 32]);
let ad = CapabilityAnnouncement::new(0x1111, eid.clone(), 1, target_caps.clone());
capability_bridge::apply_legacy_announcement(&f, ad)
.expect("apply legacy announcement in fixture");
f
};
let lookup = |_id: NodeId| -> Option<u64> { Some(200_000) }; let placement = StandardPlacement::new(&fold)
.with_proximity_max_rtt(Duration::from_millis(50))
.with_rtt_lookup(&lookup);
let req = empty_caps();
let opt = empty_caps();
let artifact = daemon_artifact(&req, &opt);
let score = placement
.placement_score(&0x1111, &artifact)
.expect("hard-constraint check passes");
assert_eq!(score, 0.0, "proximity axis vetoes — final score 0.0");
}
#[test]
fn colocation_axis_ignore_returns_one() {
let fold = index_with(&[]);
let placement =
StandardPlacement::new(&fold).with_colocation_policy(ColocationPolicy::Ignore);
let mut required = empty_caps();
required = with_metadata_pair(required, "colocate-with", "abc123");
let optional = empty_caps();
let artifact = daemon_with_intent(&required, &optional);
let target_caps = empty_caps();
assert_eq!(
placement.score_colocation_axis(&target_caps, &artifact),
1.0
);
}
#[test]
fn colocation_axis_soft_no_metadata_returns_one() {
let fold = index_with(&[]);
let placement =
StandardPlacement::new(&fold).with_colocation_policy(ColocationPolicy::SoftPreference);
let required = empty_caps();
let optional = empty_caps();
let artifact = daemon_with_intent(&required, &optional);
let target_caps = empty_caps();
assert_eq!(
placement.score_colocation_axis(&target_caps, &artifact),
1.0
);
}
#[test]
fn colocation_axis_soft_target_hosts_returns_one() {
let fold = index_with(&[]);
let placement =
StandardPlacement::new(&fold).with_colocation_policy(ColocationPolicy::SoftPreference);
let mut required = empty_caps();
required = with_metadata_pair(required, "colocate-with", "abc123");
let optional = empty_caps();
let artifact = daemon_with_intent(&required, &optional);
let target_caps = empty_caps().require_chain("abc123");
assert_eq!(
placement.score_colocation_axis(&target_caps, &artifact),
1.0
);
}
#[test]
fn colocation_axis_soft_target_misses_returns_penalty() {
let fold = index_with(&[]);
let placement =
StandardPlacement::new(&fold).with_colocation_policy(ColocationPolicy::SoftPreference);
let mut required = empty_caps();
required = with_metadata_pair(required, "colocate-with", "abc123");
let optional = empty_caps();
let artifact = daemon_with_intent(&required, &optional);
let target_caps = empty_caps();
let score = placement.score_colocation_axis(&target_caps, &artifact);
assert!(
(score - 0.7).abs() < 1e-6,
"soft penalty expected ~0.7, got {score}"
);
}
#[test]
fn colocation_axis_strict_key_vetoes_under_soft_policy() {
let fold = index_with(&[]);
let placement =
StandardPlacement::new(&fold).with_colocation_policy(ColocationPolicy::SoftPreference);
let mut required = empty_caps();
required = with_metadata_pair(required, "colocate-with-strict", "abc123");
let optional = empty_caps();
let artifact = daemon_with_intent(&required, &optional);
let target_caps = empty_caps();
assert_eq!(
placement.score_colocation_axis(&target_caps, &artifact),
0.0,
"strict-key vetoes regardless of policy",
);
}
#[test]
fn colocation_axis_strict_policy_upgrades_soft_key_to_veto() {
let fold = index_with(&[]);
let placement =
StandardPlacement::new(&fold).with_colocation_policy(ColocationPolicy::StrictRequired);
let mut required = empty_caps();
required = with_metadata_pair(required, "colocate-with", "abc123");
let optional = empty_caps();
let artifact = daemon_with_intent(&required, &optional);
let target_caps = empty_caps();
assert_eq!(
placement.score_colocation_axis(&target_caps, &artifact),
0.0
);
}
#[test]
fn colocation_axis_strict_policy_target_hosts_returns_one() {
let fold = index_with(&[]);
let placement =
StandardPlacement::new(&fold).with_colocation_policy(ColocationPolicy::StrictRequired);
let mut required = empty_caps();
required = with_metadata_pair(required, "colocate-with", "abc123");
let optional = empty_caps();
let artifact = daemon_with_intent(&required, &optional);
let target_caps = empty_caps().require_chain("abc123");
assert_eq!(
placement.score_colocation_axis(&target_caps, &artifact),
1.0
);
}
#[test]
fn colocation_axis_tip_form_satisfies_match() {
let fold = index_with(&[]);
let placement =
StandardPlacement::new(&fold).with_colocation_policy(ColocationPolicy::SoftPreference);
let mut required = empty_caps();
required = with_metadata_pair(required, "colocate-with", "abc123");
let optional = empty_caps();
let artifact = daemon_with_intent(&required, &optional);
let target_caps = empty_caps().require_chain_tip("abc123", 42);
assert_eq!(
placement.score_colocation_axis(&target_caps, &artifact),
1.0
);
}
#[test]
fn colocation_axis_zero_zeros_final_score() {
let target_caps = empty_caps();
let fold = {
let f = Fold::<CapabilityFold>::with_sweep_interval(std::time::Duration::ZERO);
let eid = crate::adapter::net::identity::EntityId::from_bytes([0u8; 32]);
let ad = CapabilityAnnouncement::new(0x1111, eid.clone(), 1, target_caps.clone());
capability_bridge::apply_legacy_announcement(&f, ad)
.expect("apply legacy announcement in fixture");
f
};
let placement =
StandardPlacement::new(&fold).with_colocation_policy(ColocationPolicy::StrictRequired);
let mut required = empty_caps();
required = with_metadata_pair(required, "colocate-with", "abc123");
let optional = empty_caps();
let artifact = daemon_with_intent(&required, &optional);
let score = placement
.placement_score(&0x1111, &artifact)
.expect("hard-constraint check passes");
assert_eq!(score, 0.0);
}
#[test]
fn resource_axis_compute_no_data_returns_one() {
let fold = index_with(&[]);
let placement = StandardPlacement::new(&fold).with_resource_axis(ResourceAxis::Compute);
let target_caps = empty_caps();
let req = empty_caps();
let opt = empty_caps();
let artifact = daemon_artifact(&req, &opt);
assert_eq!(placement.score_resource_axis(&target_caps, &artifact), 1.0);
}
#[test]
fn resource_axis_compute_cpu_at_reference_scores_half() {
let fold = index_with(&[]);
let placement = StandardPlacement::new(&fold).with_resource_axis(ResourceAxis::Compute);
let target_caps = empty_caps().add_tag("hardware.cpu_cores=8");
let req = empty_caps();
let opt = empty_caps();
let artifact = daemon_artifact(&req, &opt);
let score = placement.score_resource_axis(&target_caps, &artifact);
assert!(
(score - 0.5).abs() < 1e-6,
"8 cores at 8-reference scores 0.5; got {score}"
);
}
#[test]
fn resource_axis_compute_monotonic_in_capacity() {
let fold = index_with(&[]);
let placement = StandardPlacement::new(&fold).with_resource_axis(ResourceAxis::Compute);
let req = empty_caps();
let opt = empty_caps();
let artifact = daemon_artifact(&req, &opt);
let small = empty_caps().add_tag("hardware.cpu_cores=4");
let large = empty_caps().add_tag("hardware.cpu_cores=64");
let small_score = placement.score_resource_axis(&small, &artifact);
let large_score = placement.score_resource_axis(&large, &artifact);
assert!(
large_score > small_score,
"64-core node ({large_score}) must score higher than 4-core ({small_score})"
);
}
#[test]
fn resource_axis_compute_averages_present_components() {
let fold = index_with(&[]);
let placement = StandardPlacement::new(&fold).with_resource_axis(ResourceAxis::Compute);
let req = empty_caps();
let opt = empty_caps();
let artifact = daemon_artifact(&req, &opt);
let three_components = empty_caps()
.add_tag("hardware.cpu_cores=8")
.add_tag("hardware.memory_gb=16")
.add_tag("hardware.gpu.vram_gb=16");
let s_three = placement.score_resource_axis(&three_components, &artifact);
assert!(
(s_three - 0.5).abs() < 1e-6,
"3-comp avg got {s_three}, want 0.5"
);
let cpu_only = empty_caps().add_tag("hardware.cpu_cores=8");
let s_one = placement.score_resource_axis(&cpu_only, &artifact);
assert!((s_one - 0.5).abs() < 1e-6, "1-comp got {s_one}, want 0.5");
}
#[test]
fn resource_axis_storage_at_reference_scores_half() {
let fold = index_with(&[]);
let placement = StandardPlacement::new(&fold).with_resource_axis(ResourceAxis::Storage);
let target_caps = empty_caps().add_tag("dataforts.capacity_gb=1000");
let req = empty_caps();
let opt = empty_caps();
let artifact = daemon_artifact(&req, &opt);
let score = placement.score_resource_axis(&target_caps, &artifact);
assert!(
(score - 0.5).abs() < 1e-6,
"1 TB at 1 TB reference scores 0.5; got {score}"
);
}
#[test]
fn resource_axis_storage_no_data_returns_one() {
let fold = index_with(&[]);
let placement = StandardPlacement::new(&fold).with_resource_axis(ResourceAxis::Storage);
let target_caps = empty_caps();
let req = empty_caps();
let opt = empty_caps();
let artifact = daemon_artifact(&req, &opt);
assert_eq!(placement.score_resource_axis(&target_caps, &artifact), 1.0);
}
#[test]
fn resource_axis_both_uses_only_axes_with_data() {
let fold = index_with(&[]);
let placement = StandardPlacement::new(&fold).with_resource_axis(ResourceAxis::Both);
let target_caps = empty_caps().add_tag("hardware.cpu_cores=8");
let req = empty_caps();
let opt = empty_caps();
let artifact = daemon_artifact(&req, &opt);
let score = placement.score_resource_axis(&target_caps, &artifact);
assert!(
(score - 0.5).abs() < 1e-6,
"Both with only compute data should return compute score; got {score}"
);
let target_caps = empty_caps().add_tag("dataforts.capacity_gb=500");
let score = placement.score_resource_axis(&target_caps, &artifact);
let expected = saturating_score(500.0, 1000.0);
assert!(
(score - expected).abs() < 1e-6,
"Both with only storage data should return storage score; got {score}"
);
let target_caps = empty_caps()
.add_tag("hardware.cpu_cores=8")
.add_tag("dataforts.capacity_gb=500");
let score = placement.score_resource_axis(&target_caps, &artifact);
let expected = (0.5 + saturating_score(500.0, 1000.0)) / 2.0;
assert!(
(score - expected).abs() < 1e-6,
"Both with both axes' data averages; got {score}, expected {expected}"
);
let target_caps = empty_caps();
assert_eq!(placement.score_resource_axis(&target_caps, &artifact), 1.0);
}
#[test]
fn resource_axis_overflow_value_treated_as_no_data() {
let fold = index_with(&[]);
let placement = StandardPlacement::new(&fold).with_resource_axis(ResourceAxis::Compute);
let target_caps = empty_caps().add_tag("hardware.cpu_cores=1e308");
let req = empty_caps();
let opt = empty_caps();
let artifact = daemon_artifact(&req, &opt);
let score = placement.score_resource_axis(&target_caps, &artifact);
assert_eq!(
score, 1.0,
"overflow value should be treated as no-data, not as 0.0; got {score}",
);
let target_caps = empty_caps().add_tag("hardware.cpu_cores=8");
let score = placement.score_resource_axis(&target_caps, &artifact);
assert!(
(score - 0.5).abs() < 1e-6,
"sane value still scores normally; got {score}",
);
}
#[test]
fn resource_axis_compute_malformed_value_treated_as_no_data() {
let fold = index_with(&[]);
let placement = StandardPlacement::new(&fold).with_resource_axis(ResourceAxis::Compute);
let target_caps = empty_caps().add_tag("hardware.cpu_cores=lots");
let req = empty_caps();
let opt = empty_caps();
let artifact = daemon_artifact(&req, &opt);
let score = placement.score_resource_axis(&target_caps, &artifact);
assert_eq!(score, 1.0);
}
#[test]
fn anti_affinity_no_stats_returns_one() {
let fold = index_with(&[]);
let placement = StandardPlacement::new(&fold);
assert_eq!(placement.score_anti_affinity_axis(&0x1111), 1.0);
}
#[test]
fn anti_affinity_target_without_data_returns_one() {
let fold = index_with(&[]);
let stats = |_id: NodeId| -> Option<f32> { None };
let placement = StandardPlacement::new(&fold).with_leadership_stats(&stats);
assert_eq!(placement.score_anti_affinity_axis(&0x1111), 1.0);
}
#[test]
fn anti_affinity_under_threshold_returns_one() {
let fold = index_with(&[]);
let stats = |_id: NodeId| -> Option<f32> { Some(0.20) };
let placement = StandardPlacement::new(&fold).with_leadership_stats(&stats);
assert_eq!(placement.score_anti_affinity_axis(&0x1111), 1.0);
}
#[test]
fn anti_affinity_at_threshold_returns_one_inclusive() {
let fold = index_with(&[]);
let stats = |_id: NodeId| -> Option<f32> { Some(0.30) };
let placement = StandardPlacement::new(&fold).with_leadership_stats(&stats);
assert_eq!(placement.score_anti_affinity_axis(&0x1111), 1.0);
}
#[test]
fn anti_affinity_over_threshold_returns_penalty() {
let fold = index_with(&[]);
let stats = |_id: NodeId| -> Option<f32> { Some(0.50) };
let placement = StandardPlacement::new(&fold).with_leadership_stats(&stats);
let score = placement.score_anti_affinity_axis(&0x1111);
assert!(
(score - 0.4).abs() < 1e-6,
"default penalty 0.4; got {score}"
);
}
#[test]
fn anti_affinity_per_candidate_via_stats() {
let fold = index_with(&[]);
let stats = |id: NodeId| -> Option<f32> {
match id {
0x1111 => Some(0.10), 0x2222 => Some(0.50), _ => None,
}
};
let placement = StandardPlacement::new(&fold).with_leadership_stats(&stats);
assert_eq!(placement.score_anti_affinity_axis(&0x1111), 1.0);
assert!((placement.score_anti_affinity_axis(&0x2222) - 0.4).abs() < 1e-6);
}
#[test]
fn anti_affinity_treats_nan_concentration_as_no_data() {
let fold = index_with(&[]);
let stats = |_id: NodeId| -> Option<f32> { Some(f32::NAN) };
let placement = StandardPlacement::new(&fold).with_leadership_stats(&stats);
assert_eq!(placement.score_anti_affinity_axis(&0x1111), 1.0);
let stats_inf = |_id: NodeId| -> Option<f32> { Some(f32::INFINITY) };
let placement = StandardPlacement::new(&fold).with_leadership_stats(&stats_inf);
assert_eq!(placement.score_anti_affinity_axis(&0x1111), 1.0);
}
#[test]
fn saturating_score_rejects_non_finite_inputs() {
assert_eq!(saturating_score(f32::NAN, 8.0), 0.0);
assert_eq!(saturating_score(8.0, f32::NAN), 0.0);
assert_eq!(saturating_score(f32::INFINITY, 8.0), 0.0);
assert_eq!(saturating_score(f32::NEG_INFINITY, 8.0), 0.0);
let s = saturating_score(8.0, 8.0);
assert!((s - 0.5).abs() < 1e-6);
}
#[test]
fn anti_affinity_defensive_clamps_misconfigured_penalty() {
let fold = index_with(&[]);
let stats = |_id: NodeId| -> Option<f32> { Some(0.50) };
let mut placement = StandardPlacement::new(&fold).with_leadership_stats(&stats);
placement.anti_affinity.leadership_concentration_penalty = f32::NAN;
assert_eq!(placement.score_anti_affinity_axis(&0x1111), 0.0);
placement.anti_affinity.leadership_concentration_penalty = 2.0;
assert_eq!(placement.score_anti_affinity_axis(&0x1111), 1.0);
placement.anti_affinity.leadership_concentration_penalty = -0.5;
assert_eq!(placement.score_anti_affinity_axis(&0x1111), 0.0);
}
#[test]
fn anti_affinity_penalty_multiplies_through_composition() {
let target_caps = empty_caps();
let fold = {
let f = Fold::<CapabilityFold>::with_sweep_interval(std::time::Duration::ZERO);
let eid = crate::adapter::net::identity::EntityId::from_bytes([0u8; 32]);
let ad = CapabilityAnnouncement::new(0x1111, eid.clone(), 1, target_caps.clone());
capability_bridge::apply_legacy_announcement(&f, ad)
.expect("apply legacy announcement in fixture");
f
};
let stats = |_id: NodeId| -> Option<f32> { Some(0.50) };
let placement = StandardPlacement::new(&fold).with_leadership_stats(&stats);
let req = empty_caps();
let opt = empty_caps();
let artifact = daemon_artifact(&req, &opt);
let score = placement
.placement_score(&0x1111, &artifact)
.expect("hard-constraint check passes");
assert!(
(score - 0.4).abs() < 1e-6,
"anti-affinity penalty (0.4) is the only non-1.0 axis; got {score}"
);
}
#[test]
fn resource_axis_low_score_multiplies_through_composition() {
let target_caps = empty_caps().add_tag("hardware.cpu_cores=2");
let fold = {
let f = Fold::<CapabilityFold>::with_sweep_interval(std::time::Duration::ZERO);
let eid = crate::adapter::net::identity::EntityId::from_bytes([0u8; 32]);
let ad = CapabilityAnnouncement::new(0x1111, eid.clone(), 1, target_caps.clone());
capability_bridge::apply_legacy_announcement(&f, ad)
.expect("apply legacy announcement in fixture");
f
};
let placement = StandardPlacement::new(&fold).with_resource_axis(ResourceAxis::Compute);
let req = empty_caps();
let opt = empty_caps();
let artifact = daemon_artifact(&req, &opt);
let score = placement
.placement_score(&0x1111, &artifact)
.expect("hard-constraint check passes");
assert!(
(score - 0.2).abs() < 1e-6,
"2-core compute score 0.2 multiplies to final; got {score}"
);
}
#[test]
fn colocation_axis_soft_penalty_multiplies_through_composition() {
let target_caps = empty_caps();
let fold = {
let f = Fold::<CapabilityFold>::with_sweep_interval(std::time::Duration::ZERO);
let eid = crate::adapter::net::identity::EntityId::from_bytes([0u8; 32]);
let ad = CapabilityAnnouncement::new(0x1111, eid.clone(), 1, target_caps.clone());
capability_bridge::apply_legacy_announcement(&f, ad)
.expect("apply legacy announcement in fixture");
f
};
let placement =
StandardPlacement::new(&fold).with_colocation_policy(ColocationPolicy::SoftPreference);
let mut required = empty_caps();
required = with_metadata_pair(required, "colocate-with", "abc123");
let optional = empty_caps();
let artifact = daemon_with_intent(&required, &optional);
let score = placement
.placement_score(&0x1111, &artifact)
.expect("hard-constraint check passes");
assert!(
(score - 0.7).abs() < 1e-6,
"soft penalty multiplies through (other axes 1.0); got {score}"
);
}
#[test]
fn scope_axis_zero_zeros_final_score() {
let target_caps = empty_caps().add_tag("hardware.gpu");
let fold = {
let f = Fold::<CapabilityFold>::with_sweep_interval(std::time::Duration::ZERO);
let eid = crate::adapter::net::identity::EntityId::from_bytes([0u8; 32]);
let ad = CapabilityAnnouncement::new(0x1111, eid.clone(), 1, target_caps.clone());
capability_bridge::apply_legacy_announcement(&f, ad)
.expect("apply legacy announcement in fixture");
f
};
let placement =
StandardPlacement::new(&fold).with_scope_filter(vec![ScopeLabel::new("tenant:foo")]);
let req = empty_caps();
let opt = empty_caps();
let artifact = daemon_artifact(&req, &opt);
let score = placement
.placement_score(&0x1111, &artifact)
.expect("hard-constraint check passes (empty required tags)");
assert_eq!(score, 0.0, "scope axis vetoes — final score 0.0");
}
#[test]
fn standard_chain_and_replica_artifacts_pass_through_today() {
let fold = index_with(&[(0x1111, empty_caps())]);
let placement = StandardPlacement::new(&fold);
let chain_caps = empty_caps();
let chain = Artifact::Chain {
origin_hash: [1u8; 32],
capabilities: &chain_caps,
};
assert_eq!(placement.placement_score(&0x1111, &chain), Some(1.0));
let channel = crate::adapter::net::channel::ChannelName::new("rep").unwrap();
let replica_caps = empty_caps();
let replica = Artifact::Replica {
channel: &channel,
capabilities: &replica_caps,
};
assert_eq!(placement.placement_score(&0x1111, &replica), Some(1.0));
}
fn caps_with_blob_storage(disk_free_gb: u64) -> CapabilitySet {
CapabilitySet::new()
.add_tag("dataforts.blob.storage")
.add_tag(format!("dataforts.blob.disk_total_gb={}", disk_free_gb))
.add_tag(format!("dataforts.blob.disk_free_gb={}", disk_free_gb))
}
#[test]
fn standard_blob_placement_rejects_node_without_blob_storage() {
let fold = index_with(&[(0x1111, empty_caps())]);
let placement = StandardPlacement::new(&fold);
let blob = Artifact::Blob {
blob_hash: [0xAA; 32],
size_bytes: 1024,
};
assert_eq!(placement.placement_score(&0x1111, &blob), None);
}
#[test]
fn standard_blob_placement_admits_storage_participating_node() {
let fold = index_with(&[(0x1111, caps_with_blob_storage(100))]);
let placement = StandardPlacement::new(&fold);
let blob = Artifact::Blob {
blob_hash: [0xBB; 32],
size_bytes: 1024,
};
let score = placement.placement_score(&0x1111, &blob);
assert!(
score.is_some(),
"expected placement to admit, got {:?}",
score
);
assert_eq!(score, Some(1.0));
}
#[test]
fn standard_blob_placement_rejects_insufficient_disk_free() {
let fold = index_with(&[(0x1111, caps_with_blob_storage(2))]);
let placement = StandardPlacement::new(&fold);
let blob = Artifact::Blob {
blob_hash: [0xCC; 32],
size_bytes: 10 * (1 << 30), };
assert_eq!(placement.placement_score(&0x1111, &blob), None);
}
#[test]
fn standard_blob_placement_rejects_unhealthy_node() {
let mut unhealthy_caps = CapabilitySet::new()
.add_tag("dataforts.blob.storage")
.add_tag("dataforts.blob.disk_total_gb=100")
.add_tag("dataforts.blob.disk_free_gb=100");
unhealthy_caps
.tags
.insert(crate::adapter::net::behavior::Tag::Reserved {
prefix: "dataforts:".to_owned(),
body: "blob-storage-unhealthy".to_owned(),
});
let fold = index_with(&[(0x1111, unhealthy_caps)]);
let placement = StandardPlacement::new(&fold);
let blob = Artifact::Blob {
blob_hash: [0xDD; 32],
size_bytes: 1024,
};
assert_eq!(placement.placement_score(&0x1111, &blob), None);
}
#[test]
fn standard_blob_placement_disk_free_gb_rounds_up() {
let one_and_a_half_gib: u64 = (1 << 30) + (1 << 29);
let fold = index_with(&[(0x2222, caps_with_blob_storage(1))]);
let placement = StandardPlacement::new(&fold);
let blob = Artifact::Blob {
blob_hash: [0xEE; 32],
size_bytes: one_and_a_half_gib,
};
assert_eq!(placement.placement_score(&0x2222, &blob), None);
let fold2 = index_with(&[(0x3333, caps_with_blob_storage(2))]);
let placement2 = StandardPlacement::new(&fold2);
assert!(placement2.placement_score(&0x3333, &blob).is_some());
}
use crate::adapter::net::behavior::placement_registry::global_placement_filter_registry;
struct FixedScoreFilter(Option<f32>);
impl PlacementFilter for FixedScoreFilter {
fn placement_score(&self, _: &NodeId, _: &Artifact<'_>) -> Option<f32> {
self.0
}
}
struct FilterGuard {
id: String,
}
impl Drop for FilterGuard {
fn drop(&mut self) {
global_placement_filter_registry().unregister(&self.id);
}
}
fn with_registered_filter<F: FnOnce(&str)>(
id: &str,
filter: Arc<dyn PlacementFilter>,
body: F,
) {
let reg = global_placement_filter_registry();
let _ = reg.unregister(id); assert!(
reg.register(id.to_string(), filter, "test"),
"register {id}"
);
let _guard = FilterGuard { id: id.to_string() };
body(id);
}
#[test]
fn standard_placement_no_custom_filter_acts_as_identity_axis() {
let fold = index_with(&[(0x1111, empty_caps())]);
let placement = StandardPlacement::new(&fold);
assert!(placement.custom_filter_id.is_none());
let req = empty_caps();
let opt = empty_caps();
let artifact = daemon_artifact(&req, &opt);
assert_eq!(placement.placement_score(&0x1111, &artifact), Some(1.0));
}
#[test]
fn standard_placement_custom_filter_one_is_identity() {
let fold = index_with(&[(0x2222, empty_caps())]);
let id = "pf-test-slice5-identity";
with_registered_filter(id, Arc::new(FixedScoreFilter(Some(1.0))), |id| {
let placement = StandardPlacement::new(&fold).with_custom_filter_id(id);
let req = empty_caps();
let opt = empty_caps();
let artifact = daemon_artifact(&req, &opt);
assert_eq!(
placement.placement_score(&0x2222, &artifact),
Some(1.0),
"Some(1.0) custom score should compose identically",
);
});
}
#[test]
fn standard_placement_custom_filter_score_composes_multiplicatively() {
let fold = index_with(&[(0x3333, empty_caps())]);
let id = "pf-test-slice5-multiply";
with_registered_filter(id, Arc::new(FixedScoreFilter(Some(0.5))), |id| {
let placement = StandardPlacement::new(&fold).with_custom_filter_id(id);
let req = empty_caps();
let opt = empty_caps();
let artifact = daemon_artifact(&req, &opt);
let score = placement.placement_score(&0x3333, &artifact);
assert_eq!(score, Some(0.5));
});
}
#[test]
fn standard_placement_custom_filter_none_is_hard_veto() {
let fold = index_with(&[(0x4444, empty_caps())]);
let id = "pf-test-slice5-veto";
with_registered_filter(id, Arc::new(FixedScoreFilter(None)), |id| {
let placement = StandardPlacement::new(&fold).with_custom_filter_id(id);
let req = empty_caps();
let opt = empty_caps();
let artifact = daemon_artifact(&req, &opt);
assert_eq!(
placement.placement_score(&0x4444, &artifact),
None,
"None from custom filter must veto the candidate",
);
});
}
#[test]
fn standard_placement_unregistered_custom_filter_id_vetoes() {
let fold = index_with(&[(0x5555, empty_caps())]);
let placement = StandardPlacement::new(&fold)
.with_custom_filter_id("pf-test-slice5-NEVER-REGISTERED-xyz");
let req = empty_caps();
let opt = empty_caps();
let artifact = daemon_artifact(&req, &opt);
assert_eq!(
placement.placement_score(&0x5555, &artifact),
None,
"unregistered custom_filter_id must veto",
);
}
#[test]
fn standard_placement_custom_filter_composes_with_in_tree_axes() {
let fold = index_with(&[(0x6666, empty_caps())]);
let id = "pf-test-slice5-compose";
with_registered_filter(id, Arc::new(FixedScoreFilter(Some(1.0))), |id| {
let placement = StandardPlacement::new(&fold)
.with_custom_filter_id(id)
.with_scope_filter(vec![ScopeLabel::new("scope:tenant:foo")]);
let req = empty_caps();
let opt = empty_caps();
let artifact = daemon_artifact(&req, &opt);
assert_eq!(
placement.placement_score(&0x6666, &artifact),
Some(0.0),
"scope-axis 0.0 zeroes the composition even when custom = 1.0",
);
});
}
#[test]
fn standard_placement_custom_filter_can_query_index_without_deadlock() {
struct ReentrantFilter {
fold: Arc<Fold<CapabilityFold>>,
}
impl PlacementFilter for ReentrantFilter {
fn placement_score(&self, target: &NodeId, _artifact: &Artifact<'_>) -> Option<f32> {
let legacy = crate::adapter::net::behavior::capability::CapabilityFilter::default();
let _ = capability_bridge::find_nodes_matching(&self.fold, &legacy);
let _ = capability_bridge::synthesize_capability_set(&self.fold, *target);
Some(0.75)
}
}
let fold = index_with(&[(0x7777, empty_caps())]);
let id = "pf-test-N4-reentrant";
let filter = Arc::new(ReentrantFilter { fold: fold.clone() });
with_registered_filter(id, filter, |id| {
let placement = StandardPlacement::new(&fold).with_custom_filter_id(id);
let req = empty_caps();
let opt = empty_caps();
let artifact = daemon_artifact(&req, &opt);
assert_eq!(
placement.placement_score(&0x7777, &artifact),
Some(0.75),
"reentrant custom filter must complete without deadlock",
);
});
}
}