kcode-speaker-model 0.2.0

Deterministic cohort-scoped speaker model fitting and identification for Kennedy
Documentation
# kcode-speaker-model 0.2.0

Deterministic, cohort-scoped fitting and identification over the frozen 24-field `kcode-speaker-types` contract.

## API

```rust
pub const ALL_24: FeatureMask;

pub struct ModelConfig {
    pub mask: FeatureMask,
    pub components: u8,
    pub relevance: f64,
    pub variance_floor: f64,
    pub absolute_threshold: f64,
    pub margin_threshold: f64,
}

pub struct FitInput<'a> {
    pub cohort_id: &'a Key,
    pub samples: &'a [LabeledSample],
    pub config: ModelConfig,
}

pub struct ModelSnapshot { /* private immutable state */ }

pub struct CandidateScore {
    pub speaker_id: Key,
    pub llr: f64,
}

pub enum Decision {
    Known { speaker_id: Key },
    Unknown,
}

pub struct Identification {
    pub decision: Decision,
    pub best: CandidateScore,
    pub runner_up: Option<CandidateScore>,
    pub absolute_pass: bool,
    pub margin_pass: bool,
}

pub fn fit(input: FitInput<'_>) -> Result<ModelSnapshot, ModelError>;
pub fn identify(
    model: &ModelSnapshot,
    cohort_id: &Key,
    features: &FeatureVector,
) -> Result<Identification, ModelError>;
pub fn encode(model: &ModelSnapshot) -> Result<Vec<u8>, ModelError>;
pub fn decode(bytes: &[u8]) -> Result<ModelSnapshot, ModelError>;
```

`ALL_24` selects bits 0 through `FEATURE_COUNT - 1`. Other scoring masks are caller-supplied validated `FeatureMask` values; this package provides no historical extractor-specific subsets.

## Fitting and scoring

`fit` requires nonempty, uniquely identified samples belonging to the requested cohort, at least one represented speaker, `1..=samples.len()` components, positive finite relevance and variance floor, finite thresholds, and nonzero finite population standard deviation for every selected feature. Samples have equal weight. Selected features follow ascending frozen mask index. Normalization is learned only from the supplied training rows.

Fitting uses a deterministic global diagonal GMM-UBM with 200 maximum EM updates and `1e-8` relative tolerance; a nonconverged result is rejected. UBM responsibilities produce per-speaker component occupancy and first-order sums. Speaker models adapt component means only with the configured relevance factor while retaining UBM weights and variances.

`identify` requires the snapshot cohort and scores each speaker by speaker-model log likelihood minus UBM log likelihood. Scores are ordered by descending LLR with speaker-key tie order. `Known` requires both `best.llr >= absolute_threshold` and `best.llr - runner_up.llr >= margin_threshold`; equality passes. With one enrolled speaker, `runner_up` is `None`, `margin_pass` is true, and only the absolute gate controls. Identification is read-only.

## Snapshot identity

Snapshots are opaque, immutable, cohort-bound, manifest-hashed, and wire-versioned. The SHA-256 manifest is computed after canonical sample-ID ordering and uses tagged, length-delimited encoding for every training-row identity field: sample, attempt, speaker, cohort, and group IDs; clip object ID; primary language; recording kind; usable speech; recording quality; and all `FEATURE_COUNT` feature bytes.

`encode` emits deterministic versioned JSON. `decode` accepts only the current 24-field snapshot version and validates configuration, dimensions, finite values, component statistics, speaker ordering, sample counts, and mean-only MAP state before returning a model. Earlier 35-field artifacts are incompatible. Any training-row change requires a fresh `fit`.

This library performs no persistence, provider work, replay, evaluation-system work, publication, adoption, or deployment.