@xema/omni-protocol 0.1.99 → 0.1.100

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/guide.md CHANGED
@@ -50,7 +50,7 @@ state use `status`; name the object when discussing them to avoid ambiguity.
50
50
  | Word | Belongs to | Values |
51
51
  | --- | --- | --- |
52
52
  | `phase` | A task | `pending`, `confirmed`, `preview`, `in-progress`, `paused`, `completing` |
53
- | `media` | A task's audio | `started`, `ended` |
53
+ | `audio` | A task's audio | `started`, `ended` |
54
54
  | `transport` | A connection | `connecting`, `active`, `error` |
55
55
  | `status` | An authentication session | `signed-out`, `authenticating`, `authenticated`, `refreshing`, `expired` |
56
56
  | `status` | The agent’s break lifecycle | `not-requested`, `awaiting-approval`, `granted`, `starting-after-task`, `on-break` |
@@ -302,7 +302,7 @@ interface RecordingActions {
302
302
  }
303
303
  interface TaskRecordingPolicy {
304
304
  provider?: RecordingActions;
305
- host?: RecordingActions & { destinationId: string };
305
+ host?: RecordingActions & { storageId: string };
306
306
  }
307
307
  type RecordingState =
308
308
  | { status: "unknown"; observationId?: never; observedAt?: never; validUntil?: never; recordingId?: never }
@@ -326,7 +326,7 @@ interface HostRecordingReport {
326
326
  interface HostRecording {
327
327
  announcesToCaller?: true;
328
328
  actions: RecordingAction[];
329
- destinationIds: string[];
329
+ storageIds: string[];
330
330
  execute(request: HostRecordingRequest): Promise<RecordingCommandResult>;
331
331
  }
332
332
  type RecordingCommandResult = Exclude<TaskCommandResult, { status: "dialling" }>;
@@ -479,7 +479,7 @@ type Snapshot = {
479
479
  tasks: Task[];
480
480
  taskCount: number;
481
481
  contacts?: Contact[];
482
- scheduledActivities?: ScheduledActivity[];
482
+ calendar?: ScheduledActivity[];
483
483
  team?: TeamMembers;
484
484
  };
485
485
 
@@ -710,9 +710,9 @@ type Locked = {
710
710
 
711
711
  type Lockable<T> = T | Locked;
712
712
 
713
- type TaskMediaState = "started" | "ended";
713
+ type TaskAudioState = "started" | "ended";
714
714
 
715
- type CapabilitySource = "queue" | "ungoverned" | "undetermined";
715
+ type CapabilitySource = "queue" | "nobody" | "not-yet-read";
716
716
 
717
717
  type Task<C extends Channel = Channel> = {
718
718
  assignmentId: AssignmentId;
@@ -732,11 +732,11 @@ type Task<C extends Channel = Channel> = {
732
732
  history?: TaskHistory;
733
733
  } & TaskCompletion & (
734
734
  C extends "voice"
735
- ? { recording?: { provider?: RecordingState }; onCall?: OnCall[]; leadAssist?: TaskLeadAssist; takenOver?: TaskTakenOver; media?: TaskMediaState }
736
- : { recording?: never; onCall?: never; leadAssist?: never; takenOver?: never; media?: never }
735
+ ? { recording?: { provider?: RecordingState }; onCall?: OnCall[]; leadAssist?: TaskLeadAssist; takenOver?: TaskTakenOver; audio?: TaskAudioState }
736
+ : { recording?: never; onCall?: never; leadAssist?: never; takenOver?: never; audio?: never }
737
737
  );
738
738
 
739
- type PreviewDeadline = "calls" | "host-calls" | "waits";
739
+ type PreviewDeadline = "provider-dials" | "host-dials" | "waits";
740
740
 
741
741
  type AcceptanceMode =
742
742
  | "no-preference"
@@ -759,7 +759,7 @@ const TASK_COMMAND_NAMES = {
759
759
  voice: [
760
760
  "answer",
761
761
  "decline",
762
- "call",
762
+ "dial",
763
763
  "hold",
764
764
  "resume",
765
765
  "end-call",
@@ -783,7 +783,7 @@ type OutcomePayload = { outcome?: string; notes?: string };
783
783
  type VoiceTaskCommand =
784
784
  | { type: "answer" }
785
785
  | { type: "decline" }
786
- | { type: "call"; dialId: DialId }
786
+ | { type: "dial"; dialId: DialId }
787
787
  | { type: "hold" }
788
788
  | { type: "resume" }
789
789
  | { type: "end-call" }
@@ -968,7 +968,7 @@ type BreakEndResult =
968
968
  ### Team
969
969
 
970
970
  ```ts
971
- type TeamMemberAvailability = "ready" | "on-task" | "on-break" | "reserved" | "signed-out";
971
+ type TeamMemberAvailability = "ready" | "on-task" | "on-break" | "elsewhere" | "signed-out";
972
972
 
973
973
  type TeamMember = {
974
974
  id: UserId;
@@ -1002,8 +1002,8 @@ type MemberTask<C extends Channel = Channel> = {
1002
1002
  completionMode?: CompletionMode;
1003
1003
  wrapAllowance?: DurationSeconds;
1004
1004
  } & (C extends "voice"
1005
- ? { onCall?: OnCall[]; leadAssist?: TaskLeadAssist; takenOver?: TaskTakenOver; media?: TaskMediaState }
1006
- : { onCall?: never; leadAssist?: never; takenOver?: never; media?: never });
1005
+ ? { onCall?: OnCall[]; leadAssist?: TaskLeadAssist; takenOver?: TaskTakenOver; audio?: TaskAudioState }
1006
+ : { onCall?: never; leadAssist?: never; takenOver?: never; audio?: never });
1007
1007
 
1008
1008
  type MemberListening = {
1009
1009
  mode: ListeningMode;
@@ -1061,20 +1061,20 @@ type TeamCommandResult =
1061
1061
  | { status: "failed"; failure: ProtocolFailure };
1062
1062
  ```
1063
1063
 
1064
- ### Media
1064
+ ### Audio
1065
1065
 
1066
1066
  ```ts
1067
- type VoiceMediaSession = {
1067
+ type CallAudio = {
1068
1068
  remoteAudio: MediaStream;
1069
1069
  setMuted(muted: boolean): void;
1070
1070
  close(): void;
1071
1071
  };
1072
1072
 
1073
- type OpenMediaResult =
1074
- | { status: "opened"; session: VoiceMediaSession }
1073
+ type OpenAudioResult =
1074
+ | { status: "opened"; audio: CallAudio }
1075
1075
  | { status: "unavailable"; failure: ProtocolFailure };
1076
1076
 
1077
- type OpenMediaRequest = {
1077
+ type OpenAudioRequest = {
1078
1078
  assignmentId: AssignmentId;
1079
1079
  localAudio?: MediaStream;
1080
1080
  };
@@ -1106,10 +1106,10 @@ type ProviderEvent =
1106
1106
  assignmentExpiresAt?: IsoTimestamp;
1107
1107
  }
1108
1108
  | { type: "task-updated"; task: Task }
1109
- | { type: "task-media-started"; assignmentId: AssignmentId }
1110
- | { type: "task-media-ended"; assignmentId: AssignmentId }
1111
- | { type: "team-media-started"; memberId: UserId; assignmentId: AssignmentId }
1112
- | { type: "team-media-ended"; memberId: UserId; assignmentId: AssignmentId }
1109
+ | { type: "task-audio-started"; assignmentId: AssignmentId }
1110
+ | { type: "task-audio-ended"; assignmentId: AssignmentId }
1111
+ | { type: "team-audio-started"; memberId: UserId; assignmentId: AssignmentId }
1112
+ | { type: "team-audio-ended"; memberId: UserId; assignmentId: AssignmentId }
1113
1113
  | { type: "task-ended"; assignmentId: AssignmentId; outcome: TaskOutcome }
1114
1114
  | { type: "dial-outcome"; dialId: DialId; outcome: DialOutcome; assignmentId?: AssignmentId; destinationId?: string; reason?: string }
1115
1115
  | { type: "announcement"; text: string; html?: string; announcedAt: IsoTimestamp; expiresAt?: IsoTimestamp }
@@ -1117,7 +1117,7 @@ type ProviderEvent =
1117
1117
  | { type: "diagnostic"; expected: string; observed: string; assignmentId?: AssignmentId }
1118
1118
  | { type: "team-updated"; team: TeamMembers }
1119
1119
  | { type: "contacts-updated"; contacts: Contact[] }
1120
- | { type: "calendar-updated"; scheduledActivities: ScheduledActivity[] };
1120
+ | { type: "calendar-updated"; calendar: ScheduledActivity[] };
1121
1121
 
1122
1122
  type ProviderEventEnvelope = {
1123
1123
  id: string;
@@ -1172,7 +1172,7 @@ type Connection<C extends Channel = Channel> = {
1172
1172
  endBreak?(): Promise<BreakEndResult>;
1173
1173
 
1174
1174
  executeTeam?(request: TeamCommandRequest): Promise<TeamCommandResult>;
1175
- openMedia?(request: OpenMediaRequest): Promise<OpenMediaResult>;
1175
+ openAudio?(request: OpenAudioRequest): Promise<OpenAudioResult>;
1176
1176
  setPreference?(request: SetPreferenceRequest): Promise<PreferenceResult>;
1177
1177
  recordStep?(report: HistoryReport): Promise<HistoryReportResult>;
1178
1178
  };
@@ -1531,7 +1531,7 @@ Request/response polling does not have those properties and is not a transport f
1531
1531
 
1532
1532
  Everything an adapter publishes about a task is derived from what the platform states, or kept in
1533
1533
  the login's store where the platform cannot hold it. Per offer, the `assignmentId` comes from what
1534
- the offer itself states; per call, the media follows `task-media-started` and `task-media-ended`,
1534
+ the offer itself states; per call, the audio follows `task-audio-started` and `task-audio-ended`,
1535
1535
  never a flag set when the audio was opened; per session, the phone the agent holds is what the
1536
1536
  platform restates on activation, not a mapping read once over HTTP. What the platform cannot hold
1537
1537
  -- an agent application's muted leg -- goes in `ConnectContext.store`, keyed by the task and gone with it.
@@ -1539,11 +1539,11 @@ platform restates on activation, not a mapping read once over HTTP. What the pla
1539
1539
  A fact read once over a connection and kept in the adapter object dies with the client. An agent application
1540
1540
  reload is the first client dying and a second coming up for the same login, and the second
1541
1541
  publishes the same truth about the same task as the first did, or the first was publishing
1542
- something it made up: an assignment minted for the connection, media remembered as a boolean, a
1542
+ something it made up: an assignment minted for the connection, audio remembered as a boolean, a
1543
1543
  phone the second never read. Three pieces of exactly that state were found in one adapter in an
1544
1544
  afternoon, and none of it was visible until the adapter was built twice. The drive's `rebuild` is the test of this
1545
1545
  principle: given a way to build the adapter again, the run hands the login over and holds the
1546
- second to what the first published (`drive.reload.snapshot`, `.history`, `.openMedia`, and the
1546
+ second to what the first published (`drive.reload.snapshot`, `.history`, `.openAudio`, and the
1547
1547
  stream's own rules across the resync). An adapter that cannot be built twice against its platform
1548
1548
  and publish the same task is not a conformant adapter yet, whatever a single run says.
1549
1549
 
@@ -1753,7 +1753,7 @@ contributions from active providers into one agent-facing calendar while retaini
1753
1753
  provider identity for each activity.
1754
1754
 
1755
1755
  When declared, the provider publishes its authoritative list through
1756
- `Snapshot.scheduledActivities` and replaces it with a `calendar-updated` event when it
1756
+ `Snapshot.calendar` and replaces it with a `calendar-updated` event when it
1757
1757
  changes.
1758
1758
 
1759
1759
  | Field | Contract |
@@ -2127,13 +2127,13 @@ a capability it agrees with the login: a lead's snapshot carries `team`, nobody
2127
2127
  | `tasks` | Complete set of tasks currently offered to or owned by this agent. |
2128
2128
  | `taskCount` | The provider's own count of those tasks, stated rather than inferred, and it must equal `tasks.length`. A snapshot with no work says `taskCount: 0` in so many words — a blank or unanswered state lacks the count and cannot pass as a confirmed empty. |
2129
2129
  | `contacts` | Required complete contact contribution when the manifest declares `contacts`; `[]` clears it. Omitted only when it does not. |
2130
- | `scheduledActivities` | Required complete calendar contribution when the manifest declares `calendar`; `[]` clears it. Omitted only when it does not. |
2130
+ | `calendar` | Required complete calendar contribution when the manifest declares `calendar`; `[]` clears it. Omitted only when it does not. |
2131
2131
  | `team` | Required `TeamMembers` when the login declares `capabilities.lead` and the lead has the team feature on, `members: []` when nobody is in it. Forbidden otherwise — the login is the permission, and a lead who turned the feature off gets nothing of the team. |
2132
2132
 
2133
2133
  ## Live connection
2134
2134
 
2135
2135
  `Connection` is what `connect()` returns. Its methods are documented in the sections that follow
2136
- and under **Breaks**, **Team leads**, **Real-time media** and **Task commands**; this is the whole
2136
+ and under **Breaks**, **Team leads**, **Real-time audio** and **Task commands**; this is the whole
2137
2137
  surface in one place, and what obliges an adapter to implement each one.
2138
2138
 
2139
2139
  | Method | Implement it when |
@@ -2154,7 +2154,7 @@ surface in one place, and what obliges an adapter to implement each one.
2154
2154
  | `executeTeam(request)` | The login declares `capabilities.lead`: every lead act, on the team surface and nowhere else. See **Lead commands**. |
2155
2155
  | `setPreference(request)` | The login declares `capabilities.preferences`: the person's choice has to have somewhere to go. |
2156
2156
  | `recordStep(report)` | The manifest lists `softphone` among its `phones`. On a softphone the agent application mutes its own microphone on any call, and the provider's record has to have somewhere to take that leg; a desk phone's microphone is the phone's. See **The agent application records what it performs**. |
2157
- | `openMedia(request)` | The manifest lists `softphone` among its `phones`. On a softphone the call's audio lands in Omni, so the adapter has to open it; a platform of desk phones alone never does. |
2157
+ | `openAudio(request)` | The manifest lists `softphone` among its `phones`. On a softphone the call's audio lands in Omni, so the adapter has to open it; a platform of desk phones alone never does. |
2158
2158
 
2159
2159
  **The four break methods stand or fall together.** Declaring `capabilities.breaks` at login and then
2160
2160
  implementing `requestBreak` without `commitBreak` leaves an agent granted a break that can never
@@ -2168,7 +2168,7 @@ Returns the provider's complete authoritative state at one point in time.
2168
2168
  - Omni registers `subscribe()` before awaiting the initial snapshot. An event delivered while the
2169
2169
  snapshot is read is held until it lands, and what happens to it then depends on what it is. A
2170
2170
  snapshot restates state, so an event of a state-replacing kind -- `task-offered`, `task-updated`,
2171
- `task-ended`, `task-media-started`, `task-media-ended`, `break-state`, `team-updated`,
2171
+ `task-ended`, `task-audio-started`, `task-audio-ended`, `break-state`, `team-updated`,
2172
2172
  `contacts-updated`, `calendar-updated`, `transport-status`, `snapshot` -- is dropped, because the
2173
2173
  snapshot accounts for it. An event that reports a transaction no snapshot carries --
2174
2174
  `dial-outcome`, `diagnostic`, `announcement`, `queue-summary` -- is applied after the snapshot,
@@ -2224,7 +2224,7 @@ Stops the connection and releases adapter-owned resources.
2224
2224
 
2225
2225
  - Must be safe after partial startup and safe to call once during normal shutdown.
2226
2226
  - Must stop automatic reconnect.
2227
- - Must remove event handlers and release media resources owned by the adapter.
2227
+ - Must remove event handlers and release audio resources owned by the adapter.
2228
2228
  - Does not imply that active tasks were completed or removed.
2229
2229
 
2230
2230
  ## Task assignment lifecycle
@@ -2310,7 +2310,7 @@ const assignment = {
2310
2310
  ```
2311
2311
 
2312
2312
  The rule the phase exists to express: **nothing is acquired on the agent's behalf while a task
2313
- is pending.** An agent application that carries media must not open the microphone until the task is
2313
+ is pending.** An agent application that carries audio must not open the microphone until the task is
2314
2314
  accepted. Omni does not open the task's browsers either — a task that rings out costs nothing.
2315
2315
 
2316
2316
  When consent is required, Omni offers the agent an **Accept** control. The call is the
@@ -2362,22 +2362,22 @@ time. Runtime conformance checks also require the task channel to match its prov
2362
2362
 
2363
2363
  | Field | Contract |
2364
2364
  | --- | --- |
2365
- | `assignmentId` | Required `AssignmentId`: the assignment this task is the record of, and its one identity. Issued by the provider, unique within the provider, never reused. Every event, command and report that names a task names it by this, so a late dial outcome or a late history report for one customer never lands on the next. The stream refuses an assignment introduced twice (`stream.taskOffered.duplicate`) and a media or ending event naming one that has ended or that nobody has seen (`stream.assignment.ended`, `.unknown`); a `dial-outcome` may name an ended assignment, since a dial placed late routinely outlives its call, and the agent application routes it there. See **A task's life on the wire**. |
2365
+ | `assignmentId` | Required `AssignmentId`: the assignment this task is the record of, and its one identity. Issued by the provider, unique within the provider, never reused. Every event, command and report that names a task names it by this, so a late dial outcome or a late history report for one customer never lands on the next. The stream refuses an assignment introduced twice (`stream.taskOffered.duplicate`) and an audio or ending event naming one that has ended or that nobody has seen (`stream.assignment.ended`, `.unknown`); a `dial-outcome` may name an ended assignment, since a dial placed late routinely outlives its call, and the agent application routes it there. See **A task's life on the wire**. |
2366
2366
  | `title` | Agent-facing task title. |
2367
2367
  | `channel` | Channel used for this task. It must equal the source provider's manifest channel. |
2368
2368
  | `taskType` | Required provider-defined source or category of work, such as a voice `Queue Name`, `Mailbox Folder`, `Chat Source`, `Support`, `Billing`, or `Returns`. |
2369
2369
  | `capabilities` | Controls and workspace features available for this specific task. |
2370
- | `capabilitySource` | Required. Who chose the capabilities: `queue` when somebody configured these terms, `ungoverned` when nothing handed the work over -- an agent's own outbound -- and `undetermined` when a queue was named and its terms could not be read, in which case `capabilities` is what the provider will honour, not what the platform permits. An agent application shows `undetermined` where the agent works. See **Task capabilities**. |
2370
+ | `capabilitySource` | Required. Who chose the capabilities: `queue` when somebody configured these terms, `nobody` when nothing handed the work over -- an agent's own outbound -- and `not-yet-read` when a queue was named and its terms could not be read, in which case `capabilities` is what the provider will honour, not what the platform permits. An agent application shows `not-yet-read` where the agent works. See **Task capabilities**. |
2371
2371
  | `browsers` | Named browser definitions for the task workspace: at least one when the task declares the `browsers` capability, empty when it does not. |
2372
2372
  | `party` | The person or entity on the other end of this task, as a `Contact`: often a name and one address; a withheld caller ID may leave nothing to send at all. Optional. The party is who the task is *with*; `contacts` is the directory. |
2373
2373
  | `phase` | Current canonical task phase: `pending`, `confirmed`, `preview`, `in-progress`, `paused`, or `completing`. `preview` is voice only. |
2374
- | `media` | Voice only. The task's real-time audio as the provider holds it: `started` while audio is attached, `ended` once it ended, omitted while none is. The provider's word — see **`task-media-started`**. Media names a task whose work has begun, or whose party the agent application is dialling: on a `pending`, `confirmed` or `preview` task with nobody ringing it is refused (`task.media.beforeWork`), on a snapshot as on the event, since an agent application opens the microphone on it; with the party ringing by an agent application dial or provider-triggered preview dial, actual ring-back media may precede answer. |
2374
+ | `audio` | Voice only. The task's real-time audio as the provider holds it: `started` while audio is attached, `ended` once it ended, omitted while none is. The provider's word — see **`task-audio-started`**. Audio names a task whose work has begun, or whose party the agent application is dialling: on a `pending`, `confirmed` or `preview` task with nobody ringing it is refused (`task.audio.beforeWork`), on a snapshot as on the event, since an agent application opens the microphone on it; with the party ringing by an agent application dial or provider-triggered preview dial, actual ring-back audio may precede answer. |
2375
2375
  | `acceptance` | How this offer is accepted — `no-preference`, `consent`, or `automatic` — stated on the pending task so a reconnect snapshot says it too. Required while `pending` when `autoAcceptTasks` was `true`, forbidden when it was `false`, and absent past `pending`. See **Acceptance modes**. |
2376
2376
  | `previewEndsAt` | Voice only, in `preview`: the preparation target instant. Absent, the agent has as long as they need without a preparation countdown. Always with `atDeadline`. See **Preview: the agent presses Call**. |
2377
- | `atDeadline` | Voice only, in `preview`, with `previewEndsAt`: what the system does at the deadline -- `calls` makes the provider initiate dialing, `host-calls` makes the agent application issue Call, `waits` keeps the task in preview awaiting the agent. |
2377
+ | `atDeadline` | Voice only, in `preview`, with `previewEndsAt`: what the system does at the deadline -- `provider-dials` makes the provider initiate dialing, `host-dials` makes the agent application issue Call, `waits` keeps the task in preview awaiting the agent. |
2378
2378
  | `reference` | Optional agent-facing reference such as a case, call, conversation, ticket, or message number. It is distinct from the protocol `id`. |
2379
2379
  | `completionMode` | `agent-command` waits for the channel's `complete` command; `provider-automatic` completes without one. |
2380
- | `wrapAllowance` | Fixed time allowed to complete the task after primary interaction ends. For real-time media, it begins after `task-media-ended`. Required under `provider-automatic`, where the provider acts on it. Optional under `agent-command`: omitted says the provider imposes no deadline, and Omni counts nothing down. |
2380
+ | `wrapAllowance` | Fixed time allowed to complete the task after primary interaction ends. For real-time audio, it begins after `task-audio-ended`. Required under `provider-automatic`, where the provider acts on it. Optional under `agent-command`: omitted says the provider imposes no deadline, and Omni counts nothing down. |
2381
2381
  | `attributes` | Optional ordered, typed `TaskAttribute` entries with keys unique within the task. Each contact or timestamp is a separate array item; new attribute shapes require new union members. |
2382
2382
  | `history` | The call record: `steps` — the ordered interaction history of this open task, one entry per occurrence, oldest first — and what they add up to before this agent, `interactionSeconds`, `holdSeconds`, `queueSeconds`, `transfers`, each present when the provider knows it. Live task data restated with the task, not a permanent archive. See **Interaction history**. |
2383
2383
  | `onCall` | Voice only. Who is on the call, or being brought onto it, as the provider states it, replaced whole with the task: `party` is the customer -- carrying a `stage` while being dialled again on the same task, a connect-back with the agent application's `dialId` or a platform's callback without, ringing from the moment the dial is placed and joined on its answered outcome --, `agent` a person by user id, `consulted` and `conferenced` somebody a dial is bringing in, listed from the moment the dial is placed -- with the `destinationId` dialled, the `dialId` where an agent application placed it, the `stage` reached (`ringing` until answered, `joined` after), and `held: true` on anyone joined and parked. A `consulted` entry is what makes `transfer` `complete` and `cancel` issuable. `label` names a destination -- a person, a queue -- not a phrase; the agent application supplies the verb. Present when the provider knows the room, absent when it does not. See **Every dial has an outcome**. |
@@ -2414,7 +2414,7 @@ The canonical task transitions are:
2414
2414
  | `pending` | Task is accepted | `confirmed` |
2415
2415
  | `confirmed` | The customer's record is put in front of the agent before any call goes out (voice) | `preview` |
2416
2416
  | `confirmed` | Work begins | `in-progress` |
2417
- | `preview` | Agent presses Call (`call`) and the customer answers, or the deadline `calls` and they answer | `in-progress` |
2417
+ | `preview` | Agent presses Call (`dial`) and the customer answers, or the deadline `provider-dials` and they answer | `in-progress` |
2418
2418
  | `preview` | The call goes out and nobody answers | `completing` |
2419
2419
  | `preview` | The preparation target passes with `atDeadline: "waits"` | Remains `preview`, waiting for the agent to press Call |
2420
2420
  | `pending` | Provider withdraws the assignment, the agent declines, or the party abandons the ring | Removed by `task-ended` with `cancelled` outcome, `by` saying which |
@@ -2433,7 +2433,7 @@ The canonical task transitions are:
2433
2433
  A task has one name, the assignment it is the record of, and the provider issues it. Platforms
2434
2434
  reuse their own handles: a closed one is retired minutes later, a requeue takes seconds, and on
2435
2435
  one platform a call was offered twice, thirteen seconds apart, under one handle, through a close
2436
- and a re-offer. Everything that names a task after the fact -- a dial outcome, a media event, an
2436
+ and a re-offer. Everything that names a task after the fact -- a dial outcome, an audio event, an
2437
2437
  ending, a history report, a command -- would land on whichever assignment is open when it arrives.
2438
2438
  So the assignment id is unique within the provider and never reused: where the platform's handle
2439
2439
  never comes back, the adapter passes it through; where it does, the adapter mints the assignment id
@@ -2442,7 +2442,7 @@ belongs to or is refused, and a task-scoped browser session (`PROVIDER_NAME__ASS
2442
2442
  lives one assignment, never the next customer's cookies. A dial the agent application placed was
2443
2443
  already safe, since its outcome is placed by the agent application's own `dialId`; where the
2444
2444
  assignment earns its place is everything the agent application does not mint --
2445
- `task-media-started`, `task-media-ended`, `task-ended`, a `recordStep` naming a task -- any of which
2445
+ `task-audio-started`, `task-audio-ended`, `task-ended`, a `recordStep` naming a task -- any of which
2446
2446
  would otherwise find the next customer under a reused handle and act on them. A minted id is part
2447
2447
  of the task the adapter keeps, not a field held in memory beside it: it lives in the login's
2448
2448
  `store` with the task, or is derived from a platform handle that itself never reuses, so a rebuilt
@@ -2469,19 +2469,19 @@ const previewed = {
2469
2469
  phase: "preview",
2470
2470
  party: { name: "Maya Rao", number: "+919876543210" },
2471
2471
  previewEndsAt: "2026-08-25T10:40:37.000Z",
2472
- atDeadline: "calls",
2472
+ atDeadline: "provider-dials",
2473
2473
  } satisfies Pick<Task<"voice">, "channel" | "capabilities" | "phase" | "party" | "previewEndsAt" | "atDeadline">;
2474
2474
 
2475
2475
  // The agent presses Call. It is a dial like any other.
2476
- const pressed: TaskCommand<"voice"> = { type: "call", dialId: "dial-7f2" };
2476
+ const pressed: TaskCommand<"voice"> = { type: "dial", dialId: "dial-7f2" };
2477
2477
  ```
2478
2478
 
2479
2479
  **Call is a dial.** It carries the agent application's `dialId`, is answered `dialling`, and ends in exactly one
2480
2480
  `dial-outcome`; the phase is its gate and there is no capability, since a record put in front of an
2481
- agent is there to be called. Its media starts on `dialling`, as every agent application-placed dial's does --
2482
- ring-back is audio the agent hears -- so `task-media-started` arrives on the `preview` task with
2483
- its party ringing. On `answered` the task is `in-progress`; on any other outcome the media ends,
2484
- `task-media-ended` starts the wrap clock as on every voice task, and the task goes to
2481
+ agent is there to be called. Its audio starts on `dialling`, as every agent application-placed dial's does --
2482
+ ring-back is audio the agent hears -- so `task-audio-started` arrives on the `preview` task with
2483
+ its party ringing. On `answered` the task is `in-progress`; on any other outcome the audio ends,
2484
+ `task-audio-ended` starts the wrap clock as on every voice task, and the task goes to
2485
2485
  `completing`, so the agent records the
2486
2486
  no-answer as the outcome it is -- in a campaign that is the commonest outcome there is, and it
2487
2487
  is work, not a cancellation. A `preview` task therefore needs a manifest that says how a dial ends
@@ -2493,8 +2493,8 @@ carries the provider's authoritative preparation-end instant and exactly one tri
2493
2493
 
2494
2494
  | Declaration | At preparation end |
2495
2495
  | --- | --- |
2496
- | `atDeadline: "calls"` | The provider initiates dialing. The agent application never sends a timer-triggered Call. |
2497
- | `atDeadline: "host-calls"` | The agent application sends the ordinary `call` command with a fresh agent application `dialId`. The provider does not independently auto-dial this task. |
2496
+ | `atDeadline: "provider-dials"` | The provider initiates dialing. The agent application never sends a timer-triggered Call. |
2497
+ | `atDeadline: "host-dials"` | The agent application sends the ordinary `dial` command with a fresh agent application `dialId`. The provider does not independently auto-dial this task. |
2498
2498
  | `atDeadline: "waits"` | Neither side auto-dials. The task remains in preview until the agent presses Call. |
2499
2499
 
2500
2500
  The agent may press Call early in either fixed-preparation dialing mode, or at any time in
@@ -2502,7 +2502,7 @@ The agent may press Call early in either fixed-preparation dialing mode, or at a
2502
2502
  zero the UI says "Waiting for agent" and keeps Call available. There is no automatic task-ended,
2503
2503
  completion, dialing or phase change. No repeating timer action occurs on later snapshots. This differs
2504
2504
  from unlimited preparation only by displaying a preparation target. The former `expires` deadline
2505
- value is not supported; elapsed preparation must not withdraw the task. For `calls` and `host-calls`, the deadline ends
2505
+ value is not supported; elapsed preparation must not withdraw the task. For `provider-dials` and `host-dials`, the deadline ends
2506
2506
  preparation and triggers initiation; it does not promise ringing, playable audio or customer
2507
2507
  answer at that exact instant. Scheduling/dispatch delay must remain visible, and a failed or
2508
2508
  prevented initiation must be reported rather than leaving a silently expired countdown.
@@ -2513,7 +2513,7 @@ time; clock estimation is allowed only under the explicit agent application-trig
2513
2513
  Without usable provider-domain time
2514
2514
  it cannot safely auto-trigger and must expose the uncertainty and reconcile. No zero-duration,
2515
2515
  receipt-time or local-default deadline is inferred. Neither elapsed time nor submission changes
2516
- the task phase: subsequent authoritative events state ringing, answer, media and completion.
2516
+ the task phase: subsequent authoritative events state ringing, answer, audio and completion.
2517
2517
 
2518
2518
  An agent application must serialize manual clicks and its timer under the exact provider/login/task/assignment
2519
2519
  scope, allowing at most one unresolved submission. Recheck the current phase, deadline owner,
@@ -2527,11 +2527,11 @@ command as ownership of an already-running independent attempt.
2527
2527
  Agent application-triggered automatic dialing is an ordinary agent application dial: its result is `dialling` with the same
2528
2528
  agent application `dialId`, followed by exactly one correlated terminal `dial-outcome`. A provider-triggered
2529
2529
  dial has no invented agent application ID or agent application dial outcome. It reports source-evidenced party ringing,
2530
- actual media and customer answer separately. In preview with `atDeadline: "calls"`, a ringing
2531
- party without an agent application ID may carry actual pre-answer media; the deadline alone permits no media.
2532
- Media is still introduced/ended by the corresponding events and must not imply customer answer.
2530
+ actual audio and customer answer separately. In preview with `atDeadline: "provider-dials"`, a ringing
2531
+ party without an agent application ID may carry actual pre-answer audio; the deadline alone permits no audio.
2532
+ Audio is still introduced/ended by the corresponding events and must not imply customer answer.
2533
2533
  Submission acceptance is never an answered outcome or permission to publish `in-progress` early.
2534
- Unsupported source correlation/outcome/media evidence remains an integration blocker.
2534
+ Unsupported source correlation/outcome/audio evidence remains an integration blocker.
2535
2535
 
2536
2536
  **Drop both fields when the phase moves.** A provider that builds the `in-progress` task by
2537
2537
  spreading the `preview` one carries `previewEndsAt` and `atDeadline` with it, and the agent application refuses
@@ -2549,7 +2549,7 @@ recording contract; this distinction does not remove it or move provider call op
2549
2549
 
2550
2550
  A caller journey may revisit the same agent while an earlier interaction still wraps. Each is its
2551
2551
  own assignment, and two open at once carry two assignment ids. Restore them unchanged on
2552
- reconnect. Commands, media, endings and history reports name the exact assignment; never retarget
2552
+ reconnect. Commands, audio, endings and history reports name the exact assignment; never retarget
2553
2553
  an old command to the newest interaction of a journey. `validateTaskCommandRequest` checks the
2554
2554
  request's assignment against the supplied published task and then its command prerequisites. The
2555
2555
  caller must select that task within the correct provider/login and recheck at the provider; the
@@ -2559,33 +2559,33 @@ portion must not be cleared because this task ended. Snapshot counts include all
2559
2559
  and active interactions; task completion is not caller hangup.
2560
2560
 
2561
2561
  **Voice describes the agent's interaction within the wider call.** The task defines that agent's
2562
- workspace, tools, permissions, media participation and completion work. The caller's channel may
2562
+ workspace, tools, permissions, audio participation and completion work. The caller's channel may
2563
2563
  continue through IVR, queues, other agents, holds or conferences while this interaction ends or wraps.
2564
2564
  Completing this task ends this interaction responsibility; it is not evidence that the caller's channel
2565
- or journey ended. Task media describes this agent's attachment, not the lifetime of every party's
2565
+ or journey ended. Task audio describes this agent's attachment, not the lifetime of every party's
2566
2566
  connection. Commands retain their explicit targets and effects; task completion must not silently
2567
2567
  become a caller-disconnect operation.
2568
2568
 
2569
2569
  **A task is never its audio.** A voice task represents the agent’s interaction: the call is offered when it is
2570
2570
  routed to the agent and accepted as its `acceptance` dictates, and its presence and phase follow
2571
2571
  the provider's reports about the work — never the audio. Wherever audio moves — an offer, a hold, a
2572
- consult, a conference leg joining or leaving, a transfer, a connect-back — the media follows
2573
- separately, arriving on `task-media-started`, attaching through `openMedia` and ending with
2574
- `task-media-ended`. Omni does not ring,
2572
+ consult, a conference leg joining or leaving, a transfer, a connect-back — the audio follows
2573
+ separately, arriving on `task-audio-started`, attaching through `openAudio` and ending with
2574
+ `task-audio-ended`. Omni does not ring,
2575
2575
  bridge, or hold a line. How the phone rings, whether it rings at all, and where legs join and leave
2576
2576
  are the adapter's and the platform's, transient, and decide neither when a task exists nor what
2577
2577
  phase it is in.
2578
2578
 
2579
- The line runs between the provider's word and Omni's own senses. `task-media-ended` is the
2579
+ The line runs between the provider's word and Omni's own senses. `task-audio-ended` is the
2580
2580
  provider's report that primary interaction ended — a fact about the work, which is why the completion
2581
2581
  allowance starts on it and the Connect back control appears on it — and Omni follows that report as it
2582
- follows any other. What Omni never does is derive a task's state from its own media session: a
2582
+ follows any other. What Omni never does is derive a task's state from its own audio session: a
2583
2583
  stream that drops, a track that ends, a transport that disconnects, a microphone that fails, an
2584
2584
  endpoint re-registering change nothing about the task until the provider says so. Structurally:
2585
- `task-media-started` and `task-media-ended` alternate on a task whose work has begun, media ends
2586
- only where it arrived, what follows the media ending is `completing` or `task-ended`, and every
2585
+ `task-audio-started` and `task-audio-ended` alternate on a task whose work has begun, audio ends
2586
+ only where it arrived, what follows the audio ending is `completing` or `task-ended`, and every
2587
2587
  task is introduced once — `exerciseAdapter` holds the stream to that from the connect snapshot on,
2588
- and `assertMediaFollowsTheTask` holds any sequence.
2588
+ and `assertAudioFollowsTheTask` holds any sequence.
2589
2589
 
2590
2590
  #### Completion timing
2591
2591
 
@@ -2594,16 +2594,16 @@ the task open until Omni sends the channel's `complete` command. With `provider-
2594
2594
  provider may complete the task without receiving that command.
2595
2595
 
2596
2596
  `wrapAllowance` is independent of that decision. It is fixed, and when it starts depends on
2597
- whether the channel carries real-time media:
2597
+ whether the channel carries real-time audio:
2598
2598
 
2599
2599
  | Channel | Wrap allowance starts at |
2600
2600
  | --- | --- |
2601
- | Voice and any channel with real-time media | The `task-media-ended` event |
2601
+ | Voice and any channel with real-time audio | The `task-audio-ended` event |
2602
2602
  | Chat | The `task-updated` that moves the task to `completing`: the provider's word that the conversation is closed on its side, the allowance running from that publication's `occurredAt` |
2603
2603
  | Email | The `task-updated` that moves the task to `completing`: the provider's word that the platform has accepted the outgoing message, the allowance running from that publication's `occurredAt` |
2604
- | Other non-media channels | The `task-updated` that moves the task to `completing` |
2604
+ | Other non-audio channels | The `task-updated` that moves the task to `completing` |
2605
2605
 
2606
- **Off voice, `completing` is the provider's word that interaction ended.** There is no media event to
2606
+ **Off voice, `completing` is the provider's word that interaction ended.** There is no audio event to
2607
2607
  carry it, so the phase does; an agent application starts the wrap clock at that publication and nowhere else. It
2608
2608
  is optional: a conversation with nothing to wrap moves from `in-progress` to `task-ended` and
2609
2609
  `completing` is never published. Under `provider-automatic` with a non-zero `wrapAllowance` it is
@@ -2638,9 +2638,9 @@ const untimedWrap = {
2638
2638
  } satisfies Pick<Task<"voice">, "completionMode" | "wrapAllowance">;
2639
2639
  ```
2640
2640
 
2641
- Here the customer has hung up, `task-media-ended` has been sent on time, the task is `completing`,
2641
+ Here the customer has hung up, `task-audio-ended` has been sent on time, the task is `completing`,
2642
2642
  and the agent takes as long as the work needs. Moving the task to `completing` late to avoid a
2643
- deadline is not an alternative on a media channel: the clock starts at a real event, and delaying
2643
+ deadline is not an alternative on an audio channel: the clock starts at a real event, and delaying
2644
2644
  that event would falsify the phase and everything timed from it.
2645
2645
 
2646
2646
  #### Connecting back during completion
@@ -2655,9 +2655,9 @@ is; the command carries no destination, and it is a dial like any other, so it c
2655
2655
 
2656
2656
  On `dialling` the provider is placing the call and the task returns to `in-progress`: the agent is
2657
2657
  working again, and the wrap allowance is **discarded, not paused**. From there the call is
2658
- reported as any call is -- `paused`, `in-progress`, and when its media ends, `task-media-ended`
2658
+ reported as any call is -- `paused`, `in-progress`, and when its audio ends, `task-audio-ended`
2659
2659
  again, which starts a fresh allowance from that instant. A party who does not answer is a dial
2660
- whose outcome says so and a call whose media ended: the task returns to `completing` through the
2660
+ whose outcome says so and a call whose audio ended: the task returns to `completing` through the
2661
2661
  same event and the clock starts again from there. At no point is an agent dialling against a
2662
2662
  deadline.
2663
2663
 
@@ -2693,7 +2693,7 @@ const connectBackCapable = {
2693
2693
  With ten seconds of the thirty left, the agent presses Connect back: `execute({ command: { type:
2694
2694
  "connect-back", dialId } })` returns `dialling`, the task is `in-progress`, and the thirty seconds
2695
2695
  are gone.
2696
- The second call ends: `task-media-ended`, the task is `completing`, and a new thirty seconds runs
2696
+ The second call ends: `task-audio-ended`, the task is `completing`, and a new thirty seconds runs
2697
2697
  from that instant.
2698
2698
 
2699
2699
  ```ts
@@ -2729,6 +2729,12 @@ Migration from the earlier spellings:
2729
2729
  | Task.id, TaskId, and `taskId` on every event, command, report and lead request | gone: a task is named by `assignmentId` alone, and `assignmentKey(providerId, assignmentId)` scopes it |
2730
2730
  | taskKey, omni.task-not-found, PROVIDER_NAME__TASK_ID__TAB_NAME (ProviderName.TaskId.TabName) | `assignmentKey`, `omni.assignment-not-found`, `PROVIDER_NAME__ASSIGNMENT_ID__TAB_NAME` (`ProviderName.AssignmentId.TabName`) |
2731
2731
  | Manifest.disposalSettleMs | `Manifest.completionSettleMs` |
2732
+ | the call command, atDeadline calls and host-calls | `dial`, `"provider-dials"`, `"host-dials"` |
2733
+ | media: task-media-started/-ended, team-media-*, Task.media, TaskMediaState, openMedia, OpenMediaRequest/Result, VoiceMediaSession and its session field | audio: `task-audio-started`, `task-audio-ended`, `team-audio-started`, `team-audio-ended`, `audio` on the task, `TaskAudioState`, `openAudio`, `OpenAudioRequest`, `OpenAudioResult`, `CallAudio` on the result's `audio` |
2734
+ | capabilitySource values ungoverned and undetermined | `nobody`, `not-yet-read` (`capabilitySource.notYetRead`) |
2735
+ | Snapshot.scheduledActivities, and scheduledActivities on calendar-updated | `calendar` in both |
2736
+ | availability reserved | `elsewhere` |
2737
+ | recording destinationId, HostRecording.destinationIds | `storageId`, `storageIds` (`recording.storage`, `recording.host.storage`) |
2732
2738
 
2733
2739
  Update producers, consumers, saved task snapshots, and validation-rule assertions together.
2734
2740
  History and report rule names use `history` and `historyReport`; assignment rules use
@@ -2772,16 +2778,16 @@ Steps are `queued`, `offered`, `answered`, `held`, `muted`, `transferred`, `conf
2772
2778
  when it began, `seconds` once it ended and omitted while it runs — and a second hold is a second
2773
2779
  entry after the first, never a revision of it. A leg that has ended states its duration, and the
2774
2780
  task says whether a leg can still be running: a hold runs only while the task is `paused`, a mute
2775
- only while its media is up, so a `held` entry without `seconds` on a task that is not paused, or a
2781
+ only while its audio is up, so a `held` entry without `seconds` on a task that is not paused, or a
2776
2782
  `muted` one on a call that is over, is a leg nobody closed and reads exactly like a leg running now
2777
2783
  (`task.history.held.open`, `.muted.open`). Whoever performs the leg closes it — the
2778
2784
  provider whose platform parks the caller, the agent application whose microphone it is — by restating the entry
2779
2785
  with its duration, and **an entry that cannot be closed is not written**: open for ever is a
2780
- plausible nought one level down from a total. **A leg still open when the media ends is closed by
2781
- the provider**, at that instant, in the same publication that says the media ended: the provider
2786
+ plausible nought one level down from a total. **A leg still open when the audio ends is closed by
2787
+ the provider**, at that instant, in the same publication that says the audio ended: the provider
2782
2788
  is the one that knows the instant, and the agent application can only learn of it afterwards. Agents end calls
2783
- muted, so the agent application's leg is routinely open at media end; the provider closes it with the duration
2784
- from the leg's `at` to the media's end, and the agent application's own closing report for that leg, which
2789
+ muted, so the agent application's leg is routinely open at audio end; the provider closes it with the duration
2790
+ from the leg's `at` to the audio's end, and the agent application's own closing report for that leg, which
2785
2791
  follows what it hears, is answered `recorded` and changes nothing, the entry standing as the
2786
2792
  provider closed it. One publisher of the closed leg, and no order between them to get right. There is no resumed step; a resume is the end of a
2787
2793
  hold, at the entry's `at` plus its `seconds`, and nothing is lost by not naming it twice. The same goes for every step: two mutes are two
@@ -2828,7 +2834,7 @@ or combine them: report the representation conflict. No ambiguous event is silen
2828
2834
 
2829
2835
  **Handle time is anchored, not restarted.** It runs from the
2830
2836
  `answered` step's `at` — from the task's first `in-progress` where the provider reports no
2831
- history — until the task's media ends, and a hold neither pauses nor resets it: the hold's own
2837
+ history — until the task's audio ends, and a hold neither pauses nor resets it: the hold's own
2832
2838
  duration is the `held` entry's `seconds`, and a desk that restarts its counter on resume is
2833
2839
  counting the wrong thing.
2834
2840
 
@@ -2928,7 +2934,7 @@ the agent application mutes nothing and records nothing.
2928
2934
  **The provider's confirmed end is decisive.** The agent application keeps local state for interaction and
2929
2935
  reporting, but follows the provider's authoritative state. When the provider publishes the end
2930
2936
  of the current mute leg, the agent application ends that local mute and releases its agent application-controlled mute
2931
- on the matching task's media. It does not wait for its own timer, reopen the leg, replace the
2937
+ on the matching task's audio. It does not wait for its own timer, reopen the leg, replace the
2932
2938
  provider timestamp, or overwrite the provider's final duration with a later agent application report.
2933
2939
  A later agent mute is a new leg, never a reopening of the ended one.
2934
2940
 
@@ -2940,7 +2946,7 @@ retain the current provider view and apply the matching closure once correlation
2940
2946
  never guess a match from arrival order or nearest timestamp. Failure to release an agent application-controlled
2941
2947
  mute is reported visibly; local device reports still describe the actual device state.
2942
2948
 
2943
- At a provider-confirmed task/media end, the agent application also stops the associated local mute and reports
2949
+ At a provider-confirmed task/audio end, the agent application also stops the associated local mute and reports
2944
2950
  its observed ending where the report is still accepted. An agent application closing report repeats its original
2945
2951
  key and may include its measured duration, but cannot reverse an already confirmed provider end.
2946
2952
  The provider acknowledges a known closed leg without rewriting its final record; after the task
@@ -3068,7 +3074,7 @@ from no other source -- not the queue the task came from, not the login, not its
3068
3074
  about this task, and a client with two sources and a rule for choosing between them is the shape
3069
3075
  that produces two consumers disagreeing about one fact. The task is the one source, and the
3070
3076
  provider puts on the task what the platform permits for it -- and says, in `capabilitySource`, who
3071
- chose those terms. `queue` says somebody configured them. `ungoverned` says nothing handed the work
3077
+ chose those terms. `queue` says somebody configured them. `nobody` says nothing handed the work
3072
3078
  over: an agent's own outbound call has no queue behind it, and the provider states what it permits
3073
3079
  for such a call. Neither changes where an agent application reads the capabilities from, which is the task; the
3074
3080
  source is one more published fact about them, and the one that lets an agent application tell a fact from a fault
@@ -3106,15 +3112,15 @@ direction: the task as offered and as republished, and one command that was issu
3106
3112
  first and is refused under the last for want of the capability withdrawn -- and nothing else.
3107
3113
 
3108
3114
  **An empty capability set is a statement, not a shrug.** `capabilities: {}` under `queue` or
3109
- `ungoverned` says the platform permits nothing capability-gated on this task, and an agent application draws
3115
+ `nobody` says the platform permits nothing capability-gated on this task, and an agent application draws
3110
3116
  nothing beyond what the phase and `completionMode` require. A provider that has not yet learned
3111
3117
  what the platform permits -- a queue's configuration that has not reached it -- knows nothing of
3112
3118
  the kind, and must not publish the task as if it did, neither as `{}` nor as every control it has.
3113
- It publishes the task under `capabilitySource: "undetermined"`, with the capabilities it will
3119
+ It publishes the task under `capabilitySource: "not-yet-read"`, with the capabilities it will
3114
3120
  honour until it knows, and an agent application shows that where the agent works, beside the controls it draws
3115
3121
  from them: "no queue governs this call" is a fact, "the configuration has not arrived" is a fault,
3116
3122
  and the set alone cannot tell them apart, so the provider says which. What a provider honours
3117
- under undetermined terms is its own call -- a floor that would rather an agent briefly hold a
3123
+ under not-yet-read terms is its own call -- a floor that would rather an agent briefly hold a
3118
3124
  control the platform might not have granted than lose hold or hang-up mid-call over a slow
3119
3125
  configuration read publishes those -- and the protocol chooses no default set for it. The fault is
3120
3126
  also reported as a `diagnostic` naming the task, one per occurrence, so an operator counts it. When
@@ -3122,12 +3128,12 @@ the terms arrive, the task is republished under `queue` with the set as it now s
3122
3128
  republish as any other permission that changed while the task was open. The move goes one way.
3123
3129
  Terms once read stay read: a re-read that fails mid-task is not a new fact about the task, so the
3124
3130
  last statement stands and the failure is a `diagnostic`, and a task that was published under
3125
- `queue` or `ungoverned` never returns to `undetermined`, on an update (`stream.taskUpdated.capabilitySource`)
3131
+ `queue` or `nobody` never returns to `not-yet-read`, on an update (`stream.taskUpdated.capabilitySource`)
3126
3132
  or on a resync snapshot (`stream.snapshot.capabilitySource`); a record once read never loses an
3127
3133
  entry the same two ways (`stream.taskUpdated.history`, `stream.snapshot.history`);
3128
- a snapshot carrying a task still at work does not forget the audio the stream held up, since media
3129
- ends on `task-media-ended` and the call moves on (`stream.snapshot.media`); a voice task ends after
3130
- its audio ends, never around it, whatever the outcome (`stream.taskEnded.mediaOpen`); and a task does not go
3134
+ a snapshot carrying a task still at work does not forget the audio the stream held up, since audio
3135
+ ends on `task-audio-ended` and the call moves on (`stream.snapshot.audio`); a voice task ends after
3136
+ its audio ends, never around it, whatever the outcome (`stream.taskEnded.audioOpen`); and a task does not go
3131
3137
  backwards, on an update or on a resync (`stream.taskUpdated.phase`, `stream.snapshot.phase`): the
3132
3138
  stream sees publications, not
3133
3139
  transitions, and a task may pass through a phase between two, so `pending` to `in-progress` stands
@@ -3136,32 +3142,32 @@ the transition table -- back to `pending`, back to `confirmed` or `preview` once
3136
3142
  `completing` except by the party being dialled again, a connect-back or a platform's callback,
3137
3143
  which the update itself shows: the party ringing, or joined by a dial whose answered outcome the
3138
3144
  stream saw in this life. A completing task republished as `in-progress` from a stale copy carries
3139
- no such stage, and that is the ending the agent never saw. Audio arrives only on a task at work: `task-media-started` on a `completing` task
3140
- is refused as it is on a pending one (`stream.taskMediaStarted.beforeWork`), since a connect-back
3141
- returns the task to `in-progress` before any media. And a task completes after its audio ends,
3142
- never around it: an update moving a task to `completing` while the stream holds its media as
3143
- started is refused (`stream.taskUpdated.mediaOpen`), whoever caused the ending, and a task stating
3144
- `completing` with `media: "started"` contradicts itself on any snapshot or update
3145
- (`task.media.completing`). The consequence the rule exists for is concrete: the customer's audio
3145
+ no such stage, and that is the ending the agent never saw. Audio arrives only on a task at work: `task-audio-started` on a `completing` task
3146
+ is refused as it is on a pending one (`stream.taskAudioStarted.beforeWork`), since a connect-back
3147
+ returns the task to `in-progress` before any audio. And a task completes after its audio ends,
3148
+ never around it: an update moving a task to `completing` while the stream holds its audio as
3149
+ started is refused (`stream.taskUpdated.audioOpen`), whoever caused the ending, and a task stating
3150
+ `completing` with `audio: "started"` contradicts itself on any snapshot or update
3151
+ (`task.audio.completing`). The consequence the rule exists for is concrete: the customer's audio
3146
3152
  keeps playing through the agent's wrap-up.
3147
3153
 
3148
3154
  What the agent is told differs by source, and only one source tells them anything. Under `queue`
3149
- and `ungoverned` the agent sees controls and nothing about where they came from: both are facts,
3155
+ and `nobody` the agent sees controls and nothing about where they came from: both are facts,
3150
3156
  and an agent working a call has no use for the name of the rule behind its buttons. Under
3151
- `undetermined` the agent is told, beside the controls, that these are what the provider will honour
3157
+ `not-yet-read` the agent is told, beside the controls, that these are what the provider will honour
3152
3158
  until the queue's terms arrive, and that the controls may change when they do -- a statement about
3153
3159
  the buttons in front of them now, not about the provider, because that is what changes when the
3154
3160
  republish lands. It stays for as long as the set is provisional, beside the controls it qualifies;
3155
3161
  a message that shows and clears has said nothing about the buttons still on the screen. The two
3156
- words are close in English and far apart on the desk: `ungoverned` is silence, `undetermined` is a
3162
+ words are close in English and far apart on the desk: `nobody` is silence, `not-yet-read` is a
3157
3163
  standing notice.
3158
3164
 
3159
- One consequence for whoever builds the agent application: because a conformance run fails on `undetermined`, a
3160
- conformant adapter never shows an agent application `undetermined` under test, and a clean `exerciseAdapter`
3165
+ One consequence for whoever builds the agent application: because a conformance run fails on `not-yet-read`, a
3166
+ conformant adapter never shows an agent application `not-yet-read` under test, and a clean `exerciseAdapter`
3161
3167
  result says nothing about how the agent application renders it. That rendering is tested against a fixture --
3162
- a task published under `undetermined` shows the notice, the same task under `queue` shows none --
3168
+ a task published under `not-yet-read` shows the notice, the same task under `queue` shows none --
3163
3169
  and never against an adapter, even in principle. `exerciseAdapter` treats a
3164
- task published under `undetermined` as a violation (`capabilitySource.undetermined`), as it treats
3170
+ task published under `not-yet-read` as a violation (`capabilitySource.notYetRead`), as it treats
3165
3171
  a diagnostic: a conformance run against a platform that cannot say what it permits fails loudly
3166
3172
  rather than passing with a note.
3167
3173
 
@@ -3302,7 +3308,7 @@ provider decides: another IVR, a queue, a survey, or the end of the call. Gated
3302
3308
  putting my own side down.
3303
3309
 
3304
3310
  Both are commands to the provider through `execute`, and nothing happens on the desk until the
3305
- provider reports it: the agent's media ends on `task-media-ended`, the task moves to `completing`,
3311
+ provider reports it: the agent's audio ends on `task-audio-ended`, the task moves to `completing`,
3306
3312
  any wrap allowance runs, and the agent completes. Neither is `task-ended`, and `complete` is
3307
3313
  neither of them. Both capabilities are the queue's to grant and a level's to lock, and both may
3308
3314
  change while the task is open: the provider republishes the task at the moment a permission
@@ -3352,7 +3358,7 @@ that offers `warmTransfer` implements all three.
3352
3358
 
3353
3359
  `applied` on `complete` says the provider is bridging the customer to the destination and
3354
3360
  dropping the agent's leg. What follows is what follows any call the agent leaves: the agent's
3355
- media ends and the provider reports `task-media-ended`, the task moves to `completing`, any wrap
3361
+ audio ends and the provider reports `task-audio-ended`, the task moves to `completing`, any wrap
3356
3362
  allowance runs, and the task ends `completed` as any call does. A warm complete is not a completion:
3357
3363
  the agent has a wrap to do, so nothing is owed within `completionSettleMs`. `transferred` names a
3358
3364
  cold transfer alone, where the agent had no wrap. `applied` on `cancel` says the destination is
@@ -3438,7 +3444,7 @@ inside Omni.
3438
3444
 
3439
3445
  ## Every dial has an outcome
3440
3446
 
3441
- Five commands place a call: `dial` from the idle dialpad, `call` from preview, a cold or warm `transfer`, a
3447
+ Five commands place a call: `dial()` from the idle dialpad, the `dial` command from preview, a cold or warm `transfer`, a
3442
3448
  `conference` `add`, and `connect-back`. Each is accepted or refused at once, and each then ends later
3443
3449
  and apart from its answer -- the destination picks up, is busy, or never does -- and a dial placed
3444
3450
  late in a call routinely outlives the call. Nothing in between is reported: the wire says
@@ -3544,7 +3550,7 @@ never saw.
3544
3550
 
3545
3551
  **`onCall` describes this agent's current interaction.** When the caller disconnects but the agent
3546
3552
  and added channels remain connected, the remaining room is still valid. When this interaction's
3547
- media ends or the task enters `completing`, clear its `onCall` view; absence is used only by a
3553
+ audio ends or the task enters `completing`, clear its `onCall` view; absence is used only by a
3548
3554
  provider that never publishes the room. This does not assert that the caller, bridge or other
3549
3555
  agents' channels ended. A published room receives a final empty view for this interaction, and the
3550
3556
  task may remain open for wrap. Completion is a separate task action, not the caller's disconnect.
@@ -3569,10 +3575,10 @@ still-ringing `destinationId` calls that dial off, with `cancelled` as its outco
3569
3575
 
3570
3576
  **The entry says where it stands.** A dialled entry carries `stage`: `ringing` until its dial is
3571
3577
  answered, `joined` after. The `dial-outcome` is the transition and the stage is the state, the same
3572
- pairing as `task-media-started` and `media`: an `answered` outcome and the task restated with the
3578
+ pairing as `task-audio-started` and `audio`: an `answered` outcome and the task restated with the
3573
3579
  entry `joined` say one thing twice, and any other outcome removes the entry. The outcome comes
3574
3580
  first: a `task-updated` that itself moves an entry from `ringing` to `joined` before an `answered`
3575
- outcome for its dial is refused (`stream.taskUpdated.stage`), as an update that moves `media` is.
3581
+ outcome for its dial is refused (`stream.taskUpdated.stage`), as an update that moves `audio` is.
3576
3582
  The rule keys on the entry's `dialId`, so an entry the platform added itself, with none, is one
3577
3583
  whose move the stream cannot hold to an outcome: a clean stream proves nothing about ordering there. It is stated rather
3578
3584
  than left to whoever placed the dial because that knowledge lives in one process: after a reload,
@@ -3789,7 +3795,7 @@ Your own tasks are the only ones you count. What the agent holds at other provid
3789
3795
  concern — Omni set `count` knowing it, and this is how: the agent is one person on several
3790
3796
  providers, and the agent application divides their capacity among them rather than telling each the whole. A
3791
3797
  provider that has none of it for now is told **`count: 0`, agent application-stopped**: assign nothing, show
3792
- the member as `reserved` on the team member list -- signed in here, capacity held by the agent application for elsewhere,
3798
+ the member as `elsewhere` on the team member list -- signed in here, capacity held by the agent application for elsewhere,
3793
3799
  a fact this provider holds, where `on-task` would assert work it cannot see -- and take the next
3794
3800
  count as any other when the agent application has capacity for this provider again. Zero is the one restatement
3795
3801
  that follows work rather than local policy.
@@ -4125,7 +4131,7 @@ for nothing and computes nothing.
4125
4131
  | `availability` | Required. What the member is doing now. |
4126
4132
  | `since` | Optional. When the current `availability` began — not when they signed in, and not when the team member list was read. |
4127
4133
  | `break` | Present only while the member has an outstanding break request. See **A member waiting for a break**. |
4128
- | `tasks` | The member's open tasks as `MemberTask`s: the same task the member's desk holds, trimmed by the provider. The assignment, title, task type, phase, party, room, media and the full history are what the lead reads; the workspace — controls, their source, browsers, completion terms — is the member's and travels only if the provider sends it. `[]` when the member holds none; omitted only where the provider cannot see them. |
4134
+ | `tasks` | The member's open tasks as `MemberTask`s: the same task the member's desk holds, trimmed by the provider. The assignment, title, task type, phase, party, room, audio and the full history are what the lead reads; the workspace — controls, their source, browsers, completion terms — is the member's and travels only if the provider sends it. `[]` when the member holds none; omitted only where the provider cannot see them. |
4129
4135
  | `listening` | Present while this lead's channel is in this member's call — listening, coaching or joined — with the `mode` they are heard in and since when. One member's call at a time (`team.listening.single`). |
4130
4136
 
4131
4137
  Each availability value means one thing:
@@ -4135,7 +4141,7 @@ Each availability value means one thing:
4135
4141
  | `ready` | Signed in, able to take work, none assigned. |
4136
4142
  | `on-task` | Working on at least one task. It says nothing about how many, and nothing about whether more will fit. |
4137
4143
  | `on-break` | Stopped and not taking work, whether they asked or somebody stopped them. The reason lives on their own `BreakState`, not here. |
4138
- | `reserved` | Signed in here, and the agent application holds this agent's capacity for another provider (`count: 0`, agent application-stopped): not receiving this provider's work, and not on a break. See **Capacity**. |
4144
+ | `elsewhere` | Signed in here, and the agent application holds this agent's capacity for another provider (`count: 0`, agent application-stopped): not receiving this provider's work, and not on a break. See **Capacity**. |
4139
4145
  | `signed-out` | Known to this team but not signed in to this provider. |
4140
4146
 
4141
4147
  **Always publish the complete team member list, never a change to it.** Team presence typically reaches an
@@ -4255,7 +4261,7 @@ listening unasked -- and one act at the end of either. What follows is the same
4255
4261
 
4256
4262
  | | The member's task | The lead's desk |
4257
4263
  | --- | --- | --- |
4258
- | Take-over | `task-media-ended`, then `completing`: the member's interaction is over and their wrap runs, exactly as after `end-call`. The audio ends first, as before every voice ending (`stream.taskEnded.mediaOpen`). | An ordinary assignment arrives: `task-offered` with `acceptance: "automatic"`, carrying the call's history and `takenOver: { memberId, since }`. |
4264
+ | Take-over | `task-audio-ended`, then `completing`: the member's interaction is over and their wrap runs, exactly as after `end-call`. The audio ends first, as before every voice ending (`stream.taskEnded.audioOpen`). | An ordinary assignment arrives: `task-offered` with `acceptance: "automatic"`, carrying the call's history and `takenOver: { memberId, since }`. |
4259
4265
  | The member completes | `task-ended` with `{ type: "taken-over", leadId }`, at the member's own completion. The lead is named by user id, since a lead is not a directory item. | The lead works the call as any agent would, and ends it as any call ends. |
4260
4266
 
4261
4267
  **The taken-over call is offered whatever break the lead is on.** A lead working as lead alone is
@@ -4303,7 +4309,7 @@ All three come with the `lead` flag; a centre reserves none of them per lead. Th
4303
4309
  // 1. The lead picks a member from the team member list and starts silent.
4304
4310
  executeTeam({ command: { type: "listen", memberId: "A-1" } })
4305
4311
  // team-updated: the member carries listening: { mode: "listen", since }
4306
- // team-media-started: { memberId: "A-1", assignmentId: "alloc-42" } -- the lead's audio attaches
4312
+ // team-audio-started: { memberId: "A-1", assignmentId: "alloc-42" } -- the lead's audio attaches
4307
4313
 
4308
4314
  // 2. The lead changes how they are heard; the provider restates the member with the new mode.
4309
4315
  executeTeam({ command: { type: "coach", memberId: "A-1" } })
@@ -4314,17 +4320,17 @@ executeTeam({ command: { type: "leave", memberId: "A-1" } })
4314
4320
  executeTeam({ command: { type: "take-over-call", memberId: "A-1" } })
4315
4321
  ```
4316
4322
 
4317
- **The lead's audio arrives through team media.** While the lead's channel is in a member's call
4318
- -- listening, coaching or joined on request -- the lead's connection receives `team-media-started`
4323
+ **The lead's audio arrives through team audio.** While the lead's channel is in a member's call
4324
+ -- listening, coaching or joined on request -- the lead's connection receives `team-audio-started`
4319
4325
  naming the member and the member's assignment, and on a softphone the agent application opens
4320
- `openMedia` on that assignment as it does for a task; `team-media-ended` closes it. Voice only, and
4321
- to a login that declares `lead` (`event.teamMedia.*`). The member's own media events are the
4326
+ `openAudio` on that assignment as it does for a task; `team-audio-ended` closes it. Voice only, and
4327
+ to a login that declares `lead` (`event.teamAudio.*`). The member's own audio events are the
4322
4328
  member's and never reach the lead.
4323
4329
 
4324
4330
  **`listening` on the member is the state**, restated on every change of mode, and a lead is on
4325
4331
  one member's call at a time (`team.listening.single`). The member's call ending ends the lead's
4326
4332
  listening with it: the provider republishes the member without `listening` and sends
4327
- `team-media-ended`.
4333
+ `team-audio-ended`.
4328
4334
 
4329
4335
  **A lead listens while holding no call of their own.** Omni offers Listen to a lead whose voice
4330
4336
  channel is free, and a provider answers a `listen` from one whose channel is not `failed`. That
@@ -4369,20 +4375,20 @@ A request needing *more than one* approval is not something this contract descri
4369
4375
  no partial state to report and no progress to display: a request is either still owed a
4370
4376
  decision or it is not.
4371
4377
 
4372
- ## Real-time media
4378
+ ## Real-time audio
4373
4379
 
4374
- Every voice provider has media: `channel: "voice"` says audio exists. Where the agent hears it
4380
+ Every voice provider has audio: `channel: "voice"` says audio exists. Where the agent hears it
4375
4381
  depends on the `phone` the agent application selected at authentication and connect from the manifest's
4376
4382
  `phones`. On a softphone, audio lands in Omni; on a desk phone, it lands on the handset and Omni
4377
- opens no audio. See **How the agent hears the call**. Media transitions are voice-only;
4378
- chat and email publish none (`event.media.channel`, `stream.taskMedia.channel`).
4383
+ opens no audio. See **How the agent hears the call**. Audio transitions are voice-only;
4384
+ chat and email publish none (`event.audio.channel`, `stream.taskAudio.channel`).
4379
4385
 
4380
4386
  The provider owns signalling and the platform's endpoint configuration. The agent application selects the
4381
4387
  declared phone mode; it does not enumerate or reconfigure the platform's devices. The selected
4382
4388
  mode stays with the login rather than being inferred from a snapshot or a device failure.
4383
4389
 
4384
4390
  Nor does the audio ever stand in for the task: a task's presence and
4385
- phase follow the provider's reports about the work, and the media — attaching, moving through a
4391
+ phase follow the provider's reports about the work, and the audio — attaching, moving through a
4386
4392
  hold, a consult, a conference or a transfer, and ending — is transient beside it. See **A task is
4387
4393
  never its audio** under **Task assignment lifecycle**.
4388
4394
 
@@ -4419,7 +4425,7 @@ refuses a false one, as it refuses a name this contract does not list.
4419
4425
  | --- | --- |
4420
4426
  | `online` | Whether the agent application has a network interface up. Not a claim that anything is reachable — the adapter knows whether it can reach its own platform far better than the agent application does — so `false` is a reason not to go ready and `true` is not a reason to. |
4421
4427
  | `audio` | Present on a voice connection, absent where there is no audio. |
4422
- | `audio.input` | `available` with `localAudio` — the microphone as captured, the same stream `openMedia` receives — and `flowing`, false while no audio moves through it, when `mutedBy` says who stopped it: `host`, the agent application's own Mute on an agent application that mutes the station, or `station`, a slider on the headset or the operating system, which the agent application observed and did not do. An adapter treats `host` as the agent's act on a call and `station` as a condition of the station. `unavailable` with `reason`, since each wants a different fix from the agent: `no-device`; `denied`; `not-asked`, which an agent application that asks at connect never publishes; `in-use`, a device present and permitted that another application holds — on an agent desktop the commonest of all; `lost`, a capture that ended. An agent application decides the reason from the devices before the error name: a browser can report a permission error on a machine with no microphone at all, and "grant permission" is the wrong instruction for an agent who needs to plug one in. `failure` carries the words Omni showed them. |
4428
+ | `audio.input` | `available` with `localAudio` — the microphone as captured, the same stream `openAudio` receives — and `flowing`, false while no audio moves through it, when `mutedBy` says who stopped it: `host`, the agent application's own Mute on an agent application that mutes the station, or `station`, a slider on the headset or the operating system, which the agent application observed and did not do. An adapter treats `host` as the agent's act on a call and `station` as a condition of the station. `unavailable` with `reason`, since each wants a different fix from the agent: `no-device`; `denied`; `not-asked`, which an agent application that asks at connect never publishes; `in-use`, a device present and permitted that another application holds — on an agent desktop the commonest of all; `lost`, a capture that ended. An agent application decides the reason from the devices before the error name: a browser can report a permission error on a machine with no microphone at all, and "grant permission" is the wrong instruction for an agent who needs to plug one in. `failure` carries the words Omni showed them. |
4423
4429
  | `audio.output` | `available`, with `flowing` where the agent application can know whether audio reaches the speaker — a browser mostly cannot, and omits it; a native agent application reads the endpoint — false while it is silenced, when `mutedBy` says who did it, as on input. Or `unavailable` with `reason` — `no-device`, or `lost` for one removed — and `failure`: an agent who cannot hear is as unable to take a call as one who cannot speak. |
4424
4430
 
4425
4431
  Omni republishes the report whenever it changes — a permission granted late, a headset unplugged,
@@ -4488,10 +4494,10 @@ A voice manifest lists its `phones` and any other channel lists none (`manifest.
4488
4494
  `manifest.phones.channel`). The agent application's `phone` is required on a voice login, absent on any other,
4489
4495
  and one the manifest listed (`context.phone.required`, `.unexpected`, `.unsupported`). Everything
4490
4496
  about audio then follows the phone rather than the channel: on a softphone the agent application reports its
4491
- audio, the adapter implements `openMedia`, and `task-media-started` is the word to open it; on a
4492
- desk phone the agent application reports no audio, opens nothing, and `task-media-started` still marks the
4497
+ audio, the adapter implements `openAudio`, and `task-audio-started` is the word to open it; on a
4498
+ desk phone the agent application reports no audio, opens nothing, and `task-audio-started` still marks the
4493
4499
  moment the call is live so the desk shows it, with the sound on the handset. A platform that lists
4494
- `deskPhone` alone never implements `openMedia`; one that lists `softphone` always does.
4500
+ `deskPhone` alone never implements `openAudio`; one that lists `softphone` always does.
4495
4501
 
4496
4502
  **The mode comes from the agent application; the status comes from the provider.** The agent application knows which kind
4497
4503
  of station the agent signed in at, because the person chose it, and nothing else can know that.
@@ -4503,10 +4509,10 @@ the handset is momentarily unregistered, and demanding a microphone of it, is th
4503
4509
  sentence exists to refuse. What the provider does when the handset is not registered is what it
4504
4510
  does for any station that cannot take a call -- hold the agent not-ready and say why.
4505
4511
 
4506
- **On a desk-phone login the agent application never calls `openMedia`.** There is no stream to hand over and
4512
+ **On a desk-phone login the agent application never calls `openAudio`.** There is no stream to hand over and
4507
4513
  no audio to attach; an agent application that calls it anyway is in error, and an adapter that receives the call
4508
4514
  answers `unavailable` with a non-retryable failure, since waiting changes nothing about a station
4509
- that is a telephone. The harness requires no `openMedia` of such an adapter and never calls it.
4515
+ that is a telephone. The harness requires no `openAudio` of such an adapter and never calls it.
4510
4516
 
4511
4517
  **Which handset a desk-phone login rings is the platform's configuration for that agent**, and
4512
4518
  this wire never asks the agent for it: an agent application declares `phone` and nothing more. What a platform
@@ -4529,11 +4535,11 @@ is the administrator's, and a login is not a request to reconfigure an agent.
4529
4535
 
4530
4536
  ### Opening the audio
4531
4537
 
4532
- `openMedia` hands Omni the remote audio for one task. Every adapter whose manifest lists
4538
+ `openAudio` hands Omni the remote audio for one task. Every adapter whose manifest lists
4533
4539
  `softphone` implements it, because on a softphone the call's audio lands in Omni:
4534
4540
 
4535
4541
  ```ts
4536
- openMedia({ assignmentId, localAudio }): Promise<OpenMediaResult>
4542
+ openAudio({ assignmentId, localAudio }): Promise<OpenAudioResult>
4537
4543
  // { status: "opened", session } | { status: "unavailable", failure }
4538
4544
  ```
4539
4545
 
@@ -4556,8 +4562,8 @@ carries as `audio.input.localAudio`, and absent while that input is `unavailable
4556
4562
  bridges audio without an application-side input may ignore it; one that needs it and finds it absent
4557
4563
  answers `unavailable` with a failure Omni shows the agent.
4558
4564
 
4559
- **When to ask is the provider's word, not Omni's guess.** On a softphone login, Omni opens media on `task-media-started`,
4560
- and on a task arriving with `media: "started"` on a snapshot; it closes on `task-media-ended` and
4565
+ **When to ask is the provider's word, not Omni's guess.** On a softphone login, Omni opens audio on `task-audio-started`,
4566
+ and on a task arriving with `audio: "started"` on a snapshot; it closes on `task-audio-ended` and
4561
4567
  when the task ends. Between those words, nothing Omni's own senses report — a stream that drops, a
4562
4568
  track that ends — moves the task or its audio.
4563
4569
 
@@ -4607,8 +4613,8 @@ agent application's. So mute is not a capability a provider declares, not a cont
4607
4613
  locks, not a preference the person keeps with the provider, and not a command: nothing about the
4608
4614
  station crosses to the provider except two things -- the station's condition, in the agent application report,
4609
4615
  and the record of when the agent could not be heard, through `recordStep`. An agent application offers Mute on
4610
- every voice task with media open, under its own local policy, in `in-progress` and `paused`
4611
- alone, and performs it through `VoiceMediaSession.setMuted()`. A task carrying
4616
+ every voice task with audio open, under its own local policy, in `in-progress` and `paused`
4617
+ alone, and performs it through `CallAudio.setMuted()`. A task carrying
4612
4618
  `capabilities.mute` is refused (`task.capability.unknown`), and so is a `mute` command
4613
4619
  (`command.type`), a `mute` preference (`preference.id`) and a `mute` policy (`team.policy.key`).
4614
4620
 
@@ -4644,9 +4650,9 @@ forty seconds" and "the agent's headset was muted for forty seconds" as the diff
4644
4650
  are. See **The agent application records what it performs**.
4645
4651
 
4646
4652
  **Mute has a lifecycle, and none of it is inferred.** A call that starts while the station is
4647
- already muted begins a `muted` leg the moment its media starts, `mutedBy: "station"`. Media that
4653
+ already muted begins a `muted` leg the moment its audio starts, `mutedBy: "station"`. Audio that
4648
4654
  ends while any leg is open ends the leg at that instant, as every agent application-performed leg ends. And the
4649
- agent application's own Mute starts off on every call, which is every `task-media-started` -- a connect-back
4655
+ agent application's own Mute starts off on every call, which is every `task-audio-started` -- a connect-back
4650
4656
  opens a second call on the same task with no offer -- so an agent is never muted by the call before.
4651
4657
 
4652
4658
  **Every press on a headset is the agent's own press**, performed the agent application's way, and the lights
@@ -4686,7 +4692,7 @@ declared:
4686
4692
  | `terminate-call` | The `terminateCall` capability: ends the caller channel. |
4687
4693
  | `conference` with `action: "remove"` | The `conference` capability, and somebody else on the call: a remove that would leave the agent alone is `end-call`, and a provider answers it `failed`. |
4688
4694
  | `decline` | The `decline` capability on any channel, **and** Omni local policy permitting it. One word for refusing an offer, whatever the channel. |
4689
- | `call` | The `preview` phase. A record put in front of an agent is there to be called, so the phase is the gate and there is no capability. It is a dial, with a `dialId` and a `dial-outcome`. |
4695
+ | `dial` | The `preview` phase. A record put in front of an agent is there to be called, so the phase is the gate and there is no capability. It is a dial, with a `dialId` and a `dial-outcome`. |
4690
4696
  | `complete` | `completionMode: "agent-command"`. The `outcomes` capability decides whether a code travels with the command, never whether the command exists — a task Omni cannot complete never ends. What travels is what the capability published: a code from its list where it has one (`command.complete.outcome.unknown`), a code at all where it requires one (`.outcome.required`), notes as it said (`.notes.required`, `.notes.unexpected`), and neither where the task declares no outcomes (`.outcome.unexpected`). |
4691
4697
  | `connect-back` | The `connectBack` capability **and** the `completing` phase. It exists to reach the party again after the call, so it has no meaning while the call is up. |
4692
4698
  | `transfer` with `action: "warm"` | The `warmTransfer` capability. `action: "cold"` is gated by `coldTransfer`; the two are declared and offered separately. |
@@ -4706,7 +4712,7 @@ declared while the task remains open; the phase prevents this task from controll
4706
4712
  it no longer owns. Omni shows these controls only in the two interaction phases, and
4707
4713
  `validateTaskCommand` refuses them outside those phases (`command.phase.interaction`).
4708
4714
  The commands with a phase of their own -- `answer`, `accept` and `decline` in `pending`,
4709
- `call` in `preview`, `connect-back` in `completing`, `complete` in any -- are not among them.
4715
+ `dial` in `preview`, `connect-back` in `completing`, `complete` in any -- are not among them.
4710
4716
 
4711
4717
  `validateTaskCommand(command, task)` holds a command to this table at runtime, both ways: the
4712
4718
  capability it needs, the phase it belongs to, and the state that has to stand. The task it wants
@@ -5055,30 +5061,30 @@ snapshots until it ends.
5055
5061
  Replaces the current representation of one provider-local task. It is a full task value, not a
5056
5062
  partial patch.
5057
5063
 
5058
- ### `task-media-started`
5064
+ ### `task-audio-started`
5059
5065
 
5060
- The provider's word that the task's audio should now attach. Omni calls `openMedia` on it — and on
5061
- a task carried with `media: "started"`, which is how a reconnect snapshot reattaches audio an
5066
+ The provider's word that the task's audio should now attach. Omni calls `openAudio` on it — and on
5067
+ a task carried with `audio: "started"`, which is how a reconnect snapshot reattaches audio an
5062
5068
  earlier event brought — and renders the call as live from that word, never from its own senses. It
5063
- precedes `openMedia` and is never a reply to it: a provider whose media state comes from the
5069
+ precedes `openAudio` and is never a reply to it: a provider whose audio state comes from the
5064
5070
  platform, a station going in use the moment a call is answered, sends it then, before any agent application has
5065
- opened anything, and `openMedia` has its own answer for what the agent application did. It
5066
- names a task whose work has begun, and it alternates with `task-media-ended`: media that never
5071
+ opened anything, and `openAudio` has its own answer for what the agent application did. It
5072
+ names a task whose work has begun, and it alternates with `task-audio-ended`: audio that never
5067
5073
  started cannot end, so a live call whose provider says nothing about its audio is a provider in
5068
5074
  breach, not a state a desk fills in from its own devices.
5069
5075
 
5070
- The event is the transition and the task's `media` field is the state. A `task-updated` re-states
5071
- the media its task already holds — republishing `started` on a hold is a statement, not a second
5076
+ The event is the transition and the task's `audio` field is the state. A `task-updated` re-states
5077
+ the audio its task already holds — republishing `started` on a hold is a statement, not a second
5072
5078
  arrival — but it does not move it: an update that itself flips the field is refused
5073
- (`stream.taskUpdated.media`), and the pairing at the moment audio arrives is the phase change
5079
+ (`stream.taskUpdated.audio`), and the pairing at the moment audio arrives is the phase change
5074
5080
  without the field, then the event. Releasing `ended` is the one move an update may make, since
5075
5081
  wrapped audio has nothing left to end.
5076
5082
 
5077
- ### `task-media-ended`
5083
+ ### `task-audio-ended`
5078
5084
 
5079
- Signals that a task's real-time media ended. For voice and similar channels, this starts the fixed
5080
- completion timer. It does not remove the task, and it ends only audio that `task-media-started` — or
5081
- a task carried with `media: "started"` — attached.
5085
+ Signals that a task's real-time audio ended. For voice and similar channels, this starts the fixed
5086
+ completion timer. It does not remove the task, and it ends only audio that `task-audio-started` — or
5087
+ a task carried with `audio: "started"` — attached.
5082
5088
 
5083
5089
  ### `task-ended`
5084
5090
 
@@ -5086,7 +5092,7 @@ Every outcome ends the task for this agent. On `task-ended`, Omni:
5086
5092
 
5087
5093
  - removes the task from its current provider view;
5088
5094
  - clears the task workspace when it is selected;
5089
- - stops task timers and media;
5095
+ - stops task timers and audio;
5090
5096
  - releases task-scoped resources; and
5091
5097
  - selects another task or returns to the idle workspace.
5092
5098
 
@@ -5101,7 +5107,7 @@ performed. Past the bound the agent application calls `snapshot()`: a snapshot s
5101
5107
  held open by a provider that said it was done, and the desk shows it as unsettled -- "Completing...
5102
5108
  the provider has not confirmed" -- naming the command; a snapshot no longer carrying it clears the
5103
5109
  task, since the ending was owed and lost. The drive holds a provider to the same bound
5104
- (`drive.completion.unsettled`). The `task-media-ended` event and the `completing` phase are likewise
5110
+ (`drive.completion.unsettled`). The `task-audio-ended` event and the `completing` phase are likewise
5105
5111
  non-terminal. A replacement
5106
5112
  snapshot that no longer contains the task also clears it. Repeated `task-ended` delivery with the
5107
5113
  same envelope ID is harmless, and a `task-ended` naming an assignment that has already ended is
@@ -5135,8 +5141,8 @@ console is the silence problem one layer up. One event per occurrence; the agent
5135
5141
  provider does not batch. `exerciseAdapter` treats a diagnostic delivered during a run as a
5136
5142
  violation (`diagnostic.raised`): a conformance run against a platform that is breaking its rules
5137
5143
  fails loudly rather than passing with a note. A task published under `capabilitySource:
5138
- "undetermined"` is the same kind of fact, stated on the task instead, and fails a run the same way
5139
- (`capabilitySource.undetermined`); see **Task capabilities**.
5144
+ "not-yet-read"` is the same kind of fact, stated on the task instead, and fails a run the same way
5145
+ (`capabilitySource.notYetRead`); see **Task capabilities**.
5140
5146
 
5141
5147
  | Field | Contract |
5142
5148
  | --- | --- |
@@ -5306,10 +5312,10 @@ Nothing there is a violation: an adapter with no team has nothing to exercise. B
5306
5312
  no tasks exercises no task rule, and a pass over it reads as coverage it is not.
5307
5313
 
5308
5314
  **A static run never answers a call.** It states a capacity and disconnects, so everything
5309
- downstream of `answer` -- the room, the stage, media, every phase past `pending`, every dial
5315
+ downstream of `answer` -- the room, the stage, audio, every phase past `pending`, every dial
5310
5316
  outcome -- stays in `notExercised` for every adapter, and a rule about a live call is enforced only
5311
5317
  in each adopter's own tests. `{ drive: true }` closes that: the exercise takes the first task the
5312
- provider offers through one ordinary lifecycle -- accept it, wait for its media and open it on a
5318
+ provider offers through one ordinary lifecycle -- accept it, wait for its audio and open it on a
5313
5319
  softphone, hold and resume where the task offers `hold`, end the call where it offers `endCall`,
5314
5320
  complete it with an outcome where the agent completes -- and holds every step to the rules a
5315
5321
  agent application holds a provider to. Each command is validated against the task as published
@@ -5324,17 +5330,17 @@ nothing (`getUserDetails.user.*`, `getUserDetails.unasked`, `connection.getUserD
5324
5330
  the second adapter a `rebuild` gives comes up signed in as the same login from the secrets alone
5325
5331
  before it reads anything (`drive.reload.login`), and is then held to everything the first was on
5326
5332
  connect: the methods its declarations call for, the agent application's report, a capacity stated to it, its
5327
- snapshot read as the connect snapshot was, and its media opened afresh on a task carried with
5328
- `media: "started"`, since the first client's session died with it. The result also says which rules the
5333
+ snapshot read as the connect snapshot was, and its audio opened afresh on a task carried with
5334
+ `audio: "started"`, since the first client's session died with it. The result also says which rules the
5329
5335
  run evaluated, pass or fail, in `rulesEvaluated`: the validators' as each was applied, the stream's
5330
5336
  as each case was considered, so a test that needs a rule to have run asserts it there rather than
5331
5337
  inferring it from an empty `violations`, and a rule absent from it was never looked at, which is a
5332
5338
  gap and not a pass. With the audio open on a softphone,
5333
5339
  the drive mutes it for one second and reports the leg through `recordStep`, begun and then ended,
5334
5340
  expecting each report `recorded` with the provider-selected history `at` (`drive.recordStep.failed`, `.rejected`, `result.recordStep.at`); then it mutes again and
5335
- ends the call muted, as agents do, so the leg is open when the media ends, the provider closes it
5341
+ ends the call muted, as agents do, so the leg is open when the audio ends, the provider closes it
5336
5342
  in the completing publication or the open entry is refused (`task.history.muted.open`),
5337
- and the drive's closing report after the media ended is expected `recorded` and to change nothing:
5343
+ and the drive's closing report after the audio ended is expected `recorded` and to change nothing:
5338
5344
  a record restated afterwards with that leg's duration altered is named (`drive.recordStep.overwritten`).
5339
5345
  Where the provider restates the task's record afterwards, each leg is in it or the hole is named
5340
5346
  (`drive.recordStep.history`). Given `rebuild`, a way to build the adapter again as an agent application reload
@@ -5347,7 +5353,7 @@ the record in memory has nothing and is named (`drive.reload.snapshot`, `drive.r
5347
5353
  `.rejected`). The second adapter's snapshot is taken as any resync is: held to what the stream knew
5348
5354
  before it replaces it, so a phase gone backwards, a record that shrank or audio forgotten on a task
5349
5355
  still at work is named by the stream's own rules (`stream.snapshot.phase`, `.history`,
5350
- `.media`) and a reload is a place those rules keep working, not one where they stop. The second
5356
+ `.audio`) and a reload is a place those rules keep working, not one where they stop. The second
5351
5357
  adapter is held to what the first was: the same provider
5352
5358
  (`drive.reload.manifest`), a snapshot that stands as any snapshot must, and a record that lost none
5353
5359
  of the entries the first had published -- a record once read is not unread across a reload either.
@@ -5374,15 +5380,15 @@ completed from wherever it stands once the drive has nothing left to do on it --
5374
5380
  after an `end-call`, or from `in-progress` where there is no call to end, which is every chat and
5375
5381
  email and a voice task offering no `endCall` -- so a conversation reaches its end as a call does.
5376
5382
  The drive stops where the task offers no way on and says nothing about what it could not reach. A
5377
- softphone adapter written for a browser needs its media APIs supplied by whatever runs the
5378
- harness: the drive opens media outside a browser, and a provider that quietly stopped carrying audio
5383
+ softphone adapter written for a browser needs its audio APIs supplied by whatever runs the
5384
+ harness: the drive opens audio outside a browser, and a provider that quietly stopped carrying audio
5379
5385
  where `AudioContext` was missing would be lying about the one thing the channel is for. It is off by default because it issues
5380
5386
  commands against whatever platform the adapter is connected to: turn it on against a test backend.
5381
5387
 
5382
5388
  ```ts
5383
5389
  const driven = await exerciseAdapter(adapter, context, { collectOnly: true, drive: true });
5384
5390
  expect(driven.violations).toEqual([]);
5385
- assertReached(driven, ["task.onCall", "task.media", "event.task-ended"]);
5391
+ assertReached(driven, ["task.onCall", "task.audio", "event.task-ended"]);
5386
5392
  ```
5387
5393
  `assertReached(result, subjects)` is the paired assertion: it throws naming every subject the run
5388
5394
  never met, so a test that meant to check a team member list cannot pass on a fixture that never produced one.
@@ -5419,11 +5425,11 @@ cannot be established from TypeScript structure alone.
5419
5425
  | `stillHost(report?, guarantees?, mute?)` | An agent application that reports one thing and never changes, for a test context: `{ online: true }` by default, a report with audio for a softphone voice adapter, and never for a desk phone. |
5420
5426
  | `TaskStream`, `BreakStream` | The cross-event models the harness applies after the connect snapshot, exported for an agent application that wants the same rules at its boundary: `seed(snapshot)`, then `apply(envelope)` returns the violations. |
5421
5427
  | `assertBreakFollowsItsRequests(envelopes, snapshot?)` | A break follows its requests: a commit's states only after a grant, never backwards, and a forced break arriving in effect with `forced`. The harness applies the same rules after the connect snapshot. |
5422
- | `assertMediaFollowsTheTask(envelopes, snapshot?)` | The media follows the task and never decides it: every task is introduced once, `task-media-started` and `task-media-ended` alternate on work that has begun, media ends only where it arrived, and what follows the media ending is `completing` or `task-ended`. The harness applies the same rules to every event after the connect snapshot (`stream.*`). A sequence with no media satisfies it by never testing it — pair it with the assertion that the media end is present. |
5428
+ | `assertAudioFollowsTheTask(envelopes, snapshot?)` | The audio follows the task and never decides it: every task is introduced once, `task-audio-started` and `task-audio-ended` alternate on work that has begun, audio ends only where it arrived, and what follows the audio ending is `completing` or `task-ended`. The harness applies the same rules to every event after the connect snapshot (`stream.*`). A sequence with no audio satisfies it by never testing it — pair it with the assertion that the audio end is present. |
5423
5429
  | `assertBreakAttemptProviders(candidates, asked)` | A break attempt asks every usable provider holding capacity, `refreshing` included, and nothing of a provider whose login is `expired`. |
5424
5430
  | `assertBreakBeginsAfterTask(steps)` | A break asked for on a task is committed as `starting-after-task` while work remains and reaches `on-break` only once nothing is outstanding — never beside a task, never later than the step that has none. |
5425
5431
  | `assertDeniedAndRetriedBreak(states)` | A denial transitions directly to `not-requested`; a later request can still be granted. |
5426
- | `assertWrapTimeout(task, mediaEndedAt, deadline, toleranceMs?)` | The wrap deadline equals media end plus the task allowance, within a tolerance that defaults to 1000ms; a task with no allowance has no deadline, and one observed is the violation. |
5432
+ | `assertWrapTimeout(task, audioEndedAt, deadline, toleranceMs?)` | The wrap deadline equals audio end plus the task allowance, within a tolerance that defaults to 1000ms; a task with no allowance has no deadline, and one observed is the violation. |
5427
5433
  | `assertBrowserSessionIsolation(left, right, expected)` | Browser reuse follows only the declared isolation scheme. |
5428
5434
  | `assertNoBrowserSessionKeyCollisions(scenarios)` | No two distinct scenarios derive the same session key. Feed it adversarial names. |
5429
5435
 
@@ -5456,11 +5462,11 @@ action sets. The outer capability may be locked. Absence grants no permission, a
5456
5462
  exist without any permission. A provider may offer only stop for a recording started automatically,
5457
5463
  or withdraw a control on a later task update. There is no global recording mode and no automatic
5458
5464
  start from a capability declaration. Agent application support is declared on `ConnectContext.host.recording`,
5459
- not the provider-owned manifest. The task chooses an explicitly provisioned agent application destination;
5460
- unknown destinations or unsupported actions are refused visibly, never redirected to provider
5461
- recording or a default upload location. Initial agent application support requires voice softphone media and
5465
+ not the provider-owned manifest. The task names one of the storage places the agent application provisioned, by `storageId`;
5466
+ an unknown storage place or an unsupported action is refused visibly, never redirected to provider
5467
+ recording or a default upload location. Initial agent application support requires voice softphone audio and
5462
5468
  capture of both local and remote audio; an agent application unable to capture either must refuse start/resume.
5463
- This package declares that contract; it supplies no recorder, media mixing, storage or upload.
5469
+ This package declares that contract; it supplies no recorder, audio mixing, storage or upload.
5464
5470
 
5465
5471
  | Action | Required current recording state | Confirmed outcome |
5466
5472
  | --- | --- | --- |
@@ -5491,7 +5497,7 @@ There is no automatic restart, transfer to another recorder, or stop on task hol
5491
5497
  Task removal does not prove recording stopped: outstanding agent application recorders remain tracked by the
5492
5498
  agent application until its executor reconciles/finishes them, with visible unresolved cleanup failures.
5493
5499
 
5494
- Only start/resume require an in-progress or paused task with started media. Pause/stop/cancel may
5500
+ Only start/resume require an in-progress or paused task with started audio. Pause/stop/cancel may
5495
5501
  also finish an independently observed recorder while the task is completing. A pending task may
5496
5502
  show active recording, but agent controls wait until interaction begins. The two recording paths may
5497
5503
  both be active. A command to either path has no implied effect on the other.
@@ -5534,9 +5540,9 @@ This change does not publish a package or enable recording in any existing agent
5534
5540
  semantics, including pause/resume identity and rejection of a dialling result. It cannot prove audio
5535
5541
  retention/completion or source truth from a status flag; those remain executor obligations.
5536
5542
 
5537
- Agent application destination selection binds storage when start actually creates a recording. Existing recordings
5543
+ The storage place named on the task is bound when start actually creates a recording. Existing recordings
5538
5544
  keep that binding through pause/resume/stop/cancel; a later policy cannot redirect their stored audio.
5539
- The executor rejects a mismatched destination rather than moving or discarding another binding.
5545
+ The executor rejects a mismatched storage place rather than moving or discarding another binding.
5540
5546
  Action permission does not authorize unattended invocation: agent application controls require the agent's explicit
5541
5547
  act, and provider authorization remains enforced at its authenticated command boundary.
5542
5548