# `Parlora.Event`
[🔗](https://github.com/hfiguera/parlora/blob/v0.1.0/lib/parlora/event.ex#L1)

A live observation, independent of business completion or confirmed playback.

Match `source` and `type` before reading `payload`. Named payload types describe
supported common fields; adapter-specific additions are open map entries, not
universal guarantees. Correlation IDs belong to the envelope and may be nil
when no command/request can be identified. `observed_at_us` is signed local
monotonic time. Event IDs do not imply exactly-once delivery or global ordering.

`t/2` describes a narrowed event, for example
`t(:request_completed, Parlora.BackendResult.t())`. Runtime messages are trusted
adapter observations, not a validated serialization format. Events can contain
transcripts and application data; applications control retention and disclosure.

# `adapter_closed`

```elixir
@type adapter_closed() :: %{
  optional(:finalized?) =&gt; boolean(),
  optional(:usage) =&gt; map() | nil,
  optional(:uncertain_requests) =&gt; [String.t()],
  optional(:scope) =&gt; atom(),
  optional(:call_ended?) =&gt; boolean() | :unknown,
  optional(atom()) =&gt; term()
}
```

# `adapter_ready`

```elixir
@type adapter_ready() :: %{
  :capabilities =&gt;
    Parlora.Channel.Capabilities.t()
    | Parlora.Provider.Capabilities.t()
    | Parlora.Backend.Capabilities.t(),
  optional(:format) =&gt; Parlora.AudioFormat.t(),
  optional(atom()) =&gt; term()
}
```

# `audio_observation`

```elixir
@type audio_observation() ::
  %{
    cause: :startup_capture_discard,
    boundary: :browser_rtp,
    packets: non_neg_integer(),
    duration_us: non_neg_integer()
  }
  | %{
      cause: :source_queue_empty | :source_resumed | :cleared | :closed,
      boundary: :browser_pcm,
      gap_id: pos_integer(),
      epoch: non_neg_integer(),
      started_at_us: integer(),
      duration_us: non_neg_integer(),
      silence_bytes: non_neg_integer(),
      inserted_silence_us: non_neg_integer(),
      peak_before: non_neg_integer(),
      peak_after: non_neg_integer() | nil,
      source_returned_at_us: integer() | nil,
      source_return_queue_bytes: non_neg_integer() | nil,
      resume_queue_bytes: non_neg_integer() | nil,
      source_unavailable_us: non_neg_integer(),
      recovery_wait_us: non_neg_integer(),
      recovery_target_us: non_neg_integer() | nil,
      recovery_release_reason:
        :deadline
        | :pressure
        | :buffering_disabled
        | :queue_ready
        | :cleared
        | :closed
        | nil
    }
```

Browser media measurements, not evidence of lost speech or confirmed audibility.

# `clarification`

```elixir
@type clarification() :: %{
  delegation_id: String.t() | nil,
  task_id: String.t() | nil,
  task_revision: pos_integer() | nil
}
```

# `context_outcome`

```elixir
@type context_outcome() :: %{
  optional(:error) =&gt; Parlora.Error.t(),
  optional(:outcome) =&gt; :unknown | :unconfirmed,
  optional(:acceptance) =&gt; atom(),
  optional(atom()) =&gt; term()
}
```

# `context_wait`

```elixir
@type context_wait() :: %{
  target: {:delegation, String.t()} | {:task, String.t(), pos_integer()},
  recheck_after_ms: 1..60000
}
```

# `delegation`

```elixir
@type delegation() :: %{
  :id =&gt; String.t(),
  :target =&gt; :client,
  :offset_ms =&gt; number() | nil,
  optional(atom()) =&gt; term()
}
```

# `delegation_associated`

```elixir
@type delegation_associated() :: %{
  id: String.t(),
  task_id: String.t(),
  task_revision: pos_integer()
}
```

# `discontinuity`

```elixir
@type discontinuity() :: %{
  :cause =&gt; atom(),
  optional(:dropped_bytes) =&gt; non_neg_integer(),
  optional(:dropped_frames) =&gt; non_neg_integer(),
  optional(:dropped_duration_us) =&gt; non_neg_integer(),
  optional(atom()) =&gt; term()
}
```

# `error_payload`

```elixir
@type error_payload() :: %{:error =&gt; Parlora.Error.t(), optional(atom()) =&gt; term()}
```

# `playback`

```elixir
@type playback() :: %{
  :stage =&gt; Parlora.Status.playback_stage(),
  :evidence =&gt; Parlora.Channel.Capabilities.evidence(),
  optional(:stream_id) =&gt; String.t(),
  optional(:sequence) =&gt; non_neg_integer(),
  optional(:epoch) =&gt; non_neg_integer(),
  optional(:first_sample) =&gt; non_neg_integer(),
  optional(:end_sample) =&gt; non_neg_integer(),
  optional(atom()) =&gt; term()
}
```

# `request_started`

```elixir
@type request_started() :: %{
  :task_revision =&gt; pos_integer(),
  optional(atom()) =&gt; term()
}
```

# `result_delivery`

```elixir
@type result_delivery() :: %{
  :stage =&gt; Parlora.Status.delivery(),
  optional(:task_id) =&gt; String.t(),
  optional(:task_revision) =&gt; pos_integer(),
  optional(:delegation_id) =&gt; String.t() | nil
}
```

# `session_closed`

```elixir
@type session_closed() :: %{
  health: Parlora.SessionHealth.t(),
  finalized?: boolean(),
  usage: map() | nil,
  jobs: %{optional(String.t()) =&gt; Parlora.Status.job_state()}
}
```

# `session_ready`

```elixir
@type session_ready() :: %{
  capabilities: %{
    channel: Parlora.Channel.Capabilities.t(),
    provider: Parlora.Provider.Capabilities.t(),
    backend: Parlora.Backend.Capabilities.t()
  }
}
```

# `source`

```elixir
@type source() :: :session | :channel | :provider | :backend
```

# `t`

```elixir
@type t() ::
  t(:transcript_delta, transcript())
  | t(:delegation_requested, delegation())
  | t(:delegation_pending, %{delegation_id: String.t()})
  | t(:delegation_associated, delegation_associated())
  | t(:task_submitted, task_submission())
  | t(:task_queued, task_identity())
  | t(:request_started, request_started())
  | t(:request_progress, Parlora.ContextSnapshot.progress())
  | t(:request_clarification, Parlora.ContextSnapshot.backend_clarification())
  | t(
      :request_completed | :request_failed | :request_cancelled,
      Parlora.BackendResult.t()
    )
  | t(:stale_result, %{result: Parlora.BackendResult.t()})
  | t(:result_delivery, result_delivery())
  | t(:clarification_requested, clarification())
  | t(:context_wait_started, context_wait())
  | t(
      :context_acknowledged | :context_rejected | :context_submitted,
      context_outcome()
    )
  | t(:delegation_cancelled, %{id: String.t(), reason: atom()})
  | t(:output_recovery_requested, %{
      token: pos_integer(),
      cause: :output_overflow | :output_stale
    })
  | t(:output_recovered, %{:token =&gt; pos_integer(), optional(atom()) =&gt; term()})
  | t(:output_interrupted, %{token: non_neg_integer()})
  | t(:provider_activity, %{state: :in_progress | :idle})
  | t(:provider_speech, %{state: :speaking | :idle})
  | t(:response_status, %{
      status: atom(),
      cause: atom(),
      elapsed_ms: non_neg_integer(),
      evidence: :local_observation
    })
  | t(:provider_connection, map())
  | t(:progress_changed, Parlora.SessionHealth.expectation())
  | t(:playback_observed, playback())
  | t(:audio_discontinuity, discontinuity())
  | t(:channel, :audio_observed, audio_observation())
  | t(
      :failed | :policy_failed | :policy_rejected | :admission_rejected,
      error_payload()
    )
  | t(:session, :ready, session_ready())
  | t(:channel | :provider | :backend, :ready, adapter_ready())
  | t(:session, :closed, session_closed())
  | t(:channel | :provider | :backend, :closed, adapter_closed())
  | t(:adapter_down, %{
      role: :channel | :provider | :backend | :input_pipeline | :output_pipeline
    })
  | t(
      :disconnected
      | :request_uncertain
      | :update_applied
      | :update_rejected
      | :update_uncertain
      | :cancellation_requested
      | :cancellation_rejected
      | :cancellation_unconfirmed
      | :control_completed
      | :control_failed
      | :usage_updated
      | :usage_final
      | :extension,
      map()
    )
```

# `t`

```elixir
@type t(event_type, event_payload) :: t(source(), event_type, event_payload)
```

# `t`

```elixir
@type t(event_source, event_type, event_payload) :: %Parlora.Event{
  adapter_id: String.t(),
  command_id: String.t() | nil,
  generation: non_neg_integer(),
  id: String.t(),
  metadata: map(),
  observed_at_us: integer(),
  payload: event_payload,
  request_id: String.t() | nil,
  session_id: String.t(),
  source: event_source,
  type: event_type
}
```

# `task_identity`

```elixir
@type task_identity() :: %{task_id: String.t(), task_revision: pos_integer()}
```

# `task_submission`

```elixir
@type task_submission() :: %{
  request: Parlora.BackendRequest.t(),
  admission: :ok | {:error, Parlora.Error.t()}
}
```

# `transcript`

```elixir
@type transcript() :: %{
  :speaker =&gt; Parlora.ContextSnapshot.speaker(),
  :delta =&gt; String.t(),
  :start_ms =&gt; number() | nil,
  :end_ms =&gt; number() | nil,
  optional(:segment_id) =&gt; String.t(),
  optional(atom()) =&gt; term()
}
```

# `emit`

```elixir
@spec emit(Parlora.AdapterInit.t(), atom(), atom(), term(), keyword()) :: t()
```

---

*Consult [api-reference.md](api-reference.md) for complete listing*
