@absolutejs/voice 0.0.22-beta.252 → 0.0.22-beta.253

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.
@@ -3000,6 +3000,84 @@ var readVoiceProofTrendReportFile = async (path, options = {}) => {
3000
3000
  });
3001
3001
  }
3002
3002
  };
3003
+ var maxNumber = (values) => {
3004
+ const finite = values.filter((value) => typeof value === "number" && Number.isFinite(value));
3005
+ return finite.length > 0 ? Math.max(...finite) : undefined;
3006
+ };
3007
+ var readProofTrendMaxLiveP95 = (report) => report.summary.maxLiveP95Ms ?? maxNumber(report.cycles.map((cycle) => cycle.liveLatency?.p95Ms));
3008
+ var readProofTrendMaxProviderP95 = (report) => report.summary.maxProviderP95Ms;
3009
+ var readProofTrendMaxTurnP95 = (report) => report.summary.maxTurnP95Ms ?? maxNumber(report.cycles.map((cycle) => cycle.turnLatency?.p95Ms));
3010
+ var evaluateVoiceProofTrendEvidence = (report, input = {}) => {
3011
+ const issues = [];
3012
+ const requiredStatus = input.requireStatus ?? "pass";
3013
+ const minCycles = input.minCycles ?? 1;
3014
+ const requireAllCyclesOk = input.requireAllCyclesOk ?? true;
3015
+ const cycles = report.summary.cycles ?? report.cycles.length;
3016
+ const failedCycles = report.cycles.filter((cycle) => cycle.ok !== true).length;
3017
+ const maxLiveP95Ms = readProofTrendMaxLiveP95(report);
3018
+ const maxProviderP95Ms = readProofTrendMaxProviderP95(report);
3019
+ const maxTurnP95Ms = readProofTrendMaxTurnP95(report);
3020
+ if (report.status !== requiredStatus) {
3021
+ issues.push(`Expected proof trends status ${requiredStatus}, found ${report.status}.`);
3022
+ }
3023
+ if (report.ok !== true) {
3024
+ issues.push("Expected proof trends ok to be true.");
3025
+ }
3026
+ if (cycles < minCycles) {
3027
+ issues.push(`Expected at least ${String(minCycles)} proof trend cycle(s), found ${String(cycles)}.`);
3028
+ }
3029
+ if (requireAllCyclesOk && failedCycles > 0) {
3030
+ issues.push(`Expected all proof trend cycles to pass, found ${String(failedCycles)} failing cycle(s).`);
3031
+ }
3032
+ if (input.maxAgeMs !== undefined && (report.ageMs === undefined || report.ageMs > input.maxAgeMs)) {
3033
+ issues.push(report.ageMs === undefined ? "Missing proof trends artifact age." : `Expected proof trends age at most ${String(input.maxAgeMs)}ms, found ${String(report.ageMs)}ms.`);
3034
+ }
3035
+ if (input.maxLiveP95Ms !== undefined && (maxLiveP95Ms === undefined || maxLiveP95Ms > input.maxLiveP95Ms)) {
3036
+ issues.push(maxLiveP95Ms === undefined ? "Missing proof trends live latency p95." : `Expected proof trends live latency p95 at most ${String(input.maxLiveP95Ms)}ms, found ${String(maxLiveP95Ms)}ms.`);
3037
+ }
3038
+ if (input.maxProviderP95Ms !== undefined && (maxProviderP95Ms === undefined || maxProviderP95Ms > input.maxProviderP95Ms)) {
3039
+ issues.push(maxProviderP95Ms === undefined ? "Missing proof trends provider p95." : `Expected proof trends provider p95 at most ${String(input.maxProviderP95Ms)}ms, found ${String(maxProviderP95Ms)}ms.`);
3040
+ }
3041
+ if (input.maxTurnP95Ms !== undefined && (maxTurnP95Ms === undefined || maxTurnP95Ms > input.maxTurnP95Ms)) {
3042
+ issues.push(maxTurnP95Ms === undefined ? "Missing proof trends turn latency p95." : `Expected proof trends turn latency p95 at most ${String(input.maxTurnP95Ms)}ms, found ${String(maxTurnP95Ms)}ms.`);
3043
+ }
3044
+ if (input.minLiveLatencySamples !== undefined) {
3045
+ const lowSamples = report.cycles.filter((cycle) => (cycle.liveLatency?.samples ?? 0) < input.minLiveLatencySamples).length;
3046
+ if (lowSamples > 0) {
3047
+ issues.push(`Expected every proof trend cycle to have at least ${String(input.minLiveLatencySamples)} live latency sample(s), found ${String(lowSamples)} low-sample cycle(s).`);
3048
+ }
3049
+ }
3050
+ if (input.minProviderSloEventsWithLatency !== undefined) {
3051
+ const lowSamples = report.cycles.filter((cycle) => (cycle.providerSlo?.eventsWithLatency ?? 0) < input.minProviderSloEventsWithLatency).length;
3052
+ if (lowSamples > 0) {
3053
+ issues.push(`Expected every proof trend cycle to have at least ${String(input.minProviderSloEventsWithLatency)} provider latency event(s), found ${String(lowSamples)} low-sample cycle(s).`);
3054
+ }
3055
+ }
3056
+ if (input.minTurnLatencySamples !== undefined) {
3057
+ const lowSamples = report.cycles.filter((cycle) => (cycle.turnLatency?.samples ?? 0) < input.minTurnLatencySamples).length;
3058
+ if (lowSamples > 0) {
3059
+ issues.push(`Expected every proof trend cycle to have at least ${String(input.minTurnLatencySamples)} turn latency sample(s), found ${String(lowSamples)} low-sample cycle(s).`);
3060
+ }
3061
+ }
3062
+ return {
3063
+ ageMs: report.ageMs,
3064
+ cycles,
3065
+ failedCycles,
3066
+ issues,
3067
+ maxLiveP95Ms,
3068
+ maxProviderP95Ms,
3069
+ maxTurnP95Ms,
3070
+ ok: issues.length === 0,
3071
+ status: report.status
3072
+ };
3073
+ };
3074
+ var assertVoiceProofTrendEvidence = (report, input = {}) => {
3075
+ const assertion = evaluateVoiceProofTrendEvidence(report, input);
3076
+ if (!assertion.ok) {
3077
+ throw new Error(`Voice proof trends assertion failed: ${assertion.issues.join(" ")}`);
3078
+ }
3079
+ return assertion;
3080
+ };
3003
3081
  var createVoiceProofTrendRoutes = (options) => {
3004
3082
  const path = options.path ?? "/api/voice/proof-trends";
3005
3083
  const routes = new Elysia({
package/dist/index.d.ts CHANGED
@@ -16,8 +16,8 @@ export { buildVoiceDeliverySinkReport, createVoiceDeliverySinkDescriptor, create
16
16
  export { buildVoiceOpsActionHistoryReport, createVoiceOpsActionAuditRoutes, recordVoiceOpsActionAudit, renderVoiceOpsActionHistoryHTML } from './opsActionAuditRoutes';
17
17
  export { assertVoicePlatformCoverage, buildVoicePlatformCoverageSummary, createVoicePlatformCoverageRoutes, evaluateVoicePlatformCoverage } from './platformCoverage';
18
18
  export type { VoicePlatformCoverageAssertionInput, VoicePlatformCoverageAssertionReport, VoicePlatformCoverageEvidence, VoicePlatformCoverageRoutesOptions, VoicePlatformCoverageStatus, VoicePlatformCoverageSummary, VoicePlatformCoverageSummaryInput, VoicePlatformCoverageSurface } from './platformCoverage';
19
- export { buildEmptyVoiceProofTrendReport, buildVoiceProofTrendReport, createVoiceProofTrendRoutes, DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS, formatVoiceProofTrendAge, normalizeVoiceProofTrendReport, readVoiceProofTrendReportFile } from './proofTrends';
20
- export type { VoiceProofTrendCycle, VoiceProofTrendReport, VoiceProofTrendReportInput, VoiceProofTrendRoutesOptions, VoiceProofTrendStatus, VoiceProofTrendSummary } from './proofTrends';
19
+ export { assertVoiceProofTrendEvidence, buildEmptyVoiceProofTrendReport, buildVoiceProofTrendReport, createVoiceProofTrendRoutes, DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS, evaluateVoiceProofTrendEvidence, formatVoiceProofTrendAge, normalizeVoiceProofTrendReport, readVoiceProofTrendReportFile } from './proofTrends';
20
+ export type { VoiceProofTrendAssertionInput, VoiceProofTrendAssertionReport, VoiceProofTrendCycle, VoiceProofTrendReport, VoiceProofTrendReportInput, VoiceProofTrendRoutesOptions, VoiceProofTrendStatus, VoiceProofTrendSummary } from './proofTrends';
21
21
  export { buildVoiceLiveOpsControlState, createVoiceLiveOpsController, createVoiceLiveOpsRoutes, createVoiceMemoryLiveOpsControlStore, getVoiceLiveOpsControlStatus, VOICE_LIVE_OPS_ACTIONS } from './liveOps';
22
22
  export type { VoiceLiveOpsAction, VoiceLiveOpsActionInput, VoiceLiveOpsActionResult, VoiceLiveOpsControllerOptions, VoiceLiveOpsControlState, VoiceLiveOpsControlStatus, VoiceLiveOpsControlStore, VoiceLiveOpsRoutesOptions } from './liveOps';
23
23
  export { buildVoiceDeliveryRuntimeReport, createVoiceDeliveryRuntime, createVoiceDeliveryRuntimePresetConfig, createVoiceDeliveryRuntimeRoutes, renderVoiceDeliveryRuntimeHTML } from './deliveryRuntime';
package/dist/index.js CHANGED
@@ -12405,6 +12405,84 @@ var readVoiceProofTrendReportFile = async (path, options = {}) => {
12405
12405
  });
12406
12406
  }
12407
12407
  };
12408
+ var maxNumber = (values) => {
12409
+ const finite = values.filter((value) => typeof value === "number" && Number.isFinite(value));
12410
+ return finite.length > 0 ? Math.max(...finite) : undefined;
12411
+ };
12412
+ var readProofTrendMaxLiveP95 = (report) => report.summary.maxLiveP95Ms ?? maxNumber(report.cycles.map((cycle) => cycle.liveLatency?.p95Ms));
12413
+ var readProofTrendMaxProviderP95 = (report) => report.summary.maxProviderP95Ms;
12414
+ var readProofTrendMaxTurnP95 = (report) => report.summary.maxTurnP95Ms ?? maxNumber(report.cycles.map((cycle) => cycle.turnLatency?.p95Ms));
12415
+ var evaluateVoiceProofTrendEvidence = (report, input = {}) => {
12416
+ const issues = [];
12417
+ const requiredStatus = input.requireStatus ?? "pass";
12418
+ const minCycles = input.minCycles ?? 1;
12419
+ const requireAllCyclesOk = input.requireAllCyclesOk ?? true;
12420
+ const cycles = report.summary.cycles ?? report.cycles.length;
12421
+ const failedCycles = report.cycles.filter((cycle) => cycle.ok !== true).length;
12422
+ const maxLiveP95Ms = readProofTrendMaxLiveP95(report);
12423
+ const maxProviderP95Ms = readProofTrendMaxProviderP95(report);
12424
+ const maxTurnP95Ms = readProofTrendMaxTurnP95(report);
12425
+ if (report.status !== requiredStatus) {
12426
+ issues.push(`Expected proof trends status ${requiredStatus}, found ${report.status}.`);
12427
+ }
12428
+ if (report.ok !== true) {
12429
+ issues.push("Expected proof trends ok to be true.");
12430
+ }
12431
+ if (cycles < minCycles) {
12432
+ issues.push(`Expected at least ${String(minCycles)} proof trend cycle(s), found ${String(cycles)}.`);
12433
+ }
12434
+ if (requireAllCyclesOk && failedCycles > 0) {
12435
+ issues.push(`Expected all proof trend cycles to pass, found ${String(failedCycles)} failing cycle(s).`);
12436
+ }
12437
+ if (input.maxAgeMs !== undefined && (report.ageMs === undefined || report.ageMs > input.maxAgeMs)) {
12438
+ issues.push(report.ageMs === undefined ? "Missing proof trends artifact age." : `Expected proof trends age at most ${String(input.maxAgeMs)}ms, found ${String(report.ageMs)}ms.`);
12439
+ }
12440
+ if (input.maxLiveP95Ms !== undefined && (maxLiveP95Ms === undefined || maxLiveP95Ms > input.maxLiveP95Ms)) {
12441
+ issues.push(maxLiveP95Ms === undefined ? "Missing proof trends live latency p95." : `Expected proof trends live latency p95 at most ${String(input.maxLiveP95Ms)}ms, found ${String(maxLiveP95Ms)}ms.`);
12442
+ }
12443
+ if (input.maxProviderP95Ms !== undefined && (maxProviderP95Ms === undefined || maxProviderP95Ms > input.maxProviderP95Ms)) {
12444
+ issues.push(maxProviderP95Ms === undefined ? "Missing proof trends provider p95." : `Expected proof trends provider p95 at most ${String(input.maxProviderP95Ms)}ms, found ${String(maxProviderP95Ms)}ms.`);
12445
+ }
12446
+ if (input.maxTurnP95Ms !== undefined && (maxTurnP95Ms === undefined || maxTurnP95Ms > input.maxTurnP95Ms)) {
12447
+ issues.push(maxTurnP95Ms === undefined ? "Missing proof trends turn latency p95." : `Expected proof trends turn latency p95 at most ${String(input.maxTurnP95Ms)}ms, found ${String(maxTurnP95Ms)}ms.`);
12448
+ }
12449
+ if (input.minLiveLatencySamples !== undefined) {
12450
+ const lowSamples = report.cycles.filter((cycle) => (cycle.liveLatency?.samples ?? 0) < input.minLiveLatencySamples).length;
12451
+ if (lowSamples > 0) {
12452
+ issues.push(`Expected every proof trend cycle to have at least ${String(input.minLiveLatencySamples)} live latency sample(s), found ${String(lowSamples)} low-sample cycle(s).`);
12453
+ }
12454
+ }
12455
+ if (input.minProviderSloEventsWithLatency !== undefined) {
12456
+ const lowSamples = report.cycles.filter((cycle) => (cycle.providerSlo?.eventsWithLatency ?? 0) < input.minProviderSloEventsWithLatency).length;
12457
+ if (lowSamples > 0) {
12458
+ issues.push(`Expected every proof trend cycle to have at least ${String(input.minProviderSloEventsWithLatency)} provider latency event(s), found ${String(lowSamples)} low-sample cycle(s).`);
12459
+ }
12460
+ }
12461
+ if (input.minTurnLatencySamples !== undefined) {
12462
+ const lowSamples = report.cycles.filter((cycle) => (cycle.turnLatency?.samples ?? 0) < input.minTurnLatencySamples).length;
12463
+ if (lowSamples > 0) {
12464
+ issues.push(`Expected every proof trend cycle to have at least ${String(input.minTurnLatencySamples)} turn latency sample(s), found ${String(lowSamples)} low-sample cycle(s).`);
12465
+ }
12466
+ }
12467
+ return {
12468
+ ageMs: report.ageMs,
12469
+ cycles,
12470
+ failedCycles,
12471
+ issues,
12472
+ maxLiveP95Ms,
12473
+ maxProviderP95Ms,
12474
+ maxTurnP95Ms,
12475
+ ok: issues.length === 0,
12476
+ status: report.status
12477
+ };
12478
+ };
12479
+ var assertVoiceProofTrendEvidence = (report, input = {}) => {
12480
+ const assertion = evaluateVoiceProofTrendEvidence(report, input);
12481
+ if (!assertion.ok) {
12482
+ throw new Error(`Voice proof trends assertion failed: ${assertion.issues.join(" ")}`);
12483
+ }
12484
+ return assertion;
12485
+ };
12408
12486
  var createVoiceProofTrendRoutes = (options) => {
12409
12487
  const path = options.path ?? "/api/voice/proof-trends";
12410
12488
  const routes = new Elysia14({
@@ -30297,6 +30375,7 @@ export {
30297
30375
  evaluateVoiceQuality,
30298
30376
  evaluateVoiceProviderStackGaps,
30299
30377
  evaluateVoiceProviderSloEvidence,
30378
+ evaluateVoiceProofTrendEvidence,
30300
30379
  evaluateVoiceProductionReadinessEvidence,
30301
30380
  evaluateVoicePlatformCoverage,
30302
30381
  evaluateVoiceOperationsRecordGuardrails,
@@ -30616,6 +30695,7 @@ export {
30616
30695
  assignVoiceOpsTask,
30617
30696
  assertVoiceProviderSloEvidence,
30618
30697
  assertVoiceProviderRoutingContract,
30698
+ assertVoiceProofTrendEvidence,
30619
30699
  assertVoiceProductionReadinessEvidence,
30620
30700
  assertVoicePlatformCoverage,
30621
30701
  assertVoiceOperationsRecordGuardrails,
@@ -59,6 +59,29 @@ export type VoiceProofTrendReport = {
59
59
  status: VoiceProofTrendStatus;
60
60
  summary: VoiceProofTrendSummary;
61
61
  };
62
+ export type VoiceProofTrendAssertionInput = {
63
+ maxAgeMs?: number;
64
+ maxLiveP95Ms?: number;
65
+ maxProviderP95Ms?: number;
66
+ maxTurnP95Ms?: number;
67
+ minCycles?: number;
68
+ minLiveLatencySamples?: number;
69
+ minProviderSloEventsWithLatency?: number;
70
+ minTurnLatencySamples?: number;
71
+ requireAllCyclesOk?: boolean;
72
+ requireStatus?: VoiceProofTrendStatus;
73
+ };
74
+ export type VoiceProofTrendAssertionReport = {
75
+ ageMs?: number;
76
+ cycles: number;
77
+ failedCycles: number;
78
+ issues: string[];
79
+ maxLiveP95Ms?: number;
80
+ maxProviderP95Ms?: number;
81
+ maxTurnP95Ms?: number;
82
+ ok: boolean;
83
+ status: VoiceProofTrendStatus;
84
+ };
62
85
  export type VoiceProofTrendRoutesOptions = {
63
86
  headers?: HeadersInit;
64
87
  jsonPath?: string;
@@ -77,6 +100,8 @@ export declare const normalizeVoiceProofTrendReport: (value: VoiceProofTrendRepo
77
100
  export declare const readVoiceProofTrendReportFile: (path: string, options?: {
78
101
  maxAgeMs?: number;
79
102
  }) => Promise<VoiceProofTrendReport>;
103
+ export declare const evaluateVoiceProofTrendEvidence: (report: VoiceProofTrendReport, input?: VoiceProofTrendAssertionInput) => VoiceProofTrendAssertionReport;
104
+ export declare const assertVoiceProofTrendEvidence: (report: VoiceProofTrendReport, input?: VoiceProofTrendAssertionInput) => VoiceProofTrendAssertionReport;
80
105
  export declare const createVoiceProofTrendRoutes: (options: VoiceProofTrendRoutesOptions) => Elysia<"", {
81
106
  decorator: {};
82
107
  store: {};
@@ -1564,6 +1564,84 @@ var readVoiceProofTrendReportFile = async (path, options = {}) => {
1564
1564
  });
1565
1565
  }
1566
1566
  };
1567
+ var maxNumber = (values) => {
1568
+ const finite = values.filter((value) => typeof value === "number" && Number.isFinite(value));
1569
+ return finite.length > 0 ? Math.max(...finite) : undefined;
1570
+ };
1571
+ var readProofTrendMaxLiveP95 = (report) => report.summary.maxLiveP95Ms ?? maxNumber(report.cycles.map((cycle) => cycle.liveLatency?.p95Ms));
1572
+ var readProofTrendMaxProviderP95 = (report) => report.summary.maxProviderP95Ms;
1573
+ var readProofTrendMaxTurnP95 = (report) => report.summary.maxTurnP95Ms ?? maxNumber(report.cycles.map((cycle) => cycle.turnLatency?.p95Ms));
1574
+ var evaluateVoiceProofTrendEvidence = (report, input = {}) => {
1575
+ const issues = [];
1576
+ const requiredStatus = input.requireStatus ?? "pass";
1577
+ const minCycles = input.minCycles ?? 1;
1578
+ const requireAllCyclesOk = input.requireAllCyclesOk ?? true;
1579
+ const cycles = report.summary.cycles ?? report.cycles.length;
1580
+ const failedCycles = report.cycles.filter((cycle) => cycle.ok !== true).length;
1581
+ const maxLiveP95Ms = readProofTrendMaxLiveP95(report);
1582
+ const maxProviderP95Ms = readProofTrendMaxProviderP95(report);
1583
+ const maxTurnP95Ms = readProofTrendMaxTurnP95(report);
1584
+ if (report.status !== requiredStatus) {
1585
+ issues.push(`Expected proof trends status ${requiredStatus}, found ${report.status}.`);
1586
+ }
1587
+ if (report.ok !== true) {
1588
+ issues.push("Expected proof trends ok to be true.");
1589
+ }
1590
+ if (cycles < minCycles) {
1591
+ issues.push(`Expected at least ${String(minCycles)} proof trend cycle(s), found ${String(cycles)}.`);
1592
+ }
1593
+ if (requireAllCyclesOk && failedCycles > 0) {
1594
+ issues.push(`Expected all proof trend cycles to pass, found ${String(failedCycles)} failing cycle(s).`);
1595
+ }
1596
+ if (input.maxAgeMs !== undefined && (report.ageMs === undefined || report.ageMs > input.maxAgeMs)) {
1597
+ issues.push(report.ageMs === undefined ? "Missing proof trends artifact age." : `Expected proof trends age at most ${String(input.maxAgeMs)}ms, found ${String(report.ageMs)}ms.`);
1598
+ }
1599
+ if (input.maxLiveP95Ms !== undefined && (maxLiveP95Ms === undefined || maxLiveP95Ms > input.maxLiveP95Ms)) {
1600
+ issues.push(maxLiveP95Ms === undefined ? "Missing proof trends live latency p95." : `Expected proof trends live latency p95 at most ${String(input.maxLiveP95Ms)}ms, found ${String(maxLiveP95Ms)}ms.`);
1601
+ }
1602
+ if (input.maxProviderP95Ms !== undefined && (maxProviderP95Ms === undefined || maxProviderP95Ms > input.maxProviderP95Ms)) {
1603
+ issues.push(maxProviderP95Ms === undefined ? "Missing proof trends provider p95." : `Expected proof trends provider p95 at most ${String(input.maxProviderP95Ms)}ms, found ${String(maxProviderP95Ms)}ms.`);
1604
+ }
1605
+ if (input.maxTurnP95Ms !== undefined && (maxTurnP95Ms === undefined || maxTurnP95Ms > input.maxTurnP95Ms)) {
1606
+ issues.push(maxTurnP95Ms === undefined ? "Missing proof trends turn latency p95." : `Expected proof trends turn latency p95 at most ${String(input.maxTurnP95Ms)}ms, found ${String(maxTurnP95Ms)}ms.`);
1607
+ }
1608
+ if (input.minLiveLatencySamples !== undefined) {
1609
+ const lowSamples = report.cycles.filter((cycle) => (cycle.liveLatency?.samples ?? 0) < input.minLiveLatencySamples).length;
1610
+ if (lowSamples > 0) {
1611
+ issues.push(`Expected every proof trend cycle to have at least ${String(input.minLiveLatencySamples)} live latency sample(s), found ${String(lowSamples)} low-sample cycle(s).`);
1612
+ }
1613
+ }
1614
+ if (input.minProviderSloEventsWithLatency !== undefined) {
1615
+ const lowSamples = report.cycles.filter((cycle) => (cycle.providerSlo?.eventsWithLatency ?? 0) < input.minProviderSloEventsWithLatency).length;
1616
+ if (lowSamples > 0) {
1617
+ issues.push(`Expected every proof trend cycle to have at least ${String(input.minProviderSloEventsWithLatency)} provider latency event(s), found ${String(lowSamples)} low-sample cycle(s).`);
1618
+ }
1619
+ }
1620
+ if (input.minTurnLatencySamples !== undefined) {
1621
+ const lowSamples = report.cycles.filter((cycle) => (cycle.turnLatency?.samples ?? 0) < input.minTurnLatencySamples).length;
1622
+ if (lowSamples > 0) {
1623
+ issues.push(`Expected every proof trend cycle to have at least ${String(input.minTurnLatencySamples)} turn latency sample(s), found ${String(lowSamples)} low-sample cycle(s).`);
1624
+ }
1625
+ }
1626
+ return {
1627
+ ageMs: report.ageMs,
1628
+ cycles,
1629
+ failedCycles,
1630
+ issues,
1631
+ maxLiveP95Ms,
1632
+ maxProviderP95Ms,
1633
+ maxTurnP95Ms,
1634
+ ok: issues.length === 0,
1635
+ status: report.status
1636
+ };
1637
+ };
1638
+ var assertVoiceProofTrendEvidence = (report, input = {}) => {
1639
+ const assertion = evaluateVoiceProofTrendEvidence(report, input);
1640
+ if (!assertion.ok) {
1641
+ throw new Error(`Voice proof trends assertion failed: ${assertion.issues.join(" ")}`);
1642
+ }
1643
+ return assertion;
1644
+ };
1567
1645
  var createVoiceProofTrendRoutes = (options) => {
1568
1646
  const path = options.path ?? "/api/voice/proof-trends";
1569
1647
  const routes = new Elysia({
package/dist/vue/index.js CHANGED
@@ -1485,6 +1485,84 @@ var readVoiceProofTrendReportFile = async (path, options = {}) => {
1485
1485
  });
1486
1486
  }
1487
1487
  };
1488
+ var maxNumber = (values) => {
1489
+ const finite = values.filter((value) => typeof value === "number" && Number.isFinite(value));
1490
+ return finite.length > 0 ? Math.max(...finite) : undefined;
1491
+ };
1492
+ var readProofTrendMaxLiveP95 = (report) => report.summary.maxLiveP95Ms ?? maxNumber(report.cycles.map((cycle) => cycle.liveLatency?.p95Ms));
1493
+ var readProofTrendMaxProviderP95 = (report) => report.summary.maxProviderP95Ms;
1494
+ var readProofTrendMaxTurnP95 = (report) => report.summary.maxTurnP95Ms ?? maxNumber(report.cycles.map((cycle) => cycle.turnLatency?.p95Ms));
1495
+ var evaluateVoiceProofTrendEvidence = (report, input = {}) => {
1496
+ const issues = [];
1497
+ const requiredStatus = input.requireStatus ?? "pass";
1498
+ const minCycles = input.minCycles ?? 1;
1499
+ const requireAllCyclesOk = input.requireAllCyclesOk ?? true;
1500
+ const cycles = report.summary.cycles ?? report.cycles.length;
1501
+ const failedCycles = report.cycles.filter((cycle) => cycle.ok !== true).length;
1502
+ const maxLiveP95Ms = readProofTrendMaxLiveP95(report);
1503
+ const maxProviderP95Ms = readProofTrendMaxProviderP95(report);
1504
+ const maxTurnP95Ms = readProofTrendMaxTurnP95(report);
1505
+ if (report.status !== requiredStatus) {
1506
+ issues.push(`Expected proof trends status ${requiredStatus}, found ${report.status}.`);
1507
+ }
1508
+ if (report.ok !== true) {
1509
+ issues.push("Expected proof trends ok to be true.");
1510
+ }
1511
+ if (cycles < minCycles) {
1512
+ issues.push(`Expected at least ${String(minCycles)} proof trend cycle(s), found ${String(cycles)}.`);
1513
+ }
1514
+ if (requireAllCyclesOk && failedCycles > 0) {
1515
+ issues.push(`Expected all proof trend cycles to pass, found ${String(failedCycles)} failing cycle(s).`);
1516
+ }
1517
+ if (input.maxAgeMs !== undefined && (report.ageMs === undefined || report.ageMs > input.maxAgeMs)) {
1518
+ issues.push(report.ageMs === undefined ? "Missing proof trends artifact age." : `Expected proof trends age at most ${String(input.maxAgeMs)}ms, found ${String(report.ageMs)}ms.`);
1519
+ }
1520
+ if (input.maxLiveP95Ms !== undefined && (maxLiveP95Ms === undefined || maxLiveP95Ms > input.maxLiveP95Ms)) {
1521
+ issues.push(maxLiveP95Ms === undefined ? "Missing proof trends live latency p95." : `Expected proof trends live latency p95 at most ${String(input.maxLiveP95Ms)}ms, found ${String(maxLiveP95Ms)}ms.`);
1522
+ }
1523
+ if (input.maxProviderP95Ms !== undefined && (maxProviderP95Ms === undefined || maxProviderP95Ms > input.maxProviderP95Ms)) {
1524
+ issues.push(maxProviderP95Ms === undefined ? "Missing proof trends provider p95." : `Expected proof trends provider p95 at most ${String(input.maxProviderP95Ms)}ms, found ${String(maxProviderP95Ms)}ms.`);
1525
+ }
1526
+ if (input.maxTurnP95Ms !== undefined && (maxTurnP95Ms === undefined || maxTurnP95Ms > input.maxTurnP95Ms)) {
1527
+ issues.push(maxTurnP95Ms === undefined ? "Missing proof trends turn latency p95." : `Expected proof trends turn latency p95 at most ${String(input.maxTurnP95Ms)}ms, found ${String(maxTurnP95Ms)}ms.`);
1528
+ }
1529
+ if (input.minLiveLatencySamples !== undefined) {
1530
+ const lowSamples = report.cycles.filter((cycle) => (cycle.liveLatency?.samples ?? 0) < input.minLiveLatencySamples).length;
1531
+ if (lowSamples > 0) {
1532
+ issues.push(`Expected every proof trend cycle to have at least ${String(input.minLiveLatencySamples)} live latency sample(s), found ${String(lowSamples)} low-sample cycle(s).`);
1533
+ }
1534
+ }
1535
+ if (input.minProviderSloEventsWithLatency !== undefined) {
1536
+ const lowSamples = report.cycles.filter((cycle) => (cycle.providerSlo?.eventsWithLatency ?? 0) < input.minProviderSloEventsWithLatency).length;
1537
+ if (lowSamples > 0) {
1538
+ issues.push(`Expected every proof trend cycle to have at least ${String(input.minProviderSloEventsWithLatency)} provider latency event(s), found ${String(lowSamples)} low-sample cycle(s).`);
1539
+ }
1540
+ }
1541
+ if (input.minTurnLatencySamples !== undefined) {
1542
+ const lowSamples = report.cycles.filter((cycle) => (cycle.turnLatency?.samples ?? 0) < input.minTurnLatencySamples).length;
1543
+ if (lowSamples > 0) {
1544
+ issues.push(`Expected every proof trend cycle to have at least ${String(input.minTurnLatencySamples)} turn latency sample(s), found ${String(lowSamples)} low-sample cycle(s).`);
1545
+ }
1546
+ }
1547
+ return {
1548
+ ageMs: report.ageMs,
1549
+ cycles,
1550
+ failedCycles,
1551
+ issues,
1552
+ maxLiveP95Ms,
1553
+ maxProviderP95Ms,
1554
+ maxTurnP95Ms,
1555
+ ok: issues.length === 0,
1556
+ status: report.status
1557
+ };
1558
+ };
1559
+ var assertVoiceProofTrendEvidence = (report, input = {}) => {
1560
+ const assertion = evaluateVoiceProofTrendEvidence(report, input);
1561
+ if (!assertion.ok) {
1562
+ throw new Error(`Voice proof trends assertion failed: ${assertion.issues.join(" ")}`);
1563
+ }
1564
+ return assertion;
1565
+ };
1488
1566
  var createVoiceProofTrendRoutes = (options) => {
1489
1567
  const path = options.path ?? "/api/voice/proof-trends";
1490
1568
  const routes = new Elysia({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.252",
3
+ "version": "0.0.22-beta.253",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",