@absolutejs/voice 0.0.22-beta.336 → 0.0.22-beta.338

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.
@@ -3935,7 +3935,35 @@ var bestProviderByRole = (providers) => {
3935
3935
  }
3936
3936
  return [...best.values()].sort((left, right) => String(left.role ?? left.id).localeCompare(String(right.role ?? right.id)));
3937
3937
  };
3938
- var formatProviderMix = (providers) => providers.length === 0 ? "n/a" : providers.map((provider) => provider.role ? `${provider.role.toUpperCase()} ${provider.label ?? provider.id}` : provider.label ?? provider.id).join(", ");
3938
+ var formatProviderMix = (providers) => providers.length === 0 ? "n/a" : providers.map((provider) => provider.role && !(provider.label ?? provider.id).toLowerCase().startsWith(provider.role.toLowerCase()) ? `${provider.role.toUpperCase()} ${provider.label ?? provider.id}` : provider.label ?? provider.id).join(", ");
3939
+ var buildProfileRecommendations = (report, budgets) => (report.summary.profiles ?? []).map((profile) => {
3940
+ const providers = summarizeProofTrendProviders({
3941
+ ...report,
3942
+ cycles: [],
3943
+ summary: {
3944
+ cycles: report.summary.cycles,
3945
+ maxLiveP95Ms: profile.maxLiveP95Ms,
3946
+ maxProviderP95Ms: profile.maxProviderP95Ms,
3947
+ maxTurnP95Ms: profile.maxTurnP95Ms,
3948
+ providers: profile.providers,
3949
+ runtimeChannel: profile.runtimeChannel
3950
+ }
3951
+ }, budgets.maxProviderP95Ms);
3952
+ const bestProviders = bestProviderByRole(providers).filter((provider) => provider.status === "pass");
3953
+ const hasRequiredProviderRoles = bestProviders.some((provider) => provider.role === "llm") && bestProviders.some((provider) => provider.role === "stt") && bestProviders.some((provider) => provider.role === "tts");
3954
+ const runtimePass = (profile.runtimeChannel?.status === undefined || profile.runtimeChannel.status === "pass") && (profile.runtimeChannel?.maxFirstAudioLatencyMs === undefined || profile.runtimeChannel.maxFirstAudioLatencyMs <= budgets.maxRuntimeFirstAudioLatencyMs) && (profile.runtimeChannel?.maxInterruptionP95Ms === undefined || profile.runtimeChannel.maxInterruptionP95Ms <= budgets.maxRuntimeInterruptionP95Ms) && (profile.runtimeChannel?.maxJitterMs === undefined || profile.runtimeChannel.maxJitterMs <= budgets.maxRuntimeJitterMs) && (profile.runtimeChannel?.maxTimestampDriftMs === undefined || profile.runtimeChannel.maxTimestampDriftMs <= budgets.maxRuntimeTimestampDriftMs) && (profile.runtimeChannel?.maxBackpressureEvents === undefined || profile.runtimeChannel.maxBackpressureEvents <= budgets.maxRuntimeBackpressureEvents);
3955
+ const latencyPass = (profile.maxProviderP95Ms === undefined || profile.maxProviderP95Ms <= budgets.maxProviderP95Ms) && (profile.maxLiveP95Ms === undefined || profile.maxLiveP95Ms <= budgets.maxLiveP95Ms) && (profile.maxTurnP95Ms === undefined || profile.maxTurnP95Ms <= budgets.maxTurnP95Ms);
3956
+ const status = profile.status === "fail" || !runtimePass ? "fail" : !latencyPass || !hasRequiredProviderRoles ? "warn" : "pass";
3957
+ return {
3958
+ bestProviders,
3959
+ id: profile.id,
3960
+ label: profile.label,
3961
+ nextMove: status === "pass" ? `Use this proven provider mix for ${profile.label ?? profile.id}: ${formatProviderMix(bestProviders)}.` : providers.length === 0 ? `Collect provider-specific sustained samples for ${profile.label ?? profile.id}.` : `Tune latency/runtime budgets for ${profile.label ?? profile.id} before promoting this profile.`,
3962
+ providerComparisonCount: providers.length,
3963
+ recommendation: status === "pass" ? `Profile ready: ${profile.label ?? profile.id}` : `Profile needs proof: ${profile.label ?? profile.id}`,
3964
+ status
3965
+ };
3966
+ });
3939
3967
  var evaluateVoiceProofTrendEvidence = (report, input = {}) => {
3940
3968
  const issues = [];
3941
3969
  const requiredStatus = input.requireStatus ?? "pass";
@@ -4054,8 +4082,10 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
4054
4082
  const bestProvider = providers.find((provider) => provider.status === "pass") ?? providers[0];
4055
4083
  const bestProviders = bestProviderByRole(providers).filter((provider) => provider.status === "pass");
4056
4084
  const currentProvider = options.currentProviderId ? providers.find((provider) => provider.id === options.currentProviderId) : undefined;
4085
+ const hasSingleProviderRole = new Set(bestProviders.map((provider) => provider.role ?? provider.id)).size <= 1;
4057
4086
  const bestComparableProvider = currentProvider?.role ? bestProviders.find((provider) => provider.role === currentProvider.role) : bestProvider;
4058
4087
  const providerSwitchRecommended = shouldSwitchProvider(currentProvider, bestComparableProvider, options);
4088
+ const profileRecommendations = buildProfileRecommendations(report, budgets);
4059
4089
  const recommendations = [];
4060
4090
  const issues = [];
4061
4091
  if (report.ok !== true) {
@@ -4063,9 +4093,9 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
4063
4093
  }
4064
4094
  recommendations.push({
4065
4095
  evidence: {
4066
- bestProviderId: bestComparableProvider?.id ?? bestProvider?.id,
4096
+ bestProviderId: currentProvider || hasSingleProviderRole ? bestComparableProvider?.id ?? bestProvider?.id : undefined,
4067
4097
  bestProviderMix: formatProviderMix(bestProviders),
4068
- bestProviderP95Ms: bestComparableProvider?.p95Ms ?? bestProvider?.p95Ms,
4098
+ bestProviderP95Ms: currentProvider || hasSingleProviderRole ? bestComparableProvider?.p95Ms ?? bestProvider?.p95Ms : undefined,
4069
4099
  budgetMs: budgets.maxProviderP95Ms,
4070
4100
  currentProviderId: currentProvider?.id ?? options.currentProviderId,
4071
4101
  currentProviderP95Ms: currentProvider?.p95Ms,
@@ -4075,7 +4105,7 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
4075
4105
  nextMove: providers.length > 0 ? providerSwitchRecommended ? `Route latency-sensitive ${currentProvider?.role ?? "provider"} traffic to ${bestComparableProvider?.label ?? bestComparableProvider?.id} for this call profile and keep the current path as fallback.` : bestProviders.length > 0 ? `Use the fastest proven provider mix for this call profile: ${formatProviderMix(bestProviders)}.` : "Collect provider-specific sustained samples before making provider-specific routing decisions." : withinBudget(maxProviderP95Ms, budgets.maxProviderP95Ms) ? "Keep the current provider route for latency-sensitive turns and keep collecting sustained proof." : "Route latency-sensitive turns to a faster provider profile or tighten fallback/circuit-breaker budgets before promotion.",
4076
4106
  providerId: providerSwitchRecommended ? bestComparableProvider?.id : bestProviders.length === 1 ? bestProviders[0]?.id : undefined,
4077
4107
  recommendation: providers.length > 0 ? providerSwitchRecommended ? `Switch latency-sensitive ${currentProvider?.role ?? "provider"} routing to ${bestComparableProvider?.label ?? bestComparableProvider?.id}` : bestProviders.length > 0 ? "Prefer the fastest proven provider mix for this call profile" : "Collect provider-specific latency samples" : withinBudget(maxProviderP95Ms, budgets.maxProviderP95Ms) ? "Keep current provider path" : "Change provider routing for latency-sensitive traffic",
4078
- role: bestComparableProvider?.role,
4108
+ role: currentProvider || hasSingleProviderRole ? bestComparableProvider?.role : undefined,
4079
4109
  status: providers.length > 0 ? providerSwitchRecommended ? "warn" : bestProviders.length > 0 ? "pass" : bestProvider?.status ?? "fail" : withinBudget(maxProviderP95Ms, budgets.maxProviderP95Ms) ? "pass" : maxProviderP95Ms === undefined ? "fail" : "warn",
4080
4110
  surface: "provider-path"
4081
4111
  });
@@ -4118,16 +4148,25 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
4118
4148
  surface: "turn-latency"
4119
4149
  });
4120
4150
  const status = issues.length > 0 ? "fail" : worstRecommendationStatus(recommendations);
4151
+ const profileStatus = worstRecommendationStatus(profileRecommendations.map((profile) => ({
4152
+ evidence: {},
4153
+ nextMove: profile.nextMove,
4154
+ recommendation: profile.recommendation,
4155
+ status: profile.status,
4156
+ surface: "provider-path"
4157
+ })));
4158
+ const combinedStatus = recommendationStatusRank[profileStatus] > recommendationStatusRank[status] ? profileStatus : status;
4121
4159
  return {
4122
4160
  bestProvider,
4123
4161
  bestProviders,
4124
4162
  generatedAt: new Date().toISOString(),
4125
4163
  issues,
4126
- ok: status !== "fail",
4164
+ ok: combinedStatus !== "fail",
4165
+ profiles: profileRecommendations,
4127
4166
  providers,
4128
4167
  recommendations,
4129
4168
  source: report.source || report.outputDir || report.runId || "proof-trends",
4130
- status,
4169
+ status: combinedStatus,
4131
4170
  summary: {
4132
4171
  keepCurrentProviderPath: !providerSwitchRecommended && recommendations.find((item) => item.surface === "provider-path")?.status !== "fail",
4133
4172
  keepCurrentRuntimeChannel: recommendations.find((item) => item.surface === "runtime-channel")?.status === "pass",
@@ -4158,6 +4197,12 @@ var renderVoiceProofTrendRecommendationMarkdown = (report, title = "Voice Provid
4158
4197
  "| ---: | --- | --- | --- | ---: | ---: | --- |",
4159
4198
  ...report.providers.length ? report.providers.map((provider) => `| ${String(provider.rank)} | ${escapeMarkdown(provider.label ?? provider.id)} | ${escapeMarkdown(provider.role ?? "n/a")} | ${provider.status} | ${provider.p95Ms === undefined ? "n/a" : String(provider.p95Ms)} | ${provider.samples === undefined ? "n/a" : String(provider.samples)} | ${escapeMarkdown(provider.nextMove)} |`) : ["| n/a | n/a | n/a | n/a | n/a | n/a | No provider-specific samples were present. |"],
4160
4199
  "",
4200
+ "## Benchmark Profiles",
4201
+ "",
4202
+ "| Profile | Status | Provider mix | Next move |",
4203
+ "| --- | --- | --- | --- |",
4204
+ ...report.profiles.length ? report.profiles.map((profile) => `| ${escapeMarkdown(profile.label ?? profile.id)} | ${profile.status} | ${escapeMarkdown(formatProviderMix(profile.bestProviders))} | ${escapeMarkdown(profile.nextMove)} |`) : ["| n/a | n/a | n/a | No benchmark profiles were present. |"],
4205
+ "",
4161
4206
  "## Issues",
4162
4207
  "",
4163
4208
  ...report.issues.length ? report.issues.map((issue) => `- ${issue}`) : ["- None"]
@@ -4167,7 +4212,8 @@ var renderVoiceProofTrendRecommendationHTML = (report, title = "Voice Provider R
4167
4212
  const cards = report.recommendations.map((recommendation) => `<article class="${escapeHtml3(recommendation.status)}"><p class="eyebrow">${escapeHtml3(recommendation.surface)} \xB7 ${escapeHtml3(recommendation.status)}</p><h2>${escapeHtml3(recommendation.recommendation)}</h2><p>${escapeHtml3(recommendation.nextMove)}</p><pre>${escapeHtml3(JSON.stringify(recommendation.evidence, null, 2))}</pre></article>`).join("");
4168
4213
  const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${escapeHtml3(issue)}</li>`).join("");
4169
4214
  const providerRows = report.providers.length === 0 ? "<li>No provider-specific samples were present.</li>" : report.providers.map((provider) => `<li><strong>#${String(provider.rank)} ${escapeHtml3(provider.label ?? provider.id)}</strong><span>${escapeHtml3(provider.role ?? "provider")} \xB7 ${escapeHtml3(provider.status)} \xB7 p95 ${escapeHtml3(provider.p95Ms ?? "n/a")}ms \xB7 ${escapeHtml3(provider.samples ?? "n/a")} sample(s)</span><small>${escapeHtml3(provider.nextMove)}</small></li>`).join("");
4170
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml3(title)}</title><style>body{background:#101418;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.hero,article{background:#17201d;border:1px solid #2e3d36;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.12))}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.1em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.7rem);letter-spacing:-.06em;line-height:.92;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{border:1px solid #42534a;border-radius:999px;padding:8px 12px}.pass{border-color:rgba(34,197,94,.55)}.warn{border-color:rgba(245,158,11,.7)}.fail{border-color:rgba(239,68,68,.75)}pre{background:#0b1110;border-radius:14px;overflow:auto;padding:12px}a{color:#5eead4}li{margin:.45rem 0}li span,li small{display:block;color:#c9d3ca}</style></head><body><main><section class="hero"><p class="eyebrow">Sustained proof recommendations</p><h1>${escapeHtml3(title)}</h1><p>Generated ${escapeHtml3(report.generatedAt)} from ${escapeHtml3(report.source)}.</p><div class="summary"><span class="pill">Status ${escapeHtml3(report.status)}</span><span class="pill">Provider ${report.summary.keepCurrentProviderPath ? "keep" : "change"}</span><span class="pill">Best mix ${escapeHtml3(formatProviderMix(report.bestProviders))}</span><span class="pill">Runtime ${report.summary.keepCurrentRuntimeChannel ? "keep" : "tune"}</span><span class="pill">${String(report.summary.recommendedActions)} action(s)</span></div></section>${cards}<section class="hero"><h2>Provider Comparison</h2><ul>${providerRows}</ul></section><section class="hero"><h2>Issues</h2><ul>${issues}</ul></section></main></body></html>`;
4215
+ const profileRows = report.profiles.length === 0 ? "<li>No benchmark profiles were present.</li>" : report.profiles.map((profile) => `<li><strong>${escapeHtml3(profile.label ?? profile.id)}</strong><span>${escapeHtml3(profile.status)} \xB7 ${escapeHtml3(formatProviderMix(profile.bestProviders))}</span><small>${escapeHtml3(profile.nextMove)}</small></li>`).join("");
4216
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml3(title)}</title><style>body{background:#101418;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.hero,article{background:#17201d;border:1px solid #2e3d36;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.12))}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.1em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.7rem);letter-spacing:-.06em;line-height:.92;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{border:1px solid #42534a;border-radius:999px;padding:8px 12px}.pass{border-color:rgba(34,197,94,.55)}.warn{border-color:rgba(245,158,11,.7)}.fail{border-color:rgba(239,68,68,.75)}pre{background:#0b1110;border-radius:14px;overflow:auto;padding:12px}a{color:#5eead4}li{margin:.45rem 0}li span,li small{display:block;color:#c9d3ca}</style></head><body><main><section class="hero"><p class="eyebrow">Sustained proof recommendations</p><h1>${escapeHtml3(title)}</h1><p>Generated ${escapeHtml3(report.generatedAt)} from ${escapeHtml3(report.source)}.</p><div class="summary"><span class="pill">Status ${escapeHtml3(report.status)}</span><span class="pill">Provider ${report.summary.keepCurrentProviderPath ? "keep" : "change"}</span><span class="pill">Best mix ${escapeHtml3(formatProviderMix(report.bestProviders))}</span><span class="pill">Profiles ${String(report.profiles.length)}</span><span class="pill">Runtime ${report.summary.keepCurrentRuntimeChannel ? "keep" : "tune"}</span><span class="pill">${String(report.summary.recommendedActions)} action(s)</span></div></section>${cards}<section class="hero"><h2>Benchmark Profiles</h2><ul>${profileRows}</ul></section><section class="hero"><h2>Provider Comparison</h2><ul>${providerRows}</ul></section><section class="hero"><h2>Issues</h2><ul>${issues}</ul></section></main></body></html>`;
4171
4217
  };
4172
4218
  var createVoiceProofTrendRecommendationRoutes = (options) => {
4173
4219
  const path = options.path ?? "/api/voice/proof-trend-recommendations";
package/dist/index.d.ts CHANGED
@@ -31,7 +31,7 @@ export type { VoicePlatformCoverageAssertionInput, VoicePlatformCoverageAssertio
31
31
  export { assertVoiceProofTrendEvidence, buildEmptyVoiceProofTrendReport, buildVoiceProofTrendRecommendationReport, buildVoiceProofTrendReport, createVoiceProofTrendRecommendationRoutes, createVoiceProofTrendRoutes, DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS, evaluateVoiceProofTrendEvidence, formatVoiceProofTrendAge, normalizeVoiceProofTrendReport, readVoiceProofTrendReportFile, renderVoiceProofTrendRecommendationHTML, renderVoiceProofTrendRecommendationMarkdown } from './proofTrends';
32
32
  export { buildVoiceProviderDecisionTraceReport, createVoiceProviderDecisionTraceEvent, createVoiceProviderDecisionTraceRoutes, listVoiceProviderDecisionTraces, renderVoiceProviderDecisionTraceHTML, renderVoiceProviderDecisionTraceMarkdown } from './providerDecisionTraces';
33
33
  export type { VoiceProviderDecisionStatus, VoiceProviderDecisionSurfaceReport, VoiceProviderDecisionTrace, VoiceProviderDecisionTraceInput, VoiceProviderDecisionTraceIssue, VoiceProviderDecisionTraceReport, VoiceProviderDecisionTraceReportOptions, VoiceProviderDecisionTraceRoutesOptions } from './providerDecisionTraces';
34
- export type { VoiceProofTrendAssertionInput, VoiceProofTrendAssertionReport, VoiceProofTrendCycle, VoiceProofTrendProviderRecommendation, VoiceProofTrendProviderSummary, VoiceProofTrendRecommendation, VoiceProofTrendRecommendationOptions, VoiceProofTrendRecommendationReport, VoiceProofTrendRecommendationRoutesOptions, VoiceProofTrendRecommendationStatus, VoiceProofTrendRecommendationSurface, VoiceProofTrendReport, VoiceProofTrendReportInput, VoiceProofTrendRoutesOptions, VoiceProofTrendStatus, VoiceProofTrendSummary } from './proofTrends';
34
+ export type { VoiceProofTrendAssertionInput, VoiceProofTrendAssertionReport, VoiceProofTrendCycle, VoiceProofTrendProfileRecommendation, VoiceProofTrendProfileSummary, VoiceProofTrendProviderRecommendation, VoiceProofTrendProviderSummary, VoiceProofTrendRecommendation, VoiceProofTrendRecommendationOptions, VoiceProofTrendRecommendationReport, VoiceProofTrendRecommendationRoutesOptions, VoiceProofTrendRecommendationStatus, VoiceProofTrendRecommendationSurface, VoiceProofTrendReport, VoiceProofTrendReportInput, VoiceProofTrendRoutesOptions, VoiceProofTrendStatus, VoiceProofTrendSummary } from './proofTrends';
35
35
  export { assertVoiceSloCalibration, buildVoiceSloCalibrationReport, buildVoiceSloReadinessThresholdReport, createVoiceSloReadinessThresholdOptions, createVoiceSloReadinessThresholdRoutes, createVoiceSloThresholdProfile, createVoiceSloCalibrationRoutes, renderVoiceSloCalibrationMarkdown, renderVoiceSloReadinessThresholdHTML, renderVoiceSloReadinessThresholdMarkdown } from './sloCalibration';
36
36
  export type { VoiceSloCalibrationMetricKey, VoiceSloCalibrationOptions, VoiceSloCalibrationReport, VoiceSloCalibrationRoutesOptions, VoiceSloCalibrationSample, VoiceSloCalibrationStatus, VoiceSloCalibrationThreshold, VoiceSloCalibrationThresholds, VoiceSloReadinessThresholdReport, VoiceSloReadinessThresholdReportOptions, VoiceSloReadinessThresholdOptions, VoiceSloReadinessThresholdRoutesOptions, VoiceSloThresholdProfile } from './sloCalibration';
37
37
  export { assertVoiceLiveOpsControlEvidence, assertVoiceLiveOpsEvidence, buildVoiceLiveOpsControlState, createVoiceLiveOpsController, createVoiceLiveOpsRoutes, createVoiceMemoryLiveOpsControlStore, evaluateVoiceLiveOpsControlEvidence, evaluateVoiceLiveOpsEvidence, getVoiceLiveOpsControlStatus, VOICE_LIVE_OPS_ACTIONS } from './liveOps';
package/dist/index.js CHANGED
@@ -14652,7 +14652,35 @@ var bestProviderByRole = (providers) => {
14652
14652
  }
14653
14653
  return [...best.values()].sort((left, right) => String(left.role ?? left.id).localeCompare(String(right.role ?? right.id)));
14654
14654
  };
14655
- var formatProviderMix = (providers) => providers.length === 0 ? "n/a" : providers.map((provider) => provider.role ? `${provider.role.toUpperCase()} ${provider.label ?? provider.id}` : provider.label ?? provider.id).join(", ");
14655
+ var formatProviderMix = (providers) => providers.length === 0 ? "n/a" : providers.map((provider) => provider.role && !(provider.label ?? provider.id).toLowerCase().startsWith(provider.role.toLowerCase()) ? `${provider.role.toUpperCase()} ${provider.label ?? provider.id}` : provider.label ?? provider.id).join(", ");
14656
+ var buildProfileRecommendations = (report, budgets) => (report.summary.profiles ?? []).map((profile) => {
14657
+ const providers = summarizeProofTrendProviders({
14658
+ ...report,
14659
+ cycles: [],
14660
+ summary: {
14661
+ cycles: report.summary.cycles,
14662
+ maxLiveP95Ms: profile.maxLiveP95Ms,
14663
+ maxProviderP95Ms: profile.maxProviderP95Ms,
14664
+ maxTurnP95Ms: profile.maxTurnP95Ms,
14665
+ providers: profile.providers,
14666
+ runtimeChannel: profile.runtimeChannel
14667
+ }
14668
+ }, budgets.maxProviderP95Ms);
14669
+ const bestProviders = bestProviderByRole(providers).filter((provider) => provider.status === "pass");
14670
+ const hasRequiredProviderRoles = bestProviders.some((provider) => provider.role === "llm") && bestProviders.some((provider) => provider.role === "stt") && bestProviders.some((provider) => provider.role === "tts");
14671
+ const runtimePass = (profile.runtimeChannel?.status === undefined || profile.runtimeChannel.status === "pass") && (profile.runtimeChannel?.maxFirstAudioLatencyMs === undefined || profile.runtimeChannel.maxFirstAudioLatencyMs <= budgets.maxRuntimeFirstAudioLatencyMs) && (profile.runtimeChannel?.maxInterruptionP95Ms === undefined || profile.runtimeChannel.maxInterruptionP95Ms <= budgets.maxRuntimeInterruptionP95Ms) && (profile.runtimeChannel?.maxJitterMs === undefined || profile.runtimeChannel.maxJitterMs <= budgets.maxRuntimeJitterMs) && (profile.runtimeChannel?.maxTimestampDriftMs === undefined || profile.runtimeChannel.maxTimestampDriftMs <= budgets.maxRuntimeTimestampDriftMs) && (profile.runtimeChannel?.maxBackpressureEvents === undefined || profile.runtimeChannel.maxBackpressureEvents <= budgets.maxRuntimeBackpressureEvents);
14672
+ const latencyPass = (profile.maxProviderP95Ms === undefined || profile.maxProviderP95Ms <= budgets.maxProviderP95Ms) && (profile.maxLiveP95Ms === undefined || profile.maxLiveP95Ms <= budgets.maxLiveP95Ms) && (profile.maxTurnP95Ms === undefined || profile.maxTurnP95Ms <= budgets.maxTurnP95Ms);
14673
+ const status = profile.status === "fail" || !runtimePass ? "fail" : !latencyPass || !hasRequiredProviderRoles ? "warn" : "pass";
14674
+ return {
14675
+ bestProviders,
14676
+ id: profile.id,
14677
+ label: profile.label,
14678
+ nextMove: status === "pass" ? `Use this proven provider mix for ${profile.label ?? profile.id}: ${formatProviderMix(bestProviders)}.` : providers.length === 0 ? `Collect provider-specific sustained samples for ${profile.label ?? profile.id}.` : `Tune latency/runtime budgets for ${profile.label ?? profile.id} before promoting this profile.`,
14679
+ providerComparisonCount: providers.length,
14680
+ recommendation: status === "pass" ? `Profile ready: ${profile.label ?? profile.id}` : `Profile needs proof: ${profile.label ?? profile.id}`,
14681
+ status
14682
+ };
14683
+ });
14656
14684
  var evaluateVoiceProofTrendEvidence = (report, input = {}) => {
14657
14685
  const issues = [];
14658
14686
  const requiredStatus = input.requireStatus ?? "pass";
@@ -14771,8 +14799,10 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
14771
14799
  const bestProvider = providers.find((provider) => provider.status === "pass") ?? providers[0];
14772
14800
  const bestProviders = bestProviderByRole(providers).filter((provider) => provider.status === "pass");
14773
14801
  const currentProvider = options.currentProviderId ? providers.find((provider) => provider.id === options.currentProviderId) : undefined;
14802
+ const hasSingleProviderRole = new Set(bestProviders.map((provider) => provider.role ?? provider.id)).size <= 1;
14774
14803
  const bestComparableProvider = currentProvider?.role ? bestProviders.find((provider) => provider.role === currentProvider.role) : bestProvider;
14775
14804
  const providerSwitchRecommended = shouldSwitchProvider(currentProvider, bestComparableProvider, options);
14805
+ const profileRecommendations = buildProfileRecommendations(report, budgets);
14776
14806
  const recommendations = [];
14777
14807
  const issues = [];
14778
14808
  if (report.ok !== true) {
@@ -14780,9 +14810,9 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
14780
14810
  }
14781
14811
  recommendations.push({
14782
14812
  evidence: {
14783
- bestProviderId: bestComparableProvider?.id ?? bestProvider?.id,
14813
+ bestProviderId: currentProvider || hasSingleProviderRole ? bestComparableProvider?.id ?? bestProvider?.id : undefined,
14784
14814
  bestProviderMix: formatProviderMix(bestProviders),
14785
- bestProviderP95Ms: bestComparableProvider?.p95Ms ?? bestProvider?.p95Ms,
14815
+ bestProviderP95Ms: currentProvider || hasSingleProviderRole ? bestComparableProvider?.p95Ms ?? bestProvider?.p95Ms : undefined,
14786
14816
  budgetMs: budgets.maxProviderP95Ms,
14787
14817
  currentProviderId: currentProvider?.id ?? options.currentProviderId,
14788
14818
  currentProviderP95Ms: currentProvider?.p95Ms,
@@ -14792,7 +14822,7 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
14792
14822
  nextMove: providers.length > 0 ? providerSwitchRecommended ? `Route latency-sensitive ${currentProvider?.role ?? "provider"} traffic to ${bestComparableProvider?.label ?? bestComparableProvider?.id} for this call profile and keep the current path as fallback.` : bestProviders.length > 0 ? `Use the fastest proven provider mix for this call profile: ${formatProviderMix(bestProviders)}.` : "Collect provider-specific sustained samples before making provider-specific routing decisions." : withinBudget(maxProviderP95Ms, budgets.maxProviderP95Ms) ? "Keep the current provider route for latency-sensitive turns and keep collecting sustained proof." : "Route latency-sensitive turns to a faster provider profile or tighten fallback/circuit-breaker budgets before promotion.",
14793
14823
  providerId: providerSwitchRecommended ? bestComparableProvider?.id : bestProviders.length === 1 ? bestProviders[0]?.id : undefined,
14794
14824
  recommendation: providers.length > 0 ? providerSwitchRecommended ? `Switch latency-sensitive ${currentProvider?.role ?? "provider"} routing to ${bestComparableProvider?.label ?? bestComparableProvider?.id}` : bestProviders.length > 0 ? "Prefer the fastest proven provider mix for this call profile" : "Collect provider-specific latency samples" : withinBudget(maxProviderP95Ms, budgets.maxProviderP95Ms) ? "Keep current provider path" : "Change provider routing for latency-sensitive traffic",
14795
- role: bestComparableProvider?.role,
14825
+ role: currentProvider || hasSingleProviderRole ? bestComparableProvider?.role : undefined,
14796
14826
  status: providers.length > 0 ? providerSwitchRecommended ? "warn" : bestProviders.length > 0 ? "pass" : bestProvider?.status ?? "fail" : withinBudget(maxProviderP95Ms, budgets.maxProviderP95Ms) ? "pass" : maxProviderP95Ms === undefined ? "fail" : "warn",
14797
14827
  surface: "provider-path"
14798
14828
  });
@@ -14835,16 +14865,25 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
14835
14865
  surface: "turn-latency"
14836
14866
  });
14837
14867
  const status = issues.length > 0 ? "fail" : worstRecommendationStatus(recommendations);
14868
+ const profileStatus = worstRecommendationStatus(profileRecommendations.map((profile) => ({
14869
+ evidence: {},
14870
+ nextMove: profile.nextMove,
14871
+ recommendation: profile.recommendation,
14872
+ status: profile.status,
14873
+ surface: "provider-path"
14874
+ })));
14875
+ const combinedStatus = recommendationStatusRank[profileStatus] > recommendationStatusRank[status] ? profileStatus : status;
14838
14876
  return {
14839
14877
  bestProvider,
14840
14878
  bestProviders,
14841
14879
  generatedAt: new Date().toISOString(),
14842
14880
  issues,
14843
- ok: status !== "fail",
14881
+ ok: combinedStatus !== "fail",
14882
+ profiles: profileRecommendations,
14844
14883
  providers,
14845
14884
  recommendations,
14846
14885
  source: report.source || report.outputDir || report.runId || "proof-trends",
14847
- status,
14886
+ status: combinedStatus,
14848
14887
  summary: {
14849
14888
  keepCurrentProviderPath: !providerSwitchRecommended && recommendations.find((item) => item.surface === "provider-path")?.status !== "fail",
14850
14889
  keepCurrentRuntimeChannel: recommendations.find((item) => item.surface === "runtime-channel")?.status === "pass",
@@ -14875,6 +14914,12 @@ var renderVoiceProofTrendRecommendationMarkdown = (report, title = "Voice Provid
14875
14914
  "| ---: | --- | --- | --- | ---: | ---: | --- |",
14876
14915
  ...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. |"],
14877
14916
  "",
14917
+ "## Benchmark Profiles",
14918
+ "",
14919
+ "| Profile | Status | Provider mix | Next move |",
14920
+ "| --- | --- | --- | --- |",
14921
+ ...report.profiles.length ? report.profiles.map((profile) => `| ${escapeMarkdown2(profile.label ?? profile.id)} | ${profile.status} | ${escapeMarkdown2(formatProviderMix(profile.bestProviders))} | ${escapeMarkdown2(profile.nextMove)} |`) : ["| n/a | n/a | n/a | No benchmark profiles were present. |"],
14922
+ "",
14878
14923
  "## Issues",
14879
14924
  "",
14880
14925
  ...report.issues.length ? report.issues.map((issue) => `- ${issue}`) : ["- None"]
@@ -14884,7 +14929,8 @@ var renderVoiceProofTrendRecommendationHTML = (report, title = "Voice Provider R
14884
14929
  const cards = report.recommendations.map((recommendation) => `<article class="${escapeHtml22(recommendation.status)}"><p class="eyebrow">${escapeHtml22(recommendation.surface)} \xB7 ${escapeHtml22(recommendation.status)}</p><h2>${escapeHtml22(recommendation.recommendation)}</h2><p>${escapeHtml22(recommendation.nextMove)}</p><pre>${escapeHtml22(JSON.stringify(recommendation.evidence, null, 2))}</pre></article>`).join("");
14885
14930
  const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${escapeHtml22(issue)}</li>`).join("");
14886
14931
  const providerRows = report.providers.length === 0 ? "<li>No provider-specific samples were present.</li>" : report.providers.map((provider) => `<li><strong>#${String(provider.rank)} ${escapeHtml22(provider.label ?? provider.id)}</strong><span>${escapeHtml22(provider.role ?? "provider")} \xB7 ${escapeHtml22(provider.status)} \xB7 p95 ${escapeHtml22(provider.p95Ms ?? "n/a")}ms \xB7 ${escapeHtml22(provider.samples ?? "n/a")} sample(s)</span><small>${escapeHtml22(provider.nextMove)}</small></li>`).join("");
14887
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml22(title)}</title><style>body{background:#101418;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.hero,article{background:#17201d;border:1px solid #2e3d36;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.12))}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.1em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.7rem);letter-spacing:-.06em;line-height:.92;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{border:1px solid #42534a;border-radius:999px;padding:8px 12px}.pass{border-color:rgba(34,197,94,.55)}.warn{border-color:rgba(245,158,11,.7)}.fail{border-color:rgba(239,68,68,.75)}pre{background:#0b1110;border-radius:14px;overflow:auto;padding:12px}a{color:#5eead4}li{margin:.45rem 0}li span,li small{display:block;color:#c9d3ca}</style></head><body><main><section class="hero"><p class="eyebrow">Sustained proof recommendations</p><h1>${escapeHtml22(title)}</h1><p>Generated ${escapeHtml22(report.generatedAt)} from ${escapeHtml22(report.source)}.</p><div class="summary"><span class="pill">Status ${escapeHtml22(report.status)}</span><span class="pill">Provider ${report.summary.keepCurrentProviderPath ? "keep" : "change"}</span><span class="pill">Best mix ${escapeHtml22(formatProviderMix(report.bestProviders))}</span><span class="pill">Runtime ${report.summary.keepCurrentRuntimeChannel ? "keep" : "tune"}</span><span class="pill">${String(report.summary.recommendedActions)} action(s)</span></div></section>${cards}<section class="hero"><h2>Provider Comparison</h2><ul>${providerRows}</ul></section><section class="hero"><h2>Issues</h2><ul>${issues}</ul></section></main></body></html>`;
14932
+ const profileRows = report.profiles.length === 0 ? "<li>No benchmark profiles were present.</li>" : report.profiles.map((profile) => `<li><strong>${escapeHtml22(profile.label ?? profile.id)}</strong><span>${escapeHtml22(profile.status)} \xB7 ${escapeHtml22(formatProviderMix(profile.bestProviders))}</span><small>${escapeHtml22(profile.nextMove)}</small></li>`).join("");
14933
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml22(title)}</title><style>body{background:#101418;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.hero,article{background:#17201d;border:1px solid #2e3d36;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.12))}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.1em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.7rem);letter-spacing:-.06em;line-height:.92;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{border:1px solid #42534a;border-radius:999px;padding:8px 12px}.pass{border-color:rgba(34,197,94,.55)}.warn{border-color:rgba(245,158,11,.7)}.fail{border-color:rgba(239,68,68,.75)}pre{background:#0b1110;border-radius:14px;overflow:auto;padding:12px}a{color:#5eead4}li{margin:.45rem 0}li span,li small{display:block;color:#c9d3ca}</style></head><body><main><section class="hero"><p class="eyebrow">Sustained proof recommendations</p><h1>${escapeHtml22(title)}</h1><p>Generated ${escapeHtml22(report.generatedAt)} from ${escapeHtml22(report.source)}.</p><div class="summary"><span class="pill">Status ${escapeHtml22(report.status)}</span><span class="pill">Provider ${report.summary.keepCurrentProviderPath ? "keep" : "change"}</span><span class="pill">Best mix ${escapeHtml22(formatProviderMix(report.bestProviders))}</span><span class="pill">Profiles ${String(report.profiles.length)}</span><span class="pill">Runtime ${report.summary.keepCurrentRuntimeChannel ? "keep" : "tune"}</span><span class="pill">${String(report.summary.recommendedActions)} action(s)</span></div></section>${cards}<section class="hero"><h2>Benchmark Profiles</h2><ul>${profileRows}</ul></section><section class="hero"><h2>Provider Comparison</h2><ul>${providerRows}</ul></section><section class="hero"><h2>Issues</h2><ul>${issues}</ul></section></main></body></html>`;
14888
14934
  };
14889
14935
  var createVoiceProofTrendRecommendationRoutes = (options) => {
14890
14936
  const path = options.path ?? "/api/voice/proof-trend-recommendations";
@@ -4,10 +4,22 @@ export type VoiceProofTrendSummary = {
4
4
  cycles?: number;
5
5
  maxLiveP95Ms?: number;
6
6
  maxProviderP95Ms?: number;
7
+ profiles?: VoiceProofTrendProfileSummary[];
7
8
  providers?: VoiceProofTrendProviderSummary[];
8
9
  runtimeChannel?: VoiceProofTrendRuntimeChannelSummary;
9
10
  maxTurnP95Ms?: number;
10
11
  };
12
+ export type VoiceProofTrendProfileSummary = {
13
+ description?: string;
14
+ id: string;
15
+ label?: string;
16
+ maxLiveP95Ms?: number;
17
+ maxProviderP95Ms?: number;
18
+ maxTurnP95Ms?: number;
19
+ providers?: VoiceProofTrendProviderSummary[];
20
+ runtimeChannel?: VoiceProofTrendRuntimeChannelSummary;
21
+ status?: string;
22
+ };
11
23
  export type VoiceProofTrendProviderSummary = {
12
24
  averageMs?: number;
13
25
  id: string;
@@ -149,6 +161,7 @@ export type VoiceProofTrendRecommendationReport = {
149
161
  generatedAt: string;
150
162
  issues: string[];
151
163
  ok: boolean;
164
+ profiles: VoiceProofTrendProfileRecommendation[];
152
165
  providers: VoiceProofTrendProviderRecommendation[];
153
166
  recommendations: VoiceProofTrendRecommendation[];
154
167
  source: string;
@@ -161,6 +174,15 @@ export type VoiceProofTrendRecommendationReport = {
161
174
  switchRecommended: boolean;
162
175
  };
163
176
  };
177
+ export type VoiceProofTrendProfileRecommendation = {
178
+ bestProviders: VoiceProofTrendProviderRecommendation[];
179
+ id: string;
180
+ label?: string;
181
+ nextMove: string;
182
+ providerComparisonCount: number;
183
+ recommendation: string;
184
+ status: VoiceProofTrendRecommendationStatus;
185
+ };
164
186
  export type VoiceProofTrendRecommendationOptions = {
165
187
  currentProviderId?: string;
166
188
  maxLiveP95Ms?: number;
@@ -1683,7 +1683,35 @@ var bestProviderByRole = (providers) => {
1683
1683
  }
1684
1684
  return [...best.values()].sort((left, right) => String(left.role ?? left.id).localeCompare(String(right.role ?? right.id)));
1685
1685
  };
1686
- var formatProviderMix = (providers) => providers.length === 0 ? "n/a" : providers.map((provider) => provider.role ? `${provider.role.toUpperCase()} ${provider.label ?? provider.id}` : provider.label ?? provider.id).join(", ");
1686
+ var formatProviderMix = (providers) => providers.length === 0 ? "n/a" : providers.map((provider) => provider.role && !(provider.label ?? provider.id).toLowerCase().startsWith(provider.role.toLowerCase()) ? `${provider.role.toUpperCase()} ${provider.label ?? provider.id}` : provider.label ?? provider.id).join(", ");
1687
+ var buildProfileRecommendations = (report, budgets) => (report.summary.profiles ?? []).map((profile) => {
1688
+ const providers = summarizeProofTrendProviders({
1689
+ ...report,
1690
+ cycles: [],
1691
+ summary: {
1692
+ cycles: report.summary.cycles,
1693
+ maxLiveP95Ms: profile.maxLiveP95Ms,
1694
+ maxProviderP95Ms: profile.maxProviderP95Ms,
1695
+ maxTurnP95Ms: profile.maxTurnP95Ms,
1696
+ providers: profile.providers,
1697
+ runtimeChannel: profile.runtimeChannel
1698
+ }
1699
+ }, budgets.maxProviderP95Ms);
1700
+ const bestProviders = bestProviderByRole(providers).filter((provider) => provider.status === "pass");
1701
+ const hasRequiredProviderRoles = bestProviders.some((provider) => provider.role === "llm") && bestProviders.some((provider) => provider.role === "stt") && bestProviders.some((provider) => provider.role === "tts");
1702
+ const runtimePass = (profile.runtimeChannel?.status === undefined || profile.runtimeChannel.status === "pass") && (profile.runtimeChannel?.maxFirstAudioLatencyMs === undefined || profile.runtimeChannel.maxFirstAudioLatencyMs <= budgets.maxRuntimeFirstAudioLatencyMs) && (profile.runtimeChannel?.maxInterruptionP95Ms === undefined || profile.runtimeChannel.maxInterruptionP95Ms <= budgets.maxRuntimeInterruptionP95Ms) && (profile.runtimeChannel?.maxJitterMs === undefined || profile.runtimeChannel.maxJitterMs <= budgets.maxRuntimeJitterMs) && (profile.runtimeChannel?.maxTimestampDriftMs === undefined || profile.runtimeChannel.maxTimestampDriftMs <= budgets.maxRuntimeTimestampDriftMs) && (profile.runtimeChannel?.maxBackpressureEvents === undefined || profile.runtimeChannel.maxBackpressureEvents <= budgets.maxRuntimeBackpressureEvents);
1703
+ const latencyPass = (profile.maxProviderP95Ms === undefined || profile.maxProviderP95Ms <= budgets.maxProviderP95Ms) && (profile.maxLiveP95Ms === undefined || profile.maxLiveP95Ms <= budgets.maxLiveP95Ms) && (profile.maxTurnP95Ms === undefined || profile.maxTurnP95Ms <= budgets.maxTurnP95Ms);
1704
+ const status = profile.status === "fail" || !runtimePass ? "fail" : !latencyPass || !hasRequiredProviderRoles ? "warn" : "pass";
1705
+ return {
1706
+ bestProviders,
1707
+ id: profile.id,
1708
+ label: profile.label,
1709
+ nextMove: status === "pass" ? `Use this proven provider mix for ${profile.label ?? profile.id}: ${formatProviderMix(bestProviders)}.` : providers.length === 0 ? `Collect provider-specific sustained samples for ${profile.label ?? profile.id}.` : `Tune latency/runtime budgets for ${profile.label ?? profile.id} before promoting this profile.`,
1710
+ providerComparisonCount: providers.length,
1711
+ recommendation: status === "pass" ? `Profile ready: ${profile.label ?? profile.id}` : `Profile needs proof: ${profile.label ?? profile.id}`,
1712
+ status
1713
+ };
1714
+ });
1687
1715
  var evaluateVoiceProofTrendEvidence = (report, input = {}) => {
1688
1716
  const issues = [];
1689
1717
  const requiredStatus = input.requireStatus ?? "pass";
@@ -1802,8 +1830,10 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
1802
1830
  const bestProvider = providers.find((provider) => provider.status === "pass") ?? providers[0];
1803
1831
  const bestProviders = bestProviderByRole(providers).filter((provider) => provider.status === "pass");
1804
1832
  const currentProvider = options.currentProviderId ? providers.find((provider) => provider.id === options.currentProviderId) : undefined;
1833
+ const hasSingleProviderRole = new Set(bestProviders.map((provider) => provider.role ?? provider.id)).size <= 1;
1805
1834
  const bestComparableProvider = currentProvider?.role ? bestProviders.find((provider) => provider.role === currentProvider.role) : bestProvider;
1806
1835
  const providerSwitchRecommended = shouldSwitchProvider(currentProvider, bestComparableProvider, options);
1836
+ const profileRecommendations = buildProfileRecommendations(report, budgets);
1807
1837
  const recommendations = [];
1808
1838
  const issues = [];
1809
1839
  if (report.ok !== true) {
@@ -1811,9 +1841,9 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
1811
1841
  }
1812
1842
  recommendations.push({
1813
1843
  evidence: {
1814
- bestProviderId: bestComparableProvider?.id ?? bestProvider?.id,
1844
+ bestProviderId: currentProvider || hasSingleProviderRole ? bestComparableProvider?.id ?? bestProvider?.id : undefined,
1815
1845
  bestProviderMix: formatProviderMix(bestProviders),
1816
- bestProviderP95Ms: bestComparableProvider?.p95Ms ?? bestProvider?.p95Ms,
1846
+ bestProviderP95Ms: currentProvider || hasSingleProviderRole ? bestComparableProvider?.p95Ms ?? bestProvider?.p95Ms : undefined,
1817
1847
  budgetMs: budgets.maxProviderP95Ms,
1818
1848
  currentProviderId: currentProvider?.id ?? options.currentProviderId,
1819
1849
  currentProviderP95Ms: currentProvider?.p95Ms,
@@ -1823,7 +1853,7 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
1823
1853
  nextMove: providers.length > 0 ? providerSwitchRecommended ? `Route latency-sensitive ${currentProvider?.role ?? "provider"} traffic to ${bestComparableProvider?.label ?? bestComparableProvider?.id} for this call profile and keep the current path as fallback.` : bestProviders.length > 0 ? `Use the fastest proven provider mix for this call profile: ${formatProviderMix(bestProviders)}.` : "Collect provider-specific sustained samples before making provider-specific routing decisions." : withinBudget(maxProviderP95Ms, budgets.maxProviderP95Ms) ? "Keep the current provider route for latency-sensitive turns and keep collecting sustained proof." : "Route latency-sensitive turns to a faster provider profile or tighten fallback/circuit-breaker budgets before promotion.",
1824
1854
  providerId: providerSwitchRecommended ? bestComparableProvider?.id : bestProviders.length === 1 ? bestProviders[0]?.id : undefined,
1825
1855
  recommendation: providers.length > 0 ? providerSwitchRecommended ? `Switch latency-sensitive ${currentProvider?.role ?? "provider"} routing to ${bestComparableProvider?.label ?? bestComparableProvider?.id}` : bestProviders.length > 0 ? "Prefer the fastest proven provider mix for this call profile" : "Collect provider-specific latency samples" : withinBudget(maxProviderP95Ms, budgets.maxProviderP95Ms) ? "Keep current provider path" : "Change provider routing for latency-sensitive traffic",
1826
- role: bestComparableProvider?.role,
1856
+ role: currentProvider || hasSingleProviderRole ? bestComparableProvider?.role : undefined,
1827
1857
  status: providers.length > 0 ? providerSwitchRecommended ? "warn" : bestProviders.length > 0 ? "pass" : bestProvider?.status ?? "fail" : withinBudget(maxProviderP95Ms, budgets.maxProviderP95Ms) ? "pass" : maxProviderP95Ms === undefined ? "fail" : "warn",
1828
1858
  surface: "provider-path"
1829
1859
  });
@@ -1866,16 +1896,25 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
1866
1896
  surface: "turn-latency"
1867
1897
  });
1868
1898
  const status = issues.length > 0 ? "fail" : worstRecommendationStatus(recommendations);
1899
+ const profileStatus = worstRecommendationStatus(profileRecommendations.map((profile) => ({
1900
+ evidence: {},
1901
+ nextMove: profile.nextMove,
1902
+ recommendation: profile.recommendation,
1903
+ status: profile.status,
1904
+ surface: "provider-path"
1905
+ })));
1906
+ const combinedStatus = recommendationStatusRank[profileStatus] > recommendationStatusRank[status] ? profileStatus : status;
1869
1907
  return {
1870
1908
  bestProvider,
1871
1909
  bestProviders,
1872
1910
  generatedAt: new Date().toISOString(),
1873
1911
  issues,
1874
- ok: status !== "fail",
1912
+ ok: combinedStatus !== "fail",
1913
+ profiles: profileRecommendations,
1875
1914
  providers,
1876
1915
  recommendations,
1877
1916
  source: report.source || report.outputDir || report.runId || "proof-trends",
1878
- status,
1917
+ status: combinedStatus,
1879
1918
  summary: {
1880
1919
  keepCurrentProviderPath: !providerSwitchRecommended && recommendations.find((item) => item.surface === "provider-path")?.status !== "fail",
1881
1920
  keepCurrentRuntimeChannel: recommendations.find((item) => item.surface === "runtime-channel")?.status === "pass",
@@ -1906,6 +1945,12 @@ var renderVoiceProofTrendRecommendationMarkdown = (report, title = "Voice Provid
1906
1945
  "| ---: | --- | --- | --- | ---: | ---: | --- |",
1907
1946
  ...report.providers.length ? report.providers.map((provider) => `| ${String(provider.rank)} | ${escapeMarkdown(provider.label ?? provider.id)} | ${escapeMarkdown(provider.role ?? "n/a")} | ${provider.status} | ${provider.p95Ms === undefined ? "n/a" : String(provider.p95Ms)} | ${provider.samples === undefined ? "n/a" : String(provider.samples)} | ${escapeMarkdown(provider.nextMove)} |`) : ["| n/a | n/a | n/a | n/a | n/a | n/a | No provider-specific samples were present. |"],
1908
1947
  "",
1948
+ "## Benchmark Profiles",
1949
+ "",
1950
+ "| Profile | Status | Provider mix | Next move |",
1951
+ "| --- | --- | --- | --- |",
1952
+ ...report.profiles.length ? report.profiles.map((profile) => `| ${escapeMarkdown(profile.label ?? profile.id)} | ${profile.status} | ${escapeMarkdown(formatProviderMix(profile.bestProviders))} | ${escapeMarkdown(profile.nextMove)} |`) : ["| n/a | n/a | n/a | No benchmark profiles were present. |"],
1953
+ "",
1909
1954
  "## Issues",
1910
1955
  "",
1911
1956
  ...report.issues.length ? report.issues.map((issue) => `- ${issue}`) : ["- None"]
@@ -1915,7 +1960,8 @@ var renderVoiceProofTrendRecommendationHTML = (report, title = "Voice Provider R
1915
1960
  const cards = report.recommendations.map((recommendation) => `<article class="${escapeHtml5(recommendation.status)}"><p class="eyebrow">${escapeHtml5(recommendation.surface)} \xB7 ${escapeHtml5(recommendation.status)}</p><h2>${escapeHtml5(recommendation.recommendation)}</h2><p>${escapeHtml5(recommendation.nextMove)}</p><pre>${escapeHtml5(JSON.stringify(recommendation.evidence, null, 2))}</pre></article>`).join("");
1916
1961
  const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${escapeHtml5(issue)}</li>`).join("");
1917
1962
  const providerRows = report.providers.length === 0 ? "<li>No provider-specific samples were present.</li>" : report.providers.map((provider) => `<li><strong>#${String(provider.rank)} ${escapeHtml5(provider.label ?? provider.id)}</strong><span>${escapeHtml5(provider.role ?? "provider")} \xB7 ${escapeHtml5(provider.status)} \xB7 p95 ${escapeHtml5(provider.p95Ms ?? "n/a")}ms \xB7 ${escapeHtml5(provider.samples ?? "n/a")} sample(s)</span><small>${escapeHtml5(provider.nextMove)}</small></li>`).join("");
1918
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml5(title)}</title><style>body{background:#101418;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.hero,article{background:#17201d;border:1px solid #2e3d36;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.12))}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.1em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.7rem);letter-spacing:-.06em;line-height:.92;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{border:1px solid #42534a;border-radius:999px;padding:8px 12px}.pass{border-color:rgba(34,197,94,.55)}.warn{border-color:rgba(245,158,11,.7)}.fail{border-color:rgba(239,68,68,.75)}pre{background:#0b1110;border-radius:14px;overflow:auto;padding:12px}a{color:#5eead4}li{margin:.45rem 0}li span,li small{display:block;color:#c9d3ca}</style></head><body><main><section class="hero"><p class="eyebrow">Sustained proof recommendations</p><h1>${escapeHtml5(title)}</h1><p>Generated ${escapeHtml5(report.generatedAt)} from ${escapeHtml5(report.source)}.</p><div class="summary"><span class="pill">Status ${escapeHtml5(report.status)}</span><span class="pill">Provider ${report.summary.keepCurrentProviderPath ? "keep" : "change"}</span><span class="pill">Best mix ${escapeHtml5(formatProviderMix(report.bestProviders))}</span><span class="pill">Runtime ${report.summary.keepCurrentRuntimeChannel ? "keep" : "tune"}</span><span class="pill">${String(report.summary.recommendedActions)} action(s)</span></div></section>${cards}<section class="hero"><h2>Provider Comparison</h2><ul>${providerRows}</ul></section><section class="hero"><h2>Issues</h2><ul>${issues}</ul></section></main></body></html>`;
1963
+ const profileRows = report.profiles.length === 0 ? "<li>No benchmark profiles were present.</li>" : report.profiles.map((profile) => `<li><strong>${escapeHtml5(profile.label ?? profile.id)}</strong><span>${escapeHtml5(profile.status)} \xB7 ${escapeHtml5(formatProviderMix(profile.bestProviders))}</span><small>${escapeHtml5(profile.nextMove)}</small></li>`).join("");
1964
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml5(title)}</title><style>body{background:#101418;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.hero,article{background:#17201d;border:1px solid #2e3d36;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.12))}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.1em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.7rem);letter-spacing:-.06em;line-height:.92;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{border:1px solid #42534a;border-radius:999px;padding:8px 12px}.pass{border-color:rgba(34,197,94,.55)}.warn{border-color:rgba(245,158,11,.7)}.fail{border-color:rgba(239,68,68,.75)}pre{background:#0b1110;border-radius:14px;overflow:auto;padding:12px}a{color:#5eead4}li{margin:.45rem 0}li span,li small{display:block;color:#c9d3ca}</style></head><body><main><section class="hero"><p class="eyebrow">Sustained proof recommendations</p><h1>${escapeHtml5(title)}</h1><p>Generated ${escapeHtml5(report.generatedAt)} from ${escapeHtml5(report.source)}.</p><div class="summary"><span class="pill">Status ${escapeHtml5(report.status)}</span><span class="pill">Provider ${report.summary.keepCurrentProviderPath ? "keep" : "change"}</span><span class="pill">Best mix ${escapeHtml5(formatProviderMix(report.bestProviders))}</span><span class="pill">Profiles ${String(report.profiles.length)}</span><span class="pill">Runtime ${report.summary.keepCurrentRuntimeChannel ? "keep" : "tune"}</span><span class="pill">${String(report.summary.recommendedActions)} action(s)</span></div></section>${cards}<section class="hero"><h2>Benchmark Profiles</h2><ul>${profileRows}</ul></section><section class="hero"><h2>Provider Comparison</h2><ul>${providerRows}</ul></section><section class="hero"><h2>Issues</h2><ul>${issues}</ul></section></main></body></html>`;
1919
1965
  };
1920
1966
  var createVoiceProofTrendRecommendationRoutes = (options) => {
1921
1967
  const path = options.path ?? "/api/voice/proof-trend-recommendations";
package/dist/vue/index.js CHANGED
@@ -1604,7 +1604,35 @@ var bestProviderByRole = (providers) => {
1604
1604
  }
1605
1605
  return [...best.values()].sort((left, right) => String(left.role ?? left.id).localeCompare(String(right.role ?? right.id)));
1606
1606
  };
1607
- var formatProviderMix = (providers) => providers.length === 0 ? "n/a" : providers.map((provider) => provider.role ? `${provider.role.toUpperCase()} ${provider.label ?? provider.id}` : provider.label ?? provider.id).join(", ");
1607
+ var formatProviderMix = (providers) => providers.length === 0 ? "n/a" : providers.map((provider) => provider.role && !(provider.label ?? provider.id).toLowerCase().startsWith(provider.role.toLowerCase()) ? `${provider.role.toUpperCase()} ${provider.label ?? provider.id}` : provider.label ?? provider.id).join(", ");
1608
+ var buildProfileRecommendations = (report, budgets) => (report.summary.profiles ?? []).map((profile) => {
1609
+ const providers = summarizeProofTrendProviders({
1610
+ ...report,
1611
+ cycles: [],
1612
+ summary: {
1613
+ cycles: report.summary.cycles,
1614
+ maxLiveP95Ms: profile.maxLiveP95Ms,
1615
+ maxProviderP95Ms: profile.maxProviderP95Ms,
1616
+ maxTurnP95Ms: profile.maxTurnP95Ms,
1617
+ providers: profile.providers,
1618
+ runtimeChannel: profile.runtimeChannel
1619
+ }
1620
+ }, budgets.maxProviderP95Ms);
1621
+ const bestProviders = bestProviderByRole(providers).filter((provider) => provider.status === "pass");
1622
+ const hasRequiredProviderRoles = bestProviders.some((provider) => provider.role === "llm") && bestProviders.some((provider) => provider.role === "stt") && bestProviders.some((provider) => provider.role === "tts");
1623
+ const runtimePass = (profile.runtimeChannel?.status === undefined || profile.runtimeChannel.status === "pass") && (profile.runtimeChannel?.maxFirstAudioLatencyMs === undefined || profile.runtimeChannel.maxFirstAudioLatencyMs <= budgets.maxRuntimeFirstAudioLatencyMs) && (profile.runtimeChannel?.maxInterruptionP95Ms === undefined || profile.runtimeChannel.maxInterruptionP95Ms <= budgets.maxRuntimeInterruptionP95Ms) && (profile.runtimeChannel?.maxJitterMs === undefined || profile.runtimeChannel.maxJitterMs <= budgets.maxRuntimeJitterMs) && (profile.runtimeChannel?.maxTimestampDriftMs === undefined || profile.runtimeChannel.maxTimestampDriftMs <= budgets.maxRuntimeTimestampDriftMs) && (profile.runtimeChannel?.maxBackpressureEvents === undefined || profile.runtimeChannel.maxBackpressureEvents <= budgets.maxRuntimeBackpressureEvents);
1624
+ const latencyPass = (profile.maxProviderP95Ms === undefined || profile.maxProviderP95Ms <= budgets.maxProviderP95Ms) && (profile.maxLiveP95Ms === undefined || profile.maxLiveP95Ms <= budgets.maxLiveP95Ms) && (profile.maxTurnP95Ms === undefined || profile.maxTurnP95Ms <= budgets.maxTurnP95Ms);
1625
+ const status = profile.status === "fail" || !runtimePass ? "fail" : !latencyPass || !hasRequiredProviderRoles ? "warn" : "pass";
1626
+ return {
1627
+ bestProviders,
1628
+ id: profile.id,
1629
+ label: profile.label,
1630
+ nextMove: status === "pass" ? `Use this proven provider mix for ${profile.label ?? profile.id}: ${formatProviderMix(bestProviders)}.` : providers.length === 0 ? `Collect provider-specific sustained samples for ${profile.label ?? profile.id}.` : `Tune latency/runtime budgets for ${profile.label ?? profile.id} before promoting this profile.`,
1631
+ providerComparisonCount: providers.length,
1632
+ recommendation: status === "pass" ? `Profile ready: ${profile.label ?? profile.id}` : `Profile needs proof: ${profile.label ?? profile.id}`,
1633
+ status
1634
+ };
1635
+ });
1608
1636
  var evaluateVoiceProofTrendEvidence = (report, input = {}) => {
1609
1637
  const issues = [];
1610
1638
  const requiredStatus = input.requireStatus ?? "pass";
@@ -1723,8 +1751,10 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
1723
1751
  const bestProvider = providers.find((provider) => provider.status === "pass") ?? providers[0];
1724
1752
  const bestProviders = bestProviderByRole(providers).filter((provider) => provider.status === "pass");
1725
1753
  const currentProvider = options.currentProviderId ? providers.find((provider) => provider.id === options.currentProviderId) : undefined;
1754
+ const hasSingleProviderRole = new Set(bestProviders.map((provider) => provider.role ?? provider.id)).size <= 1;
1726
1755
  const bestComparableProvider = currentProvider?.role ? bestProviders.find((provider) => provider.role === currentProvider.role) : bestProvider;
1727
1756
  const providerSwitchRecommended = shouldSwitchProvider(currentProvider, bestComparableProvider, options);
1757
+ const profileRecommendations = buildProfileRecommendations(report, budgets);
1728
1758
  const recommendations = [];
1729
1759
  const issues = [];
1730
1760
  if (report.ok !== true) {
@@ -1732,9 +1762,9 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
1732
1762
  }
1733
1763
  recommendations.push({
1734
1764
  evidence: {
1735
- bestProviderId: bestComparableProvider?.id ?? bestProvider?.id,
1765
+ bestProviderId: currentProvider || hasSingleProviderRole ? bestComparableProvider?.id ?? bestProvider?.id : undefined,
1736
1766
  bestProviderMix: formatProviderMix(bestProviders),
1737
- bestProviderP95Ms: bestComparableProvider?.p95Ms ?? bestProvider?.p95Ms,
1767
+ bestProviderP95Ms: currentProvider || hasSingleProviderRole ? bestComparableProvider?.p95Ms ?? bestProvider?.p95Ms : undefined,
1738
1768
  budgetMs: budgets.maxProviderP95Ms,
1739
1769
  currentProviderId: currentProvider?.id ?? options.currentProviderId,
1740
1770
  currentProviderP95Ms: currentProvider?.p95Ms,
@@ -1744,7 +1774,7 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
1744
1774
  nextMove: providers.length > 0 ? providerSwitchRecommended ? `Route latency-sensitive ${currentProvider?.role ?? "provider"} traffic to ${bestComparableProvider?.label ?? bestComparableProvider?.id} for this call profile and keep the current path as fallback.` : bestProviders.length > 0 ? `Use the fastest proven provider mix for this call profile: ${formatProviderMix(bestProviders)}.` : "Collect provider-specific sustained samples before making provider-specific routing decisions." : withinBudget(maxProviderP95Ms, budgets.maxProviderP95Ms) ? "Keep the current provider route for latency-sensitive turns and keep collecting sustained proof." : "Route latency-sensitive turns to a faster provider profile or tighten fallback/circuit-breaker budgets before promotion.",
1745
1775
  providerId: providerSwitchRecommended ? bestComparableProvider?.id : bestProviders.length === 1 ? bestProviders[0]?.id : undefined,
1746
1776
  recommendation: providers.length > 0 ? providerSwitchRecommended ? `Switch latency-sensitive ${currentProvider?.role ?? "provider"} routing to ${bestComparableProvider?.label ?? bestComparableProvider?.id}` : bestProviders.length > 0 ? "Prefer the fastest proven provider mix for this call profile" : "Collect provider-specific latency samples" : withinBudget(maxProviderP95Ms, budgets.maxProviderP95Ms) ? "Keep current provider path" : "Change provider routing for latency-sensitive traffic",
1747
- role: bestComparableProvider?.role,
1777
+ role: currentProvider || hasSingleProviderRole ? bestComparableProvider?.role : undefined,
1748
1778
  status: providers.length > 0 ? providerSwitchRecommended ? "warn" : bestProviders.length > 0 ? "pass" : bestProvider?.status ?? "fail" : withinBudget(maxProviderP95Ms, budgets.maxProviderP95Ms) ? "pass" : maxProviderP95Ms === undefined ? "fail" : "warn",
1749
1779
  surface: "provider-path"
1750
1780
  });
@@ -1787,16 +1817,25 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
1787
1817
  surface: "turn-latency"
1788
1818
  });
1789
1819
  const status = issues.length > 0 ? "fail" : worstRecommendationStatus(recommendations);
1820
+ const profileStatus = worstRecommendationStatus(profileRecommendations.map((profile) => ({
1821
+ evidence: {},
1822
+ nextMove: profile.nextMove,
1823
+ recommendation: profile.recommendation,
1824
+ status: profile.status,
1825
+ surface: "provider-path"
1826
+ })));
1827
+ const combinedStatus = recommendationStatusRank[profileStatus] > recommendationStatusRank[status] ? profileStatus : status;
1790
1828
  return {
1791
1829
  bestProvider,
1792
1830
  bestProviders,
1793
1831
  generatedAt: new Date().toISOString(),
1794
1832
  issues,
1795
- ok: status !== "fail",
1833
+ ok: combinedStatus !== "fail",
1834
+ profiles: profileRecommendations,
1796
1835
  providers,
1797
1836
  recommendations,
1798
1837
  source: report.source || report.outputDir || report.runId || "proof-trends",
1799
- status,
1838
+ status: combinedStatus,
1800
1839
  summary: {
1801
1840
  keepCurrentProviderPath: !providerSwitchRecommended && recommendations.find((item) => item.surface === "provider-path")?.status !== "fail",
1802
1841
  keepCurrentRuntimeChannel: recommendations.find((item) => item.surface === "runtime-channel")?.status === "pass",
@@ -1827,6 +1866,12 @@ var renderVoiceProofTrendRecommendationMarkdown = (report, title = "Voice Provid
1827
1866
  "| ---: | --- | --- | --- | ---: | ---: | --- |",
1828
1867
  ...report.providers.length ? report.providers.map((provider) => `| ${String(provider.rank)} | ${escapeMarkdown(provider.label ?? provider.id)} | ${escapeMarkdown(provider.role ?? "n/a")} | ${provider.status} | ${provider.p95Ms === undefined ? "n/a" : String(provider.p95Ms)} | ${provider.samples === undefined ? "n/a" : String(provider.samples)} | ${escapeMarkdown(provider.nextMove)} |`) : ["| n/a | n/a | n/a | n/a | n/a | n/a | No provider-specific samples were present. |"],
1829
1868
  "",
1869
+ "## Benchmark Profiles",
1870
+ "",
1871
+ "| Profile | Status | Provider mix | Next move |",
1872
+ "| --- | --- | --- | --- |",
1873
+ ...report.profiles.length ? report.profiles.map((profile) => `| ${escapeMarkdown(profile.label ?? profile.id)} | ${profile.status} | ${escapeMarkdown(formatProviderMix(profile.bestProviders))} | ${escapeMarkdown(profile.nextMove)} |`) : ["| n/a | n/a | n/a | No benchmark profiles were present. |"],
1874
+ "",
1830
1875
  "## Issues",
1831
1876
  "",
1832
1877
  ...report.issues.length ? report.issues.map((issue) => `- ${issue}`) : ["- None"]
@@ -1836,7 +1881,8 @@ var renderVoiceProofTrendRecommendationHTML = (report, title = "Voice Provider R
1836
1881
  const cards = report.recommendations.map((recommendation) => `<article class="${escapeHtml5(recommendation.status)}"><p class="eyebrow">${escapeHtml5(recommendation.surface)} \xB7 ${escapeHtml5(recommendation.status)}</p><h2>${escapeHtml5(recommendation.recommendation)}</h2><p>${escapeHtml5(recommendation.nextMove)}</p><pre>${escapeHtml5(JSON.stringify(recommendation.evidence, null, 2))}</pre></article>`).join("");
1837
1882
  const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${escapeHtml5(issue)}</li>`).join("");
1838
1883
  const providerRows = report.providers.length === 0 ? "<li>No provider-specific samples were present.</li>" : report.providers.map((provider) => `<li><strong>#${String(provider.rank)} ${escapeHtml5(provider.label ?? provider.id)}</strong><span>${escapeHtml5(provider.role ?? "provider")} \xB7 ${escapeHtml5(provider.status)} \xB7 p95 ${escapeHtml5(provider.p95Ms ?? "n/a")}ms \xB7 ${escapeHtml5(provider.samples ?? "n/a")} sample(s)</span><small>${escapeHtml5(provider.nextMove)}</small></li>`).join("");
1839
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml5(title)}</title><style>body{background:#101418;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.hero,article{background:#17201d;border:1px solid #2e3d36;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.12))}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.1em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.7rem);letter-spacing:-.06em;line-height:.92;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{border:1px solid #42534a;border-radius:999px;padding:8px 12px}.pass{border-color:rgba(34,197,94,.55)}.warn{border-color:rgba(245,158,11,.7)}.fail{border-color:rgba(239,68,68,.75)}pre{background:#0b1110;border-radius:14px;overflow:auto;padding:12px}a{color:#5eead4}li{margin:.45rem 0}li span,li small{display:block;color:#c9d3ca}</style></head><body><main><section class="hero"><p class="eyebrow">Sustained proof recommendations</p><h1>${escapeHtml5(title)}</h1><p>Generated ${escapeHtml5(report.generatedAt)} from ${escapeHtml5(report.source)}.</p><div class="summary"><span class="pill">Status ${escapeHtml5(report.status)}</span><span class="pill">Provider ${report.summary.keepCurrentProviderPath ? "keep" : "change"}</span><span class="pill">Best mix ${escapeHtml5(formatProviderMix(report.bestProviders))}</span><span class="pill">Runtime ${report.summary.keepCurrentRuntimeChannel ? "keep" : "tune"}</span><span class="pill">${String(report.summary.recommendedActions)} action(s)</span></div></section>${cards}<section class="hero"><h2>Provider Comparison</h2><ul>${providerRows}</ul></section><section class="hero"><h2>Issues</h2><ul>${issues}</ul></section></main></body></html>`;
1884
+ const profileRows = report.profiles.length === 0 ? "<li>No benchmark profiles were present.</li>" : report.profiles.map((profile) => `<li><strong>${escapeHtml5(profile.label ?? profile.id)}</strong><span>${escapeHtml5(profile.status)} \xB7 ${escapeHtml5(formatProviderMix(profile.bestProviders))}</span><small>${escapeHtml5(profile.nextMove)}</small></li>`).join("");
1885
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml5(title)}</title><style>body{background:#101418;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.hero,article{background:#17201d;border:1px solid #2e3d36;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.12))}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.1em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.7rem);letter-spacing:-.06em;line-height:.92;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{border:1px solid #42534a;border-radius:999px;padding:8px 12px}.pass{border-color:rgba(34,197,94,.55)}.warn{border-color:rgba(245,158,11,.7)}.fail{border-color:rgba(239,68,68,.75)}pre{background:#0b1110;border-radius:14px;overflow:auto;padding:12px}a{color:#5eead4}li{margin:.45rem 0}li span,li small{display:block;color:#c9d3ca}</style></head><body><main><section class="hero"><p class="eyebrow">Sustained proof recommendations</p><h1>${escapeHtml5(title)}</h1><p>Generated ${escapeHtml5(report.generatedAt)} from ${escapeHtml5(report.source)}.</p><div class="summary"><span class="pill">Status ${escapeHtml5(report.status)}</span><span class="pill">Provider ${report.summary.keepCurrentProviderPath ? "keep" : "change"}</span><span class="pill">Best mix ${escapeHtml5(formatProviderMix(report.bestProviders))}</span><span class="pill">Profiles ${String(report.profiles.length)}</span><span class="pill">Runtime ${report.summary.keepCurrentRuntimeChannel ? "keep" : "tune"}</span><span class="pill">${String(report.summary.recommendedActions)} action(s)</span></div></section>${cards}<section class="hero"><h2>Benchmark Profiles</h2><ul>${profileRows}</ul></section><section class="hero"><h2>Provider Comparison</h2><ul>${providerRows}</ul></section><section class="hero"><h2>Issues</h2><ul>${issues}</ul></section></main></body></html>`;
1840
1886
  };
1841
1887
  var createVoiceProofTrendRecommendationRoutes = (options) => {
1842
1888
  const path = options.path ?? "/api/voice/proof-trend-recommendations";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.336",
3
+ "version": "0.0.22-beta.338",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",