@webex/contact-center 3.12.0-llmrefactor.7 → 3.12.0-llmrefactor.9

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.
Files changed (69) hide show
  1. package/.sdd/manifest.json +3 -2
  2. package/ai-docs/CONTRACTS.md +3 -2
  3. package/dist/cc.js +108 -6
  4. package/dist/cc.js.map +1 -1
  5. package/dist/metrics/MetricsManager.js +16 -0
  6. package/dist/metrics/MetricsManager.js.map +1 -1
  7. package/dist/metrics/behavioral-events.js +91 -0
  8. package/dist/metrics/behavioral-events.js.map +1 -1
  9. package/dist/metrics/constants.js +16 -0
  10. package/dist/metrics/constants.js.map +1 -1
  11. package/dist/services/AnswerCallOnWebexService.js +34 -6
  12. package/dist/services/AnswerCallOnWebexService.js.map +1 -1
  13. package/dist/services/WebexCrossClientService.js +54 -3
  14. package/dist/services/WebexCrossClientService.js.map +1 -1
  15. package/dist/services/WxAppTelephonyMercurySync.js +21 -6
  16. package/dist/services/WxAppTelephonyMercurySync.js.map +1 -1
  17. package/dist/services/task/state-machine/TaskStateMachine.js +0 -17
  18. package/dist/services/task/state-machine/TaskStateMachine.js.map +1 -1
  19. package/dist/services/task/state-machine/guards.js +7 -37
  20. package/dist/services/task/state-machine/guards.js.map +1 -1
  21. package/dist/services/task/voice/Voice.js +81 -14
  22. package/dist/services/task/voice/Voice.js.map +1 -1
  23. package/dist/services/task/voice/wxAppVoiceMethods.js +154 -1
  24. package/dist/services/task/voice/wxAppVoiceMethods.js.map +1 -1
  25. package/dist/services/wxAppDiagnosticLogging.js +122 -0
  26. package/dist/services/wxAppDiagnosticLogging.js.map +1 -0
  27. package/dist/types/cc.d.ts +1 -0
  28. package/dist/types/metrics/MetricsManager.d.ts +6 -0
  29. package/dist/types/metrics/constants.d.ts +15 -0
  30. package/dist/types/services/AnswerCallOnWebexService.d.ts +1 -0
  31. package/dist/types/services/WebexCrossClientService.d.ts +4 -0
  32. package/dist/types/services/task/state-machine/TaskStateMachine.d.ts +0 -42
  33. package/dist/types/services/task/state-machine/guards.d.ts +4 -4
  34. package/dist/types/services/task/voice/Voice.d.ts +5 -1
  35. package/dist/types/services/task/voice/wxAppVoiceMethods.d.ts +3 -0
  36. package/dist/types/services/wxAppDiagnosticLogging.d.ts +51 -0
  37. package/dist/webex.js +1 -1
  38. package/package.json +8 -8
  39. package/src/cc.ts +155 -7
  40. package/src/metrics/MetricsManager.ts +16 -0
  41. package/src/metrics/ai-docs/metrics-spec.md +71 -9
  42. package/src/metrics/behavioral-events.ts +92 -0
  43. package/src/metrics/constants.ts +18 -0
  44. package/src/services/AnswerCallOnWebexService.ts +41 -8
  45. package/src/services/WebexCrossClientService.ts +85 -4
  46. package/src/services/WxAppTelephonyMercurySync.ts +31 -4
  47. package/src/services/agent/ai-docs/agent-spec.md +1 -0
  48. package/src/services/task/ai-docs/task-spec.md +17 -16
  49. package/src/services/task/state-machine/TaskStateMachine.ts +0 -20
  50. package/src/services/task/state-machine/ai-docs/AGENTS.md +2 -4
  51. package/src/services/task/state-machine/ai-docs/ARCHITECTURE.md +8 -9
  52. package/src/services/task/state-machine/ai-docs/task-state-machine-spec.md +5 -7
  53. package/src/services/task/state-machine/guards.ts +7 -63
  54. package/src/services/task/voice/Voice.ts +115 -26
  55. package/src/services/task/voice/wxAppVoiceMethods.ts +211 -2
  56. package/src/services/wxAppDiagnosticLogging.ts +174 -0
  57. package/test/unit/spec/cc.ts +251 -22
  58. package/test/unit/spec/metrics/MetricsManager.ts +25 -0
  59. package/test/unit/spec/metrics/behavioral-events.ts +42 -0
  60. package/test/unit/spec/services/AnswerCallOnWebexService.ts +41 -0
  61. package/test/unit/spec/services/WebexCrossClientService.ts +207 -1
  62. package/test/unit/spec/services/WxAppTelephonyMercurySync.ts +23 -0
  63. package/test/unit/spec/services/task/state-machine/TaskStateMachine.ts +72 -46
  64. package/test/unit/spec/services/task/state-machine/guards.ts +6 -6
  65. package/test/unit/spec/services/task/voice/Voice.ts +380 -0
  66. package/test/unit/spec/services/task/voice/wxAppVoiceMethods.ts +145 -1
  67. package/test/unit/spec/services/wxAppDiagnosticLogging.ts +143 -0
  68. package/umd/contact-center.min.js +2 -2
  69. package/umd/contact-center.min.js.map +1 -1
@@ -199,13 +199,6 @@ export declare function getTaskStateMachineConfig(uiControlConfig: UIControlConf
199
199
  }) => boolean;
200
200
  actions: string[];
201
201
  })[];
202
- PARTICIPANT_LEAVE: ({
203
- guard: (params: any) => boolean;
204
- target: TaskState;
205
- actions: string[];
206
- } | {
207
- actions: string[];
208
- })[];
209
202
  CONTACT_ENDED: ({
210
203
  guard: ({ context, event }: import("./guards").GuardParams) => boolean;
211
204
  target: TaskState;
@@ -246,13 +239,6 @@ export declare function getTaskStateMachineConfig(uiControlConfig: UIControlConf
246
239
  target: TaskState;
247
240
  actions: string[];
248
241
  };
249
- PARTICIPANT_LEAVE: ({
250
- guard: (params: any) => boolean;
251
- target: TaskState;
252
- actions: string[];
253
- } | {
254
- actions: string[];
255
- })[];
256
242
  OUTBOUND_FAILED: ({
257
243
  guard: ({ context, event }: import("./guards").GuardParams) => boolean;
258
244
  target: TaskState;
@@ -549,13 +535,6 @@ export declare function getTaskStateMachineConfig(uiControlConfig: UIControlConf
549
535
  target: TaskState;
550
536
  actions: string[];
551
537
  })[];
552
- PARTICIPANT_LEAVE: ({
553
- guard: (params: any) => boolean;
554
- target: TaskState;
555
- actions: string[];
556
- } | {
557
- actions: string[];
558
- })[];
559
538
  OUTBOUND_FAILED: ({
560
539
  guard: ({ context, event }: import("./guards").GuardParams) => boolean;
561
540
  target: TaskState;
@@ -897,13 +876,6 @@ export declare function createTaskStateMachine(uiControlConfig: UIControlConfig,
897
876
  }) => boolean;
898
877
  actions: string[];
899
878
  })[];
900
- PARTICIPANT_LEAVE: ({
901
- guard: (params: any) => boolean;
902
- target: TaskState;
903
- actions: string[];
904
- } | {
905
- actions: string[];
906
- })[];
907
879
  CONTACT_ENDED: ({
908
880
  guard: ({ context, event }: import("./guards").GuardParams) => boolean;
909
881
  target: TaskState;
@@ -944,13 +916,6 @@ export declare function createTaskStateMachine(uiControlConfig: UIControlConfig,
944
916
  target: TaskState;
945
917
  actions: string[];
946
918
  };
947
- PARTICIPANT_LEAVE: ({
948
- guard: (params: any) => boolean;
949
- target: TaskState;
950
- actions: string[];
951
- } | {
952
- actions: string[];
953
- })[];
954
919
  OUTBOUND_FAILED: ({
955
920
  guard: ({ context, event }: import("./guards").GuardParams) => boolean;
956
921
  target: TaskState;
@@ -1247,13 +1212,6 @@ export declare function createTaskStateMachine(uiControlConfig: UIControlConfig,
1247
1212
  target: TaskState;
1248
1213
  actions: string[];
1249
1214
  })[];
1250
- PARTICIPANT_LEAVE: ({
1251
- guard: (params: any) => boolean;
1252
- target: TaskState;
1253
- actions: string[];
1254
- } | {
1255
- actions: string[];
1256
- })[];
1257
1215
  OUTBOUND_FAILED: ({
1258
1216
  guard: ({ context, event }: import("./guards").GuardParams) => boolean;
1259
1217
  target: TaskState;
@@ -80,10 +80,10 @@ export declare const guards: {
80
80
  /**
81
81
  * True when an updated lifecycle event shows that this agent left the main interaction.
82
82
  *
83
- * Explicit self-participant evidence is authoritative. Main-call membership is used only
84
- * for the from-conference nested-consult race where CONSULT_END still represents the agent as
85
- * active on the consult leg after removing them from the main leg. Partial or ordinary call
86
- * snapshots are not treated as a departure.
83
+ * Returns true when the event names this agent, or when this agent is absent from the
84
+ * updated participants map. EP-DN payloads remove the leaving participant instead of
85
+ * setting hasLeft. Remaining in the map with hasLeft, or disappearing only from
86
+ * mainCall media, is not treated as departure.
87
87
  */
88
88
  didCurrentAgentLeaveMainInteraction: ({ context, event }: GuardParams) => boolean;
89
89
  /**
@@ -12,7 +12,9 @@ export default class Voice extends Task implements IVoice {
12
12
  private wxAppAnswerPending;
13
13
  private wxAppAcceptInFlight;
14
14
  private wxAppMuteSyncInFlight?;
15
- private wxAppMuteToggleInFlight?;
15
+ private wxAppMuteToggleTail;
16
+ private wxAppDtmfTail;
17
+ private lastLoggedWxAppAcceptReason?;
16
18
  constructor(contact: ReturnType<typeof routingContact>, data: TaskData, callOptions?: VoiceUIControlOptions, wrapupData?: WrapupData, agentId?: string);
17
19
  private getWxAppVoiceDependencies;
18
20
  /** @deprecated Use {@link Voice.getWxAppVoiceDependencies} */
@@ -22,6 +24,8 @@ export default class Voice extends Task implements IVoice {
22
24
  private setWxAppAnswerPending;
23
25
  private setWxAppAcceptInFlight;
24
26
  setEnableWxBetterTogether(enabled: boolean): void;
27
+ protected updateUiControls(forceEmit?: boolean): void;
28
+ private logWxAppOfferDecisionIfNeeded;
25
29
  applyWxAppMuteStateFromSync(incomingCallId: string, muted: boolean): void;
26
30
  getWxAppMuted(): boolean;
27
31
  private static delay;
@@ -1,11 +1,13 @@
1
1
  import AnswerCallOnWebexService from '../../AnswerCallOnWebexService';
2
2
  import { TaskData, TaskToggleMuteOptions, TaskTransmitDtmfOptions } from '../types';
3
3
  import { TaskState } from '../state-machine';
4
+ import MetricsManager from '../../../metrics/MetricsManager';
4
5
  import { WebexCallingDeviceDetails } from '../WebexCallingUtils';
5
6
  export type WxAppVoiceDependencies = {
6
7
  enableWxBetterTogether: boolean;
7
8
  answerCallOnWebexService?: AnswerCallOnWebexService;
8
9
  agentId?: string;
10
+ metricsManager: MetricsManager;
9
11
  getTaskData: () => TaskData;
10
12
  getTaskState: () => TaskState | undefined;
11
13
  getWxAppMuted: () => boolean;
@@ -47,6 +49,7 @@ export declare function runWxAppAccept(deps: WxAppVoiceDependencies, lifecycle:
47
49
  export declare function runWxAppReject(deps: WxAppVoiceDependencies, lifecycle: WxAppVoiceLifecycle, options?: {
48
50
  lineOwnerId?: string;
49
51
  }): Promise<void>;
52
+ export declare function runWxAppOutdialDecline<T>(deps: WxAppVoiceDependencies, executeCancel: () => Promise<T>): Promise<T>;
50
53
  export declare function runWxAppToggleMute(deps: WxAppVoiceDependencies, lifecycle: WxAppVoiceLifecycle, options?: TaskToggleMuteOptions): Promise<void>;
51
54
  export declare function runWxAppTransmitDtmf(deps: WxAppVoiceDependencies, lifecycle: WxAppVoiceLifecycle, options: TaskTransmitDtmfOptions): Promise<void>;
52
55
  export declare function mapWxAppVoiceError(error: unknown, method: string, module: string): never;
@@ -0,0 +1,51 @@
1
+ export declare const WXAPP_LOG_FEATURE = "wxApp";
2
+ export declare const WXAPP_LOG_PREFIX = "[CC wxApp]";
3
+ export type WxAppAcceptReason = 'wxApp_offer_ready' | 'wxApp_answer_pending' | 'wxApp_accept_in_flight' | 'extension_non_wxApp_offer' | 'browser_webrtc_offer' | 'outdial_auto_answer';
4
+ export type WxAppSessionSkipReason = 'unsupported_browser_login' | 'flag_disabled' | 'mercury_subscribe_failed' | 'publish_failed';
5
+ export type WxAppTelephonyAction = 'accept' | 'decline' | 'mute' | 'dtmf';
6
+ export type WxAppTelephonyPhase = 'started' | 'success' | 'failed';
7
+ /** Last 8 chars of callId for correlation without logging full id. */
8
+ export declare function callIdSuffix(callId: string | null | undefined): string | undefined;
9
+ export declare function logWxAppSessionReadiness(params: {
10
+ enableWxBetterTogether: boolean;
11
+ loginOption: string | undefined;
12
+ wxAppHooksApplied: boolean;
13
+ usersubPublished: boolean;
14
+ mercurySubscribed: boolean;
15
+ telephonyTaskType: 'Voice' | 'WebRTC' | 'unknown';
16
+ skipReason?: WxAppSessionSkipReason;
17
+ }): void;
18
+ export declare function deriveWxAppAcceptReason(params: {
19
+ isWxAppInboundOffer: boolean;
20
+ isWxAppOutdialOffer: boolean;
21
+ isWebrtc: boolean;
22
+ isOutdial: boolean;
23
+ wxAppAcceptInFlight: boolean;
24
+ wxAppAnswerPending: boolean;
25
+ enableWxBetterTogether: boolean;
26
+ hasDeviceCallId: boolean;
27
+ }): WxAppAcceptReason;
28
+ export declare function logWxAppOfferDecision(params: {
29
+ interactionId: string;
30
+ acceptVisible: boolean;
31
+ acceptEnabled: boolean;
32
+ acceptReason: WxAppAcceptReason;
33
+ wxAppParticipantDeviceType?: string;
34
+ hasDeviceCallId: boolean;
35
+ }): void;
36
+ export declare function logWxAppTelephonyAction(params: {
37
+ action: WxAppTelephonyAction;
38
+ phase: WxAppTelephonyPhase;
39
+ interactionId?: string;
40
+ trackingId?: string;
41
+ httpStatus?: number | string;
42
+ failureReason?: string;
43
+ }): void;
44
+ export declare function logWxAppValidationFailure(reason: string, interactionId?: string): void;
45
+ export declare function logWxAppMercuryMuteSync(params: {
46
+ phase: 'received' | 'applied' | 'dropped';
47
+ muted?: boolean;
48
+ callIdSuffix?: string;
49
+ interactionId?: string;
50
+ dropReason?: string;
51
+ }): void;
package/dist/webex.js CHANGED
@@ -41,7 +41,7 @@ if (!global.Buffer) {
41
41
  */
42
42
  const Webex = _webexCore.default.extend({
43
43
  webex: true,
44
- version: `3.12.0-llmrefactor.7`
44
+ version: `3.12.0-llmrefactor.9`
45
45
  });
46
46
 
47
47
  /**
package/package.json CHANGED
@@ -46,13 +46,13 @@
46
46
  },
47
47
  "dependencies": {
48
48
  "@types/platform": "1.3.4",
49
- "@webex/calling": "3.12.0-llmrefactor.4",
50
- "@webex/internal-plugin-mercury": "3.12.0-llmrefactor.5",
51
- "@webex/internal-plugin-metrics": "3.12.0-llmrefactor.3",
52
- "@webex/internal-plugin-support": "3.12.0-llmrefactor.5",
53
- "@webex/plugin-authorization": "3.12.0-llmrefactor.3",
54
- "@webex/plugin-logger": "3.12.0-llmrefactor.3",
55
- "@webex/webex-core": "3.12.0-llmrefactor.3",
49
+ "@webex/calling": "3.12.0-llmrefactor.6",
50
+ "@webex/internal-plugin-mercury": "3.12.0-llmrefactor.7",
51
+ "@webex/internal-plugin-metrics": "3.12.0-llmrefactor.5",
52
+ "@webex/internal-plugin-support": "3.12.0-llmrefactor.7",
53
+ "@webex/plugin-authorization": "3.12.0-llmrefactor.5",
54
+ "@webex/plugin-logger": "3.12.0-llmrefactor.5",
55
+ "@webex/webex-core": "3.12.0-llmrefactor.5",
56
56
  "jest-html-reporters": "3.0.11",
57
57
  "lodash": "^4.17.21",
58
58
  "uuid": "^3.3.2",
@@ -84,5 +84,5 @@
84
84
  "typedoc": "^0.25.0",
85
85
  "typescript": "5.4.5"
86
86
  },
87
- "version": "3.12.0-llmrefactor.7"
87
+ "version": "3.12.0-llmrefactor.9"
88
88
  }
package/src/cc.ts CHANGED
@@ -59,6 +59,7 @@ import WebCallingService from './services/WebCallingService';
59
59
  import AnswerCallOnWebexService from './services/AnswerCallOnWebexService';
60
60
  import WebexCrossClientService from './services/WebexCrossClientService';
61
61
  import WxAppTelephonyMercurySync from './services/WxAppTelephonyMercurySync';
62
+ import {logWxAppSessionReadiness} from './services/wxAppDiagnosticLogging';
62
63
  import {
63
64
  ITask,
64
65
  TASK_EVENTS,
@@ -1015,14 +1016,15 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
1015
1016
  }
1016
1017
  }
1017
1018
 
1019
+ const deviceId = this.getDeviceId(data.loginOption, data.dialNumber);
1018
1020
  const loginResponse = await this.services.agent.stationLogin({
1019
1021
  data: {
1020
- dialNumber:
1021
- data.loginOption === LoginOption.BROWSER ? this.agentConfig.agentId : data.dialNumber,
1022
+ // BROWSER DN must be webrtc-{agentId} so VPOP/RTMS do not treat a bare UUID as PSTN.
1023
+ dialNumber: data.loginOption === LoginOption.BROWSER ? deviceId : data.dialNumber,
1022
1024
  teamId: data.teamId,
1023
1025
  deviceType: data.loginOption,
1024
1026
  isExtension: data.loginOption === LoginOption.EXTENSION,
1025
- deviceId: this.getDeviceId(data.loginOption, data.dialNumber),
1027
+ deviceId,
1026
1028
  roles: [AGENT],
1027
1029
  teamName: EMPTY_STRING,
1028
1030
  siteId: EMPTY_STRING,
@@ -1562,25 +1564,120 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
1562
1564
  }
1563
1565
  }
1564
1566
 
1567
+ private getWxAppTelephonyTaskType(): 'Voice' | 'WebRTC' | 'unknown' {
1568
+ const loginOption = this.getCurrentStationLoginOption();
1569
+
1570
+ if (loginOption === LoginOption.BROWSER) {
1571
+ return 'WebRTC';
1572
+ }
1573
+
1574
+ if (loginOption === LoginOption.EXTENSION || loginOption === LoginOption.AGENT_DN) {
1575
+ return 'Voice';
1576
+ }
1577
+
1578
+ return 'unknown';
1579
+ }
1580
+
1565
1581
  private async ensureWxAppPostStationLogin(): Promise<void> {
1566
- if (this.getCurrentStationLoginOption() === LoginOption.BROWSER) {
1582
+ const loginOption = this.getCurrentStationLoginOption();
1583
+ const flagEnabled = this.isWxBetterTogetherEnabled();
1584
+ const telephonyTaskType = this.getWxAppTelephonyTaskType();
1585
+
1586
+ if (loginOption === LoginOption.BROWSER) {
1587
+ if (flagEnabled) {
1588
+ logWxAppSessionReadiness({
1589
+ enableWxBetterTogether: true,
1590
+ loginOption,
1591
+ wxAppHooksApplied: false,
1592
+ usersubPublished: false,
1593
+ mercurySubscribed: false,
1594
+ telephonyTaskType,
1595
+ skipReason: 'unsupported_browser_login',
1596
+ });
1597
+
1598
+ this.metricsManager.trackEvent(
1599
+ METRIC_EVENT_NAMES.WXAPP_SESSION_SKIPPED,
1600
+ {
1601
+ loginOption,
1602
+ enableWxBetterTogether: true,
1603
+ skipReason: 'unsupported_browser_login',
1604
+ },
1605
+ ['operational', 'behavioral']
1606
+ );
1607
+ }
1608
+
1567
1609
  return;
1568
1610
  }
1569
1611
 
1570
1612
  let publishedEnable = false;
1613
+ let wxAppInitStage: 'mercury' | 'publish' = 'mercury';
1571
1614
 
1572
1615
  try {
1573
- if (this.isWxBetterTogetherEnabled()) {
1616
+ if (flagEnabled) {
1617
+ this.metricsManager.timeEvent([
1618
+ METRIC_EVENT_NAMES.WXAPP_SESSION_INIT_SUCCESS,
1619
+ METRIC_EVENT_NAMES.WXAPP_SESSION_INIT_FAILED,
1620
+ ]);
1621
+
1574
1622
  await this.ensureWxAppMercuryAndSubscribe();
1623
+ wxAppInitStage = 'publish';
1575
1624
  await this.publishAnswerOnWebexCrossClientState(true);
1576
1625
  publishedEnable = true;
1577
1626
  this.taskManager.syncWxAppMuteFromCallDetailsForAllTasks();
1627
+
1628
+ const mercurySubscribed = this.wxAppTelephonyMercurySync.isSubscribed();
1629
+ const usersubPublished = this.webexCrossClientService.isAnswerCallsStateActive();
1630
+
1631
+ logWxAppSessionReadiness({
1632
+ enableWxBetterTogether: true,
1633
+ loginOption,
1634
+ wxAppHooksApplied: true,
1635
+ usersubPublished,
1636
+ mercurySubscribed,
1637
+ telephonyTaskType,
1638
+ });
1639
+
1640
+ const sessionInitReady = mercurySubscribed && usersubPublished;
1641
+
1642
+ if (sessionInitReady) {
1643
+ this.metricsManager.trackEvent(
1644
+ METRIC_EVENT_NAMES.WXAPP_SESSION_INIT_SUCCESS,
1645
+ {loginOption, enableWxBetterTogether: true},
1646
+ ['operational', 'behavioral']
1647
+ );
1648
+ } else {
1649
+ this.metricsManager.trackEvent(
1650
+ METRIC_EVENT_NAMES.WXAPP_SESSION_INIT_FAILED,
1651
+ {
1652
+ loginOption,
1653
+ enableWxBetterTogether: true,
1654
+ skipReason: !usersubPublished ? 'usersub_not_published' : 'mercury_not_subscribed',
1655
+ },
1656
+ ['operational', 'behavioral']
1657
+ );
1658
+ }
1578
1659
  } else {
1579
1660
  await this.ensureWxAppDeviceRegistered();
1580
1661
  await this.publishAnswerOnWebexCrossClientState(false, {force: true});
1581
1662
  this.webexCrossClientService.teardown();
1582
1663
  this.wxAppTelephonyMercurySync.unsubscribe();
1583
1664
  await this.releaseWxAppMercuryResources();
1665
+
1666
+ logWxAppSessionReadiness({
1667
+ enableWxBetterTogether: false,
1668
+ loginOption,
1669
+ wxAppHooksApplied: true,
1670
+ usersubPublished: false,
1671
+ mercurySubscribed: false,
1672
+ telephonyTaskType,
1673
+ skipReason: 'flag_disabled',
1674
+ });
1675
+
1676
+ this.metricsManager.trackEvent(
1677
+ METRIC_EVENT_NAMES.WXAPP_SESSION_SKIPPED,
1678
+ {loginOption, enableWxBetterTogether: false, skipReason: 'flag_disabled'},
1679
+ ['operational', 'behavioral']
1680
+ );
1584
1681
  }
1585
1682
  } catch (error) {
1586
1683
  LoggerProxy.error(`Failed to initialize wxApp post-station-login: ${error}`, {
@@ -1588,7 +1685,32 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
1588
1685
  method: METHODS.STATION_LOGIN,
1589
1686
  });
1590
1687
 
1591
- if (this.isWxBetterTogetherEnabled()) {
1688
+ if (flagEnabled) {
1689
+ const sessionInitFailureReason =
1690
+ wxAppInitStage === 'mercury' ? 'mercury_subscribe_failed' : 'publish_failed';
1691
+
1692
+ this.metricsManager.trackEvent(
1693
+ METRIC_EVENT_NAMES.WXAPP_SESSION_INIT_FAILED,
1694
+ {
1695
+ loginOption,
1696
+ enableWxBetterTogether: true,
1697
+ skipReason: sessionInitFailureReason,
1698
+ error: error instanceof Error ? error.toString() : String(error),
1699
+ },
1700
+ ['operational', 'behavioral']
1701
+ );
1702
+
1703
+ logWxAppSessionReadiness({
1704
+ enableWxBetterTogether: true,
1705
+ loginOption,
1706
+ wxAppHooksApplied: false,
1707
+ usersubPublished:
1708
+ publishedEnable && this.webexCrossClientService.isAnswerCallsStateActive(),
1709
+ mercurySubscribed: this.wxAppTelephonyMercurySync.isSubscribed(),
1710
+ telephonyTaskType,
1711
+ skipReason: sessionInitFailureReason,
1712
+ });
1713
+
1592
1714
  if (publishedEnable) {
1593
1715
  await this.revertWxAppCrossClientPublish();
1594
1716
  } else {
@@ -1829,6 +1951,12 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
1829
1951
  method: METHODS.SYNC_WXAPP_MUTE_FROM_MERCURY,
1830
1952
  });
1831
1953
 
1954
+ this.metricsManager.trackEvent(
1955
+ METRIC_EVENT_NAMES.WXAPP_MERCURY_SUBSCRIBE_FAILED,
1956
+ {error: 'agentId unavailable'},
1957
+ ['operational', 'behavioral']
1958
+ );
1959
+
1832
1960
  return;
1833
1961
  }
1834
1962
 
@@ -1842,6 +1970,11 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
1842
1970
  module: CC_FILE,
1843
1971
  method: METHODS.SYNC_WXAPP_MUTE_FROM_MERCURY,
1844
1972
  });
1973
+ this.metricsManager.trackEvent(
1974
+ METRIC_EVENT_NAMES.WXAPP_MERCURY_SUBSCRIBE_FAILED,
1975
+ {error: error instanceof Error ? error.toString() : String(error)},
1976
+ ['operational', 'behavioral']
1977
+ );
1845
1978
  this.wxAppTelephonyMercurySync.unsubscribe();
1846
1979
  await this.releaseWxAppMercuryResources();
1847
1980
  throw error;
@@ -1862,10 +1995,25 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
1862
1995
 
1863
1996
  const userId = this.$webex.internal.device?.userId;
1864
1997
  if (!userId) {
1998
+ if (enable && this.isWxBetterTogetherEnabled()) {
1999
+ this.metricsManager.trackEvent(
2000
+ METRIC_EVENT_NAMES.WXAPP_USERSUB_PUBLISH_FAILED,
2001
+ {
2002
+ enableWxBetterTogether: true,
2003
+ skipReason: 'user_id_unavailable',
2004
+ error: 'User ID is unavailable for cross-client publish',
2005
+ },
2006
+ ['operational', 'behavioral']
2007
+ );
2008
+ }
2009
+
1865
2010
  return;
1866
2011
  }
1867
2012
 
1868
- await this.webexCrossClientService.setManageWebexCallingInWxcc(enable, {userId});
2013
+ await this.webexCrossClientService.setManageWebexCallingInWxcc(enable, {
2014
+ userId,
2015
+ trackPublishMetrics: true,
2016
+ });
1869
2017
 
1870
2018
  if (enable) {
1871
2019
  this.clearWxAppFalsePublishRetryTimer();
@@ -412,6 +412,22 @@ export default class MetricsManager {
412
412
  this.runningEvents[genericKey] = {startTime: Date.now(), keys: new Set(keyArray)};
413
413
  }
414
414
 
415
+ /**
416
+ * Clears a running timed event without emitting a metric.
417
+ * @param keys - A string or array of strings representing event keys (same as timeEvent).
418
+ * @public
419
+ */
420
+ public cancelTimedEvent(keys: string | string[]): void {
421
+ if (this.isMetricsDisabled()) {
422
+ return;
423
+ }
424
+ const keyArray = Array.isArray(keys) ? keys : [keys];
425
+ if (keyArray.length === 0) {
426
+ return;
427
+ }
428
+ delete this.runningEvents[keyArray[0]];
429
+ }
430
+
415
431
  /**
416
432
  * Sets the Webex SDK instance and marks the manager as ready when the SDK is ready.
417
433
  * @param webex - The Webex SDK instance.
@@ -35,6 +35,8 @@ Metrics is one of nine confirmed Contact Center SDK modules. Own timing, taxonom
35
35
 
36
36
  - **Behavioral Taxonomy**: Structured `product.agent.target.verb` naming convention for behavioral events
37
37
 
38
+ - **Webex Together behavioral naming**: Webex Together (wxApp) events use `*_webex_together` compound targets (e.g. `wxcc_sdk.user.task_accept_webex_together.complete`). Operational/business wire names remain `WXCC_SDK_WXAPP_*` unchanged.
39
+
38
40
  - **Payload Preparation**: Automatic cleanup of empty fields, space-to-underscore conversion, and `tabHidden` metadata
39
41
 
40
42
  - **AQM Response Helpers**: Static methods to extract common tracking fields from AQM responses
@@ -236,6 +238,14 @@ All event names are defined in `METRIC_EVENT_NAMES` (`constants.ts`). Events fol
236
238
  | `TASK_ACCEPT_CONSULT_SUCCESS` / `FAILED` | `'Task Accept Consult ...'` | Accept consult result |
237
239
  | `TASK_AUTO_ANSWER_SUCCESS` / `FAILED` | `'Task Auto Answer ...'` | Auto-answer result |
238
240
  | `TASK_OUTDIAL_SUCCESS` / `FAILED` | `'Task Outdial ...'` | Outdial result |
241
+ | `WXAPP_TASK_MUTE_SUCCESS` / `FAILED` | `'WxApp Task Mute ...'` | Webex Together task mute/unmute toggle (`wxcc_sdk.user.task_mute_webex_together.complete\|fail`). Mute telephony is queued per task via tail promise chain (`Voice.wxAppMuteToggleTail`) so concurrent toggles do not overwrite the shared `timeEvent` timer or reorder requests. |
242
+ | `WXAPP_TASK_DTMF_SUCCESS` / `FAILED` | `'WxApp Task Dtmf ...'` | Webex Together DTMF/keypad (`wxcc_sdk.user.task_dtmf_webex_together.complete\|fail`). DTMF telephony is queued per task via tail promise chain (`Voice.wxAppDtmfTail`) so concurrent keypad input does not overwrite the shared `timeEvent` timer or reorder digits. |
243
+ | `WXAPP_TASK_ACCEPT_SUCCESS` / `FAILED` | `'WxApp Task Accept ...'` | Webex Together accept/answer (`wxcc_sdk.user.task_accept_webex_together.complete\|fail`) |
244
+ | `WXAPP_TASK_DECLINE_SUCCESS` / `FAILED` | `'WxApp Task Decline ...'` | Webex Together reject/decline (`wxcc_sdk.user.task_reject_webex_together.complete\|fail`). Inbound offers: telephony `rejectCall` via `runWxAppReject`. wxApp outdial cancellations: CC `cancelTask` via `runWxAppOutdialDecline` (additive with `TASK_DECLINE_*`). Outdial failure payloads merge AQM `error.details` via `getCommonTrackingFieldForAQMResponseFailed` so wxApp metrics and diagnostic logs preserve `trackingId` / structured failure reason. |
245
+ | `WXAPP_SESSION_INIT_SUCCESS` / `FAILED` | `'WxApp Session Init ...'` | Webex Together session orchestration (`wxcc_sdk.user.webex_together_session_init.complete\|fail`) |
246
+ | `WXAPP_SESSION_SKIPPED` | `'WxApp Session Skipped'` | Webex Together session skipped (`wxcc_sdk.user.webex_together_session_init.ignore`) |
247
+ | `WXAPP_USERSUB_PUBLISH_SUCCESS` / `FAILED` | `'WxApp Usersub Publish ...'` | Cross-client usersub publish (`wxcc_sdk.user.webex_together_usersub_publish.complete\|fail`). Preflight failures (missing `userId` or device URL before HTTP publish) emit `WXAPP_USERSUB_PUBLISH_FAILED` with `skipReason` (`user_id_unavailable` / `device_url_unavailable`) and no `timeEvent` timer. Stale-generation discards (teardown or concurrent disable while HTTP publish is in flight) call `cancelTimedEvent` without emitting success/fail only when the completing publish still owns the active timer (`usersubPublishMetricsId` guard — a newer overlapping publish must not have its timer cleared). |
248
+ | `WXAPP_MERCURY_SUBSCRIBE_SUCCESS` / `FAILED` | `'WxApp Mercury Subscribe ...'` | Telephony Mercury mute-sync subscribe (`wxcc_sdk.user.webex_together_mercury_subscribe.complete\|fail`) |
239
249
  | `TASK_CONFERENCE_START_SUCCESS` / `FAILED` | `'Task Conference Start ...'` | Conference start result |
240
250
  | `TASK_CONFERENCE_END_SUCCESS` / `FAILED` | `'Task Conference End ...'` | Conference end result |
241
251
  | `TASK_CONFERENCE_TRANSFER_SUCCESS` / `FAILED` | `'Task Conference Transfer ...'` | Conference transfer result |
@@ -281,6 +291,13 @@ All event names are defined in `constants.ts` as `METRIC_EVENT_NAMES`. Events fo
281
291
  | Conference Participant Drop | `TASK_CONFERENCE_PARTICIPANT_DROP_SUCCESS` | `TASK_CONFERENCE_PARTICIPANT_DROP_FAILED` |
282
292
  | Switch Call | `TASK_SWITCH_CALL_SUCCESS` | `TASK_SWITCH_CALL_FAILED` |
283
293
  | Outdial | `TASK_OUTDIAL_SUCCESS` | `TASK_OUTDIAL_FAILED` |
294
+ | WxApp Task Mute | `WXAPP_TASK_MUTE_SUCCESS` | `WXAPP_TASK_MUTE_FAILED` |
295
+ | WxApp Task DTMF | `WXAPP_TASK_DTMF_SUCCESS` | `WXAPP_TASK_DTMF_FAILED` |
296
+ | WxApp Task Accept | `WXAPP_TASK_ACCEPT_SUCCESS` | `WXAPP_TASK_ACCEPT_FAILED` |
297
+ | WxApp Task Decline | `WXAPP_TASK_DECLINE_SUCCESS` | `WXAPP_TASK_DECLINE_FAILED` |
298
+ | WxApp Session Init | `WXAPP_SESSION_INIT_SUCCESS` | `WXAPP_SESSION_INIT_FAILED` |
299
+ | WxApp Usersub Publish | `WXAPP_USERSUB_PUBLISH_SUCCESS` | `WXAPP_USERSUB_PUBLISH_FAILED` |
300
+ | WxApp Mercury Subscribe | `WXAPP_MERCURY_SUBSCRIBE_SUCCESS` | `WXAPP_MERCURY_SUBSCRIBE_FAILED` |
284
301
  | Upload Logs | `UPLOAD_LOGS_SUCCESS` | `UPLOAD_LOGS_FAILED` |
285
302
  | WebSocket Deregister | `WEBSOCKET_DEREGISTER_SUCCESS` | `WEBSOCKET_DEREGISTER_FAIL` |
286
303
  | Device Type Update | `AGENT_DEVICE_TYPE_UPDATE_SUCCESS` | `AGENT_DEVICE_TYPE_UPDATE_FAILED` |
@@ -289,6 +306,22 @@ All event names are defined in `constants.ts` as `METRIC_EVENT_NAMES`. Events fo
289
306
  | Queue | `QUEUE_FETCH_SUCCESS` | `QUEUE_FETCH_FAILED` |
290
307
  | Outdial ANI Entries | `OUTDIAL_ANI_EP_FETCH_SUCCESS` | `OUTDIAL_ANI_EP_FETCH_FAILED` |
291
308
 
309
+ ### Webex Together behavioral taxonomy
310
+
311
+ Webex Together events (`WXAPP_*` constants) use `*_webex_together` compound targets. Assembled Amplitude names follow `wxcc_sdk.user.{target}.{verb}`:
312
+
313
+ | Feature | Behavioral target | Success name | Failure name | Skip name |
314
+ |---|---|---|---|---|
315
+ | Task accept / answer | `task_accept_webex_together` | `wxcc_sdk.user.task_accept_webex_together.complete` | `wxcc_sdk.user.task_accept_webex_together.fail` | — |
316
+ | Task reject / decline | `task_reject_webex_together` | `wxcc_sdk.user.task_reject_webex_together.complete` | `wxcc_sdk.user.task_reject_webex_together.fail` | — |
317
+ | Task mute / unmute toggle | `task_mute_webex_together` | `wxcc_sdk.user.task_mute_webex_together.complete` | `wxcc_sdk.user.task_mute_webex_together.fail` | — |
318
+ | Task DTMF / keypad | `task_dtmf_webex_together` | `wxcc_sdk.user.task_dtmf_webex_together.complete` | `wxcc_sdk.user.task_dtmf_webex_together.fail` | — |
319
+ | Usersub publish | `webex_together_usersub_publish` | `wxcc_sdk.user.webex_together_usersub_publish.complete` | `wxcc_sdk.user.webex_together_usersub_publish.fail` | — |
320
+ | Mercury subscribe | `webex_together_mercury_subscribe` | `wxcc_sdk.user.webex_together_mercury_subscribe.complete` | `wxcc_sdk.user.webex_together_mercury_subscribe.fail` | — |
321
+ | Session init | `webex_together_session_init` | `wxcc_sdk.user.webex_together_session_init.complete` | `wxcc_sdk.user.webex_together_session_init.fail` | `wxcc_sdk.user.webex_together_session_init.ignore` |
322
+
323
+ Operational and business wire names are unchanged (`WXCC_SDK_WXAPP_*`).
324
+
292
325
  Special events (no success/failure pair):
293
326
 
294
327
  - `AGENT_RONA` — has behavioral taxonomy (`service.agent_rona.set`)
@@ -299,11 +332,13 @@ Special events (no success/failure pair):
299
332
 
300
333
  - `WEBSOCKET_EVENT_RECEIVED` — **no** behavioral taxonomy (not in `eventTaxonomyMap`)
301
334
 
302
- Of the 82 defined metric names, 73 have behavioral taxonomy and 9 do not. Events **without** an `eventTaxonomyMap` entry are the six `AI_ASSISTANT_*` names plus `WEBSOCKET_DEREGISTER_SUCCESS`, `WEBSOCKET_DEREGISTER_FAIL`, and `WEBSOCKET_EVENT_RECEIVED`.
335
+ - `WXAPP_SESSION_SKIPPED` — has behavioral taxonomy (`wxcc_sdk.user.webex_together_session_init.ignore`)
336
+
337
+ Of the 107 defined metric names, 96 have behavioral taxonomy and 11 do not. Events **without** an `eventTaxonomyMap` entry are the eight `AI_ASSISTANT_*` names plus `WEBSOCKET_DEREGISTER_SUCCESS`, `WEBSOCKET_DEREGISTER_FAIL`, and `WEBSOCKET_EVENT_RECEIVED`.
303
338
 
304
339
  ### Complete METRIC_EVENT_NAMES catalog
305
340
 
306
- This table contains all 82 names from `src/metrics/constants.ts`; taxonomy presence is checked against `src/metrics/behavioral-events.ts`: 73 mapped and 9 unmapped.
341
+ This table contains all 107 names from `src/metrics/constants.ts`; taxonomy presence is checked against `src/metrics/behavioral-events.ts`: 96 mapped and 11 unmapped.
307
342
 
308
343
  | Constant | Emitted name | Behavioral taxonomy? |
309
344
  |---|---|---|
@@ -362,6 +397,21 @@ This table contains all 82 names from `src/metrics/constants.ts`; taxonomy prese
362
397
  | `TASK_SWITCH_CALL_FAILED` | `Task Switch Call Failed` | yes |
363
398
  | `TASK_OUTDIAL_SUCCESS` | `Task Outdial Success` | yes |
364
399
  | `TASK_OUTDIAL_FAILED` | `Task Outdial Failed` | yes |
400
+ | `WXAPP_TASK_MUTE_SUCCESS` | `WxApp Task Mute Success` | yes |
401
+ | `WXAPP_TASK_MUTE_FAILED` | `WxApp Task Mute Failed` | yes |
402
+ | `WXAPP_TASK_DTMF_SUCCESS` | `WxApp Task Dtmf Success` | yes |
403
+ | `WXAPP_TASK_DTMF_FAILED` | `WxApp Task Dtmf Failed` | yes |
404
+ | `WXAPP_TASK_ACCEPT_SUCCESS` | `WxApp Task Accept Success` | yes |
405
+ | `WXAPP_TASK_ACCEPT_FAILED` | `WxApp Task Accept Failed` | yes |
406
+ | `WXAPP_TASK_DECLINE_SUCCESS` | `WxApp Task Decline Success` | yes |
407
+ | `WXAPP_TASK_DECLINE_FAILED` | `WxApp Task Decline Failed` | yes |
408
+ | `WXAPP_SESSION_INIT_SUCCESS` | `WxApp Session Init Success` | yes |
409
+ | `WXAPP_SESSION_INIT_FAILED` | `WxApp Session Init Failed` | yes |
410
+ | `WXAPP_SESSION_SKIPPED` | `WxApp Session Skipped` | yes |
411
+ | `WXAPP_USERSUB_PUBLISH_SUCCESS` | `WxApp Usersub Publish Success` | yes |
412
+ | `WXAPP_USERSUB_PUBLISH_FAILED` | `WxApp Usersub Publish Failed` | yes |
413
+ | `WXAPP_MERCURY_SUBSCRIBE_SUCCESS` | `WxApp Mercury Subscribe Success` | yes |
414
+ | `WXAPP_MERCURY_SUBSCRIBE_FAILED` | `WxApp Mercury Subscribe Failed` | yes |
365
415
  | `UPLOAD_LOGS_SUCCESS` | `Upload Logs Success` | yes |
366
416
  | `UPLOAD_LOGS_FAILED` | `Upload Logs Failed` | yes |
367
417
  | `WEBSOCKET_DEREGISTER_SUCCESS` | `Websocket Deregister Success` | no |
@@ -385,12 +435,22 @@ This table contains all 82 names from `src/metrics/constants.ts`; taxonomy prese
385
435
  | `CAMPAIGN_PREVIEW_REMOVE_FAILED` | `Campaign Preview Remove Failed` | yes |
386
436
  | `AI_ASSISTANT_SEND_EVENT_SUCCESS` | `AI Assistant Send Event Success` | no |
387
437
  | `AI_ASSISTANT_SEND_EVENT_FAILED` | `AI Assistant Send Event Failed` | no |
388
- | `AI_ASSISTANT_GET_SUGGESTED_RESPONSE_SUCCESS` | `AI Assistant Get Suggested Response Success` | no |
389
- | `AI_ASSISTANT_GET_SUGGESTED_RESPONSE_FAILED` | `AI Assistant Get Suggested Response Failed` | no |
438
+ | `AI_ASSISTANT_GET_REAL_TIME_ASSISTANCE_SUCCESS` | `AI Assistant Get Real Time Assistance Success` | no |
439
+ | `AI_ASSISTANT_GET_REAL_TIME_ASSISTANCE_FAILED` | `AI Assistant Get Real Time Assistance Failed` | no |
440
+ | `AI_ASSISTANT_SEND_REAL_TIME_ASSISTANCE_USER_ACTION_SUCCESS` | `AI Assistant Send Real Time Assistance User Action Success` | no |
441
+ | `AI_ASSISTANT_SEND_REAL_TIME_ASSISTANCE_USER_ACTION_FAILED` | `AI Assistant Send Real Time Assistance User Action Failed` | no |
390
442
  | `AI_ASSISTANT_FETCH_HISTORIC_TRANSCRIPTS_SUCCESS` | `AI Assistant Fetch Historic Transcripts Success` | no |
391
443
  | `AI_ASSISTANT_FETCH_HISTORIC_TRANSCRIPTS_FAILED` | `AI Assistant Fetch Historic Transcripts Failed` | no |
444
+ | `USER_PREFERENCE_GET_SUCCESS` | `User Preference Get Success` | yes |
445
+ | `USER_PREFERENCE_GET_FAILED` | `User Preference Get Failed` | yes |
446
+ | `USER_PREFERENCE_CREATE_SUCCESS` | `User Preference Create Success` | yes |
447
+ | `USER_PREFERENCE_CREATE_FAILED` | `User Preference Create Failed` | yes |
448
+ | `USER_PREFERENCE_UPDATE_SUCCESS` | `User Preference Update Success` | yes |
449
+ | `USER_PREFERENCE_UPDATE_FAILED` | `User Preference Update Failed` | yes |
450
+ | `USER_PREFERENCE_DELETE_SUCCESS` | `User Preference Delete Success` | yes |
451
+ | `USER_PREFERENCE_DELETE_FAILED` | `User Preference Delete Failed` | yes |
392
452
 
393
- Defined names without an `eventTaxonomyMap` entry: `AI_ASSISTANT_FETCH_HISTORIC_TRANSCRIPTS_FAILED`, `AI_ASSISTANT_FETCH_HISTORIC_TRANSCRIPTS_SUCCESS`, `AI_ASSISTANT_GET_SUGGESTED_RESPONSE_FAILED`, `AI_ASSISTANT_GET_SUGGESTED_RESPONSE_SUCCESS`, `AI_ASSISTANT_SEND_EVENT_FAILED`, `AI_ASSISTANT_SEND_EVENT_SUCCESS`, `WEBSOCKET_DEREGISTER_FAIL`, `WEBSOCKET_DEREGISTER_SUCCESS`, `WEBSOCKET_EVENT_RECEIVED`.
453
+ Defined names without an `eventTaxonomyMap` entry: `AI_ASSISTANT_FETCH_HISTORIC_TRANSCRIPTS_FAILED`, `AI_ASSISTANT_FETCH_HISTORIC_TRANSCRIPTS_SUCCESS`, `AI_ASSISTANT_GET_REAL_TIME_ASSISTANCE_FAILED`, `AI_ASSISTANT_GET_REAL_TIME_ASSISTANCE_SUCCESS`, `AI_ASSISTANT_SEND_EVENT_FAILED`, `AI_ASSISTANT_SEND_EVENT_SUCCESS`, `AI_ASSISTANT_SEND_REAL_TIME_ASSISTANCE_USER_ACTION_FAILED`, `AI_ASSISTANT_SEND_REAL_TIME_ASSISTANCE_USER_ACTION_SUCCESS`, `WEBSOCKET_DEREGISTER_FAIL`, `WEBSOCKET_DEREGISTER_SUCCESS`, `WEBSOCKET_EVENT_RECEIVED`.
394
454
 
395
455
  ## Requires (dependencies)
396
456
  - `webex.internal.newMetrics` submission APIs
@@ -438,8 +498,10 @@ Each behavioral event maps to a structured taxonomy in `behavioral-events.ts`:
438
498
  > **Note**: The following events do **not** have behavioral taxonomy mappings in `behavioral-events.ts`:
439
499
  > - `AI_ASSISTANT_SEND_EVENT_SUCCESS`
440
500
  > - `AI_ASSISTANT_SEND_EVENT_FAILED`
441
- > - `AI_ASSISTANT_GET_SUGGESTED_RESPONSE_SUCCESS`
442
- > - `AI_ASSISTANT_GET_SUGGESTED_RESPONSE_FAILED`
501
+ > - `AI_ASSISTANT_GET_REAL_TIME_ASSISTANCE_SUCCESS`
502
+ > - `AI_ASSISTANT_GET_REAL_TIME_ASSISTANCE_FAILED`
503
+ > - `AI_ASSISTANT_SEND_REAL_TIME_ASSISTANCE_USER_ACTION_SUCCESS`
504
+ > - `AI_ASSISTANT_SEND_REAL_TIME_ASSISTANCE_USER_ACTION_FAILED`
443
505
  > - `AI_ASSISTANT_FETCH_HISTORIC_TRANSCRIPTS_SUCCESS`
444
506
  > - `AI_ASSISTANT_FETCH_HISTORIC_TRANSCRIPTS_FAILED`
445
507
  > - `WEBSOCKET_DEREGISTER_SUCCESS`
@@ -769,7 +831,7 @@ stateDiagram-v2
769
831
  - **metricsDisabled**: When `true`, `timeEvent` and all `track*` methods return early, and `clearPendingEvents()` empties all queues.
770
832
 
771
833
  ## Pitfalls
772
- - `METRIC_EVENT_NAMES` and `eventTaxonomyMap` are different inventories: nine defined names intentionally have no behavioral taxonomy.
834
+ - `METRIC_EVENT_NAMES` and `eventTaxonomyMap` are different inventories: eleven defined names intentionally have no behavioral taxonomy.
773
835
  - `setMetricsDisabled(true)` clears pending queues but does not create a delivery receipt; callers must not infer that previously submitted events were accepted.
774
836
  - Submission helpers hand events to `webex.internal.newMetrics` without a module-level retry/requeue policy, so telemetry must remain non-blocking and non-authoritative.
775
837
 
@@ -830,7 +892,7 @@ Use `test/unit/spec/metrics/MetricsManager.ts` for readiness queues, timing/trac
830
892
  | Behavior / Requirement | Existing test evidence | Gap |
831
893
  |---|---|---|
832
894
  | `METRICS-R-001` | `test/unit/spec/metrics/MetricsManager.ts` | Add a catalog parity assertion if constants change. |
833
- | `METRICS-R-002` | `test/unit/spec/metrics/behavioral-events.ts` | Keep explicit coverage for all nine unmapped names. |
895
+ | `METRICS-R-002` | `test/unit/spec/metrics/behavioral-events.ts` | Keep explicit coverage for all eleven unmapped names. |
834
896
  | `METRICS-R-003` | `test/unit/spec/metrics/MetricsManager.ts` | None. |
835
897
  | `METRICS-R-004` | `test/unit/spec/metrics/MetricsManager.ts` | None. |
836
898
  | `METRICS-R-005` | `test/unit/spec/metrics/MetricsManager.ts` | Authentication ownership is verified indirectly through the host metrics client. |