@absolutejs/voice 0.0.22-beta.439 → 0.0.22-beta.441

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 (313) hide show
  1. package/README.md +2729 -2698
  2. package/dist/agent.d.ts +10 -10
  3. package/dist/agentSquadContract.d.ts +4 -4
  4. package/dist/angular/index.d.ts +22 -22
  5. package/dist/angular/voice-agent-squad-status.service.d.ts +1 -1
  6. package/dist/angular/voice-call-debugger.service.d.ts +2 -2
  7. package/dist/angular/voice-campaign-dialer-proof.service.d.ts +2 -2
  8. package/dist/angular/voice-controller.service.d.ts +1 -1
  9. package/dist/angular/voice-delivery-runtime.component.d.ts +2 -2
  10. package/dist/angular/voice-delivery-runtime.service.d.ts +2 -2
  11. package/dist/angular/voice-live-ops.service.d.ts +1 -1
  12. package/dist/angular/voice-ops-action-center.service.d.ts +1 -1
  13. package/dist/angular/voice-ops-status.component.d.ts +2 -2
  14. package/dist/angular/voice-ops-status.service.d.ts +2 -2
  15. package/dist/angular/voice-platform-coverage.service.d.ts +2 -2
  16. package/dist/angular/voice-profile-comparison.service.d.ts +2 -2
  17. package/dist/angular/voice-proof-trends.service.d.ts +2 -2
  18. package/dist/angular/voice-provider-capabilities.service.d.ts +2 -2
  19. package/dist/angular/voice-provider-contracts.service.d.ts +2 -2
  20. package/dist/angular/voice-provider-status.service.d.ts +2 -2
  21. package/dist/angular/voice-readiness-failures.service.d.ts +2 -2
  22. package/dist/angular/voice-routing-status.service.d.ts +1 -1
  23. package/dist/angular/voice-session-snapshot.service.d.ts +2 -2
  24. package/dist/angular/voice-stream.service.d.ts +1 -1
  25. package/dist/angular/voice-trace-timeline.service.d.ts +2 -2
  26. package/dist/angular/voice-turn-latency.service.d.ts +2 -2
  27. package/dist/angular/voice-turn-quality.service.d.ts +2 -2
  28. package/dist/angular/voice-workflow-status.service.d.ts +2 -2
  29. package/dist/assistant.d.ts +11 -11
  30. package/dist/assistantHealth.d.ts +6 -6
  31. package/dist/assistantMemory.d.ts +3 -3
  32. package/dist/audioConditioning.d.ts +1 -1
  33. package/dist/audit.d.ts +11 -11
  34. package/dist/auditDeliveryRoutes.d.ts +3 -3
  35. package/dist/auditExport.d.ts +3 -3
  36. package/dist/auditRoutes.d.ts +2 -2
  37. package/dist/auditSinks.d.ts +8 -8
  38. package/dist/bargeInRoutes.d.ts +3 -3
  39. package/dist/browserCallProfiles.d.ts +2 -2
  40. package/dist/browserMediaRoutes.d.ts +4 -4
  41. package/dist/callDebugger.d.ts +6 -6
  42. package/dist/campaign.d.ts +22 -22
  43. package/dist/campaignDialers.d.ts +14 -14
  44. package/dist/client/actions.d.ts +1 -1
  45. package/dist/client/agentSquadStatus.d.ts +3 -3
  46. package/dist/client/agentSquadStatusWidget.d.ts +1 -1
  47. package/dist/client/audioPlayer.d.ts +2 -2
  48. package/dist/client/bargeInMonitor.d.ts +1 -1
  49. package/dist/client/browserMedia.d.ts +1 -1
  50. package/dist/client/callDebugger.d.ts +1 -1
  51. package/dist/client/callDebuggerWidget.d.ts +3 -3
  52. package/dist/client/campaignDialerProof.d.ts +1 -1
  53. package/dist/client/connection.d.ts +3 -3
  54. package/dist/client/controller.d.ts +1 -1
  55. package/dist/client/createVoiceStream.d.ts +1 -1
  56. package/dist/client/deliveryRuntime.d.ts +4 -4
  57. package/dist/client/deliveryRuntimeWidget.d.ts +5 -5
  58. package/dist/client/duplex.d.ts +1 -1
  59. package/dist/client/htmx.d.ts +1 -1
  60. package/dist/client/index.d.ts +96 -96
  61. package/dist/client/index.js +41 -15
  62. package/dist/client/liveOps.d.ts +2 -2
  63. package/dist/client/liveOpsWidget.d.ts +2 -2
  64. package/dist/client/liveTurnLatency.d.ts +3 -3
  65. package/dist/client/microphone.d.ts +4 -4
  66. package/dist/client/opsActionCenter.d.ts +1 -1
  67. package/dist/client/opsActionCenterWidget.d.ts +2 -2
  68. package/dist/client/opsActionHistory.d.ts +1 -1
  69. package/dist/client/opsActionHistoryWidget.d.ts +1 -1
  70. package/dist/client/opsStatus.d.ts +1 -1
  71. package/dist/client/opsStatusWidget.d.ts +4 -4
  72. package/dist/client/platformCoverage.d.ts +1 -1
  73. package/dist/client/platformCoverageWidget.d.ts +3 -3
  74. package/dist/client/profileComparison.d.ts +1 -1
  75. package/dist/client/profileComparisonWidget.d.ts +2 -2
  76. package/dist/client/profileSwitchRecommendation.d.ts +1 -1
  77. package/dist/client/profileSwitchRecommendationWidget.d.ts +1 -1
  78. package/dist/client/proofTrends.d.ts +1 -1
  79. package/dist/client/proofTrendsWidget.d.ts +3 -3
  80. package/dist/client/providerCapabilities.d.ts +1 -1
  81. package/dist/client/providerCapabilitiesWidget.d.ts +3 -3
  82. package/dist/client/providerContracts.d.ts +1 -1
  83. package/dist/client/providerContractsWidget.d.ts +3 -3
  84. package/dist/client/providerSimulationControls.d.ts +2 -2
  85. package/dist/client/providerSimulationControlsWidget.d.ts +1 -1
  86. package/dist/client/providerStatus.d.ts +1 -1
  87. package/dist/client/providerStatusWidget.d.ts +3 -3
  88. package/dist/client/readinessFailures.d.ts +1 -1
  89. package/dist/client/readinessFailuresWidget.d.ts +4 -4
  90. package/dist/client/routingStatus.d.ts +1 -1
  91. package/dist/client/routingStatusWidget.d.ts +3 -3
  92. package/dist/client/sessionSnapshot.d.ts +1 -1
  93. package/dist/client/sessionSnapshotWidget.d.ts +2 -2
  94. package/dist/client/store.d.ts +1 -1
  95. package/dist/client/traceTimeline.d.ts +1 -1
  96. package/dist/client/traceTimelineWidget.d.ts +3 -3
  97. package/dist/client/turnLatency.d.ts +1 -1
  98. package/dist/client/turnLatencyWidget.d.ts +3 -3
  99. package/dist/client/turnQuality.d.ts +1 -1
  100. package/dist/client/turnQualityWidget.d.ts +3 -3
  101. package/dist/client/workflowStatus.d.ts +1 -1
  102. package/dist/competitiveCoverage.d.ts +9 -9
  103. package/dist/correction.d.ts +2 -2
  104. package/dist/dataControl.d.ts +16 -16
  105. package/dist/deliveryRuntime.d.ts +9 -9
  106. package/dist/deliverySinkRoutes.d.ts +6 -6
  107. package/dist/demoReadyRoutes.d.ts +8 -8
  108. package/dist/diagnosticsRoutes.d.ts +2 -2
  109. package/dist/evalRoutes.d.ts +4 -4
  110. package/dist/fileStore.d.ts +9 -9
  111. package/dist/guardrails.d.ts +9 -9
  112. package/dist/handoff.d.ts +6 -6
  113. package/dist/handoffHealth.d.ts +5 -5
  114. package/dist/htmx.d.ts +1 -1
  115. package/dist/incidentBundle.d.ts +7 -7
  116. package/dist/incidentTimeline.d.ts +30 -16
  117. package/dist/index.d.ts +215 -215
  118. package/dist/index.js +375 -111
  119. package/dist/latencySlo.d.ts +4 -4
  120. package/dist/liveLatency.d.ts +3 -3
  121. package/dist/liveOps.d.ts +11 -11
  122. package/dist/logger.d.ts +1 -1
  123. package/dist/mediaPipelineRoutes.d.ts +2 -2
  124. package/dist/memoryStore.d.ts +1 -1
  125. package/dist/modelAdapters.d.ts +9 -9
  126. package/dist/observabilityExport.d.ts +44 -44
  127. package/dist/openaiTTS.d.ts +3 -3
  128. package/dist/operationalStatus.d.ts +5 -5
  129. package/dist/operationsRecord.d.ts +12 -12
  130. package/dist/ops.d.ts +12 -12
  131. package/dist/opsActionAuditRoutes.d.ts +3 -3
  132. package/dist/opsConsoleRoutes.d.ts +6 -6
  133. package/dist/opsPresets.d.ts +2 -2
  134. package/dist/opsRecovery.d.ts +11 -11
  135. package/dist/opsRuntime.d.ts +6 -6
  136. package/dist/opsSinks.d.ts +13 -13
  137. package/dist/opsStatus.d.ts +7 -7
  138. package/dist/opsStatusRoutes.d.ts +2 -2
  139. package/dist/opsWebhook.d.ts +6 -6
  140. package/dist/outcomeContract.d.ts +5 -5
  141. package/dist/outcomeRecipes.d.ts +4 -4
  142. package/dist/phoneAgent.d.ts +18 -18
  143. package/dist/phoneAgentProductionSmoke.d.ts +8 -8
  144. package/dist/platformCoverage.d.ts +3 -3
  145. package/dist/plugin.d.ts +2 -2
  146. package/dist/postCallAnalysis.d.ts +6 -6
  147. package/dist/postgresStore.d.ts +8 -8
  148. package/dist/presets.d.ts +3 -3
  149. package/dist/productionReadiness.d.ts +62 -36
  150. package/dist/profileSwitchRecommendation.d.ts +15 -15
  151. package/dist/proofAssertions.d.ts +1 -1
  152. package/dist/proofPack.d.ts +12 -12
  153. package/dist/proofRunner.d.ts +5 -5
  154. package/dist/proofTrends.d.ts +17 -17
  155. package/dist/providerAdapters.d.ts +5 -5
  156. package/dist/providerCapabilities.d.ts +4 -4
  157. package/dist/providerDecisionTraces.d.ts +8 -8
  158. package/dist/providerHealth.d.ts +3 -3
  159. package/dist/providerOrchestration.d.ts +5 -5
  160. package/dist/providerRouterTraces.d.ts +7 -7
  161. package/dist/providerRoutingContract.d.ts +3 -3
  162. package/dist/providerSlo.d.ts +6 -6
  163. package/dist/providerStackRecommendations.d.ts +6 -6
  164. package/dist/qualityRoutes.d.ts +4 -4
  165. package/dist/queue.d.ts +16 -16
  166. package/dist/react/VoiceAgentSquadStatus.d.ts +1 -1
  167. package/dist/react/VoiceCallDebuggerLaunch.d.ts +1 -1
  168. package/dist/react/VoiceDeliveryRuntime.d.ts +1 -1
  169. package/dist/react/VoiceOpsActionCenter.d.ts +1 -1
  170. package/dist/react/VoiceOpsStatus.d.ts +1 -1
  171. package/dist/react/VoicePlatformCoverage.d.ts +1 -1
  172. package/dist/react/VoiceProfileComparison.d.ts +1 -1
  173. package/dist/react/VoiceProfileSwitchRecommendation.d.ts +1 -1
  174. package/dist/react/VoiceProofTrends.d.ts +1 -1
  175. package/dist/react/VoiceProviderCapabilities.d.ts +1 -1
  176. package/dist/react/VoiceProviderContracts.d.ts +1 -1
  177. package/dist/react/VoiceProviderSimulationControls.d.ts +1 -1
  178. package/dist/react/VoiceProviderStatus.d.ts +1 -1
  179. package/dist/react/VoiceReadinessFailures.d.ts +1 -1
  180. package/dist/react/VoiceRoutingStatus.d.ts +1 -1
  181. package/dist/react/VoiceSessionSnapshot.d.ts +1 -1
  182. package/dist/react/VoiceTraceTimeline.d.ts +1 -1
  183. package/dist/react/VoiceTurnLatency.d.ts +1 -1
  184. package/dist/react/VoiceTurnQuality.d.ts +1 -1
  185. package/dist/react/index.d.ts +43 -43
  186. package/dist/react/index.js +41 -15
  187. package/dist/react/useVoiceAgentSquadStatus.d.ts +1 -1
  188. package/dist/react/useVoiceCallDebugger.d.ts +1 -1
  189. package/dist/react/useVoiceCampaignDialerProof.d.ts +1 -1
  190. package/dist/react/useVoiceController.d.ts +1 -1
  191. package/dist/react/useVoiceDeliveryRuntime.d.ts +1 -1
  192. package/dist/react/useVoiceLiveOps.d.ts +1 -1
  193. package/dist/react/useVoiceOpsActionCenter.d.ts +1 -1
  194. package/dist/react/useVoiceOpsStatus.d.ts +1 -1
  195. package/dist/react/useVoicePlatformCoverage.d.ts +1 -1
  196. package/dist/react/useVoiceProfileComparison.d.ts +1 -1
  197. package/dist/react/useVoiceProfileSwitchRecommendation.d.ts +1 -1
  198. package/dist/react/useVoiceProofTrends.d.ts +1 -1
  199. package/dist/react/useVoiceProviderCapabilities.d.ts +1 -1
  200. package/dist/react/useVoiceProviderContracts.d.ts +1 -1
  201. package/dist/react/useVoiceProviderSimulationControls.d.ts +1 -1
  202. package/dist/react/useVoiceProviderStatus.d.ts +1 -1
  203. package/dist/react/useVoiceReadinessFailures.d.ts +1 -1
  204. package/dist/react/useVoiceRoutingStatus.d.ts +1 -1
  205. package/dist/react/useVoiceSessionSnapshot.d.ts +1 -1
  206. package/dist/react/useVoiceStream.d.ts +1 -1
  207. package/dist/react/useVoiceTraceTimeline.d.ts +1 -1
  208. package/dist/react/useVoiceTurnLatency.d.ts +1 -1
  209. package/dist/react/useVoiceTurnQuality.d.ts +1 -1
  210. package/dist/react/useVoiceWorkflowStatus.d.ts +1 -1
  211. package/dist/readinessProfiles.d.ts +22 -15
  212. package/dist/realtimeChannel.d.ts +6 -6
  213. package/dist/realtimeProviderContracts.d.ts +7 -7
  214. package/dist/reconnectContract.d.ts +6 -6
  215. package/dist/resilienceRoutes.d.ts +6 -6
  216. package/dist/routing.d.ts +1 -1
  217. package/dist/runtimeOps.d.ts +3 -3
  218. package/dist/s3Store.d.ts +3 -3
  219. package/dist/session.d.ts +1 -1
  220. package/dist/sessionReplay.d.ts +9 -9
  221. package/dist/sessionSnapshot.d.ts +8 -8
  222. package/dist/simulationSuite.d.ts +12 -12
  223. package/dist/sloCalibration.d.ts +8 -8
  224. package/dist/sqliteStore.d.ts +8 -8
  225. package/dist/store.d.ts +1 -1
  226. package/dist/svelte/createVoiceAgentSquadStatus.d.ts +1 -1
  227. package/dist/svelte/createVoiceCallDebugger.d.ts +2 -2
  228. package/dist/svelte/createVoiceCampaignDialerProof.d.ts +1 -1
  229. package/dist/svelte/createVoiceDeliveryRuntime.d.ts +1 -1
  230. package/dist/svelte/createVoiceLiveOps.d.ts +2 -2
  231. package/dist/svelte/createVoiceOpsActionCenter.d.ts +1 -1
  232. package/dist/svelte/createVoiceOpsStatus.d.ts +1 -1
  233. package/dist/svelte/createVoicePlatformCoverage.d.ts +1 -1
  234. package/dist/svelte/createVoiceProfileComparison.d.ts +1 -1
  235. package/dist/svelte/createVoiceProofTrends.d.ts +1 -1
  236. package/dist/svelte/createVoiceProviderCapabilities.d.ts +1 -1
  237. package/dist/svelte/createVoiceProviderContracts.d.ts +1 -1
  238. package/dist/svelte/createVoiceProviderSimulationControls.d.ts +1 -1
  239. package/dist/svelte/createVoiceProviderStatus.d.ts +1 -1
  240. package/dist/svelte/createVoiceReadinessFailures.d.ts +1 -1
  241. package/dist/svelte/createVoiceRoutingStatus.d.ts +1 -1
  242. package/dist/svelte/createVoiceSessionSnapshot.d.ts +2 -2
  243. package/dist/svelte/createVoiceStream.d.ts +1 -1
  244. package/dist/svelte/createVoiceTraceTimeline.d.ts +1 -1
  245. package/dist/svelte/createVoiceTurnLatency.d.ts +1 -1
  246. package/dist/svelte/createVoiceTurnQuality.d.ts +1 -1
  247. package/dist/svelte/createVoiceWorkflowStatus.d.ts +1 -1
  248. package/dist/svelte/index.d.ts +23 -23
  249. package/dist/svelte/index.js +30 -8
  250. package/dist/telephony/contract.d.ts +5 -5
  251. package/dist/telephony/matrix.d.ts +4 -4
  252. package/dist/telephony/plivo.d.ts +30 -30
  253. package/dist/telephony/response.d.ts +1 -1
  254. package/dist/telephony/security.d.ts +17 -17
  255. package/dist/telephony/telnyx.d.ts +31 -31
  256. package/dist/telephony/twilio.d.ts +22 -22
  257. package/dist/telephonyMediaRoutes.d.ts +4 -4
  258. package/dist/telephonyOutcome.d.ts +13 -13
  259. package/dist/testing/accuracy.d.ts +1 -1
  260. package/dist/testing/benchmark.d.ts +9 -9
  261. package/dist/testing/corrected.d.ts +5 -5
  262. package/dist/testing/duplex.d.ts +3 -3
  263. package/dist/testing/fixtures.d.ts +3 -3
  264. package/dist/testing/index.d.ts +13 -13
  265. package/dist/testing/index.js +49 -20
  266. package/dist/testing/ioProviderSimulator.d.ts +5 -5
  267. package/dist/testing/providerSimulator.d.ts +5 -5
  268. package/dist/testing/review.d.ts +4 -4
  269. package/dist/testing/sessionBenchmark.d.ts +3 -3
  270. package/dist/testing/stt.d.ts +3 -3
  271. package/dist/testing/telephony.d.ts +3 -3
  272. package/dist/testing/tts.d.ts +1 -1
  273. package/dist/toolContract.d.ts +10 -10
  274. package/dist/toolRuntime.d.ts +3 -3
  275. package/dist/trace.d.ts +10 -10
  276. package/dist/traceDeliveryRoutes.d.ts +4 -4
  277. package/dist/traceTimeline.d.ts +4 -4
  278. package/dist/turnDetection.d.ts +1 -1
  279. package/dist/turnLatency.d.ts +4 -4
  280. package/dist/turnProfiles.d.ts +2 -2
  281. package/dist/turnQuality.d.ts +4 -4
  282. package/dist/types.d.ts +92 -92
  283. package/dist/voiceMonitoring.d.ts +6 -6
  284. package/dist/vue/VoiceOpsActionCenter.d.ts +2 -2
  285. package/dist/vue/VoiceProviderSimulationControls.d.ts +2 -2
  286. package/dist/vue/index.d.ts +38 -38
  287. package/dist/vue/index.js +41 -15
  288. package/dist/vue/useVoiceAgentSquadStatus.d.ts +1 -1
  289. package/dist/vue/useVoiceCallDebugger.d.ts +2 -2
  290. package/dist/vue/useVoiceCampaignDialerProof.d.ts +2 -2
  291. package/dist/vue/useVoiceController.d.ts +1 -1
  292. package/dist/vue/useVoiceDeliveryRuntime.d.ts +2 -2
  293. package/dist/vue/useVoiceLiveOps.d.ts +1 -1
  294. package/dist/vue/useVoiceOpsActionCenter.d.ts +1 -1
  295. package/dist/vue/useVoiceOpsStatus.d.ts +2 -2
  296. package/dist/vue/useVoicePlatformCoverage.d.ts +2 -2
  297. package/dist/vue/useVoiceProfileComparison.d.ts +2 -2
  298. package/dist/vue/useVoiceProofTrends.d.ts +2 -2
  299. package/dist/vue/useVoiceProviderCapabilities.d.ts +2 -2
  300. package/dist/vue/useVoiceProviderContracts.d.ts +2 -2
  301. package/dist/vue/useVoiceProviderSimulationControls.d.ts +1 -1
  302. package/dist/vue/useVoiceProviderStatus.d.ts +2 -2
  303. package/dist/vue/useVoiceReadinessFailures.d.ts +30 -2
  304. package/dist/vue/useVoiceRoutingStatus.d.ts +1 -1
  305. package/dist/vue/useVoiceSessionSnapshot.d.ts +2 -2
  306. package/dist/vue/useVoiceStream.d.ts +1 -1
  307. package/dist/vue/useVoiceTraceTimeline.d.ts +2 -2
  308. package/dist/vue/useVoiceTurnLatency.d.ts +2 -2
  309. package/dist/vue/useVoiceTurnQuality.d.ts +2 -2
  310. package/dist/vue/useVoiceWorkflowStatus.d.ts +2 -2
  311. package/dist/workflowContract.d.ts +8 -8
  312. package/fixtures/manifest.json +356 -197
  313. package/package.json +260 -259
package/dist/index.js CHANGED
@@ -1830,10 +1830,7 @@ var createVoiceZendeskTicketUpdateSink = (options) => {
1830
1830
  }
1831
1831
  });
1832
1832
  },
1833
- eventTypes: options.eventTypes ?? [
1834
- "task.updated",
1835
- "task.sla_breached"
1836
- ],
1833
+ eventTypes: options.eventTypes ?? ["task.updated", "task.sla_breached"],
1837
1834
  id: options.id,
1838
1835
  kind: options.kind ?? "zendesk-ticket-update"
1839
1836
  };
@@ -1844,19 +1841,13 @@ var createVoiceZendeskTicketSyncSinks = (options) => {
1844
1841
  createVoiceZendeskTicketSink({
1845
1842
  ...baseOptions,
1846
1843
  ...create,
1847
- eventTypes: create?.eventTypes ?? [
1848
- "review.saved",
1849
- "task.created"
1850
- ],
1844
+ eventTypes: create?.eventTypes ?? ["review.saved", "task.created"],
1851
1845
  id: createId ?? create?.id ?? options.id
1852
1846
  }),
1853
1847
  createVoiceZendeskTicketUpdateSink({
1854
1848
  ...baseOptions,
1855
1849
  ...update,
1856
- eventTypes: update?.eventTypes ?? [
1857
- "task.updated",
1858
- "task.sla_breached"
1859
- ],
1850
+ eventTypes: update?.eventTypes ?? ["task.updated", "task.sla_breached"],
1860
1851
  id: updateId ?? update?.id ?? `${options.id}:update`
1861
1852
  })
1862
1853
  ];
@@ -1961,10 +1952,7 @@ var createVoiceHubSpotTaskUpdateSink = (options) => {
1961
1952
  }
1962
1953
  });
1963
1954
  },
1964
- eventTypes: options.eventTypes ?? [
1965
- "task.updated",
1966
- "task.sla_breached"
1967
- ],
1955
+ eventTypes: options.eventTypes ?? ["task.updated", "task.sla_breached"],
1968
1956
  id: options.id,
1969
1957
  kind: options.kind ?? "hubspot-task-update"
1970
1958
  };
@@ -1981,10 +1969,7 @@ var createVoiceHubSpotTaskSyncSinks = (options) => {
1981
1969
  createVoiceHubSpotTaskUpdateSink({
1982
1970
  ...baseOptions,
1983
1971
  ...update,
1984
- eventTypes: update?.eventTypes ?? [
1985
- "task.updated",
1986
- "task.sla_breached"
1987
- ],
1972
+ eventTypes: update?.eventTypes ?? ["task.updated", "task.sla_breached"],
1988
1973
  id: updateId ?? update?.id ?? `${options.id}:update`
1989
1974
  })
1990
1975
  ];
@@ -2061,19 +2046,13 @@ var createVoiceLinearIssueSyncSinks = (options) => {
2061
2046
  createVoiceLinearIssueSink({
2062
2047
  ...baseOptions,
2063
2048
  ...create,
2064
- eventTypes: create?.eventTypes ?? [
2065
- "review.saved",
2066
- "task.created"
2067
- ],
2049
+ eventTypes: create?.eventTypes ?? ["review.saved", "task.created"],
2068
2050
  id: createId ?? create?.id ?? options.id
2069
2051
  }),
2070
2052
  createVoiceLinearIssueUpdateSink({
2071
2053
  ...baseOptions,
2072
2054
  ...update,
2073
- eventTypes: update?.eventTypes ?? [
2074
- "task.updated",
2075
- "task.sla_breached"
2076
- ],
2055
+ eventTypes: update?.eventTypes ?? ["task.updated", "task.sla_breached"],
2077
2056
  id: updateId ?? update?.id ?? `${options.id}:update`
2078
2057
  })
2079
2058
  ];
@@ -2136,10 +2115,7 @@ var createVoiceLinearIssueUpdateSink = (options) => {
2136
2115
  }
2137
2116
  });
2138
2117
  },
2139
- eventTypes: options.eventTypes ?? [
2140
- "task.updated",
2141
- "task.sla_breached"
2142
- ],
2118
+ eventTypes: options.eventTypes ?? ["task.updated", "task.sla_breached"],
2143
2119
  id: options.id,
2144
2120
  kind: options.kind ?? "linear-issue-update"
2145
2121
  };
@@ -5463,7 +5439,9 @@ var recommendVoiceProfileSwitch = (options) => {
5463
5439
  const recommended = candidates.slice().sort((left, right) => scoreProfile(left, observed) - scoreProfile(right, observed))[0];
5464
5440
  const issues = [
5465
5441
  ...defaults.profiles.length === 0 ? ["No measured profile defaults are available."] : [],
5466
- ...!currentProfile && currentProfileId ? [`Current profile ${currentProfileId} is not present in measured defaults.`] : [],
5442
+ ...!currentProfile && currentProfileId ? [
5443
+ `Current profile ${currentProfileId} is not present in measured defaults.`
5444
+ ] : [],
5467
5445
  ...!recommended ? ["No non-failing measured profile can be recommended."] : []
5468
5446
  ];
5469
5447
  const currentOverBudget = currentProfile ? [
@@ -5994,7 +5972,9 @@ var createVoiceProfileSwitchReadinessRoutes = (options) => {
5994
5972
  limit: typeof query.limit === "string" && Number.isFinite(Number(query.limit)) ? Number(query.limit) : options.limit,
5995
5973
  sessionId: typeof query.sessionId === "string" && query.sessionId.trim() ? query.sessionId.trim() : options.sessionId
5996
5974
  });
5997
- const render = options.render ?? ((input) => renderVoiceProfileSwitchReadinessHTML(input, { title: options.title }));
5975
+ const render = options.render ?? ((input) => renderVoiceProfileSwitchReadinessHTML(input, {
5976
+ title: options.title
5977
+ }));
5998
5978
  return new Response(await render(report), {
5999
5979
  headers: { "Content-Type": "text/html; charset=utf-8" }
6000
5980
  });
@@ -7704,10 +7684,7 @@ var createVoiceCampaignRoutes = (options) => {
7704
7684
  }).post(`${path}/:campaignId/recipients`, async ({ params, request }) => {
7705
7685
  const body = await readJsonBody(request);
7706
7686
  return runtime.addRecipients(params.campaignId, body.recipients ?? []);
7707
- }).post(`${path}/:campaignId/recipients/import`, async ({ params, request }) => runtime.importRecipients(params.campaignId, await readJsonBody(request))).post(`${path}/:campaignId/enqueue`, ({ params }) => runtime.enqueue(params.campaignId)).post(`${path}/:campaignId/pause`, ({ params }) => runtime.pause(params.campaignId)).post(`${path}/:campaignId/resume`, ({ params }) => runtime.resume(params.campaignId)).post(`${path}/:campaignId/cancel`, ({ params }) => runtime.cancel(params.campaignId)).post(`${path}/:campaignId/tick`, ({ params }) => runtime.tick(params.campaignId)).post(`${path}/:campaignId/attempts/:attemptId/result`, async ({
7708
- params,
7709
- request
7710
- }) => runtime.completeAttempt(params.campaignId, params.attemptId, await readJsonBody(request)));
7687
+ }).post(`${path}/:campaignId/recipients/import`, async ({ params, request }) => runtime.importRecipients(params.campaignId, await readJsonBody(request))).post(`${path}/:campaignId/enqueue`, ({ params }) => runtime.enqueue(params.campaignId)).post(`${path}/:campaignId/pause`, ({ params }) => runtime.pause(params.campaignId)).post(`${path}/:campaignId/resume`, ({ params }) => runtime.resume(params.campaignId)).post(`${path}/:campaignId/cancel`, ({ params }) => runtime.cancel(params.campaignId)).post(`${path}/:campaignId/tick`, ({ params }) => runtime.tick(params.campaignId)).post(`${path}/:campaignId/attempts/:attemptId/result`, async ({ params, request }) => runtime.completeAttempt(params.campaignId, params.attemptId, await readJsonBody(request)));
7711
7688
  if (htmlPath) {
7712
7689
  app.get(htmlPath, async () => {
7713
7690
  const records = await runtime.list();
@@ -10410,8 +10387,12 @@ var redactVoiceTraceEvent = (event, options = {}) => {
10410
10387
  const resolved = resolveVoiceTraceRedactionOptions(options);
10411
10388
  return {
10412
10389
  ...event,
10413
- metadata: redactTraceValue(event.metadata, resolved, ["metadata"]),
10414
- payload: redactTraceValue(event.payload, resolved, ["payload"])
10390
+ metadata: redactTraceValue(event.metadata, resolved, [
10391
+ "metadata"
10392
+ ]),
10393
+ payload: redactTraceValue(event.payload, resolved, [
10394
+ "payload"
10395
+ ])
10415
10396
  };
10416
10397
  };
10417
10398
  var redactVoiceTraceEvents = (events, options = {}) => events.map((event) => redactVoiceTraceEvent(event, options));
@@ -11760,7 +11741,9 @@ var createVoiceReconnectContractRoutes = (options) => {
11760
11741
  requireResume: options.requireResume,
11761
11742
  snapshots: await options.getSnapshots()
11762
11743
  });
11763
- const app = new Elysia9({ name: options.name ?? "absolutejs-voice-reconnect-contract" }).get(path, async () => new Response(JSON.stringify(await buildReport()), {
11744
+ const app = new Elysia9({
11745
+ name: options.name ?? "absolutejs-voice-reconnect-contract"
11746
+ }).get(path, async () => new Response(JSON.stringify(await buildReport()), {
11764
11747
  headers: {
11765
11748
  "content-type": "application/json; charset=utf-8",
11766
11749
  ...options.headers
@@ -12071,7 +12054,9 @@ var createVoiceRealtimeChannelRoutes = (options) => {
12071
12054
  return reportOptions;
12072
12055
  };
12073
12056
  const report = async () => buildVoiceRealtimeChannelReport(await resolveOptions());
12074
- const app = new Elysia10({ name: options.name ?? "voice-realtime-channel" }).get(path, async () => new Response(JSON.stringify(await report(), null, 2), {
12057
+ const app = new Elysia10({
12058
+ name: options.name ?? "voice-realtime-channel"
12059
+ }).get(path, async () => new Response(JSON.stringify(await report(), null, 2), {
12075
12060
  headers: {
12076
12061
  "content-type": "application/json; charset=utf-8",
12077
12062
  ...headers
@@ -12115,10 +12100,7 @@ var defaultProviderEnv = {
12115
12100
  "gemini-live": ["GEMINI_API_KEY"],
12116
12101
  "openai-realtime": ["OPENAI_API_KEY"]
12117
12102
  };
12118
- var defaultRealtimeProviders = [
12119
- "openai-realtime",
12120
- "gemini-live"
12121
- ];
12103
+ var defaultRealtimeProviders = ["openai-realtime", "gemini-live"];
12122
12104
  var statusRank = {
12123
12105
  pass: 0,
12124
12106
  warn: 1,
@@ -12397,7 +12379,10 @@ var buildVoiceDiagnosticsMarkdown = (events, options = {}) => {
12397
12379
  var renderDiagnosticsIndex = (input) => {
12398
12380
  const sessions = new Map;
12399
12381
  for (const event of input.events) {
12400
- sessions.set(event.sessionId, [...sessions.get(event.sessionId) ?? [], event]);
12382
+ sessions.set(event.sessionId, [
12383
+ ...sessions.get(event.sessionId) ?? [],
12384
+ event
12385
+ ]);
12401
12386
  }
12402
12387
  const rows = [...sessions.entries()].sort(([, left], [, right]) => (right.at(-1)?.at ?? 0) - (left.at(-1)?.at ?? 0)).slice(0, 50).map(([sessionId, events]) => {
12403
12388
  const summary = summarizeVoiceTrace(events);
@@ -13982,7 +13967,10 @@ var createVoiceDemoReadyRoutes = (options) => {
13982
13967
  routes.get(path, async ({ query, request }) => buildVoiceDemoReadyReport(options, { query, request }));
13983
13968
  if (htmlPath !== false) {
13984
13969
  routes.get(htmlPath, async ({ query, request }) => {
13985
- const report = await buildVoiceDemoReadyReport(options, { query, request });
13970
+ const report = await buildVoiceDemoReadyReport(options, {
13971
+ query,
13972
+ request
13973
+ });
13986
13974
  const body = await (options.render ?? renderVoiceDemoReadyHTML)(report);
13987
13975
  return new Response(body, {
13988
13976
  headers: {
@@ -16282,7 +16270,9 @@ var createVoiceProviderDecisionTraceRoutes = (options) => {
16282
16270
  const headers = options.headers ?? {};
16283
16271
  const title = options.title ?? "Provider Decision Traces";
16284
16272
  const report = () => buildVoiceProviderDecisionTraceReport(options);
16285
- const app = new Elysia23({ name: options.name ?? "voice-provider-decisions" }).get(path, async () => new Response(JSON.stringify(await report(), null, 2), {
16273
+ const app = new Elysia23({
16274
+ name: options.name ?? "voice-provider-decisions"
16275
+ }).get(path, async () => new Response(JSON.stringify(await report(), null, 2), {
16286
16276
  headers: {
16287
16277
  "content-type": "application/json; charset=utf-8",
16288
16278
  ...headers
@@ -16529,7 +16519,10 @@ var summarizeProviderTraceEvidence = (events, maxProviderP95Ms) => {
16529
16519
  const id = `${role}:${provider}`;
16530
16520
  const latency = readProviderTraceLatency(payload);
16531
16521
  if (latency !== undefined) {
16532
- providerLatencies.set(id, [...providerLatencies.get(id) ?? [], latency]);
16522
+ providerLatencies.set(id, [
16523
+ ...providerLatencies.get(id) ?? [],
16524
+ latency
16525
+ ]);
16533
16526
  }
16534
16527
  const existing = providerMeta.get(id);
16535
16528
  providerMeta.set(id, {
@@ -16626,10 +16619,7 @@ var buildVoiceRealCallProfileEvidenceFromTraceEvents = (events, options = {}) =>
16626
16619
  event
16627
16620
  ]);
16628
16621
  }
16629
- return [...eventsBySession.entries()].map(([
16630
- sessionId,
16631
- sessionEvents
16632
- ]) => {
16622
+ return [...eventsBySession.entries()].map(([sessionId, sessionEvents]) => {
16633
16623
  const profileId = readTraceProfileId(sessionEvents, options);
16634
16624
  if (!profileId) {
16635
16625
  return;
@@ -18071,7 +18061,9 @@ var renderVoiceProofTrendRecommendationMarkdown = (report, title = "Voice Provid
18071
18061
  "",
18072
18062
  "| Rank | Provider | Role | Status | P95 | Samples | Next move |",
18073
18063
  "| ---: | --- | --- | --- | ---: | ---: | --- |",
18074
- ...report.providers.length ? report.providers.map((provider) => `| ${String(provider.rank)} | ${escapeMarkdown2(provider.label ?? provider.id)} | ${escapeMarkdown2(provider.role ?? "n/a")} | ${provider.status} | ${provider.p95Ms === undefined ? "n/a" : String(provider.p95Ms)} | ${provider.samples === undefined ? "n/a" : String(provider.samples)} | ${escapeMarkdown2(provider.nextMove)} |`) : ["| n/a | n/a | n/a | n/a | n/a | n/a | No provider-specific samples were present. |"],
18064
+ ...report.providers.length ? report.providers.map((provider) => `| ${String(provider.rank)} | ${escapeMarkdown2(provider.label ?? provider.id)} | ${escapeMarkdown2(provider.role ?? "n/a")} | ${provider.status} | ${provider.p95Ms === undefined ? "n/a" : String(provider.p95Ms)} | ${provider.samples === undefined ? "n/a" : String(provider.samples)} | ${escapeMarkdown2(provider.nextMove)} |`) : [
18065
+ "| n/a | n/a | n/a | n/a | n/a | n/a | No provider-specific samples were present. |"
18066
+ ],
18075
18067
  "",
18076
18068
  "## Benchmark Profiles",
18077
18069
  "",
@@ -18589,7 +18581,9 @@ var createVoiceSessionSnapshotRoutes = (options = {}) => {
18589
18581
  const path = options.path ?? "/api/voice/session-snapshot/:sessionId";
18590
18582
  const downloadPath = options.downloadPath ?? "/api/voice/session-snapshot/:sessionId/download";
18591
18583
  const headers = options.headers ?? {};
18592
- const app = new Elysia25({ name: options.name ?? "voice-session-snapshot" }).get(path, async ({ params, request, query }) => sessionSnapshotJsonResponse(await resolveVoiceSessionSnapshot(options, {
18584
+ const app = new Elysia25({
18585
+ name: options.name ?? "voice-session-snapshot"
18586
+ }).get(path, async ({ params, request, query }) => sessionSnapshotJsonResponse(await resolveVoiceSessionSnapshot(options, {
18593
18587
  request,
18594
18588
  sessionId: readRouteSessionId(params),
18595
18589
  turnId: typeof query.turnId === "string" ? query.turnId : undefined
@@ -18736,7 +18730,10 @@ var summarizeVoiceSessions = async (options = {}) => {
18736
18730
  const events = options.events ?? await options.store?.list() ?? [];
18737
18731
  const grouped = new Map;
18738
18732
  for (const event of events) {
18739
- grouped.set(event.sessionId, [...grouped.get(event.sessionId) ?? [], event]);
18733
+ grouped.set(event.sessionId, [
18734
+ ...grouped.get(event.sessionId) ?? [],
18735
+ event
18736
+ ]);
18740
18737
  }
18741
18738
  const sessions = [...grouped.entries()].map(([sessionId, sessionEvents]) => {
18742
18739
  const sorted = filterVoiceTraceEvents(sessionEvents);
@@ -19034,7 +19031,10 @@ var summarizeVoiceTraceTimeline = (events, options = {}) => {
19034
19031
  const source = options.redact ? redactVoiceTraceEvents(events, options.redact) : events;
19035
19032
  const grouped = new Map;
19036
19033
  for (const event of filterVoiceTraceEvents(source)) {
19037
- grouped.set(event.sessionId, [...grouped.get(event.sessionId) ?? [], event]);
19034
+ grouped.set(event.sessionId, [
19035
+ ...grouped.get(event.sessionId) ?? [],
19036
+ event
19037
+ ]);
19038
19038
  }
19039
19039
  const sessions = [...grouped.entries()].map(([sessionId, sessionEvents]) => {
19040
19040
  const sorted = filterVoiceTraceEvents(sessionEvents);
@@ -22236,7 +22236,11 @@ var resolveVoiceTelephonyOutcome = (event, policyInput = {}) => {
22236
22236
  }
22237
22237
  if (target) {
22238
22238
  return {
22239
- ...buildDecision("transfer", { event, policy, source: "explicit-target" }),
22239
+ ...buildDecision("transfer", {
22240
+ event,
22241
+ policy,
22242
+ source: "explicit-target"
22243
+ }),
22240
22244
  confidence: "medium"
22241
22245
  };
22242
22246
  }
@@ -22418,7 +22422,12 @@ var parseVoiceTelephonyWebhookEvent = (input) => {
22418
22422
  "hangupCauseCode"
22419
22423
  ]);
22420
22424
  const from = firstString4(payload, ["From", "from", "caller_id", "callerId"]);
22421
- const to = firstString4(payload, ["To", "to", "called_number", "calledNumber"]);
22425
+ const to = firstString4(payload, [
22426
+ "To",
22427
+ "to",
22428
+ "called_number",
22429
+ "calledNumber"
22430
+ ]);
22422
22431
  const target = firstString4(payload, [
22423
22432
  "transferTarget",
22424
22433
  "TransferTarget",
@@ -23220,7 +23229,9 @@ var buildTwilioVoiceSetupStatus = async (options, input) => {
23220
23229
  const warnings = [
23221
23230
  ...stream.startsWith("wss://") ? [] : ["Twilio media streams should use wss:// in production."],
23222
23231
  ...signingConfigured ? [] : ["Webhook signature verification is not configured."],
23223
- ...verificationUrl || !signingConfigured ? [] : ["Webhook signing is configured without an explicit verification URL."]
23232
+ ...verificationUrl || !signingConfigured ? [] : [
23233
+ "Webhook signing is configured without an explicit verification URL."
23234
+ ]
23224
23235
  ];
23225
23236
  return {
23226
23237
  generatedAt: Date.now(),
@@ -25842,7 +25853,9 @@ var createVoiceProviderSloRoutes = (options) => {
25842
25853
  ...options.headers ?? {}
25843
25854
  };
25844
25855
  const buildReport = () => buildVoiceProviderSloReport(options);
25845
- const app = new Elysia41({ name: options.name ?? "absolute-voice-provider-slos" });
25856
+ const app = new Elysia41({
25857
+ name: options.name ?? "absolute-voice-provider-slos"
25858
+ });
25846
25859
  app.get(path, async () => Response.json(await buildReport(), { headers }));
25847
25860
  if (markdownPath !== false) {
25848
25861
  app.get(markdownPath, async () => {
@@ -26590,6 +26603,84 @@ var buildVoiceIncidentRecoveryOutcomeReadinessCheck = (report, options = {}) =>
26590
26603
  value: `${report.improved}/${report.total} improved`
26591
26604
  };
26592
26605
  };
26606
+ var buildVoiceIncidentRecoveryTrendSLOReadinessCheck = (report, options = {}) => {
26607
+ const mode = options.mode ?? "latest";
26608
+ const minCycles = Math.max(1, options.minCycles ?? 1);
26609
+ const minActions = Math.max(1, options.minActions ?? 1);
26610
+ const minImprovementRate = options.minImprovementRate ?? 0;
26611
+ const maxRegressionRate = options.maxRegressionRate ?? 0;
26612
+ const maxFailureRate = options.maxFailureRate ?? 0;
26613
+ const maxUnchangedRate = options.maxUnchangedRate ?? 1;
26614
+ const warnWhenEmpty = options.warnWhenEmpty ?? true;
26615
+ const href = options.href ?? "/api/voice/incident-timeline/recovery-trends";
26616
+ const modeLatestCycle = report.latest;
26617
+ const modeAggregate = report.summary.cycles > 0;
26618
+ const modeTarget = mode === "aggregate" ? modeAggregate ? {
26619
+ failed: report.summary.failed,
26620
+ failureRate: report.summary.failureRate,
26621
+ improved: report.summary.improved,
26622
+ improvementRate: report.summary.improvementRate,
26623
+ regressed: report.summary.regressed,
26624
+ regressionRate: report.summary.regressionRate,
26625
+ total: report.summary.total,
26626
+ unchanged: report.summary.unchanged,
26627
+ unchangedRate: report.summary.unchangedRate
26628
+ } : undefined : modeLatestCycle;
26629
+ const insufficientCycles = report.cycles.length < minCycles;
26630
+ const empty = !modeTarget || modeTarget.total === 0;
26631
+ const insufficientActions = !empty && modeTarget.total < minActions;
26632
+ const failedRate = modeTarget?.failureRate ?? 0;
26633
+ const regressedRate = modeTarget?.regressionRate ?? 0;
26634
+ const unchangedRate = modeTarget?.unchangedRate ?? 0;
26635
+ const improvementRate = modeTarget?.improvementRate ?? 0;
26636
+ const issues = [];
26637
+ if (empty && warnWhenEmpty) {
26638
+ issues.push("No incident recovery actions found in the configured trend window.");
26639
+ }
26640
+ if (insufficientCycles) {
26641
+ issues.push(`Need at least ${minCycles} trend cycle(s) before enforcing trend SLOs, found ${report.cycles.length}.`);
26642
+ }
26643
+ if (insufficientActions) {
26644
+ issues.push(`Need at least ${minActions} recovery actions in the trend cycle, found ${modeTarget?.total ?? 0}.`);
26645
+ }
26646
+ if (improvementRate < minImprovementRate) {
26647
+ issues.push(`Improvement rate ${Math.round(improvementRate * 100)}% is below minimum ${Math.round(minImprovementRate * 100)}%.`);
26648
+ }
26649
+ if (regressedRate > maxRegressionRate) {
26650
+ issues.push(`Regression rate ${Math.round(regressedRate * 100)}% is above maximum ${Math.round(maxRegressionRate * 100)}%.`);
26651
+ }
26652
+ if (failedRate > maxFailureRate) {
26653
+ issues.push(`Failure rate ${Math.round(failedRate * 100)}% is above maximum ${Math.round(maxFailureRate * 100)}%.`);
26654
+ }
26655
+ if (unchangedRate > maxUnchangedRate) {
26656
+ issues.push(`Unchanged rate ${Math.round(unchangedRate * 100)}% is above maximum ${Math.round(maxUnchangedRate * 100)}%.`);
26657
+ }
26658
+ const fail = issues.some((issue) => issue.includes("Regression rate") || issue.includes("Failure rate"));
26659
+ const status = fail ? "fail" : issues.length > 0 ? "warn" : "pass";
26660
+ const detail = empty && warnWhenEmpty ? `${mode} trend is empty; set up recovery action execution before release.` : `${mode} trend has ${modeTarget?.total ?? 0} recovery action(s), ${Math.round(improvementRate * 100)}% improved, ${Math.round(regressedRate * 100)}% regressed, ${Math.round(failedRate * 100)}% failed, ${Math.round(unchangedRate * 100)}% unchanged.`;
26661
+ return {
26662
+ actions: status === "pass" ? [] : [
26663
+ {
26664
+ description: `Open recovery trend report and tighten recovery handling before deploy.`,
26665
+ href,
26666
+ label: `Open recovery trend report`
26667
+ }
26668
+ ],
26669
+ detail,
26670
+ gateExplanation: modeTarget ? {
26671
+ evidenceHref: href,
26672
+ observed: `improvement ${Math.round(improvementRate * 100)}%, regression ${Math.round(regressedRate * 100)}%, failure ${Math.round(failedRate * 100)}%, unchanged ${Math.round(unchangedRate * 100)}%`,
26673
+ threshold: `cycles >= ${minCycles}, actions >= ${minActions}`,
26674
+ thresholdLabel: "Incident recovery trend SLO budget",
26675
+ unit: "rate",
26676
+ remediation: "Run recovery recovery actions and harden handler fallbacks, then rerun recovery trend capture."
26677
+ } : undefined,
26678
+ href,
26679
+ label: options.label ?? "Incident recovery trend SLO",
26680
+ status,
26681
+ value: `${Math.round(improvementRate * 100)}% improved, ${Math.round(regressedRate * 100)}% regressed`
26682
+ };
26683
+ };
26593
26684
  var rate3 = (count, total) => total > 0 ? count / total : 0;
26594
26685
  var toIncidentRecoveryTrendCycle = (report) => ({
26595
26686
  checkedAt: report.checkedAt,
@@ -29333,6 +29424,15 @@ var resolveIncidentRecoveryOutcomes = async (options, input) => {
29333
29424
  }
29334
29425
  return options.incidentRecoveryOutcomes;
29335
29426
  };
29427
+ var resolveIncidentRecoveryTrend = async (options, input) => {
29428
+ if (!options.incidentRecoveryTrend) {
29429
+ return;
29430
+ }
29431
+ if (typeof options.incidentRecoveryTrend === "function") {
29432
+ return options.incidentRecoveryTrend(input);
29433
+ }
29434
+ return options.incidentRecoveryTrend;
29435
+ };
29336
29436
  var resolveObservabilityExport = async (options, input) => {
29337
29437
  if (!options.observabilityExport) {
29338
29438
  return;
@@ -29538,7 +29638,57 @@ var buildOperationsRecordLinks = (input) => {
29538
29638
  };
29539
29639
  };
29540
29640
  var firstOperationsRecordHref = (links) => links[0]?.href;
29641
+ var applyProfileReadinessDefaults = (options) => {
29642
+ if (options.profile === false || options.profile === undefined) {
29643
+ return options;
29644
+ }
29645
+ const profileName = options.profile.name;
29646
+ if (profileName !== "meeting-recorder" && profileName !== "phone-agent") {
29647
+ return options;
29648
+ }
29649
+ const defaults = profileName === "meeting-recorder" ? {
29650
+ browserMediaMinActiveCandidatePairs: 1,
29651
+ browserMediaMinLiveAudioTracks: 1,
29652
+ browserMediaMinTotalStats: 3,
29653
+ reconnectContractsMinCount: 1,
29654
+ reconnectContractsMinSnapshotsPerContract: 1
29655
+ } : {
29656
+ browserMediaMinActiveCandidatePairs: 1,
29657
+ browserMediaMinLiveAudioTracks: 1,
29658
+ browserMediaMinTotalStats: 3,
29659
+ reconnectContractsMinCount: 1,
29660
+ reconnectContractsMinSnapshotsPerContract: 1,
29661
+ telephonyMediaMinCarriers: 1,
29662
+ telephonyMediaMinMediaEvents: 2
29663
+ };
29664
+ const resolvedOptions = {
29665
+ ...options
29666
+ };
29667
+ if (resolvedOptions.browserMediaMinActiveCandidatePairs === undefined) {
29668
+ resolvedOptions.browserMediaMinActiveCandidatePairs = defaults.browserMediaMinActiveCandidatePairs;
29669
+ }
29670
+ if (resolvedOptions.browserMediaMinLiveAudioTracks === undefined) {
29671
+ resolvedOptions.browserMediaMinLiveAudioTracks = defaults.browserMediaMinLiveAudioTracks;
29672
+ }
29673
+ if (resolvedOptions.browserMediaMinTotalStats === undefined) {
29674
+ resolvedOptions.browserMediaMinTotalStats = defaults.browserMediaMinTotalStats;
29675
+ }
29676
+ if (resolvedOptions.reconnectContractsMinCount === undefined) {
29677
+ resolvedOptions.reconnectContractsMinCount = defaults.reconnectContractsMinCount;
29678
+ }
29679
+ if (resolvedOptions.reconnectContractsMinSnapshotsPerContract === undefined) {
29680
+ resolvedOptions.reconnectContractsMinSnapshotsPerContract = defaults.reconnectContractsMinSnapshotsPerContract;
29681
+ }
29682
+ if ("telephonyMediaMinCarriers" in defaults && resolvedOptions.telephonyMediaMinCarriers === undefined) {
29683
+ resolvedOptions.telephonyMediaMinCarriers = defaults.telephonyMediaMinCarriers;
29684
+ }
29685
+ if ("telephonyMediaMinMediaEvents" in defaults && resolvedOptions.telephonyMediaMinMediaEvents === undefined) {
29686
+ resolvedOptions.telephonyMediaMinMediaEvents = defaults.telephonyMediaMinMediaEvents;
29687
+ }
29688
+ return resolvedOptions;
29689
+ };
29541
29690
  var buildVoiceProductionReadinessReport = async (options, input = {}) => {
29691
+ options = applyProfileReadinessDefaults(options);
29542
29692
  const request = input.request ?? new Request("http://localhost/");
29543
29693
  const query = input.query ?? {};
29544
29694
  const time = async (label, run) => {
@@ -29592,6 +29742,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
29592
29742
  campaignReadiness,
29593
29743
  opsRecovery,
29594
29744
  incidentRecoveryOutcomes,
29745
+ incidentRecoveryTrend,
29595
29746
  observabilityExport,
29596
29747
  observabilityExportDeliveryHistory,
29597
29748
  observabilityExportReplay,
@@ -29640,6 +29791,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
29640
29791
  time("campaignReadiness", () => resolveCampaignReadiness(options, { query, request })),
29641
29792
  time("opsRecovery", () => resolveOpsRecovery(options, { query, request })),
29642
29793
  time("incidentRecoveryOutcomes", () => resolveIncidentRecoveryOutcomes(options, { query, request })),
29794
+ time("incidentRecoveryTrend", () => resolveIncidentRecoveryTrend(options, { query, request })),
29643
29795
  time("observabilityExport", () => resolveObservabilityExport(options, { query, request })),
29644
29796
  time("observabilityExportDeliveryHistory", () => resolveObservabilityExportDeliveryHistory(options, { query, request })),
29645
29797
  time("observabilityExportReplay", () => resolveObservabilityExportReplay(options, { query, request })),
@@ -29664,6 +29816,18 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
29664
29816
  href: options.incidentRecoveryOutcomeReadiness?.href ?? "/api/voice/incident-timeline/recovery-outcomes",
29665
29817
  ...options.incidentRecoveryOutcomeReadiness
29666
29818
  }) : undefined;
29819
+ const incidentRecoveryTrendReadiness = incidentRecoveryTrend && options.incidentRecoveryTrendSLO !== false ? buildVoiceIncidentRecoveryTrendSLOReadinessCheck(incidentRecoveryTrend, {
29820
+ href: options.incidentRecoveryTrendSLO?.href ?? "/api/voice/incident-timeline/recovery-trends",
29821
+ label: options.incidentRecoveryTrendSLO?.label,
29822
+ maxFailureRate: options.incidentRecoveryTrendSLO?.maxFailureRate,
29823
+ maxRegressionRate: options.incidentRecoveryTrendSLO?.maxRegressionRate,
29824
+ maxUnchangedRate: options.incidentRecoveryTrendSLO?.maxUnchangedRate,
29825
+ minActions: options.incidentRecoveryTrendSLO?.minActions,
29826
+ minCycles: options.incidentRecoveryTrendSLO?.minCycles,
29827
+ minImprovementRate: options.incidentRecoveryTrendSLO?.minImprovementRate,
29828
+ warnWhenEmpty: options.incidentRecoveryTrendSLO?.warnWhenEmpty,
29829
+ mode: options.incidentRecoveryTrendSLO?.mode
29830
+ }) : undefined;
29667
29831
  const checks = [
29668
29832
  {
29669
29833
  detail: quality.status === "pass" ? "Quality gates are passing." : "Quality gates need attention.",
@@ -29736,6 +29900,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
29736
29900
  }
29737
29901
  ] : [],
29738
29902
  ...incidentRecoveryOutcomeReadiness ? [incidentRecoveryOutcomeReadiness] : [],
29903
+ ...incidentRecoveryTrendReadiness ? [incidentRecoveryTrendReadiness] : [],
29739
29904
  {
29740
29905
  detail: failedSessions === 0 ? sessions.length > 0 ? "Recent sessions have no recorded provider/session failures." : "No sessions have been recorded yet; run a smoke or live session for proof." : `${failedSessions} recent session(s) have failures.`,
29741
29906
  href: firstOperationsRecordHref(operationsRecords.failedSessions) ?? options.links?.sessions ?? "/sessions",
@@ -29830,6 +29995,11 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
29830
29995
  status: mediaPipeline.status === "pass" ? "pass" : "fail",
29831
29996
  timestampDriftMs: mediaPipeline.quality.timestampDriftMs
29832
29997
  } : undefined;
29998
+ const browserMediaBreadthFailures = browserMedia ? [
29999
+ options.browserMediaMinActiveCandidatePairs !== undefined && typeof options.browserMediaMinActiveCandidatePairs === "number" && options.browserMediaMinActiveCandidatePairs >= 0 && browserMedia.activeCandidatePairs < options.browserMediaMinActiveCandidatePairs ? `Expected at least ${options.browserMediaMinActiveCandidatePairs} active candidate pair(s), observed ${browserMedia.activeCandidatePairs}.` : undefined,
30000
+ options.browserMediaMinLiveAudioTracks !== undefined && typeof options.browserMediaMinLiveAudioTracks === "number" && options.browserMediaMinLiveAudioTracks >= 0 && browserMedia.liveAudioTracks < options.browserMediaMinLiveAudioTracks ? `Expected at least ${options.browserMediaMinLiveAudioTracks} live audio track(s), observed ${browserMedia.liveAudioTracks}.` : undefined,
30001
+ options.browserMediaMinTotalStats !== undefined && typeof options.browserMediaMinTotalStats === "number" && options.browserMediaMinTotalStats >= 0 && browserMedia.totalStats < options.browserMediaMinTotalStats ? `Expected at least ${options.browserMediaMinTotalStats} WebRTC stats sample(s), observed ${browserMedia.totalStats}.` : undefined
30002
+ ].filter((message) => typeof message === "string" && message.length > 0) : [];
29833
30003
  const browserMediaSummary = browserMedia ? {
29834
30004
  activeCandidatePairs: browserMedia.activeCandidatePairs,
29835
30005
  bytesReceived: browserMedia.bytesReceived,
@@ -29839,18 +30009,29 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
29839
30009
  liveAudioTracks: browserMedia.liveAudioTracks,
29840
30010
  packetLossRatio: browserMedia.packetLossRatio,
29841
30011
  roundTripTimeMs: browserMedia.roundTripTimeMs,
29842
- status: browserMedia.status === "pass" ? "pass" : "fail"
29843
- } : undefined;
29844
- const telephonyMediaSummary = telephonyMedia ? {
29845
- audioBytes: telephonyMedia.carriers.reduce((total, carrier) => total + carrier.audioBytes, 0),
29846
- carriers: telephonyMedia.carriers.length,
29847
- failed: telephonyMedia.carriers.filter((carrier) => carrier.status !== "pass").length,
29848
- issues: telephonyMedia.issues.length,
29849
- lifecycleFailures: telephonyMedia.carriers.filter((carrier) => carrier.lifecycle.status !== "pass").length,
29850
- mediaEvents: telephonyMedia.carriers.reduce((total, carrier) => total + carrier.lifecycle.mediaEvents, 0),
29851
- passed: telephonyMedia.carriers.filter((carrier) => carrier.status === "pass").length,
29852
- status: telephonyMedia.status === "pass" ? "pass" : "fail"
30012
+ status: browserMedia.status === "pass" && browserMediaBreadthFailures.length === 0 ? "pass" : "fail"
29853
30013
  } : undefined;
30014
+ let telephonyMediaBreadthFailures = [];
30015
+ const telephonyMediaSummary = telephonyMedia ? (() => {
30016
+ const telephonyMediaTotalMediaEvents = telephonyMedia.carriers.reduce((total, carrier) => total + carrier.lifecycle.mediaEvents, 0);
30017
+ const failures = [
30018
+ options.telephonyMediaMinCarriers !== undefined && typeof options.telephonyMediaMinCarriers === "number" && options.telephonyMediaMinCarriers >= 0 && telephonyMedia.carriers.length < options.telephonyMediaMinCarriers ? `Expected at least ${options.telephonyMediaMinCarriers} telephony carrier(s), observed ${telephonyMedia.carriers.length}.` : undefined,
30019
+ options.telephonyMediaMinMediaEvents !== undefined && typeof options.telephonyMediaMinMediaEvents === "number" && options.telephonyMediaMinMediaEvents >= 0 && telephonyMediaTotalMediaEvents < options.telephonyMediaMinMediaEvents ? `Expected at least ${options.telephonyMediaMinMediaEvents} telephony media event(s), observed ${telephonyMediaTotalMediaEvents}.` : undefined
30020
+ ].filter((message) => typeof message === "string" && message.length > 0);
30021
+ telephonyMediaBreadthFailures = failures;
30022
+ return {
30023
+ audioBytes: telephonyMedia.carriers.reduce((total, carrier) => total + carrier.audioBytes, 0),
30024
+ carriers: telephonyMedia.carriers.length,
30025
+ failed: telephonyMedia.carriers.filter((carrier) => carrier.status !== "pass").length,
30026
+ issues: telephonyMedia.issues.length,
30027
+ lifecycleFailures: telephonyMedia.carriers.filter((carrier) => carrier.lifecycle.status !== "pass").length,
30028
+ mediaEvents: telephonyMediaTotalMediaEvents,
30029
+ passed: telephonyMedia.carriers.filter((carrier) => carrier.status === "pass").length,
30030
+ status: telephonyMedia.status === "pass" && telephonyMediaBreadthFailures.length === 0 ? "pass" : "fail"
30031
+ };
30032
+ })() : undefined;
30033
+ const browserMediaBreadthSummary = browserMediaBreadthFailures.length > 0 ? browserMediaBreadthFailures : undefined;
30034
+ const telephonyMediaBreadthSummary = telephonyMediaBreadthFailures.length > 0 ? telephonyMediaBreadthFailures : undefined;
29854
30035
  checks.push({
29855
30036
  detail: liveLatency.total === 0 ? "No browser live-latency measurements are recorded yet." : liveLatency.status === "pass" ? `Live browser turn latency averages ${liveLatency.averageLatencyMs}ms.` : `${liveLatency.failed} failed and ${liveLatency.warnings} warned live-latency measurement(s).`,
29856
30037
  href: firstOperationsRecordHref(operationsRecords.failingLatency) ?? options.links?.liveLatency ?? "/traces",
@@ -29921,11 +30102,17 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
29921
30102
  if (browserMedia && browserMediaSummary) {
29922
30103
  const firstIssue = browserMedia.issues[0];
29923
30104
  checks.push({
29924
- detail: browserMediaSummary.status === "pass" ? `Browser media transport is passing with ${browserMediaSummary.activeCandidatePairs} active candidate pair(s), ${browserMediaSummary.liveAudioTracks} live audio track(s), ${String(browserMediaSummary.roundTripTimeMs ?? "n/a")}ms RTT, ${String(browserMediaSummary.jitterMs ?? "n/a")}ms jitter, and ${browserMediaSummary.packetLossRatio} packet loss ratio.` : firstIssue?.message ?? `${browserMediaSummary.issues} browser media transport issue(s) need review.`,
30105
+ detail: browserMediaSummary.status === "pass" ? `Browser media transport is passing with ${browserMediaSummary.activeCandidatePairs} active candidate pair(s), ${browserMediaSummary.liveAudioTracks} live audio track(s), ${String(browserMediaSummary.roundTripTimeMs ?? "n/a")}ms RTT, ${String(browserMediaSummary.jitterMs ?? "n/a")}ms jitter, and ${browserMediaSummary.packetLossRatio} packet loss ratio.` : browserMediaBreadthSummary ? browserMediaBreadthSummary.join("; ") : firstIssue?.message ?? `${browserMediaSummary.issues} browser media transport issue(s) need review.`,
29925
30106
  href: options.links?.browserMedia ?? "/voice/browser-media",
29926
30107
  label: "Browser media transport",
29927
30108
  proofSource: proofSource("browserMedia", "webrtcStats"),
29928
- gateExplanation: browserMediaSummary.status === "pass" ? undefined : {
30109
+ gateExplanation: browserMediaSummary.status === "pass" ? undefined : browserMediaBreadthSummary ? {
30110
+ evidenceHref: options.links?.browserMedia ?? "/voice/browser-media",
30111
+ observed: browserMediaBreadthSummary.join("; "),
30112
+ remediation: "Collect richer browser media evidence and rerun readiness so active candidate-pair, track, and stats thresholds are met.",
30113
+ thresholdLabel: "Browser media breadth",
30114
+ unit: "count"
30115
+ } : {
29929
30116
  evidenceHref: options.links?.browserMedia ?? "/voice/browser-media",
29930
30117
  observed: firstIssue?.code ?? `${browserMediaSummary.issues} issue(s)`,
29931
30118
  remediation: "Inspect browser WebRTC media stats, fix packet loss, RTT, jitter, candidate-pair, or audio-track issues, then rerun readiness proof.",
@@ -29946,11 +30133,17 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
29946
30133
  if (telephonyMedia && telephonyMediaSummary) {
29947
30134
  const firstIssue = telephonyMedia.issues[0];
29948
30135
  checks.push({
29949
- detail: telephonyMediaSummary.status === "pass" ? `Telephony media serializers are passing for ${telephonyMediaSummary.passed}/${telephonyMediaSummary.carriers} carrier(s) with ${telephonyMediaSummary.audioBytes} audio byte(s), ${telephonyMediaSummary.mediaEvents} media event(s), and valid start/media/stop lifecycle sequencing.` : firstIssue ?? `${telephonyMediaSummary.issues} telephony media serializer issue(s) need review.`,
30136
+ detail: telephonyMediaSummary.status === "pass" ? `Telephony media serializers are passing for ${telephonyMediaSummary.passed}/${telephonyMediaSummary.carriers} carrier(s) with ${telephonyMediaSummary.audioBytes} audio byte(s), ${telephonyMediaSummary.mediaEvents} media event(s), and valid start/media/stop lifecycle sequencing.` : telephonyMediaBreadthSummary ? telephonyMediaBreadthSummary.join("; ") : firstIssue ?? `${telephonyMediaSummary.issues} telephony media serializer issue(s) need review.`,
29950
30137
  href: firstOperationsRecordHref(operationsRecords.telephonyMedia) ?? options.links?.telephonyMedia ?? "/voice/telephony-media",
29951
30138
  label: "Telephony media serializers",
29952
30139
  proofSource: proofSource("telephonyMedia", "carrierMediaSerializers"),
29953
- gateExplanation: telephonyMediaSummary.status === "pass" ? undefined : {
30140
+ gateExplanation: telephonyMediaSummary.status === "pass" ? undefined : telephonyMediaBreadthSummary ? {
30141
+ evidenceHref: firstOperationsRecordHref(operationsRecords.telephonyMedia) ?? options.links?.telephonyMedia ?? "/voice/telephony-media",
30142
+ observed: telephonyMediaBreadthSummary.join("; "),
30143
+ remediation: "Collect richer telephony lifecycle evidence and rerun readiness so carrier/media-event thresholds are met.",
30144
+ thresholdLabel: "Telephony media breadth",
30145
+ unit: "count"
30146
+ } : {
29954
30147
  evidenceHref: firstOperationsRecordHref(operationsRecords.telephonyMedia) ?? options.links?.telephonyMedia ?? "/voice/telephony-media",
29955
30148
  observed: firstIssue ?? `${telephonyMediaSummary.issues} issue(s)`,
29956
30149
  remediation: "Inspect carrier media proof, fix start/media/stop sequencing, payload parsing, byte flow, or outbound envelope serialization, then rerun readiness proof.",
@@ -30037,17 +30230,31 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
30037
30230
  status: telephonyWebhookSecurity.status,
30038
30231
  warned: telephonyWebhookSecurity.summary.warned
30039
30232
  } : undefined;
30233
+ let reconnectContractBreadthFailures = [];
30040
30234
  const reconnectContractSummary = reconnectContracts ? (() => {
30235
+ const reconnectContractCountMin = typeof options.reconnectContractsMinCount === "number" && options.reconnectContractsMinCount >= 0 ? options.reconnectContractsMinCount : undefined;
30236
+ const reconnectContractSnapshotsMin = typeof options.reconnectContractsMinSnapshotsPerContract === "number" && options.reconnectContractsMinSnapshotsPerContract >= 0 ? options.reconnectContractsMinSnapshotsPerContract : undefined;
30237
+ const reconnectSnapshotShortfallCount = reconnectContractSnapshotsMin === undefined ? 0 : reconnectContracts.filter((report) => typeof report.snapshotCount === "number" && report.snapshotCount < reconnectContractSnapshotsMin).length;
30238
+ const reconnectContractCountShortfall = reconnectContractCountMin === undefined ? 0 : Math.max(0, reconnectContractCountMin - reconnectContracts.length);
30239
+ reconnectContractBreadthFailures = reconnectContractCountShortfall > 0 ? [
30240
+ `Expected at least ${reconnectContractCountMin} reconnect contract(s), observed ${reconnectContracts.length}.`
30241
+ ] : [];
30242
+ if (reconnectSnapshotShortfallCount > 0) {
30243
+ reconnectContractBreadthFailures.push(`${reconnectSnapshotShortfallCount} reconnect contract(s) with fewer than ${reconnectContractSnapshotsMin} snapshot(s).`);
30244
+ }
30041
30245
  const failedReports = reconnectContracts.filter((report) => !report.pass || options.reconnectResumeFailAfterMs !== undefined && report.resumeLatencyP95Ms !== undefined && report.resumeLatencyP95Ms > options.reconnectResumeFailAfterMs);
30042
30246
  const resumeLatencies = reconnectContracts.map((report) => report.resumeLatencyP95Ms).filter((value) => typeof value === "number");
30247
+ const reconnectContractBreadthFailureCount = reconnectContractBreadthFailures.length > 0 ? Math.min(reconnectContracts.length, reconnectContractBreadthFailures.length) : 0;
30248
+ const passedCount = Math.max(0, reconnectContracts.length - (failedReports.length + reconnectContractBreadthFailureCount));
30043
30249
  return {
30044
- failed: failedReports.length,
30045
- passed: reconnectContracts.length - failedReports.length,
30250
+ failed: failedReports.length + reconnectContractBreadthFailureCount,
30251
+ passed: passedCount,
30046
30252
  resumeLatencyP95Ms: resumeLatencies.length > 0 ? Math.max(...resumeLatencies) : undefined,
30047
- status: failedReports.length > 0 ? "fail" : reconnectContracts.length === 0 ? "warn" : "pass",
30253
+ status: failedReports.length > 0 || reconnectContractBreadthFailures.length > 0 ? "fail" : reconnectContracts.length === 0 ? "warn" : "pass",
30048
30254
  total: reconnectContracts.length
30049
30255
  };
30050
30256
  })() : undefined;
30257
+ const reconnectContractBreadthSummary = reconnectContractBreadthFailures.length > 0 ? reconnectContractBreadthFailures : undefined;
30051
30258
  const bargeInSummary = bargeInReports ? {
30052
30259
  failed: bargeInReports.reduce((total, report) => total + report.failed, 0),
30053
30260
  passed: bargeInReports.reduce((total, report) => total + report.passed, 0),
@@ -30077,6 +30284,19 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
30077
30284
  total: incidentRecoveryOutcomes.total,
30078
30285
  unchanged: incidentRecoveryOutcomes.unchanged
30079
30286
  } : undefined;
30287
+ const incidentRecoveryTrendSummary = incidentRecoveryTrend && incidentRecoveryTrendReadiness ? {
30288
+ cycles: incidentRecoveryTrend.summary.cycles,
30289
+ failed: incidentRecoveryTrend.summary.failed,
30290
+ failureRate: incidentRecoveryTrend.summary.failureRate,
30291
+ improved: incidentRecoveryTrend.summary.improved,
30292
+ improvementRate: incidentRecoveryTrend.summary.improvementRate,
30293
+ regressed: incidentRecoveryTrend.summary.regressed,
30294
+ regressionRate: incidentRecoveryTrend.summary.regressionRate,
30295
+ status: incidentRecoveryTrendReadiness.status,
30296
+ total: incidentRecoveryTrend.summary.total,
30297
+ unchanged: incidentRecoveryTrend.summary.unchanged,
30298
+ unchangedRate: incidentRecoveryTrend.summary.unchangedRate
30299
+ } : undefined;
30080
30300
  const observabilityExportDeliveryHistorySummary = observabilityExportDeliveryHistory ? (() => {
30081
30301
  const latestSuccess = observabilityExportDeliveryHistory.history.receipts.filter((receipt) => receipt.status === "pass" && receipt.summary.delivered > 0 && receipt.summary.failed === 0).sort((left, right) => right.checkedAt - left.checkedAt)[0];
30082
30302
  const latestSuccessAgeMs = latestSuccess ? Date.now() - latestSuccess.checkedAt : undefined;
@@ -30300,11 +30520,17 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
30300
30520
  }
30301
30521
  if (reconnectContractSummary) {
30302
30522
  checks.push({
30303
- detail: reconnectContractSummary.status === "pass" ? `${reconnectContractSummary.passed} reconnect contract(s) are passing.` : reconnectContractSummary.total === 0 ? "No reconnect contracts are configured." : options.reconnectResumeFailAfterMs !== undefined && reconnectContractSummary.resumeLatencyP95Ms !== undefined && reconnectContractSummary.resumeLatencyP95Ms > options.reconnectResumeFailAfterMs ? `Reconnect resume p95 ${reconnectContractSummary.resumeLatencyP95Ms}ms exceeded ${options.reconnectResumeFailAfterMs}ms.` : `${reconnectContractSummary.failed} reconnect contract(s) failed.`,
30523
+ detail: reconnectContractSummary.status === "pass" ? `${reconnectContractSummary.passed} reconnect contract(s) are passing.` : reconnectContractBreadthSummary && reconnectContractBreadthSummary.length > 0 ? reconnectContractBreadthSummary.join("; ") : reconnectContractSummary.total === 0 ? "No reconnect contracts are configured." : options.reconnectResumeFailAfterMs !== undefined && reconnectContractSummary.resumeLatencyP95Ms !== undefined && reconnectContractSummary.resumeLatencyP95Ms > options.reconnectResumeFailAfterMs ? `Reconnect resume p95 ${reconnectContractSummary.resumeLatencyP95Ms}ms exceeded ${options.reconnectResumeFailAfterMs}ms.` : `${reconnectContractSummary.failed} reconnect contract(s) failed.`,
30304
30524
  href: options.links?.reconnectContracts ?? options.links?.sessions ?? "/sessions",
30305
30525
  label: "Reconnect recovery contracts",
30306
30526
  proofSource: proofSource("reconnectContracts", "reconnect"),
30307
- gateExplanation: reconnectContractSummary.status === "pass" ? undefined : calibratedGateExplanation({
30527
+ gateExplanation: reconnectContractSummary.status === "pass" ? undefined : reconnectContractBreadthSummary && reconnectContractBreadthSummary.length > 0 ? {
30528
+ evidenceHref: options.links?.reconnectContracts ?? options.links?.sessions ?? "/sessions",
30529
+ observed: reconnectContractBreadthSummary.join("; "),
30530
+ remediation: "Increase reconnect contract breadth (count and snapshot depth) before marking this gate as passing.",
30531
+ thresholdLabel: "Reconnect contract breadth",
30532
+ unit: "count"
30533
+ } : calibratedGateExplanation({
30308
30534
  evidenceHref: options.links?.reconnectContracts ?? options.links?.sessions ?? "/sessions",
30309
30535
  observed: reconnectContractSummary.resumeLatencyP95Ms,
30310
30536
  remediation: "Inspect reconnect lifecycle traces, restore faster resume/replay-safe state, then rerun reconnect proof.",
@@ -30573,6 +30799,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
30573
30799
  handoffRetry: "/api/voice-handoffs/retry",
30574
30800
  liveLatency: "/traces",
30575
30801
  operationsRecords: "/voice-operations",
30802
+ incidentRecoveryTrends: "/voice/incident-recovery-trends",
30576
30803
  observabilityExport: "/voice/observability-export",
30577
30804
  observabilityExportDeliveries: "/api/voice/observability-export/deliveries",
30578
30805
  monitoring: "/voice/monitors",
@@ -30617,6 +30844,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
30617
30844
  },
30618
30845
  liveLatency,
30619
30846
  incidentRecoveryOutcomes: incidentRecoveryOutcomeSummary,
30847
+ incidentRecoveryTrend: incidentRecoveryTrendSummary,
30620
30848
  mediaPipeline: mediaPipelineSummary,
30621
30849
  monitoring: monitoringSummary,
30622
30850
  monitoringNotifierDelivery: monitoringNotifierDeliverySummary,
@@ -31576,7 +31804,10 @@ var runVoiceSessionEvals = async (options = {}) => {
31576
31804
  const events = filterVoiceTraceEvents(options.events ?? await options.store?.list() ?? []);
31577
31805
  const grouped = new Map;
31578
31806
  for (const event of events) {
31579
- grouped.set(event.sessionId, [...grouped.get(event.sessionId) ?? [], event]);
31807
+ grouped.set(event.sessionId, [
31808
+ ...grouped.get(event.sessionId) ?? [],
31809
+ event
31810
+ ]);
31580
31811
  }
31581
31812
  const sessions = await Promise.all([...grouped.entries()].map(async ([sessionId, sessionEvents]) => {
31582
31813
  const sorted = filterVoiceTraceEvents(sessionEvents);
@@ -31692,7 +31923,10 @@ var runVoiceScenarioEvals = async (options = {}) => {
31692
31923
  const events = filterVoiceTraceEvents(options.events ?? await options.store?.list() ?? []);
31693
31924
  const grouped = new Map;
31694
31925
  for (const event of events) {
31695
- grouped.set(event.sessionId, [...grouped.get(event.sessionId) ?? [], event]);
31926
+ grouped.set(event.sessionId, [
31927
+ ...grouped.get(event.sessionId) ?? [],
31928
+ event
31929
+ ]);
31696
31930
  }
31697
31931
  const results = scenarios.map((scenario) => {
31698
31932
  const sessions = [...grouped.entries()].filter(([, sessionEvents]) => scenario.scenarioId ? sessionEvents.some((event) => event.scenarioId === scenario.scenarioId) : true).map(([sessionId, sessionEvents]) => evaluateScenarioSession(scenario, sessionId, filterVoiceTraceEvents(sessionEvents), resolveSessionHref3(options.operationsRecordHref, sessionId))).sort((left, right) => left.sessionId.localeCompare(right.sessionId));
@@ -31726,7 +31960,10 @@ var runVoiceScenarioEvals = async (options = {}) => {
31726
31960
  total: results.length
31727
31961
  };
31728
31962
  };
31729
- var resolveScenarioFixtures = async (options) => [...options.fixtures ?? [], ...await options.fixtureStore?.list() ?? []];
31963
+ var resolveScenarioFixtures = async (options) => [
31964
+ ...options.fixtures ?? [],
31965
+ ...await options.fixtureStore?.list() ?? []
31966
+ ];
31730
31967
  var runVoiceScenarioFixtureEvals = async (options = {}) => {
31731
31968
  const fixtures = await resolveScenarioFixtures(options);
31732
31969
  const results = await Promise.all(fixtures.map(async (fixture) => {
@@ -32689,7 +32926,9 @@ var evaluateVoiceToolContractEvidence = (report, input = {}) => {
32689
32926
  const toolNames = [
32690
32927
  ...new Set(report.contracts.map((contract) => contract.toolName))
32691
32928
  ].sort();
32692
- const caseStatuses = [...new Set(cases.map((testCase) => testCase.status))].sort();
32929
+ const caseStatuses = [
32930
+ ...new Set(cases.map((testCase) => testCase.status))
32931
+ ].sort();
32693
32932
  const issueCount = report.contracts.reduce((total, contract) => total + contract.issues.length, 0);
32694
32933
  const timedOut = cases.filter((testCase) => testCase.timedOut).length;
32695
32934
  const missingOperationsRecordHrefs = cases.filter((testCase) => !testCase.operationsRecordHref).length;
@@ -33198,7 +33437,11 @@ var presetDefinitions = {
33198
33437
  "appointment-booking": {
33199
33438
  description: "Appointment booking should complete with enough identity, appointment, and follow-up details to act on.",
33200
33439
  fields: [
33201
- { aliases: ["name", "customer.name"], label: "Caller name", path: "caller.name" },
33440
+ {
33441
+ aliases: ["name", "customer.name"],
33442
+ label: "Caller name",
33443
+ path: "caller.name"
33444
+ },
33202
33445
  {
33203
33446
  aliases: ["phone", "customer.phone"],
33204
33447
  label: "Caller phone",
@@ -33223,7 +33466,11 @@ var presetDefinitions = {
33223
33466
  "lead-qualification": {
33224
33467
  description: "Lead qualification should complete with contact, need, qualification, and next-step fields.",
33225
33468
  fields: [
33226
- { aliases: ["name", "lead.name"], label: "Lead name", path: "contact.name" },
33469
+ {
33470
+ aliases: ["name", "lead.name"],
33471
+ label: "Lead name",
33472
+ path: "contact.name"
33473
+ },
33227
33474
  {
33228
33475
  aliases: ["email", "lead.email"],
33229
33476
  label: "Lead email",
@@ -33606,7 +33853,9 @@ var evaluateVoiceAgentSquadContractEvidence = (reports, input = {}) => {
33606
33853
  const maxIssues = input.maxIssues ?? 0;
33607
33854
  const maxBlockedHandoffs = input.maxBlockedHandoffs ?? Infinity;
33608
33855
  const allHandoffs = reports.flatMap((report) => report.turns.flatMap((turn) => turn.handoffs));
33609
- const contractIds = [...new Set(reports.map((report) => report.contractId))].sort();
33856
+ const contractIds = [
33857
+ ...new Set(reports.map((report) => report.contractId))
33858
+ ].sort();
33610
33859
  const scenarioIds = [
33611
33860
  ...new Set(reports.map((report) => report.scenarioId).filter((scenarioId) => Boolean(scenarioId)))
33612
33861
  ].sort();
@@ -33785,7 +34034,11 @@ var summarizeVoiceTurnLatency = async (options) => {
33785
34034
  const stageIndex = createTraceStageIndex(traceEvents);
33786
34035
  const warnAfterMs = options.warnAfterMs ?? DEFAULT_WARN_AFTER_MS2;
33787
34036
  const failAfterMs = options.failAfterMs ?? DEFAULT_FAIL_AFTER_MS2;
33788
- const turns = sessions.flatMap((session) => session.turns.map((turn) => summarizeTurn(session.id, turn, { failAfterMs, stageIndex, warnAfterMs }))).sort((left, right) => right.committedAt - left.committedAt);
34037
+ const turns = sessions.flatMap((session) => session.turns.map((turn) => summarizeTurn(session.id, turn, {
34038
+ failAfterMs,
34039
+ stageIndex,
34040
+ warnAfterMs
34041
+ }))).sort((left, right) => right.committedAt - left.committedAt);
33789
34042
  const totals = turns.map((turn) => turn.totalMs).filter((value) => typeof value === "number");
33790
34043
  const failed = turns.filter((turn) => turn.status === "fail").length;
33791
34044
  const warnings = turns.filter((turn) => turn.status === "warn").length;
@@ -36182,7 +36435,9 @@ var createOpenAIVoiceTTS = (options) => {
36182
36435
  };
36183
36436
  const abortController = new AbortController;
36184
36437
  const signalAbort = () => abortController.abort();
36185
- openOptions.signal?.addEventListener("abort", signalAbort, { once: true });
36438
+ openOptions.signal?.addEventListener("abort", signalAbort, {
36439
+ once: true
36440
+ });
36186
36441
  let closed = false;
36187
36442
  return {
36188
36443
  close: async (reason) => {
@@ -36310,7 +36565,9 @@ var resolveCapabilityDefinitions = (options) => {
36310
36565
  };
36311
36566
  var summarizeVoiceProviderCapabilities = async (options) => {
36312
36567
  const definitions = resolveCapabilityDefinitions(options);
36313
- const providerNames = [...new Set(definitions.map((entry) => entry.provider))];
36568
+ const providerNames = [
36569
+ ...new Set(definitions.map((entry) => entry.provider))
36570
+ ];
36314
36571
  const health = await summarizeVoiceProviderHealth({
36315
36572
  events: options.events,
36316
36573
  now: options.now,
@@ -36638,7 +36895,9 @@ var evaluateVoiceProviderRoutingContractEvidence = (reports, input = {}) => {
36638
36895
  const maxFailed = input.maxFailed ?? 0;
36639
36896
  const maxIssues = input.maxIssues ?? 0;
36640
36897
  const events = reports.flatMap((report) => report.events);
36641
- const contractIds = [...new Set(reports.map((report) => report.contractId))].sort();
36898
+ const contractIds = [
36899
+ ...new Set(reports.map((report) => report.contractId))
36900
+ ].sort();
36642
36901
  const scenarioIds = [
36643
36902
  ...new Set(reports.map((report) => report.scenarioId).filter((scenarioId) => Boolean(scenarioId)))
36644
36903
  ].sort();
@@ -37354,6 +37613,11 @@ var createVoiceReadinessProfile = (profile, options = {}) => {
37354
37613
  bargeInReports: options.bargeInReports,
37355
37614
  gate: options.gate,
37356
37615
  links: links2,
37616
+ browserMediaMinActiveCandidatePairs: options.browserMediaMinActiveCandidatePairs ?? 1,
37617
+ browserMediaMinLiveAudioTracks: options.browserMediaMinLiveAudioTracks ?? 1,
37618
+ browserMediaMinTotalStats: options.browserMediaMinTotalStats ?? 3,
37619
+ reconnectContractsMinCount: options.reconnectContractsMinCount ?? 1,
37620
+ reconnectContractsMinSnapshotsPerContract: options.reconnectContractsMinSnapshotsPerContract ?? 1,
37357
37621
  profile: profileExplanation(profile, options, links2),
37358
37622
  proofSources: options.proofSources,
37359
37623
  providerRoutingContracts: options.providerRoutingContracts,
@@ -37387,6 +37651,13 @@ var createVoiceReadinessProfile = (profile, options = {}) => {
37387
37651
  profile: profileExplanation(profile, options, links2),
37388
37652
  proofSources: options.proofSources,
37389
37653
  providerRoutingContracts: options.providerRoutingContracts,
37654
+ reconnectContractsMinCount: options.reconnectContractsMinCount ?? 1,
37655
+ reconnectContractsMinSnapshotsPerContract: options.reconnectContractsMinSnapshotsPerContract ?? 1,
37656
+ telephonyMediaMinCarriers: options.telephonyMediaMinCarriers ?? 1,
37657
+ telephonyMediaMinMediaEvents: options.telephonyMediaMinMediaEvents ?? 2,
37658
+ browserMediaMinActiveCandidatePairs: options.browserMediaMinActiveCandidatePairs ?? 1,
37659
+ browserMediaMinLiveAudioTracks: options.browserMediaMinLiveAudioTracks ?? 1,
37660
+ browserMediaMinTotalStats: options.browserMediaMinTotalStats ?? 3,
37390
37661
  telephonyWebhookSecurity: options.telephonyWebhookSecurity,
37391
37662
  traceDeliveries: options.traceDeliveries
37392
37663
  });
@@ -37506,11 +37777,7 @@ var defaultProviderEnv2 = {
37506
37777
  gemini: ["GEMINI_API_KEY"],
37507
37778
  openai: ["OPENAI_API_KEY"]
37508
37779
  };
37509
- var defaultStreamingProviders = new Set([
37510
- "assemblyai",
37511
- "deepgram",
37512
- "openai"
37513
- ]);
37780
+ var defaultStreamingProviders = new Set(["assemblyai", "deepgram", "openai"]);
37514
37781
  var defaultProviderCapabilities = {
37515
37782
  anthropic: ["tool calling", "JSON result shaping", "fallback routing"],
37516
37783
  assemblyai: ["realtime STT", "turn formatting", "fallback STT"],
@@ -40535,10 +40802,7 @@ var createRiskyTurnCorrectionHandler = (options = {}) => {
40535
40802
  if (averageConfidence !== undefined && averageConfidence > maxAverageConfidence) {
40536
40803
  return;
40537
40804
  }
40538
- const result = applyRiskTieredPhraseHintCorrections(text, [
40539
- ...phraseHints,
40540
- ...lexiconToPhraseHints(lexicon)
40541
- ], { riskTier });
40805
+ const result = applyRiskTieredPhraseHintCorrections(text, [...phraseHints, ...lexiconToPhraseHints(lexicon)], { riskTier });
40542
40806
  if (!result.changed) {
40543
40807
  return;
40544
40808
  }
@@ -41304,7 +41568,9 @@ var createVoiceProofPackSupportBundleSection = (input) => {
41304
41568
  };
41305
41569
  };
41306
41570
  var buildDerivedProofPackSections = (input) => [
41307
- ...input.productionReadiness ? [createVoiceProofPackProductionReadinessSection(input.productionReadiness)] : [],
41571
+ ...input.productionReadiness ? [
41572
+ createVoiceProofPackProductionReadinessSection(input.productionReadiness)
41573
+ ] : [],
41308
41574
  ...input.providerSlo ? [
41309
41575
  createVoiceProofPackProviderSloSection(input.providerSlo, {
41310
41576
  href: input.productionReadiness?.links.providerSlo
@@ -41331,7 +41597,10 @@ var buildVoiceProofPack = (input) => {
41331
41597
  if ("status" in input && "ok" in input && "summary" in input && Array.isArray(input.sections)) {
41332
41598
  return input;
41333
41599
  }
41334
- const sections = [...buildDerivedProofPackSections(input), ...input.sections ?? []];
41600
+ const sections = [
41601
+ ...buildDerivedProofPackSections(input),
41602
+ ...input.sections ?? []
41603
+ ];
41335
41604
  const summary = summarizeProofPackSections(sections);
41336
41605
  const status = summary.fail > 0 ? "fail" : summary.warn > 0 ? "warn" : "pass";
41337
41606
  return {
@@ -41486,13 +41755,7 @@ var renderVoiceProofPackMarkdown = (proofPack) => {
41486
41755
  return `- ${item.label}${value}${href} - ${item.status ?? "pass"}${detail}`;
41487
41756
  }).join(`
41488
41757
  `);
41489
- return [
41490
- `## ${section.title}`,
41491
- "",
41492
- section.summary ?? "",
41493
- "",
41494
- evidence
41495
- ].filter(Boolean).join(`
41758
+ return [`## ${section.title}`, "", section.summary ?? "", "", evidence].filter(Boolean).join(`
41496
41759
  `);
41497
41760
  }).join(`
41498
41761
 
@@ -42259,6 +42522,7 @@ export {
42259
42522
  buildVoiceLiveOpsControlState,
42260
42523
  buildVoiceLatencySLOGate,
42261
42524
  buildVoiceIncidentTimelineReport,
42525
+ buildVoiceIncidentRecoveryTrendSLOReadinessCheck,
42262
42526
  buildVoiceIncidentRecoveryTrendReport,
42263
42527
  buildVoiceIncidentRecoveryOutcomeReport,
42264
42528
  buildVoiceIncidentRecoveryOutcomeReadinessCheck,