kcode-k1-full-audio 0.1.0

Durable orchestration of full audio into classified overlapping K1 fragments
Documentation
# Full audio

`K1FullAudio` synchronously converts a complete media value, splits the normalized Ogg Opus stream into chronological overlapping fragments, submits every fragment for classification, and stores one private manifest Object.

## Public API

```rust
pub type FullAudioId = kcode_k1_objects::TxId;

pub struct K1FullAudio;

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum FullAudioState {
    Processing,
    AwaitingLabels,
    NeedsAttention,
    Complete,
}

#[derive(Clone, Debug, PartialEq)]
pub struct FullAudioFragmentStatus {
    pub fragment_id: kcode_k1_audio_classification::FragmentId,
    pub start_sample_48k: u64,
    pub end_sample_48k: u64,
    pub status: kcode_k1_audio_classification::FragmentStatus,
}

#[derive(Clone, Debug, PartialEq)]
pub struct FullAudioStatus {
    pub state: FullAudioState,
    pub fragments: Vec<FullAudioFragmentStatus>,
    pub final_transcript: Option<String>,
}

impl K1FullAudio {
    pub fn open(
        ffmpeg_path: impl AsRef<std::path::Path>,
        objects: std::sync::Arc<kcode_k1_objects::K1Objects>,
        classification: std::sync::Arc<kcode_k1_audio_classification::AudioClassification>,
    ) -> Result<Self, String>;

    pub fn submit(&self, audio: &[u8]) -> Result<FullAudioId, String>;

    pub fn status(&self, id: FullAudioId) -> Result<FullAudioStatus, String>;
}
```

`open` requires an absolute path and does not probe the filesystem. The path must identify a trusted FFmpeg executable satisfying the converter contract when `submit` runs. The supplied Objects and classification facades provide all persistence and transaction authority used by this facade.

`submit` accepts the converter's nonempty, self-contained media domain. It converts the first audio stream, splits the result, submits fragments sequentially in source order, and saves the manifest only after every submission succeeds. The manifest uses empty filename and description metadata and a private file type. Its returned Objects transaction ID is the `FullAudioId`. The call returns without polling or waiting for provider completion. A pre-manifest failure returns no ID and can leave already submitted, harmless fragment Objects and classification work. There is no retry, deduplication, rollback, cancellation, update, deletion, or background work.

A successful manifest is persisted only through Objects and remains available under the canonical transaction lifecycle provided by Objects and KTO. This package has no second manifest store, index, cache, or recovery log. Equal submissions create independent fragment work and manifests.

`status` accepts an ID returned by `submit`. It requires a present Objects value with the exact private manifest type and empty filename and description, strictly validates the manifest, then obtains one present classification status for every fragment. Unknown manifest IDs, unknown fragment IDs, wrong metadata, malformed manifests, invalid geometry, duplicate references, and inconsistent classification values return errors. Returned fragments retain manifest order. Their half-open 48 kHz sample intervals start at zero, have strictly increasing starts and ends, and adjacent intervals overlap.

`NeedsAttention` takes precedence when any fragment is `Failed` or `Discarded`. Otherwise `Processing` applies when any fragment is `Queued` or `Running`. `Complete` requires every fragment to be `Confirmed` with a `final_transcript`. Otherwise a set containing only `Completed` and valid `Confirmed` fragments is `AwaitingLabels`. A confirmed fragment without a final transcript, or any other state carrying one, is inconsistent and returns an error.

`FullAudioStatus::final_transcript` is `Some` only for `Complete`. Assembly compares adjacent transcript speech case-insensitively and without punctuation, ignores conforming quality and speaker prefixes for seam matching, and removes only confident duplicate prefixes. It preserves source text and readable attribution; an uncertain seam retains both sides separated by a newline.

Calls are synchronous and the facade has no package-global or per-operation lock, queue, callback, or shared serialization lane. It holds no lock across conversion, splitting, classification, Objects, or transcript assembly. Independent calls require no caller coordination, while supplied services retain their own documented serialization, backpressure, and failure behavior. A slow FFmpeg process, classification submission, Objects operation, allocation, or storage operation delays only the call using it at this layer.

Conversion and splitting work and memory scale with input, normalized audio, and returned fragment bytes. Submission additionally performs one classification submission per fragment and builds a manifest linear in fragment count. Status performs one Object load, one classification status query per fragment, strict geometry and duplicate validation, and work and memory proportional to the manifest, returned statuses, transcript text, and assembled output. Input audio is borrowed, while normalized audio, fragment outputs, manifest bytes, statuses, tokenized seam text, and the final transcript are owned as needed during their calls. No finite package limit or wall-clock bound is imposed on input duration, fragment count, FFmpeg work, provider completion, dependency queues, allocation, filesystem, KTO, peering, classification, Objects, or storage latency.

The facade does not configure or deploy FFmpeg, providers, storage, KTO, peering, classification, or Objects. It does not expose the private manifest encoding, stream partial results, edit labels, manage fragment lifecycle, infer speakers, or claim registry, Server adoption, deployment, or live behavior.