Implement Phase 6R-Y provider routing policy

This commit is contained in:
axiomlogicnexus 2026-05-25 00:52:00 +02:00
parent 7a8182cb2c
commit 3464732aab
13 changed files with 1405 additions and 31 deletions

View file

@ -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(

View file

@ -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");

View file

@ -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"));

View file

@ -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
);

View file

@ -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())
{

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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: