# Audio classification event format
Pure, stateless structural encoding for audio-classification transaction events. The library re-exports `FormatError`, `TxId`, `ExecutedAnalysis`, `FeatureVector24`, and `LocalSpeakerLabel`.
## Public API
V5 is `AudioClassificationEventV3`, encoded by `encode_event` and decoded by `decode_event`: tag 1 `Queue(QueueV2 { audio_object_id })`; tag 2 `TranscriptionComplete(TranscriptionCompleteV1 { fragment_id, analysis })`; tag 3 `Failed(FailedV2 { fragment_id, stage, llm_job_sequence, error })`; tag 4 `Discarded(DiscardedV2 { fragment_id })`; tag 5 `LabelConfirmation(LabelConfirmationV1 { fragment_id, interim_txid, speakers })`; and tag 6 `Progress(ProgressV1 { fragment_id, update })`. `SpeakerLabelV1` contains `speaker` and optional `person_id`.
`FragmentStageV1` is `Queue`, `Transcript`, `SpeakerLabels`, `SpeakerFeatures`, `Structuring`, or `LabelConfirmation`. `ProgressUpdateV1` is `LlmJobStarted { sequence, stage, name }`, `LlmJobSucceeded { sequence }`, `LlmJobFailed { sequence, error }`, or `StageCompleted { stage }`.
V6 is `AudioClassificationEventV6`, encoded by `encode_event_v6` and decoded by `decode_event_v6`: tag 1 `AttemptStarted(AttemptStartedV1 { fragment_id })`; tag 2 `Progress(AttemptProgressV1 { fragment_id, attempt_txid, update })`; tag 3 `GeminiTranscript(GeminiTranscriptV1 { fragment_id, attempt_txid, transcript })`; tag 4 `TerraSpeakerLabels(TerraSpeakerLabelsV1 { fragment_id, attempt_txid, speakers })`; tag 5 `GeminiFeatureBundle(GeminiFeatureBundleV1 { fragment_id, attempt_txid, speaker, packets })`; and tag 6 `Failed(AttemptFailedV1 { fragment_id, attempt_txid, stage, llm_job_sequence, error })`. The enum remains exhaustive with exactly these six variants.
V7 adds only `AttemptFinalAnalysisV1 { fragment_id, attempt_txid, completion_v5 }`, encoded by `encode_final_event_v7` and decoded by `decode_final_event_v7` at tag 1. Every V6 payload, `AudioClassificationEventV6`, and `AttemptFinalAnalysisV1` derives `Debug`, `Clone`, `PartialEq`, `Eq`, `Serialize`, and `Deserialize`; all existing V5 derives remain unchanged.
## Wire contract
A frame is its version byte, one tag byte, and one postcard body. Every `TxId` and present `PersonId` is exactly its canonical 12 raw bytes. Each version-specific decoder rejects other versions, unknown tags, malformed bodies, and trailing bytes, with precedence `Truncated`, `UnsupportedVersion`, `UnknownEventTag`, `InvalidEventBody`, then `TrailingBytes`.
V5 final `ExecutedAnalysis` data remains the tag-2 `TranscriptionCompleteV1` body. V7 preserves arbitrary `completion_v5` bytes without inspecting or canonicalizing them; the transaction/projection owner must later require exactly one matching V5 transcription-complete frame.
Encoding and decoding take O(input plus output) time and temporary memory proportional to the encoded or decoded value. This library owns only wire structure: it performs no semantic validation, I/O, synchronization, provider work, persistence, ordering, projection, identity, training, retry, or networking.