kcode-audio-ingress 0.5.1

Durable automatic audio transcription with restart recovery
Documentation
# kcode-audio-ingress

`kcode-audio-ingress` 0.4.0 provides durable automatic audio transcription
with transport-neutral speaker correction. It retains complete caller-owned
WAV bytes, sends overlapping chunks to Gemini for unstructured speaker
analysis, validates a typed GPT parse, scores speaker rows through a persistent
classifier, reconciles a readable transcript, and durably exposes one complete
correction packet.

The embedding application supplies typed audio and text-generation callbacks.
It owns provider routing, credentials, accounting, object creation, Kmap
storage, and user messaging. This crate adds no provider client, HTTP, Kmap,
Telegram, object-store, or application-framework dependency.

```rust,no_run
use chrono::Utc;
use kcode_audio_ingress::{
    AudioIngress, AudioInput, AudioTranscriber, ObservationConfirmation,
    RecordingConfirmation,
};

async fn accept(
    transcriber: AudioTranscriber,
    wav_bytes: Vec<u8>,
) -> Result<(), kcode_audio_ingress::Error> {
    let ingress = AudioIngress::open("./audio-ingress", transcriber).await?;
    let submission = ingress
        .submit(AudioInput {
            user_id: "user-root-id".into(),
            bytes: wav_bytes,
            recorded_at: Utc::now(),
            original_filename: Some("recording.wav".into()),
        })
        .await?;

    if let Some(packet) = ingress
        .status()?
        .recordings
        .into_iter()
        .find(|recording| recording.id == submission.recording_id)
        .and_then(|recording| recording.correction_packet)
    {
        let confirmations = packet
            .chunks
            .iter()
            .flat_map(|chunk| &chunk.observations)
            .map(|observation| ObservationConfirmation {
                observation_key: observation.observation_key.clone(),
                confirmed_full_name: "Confirmed Full Name".into(),
            })
            .collect();

        ingress.confirm_speakers(RecordingConfirmation {
            recording_id: packet.recording_id,
            observations: confirmations,
        })?;
    }

    Ok(())
}
```

## Pipeline

- Chunking remains bounded to four-minute windows, 15-second overlap, and four
  concurrent chunks.
- Each chunk goes directly to `gemini-3.1-pro-preview` with the exact exported
  `GEMINI_SPEAKER_PROMPT_V0_1`; `AudioChunkRequest::schema` is `None`.
- The complete raw Gemini response is retained verbatim. A separate
  `gpt-5.6-sol` `xhigh` text callback converts it to validated machine JSON
  containing utterances, notes, clip validity, ISO 639-3 language, and exactly
  one typed 24-feature row per local speaker.
- The persistent classifier is opened beneath the ingress root. Read-only
  scoring uses a nonaccepting finite threshold and explicit deterministic probe
  keys. Clean recordings alone train their deterministic correction keys.
- Reconciliation receives explicit chunk-local mappings, marks unclean chunks
  uncertain, and is forbidden from guessing real identities.
- Completed status includes the transcript and complete transport-neutral
  correction packet. `confirm_speakers` validates exact observation coverage,
  updates classifier assignments idempotently, and persists confirmed names.

Version 0.4.0 intentionally breaks the former structured-audio callback:
`AudioChunkRequest::schema` changed from `serde_json::Value` to
`Option<serde_json::Value>`. See [Documentation.md](Documentation.md) for the
complete API and [Specification.md](Specification.md) for behavioral and
persistence guarantees.