diff --git a/crates/eureka-pipeline/src/lib.rs b/crates/eureka-pipeline/src/lib.rs index a071572..11f4f65 100644 --- a/crates/eureka-pipeline/src/lib.rs +++ b/crates/eureka-pipeline/src/lib.rs @@ -96,6 +96,12 @@ impl Absent for Option { } } +impl Absent for bool { + fn absent(&self) -> bool { + !*self + } +} + impl Absent for Vec { fn absent(&self) -> bool { self.is_empty() @@ -591,7 +597,10 @@ fn pulse_is_well_formed(pulse: &PipelinePulse, at: &str) -> Result<(), PipelineR { return Err(format_error(&format!("{at}.urgency_permille"), &urgency.to_string())); } - if pulse.tempo_vote_beat_s.is_none() && pulse.urgency_permille.is_none() { + if pulse.tempo_vote_withdrawn && pulse.tempo_vote_beat_s.is_some() { + return Err(format_error(&format!("{at}.tempo_vote_withdrawn"), "a pulse that votes a beat and withdraws the vote")); + } + if pulse.tempo_vote_beat_s.is_none() && !pulse.tempo_vote_withdrawn && pulse.urgency_permille.is_none() { return Err(format_error(&format!("{at}.tempo_vote_beat_s"), "a pulse that votes and declares nothing")); } Ok(()) @@ -736,12 +745,14 @@ value_types! { budget_usd: Short, claims: Vec[64], campaigns: Vec[8], } => run_is_well_formed /// One Mind's heartbeat vote, in her own mind: the beat she wants (the swarm's - /// tempo is the lower median of every Mind's newest vote) and the urgency she - /// declares for herself until her next Persona turn. Either may be absent, not - /// both. Instance-rooted: the key is `:pulse: