kcode-audio-ingress 0.6.0

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

`kcode-audio-ingress` durably accepts complete WAV buffers, retains the exact
original, analyzes overlapping chunks, reconciles a readable transcript, and
exposes one transport-neutral speaker-correction packet.

The application supplies configured audio and text callbacks plus one shared
`Arc<kcode_speaker_system::SpeechClassifier>`. Provider routing, credentials,
accounting, object creation, Kmap storage, and user messaging remain outside
this crate.

## Ingress boundary

```rust
impl AudioIngress {
    pub async fn open(
        persistence_root: impl AsRef<std::path::Path>,
        transcriber: AudioTranscriber,
        classifier: std::sync::Arc<
            kcode_speaker_system::SpeechClassifier,
        >,
    ) -> Result<AudioIngress, Error>;

    pub async fn submit(&self, input: AudioInput) -> Result<Submission, Error>;
    pub fn status(&self) -> Result<Status, Error>;
    pub fn retry(&self, recording_id: uuid::Uuid) -> Result<(), Error>;
    pub fn confirm_speakers(
        &self,
        confirmation: RecordingConfirmation,
    ) -> Result<CorrectionPacket, Error>;
}
```

`open` owns `<root>/state.sqlite3` and `<root>/originals/`. It applies
compatible ingress migrations, recovers interrupted work, and starts the
background worker. Classifier storage belongs to the caller; AudioIngress does
not create a private speaker database or manage classifier models, attempts,
samples, datasets, quality metadata, or artifact lineage.

`submit` commits the exact original and metadata before returning. Repeated
bytes return the existing recording. `status` returns recordings newest first.
`retry` gives a failed recording a fresh five-attempt budget.

`confirm_speakers` requires one confirmed nonblank full name for every
classifiable observation. It applies the classifier's `train` operation,
rolls back already-applied changes if a later operation fails, persists the
packet, and treats an exact retry idempotently.

## Feature extraction and transcript parsing

The audio callback receives model `gemini-3.1-pro-preview`, the exact prompt
owned by `kcode-speaker-extract` 0.2, one complete Ogg Opus chunk, and no
structured-output schema. Segment ranges also come from that library's frozen
plan.

The text callback receives model `gpt-5.6-sol`, reasoning `xhigh`, and these
operations:

- `normalize_speaker_analysis` converts the quoted raw response to the strict
  normalized 24-value extraction result and is validated by
  `kcode-speaker-extract`;
- `parse_speaker_analysis` independently preserves transcript content and
  speaker ordinals without creating or copying classifier features;
- `reconcile_transcript` faithfully merges chronological overlap using only
  supplied identity mappings;
- `split_transcript` adds size boundaries without rewriting content.

The two parsing operations intentionally remain separate. The normalized
extractor owns the feature schema and its validation; the transcript parser
cannot invent feature values. Complete profiles are merged into `ParsedChunk`
by speaker ordinal. A substantive speaker for whom the extractor withheld a
complete profile remains in the transcript with `primary_language` and
`feature_row` absent and does not become a classifier observation.

## Correction packet and classifier semantics

The correction packet retains the stable recording metadata, chronological
chunk ranges, exact raw provider response, validated parsed transcript,
deterministic observation keys, candidate evidence, and confirmation state.
The feature row is the validated `[u8; 24]` representation exported by
`kcode-speaker-system`.

The classifier cohort is:

- provider `google`;
- model `gemini-3.1-pro-preview`;
- prompt `gemini-speaker-24-freeform/1`;
- schema `gemini-speaker-24-normalized/1`;
- the complete profile's primary language.

Read-only candidate scoring calls `identify` with finite threshold `1e308`, so
the probe is not retained. Human confirmation calls `train`; rollback and
recovery use only `train` and idempotent `delete`. AudioIngress does not decode
or reproduce the classifier's feature schema or internal GMM/LLR mechanics.

`ConfirmationState` remains `Unconfirmed`, `AutomaticallyTrained`, or
`Confirmed`. Clean-recording automatic training retains the established 0.5
behavior; incomplete or uncertain packets train nothing until confirmation.

## Persistence

Each completed chunk is committed before its progress step completes.
Attempt-scoped transcript-piece rows retain the exact raw analysis and the
merged parsed JSON. The 0.6 cache revision prevents older feature schemas from
being reused. Existing database migrations and recording/correction-packet
formats remain readable where their typed JSON is still compatible.

The crate adds no HTTP, Kmap, Telegram, object-store, provider-client,
credential-vault, or application-framework dependency.