Implement Phase 6R-Y provider routing policy
This commit is contained in:
parent
7a8182cb2c
commit
3464732aab
13 changed files with 1405 additions and 31 deletions
|
|
@ -982,6 +982,46 @@ namespace HyperTwistContractLibraryInternal
|
|||
};
|
||||
}
|
||||
|
||||
TArray<FString> MakeDefaultSpeechRoutingEligibleProviderClasses()
|
||||
{
|
||||
return {
|
||||
TEXT("official-direct-provider"),
|
||||
TEXT("openai-compatible-custom-endpoint"),
|
||||
TEXT("byok-endpoint"),
|
||||
TEXT("managed-gateway-provider"),
|
||||
TEXT("local-self-hosted-provider"),
|
||||
TEXT("bounded-speech-sidecar-service"),
|
||||
TEXT("first-party-mock-provider")
|
||||
};
|
||||
}
|
||||
|
||||
TArray<FString> MakeDefaultSpeechRoutingEligibleEndpointClasses()
|
||||
{
|
||||
return {
|
||||
TEXT("official-http-api"),
|
||||
TEXT("openai-compatible-http-api"),
|
||||
TEXT("managed-gateway-http"),
|
||||
TEXT("local-self-hosted-http"),
|
||||
TEXT("in-process-mock")
|
||||
};
|
||||
}
|
||||
|
||||
TArray<FString> MakeDefaultSpeechRoutingRequiredCapabilities()
|
||||
{
|
||||
return {
|
||||
TEXT("transcribe"),
|
||||
TEXT("grammarHints"),
|
||||
TEXT("manualTranscriptCommit")
|
||||
};
|
||||
}
|
||||
|
||||
TArray<FString> MakeDefaultSpeechRoutingSupportedTaskKinds()
|
||||
{
|
||||
return {
|
||||
TEXT("transcribe")
|
||||
};
|
||||
}
|
||||
|
||||
FHyperTwistSpeechProviderProfile MakeMockSpeechProviderProfile()
|
||||
{
|
||||
FHyperTwistSpeechProviderProfile Profile;
|
||||
|
|
@ -1029,6 +1069,110 @@ namespace HyperTwistContractLibraryInternal
|
|||
return Profile;
|
||||
}
|
||||
|
||||
FHyperTwistSpeechProviderRoutingPolicy MakeMockSpeechProviderRoutingPolicy()
|
||||
{
|
||||
FHyperTwistSpeechProviderRoutingPolicy Policy;
|
||||
Policy.ProviderRoutingPolicyId = TEXT("speech-provider-routing/local-offline-mock-first-v1");
|
||||
Policy.PolicyKind = TEXT("speech-provider-routing");
|
||||
Policy.RouteSelectionMode = TEXT("local-offline-mock-first");
|
||||
Policy.FallbackMode = TEXT("fail-closed");
|
||||
Policy.WorkflowPolicyState = TEXT("first-party-provider-policy-governed");
|
||||
Policy.FailureEscalationMode = TEXT("preserve-local-verification-route");
|
||||
Policy.UserOverridePosture = TEXT("client-kind-and-profile-override-supported");
|
||||
Policy.EligibleProviderClasses = MakeDefaultSpeechRoutingEligibleProviderClasses();
|
||||
Policy.EligibleEndpointClasses = MakeDefaultSpeechRoutingEligibleEndpointClasses();
|
||||
Policy.RequiredCapabilityFlags = MakeDefaultSpeechRoutingRequiredCapabilities();
|
||||
Policy.SupportedTaskKinds = MakeDefaultSpeechRoutingSupportedTaskKinds();
|
||||
Policy.bAllowProviderBackedRoutes = false;
|
||||
Policy.bAllowMockVerificationRoutes = true;
|
||||
Policy.bAllowOpenAiCompatibleCustomEndpointRoutes = true;
|
||||
Policy.bAllowUserLabeledByokRoutes = true;
|
||||
Policy.bAllowManagedGatewayRoutes = true;
|
||||
Policy.bAllowLocalSelfHostedRoutes = true;
|
||||
Policy.bRespectsProfileEnableDisable = true;
|
||||
Policy.bAllowFailClosedWhenNoEligibleRoute = true;
|
||||
Policy.bAllowHealthPostureFallback = false;
|
||||
Policy.bPreservesFirstPartyRoutingOwnership = true;
|
||||
Policy.bAllowsDonorOwnedRoutingLanguage = false;
|
||||
return Policy;
|
||||
}
|
||||
|
||||
FHyperTwistSpeechProviderRoutingPolicy MakeProviderBackedSpeechProviderRoutingPolicy()
|
||||
{
|
||||
FHyperTwistSpeechProviderRoutingPolicy Policy;
|
||||
Policy.ProviderRoutingPolicyId = TEXT("speech-provider-routing/provider-backed-sidecar-first-v1");
|
||||
Policy.PolicyKind = TEXT("speech-provider-routing");
|
||||
Policy.RouteSelectionMode = TEXT("provider-backed-sidecar-first");
|
||||
Policy.FallbackMode = TEXT("health-posture-only");
|
||||
Policy.WorkflowPolicyState = TEXT("first-party-provider-policy-governed");
|
||||
Policy.FailureEscalationMode = TEXT("fail-closed-and-report-health");
|
||||
Policy.UserOverridePosture = TEXT("profile-or-client-kind-override-supported");
|
||||
Policy.EligibleProviderClasses = MakeDefaultSpeechRoutingEligibleProviderClasses();
|
||||
Policy.EligibleEndpointClasses = MakeDefaultSpeechRoutingEligibleEndpointClasses();
|
||||
Policy.RequiredCapabilityFlags = MakeDefaultSpeechRoutingRequiredCapabilities();
|
||||
Policy.SupportedTaskKinds = MakeDefaultSpeechRoutingSupportedTaskKinds();
|
||||
Policy.bAllowProviderBackedRoutes = true;
|
||||
Policy.bAllowMockVerificationRoutes = true;
|
||||
Policy.bAllowOpenAiCompatibleCustomEndpointRoutes = true;
|
||||
Policy.bAllowUserLabeledByokRoutes = true;
|
||||
Policy.bAllowManagedGatewayRoutes = true;
|
||||
Policy.bAllowLocalSelfHostedRoutes = true;
|
||||
Policy.bRespectsProfileEnableDisable = true;
|
||||
Policy.bAllowFailClosedWhenNoEligibleRoute = true;
|
||||
Policy.bAllowHealthPostureFallback = true;
|
||||
Policy.bPreservesFirstPartyRoutingOwnership = true;
|
||||
Policy.bAllowsDonorOwnedRoutingLanguage = false;
|
||||
return Policy;
|
||||
}
|
||||
|
||||
FHyperTwistSpeechProviderRouteDecision MakeSpeechProviderRouteDecision(
|
||||
const FHyperTwistSpeechProviderRoutingPolicy& Policy,
|
||||
const FHyperTwistSpeechProviderProfile& Profile,
|
||||
const FString& SelectedServiceLaneId,
|
||||
const FString& DecisionSource,
|
||||
const FString& RouteStateId,
|
||||
const FString& DecisionReason,
|
||||
const FString& FailureReason,
|
||||
const bool bProviderBackedRouteRequested,
|
||||
const bool bProviderBackedRouteSelected,
|
||||
const bool bUsedFallbackHealthPosture,
|
||||
const bool bRouteReady
|
||||
)
|
||||
{
|
||||
FHyperTwistSpeechProviderRouteDecision Decision;
|
||||
Decision.RouteDecisionId = FString::Printf(
|
||||
TEXT("speech-route-decision/%s"),
|
||||
*Profile.ProviderProfileId
|
||||
);
|
||||
Decision.ProviderRoutingPolicyId = Policy.ProviderRoutingPolicyId;
|
||||
Decision.DecisionSource = DecisionSource;
|
||||
Decision.RequestedProviderProfileId = Profile.ProviderProfileId;
|
||||
Decision.SelectedProviderProfileId = Profile.ProviderProfileId;
|
||||
Decision.SelectedProviderClass = Profile.ProviderClass;
|
||||
Decision.SelectedEndpointClass = Profile.EndpointClass;
|
||||
Decision.SelectedServiceLaneId = SelectedServiceLaneId.IsEmpty()
|
||||
? TEXT("speech/python-service")
|
||||
: SelectedServiceLaneId;
|
||||
Decision.SelectedTransportKind = Profile.EndpointClass.Equals(TEXT("in-process-mock"), ESearchCase::IgnoreCase)
|
||||
? TEXT("in-process")
|
||||
: TEXT("http");
|
||||
Decision.RouteStateId = RouteStateId;
|
||||
Decision.DecisionReason = DecisionReason;
|
||||
Decision.FailureReason = FailureReason;
|
||||
Decision.FallbackMode = Policy.FallbackMode;
|
||||
Decision.bProviderBackedRouteRequested = bProviderBackedRouteRequested;
|
||||
Decision.bProviderBackedRouteSelected = bProviderBackedRouteSelected;
|
||||
Decision.bUsedFallbackHealthPosture = bUsedFallbackHealthPosture;
|
||||
Decision.bSelectedProfileEnabled = Profile.bEnabled;
|
||||
Decision.bSelectedCustomEndpointRoute =
|
||||
Profile.bUserLabeled
|
||||
&& Profile.bSupportsCustomBaseUrl
|
||||
&& !Profile.EndpointBaseUrl.IsEmpty()
|
||||
&& !Profile.EndpointBaseUrl.Contains(TEXT("127.0.0.1"), ESearchCase::IgnoreCase);
|
||||
Decision.bRouteReady = bRouteReady;
|
||||
return Decision;
|
||||
}
|
||||
|
||||
FHyperTwistSpeechByokCustodyProfile MakeDefaultSpeechByokCustodyProfile(const FString& ProfileId)
|
||||
{
|
||||
FHyperTwistSpeechByokCustodyProfile Profile;
|
||||
|
|
@ -1852,6 +1996,23 @@ FHyperTwistSpeechSessionConfig UHyperTwistContractLibrary::MakeSampleSpeechSessi
|
|||
HyperTwistContractLibraryInternal::MakeDefaultSpeechByokCustodyProfile(
|
||||
Config.ByokCustodyProfileId
|
||||
);
|
||||
Config.ProviderRoutingPolicyId = TEXT("speech-provider-routing/provider-backed-sidecar-first-v1");
|
||||
Config.ProviderRoutingPolicyDefinition =
|
||||
HyperTwistContractLibraryInternal::MakeProviderBackedSpeechProviderRoutingPolicy();
|
||||
Config.ProviderRouteDecision =
|
||||
HyperTwistContractLibraryInternal::MakeSpeechProviderRouteDecision(
|
||||
Config.ProviderRoutingPolicyDefinition,
|
||||
Config.ProviderProfileDefinition,
|
||||
TEXT("speech/python-service"),
|
||||
TEXT("sample-session-config"),
|
||||
TEXT("route-ready"),
|
||||
TEXT("provider-backed-sidecar-route-selected"),
|
||||
FString(),
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true
|
||||
);
|
||||
Config.PayloadCustodyProfileId = TEXT("downloadable-model-payload-custody-v1");
|
||||
Config.PayloadCustodyProfileDefinition =
|
||||
HyperTwistContractLibraryInternal::MakeDefaultSpeechPayloadCustodyProfile(
|
||||
|
|
@ -1950,6 +2111,9 @@ FHyperTwistSpeechServiceHealth UHyperTwistContractLibrary::MakeMockSpeechService
|
|||
TEXT("promptHints"),
|
||||
TEXT("providerProfileCustody"),
|
||||
TEXT("byokCustody"),
|
||||
TEXT("providerRoutingPolicy"),
|
||||
TEXT("providerRouteSelection"),
|
||||
TEXT("workflowPolicyState"),
|
||||
TEXT("openAiCompatibleCustomEndpointProfile"),
|
||||
TEXT("userLabeledByokProfiles"),
|
||||
TEXT("downloadableModelPayloadCustody"),
|
||||
|
|
@ -1965,6 +2129,23 @@ FHyperTwistSpeechServiceHealth UHyperTwistContractLibrary::MakeMockSpeechService
|
|||
HyperTwistContractLibraryInternal::MakeDefaultSpeechByokCustodyProfile(
|
||||
Health.ByokCustodyProfileId
|
||||
);
|
||||
Health.ProviderRoutingPolicyId = TEXT("speech-provider-routing/local-offline-mock-first-v1");
|
||||
Health.ProviderRoutingPolicyDefinition =
|
||||
HyperTwistContractLibraryInternal::MakeMockSpeechProviderRoutingPolicy();
|
||||
Health.ProviderRouteDecision =
|
||||
HyperTwistContractLibraryInternal::MakeSpeechProviderRouteDecision(
|
||||
Health.ProviderRoutingPolicyDefinition,
|
||||
Health.ProviderProfileDefinition,
|
||||
TEXT("speech/python-service"),
|
||||
TEXT("mock-health-default"),
|
||||
TEXT("route-ready"),
|
||||
TEXT("mock-verification-route-selected"),
|
||||
FString(),
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true
|
||||
);
|
||||
Health.PayloadCustodyProfileId = TEXT("downloadable-model-payload-custody-v1");
|
||||
Health.PayloadCustodyProfileDefinition =
|
||||
HyperTwistContractLibraryInternal::MakeDefaultSpeechPayloadCustodyProfile(
|
||||
|
|
|
|||
|
|
@ -332,6 +332,9 @@ FHyperTwistSpeechServiceHealth UHyperTwistHttpSpeechClient::GetSpeechServiceHeal
|
|||
TEXT("promptHints"),
|
||||
TEXT("providerProfileCustody"),
|
||||
TEXT("byokCustody"),
|
||||
TEXT("providerRoutingPolicy"),
|
||||
TEXT("providerRouteSelection"),
|
||||
TEXT("workflowPolicyState"),
|
||||
TEXT("openAiCompatibleCustomEndpointProfile"),
|
||||
TEXT("userLabeledByokProfiles"),
|
||||
TEXT("downloadableModelPayloadCustody"),
|
||||
|
|
@ -358,6 +361,18 @@ FHyperTwistSpeechServiceHealth UHyperTwistHttpSpeechClient::GetSpeechServiceHeal
|
|||
Health.ProviderProfileDefinition.EndpointBaseUrl = ServiceBaseUrl;
|
||||
Health.ByokCustodyProfileId = ProviderDefaults.ByokCustodyProfileId;
|
||||
Health.ByokCustodyProfileDefinition = ProviderDefaults.ByokCustodyProfileDefinition;
|
||||
Health.ProviderRoutingPolicyId = ProviderDefaults.ProviderRoutingPolicyId;
|
||||
Health.ProviderRoutingPolicyDefinition = ProviderDefaults.ProviderRoutingPolicyDefinition;
|
||||
Health.ProviderRouteDecision = ProviderDefaults.ProviderRouteDecision;
|
||||
Health.ProviderRouteDecision.RouteStateId = ServiceBaseUrl.IsEmpty()
|
||||
? TEXT("route-awaiting-endpoint")
|
||||
: TEXT("route-health-degraded");
|
||||
Health.ProviderRouteDecision.DecisionReason = ServiceBaseUrl.IsEmpty()
|
||||
? TEXT("provider-backed-sidecar-route-unavailable")
|
||||
: TEXT("provider-backed-sidecar-health-degraded");
|
||||
Health.ProviderRouteDecision.FailureReason = LastTransportError;
|
||||
Health.ProviderRouteDecision.bUsedFallbackHealthPosture = true;
|
||||
Health.ProviderRouteDecision.bRouteReady = false;
|
||||
Health.LastError = LastTransportError;
|
||||
return Health;
|
||||
}
|
||||
|
|
@ -388,6 +403,9 @@ FHyperTwistSpeechServiceHealth UHyperTwistHttpSpeechClient::GetSpeechServiceHeal
|
|||
TEXT("promptHints"),
|
||||
TEXT("providerProfileCustody"),
|
||||
TEXT("byokCustody"),
|
||||
TEXT("providerRoutingPolicy"),
|
||||
TEXT("providerRouteSelection"),
|
||||
TEXT("workflowPolicyState"),
|
||||
TEXT("openAiCompatibleCustomEndpointProfile"),
|
||||
TEXT("userLabeledByokProfiles"),
|
||||
TEXT("downloadableModelPayloadCustody"),
|
||||
|
|
@ -404,6 +422,14 @@ FHyperTwistSpeechServiceHealth UHyperTwistHttpSpeechClient::GetSpeechServiceHeal
|
|||
Health.ProviderProfileDefinition.EndpointBaseUrl = ServiceBaseUrl;
|
||||
Health.ByokCustodyProfileId = ProviderDefaults.ByokCustodyProfileId;
|
||||
Health.ByokCustodyProfileDefinition = ProviderDefaults.ByokCustodyProfileDefinition;
|
||||
Health.ProviderRoutingPolicyId = ProviderDefaults.ProviderRoutingPolicyId;
|
||||
Health.ProviderRoutingPolicyDefinition = ProviderDefaults.ProviderRoutingPolicyDefinition;
|
||||
Health.ProviderRouteDecision = ProviderDefaults.ProviderRouteDecision;
|
||||
Health.ProviderRouteDecision.RouteStateId = TEXT("route-health-degraded");
|
||||
Health.ProviderRouteDecision.DecisionReason = TEXT("provider-backed-sidecar-health-degraded");
|
||||
Health.ProviderRouteDecision.FailureReason = LastTransportError;
|
||||
Health.ProviderRouteDecision.bUsedFallbackHealthPosture = true;
|
||||
Health.ProviderRouteDecision.bRouteReady = false;
|
||||
Health.LastError = LastTransportError;
|
||||
return Health;
|
||||
}
|
||||
|
|
@ -432,6 +458,9 @@ FHyperTwistSpeechServiceHealth UHyperTwistHttpSpeechClient::GetSpeechServiceHeal
|
|||
Health.Capabilities.AddUnique(TEXT("promptHints"));
|
||||
Health.Capabilities.AddUnique(TEXT("providerProfileCustody"));
|
||||
Health.Capabilities.AddUnique(TEXT("byokCustody"));
|
||||
Health.Capabilities.AddUnique(TEXT("providerRoutingPolicy"));
|
||||
Health.Capabilities.AddUnique(TEXT("providerRouteSelection"));
|
||||
Health.Capabilities.AddUnique(TEXT("workflowPolicyState"));
|
||||
Health.Capabilities.AddUnique(TEXT("openAiCompatibleCustomEndpointProfile"));
|
||||
Health.Capabilities.AddUnique(TEXT("userLabeledByokProfiles"));
|
||||
Health.Capabilities.AddUnique(TEXT("downloadableModelPayloadCustody"));
|
||||
|
|
@ -457,6 +486,18 @@ FHyperTwistSpeechServiceHealth UHyperTwistHttpSpeechClient::GetSpeechServiceHeal
|
|||
{
|
||||
Health.ByokCustodyProfileDefinition = ProviderDefaults.ByokCustodyProfileDefinition;
|
||||
}
|
||||
if (Health.ProviderRoutingPolicyId.IsEmpty())
|
||||
{
|
||||
Health.ProviderRoutingPolicyId = ProviderDefaults.ProviderRoutingPolicyId;
|
||||
}
|
||||
if (!Health.ProviderRoutingPolicyDefinition.IsStructurallyValid())
|
||||
{
|
||||
Health.ProviderRoutingPolicyDefinition = ProviderDefaults.ProviderRoutingPolicyDefinition;
|
||||
}
|
||||
if (!Health.ProviderRouteDecision.IsStructurallyValid())
|
||||
{
|
||||
Health.ProviderRouteDecision = ProviderDefaults.ProviderRouteDecision;
|
||||
}
|
||||
if (Health.PayloadCustodyProfileId.IsEmpty())
|
||||
{
|
||||
Health.PayloadCustodyProfileId = TEXT("downloadable-model-payload-custody-v1");
|
||||
|
|
|
|||
|
|
@ -138,6 +138,9 @@ FHyperTwistSpeechServiceHealth UHyperTwistMockSpeechClient::GetSpeechServiceHeal
|
|||
Health.Capabilities.AddUnique(TEXT("wordTimestamps"));
|
||||
Health.Capabilities.AddUnique(TEXT("languageDetection"));
|
||||
Health.Capabilities.AddUnique(TEXT("promptHints"));
|
||||
Health.Capabilities.AddUnique(TEXT("providerRoutingPolicy"));
|
||||
Health.Capabilities.AddUnique(TEXT("providerRouteSelection"));
|
||||
Health.Capabilities.AddUnique(TEXT("workflowPolicyState"));
|
||||
Health.Capabilities.AddUnique(TEXT("downloadableModelPayloadCustody"));
|
||||
Health.Capabilities.AddUnique(TEXT("payloadIntegrityReview"));
|
||||
Health.SupportedOrchestrationProfiles.AddUnique(TEXT("python-batch-transcribe-v1"));
|
||||
|
|
|
|||
|
|
@ -3057,6 +3057,46 @@ namespace HyperTwistTrainingSubsystemInternal
|
|||
};
|
||||
}
|
||||
|
||||
TArray<FString> BuildDefaultSpeechRoutingEligibleProviderClasses()
|
||||
{
|
||||
return {
|
||||
TEXT("official-direct-provider"),
|
||||
TEXT("openai-compatible-custom-endpoint"),
|
||||
TEXT("byok-endpoint"),
|
||||
TEXT("managed-gateway-provider"),
|
||||
TEXT("local-self-hosted-provider"),
|
||||
TEXT("bounded-speech-sidecar-service"),
|
||||
TEXT("first-party-mock-provider")
|
||||
};
|
||||
}
|
||||
|
||||
TArray<FString> BuildDefaultSpeechRoutingEligibleEndpointClasses()
|
||||
{
|
||||
return {
|
||||
TEXT("official-http-api"),
|
||||
TEXT("openai-compatible-http-api"),
|
||||
TEXT("managed-gateway-http"),
|
||||
TEXT("local-self-hosted-http"),
|
||||
TEXT("in-process-mock")
|
||||
};
|
||||
}
|
||||
|
||||
TArray<FString> BuildDefaultSpeechRoutingRequiredCapabilities()
|
||||
{
|
||||
return {
|
||||
TEXT("transcribe"),
|
||||
TEXT("grammarHints"),
|
||||
TEXT("manualTranscriptCommit")
|
||||
};
|
||||
}
|
||||
|
||||
TArray<FString> BuildDefaultSpeechRoutingSupportedTaskKinds()
|
||||
{
|
||||
return {
|
||||
TEXT("transcribe")
|
||||
};
|
||||
}
|
||||
|
||||
FHyperTwistSpeechProviderProfile BuildDefaultMockSpeechProviderProfile()
|
||||
{
|
||||
FHyperTwistSpeechProviderProfile Profile;
|
||||
|
|
@ -3104,6 +3144,110 @@ namespace HyperTwistTrainingSubsystemInternal
|
|||
return Profile;
|
||||
}
|
||||
|
||||
FHyperTwistSpeechProviderRoutingPolicy BuildDefaultMockSpeechProviderRoutingPolicy()
|
||||
{
|
||||
FHyperTwistSpeechProviderRoutingPolicy Policy;
|
||||
Policy.ProviderRoutingPolicyId = TEXT("speech-provider-routing/local-offline-mock-first-v1");
|
||||
Policy.PolicyKind = TEXT("speech-provider-routing");
|
||||
Policy.RouteSelectionMode = TEXT("local-offline-mock-first");
|
||||
Policy.FallbackMode = TEXT("fail-closed");
|
||||
Policy.WorkflowPolicyState = TEXT("first-party-provider-policy-governed");
|
||||
Policy.FailureEscalationMode = TEXT("preserve-local-verification-route");
|
||||
Policy.UserOverridePosture = TEXT("client-kind-and-profile-override-supported");
|
||||
Policy.EligibleProviderClasses = BuildDefaultSpeechRoutingEligibleProviderClasses();
|
||||
Policy.EligibleEndpointClasses = BuildDefaultSpeechRoutingEligibleEndpointClasses();
|
||||
Policy.RequiredCapabilityFlags = BuildDefaultSpeechRoutingRequiredCapabilities();
|
||||
Policy.SupportedTaskKinds = BuildDefaultSpeechRoutingSupportedTaskKinds();
|
||||
Policy.bAllowProviderBackedRoutes = false;
|
||||
Policy.bAllowMockVerificationRoutes = true;
|
||||
Policy.bAllowOpenAiCompatibleCustomEndpointRoutes = true;
|
||||
Policy.bAllowUserLabeledByokRoutes = true;
|
||||
Policy.bAllowManagedGatewayRoutes = true;
|
||||
Policy.bAllowLocalSelfHostedRoutes = true;
|
||||
Policy.bRespectsProfileEnableDisable = true;
|
||||
Policy.bAllowFailClosedWhenNoEligibleRoute = true;
|
||||
Policy.bAllowHealthPostureFallback = false;
|
||||
Policy.bPreservesFirstPartyRoutingOwnership = true;
|
||||
Policy.bAllowsDonorOwnedRoutingLanguage = false;
|
||||
return Policy;
|
||||
}
|
||||
|
||||
FHyperTwistSpeechProviderRoutingPolicy BuildDefaultProviderBackedSpeechProviderRoutingPolicy()
|
||||
{
|
||||
FHyperTwistSpeechProviderRoutingPolicy Policy;
|
||||
Policy.ProviderRoutingPolicyId = TEXT("speech-provider-routing/provider-backed-sidecar-first-v1");
|
||||
Policy.PolicyKind = TEXT("speech-provider-routing");
|
||||
Policy.RouteSelectionMode = TEXT("provider-backed-sidecar-first");
|
||||
Policy.FallbackMode = TEXT("health-posture-only");
|
||||
Policy.WorkflowPolicyState = TEXT("first-party-provider-policy-governed");
|
||||
Policy.FailureEscalationMode = TEXT("fail-closed-and-report-health");
|
||||
Policy.UserOverridePosture = TEXT("profile-or-client-kind-override-supported");
|
||||
Policy.EligibleProviderClasses = BuildDefaultSpeechRoutingEligibleProviderClasses();
|
||||
Policy.EligibleEndpointClasses = BuildDefaultSpeechRoutingEligibleEndpointClasses();
|
||||
Policy.RequiredCapabilityFlags = BuildDefaultSpeechRoutingRequiredCapabilities();
|
||||
Policy.SupportedTaskKinds = BuildDefaultSpeechRoutingSupportedTaskKinds();
|
||||
Policy.bAllowProviderBackedRoutes = true;
|
||||
Policy.bAllowMockVerificationRoutes = true;
|
||||
Policy.bAllowOpenAiCompatibleCustomEndpointRoutes = true;
|
||||
Policy.bAllowUserLabeledByokRoutes = true;
|
||||
Policy.bAllowManagedGatewayRoutes = true;
|
||||
Policy.bAllowLocalSelfHostedRoutes = true;
|
||||
Policy.bRespectsProfileEnableDisable = true;
|
||||
Policy.bAllowFailClosedWhenNoEligibleRoute = true;
|
||||
Policy.bAllowHealthPostureFallback = true;
|
||||
Policy.bPreservesFirstPartyRoutingOwnership = true;
|
||||
Policy.bAllowsDonorOwnedRoutingLanguage = false;
|
||||
return Policy;
|
||||
}
|
||||
|
||||
FHyperTwistSpeechProviderRouteDecision BuildSpeechProviderRouteDecision(
|
||||
const FHyperTwistSpeechProviderRoutingPolicy& Policy,
|
||||
const FHyperTwistSpeechProviderProfile& Profile,
|
||||
const FString& SelectedServiceLaneId,
|
||||
const FString& DecisionSource,
|
||||
const FString& RouteStateId,
|
||||
const FString& DecisionReason,
|
||||
const FString& FailureReason,
|
||||
const bool bProviderBackedRouteRequested,
|
||||
const bool bProviderBackedRouteSelected,
|
||||
const bool bUsedFallbackHealthPosture,
|
||||
const bool bRouteReady
|
||||
)
|
||||
{
|
||||
FHyperTwistSpeechProviderRouteDecision Decision;
|
||||
Decision.RouteDecisionId = FString::Printf(
|
||||
TEXT("speech-route-decision/%s"),
|
||||
*Profile.ProviderProfileId
|
||||
);
|
||||
Decision.ProviderRoutingPolicyId = Policy.ProviderRoutingPolicyId;
|
||||
Decision.DecisionSource = DecisionSource;
|
||||
Decision.RequestedProviderProfileId = Profile.ProviderProfileId;
|
||||
Decision.SelectedProviderProfileId = Profile.ProviderProfileId;
|
||||
Decision.SelectedProviderClass = Profile.ProviderClass;
|
||||
Decision.SelectedEndpointClass = Profile.EndpointClass;
|
||||
Decision.SelectedServiceLaneId = SelectedServiceLaneId.IsEmpty()
|
||||
? TEXT("speech/python-service")
|
||||
: SelectedServiceLaneId;
|
||||
Decision.SelectedTransportKind = Profile.EndpointClass.Equals(TEXT("in-process-mock"), ESearchCase::IgnoreCase)
|
||||
? TEXT("in-process")
|
||||
: TEXT("http");
|
||||
Decision.RouteStateId = RouteStateId;
|
||||
Decision.DecisionReason = DecisionReason;
|
||||
Decision.FailureReason = FailureReason;
|
||||
Decision.FallbackMode = Policy.FallbackMode;
|
||||
Decision.bProviderBackedRouteRequested = bProviderBackedRouteRequested;
|
||||
Decision.bProviderBackedRouteSelected = bProviderBackedRouteSelected;
|
||||
Decision.bUsedFallbackHealthPosture = bUsedFallbackHealthPosture;
|
||||
Decision.bSelectedProfileEnabled = Profile.bEnabled;
|
||||
Decision.bSelectedCustomEndpointRoute =
|
||||
Profile.bUserLabeled
|
||||
&& Profile.bSupportsCustomBaseUrl
|
||||
&& !Profile.EndpointBaseUrl.IsEmpty()
|
||||
&& !Profile.EndpointBaseUrl.Contains(TEXT("127.0.0.1"), ESearchCase::IgnoreCase);
|
||||
Decision.bRouteReady = bRouteReady;
|
||||
return Decision;
|
||||
}
|
||||
|
||||
FHyperTwistSpeechByokCustodyProfile BuildDefaultSpeechByokCustodyProfile(const FString& ProfileId)
|
||||
{
|
||||
FHyperTwistSpeechByokCustodyProfile Profile;
|
||||
|
|
@ -3213,6 +3357,88 @@ namespace HyperTwistTrainingSubsystemInternal
|
|||
SessionConfig.ByokCustodyProfileId = SessionConfig.ByokCustodyProfileDefinition.ByokCustodyProfileId;
|
||||
}
|
||||
|
||||
void ApplySpeechProviderRoutingDefaults(
|
||||
FHyperTwistSpeechSessionConfig& SessionConfig,
|
||||
const bool bUseMockClient
|
||||
)
|
||||
{
|
||||
if (SessionConfig.ProviderRoutingPolicyId.IsEmpty()
|
||||
&& SessionConfig.ProviderRoutingPolicyDefinition.IsStructurallyValid())
|
||||
{
|
||||
SessionConfig.ProviderRoutingPolicyId =
|
||||
SessionConfig.ProviderRoutingPolicyDefinition.ProviderRoutingPolicyId;
|
||||
}
|
||||
if (SessionConfig.ProviderRoutingPolicyId.IsEmpty())
|
||||
{
|
||||
SessionConfig.ProviderRoutingPolicyId = bUseMockClient
|
||||
? TEXT("speech-provider-routing/local-offline-mock-first-v1")
|
||||
: TEXT("speech-provider-routing/provider-backed-sidecar-first-v1");
|
||||
}
|
||||
if (!SessionConfig.ProviderRoutingPolicyDefinition.IsStructurallyValid())
|
||||
{
|
||||
SessionConfig.ProviderRoutingPolicyDefinition = bUseMockClient
|
||||
? BuildDefaultMockSpeechProviderRoutingPolicy()
|
||||
: BuildDefaultProviderBackedSpeechProviderRoutingPolicy();
|
||||
}
|
||||
SessionConfig.ProviderRoutingPolicyId =
|
||||
SessionConfig.ProviderRoutingPolicyDefinition.ProviderRoutingPolicyId;
|
||||
|
||||
const FHyperTwistSpeechProviderProfile EffectiveProfile =
|
||||
SessionConfig.ProviderProfileDefinition.IsStructurallyValid()
|
||||
? SessionConfig.ProviderProfileDefinition
|
||||
: (bUseMockClient
|
||||
? BuildDefaultMockSpeechProviderProfile()
|
||||
: BuildDefaultHttpSpeechProviderProfile(
|
||||
TEXT("Local HTTP Speech Sidecar"),
|
||||
TEXT("http://127.0.0.1:8766")
|
||||
));
|
||||
const FString SelectedServiceLaneId = SessionConfig.OrchestrationProfile.ServiceLaneId;
|
||||
|
||||
FString RouteStateId;
|
||||
FString DecisionReason;
|
||||
FString FailureReason;
|
||||
bool bRouteReady = true;
|
||||
|
||||
if (!EffectiveProfile.bEnabled)
|
||||
{
|
||||
RouteStateId = TEXT("route-disabled");
|
||||
DecisionReason = TEXT("selected-provider-profile-disabled");
|
||||
FailureReason = TEXT("selected-provider-profile-disabled");
|
||||
bRouteReady = false;
|
||||
}
|
||||
else if (bUseMockClient)
|
||||
{
|
||||
RouteStateId = TEXT("route-ready");
|
||||
DecisionReason = TEXT("mock-verification-route-selected");
|
||||
}
|
||||
else if (EffectiveProfile.EndpointBaseUrl.IsEmpty())
|
||||
{
|
||||
RouteStateId = TEXT("route-awaiting-endpoint");
|
||||
DecisionReason = TEXT("provider-backed-sidecar-route-unavailable");
|
||||
FailureReason = TEXT("service-base-url-missing");
|
||||
bRouteReady = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
RouteStateId = TEXT("route-ready");
|
||||
DecisionReason = TEXT("provider-backed-sidecar-route-selected");
|
||||
}
|
||||
|
||||
SessionConfig.ProviderRouteDecision = BuildSpeechProviderRouteDecision(
|
||||
SessionConfig.ProviderRoutingPolicyDefinition,
|
||||
EffectiveProfile,
|
||||
SelectedServiceLaneId,
|
||||
TEXT("session-config-default"),
|
||||
RouteStateId,
|
||||
DecisionReason,
|
||||
FailureReason,
|
||||
!bUseMockClient,
|
||||
!bUseMockClient,
|
||||
false,
|
||||
bRouteReady
|
||||
);
|
||||
}
|
||||
|
||||
void ApplySpeechPayloadCustodyDefaults(FHyperTwistSpeechSessionConfig& SessionConfig)
|
||||
{
|
||||
if (SessionConfig.PayloadCustodyProfileId.IsEmpty())
|
||||
|
|
@ -3277,6 +3503,130 @@ namespace HyperTwistTrainingSubsystemInternal
|
|||
Health.Capabilities.AddUnique(TEXT("userLabeledByokProfiles"));
|
||||
}
|
||||
|
||||
void ApplySpeechProviderRoutingHealthDefaults(
|
||||
FHyperTwistSpeechServiceHealth& Health,
|
||||
const FHyperTwistSpeechSessionConfig* SessionConfig,
|
||||
const bool bUseProviderBackedClient,
|
||||
const FString& LastError
|
||||
)
|
||||
{
|
||||
if (Health.ProviderRoutingPolicyId.IsEmpty()
|
||||
&& Health.ProviderRoutingPolicyDefinition.IsStructurallyValid())
|
||||
{
|
||||
Health.ProviderRoutingPolicyId =
|
||||
Health.ProviderRoutingPolicyDefinition.ProviderRoutingPolicyId;
|
||||
}
|
||||
if (Health.ProviderRoutingPolicyId.IsEmpty())
|
||||
{
|
||||
Health.ProviderRoutingPolicyId = bUseProviderBackedClient
|
||||
? TEXT("speech-provider-routing/provider-backed-sidecar-first-v1")
|
||||
: TEXT("speech-provider-routing/local-offline-mock-first-v1");
|
||||
}
|
||||
if (!Health.ProviderRoutingPolicyDefinition.IsStructurallyValid())
|
||||
{
|
||||
Health.ProviderRoutingPolicyDefinition = bUseProviderBackedClient
|
||||
? BuildDefaultProviderBackedSpeechProviderRoutingPolicy()
|
||||
: BuildDefaultMockSpeechProviderRoutingPolicy();
|
||||
}
|
||||
Health.ProviderRoutingPolicyId = Health.ProviderRoutingPolicyDefinition.ProviderRoutingPolicyId;
|
||||
|
||||
const FHyperTwistSpeechProviderProfile EffectiveProfile =
|
||||
Health.ProviderProfileDefinition.IsStructurallyValid()
|
||||
? Health.ProviderProfileDefinition
|
||||
: (SessionConfig != nullptr && SessionConfig->ProviderProfileDefinition.IsStructurallyValid()
|
||||
? SessionConfig->ProviderProfileDefinition
|
||||
: (bUseProviderBackedClient
|
||||
? BuildDefaultHttpSpeechProviderProfile(
|
||||
Health.ProviderLabel,
|
||||
Health.ServiceEndpoint
|
||||
)
|
||||
: BuildDefaultMockSpeechProviderProfile()));
|
||||
const FString EffectiveRouteError = !LastError.IsEmpty() ? LastError : Health.LastError;
|
||||
const FString SelectedServiceLaneId =
|
||||
SessionConfig != nullptr
|
||||
&& !SessionConfig->OrchestrationProfile.ServiceLaneId.IsEmpty()
|
||||
? SessionConfig->OrchestrationProfile.ServiceLaneId
|
||||
: TEXT("speech/python-service");
|
||||
|
||||
FString RouteStateId;
|
||||
FString DecisionReason;
|
||||
FString FailureReason;
|
||||
bool bRouteReady = true;
|
||||
bool bUsedFallbackHealthPosture = false;
|
||||
|
||||
if (!EffectiveProfile.bEnabled)
|
||||
{
|
||||
RouteStateId = TEXT("route-disabled");
|
||||
DecisionReason = TEXT("selected-provider-profile-disabled");
|
||||
FailureReason = TEXT("selected-provider-profile-disabled");
|
||||
bRouteReady = false;
|
||||
}
|
||||
else if (!bUseProviderBackedClient)
|
||||
{
|
||||
if (!Health.bReady && !EffectiveRouteError.IsEmpty())
|
||||
{
|
||||
RouteStateId = TEXT("route-health-degraded");
|
||||
DecisionReason = TEXT("mock-verification-route-health-degraded");
|
||||
FailureReason = EffectiveRouteError;
|
||||
bRouteReady = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
RouteStateId = TEXT("route-ready");
|
||||
DecisionReason = TEXT("mock-verification-route-selected");
|
||||
}
|
||||
}
|
||||
else if (EffectiveRouteError == TEXT("no-active-training-run"))
|
||||
{
|
||||
RouteStateId = TEXT("route-idle");
|
||||
DecisionReason = TEXT("provider-backed-route-idle");
|
||||
FailureReason = EffectiveRouteError;
|
||||
bRouteReady = false;
|
||||
bUsedFallbackHealthPosture = true;
|
||||
}
|
||||
else if (EffectiveProfile.EndpointBaseUrl.IsEmpty()
|
||||
|| EffectiveRouteError == TEXT("service-base-url-missing"))
|
||||
{
|
||||
RouteStateId = TEXT("route-awaiting-endpoint");
|
||||
DecisionReason = TEXT("provider-backed-sidecar-route-unavailable");
|
||||
FailureReason = TEXT("service-base-url-missing");
|
||||
bRouteReady = false;
|
||||
bUsedFallbackHealthPosture = true;
|
||||
}
|
||||
else if (!Health.bReady || !EffectiveRouteError.IsEmpty())
|
||||
{
|
||||
RouteStateId = TEXT("route-health-degraded");
|
||||
DecisionReason = TEXT("provider-backed-sidecar-health-degraded");
|
||||
FailureReason = !EffectiveRouteError.IsEmpty()
|
||||
? EffectiveRouteError
|
||||
: TEXT("provider-route-unready");
|
||||
bRouteReady = false;
|
||||
bUsedFallbackHealthPosture = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
RouteStateId = TEXT("route-ready");
|
||||
DecisionReason = TEXT("provider-backed-sidecar-route-selected");
|
||||
}
|
||||
|
||||
Health.ProviderRouteDecision = BuildSpeechProviderRouteDecision(
|
||||
Health.ProviderRoutingPolicyDefinition,
|
||||
EffectiveProfile,
|
||||
SelectedServiceLaneId,
|
||||
TEXT("service-health-refresh"),
|
||||
RouteStateId,
|
||||
DecisionReason,
|
||||
FailureReason,
|
||||
bUseProviderBackedClient,
|
||||
bUseProviderBackedClient,
|
||||
bUsedFallbackHealthPosture,
|
||||
bRouteReady
|
||||
);
|
||||
Health.Capabilities.AddUnique(TEXT("providerRoutingPolicy"));
|
||||
Health.Capabilities.AddUnique(TEXT("providerRouteSelection"));
|
||||
Health.Capabilities.AddUnique(TEXT("workflowPolicyState"));
|
||||
}
|
||||
|
||||
void ApplySpeechPayloadCustodyHealthDefaults(FHyperTwistSpeechServiceHealth& Health)
|
||||
{
|
||||
if (Health.PayloadCustodyProfileId.IsEmpty())
|
||||
|
|
@ -9747,6 +10097,10 @@ FHyperTwistSpeechSessionConfig UHyperTwistTrainingSubsystem::BuildActiveCompanio
|
|||
SessionConfig,
|
||||
bUseMockClient
|
||||
);
|
||||
HyperTwistTrainingSubsystemInternal::ApplySpeechProviderRoutingDefaults(
|
||||
SessionConfig,
|
||||
bUseMockClient
|
||||
);
|
||||
return SessionConfig;
|
||||
}
|
||||
|
||||
|
|
@ -9868,6 +10222,10 @@ FHyperTwistSpeechSessionConfig UHyperTwistTrainingSubsystem::BuildActiveCompanio
|
|||
SessionConfig,
|
||||
bUseMockClient
|
||||
);
|
||||
HyperTwistTrainingSubsystemInternal::ApplySpeechProviderRoutingDefaults(
|
||||
SessionConfig,
|
||||
bUseMockClient
|
||||
);
|
||||
|
||||
return SessionConfig;
|
||||
}
|
||||
|
|
@ -9947,6 +10305,12 @@ void UHyperTwistTrainingSubsystem::RefreshCompanionSpeechServiceHealth()
|
|||
ActiveCompanionSpeechSessionState.ServiceHealth,
|
||||
ActiveCompanionSpeechSessionState.bUsingProviderBackedClient
|
||||
);
|
||||
HyperTwistTrainingSubsystemInternal::ApplySpeechProviderRoutingHealthDefaults(
|
||||
ActiveCompanionSpeechSessionState.ServiceHealth,
|
||||
&ActiveCompanionSpeechSessionState.SessionConfig,
|
||||
ActiveCompanionSpeechSessionState.bUsingProviderBackedClient,
|
||||
ActiveCompanionSpeechSessionState.LastError
|
||||
);
|
||||
HyperTwistTrainingSubsystemInternal::ApplySpeechPayloadCustodyHealthDefaults(
|
||||
ActiveCompanionSpeechSessionState.ServiceHealth
|
||||
);
|
||||
|
|
@ -9961,6 +10325,12 @@ void UHyperTwistTrainingSubsystem::RefreshCompanionSpeechServiceHealth()
|
|||
ActiveCompanionSpeechSessionState.ServiceHealth,
|
||||
ActiveCompanionSpeechSessionState.bUsingProviderBackedClient
|
||||
);
|
||||
HyperTwistTrainingSubsystemInternal::ApplySpeechProviderRoutingHealthDefaults(
|
||||
ActiveCompanionSpeechSessionState.ServiceHealth,
|
||||
&ActiveCompanionSpeechSessionState.SessionConfig,
|
||||
ActiveCompanionSpeechSessionState.bUsingProviderBackedClient,
|
||||
ActiveCompanionSpeechSessionState.LastError
|
||||
);
|
||||
HyperTwistTrainingSubsystemInternal::ApplySpeechPayloadCustodyHealthDefaults(
|
||||
ActiveCompanionSpeechSessionState.ServiceHealth
|
||||
);
|
||||
|
|
|
|||
|
|
@ -2104,6 +2104,209 @@ struct FHyperTwistSpeechByokCustodyProfile
|
|||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistSpeechProviderRoutingPolicy
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString ProviderRoutingPolicyId = TEXT("speech-provider-routing/provider-backed-sidecar-first-v1");
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString PolicyKind = TEXT("speech-provider-routing");
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString RouteSelectionMode = TEXT("provider-backed-sidecar-first");
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString FallbackMode = TEXT("health-posture-only");
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString WorkflowPolicyState = TEXT("first-party-provider-policy-governed");
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString FailureEscalationMode = TEXT("fail-closed-and-report-health");
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString UserOverridePosture = TEXT("profile-or-client-kind-override-supported");
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
TArray<FString> EligibleProviderClasses;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
TArray<FString> EligibleEndpointClasses;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
TArray<FString> RequiredCapabilityFlags;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
TArray<FString> SupportedTaskKinds;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bAllowProviderBackedRoutes = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bAllowMockVerificationRoutes = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bAllowOpenAiCompatibleCustomEndpointRoutes = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bAllowUserLabeledByokRoutes = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bAllowManagedGatewayRoutes = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bAllowLocalSelfHostedRoutes = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bRespectsProfileEnableDisable = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bAllowFailClosedWhenNoEligibleRoute = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bAllowHealthPostureFallback = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bPreservesFirstPartyRoutingOwnership = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bAllowsDonorOwnedRoutingLanguage = false;
|
||||
|
||||
bool IsStructurallyValid() const
|
||||
{
|
||||
if (ProviderRoutingPolicyId.IsEmpty()
|
||||
|| PolicyKind.IsEmpty()
|
||||
|| RouteSelectionMode.IsEmpty()
|
||||
|| FallbackMode.IsEmpty()
|
||||
|| WorkflowPolicyState.IsEmpty()
|
||||
|| FailureEscalationMode.IsEmpty()
|
||||
|| UserOverridePosture.IsEmpty()
|
||||
|| EligibleProviderClasses.Num() <= 0
|
||||
|| EligibleEndpointClasses.Num() <= 0
|
||||
|| RequiredCapabilityFlags.Num() <= 0
|
||||
|| SupportedTaskKinds.Num() <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const FString& ProviderClassId : EligibleProviderClasses)
|
||||
{
|
||||
if (ProviderClassId.IsEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (const FString& EndpointClassId : EligibleEndpointClasses)
|
||||
{
|
||||
if (EndpointClassId.IsEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (const FString& CapabilityFlag : RequiredCapabilityFlags)
|
||||
{
|
||||
if (CapabilityFlag.IsEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (const FString& TaskKindId : SupportedTaskKinds)
|
||||
{
|
||||
if (TaskKindId.IsEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistSpeechProviderRouteDecision
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString RouteDecisionId = TEXT("speech-route-decision/provider-backed-sidecar");
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString ProviderRoutingPolicyId = TEXT("speech-provider-routing/provider-backed-sidecar-first-v1");
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString DecisionSource = TEXT("session-config-default");
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString RequestedProviderProfileId = TEXT("speech-provider/local-http-sidecar-profile-v1");
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString SelectedProviderProfileId = TEXT("speech-provider/local-http-sidecar-profile-v1");
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString SelectedProviderClass = TEXT("bounded-speech-sidecar-service");
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString SelectedEndpointClass = TEXT("local-self-hosted-http");
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString SelectedServiceLaneId = TEXT("speech/python-service");
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString SelectedTransportKind = TEXT("http");
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString RouteStateId = TEXT("route-ready");
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString DecisionReason = TEXT("provider-backed-sidecar-route-selected");
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString FailureReason;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString FallbackMode = TEXT("health-posture-only");
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bProviderBackedRouteRequested = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bProviderBackedRouteSelected = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bUsedFallbackHealthPosture = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bSelectedProfileEnabled = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bSelectedCustomEndpointRoute = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bRouteReady = true;
|
||||
|
||||
bool IsStructurallyValid() const
|
||||
{
|
||||
return !RouteDecisionId.IsEmpty()
|
||||
&& !ProviderRoutingPolicyId.IsEmpty()
|
||||
&& !DecisionSource.IsEmpty()
|
||||
&& !RequestedProviderProfileId.IsEmpty()
|
||||
&& !SelectedProviderProfileId.IsEmpty()
|
||||
&& !SelectedProviderClass.IsEmpty()
|
||||
&& !SelectedEndpointClass.IsEmpty()
|
||||
&& !SelectedServiceLaneId.IsEmpty()
|
||||
&& !SelectedTransportKind.IsEmpty()
|
||||
&& !RouteStateId.IsEmpty()
|
||||
&& !DecisionReason.IsEmpty()
|
||||
&& !FallbackMode.IsEmpty();
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistSpeechSessionConfig
|
||||
{
|
||||
|
|
@ -2154,6 +2357,15 @@ struct FHyperTwistSpeechSessionConfig
|
|||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FHyperTwistSpeechByokCustodyProfile ByokCustodyProfileDefinition;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString ProviderRoutingPolicyId = TEXT("speech-provider-routing/provider-backed-sidecar-first-v1");
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FHyperTwistSpeechProviderRoutingPolicy ProviderRoutingPolicyDefinition;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FHyperTwistSpeechProviderRouteDecision ProviderRouteDecision;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString PayloadCustodyProfileId = TEXT("downloadable-model-payload-custody-v1");
|
||||
|
||||
|
|
@ -2193,6 +2405,9 @@ struct FHyperTwistSpeechSessionConfig
|
|||
|| !ProviderProfileDefinition.IsStructurallyValid()
|
||||
|| ByokCustodyProfileId.IsEmpty()
|
||||
|| !ByokCustodyProfileDefinition.IsStructurallyValid()
|
||||
|| ProviderRoutingPolicyId.IsEmpty()
|
||||
|| !ProviderRoutingPolicyDefinition.IsStructurallyValid()
|
||||
|| !ProviderRouteDecision.IsStructurallyValid()
|
||||
|| PayloadCustodyProfileId.IsEmpty()
|
||||
|| !PayloadCustodyProfileDefinition.IsStructurallyValid()
|
||||
|| RequiredModelPayloads.Num() <= 0
|
||||
|
|
@ -2433,6 +2648,15 @@ struct FHyperTwistSpeechServiceHealth
|
|||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FHyperTwistSpeechByokCustodyProfile ByokCustodyProfileDefinition;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString ProviderRoutingPolicyId = TEXT("speech-provider-routing/provider-backed-sidecar-first-v1");
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FHyperTwistSpeechProviderRoutingPolicy ProviderRoutingPolicyDefinition;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FHyperTwistSpeechProviderRouteDecision ProviderRouteDecision;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString PayloadCustodyProfileId = TEXT("downloadable-model-payload-custody-v1");
|
||||
|
||||
|
|
@ -2459,6 +2683,9 @@ struct FHyperTwistSpeechServiceHealth
|
|||
|| !ProviderProfileDefinition.IsStructurallyValid()
|
||||
|| ByokCustodyProfileId.IsEmpty()
|
||||
|| !ByokCustodyProfileDefinition.IsStructurallyValid()
|
||||
|| ProviderRoutingPolicyId.IsEmpty()
|
||||
|| !ProviderRoutingPolicyDefinition.IsStructurallyValid()
|
||||
|| !ProviderRouteDecision.IsStructurallyValid()
|
||||
|| PayloadCustodyProfileId.IsEmpty()
|
||||
|| !PayloadCustodyProfileDefinition.IsStructurallyValid())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,251 @@
|
|||
// Copyright HyperTwist, Inc. All Rights Reserved.
|
||||
|
||||
#include "Misc/AutomationTest.h"
|
||||
|
||||
#include "Engine/GameInstance.h"
|
||||
#include "HyperTwistRecognition/HyperTwistSpeechClient.h"
|
||||
#include "HyperTwistTraining/HyperTwistTrainingSubsystem.h"
|
||||
#include "UObject/UnrealType.h"
|
||||
|
||||
#if WITH_AUTOMATION_TESTS
|
||||
|
||||
namespace HyperTwistWhisperCppPhase6RYTestInternal
|
||||
{
|
||||
FHyperTwistTrainingDeck MakeSpeechDeck()
|
||||
{
|
||||
FHyperTwistTrainingDeck Deck;
|
||||
Deck.DeckId = TEXT("phase6r-y/provider-routing-policy");
|
||||
Deck.Title = TEXT("Phase 6R-Y Provider Routing And Policy");
|
||||
Deck.DeliveryModes = {
|
||||
EHyperTwistTrainingDeliveryMode::CoachReviewed
|
||||
};
|
||||
|
||||
FHyperTwistTrainingCase TrainingCase;
|
||||
TrainingCase.CaseId = TEXT("phase6r-y-case");
|
||||
TrainingCase.PuzzleId = TEXT("cube/3x3x3");
|
||||
TrainingCase.PromptKind = EHyperTwistTrainingPromptKind::Sequence;
|
||||
TrainingCase.PromptLabel = TEXT("Phase 6R-Y Coach Speech");
|
||||
TrainingCase.AllowedDeliveryModes = {
|
||||
EHyperTwistTrainingDeliveryMode::CoachReviewed
|
||||
};
|
||||
Deck.Cases = {TrainingCase};
|
||||
return Deck;
|
||||
}
|
||||
|
||||
void ForceSpeechClientKind(UHyperTwistTrainingSubsystem* TrainingSubsystem, const FString& ClientKind)
|
||||
{
|
||||
if (TrainingSubsystem == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (FStrProperty* SpeechClientKindProperty = FindFProperty<FStrProperty>(
|
||||
UHyperTwistTrainingSubsystem::StaticClass(),
|
||||
TEXT("CompanionSpeechClientKind")
|
||||
))
|
||||
{
|
||||
SpeechClientKindProperty->SetPropertyValue_InContainer(TrainingSubsystem, ClientKind);
|
||||
}
|
||||
}
|
||||
|
||||
UHyperTwistTrainingSubsystem* MakeSpeechSubsystem(const FString& SessionId, const FString& ClientKind)
|
||||
{
|
||||
UGameInstance* GameInstance = NewObject<UGameInstance>(GetTransientPackage());
|
||||
if (GameInstance == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UHyperTwistTrainingSubsystem* TrainingSubsystem = NewObject<UHyperTwistTrainingSubsystem>(GameInstance);
|
||||
if (TrainingSubsystem == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ForceSpeechClientKind(TrainingSubsystem, ClientKind);
|
||||
const FHyperTwistTrainingRunState RunState = TrainingSubsystem->StartTrainingRunFromDeck(
|
||||
MakeSpeechDeck(),
|
||||
TEXT("phase6r-y-user"),
|
||||
SessionId,
|
||||
EHyperTwistTrainingDeliveryMode::CoachReviewed
|
||||
);
|
||||
return RunState.IsStructurallyValid() ? TrainingSubsystem : nullptr;
|
||||
}
|
||||
|
||||
UHyperTwistHttpSpeechClient* ResolveHttpSpeechClient(UHyperTwistTrainingSubsystem* TrainingSubsystem)
|
||||
{
|
||||
if (TrainingSubsystem == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FString CloseError;
|
||||
TrainingSubsystem->CloseActiveCompanionSpeechSession(CloseError);
|
||||
|
||||
if (FObjectPropertyBase* ClientProperty = FindFProperty<FObjectPropertyBase>(
|
||||
UHyperTwistTrainingSubsystem::StaticClass(),
|
||||
TEXT("ActiveCompanionSpeechClientObject")
|
||||
))
|
||||
{
|
||||
return Cast<UHyperTwistHttpSpeechClient>(
|
||||
ClientProperty->GetObjectPropertyValue_InContainer(TrainingSubsystem)
|
||||
);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
|
||||
FHyperTwistWhisperCppPhase6RYProviderRoutingSessionConfigTest,
|
||||
"HyperTwist.Permissive.WhisperCpp.Phase6R.Y.ProviderRoutingPolicySessionConfig",
|
||||
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
|
||||
)
|
||||
|
||||
bool FHyperTwistWhisperCppPhase6RYProviderRoutingSessionConfigTest::RunTest(const FString& Parameters)
|
||||
{
|
||||
UHyperTwistTrainingSubsystem* TrainingSubsystem =
|
||||
HyperTwistWhisperCppPhase6RYTestInternal::MakeSpeechSubsystem(
|
||||
TEXT("phase6r-y-config-session"),
|
||||
TEXT("mock")
|
||||
);
|
||||
TestNotNull(TEXT("The speech subsystem must be constructed for Phase 6R-Y."), TrainingSubsystem);
|
||||
if (TrainingSubsystem == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
FString OpenError;
|
||||
TestTrue(TEXT("The mock provider-routing route must open a speech session."), TrainingSubsystem->OpenActiveCompanionSpeechSession(OpenError));
|
||||
TestTrue(TEXT("Opening the mock provider-routing speech session must not report an error."), OpenError.IsEmpty());
|
||||
|
||||
const FHyperTwistSpeechSessionConfig& Config =
|
||||
TrainingSubsystem->GetActiveCompanionSpeechSessionState().SessionConfig;
|
||||
|
||||
TestTrue(TEXT("The provider-routing session config must remain structurally valid."), Config.IsStructurallyValid());
|
||||
TestEqual(TEXT("The mock route must preserve the mock routing policy id."), Config.ProviderRoutingPolicyId, TEXT("speech-provider-routing/local-offline-mock-first-v1"));
|
||||
TestTrue(TEXT("The routing policy definition must remain structurally valid."), Config.ProviderRoutingPolicyDefinition.IsStructurallyValid());
|
||||
TestEqual(TEXT("The mock route must keep the local-offline selection mode."), Config.ProviderRoutingPolicyDefinition.RouteSelectionMode, TEXT("local-offline-mock-first"));
|
||||
TestFalse(TEXT("The mock route must not request provider-backed routing as its primary posture."), Config.ProviderRoutingPolicyDefinition.bAllowProviderBackedRoutes);
|
||||
TestTrue(TEXT("The mock route must preserve mock verification routing."), Config.ProviderRoutingPolicyDefinition.bAllowMockVerificationRoutes);
|
||||
TestTrue(TEXT("The routing policy must preserve first-party ownership."), Config.ProviderRoutingPolicyDefinition.bPreservesFirstPartyRoutingOwnership);
|
||||
TestFalse(TEXT("The routing policy must not allow donor-owned routing language."), Config.ProviderRoutingPolicyDefinition.bAllowsDonorOwnedRoutingLanguage);
|
||||
|
||||
TestTrue(TEXT("The mock route decision must remain structurally valid."), Config.ProviderRouteDecision.IsStructurallyValid());
|
||||
TestEqual(TEXT("The mock route decision must target the mock provider profile."), Config.ProviderRouteDecision.SelectedProviderProfileId, TEXT("speech-provider/mock-offline-profile-v1"));
|
||||
TestEqual(TEXT("The mock route decision must preserve the in-process transport."), Config.ProviderRouteDecision.SelectedTransportKind, TEXT("in-process"));
|
||||
TestEqual(TEXT("The mock route decision must keep the orchestration service lane."), Config.ProviderRouteDecision.SelectedServiceLaneId, TEXT("speech/python-service"));
|
||||
TestEqual(TEXT("The mock route decision must report a ready route."), Config.ProviderRouteDecision.RouteStateId, TEXT("route-ready"));
|
||||
TestEqual(TEXT("The mock route decision must expose the expected reason."), Config.ProviderRouteDecision.DecisionReason, TEXT("mock-verification-route-selected"));
|
||||
TestFalse(TEXT("The mock route decision must not request a provider-backed route."), Config.ProviderRouteDecision.bProviderBackedRouteRequested);
|
||||
TestFalse(TEXT("The mock route decision must not mark a provider-backed route as selected."), Config.ProviderRouteDecision.bProviderBackedRouteSelected);
|
||||
TestTrue(TEXT("The mock route decision must remain route-ready."), Config.ProviderRouteDecision.bRouteReady);
|
||||
return true;
|
||||
}
|
||||
|
||||
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
|
||||
FHyperTwistWhisperCppPhase6RYProviderRoutingServiceHealthTest,
|
||||
"HyperTwist.Permissive.WhisperCpp.Phase6R.Y.ProviderRoutingPolicyServiceHealth",
|
||||
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
|
||||
)
|
||||
|
||||
bool FHyperTwistWhisperCppPhase6RYProviderRoutingServiceHealthTest::RunTest(const FString& Parameters)
|
||||
{
|
||||
UHyperTwistTrainingSubsystem* TrainingSubsystem =
|
||||
HyperTwistWhisperCppPhase6RYTestInternal::MakeSpeechSubsystem(
|
||||
TEXT("phase6r-y-health-session"),
|
||||
TEXT("mock")
|
||||
);
|
||||
TestNotNull(TEXT("The speech subsystem must be constructed for Phase 6R-Y."), TrainingSubsystem);
|
||||
if (TrainingSubsystem == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
FString OpenError;
|
||||
TestTrue(TEXT("The mock provider-routing route must open a speech session."), TrainingSubsystem->OpenActiveCompanionSpeechSession(OpenError));
|
||||
TestTrue(TEXT("Opening the mock provider-routing speech session must not report an error."), OpenError.IsEmpty());
|
||||
|
||||
const FHyperTwistSpeechServiceHealth& Health =
|
||||
TrainingSubsystem->GetActiveCompanionSpeechSessionState().ServiceHealth;
|
||||
|
||||
TestTrue(TEXT("The provider-routing service health must remain structurally valid."), Health.IsStructurallyValid());
|
||||
TestTrue(TEXT("The service health must preserve provider routing policy capability."), Health.Capabilities.Contains(TEXT("providerRoutingPolicy")));
|
||||
TestTrue(TEXT("The service health must preserve provider route selection capability."), Health.Capabilities.Contains(TEXT("providerRouteSelection")));
|
||||
TestTrue(TEXT("The service health must preserve workflow-policy state capability."), Health.Capabilities.Contains(TEXT("workflowPolicyState")));
|
||||
TestEqual(TEXT("The service health must preserve the mock routing policy id."), Health.ProviderRoutingPolicyId, TEXT("speech-provider-routing/local-offline-mock-first-v1"));
|
||||
TestTrue(TEXT("The service health routing policy definition must remain structurally valid."), Health.ProviderRoutingPolicyDefinition.IsStructurallyValid());
|
||||
TestEqual(TEXT("The mock routing health must keep fail-closed fallback wording."), Health.ProviderRoutingPolicyDefinition.FallbackMode, TEXT("fail-closed"));
|
||||
TestTrue(TEXT("The mock routing policy must require manual transcript capability."), Health.ProviderRoutingPolicyDefinition.RequiredCapabilityFlags.Contains(TEXT("manualTranscriptCommit")));
|
||||
TestTrue(TEXT("The mock routing policy must support transcribe tasks."), Health.ProviderRoutingPolicyDefinition.SupportedTaskKinds.Contains(TEXT("transcribe")));
|
||||
|
||||
TestTrue(TEXT("The mock routing health decision must remain structurally valid."), Health.ProviderRouteDecision.IsStructurallyValid());
|
||||
TestEqual(TEXT("The mock routing health decision must preserve the in-process endpoint class."), Health.ProviderRouteDecision.SelectedEndpointClass, TEXT("in-process-mock"));
|
||||
TestEqual(TEXT("The mock routing health decision must keep the ready route state."), Health.ProviderRouteDecision.RouteStateId, TEXT("route-ready"));
|
||||
TestFalse(TEXT("The mock routing health decision must not mark a provider-backed route as selected."), Health.ProviderRouteDecision.bProviderBackedRouteSelected);
|
||||
TestFalse(TEXT("The mock routing health decision must not fall back into health-posture mode."), Health.ProviderRouteDecision.bUsedFallbackHealthPosture);
|
||||
TestTrue(TEXT("The mock routing health decision must keep the route ready."), Health.ProviderRouteDecision.bRouteReady);
|
||||
return true;
|
||||
}
|
||||
|
||||
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
|
||||
FHyperTwistWhisperCppPhase6RYProviderBackedRoutingFallbackTest,
|
||||
"HyperTwist.Permissive.WhisperCpp.Phase6R.Y.ProviderBackedRoutingFallback",
|
||||
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
|
||||
)
|
||||
|
||||
bool FHyperTwistWhisperCppPhase6RYProviderBackedRoutingFallbackTest::RunTest(const FString& Parameters)
|
||||
{
|
||||
UHyperTwistTrainingSubsystem* TrainingSubsystem =
|
||||
HyperTwistWhisperCppPhase6RYTestInternal::MakeSpeechSubsystem(
|
||||
TEXT("phase6r-y-provider-session"),
|
||||
TEXT("http-sidecar")
|
||||
);
|
||||
TestNotNull(TEXT("The speech subsystem must be constructed for Phase 6R-Y."), TrainingSubsystem);
|
||||
if (TrainingSubsystem == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
UHyperTwistHttpSpeechClient* HttpSpeechClient =
|
||||
HyperTwistWhisperCppPhase6RYTestInternal::ResolveHttpSpeechClient(TrainingSubsystem);
|
||||
TestNotNull(TEXT("The provider-backed speech client must be available for the routing fallback test."), HttpSpeechClient);
|
||||
if (HttpSpeechClient == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
HttpSpeechClient->ServiceBaseUrl.Reset();
|
||||
|
||||
FString OpenError;
|
||||
TestFalse(TEXT("The provider-backed routing path must fail cleanly when no provider endpoint is configured."), TrainingSubsystem->OpenActiveCompanionSpeechSession(OpenError));
|
||||
TestEqual(TEXT("The provider-backed routing path must report the missing service base URL."), OpenError, TEXT("service-base-url-missing"));
|
||||
|
||||
const FHyperTwistTrainingCompanionSpeechSessionState SessionState =
|
||||
TrainingSubsystem->GetActiveCompanionSpeechSessionState();
|
||||
const FHyperTwistSpeechServiceHealth& Health = SessionState.ServiceHealth;
|
||||
|
||||
TestTrue(TEXT("The provider-backed routing fallback health must remain structurally valid."), Health.IsStructurallyValid());
|
||||
TestEqual(TEXT("The provider-backed routing fallback must keep the provider-backed routing policy id."), Health.ProviderRoutingPolicyId, TEXT("speech-provider-routing/provider-backed-sidecar-first-v1"));
|
||||
TestTrue(TEXT("The provider-backed routing policy definition must remain structurally valid."), Health.ProviderRoutingPolicyDefinition.IsStructurallyValid());
|
||||
TestEqual(TEXT("The provider-backed routing policy must preserve sidecar-first selection mode."), Health.ProviderRoutingPolicyDefinition.RouteSelectionMode, TEXT("provider-backed-sidecar-first"));
|
||||
TestEqual(TEXT("The provider-backed routing policy must preserve health-posture fallback wording."), Health.ProviderRoutingPolicyDefinition.FallbackMode, TEXT("health-posture-only"));
|
||||
TestTrue(TEXT("The provider-backed routing policy must allow provider-backed routes."), Health.ProviderRoutingPolicyDefinition.bAllowProviderBackedRoutes);
|
||||
TestTrue(TEXT("The provider-backed routing policy must preserve health-posture fallback."), Health.ProviderRoutingPolicyDefinition.bAllowHealthPostureFallback);
|
||||
|
||||
TestTrue(TEXT("The provider-backed route decision must remain structurally valid."), Health.ProviderRouteDecision.IsStructurallyValid());
|
||||
TestEqual(TEXT("The provider-backed route decision must target the local HTTP provider profile."), Health.ProviderRouteDecision.SelectedProviderProfileId, TEXT("speech-provider/local-http-sidecar-profile-v1"));
|
||||
TestEqual(TEXT("The provider-backed route decision must preserve the local self-hosted endpoint class."), Health.ProviderRouteDecision.SelectedEndpointClass, TEXT("local-self-hosted-http"));
|
||||
TestEqual(TEXT("The provider-backed route decision must preserve HTTP transport."), Health.ProviderRouteDecision.SelectedTransportKind, TEXT("http"));
|
||||
TestEqual(TEXT("The provider-backed route decision must report the awaiting-endpoint state."), Health.ProviderRouteDecision.RouteStateId, TEXT("route-awaiting-endpoint"));
|
||||
TestEqual(TEXT("The provider-backed route decision must expose the unavailability reason."), Health.ProviderRouteDecision.DecisionReason, TEXT("provider-backed-sidecar-route-unavailable"));
|
||||
TestEqual(TEXT("The provider-backed route decision must expose the missing-endpoint failure."), Health.ProviderRouteDecision.FailureReason, TEXT("service-base-url-missing"));
|
||||
TestTrue(TEXT("The provider-backed route decision must mark a provider-backed route as requested."), Health.ProviderRouteDecision.bProviderBackedRouteRequested);
|
||||
TestTrue(TEXT("The provider-backed route decision must mark a provider-backed route as selected."), Health.ProviderRouteDecision.bProviderBackedRouteSelected);
|
||||
TestTrue(TEXT("The provider-backed route decision must preserve fallback health posture."), Health.ProviderRouteDecision.bUsedFallbackHealthPosture);
|
||||
TestFalse(TEXT("The provider-backed route decision must not report a ready route."), Health.ProviderRouteDecision.bRouteReady);
|
||||
TestEqual(TEXT("The shell state must preserve the route error."), SessionState.MicrophoneShellState.LastRouteError, TEXT("service-base-url-missing"));
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -183,8 +183,12 @@ Status update on `2026-05-21`:
|
|||
pass is now consumed
|
||||
- the bounded first-party `Phase 6R-X` provider-profile and BYOK custody packet is now landed in
|
||||
current code
|
||||
- the current next bounded move is a source-backed `Phase 6R-Y` first-party provider routing and
|
||||
policy preparation/control pass, not a new restrictive packet by default
|
||||
- the generic source-backed `Phase 6R-Y` first-party provider routing and policy control pass is
|
||||
now consumed
|
||||
- the bounded first-party `Phase 6R-Y` provider routing and policy packet is now landed in
|
||||
current code
|
||||
- the current next bounded move is a source-backed `Phase 6R-Z` first-party normalized
|
||||
usage/cost event-model preparation/control pass, not a new restrictive packet by default
|
||||
- use the repo-row README census, the portfolio standing refresh backfill, and the `2R-A`
|
||||
ownership contract for the current queue after that correction
|
||||
|
||||
|
|
@ -288,8 +292,8 @@ Current practical interpretation:
|
|||
- the landed `PostHog/posthog` boundary-sensitive widening packet now lives in `docs/HYPERTWIST_PHASE_4R_PACKET_4R_D_POSTHOG_CONTROL_PLANE_IMPLEMENTATION_2026-05-13.md`
|
||||
- the landed `screenpipe/screenpipe` boundary-sensitive widening packet now lives in `docs/HYPERTWIST_PHASE_4R_PACKET_4R_E_SCREENPIPE_CAPTURE_HISTORY_IMPLEMENTATION_2026-05-13.md`
|
||||
- the landed `remotion-dev/remotion` boundary-sensitive widening packet now lives in `docs/HYPERTWIST_PHASE_4R_PACKET_4R_F_REMOTION_MEDIA_EXPORT_IMPLEMENTATION_2026-05-13.md`
|
||||
- the next bounded move is a source-backed `Phase 6R-Y` first-party provider routing and policy
|
||||
preparation/control pass
|
||||
- the next bounded move is a source-backed `Phase 6R-Z` first-party normalized usage/cost
|
||||
event-model preparation/control pass
|
||||
|
||||
Companion docs:
|
||||
|
||||
|
|
@ -1545,11 +1549,14 @@ Approved working posture:
|
|||
payload custody metadata above the existing transcript-session and shell seams
|
||||
- the next bounded first-party implementation slice is now landed as provider-profile and BYOK
|
||||
custody metadata above the existing transcript-session, shell, and payload-custody seams
|
||||
- the next bounded first-party implementation slice is now landed as provider routing and policy
|
||||
metadata above the existing transcript-session, shell, payload-custody, and provider-custody
|
||||
seams
|
||||
- the top-level provider/session contract remains first-party HyperTwist-owned and
|
||||
provider-neutral; this row does not own that lane
|
||||
- keep real device-permission workflow, native capture-route ownership, actual payload shipping,
|
||||
first-party provider routing and policy, normalized usage/cost events, and future voice-asset
|
||||
review separate from the code-license judgment
|
||||
normalized usage/cost events, and future voice-asset review separate from the code-license
|
||||
judgment
|
||||
- treat `SYSTRAN/faster-whisper` as the landed complementary Python-orchestration donor rather
|
||||
than widening `whisper.cpp` into the runtime core
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,153 @@
|
|||
# HyperTwist Phase 6R-Y first-party provider routing and policy implementation packet
|
||||
|
||||
Created on `2026-05-24`
|
||||
|
||||
## Status
|
||||
|
||||
- first-party HyperTwist packet
|
||||
- bounded `Phase 6R-Y` implementation slice
|
||||
|
||||
## Purpose
|
||||
|
||||
This packet lands the next bounded first-party slice above the landed speech
|
||||
session, microphone-shell, payload-custody, and provider-custody seams.
|
||||
|
||||
The landed slice is:
|
||||
|
||||
- first-party provider routing and workflow-policy metadata
|
||||
|
||||
It is not:
|
||||
|
||||
- a normalized usage/cost event-model packet
|
||||
- an actual payload-shipping packet
|
||||
- a real device-permission workflow packet
|
||||
- a native audio-device route ownership packet
|
||||
- a provider-specific overlay packet
|
||||
- a voice-output packet
|
||||
- a broad assistant-platform packet
|
||||
|
||||
## Current authority basis
|
||||
|
||||
This implementation packet stands on:
|
||||
|
||||
- `docs/ops/HYPERTWIST_PROVIDER_NEUTRALITY_AND_BYOK_DOCTRINE_2026-05-21.md`
|
||||
- `docs/arch/HYPERTWIST_PHASE6R_Y_FIRST_PARTY_PROVIDER_ROUTING_AND_POLICY_PREPARATION_PACKET_2026-05-24.md`
|
||||
- `docs/arch/HYPERTWIST_PHASE6R_X_FIRST_PARTY_PROVIDER_PROFILE_AND_BYOK_CUSTODY_IMPLEMENTATION_PACKET_2026-05-24.md`
|
||||
|
||||
The preserved owners do not change:
|
||||
|
||||
- first-party HyperTwist remains the top-level provider/session owner
|
||||
- first-party HyperTwist remains the provider routing/policy owner
|
||||
- `ggml-org/whisper.cpp` remains bounded to offline STT donor seams
|
||||
- `SYSTRAN/faster-whisper` remains bounded to complementary Python
|
||||
orchestration/service-lane seams
|
||||
|
||||
## Landed scope
|
||||
|
||||
The current code now owns a bounded provider-routing / workflow-policy seam
|
||||
through:
|
||||
|
||||
- retained recognition contract types for:
|
||||
- `FHyperTwistSpeechProviderRoutingPolicy`
|
||||
- `FHyperTwistSpeechProviderRouteDecision`
|
||||
- expanded `FHyperTwistSpeechSessionConfig`
|
||||
- expanded `FHyperTwistSpeechServiceHealth`
|
||||
- contract-library defaults for:
|
||||
- provider-backed route policy
|
||||
- mock verification route policy
|
||||
- sample route-decision posture
|
||||
- active companion session-config and service-health normalization in:
|
||||
- `UHyperTwistTrainingSubsystem`
|
||||
- direct speech-client health capability exposure in:
|
||||
- `UHyperTwistHttpSpeechClient`
|
||||
- `UHyperTwistMockSpeechClient`
|
||||
- focused automation coverage in:
|
||||
- `HyperTwistWhisperCppPhase6RYProviderRoutingPolicyContractTest.cpp`
|
||||
|
||||
## Why this is still intentionally bounded
|
||||
|
||||
This packet lands the routing/policy metadata family only.
|
||||
|
||||
Still deferred:
|
||||
|
||||
- normalized usage/cost events
|
||||
- actual downloadable payload shipping
|
||||
- real device-permission workflow
|
||||
- native audio-device route ownership beyond bounded shell posture
|
||||
- broad voice-output ownership
|
||||
- broad assistant-platform scope
|
||||
|
||||
## Validation
|
||||
|
||||
Build validation:
|
||||
|
||||
- `C:\Program Files\Epic Games\UE_5.7\Engine\Build\BatchFiles\Build.bat UnrealHyperTwistEditor Win64 Development -Project='C:\HyperTwist\UnrealHyperTwist\UnrealHyperTwist.uproject' -WaitMutex -NoHotReloadFromIDE -NoUba`
|
||||
|
||||
Focused automation validation:
|
||||
|
||||
- `Automation RunTests HyperTwist.Permissive.WhisperCpp.Phase6R.Y`
|
||||
|
||||
Regression automation validation:
|
||||
|
||||
- `HyperTwist.Permissive.WhisperCpp.Phase6R.X`
|
||||
- `HyperTwist.Permissive.WhisperCpp.Phase6R.W`
|
||||
- `HyperTwist.Permissive.WhisperCpp.Phase6R.V`
|
||||
- `HyperTwist.Permissive.WhisperCpp.Phase6R.U`
|
||||
- `HyperTwist.Permissive.WhisperCpp.Phase6R.E`
|
||||
- `HyperTwist.Permissive.FasterWhisper.Phase6R.F`
|
||||
- `HyperTwist.Permissive.Piper.Phase6R.G`
|
||||
- `HyperTwist.Permissive.Coqui.Phase6R.H`
|
||||
- `HyperTwist.CleanRoom.CubeDesk`
|
||||
|
||||
Expected covered tests:
|
||||
|
||||
- `ProviderRoutingPolicySessionConfig`
|
||||
- `ProviderRoutingPolicyServiceHealth`
|
||||
- `ProviderBackedRoutingFallback`
|
||||
|
||||
## Queue effect
|
||||
|
||||
This packet consumes the current `Phase 6R-Y` implementation slice.
|
||||
|
||||
`ggml-org/whisper.cpp` remains only partially incorporated:
|
||||
|
||||
- landed now:
|
||||
- speech transcript session boundary
|
||||
- live microphone shell boundary
|
||||
- device-permission and capture-route readiness shell posture
|
||||
- downloadable model and payload custody boundary
|
||||
- first-party provider-profile and BYOK custody boundary
|
||||
- first-party provider routing and workflow-policy boundary for:
|
||||
- routing-policy ids and definitions
|
||||
- route-decision summaries
|
||||
- fallback-health posture
|
||||
- capability exposure for:
|
||||
- `providerRoutingPolicy`
|
||||
- `providerRouteSelection`
|
||||
- `workflowPolicyState`
|
||||
- still deferred:
|
||||
- normalized usage/cost event model
|
||||
- actual downloadable payload shipping
|
||||
- real device-permission workflow
|
||||
- native audio-device route ownership beyond bounded shell posture
|
||||
- broad assistant-platform scope
|
||||
|
||||
The next clean move is:
|
||||
|
||||
- a source-backed `Phase 6R-Z` first-party normalized usage/cost event-model
|
||||
preparation/control pass
|
||||
|
||||
Keep the future sequencing guards visible:
|
||||
|
||||
- first-party HyperTwist
|
||||
- keep the top-level provider/session contract and provider routing/policy
|
||||
lane first-party
|
||||
- keep normalized usage/cost events separate from the landed provider-routing
|
||||
seam
|
||||
- `ggml-org/whisper.cpp`
|
||||
- keep code-license judgments separate from actual model or payload shipping
|
||||
review in any follow-on packet
|
||||
- `SYSTRAN/faster-whisper`
|
||||
- keep the row complementary to the landed provider-routing seam and bounded
|
||||
to Python orchestration/service-lane ownership rather than usage/cost
|
||||
governance ownership
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
# HyperTwist Phase 6R-Y first-party provider routing and policy preparation packet
|
||||
|
||||
Created on `2026-05-24`
|
||||
|
||||
## Status
|
||||
|
||||
- first-party HyperTwist packet
|
||||
- source-backed `Phase 6R-Y` preparation/control slice
|
||||
|
||||
## Purpose
|
||||
|
||||
This packet scopes the next bounded first-party slice above the landed
|
||||
provider/session, microphone-shell, payload-custody, and provider-custody
|
||||
seams.
|
||||
|
||||
The granted slice is:
|
||||
|
||||
- first-party provider routing and workflow-policy metadata only
|
||||
|
||||
It is not:
|
||||
|
||||
- a normalized usage/cost event-model packet
|
||||
- an actual payload-shipping packet
|
||||
- a real device-permission workflow packet
|
||||
- a native audio-device route ownership packet
|
||||
- a provider-specific overlay packet
|
||||
- a voice-output packet
|
||||
- a broad assistant-platform packet
|
||||
|
||||
## Current authority basis
|
||||
|
||||
This control pass stands on:
|
||||
|
||||
- `docs/ops/HYPERTWIST_PROVIDER_NEUTRALITY_AND_BYOK_DOCTRINE_2026-05-21.md`
|
||||
- `docs/arch/HYPERTWIST_PHASE6R_X_FIRST_PARTY_PROVIDER_PROFILE_AND_BYOK_CUSTODY_IMPLEMENTATION_PACKET_2026-05-24.md`
|
||||
- `docs/v6_5_deep_manual_pack/HyperTwist/ROADMAP.md`
|
||||
|
||||
The preserved owners do not change here:
|
||||
|
||||
- first-party HyperTwist remains the top-level provider/session owner
|
||||
- first-party HyperTwist remains the routing/policy owner
|
||||
- `ggml-org/whisper.cpp` remains bounded to offline STT donor seams
|
||||
- `SYSTRAN/faster-whisper` remains bounded to complementary Python
|
||||
orchestration/service-lane seams
|
||||
|
||||
## Granted family
|
||||
|
||||
The bounded `Phase 6R-Y` slice may land:
|
||||
|
||||
1. first-party provider-routing policy ids and definitions
|
||||
2. first-party route-decision summaries for session config and service health
|
||||
3. explicit fallback-health posture wording above provider-backed route failure
|
||||
4. workflow-policy capability exposure in the bounded speech-health seam
|
||||
5. focused automation for mock-route and provider-backed-route posture
|
||||
|
||||
The packet must stay out of:
|
||||
|
||||
- normalized usage/cost event ownership
|
||||
- actual provider-gateway fan-out ownership
|
||||
- real secret-storage workflow ownership
|
||||
- payload download or redistribution ownership
|
||||
- real device-permission workflow ownership
|
||||
|
||||
## Proposed implementation shape
|
||||
|
||||
Land the narrower first-party boundary through:
|
||||
|
||||
- retained recognition contract types for:
|
||||
- routing-policy definition
|
||||
- route-decision summary
|
||||
- expanded speech session config
|
||||
- expanded speech service health
|
||||
- contract-library defaults for:
|
||||
- provider-backed route policy
|
||||
- local mock route policy
|
||||
- explicit route-decision defaults
|
||||
- training-subsystem normalization for:
|
||||
- requested session-route posture
|
||||
- health-surface route posture
|
||||
- fallback-health route posture on provider failure
|
||||
- direct speech-client health capability exposure for:
|
||||
- `providerRoutingPolicy`
|
||||
- `providerRouteSelection`
|
||||
- `workflowPolicyState`
|
||||
|
||||
## Validation target
|
||||
|
||||
Validate with:
|
||||
|
||||
- Unreal build for `UnrealHyperTwistEditor Win64 Development`
|
||||
- focused automation:
|
||||
- `HyperTwist.Permissive.WhisperCpp.Phase6R.Y`
|
||||
- regressions:
|
||||
- `HyperTwist.Permissive.WhisperCpp.Phase6R.X`
|
||||
- `HyperTwist.Permissive.WhisperCpp.Phase6R.W`
|
||||
- `HyperTwist.Permissive.WhisperCpp.Phase6R.V`
|
||||
- `HyperTwist.Permissive.WhisperCpp.Phase6R.U`
|
||||
- `HyperTwist.Permissive.WhisperCpp.Phase6R.E`
|
||||
- `HyperTwist.Permissive.FasterWhisper.Phase6R.F`
|
||||
- `HyperTwist.Permissive.Piper.Phase6R.G`
|
||||
- `HyperTwist.Permissive.Coqui.Phase6R.H`
|
||||
- `HyperTwist.CleanRoom.CubeDesk`
|
||||
|
||||
## Queue effect
|
||||
|
||||
If this packet lands cleanly, the next bounded move becomes:
|
||||
|
||||
- a source-backed `Phase 6R-Z` first-party normalized usage/cost event-model
|
||||
preparation/control pass
|
||||
|
||||
Keep the narrow sequencing guards visible:
|
||||
|
||||
- keep actual payload shipping separate from routing/policy ownership
|
||||
- keep real device-permission workflow and native capture-route ownership
|
||||
outside this packet
|
||||
- keep normalized usage/cost events as the next separate first-party family
|
||||
|
|
@ -132,15 +132,19 @@ The next bounded move is now:
|
|||
control pass is now consumed
|
||||
22. the bounded first-party `Phase 6R-X` provider-profile and BYOK custody packet is now
|
||||
landed in current code
|
||||
23. the next bounded move is a source-backed `Phase 6R-Y` first-party provider routing and
|
||||
policy preparation/control pass
|
||||
24. keep the speech-lane guard visible:
|
||||
23. the generic source-backed `Phase 6R-Y` first-party provider routing and policy control
|
||||
pass is now consumed
|
||||
24. the bounded first-party `Phase 6R-Y` provider routing and policy packet is now landed in
|
||||
current code
|
||||
25. the next bounded move is a source-backed `Phase 6R-Z` first-party normalized usage/cost
|
||||
event-model preparation/control pass
|
||||
26. keep the speech-lane guard visible:
|
||||
- keep code-license judgments separate from model, voice, and payload-license review
|
||||
25. keep the provider-neutral speech-lane guard visible:
|
||||
27. keep the provider-neutral speech-lane guard visible:
|
||||
- first-party HyperTwist owns the top-level provider/session contract
|
||||
- `whisper.cpp` and `faster-whisper` may win narrower donor slices without inheriting that
|
||||
lane or the provider routing/policy lane
|
||||
26. keep the `MagicTile` guard visible:
|
||||
28. keep the `MagicTile` guard visible:
|
||||
- keep broad non-Euclidean interaction or WinForms/OpenTK host-shell ownership closed by
|
||||
default unless a narrower first-party gap is proven above the landed macro-remapping seam
|
||||
|
||||
|
|
|
|||
|
|
@ -56,9 +56,11 @@ Those seams prove that HyperTwist already owns bounded provider contracts for:
|
|||
- session open/close
|
||||
- transcript/result payloads
|
||||
- health/status envelopes
|
||||
- provider-routing policy ids and definitions
|
||||
- route-decision summaries and fallback-health posture
|
||||
|
||||
Treat those as the current provisional first-party `A1` anchor for recognition
|
||||
and speech-provider contracts.
|
||||
Treat those as the current first-party `A1` anchor for recognition,
|
||||
speech-provider contracts, and bounded provider routing/policy ownership.
|
||||
|
||||
Do not let future provider donors overtake that top-level contract by
|
||||
accident.
|
||||
|
|
@ -132,10 +134,11 @@ Keep these lanes distinct:
|
|||
|
||||
### Routing/gateway lane
|
||||
|
||||
- current strongest owner unresolved in HyperTwist packet authority
|
||||
- provisional posture:
|
||||
- first-party target
|
||||
- later donor evaluation may refine `A/R/F`
|
||||
- `A1 / R1 / F1` - first-party only for the bounded routing/policy layer
|
||||
- current evidence anchor:
|
||||
- `FHyperTwistSpeechProviderRoutingPolicy`
|
||||
- `FHyperTwistSpeechProviderRouteDecision`
|
||||
- `UHyperTwistTrainingSubsystem`
|
||||
|
||||
### Provider-profile and BYOK custody lane
|
||||
|
||||
|
|
@ -162,6 +165,10 @@ Keep these lanes distinct:
|
|||
### Admin/policy lane
|
||||
|
||||
- `A1 / R1 / F1` - first-party only
|
||||
- current evidence anchor:
|
||||
- `FHyperTwistSpeechProviderRoutingPolicy`
|
||||
- `FHyperTwistSpeechProviderRouteDecision`
|
||||
- `UHyperTwistTrainingSubsystem`
|
||||
|
||||
## BYOK rules
|
||||
|
||||
|
|
@ -202,6 +209,12 @@ The correct implementation order is:
|
|||
5. operator-facing overlay/dashboard surfaces
|
||||
6. bounded provider-specific adapters where still useful
|
||||
|
||||
Current landed ordering status:
|
||||
|
||||
- steps `1` through `3` now have bounded first-party implementation anchors
|
||||
- normalized usage/cost events remain the next separate first-party gap
|
||||
- operator-facing overlays and provider-specific adapters remain later work
|
||||
|
||||
Do not invert that order.
|
||||
|
||||
If HyperTwist starts from a provider-specific overlay and only later tries to
|
||||
|
|
|
|||
|
|
@ -124,6 +124,7 @@ Do not collapse those three tiers into one undifferentiated "features" voice.
|
|||
| Device-permission and capture-route readiness shell | Implemented now | landed `whisper.cpp` `Phase 6R-V` | First-party permission/readiness shell posture, issue objects, retry/request semantics, and bounded capability exposure are now live above the microphone shell seam. |
|
||||
| Downloadable model and payload custody boundary | Implemented now | landed `whisper.cpp` `Phase 6R-W` | First-party payload-custody profile, required/supported model-payload descriptors, and bounded integrity metadata are now live above the landed speech session and shell seams. |
|
||||
| First-party provider profile and BYOK custody boundary | Implemented now | landed first-party `Phase 6R-X` | First-party provider-profile definitions, BYOK custody definitions, per-profile model/capability maps, and out-of-band auth-reference wording are now live above the landed speech session, shell, and payload-custody seams. |
|
||||
| First-party provider routing and workflow-policy boundary | Implemented now | landed first-party `Phase 6R-Y` | First-party routing-policy ids/definitions, route-decision summaries, fallback-health posture, and workflow-policy capability exposure are now live above the landed provider-custody seam. |
|
||||
| Analytics/reporting surfaces | Implemented now | landed analytics/reporting packets | Reporting is real, but bounded to accepted retained slices. |
|
||||
| Browser/spatial/media adjunct surfaces | Implemented now | landed `three.js`, `react-three-fiber`, `xr`, `model-viewer`, `remotion` packets | These are implemented bounded families, not proof of unlimited browser-shell parity. |
|
||||
|
||||
|
|
@ -217,8 +218,9 @@ repo.
|
|||
|---|---|---|---|
|
||||
| First-party provider-neutral speech/vision contract | Implemented now | first-party recognition/speech client seams | Current bounded provider/session truth. |
|
||||
| Provider-neutral BYOK/profile custody boundary | Implemented now | landed first-party `Phase 6R-X` packet | Current bounded provider-profile ids/definitions, BYOK custody ids/definitions, per-profile model/capability maps, and out-of-band auth-reference wording. |
|
||||
| First-party provider routing and workflow-policy boundary | Implemented now | landed first-party `Phase 6R-Y` packet | Current bounded routing-policy ids/definitions, route-decision summaries, explicit fallback-health posture, and workflow-policy capability exposure above the landed provider/session and provider-custody seams. |
|
||||
| OpenAI-compatible custom endpoint support | Deep-source grounded retained | doctrine-defined first-party target | First-class target is now represented in the landed custody model, but full routing/runtime support is still deferred. |
|
||||
| Normalized usage/cost/routing surface | Deep-source grounded retained | doctrine-defined first-party target | Retained governance target, not live product truth yet. |
|
||||
| Normalized usage/cost event surface | Deep-source grounded retained | doctrine-defined first-party target | Usage/cost normalization remains the next retained governance target after the landed routing/policy boundary. |
|
||||
| Provider-specific overlays | Shallow placeholder | future provider-family work only | Keep internal until source-grounded and normalized. |
|
||||
|
||||
### 9. Memory, continuity, notes, and provenance
|
||||
|
|
|
|||
|
|
@ -159,10 +159,13 @@ Canonical discovery surfaces for roadmap interpretation:
|
|||
pass is now consumed
|
||||
- the bounded first-party `Phase 6R-X` provider-profile and BYOK custody packet is now landed in
|
||||
current code
|
||||
- the current next bounded move is a source-backed `Phase 6R-Y` first-party provider routing and
|
||||
policy preparation/control pass, while keeping normalized usage/cost events, real
|
||||
device-permission workflow, native capture-route ownership, and actual payload shipping
|
||||
separately deferred
|
||||
- the generic source-backed `Phase 6R-Y` first-party provider routing and policy control pass is
|
||||
now consumed
|
||||
- the bounded first-party `Phase 6R-Y` provider routing and policy packet is now landed in
|
||||
current code
|
||||
- the current next bounded move is a source-backed `Phase 6R-Z` first-party normalized
|
||||
usage/cost event-model preparation/control pass, while keeping real device-permission
|
||||
workflow, native capture-route ownership, and actual payload shipping separately deferred
|
||||
- the repo-row implementation queue is now live from that `Phase 6R-A` entry point rather than
|
||||
waiting on another first-party packet
|
||||
|
||||
|
|
@ -224,14 +227,14 @@ Current routing truth:
|
|||
- active non-live implementation-board rows: `34`
|
||||
- retained benchmark, oracle, or clean-room-later rows outside the active implementation board: `9`
|
||||
|
||||
The next bounded move is a source-backed `Phase 6R-Y` first-party
|
||||
provider routing and policy preparation/control pass.
|
||||
The next bounded move is a source-backed `Phase 6R-Z` first-party
|
||||
normalized usage/cost event-model preparation/control pass.
|
||||
|
||||
Queue interpretation after that control pass:
|
||||
|
||||
- then continue with the retained repo-row queue
|
||||
- highest current repo-row queue pressure sits in:
|
||||
- the first-party provider routing and policy remainder above the
|
||||
- the first-party normalized usage/cost event-model remainder above the
|
||||
partially landed `whisper.cpp` and `faster-whisper` speech seams
|
||||
- `HactarCE/Hyperspeedcube` is now closed for the currently justified retained row:
|
||||
- landed:
|
||||
|
|
@ -320,6 +323,7 @@ Queue interpretation after that control pass:
|
|||
- device-permission and capture-route readiness shell posture
|
||||
- downloadable model and payload custody boundary
|
||||
- first-party provider-profile and BYOK custody boundary
|
||||
- first-party provider routing and policy boundary
|
||||
- bounded shell capability exposure for:
|
||||
- microphone capture shell
|
||||
- device-permission shell
|
||||
|
|
@ -327,8 +331,10 @@ Queue interpretation after that control pass:
|
|||
- capture-route retry
|
||||
- streaming preview
|
||||
- manual transcript commit
|
||||
- provider routing policy
|
||||
- provider route selection
|
||||
- workflow-policy state
|
||||
- still deferred:
|
||||
- first-party provider routing and policy
|
||||
- normalized usage/cost event model
|
||||
- real device-permission workflow
|
||||
- native capture-route ownership beyond bounded shell posture
|
||||
|
|
@ -377,12 +383,12 @@ Queue interpretation after that control pass:
|
|||
- viseme / gesture runtime integration
|
||||
- broad assistant-platform scope
|
||||
- the next queue shape is now:
|
||||
- first-party provider routing and policy assessment above the landed speech session, shell,
|
||||
payload-custody, and provider-custody seams
|
||||
- first-party normalized usage/cost event-model assessment above the landed speech session,
|
||||
shell, payload-custody, provider-custody, and provider-routing seams
|
||||
- the next bounded move should stay narrow:
|
||||
- a source-backed `Phase 6R-Y` control pass before any widening into normalized usage/cost
|
||||
events, actual payload shipping, real device-permission workflow, broad voice-output
|
||||
ownership, or broad assistant-platform scope
|
||||
- a source-backed `Phase 6R-Z` control pass before any widening into actual payload shipping,
|
||||
real device-permission workflow, broad voice-output ownership, or broad assistant-platform
|
||||
scope
|
||||
- keep the speech-input / voice sidecar legal sequencing guard visible:
|
||||
- keep code-license judgments separate from model, voice, and payload-license review
|
||||
- keep the provider-neutral speech-lane guard visible:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue