# K1 audio classification
Durable facade for the exact KTO subsystem `audio-classification`. The projection dependency owns local status reduction and persistence. This facade owns subsystem registration, startup recovery, transaction submission, Object loading, and provider-worker lifecycle; it does not construct providers, expose provider controls, deploy services, or claim remote-call behavior.
## Public API
The crate re-exports `ExecutedAnalysis`, `FragmentId`, `FragmentStageV1`, `SpeakerLabelV1`, `OverallState`, `StageState`, `LlmJobState`, `StageStatus`, `LlmJobStatus`, and `FragmentStatus` from the projection package.
```rust
pub enum OverallState { Queued, Running, Failed, Completed, Confirmed, Discarded }
pub enum StageState { Pending, Running, Succeeded, Failed }
pub enum LlmJobState { Running, Succeeded, Failed }
pub struct StageStatus {
pub stage: FragmentStageV1,
pub state: StageState,
}
pub struct LlmJobStatus {
pub attempt: u32,
pub sequence: u64,
pub stage: FragmentStageV1,
pub name: String,
pub state: LlmJobState,
}
pub struct FragmentStatus {
pub state: OverallState,
pub queue: StageStatus,
pub transcript: StageStatus,
pub speaker_labels: StageStatus,
pub speaker_features: StageStatus,
pub structuring: StageStatus,
pub label_confirmation: StageStatus,
pub attempt_count: u32,
pub jobs: Vec<LlmJobStatus>,
pub interim_txid: Option<FragmentId>,
pub analysis: Option<ExecutedAnalysis>,
pub confirmed_labels: Vec<SpeakerLabelV1>,
pub final_transcript: Option<String>,
pub errors: Vec<String>,
pub errors_truncated: bool,
}
pub struct AudioClassification;
impl AudioClassification {
pub fn open(root: &Path, ordering: Arc<K1TxnOrdering>, peering: Arc<K1Peering>, objects: Arc<K1Objects>, analyzer: Analyzer) -> Result<Self, String>;
pub fn submit(&self, ogg_bytes: &[u8]) -> Result<FragmentId, String>;
pub fn status(&self, fragment_id: FragmentId) -> Result<Option<FragmentStatus>, String>;
pub fn retry(&self, fragment_id: FragmentId) -> Result<(), String>;
pub fn discard(&self, fragment_id: FragmentId) -> Result<(), String>;
pub fn submit_labels(&self, fragment_id: FragmentId, labels: Vec<SpeakerLabelV1>) -> Result<(), String>;
}
```
The state enums implement `Copy`, `Clone`, `Debug`, `PartialEq`, and `Eq`. The status structs implement `Clone`, `Debug`, and `PartialEq`, and also `Eq` where their fields permit it. Re-exported values retain the defining projection and format contracts; their persistence-oriented serialization is not an interchange promise.
A fragment ID is the immutable audio Object transaction ID. `submit` validates and stores one complete supported Ogg Opus value and durably queues it before returning. `status` returns one coherent owned projection value. `retry` accepts only failed work with no active retry; its reservation is memory-only, and the next attempt becomes durable with its first canonical progress. `discard` accepts every known state, is idempotent after commitment, rejects an unknown fragment, submits at most one transaction for simultaneous calls, and permanently suppresses later progress, completion, failure, or label effects. `submit_labels` accepts only completed work and uses projection validation to require exactly one label for every interim structured speaker in interim order; each `person_id` must be nonblank and contain no carriage return or line feed.
The six named stage fields identify their corresponding `FragmentStageV1`. Jobs remain ordered by one-based attempt and sequence and retain their latest durable state. Completion stores the complete analysis and its exact callback transaction ID. Confirmation stores the exact labels and derives `final_transcript` by replacing exact `Speaker N` tokens only in conforming `[high]`, `[medium]`, or `[low]` line prefixes, with optional ` [overlap]`; all other bytes are preserved. `errors` retains the oldest 5,000 canonical failure messages in occurrence order, and `errors_truncated` records omitted later messages.
## Persistence and recovery
`open` first opens the projection at `root`. The projection owns its SQLite schema, validation, corruption rebuild, status blobs, cursor, reducer, label validation, transcript derivation, and atomic state-plus-cursor commits. The facade then registers exact subsystem `audio-classification` from the returned real checkpoint or from genesis when no checkpoint exists. Callback payload bytes are passed directly to the projection. Effects are acted on only after the projection operation returns.
Registration replay updates the projection but never starts providers. Gap-free catch-up is followed by exactly one canonical `Failed` event with error `analysis interrupted by restart` and the projection-reported stage for each durable running fragment. Worker signaling is then enabled and every queued fragment is started. A valid current checkpoint causes zero historical callbacks. A reorganization clears the projection, aborts active local work, faults the facade as reopen-required, and never recursively registers.
## Concurrency, lifecycle, and failures
One private OS thread owns a current-thread Tokio runtime, one `LocalSet`, and the shared non-`Send` analyzer. Every fragment runs in an independently cancellable local task. A provider future blocked for one fragment yields to unrelated local tasks and does not delay submission, status, or another provider future. Object loading, provider execution, Peering calls, and runner persistence occur outside projection operations and facade mutexes. Projection access is serialized only by the projection package's bounded per-operation SQLite lane; no caller coordinates it.
Queue callbacks start work only after live signaling is enabled. Discard callbacks own cancellation, and discard remains terminal even if a late task result reaches the projection. Runner persistence failure, projection apply failure, reorganization, or committed-ambiguity diagnostics fault processing and make subsequent public operations require reopen. Ambiguous submissions are never retried. Cancellation, reorganization, and drop fabricate no terminal event. Drop aborts local tasks, stops the runtime, and joins its worker; provider-side cancellation remains provider-owned.
Facade locks protect only in-memory start generations and label or discard reservations. No KTO, Projection, Objects, Peering, runner, analyzer, callback, wait, or caller code runs while such a lock is held. Different facade instances and unrelated valid operations need no caller coordination. Same-fragment reservations prevent duplicate retries, discards, and label submissions without a durable retry marker.
Encoding and projection work are linear in the addressed status, retained jobs, labels, transcript, and capped errors. Submission is linear in audio bytes plus dependency persistence. Startup replay is linear in matching canonical history; a clean cursor restart performs no historical replay. Provider, filesystem, KTO, Peering, Object, SQLite, and worker-join latency has no finite bound.