made-core 0.3.0

Domain core of MADE: entities, value objects, events, ports. No IO.
Documentation
//! [`ScoringPort`] — domain-agnostic aggregation of validator reports
//! into a single [`Score`] for a proposal.
//!
//! Keeping scoring behind a trait lets operators plug their own policy
//! (weighted average, fail-fast on any failed report, learned
//! combinator, …) without touching the core.

use async_trait::async_trait;

use crate::entities::{RankedOutcome, ValidatorReport};
use crate::error::DomainError;
use crate::value_objects::{Discrimination, Score};

#[async_trait]
pub trait ScoringPort: Send + Sync {
    /// Combine a list of validator reports into a single score.
    async fn score(&self, reports: &[ValidatorReport]) -> Result<Score, DomainError>;

    /// Report whether this policy's ranking re-ordered the winner relative
    /// to a structural baseline — the basis for the judge-discrimination
    /// metric. `ranked` is the policy's final ranking (score-descending).
    ///
    /// The default is `None`: a policy with no notion of a baseline (plain
    /// pass-fraction scoring) has nothing to discriminate. A judge-aware
    /// policy overrides this, comparing its winner against the proposal a
    /// judge-free ranking would have picked. `None` means "do not record",
    /// keeping the metric specific to policies that add a ranking signal.
    fn discrimination(&self, _ranked: &[RankedOutcome]) -> Option<Discrimination> {
        None
    }
}