Harden validation, tooling, and public product surfaces

This commit is contained in:
axiomlogicnexus 2026-06-23 09:22:54 +00:00
parent 9c93020c69
commit a1d40d1232
29 changed files with 7020 additions and 5015 deletions

2
.gitignore vendored
View file

@ -13,6 +13,8 @@ website/dist/
website/node_modules/
website/server/node_modules/
website/server/data/
tools/sentrux/bin/*
!tools/sentrux/bin/.gitkeep
# Sensitive or reference-only material.
docs/refs/

View file

@ -0,0 +1,968 @@
#include "HyperTwistRecognition/HyperTwistRecognitionTypes.h"
namespace HyperTwistRecognitionTypesInternal
{
bool AreAllStringsPopulated(const TArray<FString>& Values)
{
for (const FString& Value : Values)
{
if (Value.IsEmpty())
{
return false;
}
}
return true;
}
template <typename ItemType>
bool AreAllItemsStructurallyValid(const TArray<ItemType>& Items)
{
for (const ItemType& Item : Items)
{
if (!Item.IsStructurallyValid())
{
return false;
}
}
return true;
}
}
bool FHyperTwistSpeechNativeCaptureRouteShellProfile::IsStructurallyValid() const
{
return !NativeCaptureRouteShellProfileId.IsEmpty()
&& !ShellKind.IsEmpty()
&& !OwnershipSummarySurfaceMode.IsEmpty()
&& !PreparationSurfaceMode.IsEmpty()
&& !SessionReopenSurfaceMode.IsEmpty()
&& !RouteInspectActionId.IsEmpty()
&& !PreparationRetryActionId.IsEmpty()
&& !SessionReopenActionId.IsEmpty()
&& !PermissionDependencyActionId.IsEmpty()
&& Panels.Num() > 0
&& ActionBindings.Num() > 0
&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Panels)
&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(ActionBindings);
}
bool FHyperTwistSpeechNativeCaptureRouteShellState::IsStructurallyValid() const
{
if (NativeCaptureRouteShellProfileId.IsEmpty()
|| NativeCaptureRouteWorkflowProfileId.IsEmpty()
|| ActiveProviderProfileId.IsEmpty()
|| ActiveServiceLaneId.IsEmpty()
|| WorkflowStateId.IsEmpty()
|| CaptureRouteStateId.IsEmpty()
|| PermissionStateId.IsEmpty()
|| LatestSourceKind.IsEmpty()
|| StatusLine.IsEmpty()
|| DetailLine.IsEmpty()
|| ActiveIssueCount < 0
|| AvailableActionIds.Num() <= 0)
{
return false;
}
if (ActiveIssueCount != Issues.Num())
{
return false;
}
return (ActiveIssueCount <= 0 || ActiveIssue.IsStructurallyValid())
&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Entries)
&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Issues)
&& HyperTwistRecognitionTypesInternal::AreAllStringsPopulated(AvailableActionIds);
}
bool FHyperTwistSpeechUsageCostDashboardShellProfile::IsStructurallyValid() const
{
return !DashboardShellProfileId.IsEmpty()
&& !ShellKind.IsEmpty()
&& !UsageSurfaceMode.IsEmpty()
&& !CostSurfaceMode.IsEmpty()
&& !EscalationBannerMode.IsEmpty()
&& !RefreshActionId.IsEmpty()
&& !RouteInspectActionId.IsEmpty()
&& !BudgetInspectActionId.IsEmpty()
&& Panels.Num() > 0
&& ActionBindings.Num() > 0
&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Panels)
&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(ActionBindings);
}
bool FHyperTwistSpeechUsageCostDashboardShellState::IsStructurallyValid() const
{
if (DashboardShellProfileId.IsEmpty()
|| ActiveProviderProfileId.IsEmpty()
|| ActiveProviderDisplayLabel.IsEmpty()
|| ActiveServiceLaneId.IsEmpty()
|| ActiveRouteStateId.IsEmpty()
|| UsageAggregationWindowId.IsEmpty()
|| CostAggregationWindowId.IsEmpty()
|| UsageMeterKind.IsEmpty()
|| CurrencyCode.IsEmpty()
|| StatusLine.IsEmpty()
|| DetailLine.IsEmpty()
|| LatestUsageEventId.IsEmpty()
|| LatestCostEventId.IsEmpty()
|| LatestQuotaStateId.IsEmpty()
|| LatestRouteDecisionId.IsEmpty()
|| DisplayedUsageQuantity < 0.0f
|| DisplayedEstimatedCostUsd < 0.0f
|| DisplayedReportedCostUsd < 0.0f
|| RemainingEstimatedSpendUsd < 0.0f
|| RemainingRequestCount < 0
|| RemainingAudioSeconds < 0
|| ActiveIssueCount < 0
|| AvailableActionIds.Num() <= 0)
{
return false;
}
if (ActiveIssueCount != Issues.Num())
{
return false;
}
return (ActiveIssueCount <= 0 || ActiveIssue.IsStructurallyValid())
&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Issues)
&& HyperTwistRecognitionTypesInternal::AreAllStringsPopulated(AvailableActionIds);
}
bool FHyperTwistVisionShellProfile::IsStructurallyValid() const
{
return !ShellProfileId.IsEmpty()
&& !ShellKind.IsEmpty()
&& !DefaultLocaleCode.IsEmpty()
&& !FontReviewProfileId.IsEmpty()
&& FontReviewProfileDefinition.IsStructurallyValid()
&& SupportedFontReviews.Num() > 0
&& SupportedLocales.Num() > 0
&& Panels.Num() > 0
&& ActionBindings.Num() > 0
&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(SupportedLocales)
&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(SupportedFontReviews)
&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Panels)
&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(ActionBindings);
}
bool FHyperTwistVisionSolveExplanationProfile::IsStructurallyValid() const
{
return !ExplanationProfileId.IsEmpty()
&& !PuzzleId.IsEmpty()
&& !RecommendationMode.IsEmpty()
&& !LocaleGuidanceMode.IsEmpty()
&& !DefaultLocaleCode.IsEmpty()
&& !StartingOrientationHint.IsEmpty()
&& !FontReviewProfileId.IsEmpty()
&& FontReviewProfileDefinition.IsStructurallyValid()
&& SupportedFontReviews.Num() > 0
&& SupportedLocales.Num() > 0
&& Steps.Num() > 0
&& ActionBindings.Num() > 0
&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(SupportedLocales)
&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(SupportedFontReviews)
&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Steps)
&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(ActionBindings);
}
bool FHyperTwistVisionCorrectionState::IsStructurallyValid() const
{
if (CorrectionProfileId.IsEmpty()
|| MissingFaceCount < 0
|| ContradictionCount < 0
|| ContradictionCount != Contradictions.Num()
|| ResolvedCorrectionCount < 0
|| ResolvedCorrectionCount != ResolutionLedger.Num())
{
return false;
}
if (bCorrectionRequired
&& (ActiveTargetFaceId.IsEmpty()
|| !ActiveTarget.IsStructurallyValid()
|| ActiveTargetFaceId != ActiveTarget.FaceId))
{
return false;
}
return HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(PendingTargets)
&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Contradictions)
&& (LastResolution.ResolutionId.IsEmpty() || LastResolution.IsStructurallyValid())
&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(ResolutionLedger);
}
bool FHyperTwistSpeechProviderRoutingPolicy::IsStructurallyValid() const
{
return !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
&& HyperTwistRecognitionTypesInternal::AreAllStringsPopulated(EligibleProviderClasses)
&& HyperTwistRecognitionTypesInternal::AreAllStringsPopulated(EligibleEndpointClasses)
&& HyperTwistRecognitionTypesInternal::AreAllStringsPopulated(RequiredCapabilityFlags)
&& HyperTwistRecognitionTypesInternal::AreAllStringsPopulated(SupportedTaskKinds);
}
namespace HyperTwistRecognitionTypeValidation
{
template <typename TStruct>
bool AreStructurallyValidEntries(const TArray<TStruct>& Values)
{
return HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Values);
}
bool AreNonEmptyStrings(const TArray<FString>& Values)
{
return HyperTwistRecognitionTypesInternal::AreAllStringsPopulated(Values);
}
bool AreSpeechModelPayloadsValid(const TArray<FHyperTwistSpeechModelPayloadDescriptor>& Payloads)
{
return AreStructurallyValidEntries(Payloads);
}
bool HasValidSpeechSessionCore(const FHyperTwistSpeechSessionConfig& Session)
{
return !Session.SessionId.IsEmpty()
&& !Session.ListeningContractId.IsEmpty()
&& !Session.InputRouteId.IsEmpty()
&& !Session.AudioEncoding.IsEmpty()
&& Session.SampleRateHz > 0
&& Session.ChannelCount > 0
&& !Session.TaskKind.IsEmpty()
&& Session.RequiredModelPayloads.Num() > 0
&& Session.VadPolicy.IsStructurallyValid()
&& Session.OrchestrationProfile.IsStructurallyValid();
}
bool HasValidSpeechSessionProfiles(const FHyperTwistSpeechSessionConfig& Session)
{
return !Session.MicrophoneShellProfileId.IsEmpty()
&& Session.MicrophoneShellProfileDefinition.IsStructurallyValid()
&& !Session.DevicePermissionWorkflowProfileId.IsEmpty()
&& Session.DevicePermissionWorkflowProfileDefinition.IsStructurallyValid()
&& !Session.NativeCaptureRouteWorkflowProfileId.IsEmpty()
&& Session.NativeCaptureRouteWorkflowProfileDefinition.IsStructurallyValid()
&& !Session.NativeCaptureRouteShellProfileId.IsEmpty()
&& Session.NativeCaptureRouteShellProfileDefinition.IsStructurallyValid()
&& !Session.ExternalDictationShellProfileId.IsEmpty()
&& Session.ExternalDictationShellProfileDefinition.IsStructurallyValid()
&& !Session.ProviderProfileId.IsEmpty()
&& Session.ProviderProfileDefinition.IsStructurallyValid()
&& !Session.ByokCustodyProfileId.IsEmpty()
&& Session.ByokCustodyProfileDefinition.IsStructurallyValid()
&& !Session.ProviderRoutingPolicyId.IsEmpty()
&& Session.ProviderRoutingPolicyDefinition.IsStructurallyValid()
&& Session.ProviderRouteDecision.IsStructurallyValid()
&& !Session.UsageCostAccountingProfileId.IsEmpty()
&& Session.UsageCostAccountingProfileDefinition.IsStructurallyValid()
&& Session.UsageEventTemplate.IsStructurallyValid()
&& Session.CostEventTemplate.IsStructurallyValid()
&& !Session.UsageCostDashboardShellProfileId.IsEmpty()
&& Session.UsageCostDashboardShellProfileDefinition.IsStructurallyValid()
&& !Session.UsageCostHistoryExportShellProfileId.IsEmpty()
&& Session.UsageCostHistoryExportShellProfileDefinition.IsStructurallyValid()
&& !Session.ProviderReceiptReviewShellProfileId.IsEmpty()
&& Session.ProviderReceiptReviewShellProfileDefinition.IsStructurallyValid()
&& !Session.ProviderBillingSettlementShellProfileId.IsEmpty()
&& Session.ProviderBillingSettlementShellProfileDefinition.IsStructurallyValid()
&& !Session.ProviderSettlementExceptionShellProfileId.IsEmpty()
&& Session.ProviderSettlementExceptionShellProfileDefinition.IsStructurallyValid()
&& !Session.PayloadCustodyProfileId.IsEmpty()
&& Session.PayloadCustodyProfileDefinition.IsStructurallyValid();
}
bool HasValidTranscriptCore(const FHyperTwistSpeechTranscriptResult& Transcript)
{
return !Transcript.SessionId.IsEmpty()
&& !Transcript.UtteranceId.IsEmpty()
&& !Transcript.TaskKind.IsEmpty()
&& (!Transcript.TranscriptText.IsEmpty() || Transcript.Segments.Num() > 0)
&& !Transcript.OrchestrationProfileId.IsEmpty()
&& !Transcript.ServiceLaneId.IsEmpty()
&& Transcript.RequestedBatchSize > 0
&& Transcript.ProcessedClipCount > 0
&& Transcript.AppliedBatchCollectionWindowMs > 0
&& Transcript.LanguageProbability >= 0.0f
&& !Transcript.AppliedPromptRoutingModeId.IsEmpty()
&& !Transcript.AppliedRetrievalContextLaneId.IsEmpty();
}
bool AreTranscriptSegmentsValid(const TArray<FHyperTwistSpeechTranscriptSegment>& Segments)
{
return AreStructurallyValidEntries(Segments);
}
bool HasValidSpeechServiceHealthCore(const FHyperTwistSpeechServiceHealth& Health)
{
return !Health.ProviderLabel.IsEmpty()
&& !Health.ServiceVersion.IsEmpty()
&& !Health.ProviderProfileId.IsEmpty()
&& Health.ProviderProfileDefinition.IsStructurallyValid()
&& !Health.ByokCustodyProfileId.IsEmpty()
&& Health.ByokCustodyProfileDefinition.IsStructurallyValid()
&& !Health.ProviderRoutingPolicyId.IsEmpty()
&& Health.ProviderRoutingPolicyDefinition.IsStructurallyValid()
&& Health.ProviderRouteDecision.IsStructurallyValid()
&& !Health.UsageCostAccountingProfileId.IsEmpty()
&& Health.UsageCostAccountingProfileDefinition.IsStructurallyValid()
&& Health.LatestUsageEvent.IsStructurallyValid()
&& Health.LatestCostEvent.IsStructurallyValid()
&& Health.QuotaRateLimitState.IsStructurallyValid()
&& !Health.PayloadCustodyProfileId.IsEmpty()
&& Health.PayloadCustodyProfileDefinition.IsStructurallyValid();
}
bool HasValidExternalDictationShellProfileCore(
const FHyperTwistSpeechExternalDictationShellProfile& Profile)
{
return !Profile.ExternalDictationShellProfileId.IsEmpty()
&& !Profile.ShellKind.IsEmpty()
&& !Profile.TranscriptHistorySurfaceMode.IsEmpty()
&& !Profile.OutputRoutingSurfaceMode.IsEmpty()
&& !Profile.PostProcessOverlaySurfaceMode.IsEmpty()
&& !Profile.GlobalHotkeySurfaceMode.IsEmpty()
&& !Profile.InputDeviceSurfaceMode.IsEmpty()
&& !Profile.OutputDeviceSurfaceMode.IsEmpty()
&& !Profile.MuteSurfaceMode.IsEmpty()
&& !Profile.MicrophoneModeSurfaceMode.IsEmpty()
&& !Profile.LocalModelCatalogSurfaceMode.IsEmpty()
&& !Profile.ModelIntegritySurfaceMode.IsEmpty()
&& !Profile.ModelUnloadSurfaceMode.IsEmpty()
&& !Profile.StartCaptureActionId.IsEmpty()
&& !Profile.CancelCaptureActionId.IsEmpty()
&& !Profile.CycleOutputRouteActionId.IsEmpty()
&& !Profile.CopyTranscriptActionId.IsEmpty()
&& !Profile.PasteTranscriptActionId.IsEmpty()
&& !Profile.ScriptDispatchActionId.IsEmpty()
&& !Profile.TogglePostProcessOverlayActionId.IsEmpty()
&& !Profile.ReopenSpeechSessionActionId.IsEmpty()
&& !Profile.RouteInspectActionId.IsEmpty()
&& !Profile.InspectGlobalHotkeyActionId.IsEmpty()
&& !Profile.CycleInputDeviceActionId.IsEmpty()
&& !Profile.CycleOutputDeviceActionId.IsEmpty()
&& !Profile.ToggleMuteWhileRecordingActionId.IsEmpty()
&& !Profile.ToggleMicrophoneModeActionId.IsEmpty()
&& !Profile.InspectLocalModelCatalogActionId.IsEmpty()
&& !Profile.ReviewLocalModelIntegrityActionId.IsEmpty()
&& !Profile.ReviewLocalModelUnloadPolicyActionId.IsEmpty()
&& !Profile.PrimaryHotkeyBindingLabel.IsEmpty()
&& !Profile.PostProcessHotkeyBindingLabel.IsEmpty()
&& Profile.RetainedHistoryEntryLimit > 0
&& Profile.Panels.Num() > 0
&& Profile.ActionBindings.Num() > 0;
}
bool HasValidExternalDictationShellStateCore(const FHyperTwistSpeechExternalDictationShellState& State)
{
return !State.ExternalDictationShellProfileId.IsEmpty()
&& !State.ActiveProviderProfileId.IsEmpty()
&& !State.ActiveServiceLaneId.IsEmpty()
&& !State.SelectedOutputRouteId.IsEmpty()
&& !State.TranscriptHistorySurfaceModeId.IsEmpty()
&& !State.OutputRoutingSurfaceModeId.IsEmpty()
&& !State.PostProcessOverlaySurfaceModeId.IsEmpty()
&& !State.GlobalHotkeySurfaceModeId.IsEmpty()
&& !State.InputDeviceSurfaceModeId.IsEmpty()
&& !State.OutputDeviceSurfaceModeId.IsEmpty()
&& !State.MuteSurfaceModeId.IsEmpty()
&& !State.MicrophoneModeSurfaceModeId.IsEmpty()
&& !State.LocalModelCatalogSurfaceModeId.IsEmpty()
&& !State.ModelIntegritySurfaceModeId.IsEmpty()
&& !State.ModelUnloadSurfaceModeId.IsEmpty()
&& !State.LatestSourceKind.IsEmpty()
&& !State.StatusLine.IsEmpty()
&& !State.DetailLine.IsEmpty()
&& !State.PrimaryHotkeyBindingLabel.IsEmpty()
&& !State.PostProcessHotkeyBindingLabel.IsEmpty()
&& !State.SelectedInputDeviceId.IsEmpty()
&& !State.SelectedInputDeviceLabel.IsEmpty()
&& !State.SelectedOutputDeviceId.IsEmpty()
&& !State.SelectedOutputDeviceLabel.IsEmpty()
&& !State.MicrophoneModeId.IsEmpty()
&& !State.PayloadCustodyProfileId.IsEmpty()
&& !State.SelectedPrimaryPayloadId.IsEmpty()
&& State.HistoryEntryCount >= 0
&& State.PostProcessedEntryCount >= 0
&& State.SavedEntryCount >= 0
&& State.ModelCatalogEntryCount >= 0
&& State.OptionalModelCatalogEntryCount >= 0
&& State.DownloadDeferredModelEntryCount >= 0
&& State.IntegrityReviewRequiredEntryCount >= 0
&& State.ActiveIssueCount >= 0
&& State.OutputRouteOptions.Num() > 0
&& State.InputDeviceOptions.Num() > 0
&& State.OutputDeviceOptions.Num() > 0
&& State.ModelCatalogEntries.Num() > 0
&& State.AvailableActionIds.Num() > 0;
}
bool HasConsistentExternalDictationShellStateCounts(const FHyperTwistSpeechExternalDictationShellState& State)
{
return State.HistoryEntryCount == State.HistoryEntries.Num()
&& State.PostProcessedEntryCount <= State.HistoryEntryCount
&& State.SavedEntryCount <= State.HistoryEntryCount
&& State.ModelCatalogEntryCount == State.ModelCatalogEntries.Num()
&& State.OptionalModelCatalogEntryCount <= State.ModelCatalogEntryCount
&& State.DownloadDeferredModelEntryCount <= State.ModelCatalogEntryCount
&& State.IntegrityReviewRequiredEntryCount <= State.ModelCatalogEntryCount;
}
bool HasConsistentExternalDictationShellStateLatestEntry(const FHyperTwistSpeechExternalDictationShellState& State)
{
return State.HistoryEntryCount <= 0
|| (!State.LatestHistoryEntryId.IsEmpty() && !State.LatestTranscriptText.IsEmpty());
}
bool HasConsistentExternalDictationShellStateActiveIssue(const FHyperTwistSpeechExternalDictationShellState& State)
{
return State.ActiveIssueCount == State.Issues.Num()
&& (State.ActiveIssueCount <= 0 || State.ActiveIssue.IsStructurallyValid());
}
}
bool FHyperTwistSpeechUsageCostHistoryExportShellState::IsStructurallyValid() const
{
if (HistoryExportShellProfileId.IsEmpty()
|| ActiveProviderProfileId.IsEmpty()
|| ActiveProviderDisplayLabel.IsEmpty()
|| ActiveServiceLaneId.IsEmpty()
|| SelectedHistoryWindowId.IsEmpty()
|| ExportPreviewFormatId.IsEmpty()
|| LatestSourceKind.IsEmpty()
|| StatusLine.IsEmpty()
|| DetailLine.IsEmpty()
|| HistoryEntryCount < 0
|| EstimateOnlyEntryCount < 0
|| ProviderReceiptEntryCount < 0
|| TotalUsageQuantity < 0.0f
|| TotalEstimatedCostUsd < 0.0f
|| TotalReportedCostUsd < 0.0f
|| LowestRemainingEstimatedSpendUsd < 0.0f
|| ActiveIssueCount < 0
|| AvailableActionIds.Num() <= 0)
{
return false;
}
return HistoryEntryCount == HistoryEntries.Num()
&& (HistoryEntryCount <= 0 || !LatestHistoryEntryId.IsEmpty())
&& (!bExportPreviewReady || !ExportPreviewText.IsEmpty())
&& ActiveIssueCount == Issues.Num()
&& (ActiveIssueCount <= 0 || ActiveIssue.IsStructurallyValid())
&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(Issues)
&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(HistoryEntries)
&& HyperTwistRecognitionTypeValidation::AreNonEmptyStrings(AvailableActionIds);
}
bool FHyperTwistSpeechProviderReceiptReviewShellState::IsStructurallyValid() const
{
if (ReceiptReviewShellProfileId.IsEmpty()
|| ActiveProviderProfileId.IsEmpty()
|| ActiveProviderDisplayLabel.IsEmpty()
|| ActiveServiceLaneId.IsEmpty()
|| SelectedChargeWindowId.IsEmpty()
|| PostedChargeInspectionModeId.IsEmpty()
|| LatestSourceKind.IsEmpty()
|| StatusLine.IsEmpty()
|| DetailLine.IsEmpty()
|| ReceiptEntryCount < 0
|| ProviderPostedChargeCount < 0
|| EstimateOnlyEntryCount < 0
|| VarianceReviewEntryCount < 0
|| TotalEstimatedCostUsd < 0.0f
|| TotalReportedCostUsd < 0.0f
|| TotalAbsoluteVarianceUsd < 0.0f
|| HighestAbsoluteVarianceUsd < 0.0f
|| ActiveIssueCount < 0
|| AvailableActionIds.Num() <= 0)
{
return false;
}
return ReceiptEntryCount == ReceiptEntries.Num()
&& ProviderPostedChargeCount <= ReceiptEntryCount
&& EstimateOnlyEntryCount <= ReceiptEntryCount
&& VarianceReviewEntryCount <= ReceiptEntryCount
&& (ReceiptEntryCount <= 0 || !LatestReceiptEntryId.IsEmpty())
&& (!bReceiptSummaryReady || !ReceiptSummaryText.IsEmpty())
&& ActiveIssueCount == Issues.Num()
&& (ActiveIssueCount <= 0 || ActiveIssue.IsStructurallyValid())
&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(Issues)
&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(ReceiptEntries)
&& HyperTwistRecognitionTypeValidation::AreNonEmptyStrings(AvailableActionIds);
}
bool FHyperTwistSpeechProviderBillingSettlementShellState::IsStructurallyValid() const
{
if (BillingSettlementShellProfileId.IsEmpty()
|| ActiveProviderProfileId.IsEmpty()
|| ActiveProviderDisplayLabel.IsEmpty()
|| ActiveServiceLaneId.IsEmpty()
|| SelectedSettlementWindowId.IsEmpty()
|| SettlementSurfaceModeId.IsEmpty()
|| InvoiceReconciliationModeId.IsEmpty()
|| LatestSourceKind.IsEmpty()
|| StatusLine.IsEmpty()
|| DetailLine.IsEmpty()
|| SettlementEntryCount < 0
|| ProviderPostedChargeCount < 0
|| ReconciliationReadyEntryCount < 0
|| EstimateOnlyEntryCount < 0
|| ManualReviewEntryCount < 0
|| BlockedSettlementEntryCount < 0
|| TotalEstimatedCostUsd < 0.0f
|| TotalReportedCostUsd < 0.0f
|| TotalSettlementDeltaUsd < 0.0f
|| HighestSettlementDeltaUsd < 0.0f
|| ActiveIssueCount < 0
|| AvailableActionIds.Num() <= 0)
{
return false;
}
return SettlementEntryCount == SettlementEntries.Num()
&& ProviderPostedChargeCount <= SettlementEntryCount
&& ReconciliationReadyEntryCount <= SettlementEntryCount
&& EstimateOnlyEntryCount <= SettlementEntryCount
&& ManualReviewEntryCount <= SettlementEntryCount
&& BlockedSettlementEntryCount <= SettlementEntryCount
&& (SettlementEntryCount <= 0 || !LatestSettlementEntryId.IsEmpty())
&& (!bSettlementSummaryReady || !SettlementSummaryText.IsEmpty())
&& ActiveIssueCount == Issues.Num()
&& (ActiveIssueCount <= 0 || ActiveIssue.IsStructurallyValid())
&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(Issues)
&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(SettlementEntries)
&& HyperTwistRecognitionTypeValidation::AreNonEmptyStrings(AvailableActionIds);
}
bool FHyperTwistSpeechProviderSettlementExceptionShellState::IsStructurallyValid() const
{
if (SettlementExceptionShellProfileId.IsEmpty()
|| ActiveProviderProfileId.IsEmpty()
|| ActiveProviderDisplayLabel.IsEmpty()
|| ActiveServiceLaneId.IsEmpty()
|| SelectedSettlementWindowId.IsEmpty()
|| ExceptionSurfaceModeId.IsEmpty()
|| ExternalPortalHandoffModeId.IsEmpty()
|| LatestSourceKind.IsEmpty()
|| StatusLine.IsEmpty()
|| DetailLine.IsEmpty()
|| ExceptionEntryCount < 0
|| ExternalPortalHandoffReadyEntryCount < 0
|| PendingChargeEntryCount < 0
|| ManualReviewEntryCount < 0
|| RouteDegradedEntryCount < 0
|| BlockedSettlementEntryCount < 0
|| TotalEstimatedCostUsd < 0.0f
|| TotalReportedCostUsd < 0.0f
|| TotalSettlementDeltaUsd < 0.0f
|| HighestSettlementDeltaUsd < 0.0f
|| ActiveIssueCount < 0
|| AvailableActionIds.Num() <= 0)
{
return false;
}
return ExceptionEntryCount == ExceptionEntries.Num()
&& ExternalPortalHandoffReadyEntryCount <= ExceptionEntryCount
&& PendingChargeEntryCount <= ExceptionEntryCount
&& ManualReviewEntryCount <= ExceptionEntryCount
&& RouteDegradedEntryCount <= ExceptionEntryCount
&& BlockedSettlementEntryCount <= ExceptionEntryCount
&& (ExceptionEntryCount <= 0 || !LatestExceptionEntryId.IsEmpty())
&& (!bExceptionSummaryReady || !ExceptionSummaryText.IsEmpty())
&& ActiveIssueCount == Issues.Num()
&& (ActiveIssueCount <= 0 || ActiveIssue.IsStructurallyValid())
&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(Issues)
&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(ExceptionEntries)
&& HyperTwistRecognitionTypeValidation::AreNonEmptyStrings(AvailableActionIds);
}
bool FHyperTwistSpeechExternalDictationShellProfile::IsStructurallyValid() const
{
return HyperTwistRecognitionTypeValidation::HasValidExternalDictationShellProfileCore(*this)
&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(Panels)
&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(ActionBindings);
}
bool FHyperTwistSpeechExternalDictationShellState::IsStructurallyValid() const
{
return HyperTwistRecognitionTypeValidation::HasValidExternalDictationShellStateCore(*this)
&& HyperTwistRecognitionTypeValidation::HasConsistentExternalDictationShellStateCounts(*this)
&& HyperTwistRecognitionTypeValidation::HasConsistentExternalDictationShellStateLatestEntry(*this)
&& HyperTwistRecognitionTypeValidation::HasConsistentExternalDictationShellStateActiveIssue(*this)
&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(Issues)
&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(HistoryEntries)
&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(OutputRouteOptions)
&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(InputDeviceOptions)
&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(OutputDeviceOptions)
&& HyperTwistRecognitionTypeValidation::AreStructurallyValidEntries(ModelCatalogEntries)
&& HyperTwistRecognitionTypeValidation::AreNonEmptyStrings(AvailableActionIds);
}
bool FHyperTwistSpeechSessionConfig::IsStructurallyValid() const
{
return HyperTwistRecognitionTypeValidation::HasValidSpeechSessionCore(*this)
&& HyperTwistRecognitionTypeValidation::HasValidSpeechSessionProfiles(*this)
&& HyperTwistRecognitionTypeValidation::AreSpeechModelPayloadsValid(RequiredModelPayloads);
}
bool FHyperTwistSpeechTranscriptResult::IsStructurallyValid() const
{
if (!HyperTwistRecognitionTypeValidation::HasValidTranscriptCore(*this)
|| RetrievedHintCount < 0)
{
return false;
}
if (bUsedRetrievedHintAugmentation && RetrievedHintCount <= 0)
{
return false;
}
return RetrievedHintCount == AppliedRetrievedHints.Num()
&& HyperTwistRecognitionTypeValidation::AreTranscriptSegmentsValid(Segments)
&& HyperTwistRecognitionTypeValidation::AreNonEmptyStrings(AppliedRetrievedHints);
}
bool FHyperTwistSpeechServiceHealth::IsStructurallyValid() const
{
return HyperTwistRecognitionTypeValidation::HasValidSpeechServiceHealthCore(*this)
&& HyperTwistRecognitionTypeValidation::AreNonEmptyStrings(SupportedModelPayloadIds)
&& HyperTwistRecognitionTypeValidation::AreSpeechModelPayloadsValid(SupportedModelPayloads);
}
bool FHyperTwistVoiceAssetDescriptor::IsStructurallyValid() const
{
return !VoiceAssetId.IsEmpty()
&& !VoiceProfileId.IsEmpty()
&& !ArtifactName.IsEmpty()
&& !RelativePathHint.IsEmpty()
&& !SourceDocumentPath.IsEmpty()
&& !ReviewDocumentPath.IsEmpty()
&& !AcquisitionMode.IsEmpty()
&& !ReviewPosture.IsEmpty()
&& ApproximateSizeMiB > 0;
}
bool FHyperTwistVoiceAssetReviewProfile::IsStructurallyValid() const
{
return !VoiceAssetReviewProfileId.IsEmpty()
&& !VoiceAssetReviewPosture.IsEmpty()
&& !ShippingPosture.IsEmpty()
&& !DownloadWorkflowPosture.IsEmpty()
&& !ProvisioningPosture.IsEmpty()
&& !CodeLicenseBoundary.IsEmpty();
}
bool FHyperTwistVoiceModelReviewDescriptor::IsStructurallyValid() const
{
return !VoiceModelReviewId.IsEmpty()
&& !ModelBindingId.IsEmpty()
&& !VocoderBindingId.IsEmpty()
&& !VoiceProfileId.IsEmpty()
&& !RegistryReferencePath.IsEmpty()
&& !ReviewDocumentPath.IsEmpty()
&& !ModelLicensePosture.IsEmpty()
&& !PayloadLicensePosture.IsEmpty()
&& !AcquisitionMode.IsEmpty();
}
bool FHyperTwistVoiceModelReviewProfile::IsStructurallyValid() const
{
return !VoiceModelReviewProfileId.IsEmpty()
&& !ReviewPosture.IsEmpty()
&& !ShippingPosture.IsEmpty()
&& !DownloadWorkflowPosture.IsEmpty()
&& !CodeLicenseBoundary.IsEmpty();
}
bool FHyperTwistVoiceProfileSummary::IsStructurallyValid() const
{
return !VoiceProfileId.IsEmpty()
&& !VoiceName.IsEmpty()
&& !LanguageCode.IsEmpty()
&& !LanguageFamily.IsEmpty()
&& !RegionCode.IsEmpty()
&& !LanguageNameEnglish.IsEmpty()
&& !Quality.IsEmpty()
&& NumSpeakers > 0;
}
bool FHyperTwistVoiceProfileCatalog::IsStructurallyValid() const
{
return Profiles.Num() > 0
&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Profiles);
}
bool FHyperTwistNarrationOrchestrationProfile::IsStructurallyValid() const
{
return !OrchestrationProfileId.IsEmpty()
&& !ServiceLaneId.IsEmpty()
&& !ModelBindingId.IsEmpty()
&& !VocoderBindingId.IsEmpty()
&& !DefaultSpeakerProfileId.IsEmpty();
}
bool FHyperTwistNarrationSynthesisRequest::IsStructurallyValid() const
{
return !RequestId.IsEmpty()
&& !NarrationContractId.IsEmpty()
&& !ServiceLaneId.IsEmpty()
&& !OutputRouteId.IsEmpty()
&& !VoiceProfileId.IsEmpty()
&& !LanguageCode.IsEmpty()
&& OrchestrationProfile.IsStructurallyValid()
&& ServiceLaneId.Equals(OrchestrationProfile.ServiceLaneId, ESearchCase::CaseSensitive)
&& !ScriptText.IsEmpty()
&& !AudioEncodingHint.IsEmpty()
&& LengthScale > 0.0f
&& NoiseScale >= 0.0f
&& NoiseW >= 0.0f
&& SentenceSilenceSeconds >= 0.0f;
}
bool FHyperTwistNarrationSynthesisResult::IsStructurallyValid() const
{
return !RequestId.IsEmpty()
&& !NarrationContractId.IsEmpty()
&& !ServiceLaneId.IsEmpty()
&& !OutputRouteId.IsEmpty()
&& !VoiceProfileId.IsEmpty()
&& !LanguageCode.IsEmpty()
&& !OrchestrationProfileId.IsEmpty()
&& !ModelBindingId.IsEmpty()
&& !VocoderBindingId.IsEmpty()
&& !SubtitleText.IsEmpty()
&& !AudioEncoding.IsEmpty()
&& SampleRateHz > 0
&& ChannelCount > 0
&& DurationMs >= 0
&& AudioBytes.Num() > 0
&& AppliedLengthScale > 0.0f
&& AppliedNoiseScale >= 0.0f
&& AppliedNoiseW >= 0.0f
&& AppliedSentenceSilenceSeconds >= 0.0f;
}
bool FHyperTwistVoiceServiceHealth::IsStructurallyValid() const
{
if (ProviderLabel.IsEmpty() || ServiceVersion.IsEmpty())
{
return false;
}
if ((!VoiceAssetReviewProfileId.IsEmpty()
|| VoiceAssetReviewProfileDefinition.IsStructurallyValid()
|| SupportedVoiceAssetIds.Num() > 0
|| SupportedVoiceAssets.Num() > 0)
&& (VoiceAssetReviewProfileId.IsEmpty()
|| !VoiceAssetReviewProfileDefinition.IsStructurallyValid()
|| SupportedVoiceAssetIds.Num() != SupportedVoiceAssets.Num()))
{
return false;
}
if ((!VoiceModelReviewProfileId.IsEmpty()
|| VoiceModelReviewProfileDefinition.IsStructurallyValid()
|| SupportedVoiceModelReviewIds.Num() > 0
|| SupportedVoiceModelReviews.Num() > 0)
&& (VoiceModelReviewProfileId.IsEmpty()
|| !VoiceModelReviewProfileDefinition.IsStructurallyValid()
|| SupportedVoiceModelReviewIds.Num() != SupportedVoiceModelReviews.Num()))
{
return false;
}
return HyperTwistRecognitionTypesInternal::AreAllStringsPopulated(SupportedVoiceAssetIds)
&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(SupportedVoiceAssets)
&& HyperTwistRecognitionTypesInternal::AreAllStringsPopulated(SupportedVoiceModelReviewIds)
&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(SupportedVoiceModelReviews);
}
bool FHyperTwistSpeechMicrophoneShellState::IsStructurallyValid() const
{
if (MicrophoneShellProfileId.IsEmpty()
|| CaptureMode.IsEmpty()
|| ListeningContractId.IsEmpty()
|| InputRouteId.IsEmpty()
|| PermissionStateId.IsEmpty()
|| CaptureRouteStateId.IsEmpty()
|| LastLanguageCode.IsEmpty()
|| StatusLine.IsEmpty()
|| DetailLine.IsEmpty()
|| StepWindowMs <= 0
|| CaptureWindowMs < StepWindowMs
|| KeepWindowMs < 0
|| KeepWindowMs > CaptureWindowMs
|| SubmittedUtteranceCount < 0
|| FinalTranscriptCount < 0
|| DetectedSpeechStartMs < 0
|| DetectedSpeechEndMs < DetectedSpeechStartMs
|| LastSilenceGapMs < 0
|| VadThreshold <= 0.0f
|| ActiveIssueCount < 0
|| AvailableActionIds.Num() <= 0)
{
return false;
}
return ActiveIssueCount == Issues.Num()
&& (ActiveIssueCount <= 0 || ActiveIssue.IsStructurallyValid())
&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Issues)
&& HyperTwistRecognitionTypesInternal::AreAllStringsPopulated(AvailableActionIds);
}
bool FHyperTwistSpeechDevicePermissionWorkflowProfile::IsStructurallyValid() const
{
return !DevicePermissionWorkflowProfileId.IsEmpty()
&& !WorkflowKind.IsEmpty()
&& !PermissionContractId.IsEmpty()
&& !SettingsHandoffContractId.IsEmpty()
&& !PermissionRecheckContractId.IsEmpty()
&& !PermissionRequestActionId.IsEmpty()
&& !OpenSettingsActionId.IsEmpty()
&& !PermissionRecheckActionId.IsEmpty()
&& Panels.Num() > 0
&& ActionBindings.Num() > 0
&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Panels)
&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(ActionBindings);
}
bool FHyperTwistSpeechDevicePermissionWorkflowEntry::IsStructurallyValid() const
{
return !EntryId.IsEmpty()
&& !SourceKind.IsEmpty()
&& !WorkflowStateId.IsEmpty()
&& !StatusLine.IsEmpty()
&& !DetailLine.IsEmpty()
&& !RecommendedActionId.IsEmpty();
}
bool FHyperTwistSpeechDevicePermissionWorkflowIssue::IsStructurallyValid() const
{
return !IssueId.IsEmpty()
&& !IssueKind.IsEmpty()
&& !StatusLine.IsEmpty()
&& !DetailLine.IsEmpty()
&& !RecommendedActionId.IsEmpty();
}
bool FHyperTwistSpeechDevicePermissionWorkflowState::IsStructurallyValid() const
{
if (DevicePermissionWorkflowProfileId.IsEmpty()
|| WorkflowStateId.IsEmpty()
|| PermissionStateId.IsEmpty()
|| LatestSourceKind.IsEmpty()
|| StatusLine.IsEmpty()
|| DetailLine.IsEmpty()
|| WorkflowEntryCount < 0
|| PermissionRequestEntryCount < 0
|| SettingsHandoffEntryCount < 0
|| PermissionRecheckEntryCount < 0
|| ActiveIssueCount < 0
|| AvailableActionIds.Num() <= 0)
{
return false;
}
if (WorkflowEntryCount != Entries.Num()
|| ActiveIssueCount != Issues.Num()
|| PermissionRequestEntryCount > WorkflowEntryCount
|| SettingsHandoffEntryCount > WorkflowEntryCount
|| PermissionRecheckEntryCount > WorkflowEntryCount)
{
return false;
}
return (ActiveIssueCount <= 0 || ActiveIssue.IsStructurallyValid())
&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Entries)
&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Issues)
&& HyperTwistRecognitionTypesInternal::AreAllStringsPopulated(AvailableActionIds);
}
bool FHyperTwistSpeechNativeCaptureRouteWorkflowProfile::IsStructurallyValid() const
{
return !NativeCaptureRouteWorkflowProfileId.IsEmpty()
&& !WorkflowKind.IsEmpty()
&& !OwnershipContractId.IsEmpty()
&& !PreparationContractId.IsEmpty()
&& !SessionReopenContractId.IsEmpty()
&& !RouteInspectActionId.IsEmpty()
&& !PreparationRetryActionId.IsEmpty()
&& !SessionReopenActionId.IsEmpty()
&& !PermissionDependencyActionId.IsEmpty()
&& Panels.Num() > 0
&& ActionBindings.Num() > 0
&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Panels)
&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(ActionBindings);
}
bool FHyperTwistSpeechNativeCaptureRouteWorkflowEntry::IsStructurallyValid() const
{
return !EntryId.IsEmpty()
&& !SourceKind.IsEmpty()
&& !WorkflowStateId.IsEmpty()
&& !CaptureRouteStateId.IsEmpty()
&& !StatusLine.IsEmpty()
&& !DetailLine.IsEmpty()
&& !RecommendedActionId.IsEmpty();
}
bool FHyperTwistSpeechNativeCaptureRouteWorkflowIssue::IsStructurallyValid() const
{
return !IssueId.IsEmpty()
&& !IssueKind.IsEmpty()
&& !StatusLine.IsEmpty()
&& !DetailLine.IsEmpty()
&& !RecommendedActionId.IsEmpty();
}
bool FHyperTwistSpeechNativeCaptureRouteWorkflowState::IsStructurallyValid() const
{
if (NativeCaptureRouteWorkflowProfileId.IsEmpty()
|| WorkflowStateId.IsEmpty()
|| CaptureRouteStateId.IsEmpty()
|| PermissionStateId.IsEmpty()
|| ActiveProviderProfileId.IsEmpty()
|| ActiveServiceLaneId.IsEmpty()
|| LatestSourceKind.IsEmpty()
|| StatusLine.IsEmpty()
|| DetailLine.IsEmpty()
|| WorkflowEntryCount < 0
|| PreparationEntryCount < 0
|| RouteRetryEntryCount < 0
|| SessionReopenEntryCount < 0
|| PermissionDependencyEntryCount < 0
|| ActiveIssueCount < 0
|| AvailableActionIds.Num() <= 0)
{
return false;
}
if (WorkflowEntryCount != Entries.Num()
|| ActiveIssueCount != Issues.Num()
|| PreparationEntryCount > WorkflowEntryCount
|| RouteRetryEntryCount > WorkflowEntryCount
|| SessionReopenEntryCount > WorkflowEntryCount
|| PermissionDependencyEntryCount > WorkflowEntryCount)
{
return false;
}
return (ActiveIssueCount <= 0 || ActiveIssue.IsStructurallyValid())
&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Entries)
&& HyperTwistRecognitionTypesInternal::AreAllItemsStructurallyValid(Issues)
&& HyperTwistRecognitionTypesInternal::AreAllStringsPopulated(AvailableActionIds);
}

View file

@ -3647,6 +3647,11 @@ UHyperTwistSkillCoreLibrary::DeriveSkillContinuityResumeState(
}
else if (SkillId == TEXT("skill/capture-note"))
{
const bool bCanCaptureNotesNow =
KnowledgeNotesState.bUserNotesLaneAvailable
&& !KnowledgeNotesState.UserNotesPosture.bRequiresSeparateOwnerActivation
&& Entry->Status == EHyperTwistSkillStatus::ImplementedNow;
SkillState.InputStateKinds = {
TEXT("state/memory-knowledge-notes"),
TEXT("state/memory-user-notes-posture")
@ -3660,14 +3665,13 @@ UHyperTwistSkillCoreLibrary::DeriveSkillContinuityResumeState(
KnowledgeNotesState.UserNotesPosture.SummaryLine
);
SkillState.AvailableItemCount =
KnowledgeNotesState.bUserNotesLaneAvailable ? 1 : 0;
SkillState.AvailableItemCount = bCanCaptureNotesNow ? 1 : 0;
SkillState.BlockingItemCount =
KnowledgeNotesState.UserNotesPosture.bRequiresSeparateOwnerActivation ? 1 : 0;
SkillState.bLiveSkill = false;
SkillState.bReadsAuthoritativeStores =
KnowledgeNotesState.UserNotesPosture.bOwnershipJustified;
SkillState.bAvailableNow = KnowledgeNotesState.bUserNotesLaneAvailable;
SkillState.bAvailableNow = bCanCaptureNotesNow;
SkillState.bRequiresOwnerActivation =
KnowledgeNotesState.UserNotesPosture.bRequiresSeparateOwnerActivation;
SkillState.Summary =

View file

@ -20,6 +20,7 @@ VectorShell.
## Landed HyperTwist-owned entry points
- `.sentrux/rules.toml`
- `scripts/bootstrap-hypertwist-sentrux.sh`
- `scripts/run-hypertwist-sentrux-source-only.sh`
- `scripts/run-hypertwist-gitnexus-analyze.sh`
- `scripts/run-hypertwist-gitnexus-status.sh`
@ -56,9 +57,16 @@ Resolution order for the analyzer binary is now HyperTwist-owned first:
- `HYPERTWIST_SENTRUX_BINARY` if explicitly provided
- repo-local `./sentrux` or `./sentrux.exe` if present
- repo-local `tools/sentrux/bin/sentrux` or `tools/sentrux/bin/sentrux.exe`
- `sentrux` on `PATH`
- the retained local fallback under `/home/dev/src/VectorShell/sentrux`
If the repo-local tools path is empty, materialize it with:
```bash
scripts/bootstrap-hypertwist-sentrux.sh
```
Current rules enforce:
- no cycles
@ -237,6 +245,129 @@ Important nuance from the `2026-06-22` follow-up:
family extraction or multi-header ownership separation for the remaining
validator clusters rather than more in-place header-local helperization
## `2026-06-23` continuation refresh
Additional same-lane follow-up on `2026-06-23`:
- the remaining inline validator clusters in
`HyperTwistSkillTypes.h` and `HyperTwistRecognitionTypes.h` were then moved
further out of the public headers into dedicated private translation units:
- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistSkills/HyperTwistSkillTypes.cpp`
- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistRecognition/HyperTwistRecognitionTypes.cpp`
- a public-website/manual continuation also landed in the same pass so the
docs/resources/support surfaces now explicitly project current keyboard,
higher-dimensional control, and unfinished XR/controller truth instead of
only the browser-versus-desktop topology boundary
- focused website coverage for
`src/__tests__/public-marketing-pages.test.tsx` and
`src/__tests__/protected-app-pages.test.tsx` passed after that public-manual
continuation
- a fresh full website validation pass then stayed green:
- `npm --prefix website test -- --run`
- `37` test files passed
- `137` tests passed
- the same widened public-manual packet also kept the production website build
green under `npm --prefix website run build`
Current highest-signal structural truth after that `2026-06-23` continuation:
- `scripts/run-hypertwist-sentrux-source-only.sh` now reports `Quality: 6070`
- the only remaining reported `sentrux` debt is still:
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistRecognition/HyperTwistRecognitionTypes.h:IsStructurallyValid (308 lines)`
- that remaining hit is now more likely a parser/grouping artifact than a new
broad website or browser regression, because the website/manual widening
stayed structurally clean and the real validator ownership was moved out of
the header family rather than expanded inside it
Additional same-lane follow-up later on `2026-06-23`:
- `scripts/run-hypertwist-gitnexus-analyze.sh` re-indexed the bounded
source-only mirror successfully at `16,042` nodes, `37,412` edges,
`643` clusters, and `300` flows
- `scripts/run-hypertwist-gitnexus-status.sh` again reported the bounded
mirror `Status: up-to-date`
- a fresh full website validation rerun stayed green again:
- `npm --prefix website test -- --run`
- `37` test files passed
- `137` tests passed
- duration `4.63s`
- `npm --prefix website run build`
- Vite production build succeeded
- `scripts/run-hypertwist-sentrux-source-only.sh` improved again to
`Quality: 6076`
- one more out-of-header migration moved
`FHyperTwistSpeechExternalDictationShellProfile::IsStructurallyValid()`
into `Private/HyperTwistRecognition/HyperTwistRecognitionTypes.cpp`
- the same remaining reported `sentrux` hit still stayed fixed at
`HyperTwistRecognitionTypes.h:IsStructurallyValid (308 lines)` even after
that migration, which further supports the current interpretation that this
residual is a repeated-name/grouping artifact inside the analyzer rather
than one newly expanded high-risk validator body
- the public-website lane was then refactored into bounded per-page modules so
the website manual/distribution surface is no longer concentrated in one
large `public-pages.tsx` owner
- the public route tree then stopped lazy-loading the old barrel and now loads
`public-pages-marketing` and `public-pages-commerce` directly, which restored
real route-level bundle separation instead of keeping one coarse public-pages
chunk
- HyperTwist also gained a repo-local `scripts/bootstrap-hypertwist-sentrux.sh`
helper plus `tools/sentrux/bin/` landing zone so the analyzer path can be
materialized under HyperTwist authority instead of depending only on
cross-repo memory
- after that same refactor/tooling continuation, the repo-local materialized
analyzer reran successfully through
`scripts/run-hypertwist-sentrux-source-only.sh` at `Quality: 6032`
- the same single residual violation remained:
`HyperTwistRecognitionTypes.h:IsStructurallyValid (308 lines)`
- that lower numeric score did not reopen cycle debt or website/page-module
god-file debt; it still reported the same one residual recognition-header hit
and no new browser/website structural regression
Latest same-lane follow-up later on `2026-06-23`:
- the remaining repeated-name recognition validator hotspot was then reduced
again by moving these larger header-local validators into
`Private/HyperTwistRecognition/HyperTwistRecognitionTypes.cpp`:
- `FHyperTwistVisionShellProfile::IsStructurallyValid()`
- `FHyperTwistVisionSolveExplanationProfile::IsStructurallyValid()`
- `FHyperTwistVisionCorrectionState::IsStructurallyValid()`
- `FHyperTwistSpeechProviderRoutingPolicy::IsStructurallyValid()`
- after that out-of-header continuation,
`scripts/run-hypertwist-sentrux-source-only.sh` reached `Quality: 6112`
and all `7` rules passed with no remaining violations
- `scripts/run-hypertwist-gitnexus-analyze.sh` then re-indexed the bounded
source-only mirror successfully at `16,055` nodes, `37,472` edges,
`645` clusters, and `300` flows
- `scripts/run-hypertwist-gitnexus-status.sh` again reported the bounded
mirror `Status: up-to-date`
- the tightened public/manual route split remained green under focused website
validation:
- `npm test -- --run src/__tests__/public-marketing-pages.test.tsx src/__tests__/protected-app-pages.test.tsx`
- `2` test files passed
- `11` tests passed
- the production website build remained green under `npm run build` in
`website/`
- the embedded browser runtime verification and production build also remained
green under:
- `npm run verify:shell` in `Content/Browser/`
- `npm run build` in `Content/Browser/`
- the same lane also preserved remote validation truth for the repaired skill
fixture packet:
- all `9` Windows Unreal automation reports under
`Skill-S3-Full-PostFixture-*` were present
- every report recorded `Succeeded: true`
- the green set covered `S3A`, `S3B`, and `S3C` continuity, authoritative,
and serialization filters
Current highest-signal structural truth after this latest continuation:
- HyperTwist now has repo-owned `sentrux` and `GitNexus` entry points that are
both revalidated and green on the bounded source-only mirror
- the public/manual/browser lane stayed validation-clean while the Unreal
validator ownership was pushed farther out of public headers
- the repaired skill-memory fixture lane is now fully green on the real remote
Windows Unreal path across all `9` focused `S3` reports
## Out of scope
This note does not:

View file

@ -50,6 +50,15 @@ Fallback connect-back shape when `22022` is occupied or stale:
ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no -o StrictHostKeyChecking=accept-new -o ConnectTimeout=10 -p 22023 -l 'DESKTOP-KS3VGHU\\anthracite ace' localhost
```
Verified helper shape for short Windows-side PowerShell diagnostics on the same
lane:
```bash
HYPERTWIST_REMOTE_WINDOWS_PASSWORD='...' \
scripts/run-hypertwist-remote-windows-powershell.sh \
--command 'Write-Output ("ComputerName=" + $env:COMPUTERNAME)'
```
## Current Linux-side pickup sequence
For a HyperTwist AI session that starts on Linux and needs to pick up the live
@ -148,6 +157,27 @@ Live follow-up on `2026-06-04` established these current facts:
- `22023` and `22024` were not visible in the latest probe and should be
treated as unavailable until re-established
- live `whoami` over `22022` again returned `desktop-ks3vghu\anthracite ace`
- the repo now also carries
`scripts/run-hypertwist-remote-windows-powershell.sh` as a bounded encoded-
PowerShell wrapper for the reverse-SSH lane so future sessions can run short
diagnostics or automation commands through `localhost:22022` without brittle
nested shell quoting
- the repo now also carries
`scripts/run-hypertwist-remote-unreal-automation.sh` as a thin first-party
helper that builds canonical `UnrealEditor-Cmd` automation invocations on top
of that encoded-PowerShell wrapper for the maintained
`C:\HyperTwist_worktrees\phase10validate` lane
- the repo now also carries
`scripts/run-hypertwist-remote-unreal-automation-sequence.sh` as a thin
first-party fail-fast helper for short ordered batches of focused automation
reruns on that same maintained validation lane
- the repo now also carries
`scripts/run-hypertwist-remote-unreal-build.sh` as a thin first-party helper
that builds canonical `Build.bat` invocations on top of that same encoded-
PowerShell wrapper for the maintained
`C:\HyperTwist_worktrees\phase10validate` lane, with the currently verified
reverse-lane low-memory posture `-NoUBA -MaxParallelActions=2` as its
default build shape
The sensitive runbook now carries the exact current Windows-side tunnel
commands, known-hosts scratch file, listener verification command, reverse-sync
@ -564,6 +594,41 @@ Operational rules reinforced by this proof:
- when the export helper reports success, do one lightweight media sanity check
on the canonical MP4 rather than trusting file existence alone; current proof
used `ffprobe` to confirm codec, resolution, frame count, and duration
- when the refreshed reverse-SSH Windows lane only has about `1.2 GB` of free
physical memory and the host is still carrying large resident
`chrome.exe` / `Code.exe` workloads, expect UnrealBuildTool to fall back to
one active compiler worker; that is a slow-but-healthy memory-pressure
condition, not by itself proof of tunnel corruption or a looping build
- when a future session needs a short bounded PowerShell diagnostic over the
reverse-SSH lane, prefer
`scripts/run-hypertwist-remote-windows-powershell.sh` over ad hoc nested
shell quoting; the wrapper was re-proved on `2026-06-23` against the live
`22022` lane with `ComputerName=DESKTOP-KS3VGHU`
- when a future session needs a focused `UnrealEditor-Cmd` automation rerun on
the maintained Windows lane, prefer
`scripts/run-hypertwist-remote-unreal-automation.sh`; its generated command
shape was dry-run-validated on `2026-06-23` for
`HyperTwist.FirstParty.Skill` before the next live post-build invocation
- when that future session instead needs a short ordered batch of those focused
automation reruns, prefer
`scripts/run-hypertwist-remote-unreal-automation-sequence.sh`; its generated
command shape was dry-run-validated on `2026-06-23`
Additional `2026-06-23` lane truth:
- the primary tunnel on `localhost:22022` remained healthy for a same-lane
skill-memory repair continuation
- the isolated Windows build root again stayed
`C:\HyperTwist_worktrees\phase10validate`
- a safe narrow-sync route was re-proved from the Windows side by using the
remote host's own `scp.exe` plus the retained VPS key to pull changed files
directly from `root@212.227.13.220` into that isolated worktree
- that route is now suitable when the active lane needs only a few touched
Unreal files refreshed in the maintained validation tree and a broad
reverse-sync would be wasteful or riskier than necessary
- after that narrow sync, the authoritative incremental Unreal editor rebuild
succeeded and the widened `S3` skill-memory automation packet finished with
all `9` expected `Skill-S3-Full-PostFixture-*` reports present and green
## Addendum - 2026-06-03 (stale-listener recovery)

View file

@ -267,6 +267,55 @@ Operational reading:
it as stale and shift to `localhost:22023`
- if `22023` is not visibly listening, do not assume fallback availability;
re-establish it first or report that only the primary lane is currently live
- when a short bounded Windows-side PowerShell diagnostic or automation command
is needed from Linux over the tunnel, prefer
`scripts/run-hypertwist-remote-windows-powershell.sh` over ad hoc nested
shell quoting; the wrapper encodes the payload for `powershell -EncodedCommand`
and was re-proved against the live `22022` lane on `2026-06-23`
- when the next step is a focused `UnrealEditor-Cmd` automation rerun on the
maintained Windows worktree, prefer
`scripts/run-hypertwist-remote-unreal-automation.sh`; it composes canonical
`-NullRHI`, `-ReportExportPath`, `-AbsLog`, and single-filter
`Automation RunTests ...; Quit` invocations on top of that encoded-
PowerShell wrapper, and its generated command shape was dry-run-validated on
`2026-06-23`
- when the next step is a short ordered batch of focused automation reruns on
that same maintained Windows worktree, prefer
`scripts/run-hypertwist-remote-unreal-automation-sequence.sh`; it composes
repeated fail-fast invocations of the single-filter wrapper in the exact
order provided, and its generated command shape was dry-run-validated on
`2026-06-23`
- when the next step is the authoritative remote Unreal editor build itself on
the maintained Windows worktree, prefer
`scripts/run-hypertwist-remote-unreal-build.sh`; it composes the verified
`Build.bat` invocation on top of that same encoded-PowerShell wrapper,
defaults the reverse-SSH lane to the maintained
`C:\HyperTwist_worktrees\phase10validate` root, and bakes in the
currently-verified low-memory recovery posture `-NoUBA -MaxParallelActions=2`
unless explicitly overridden. Its generated command shape was dry-run-
validated on `2026-06-23`
Canonical helper shape for the next focused post-build reruns:
```bash
HYPERTWIST_REMOTE_WINDOWS_PASSWORD='...' \
scripts/run-hypertwist-remote-unreal-automation.sh \
--filter HyperTwist.FirstParty.Skill \
--report-name Skill-Verify
HYPERTWIST_REMOTE_WINDOWS_PASSWORD='...' \
scripts/run-hypertwist-remote-unreal-automation.sh \
--filter HyperTwist.Permissive.WhisperCpp \
--report-name WhisperCpp-Verify
HYPERTWIST_REMOTE_WINDOWS_PASSWORD='...' \
scripts/run-hypertwist-remote-unreal-automation-sequence.sh \
--report-prefix Skill-S3 \
--filter HyperTwist.FirstParty.Skill.PhaseS3A.ContinuityResumeCoverage \
--filter HyperTwist.FirstParty.Skill.PhaseS3A.AuthoritativeStoreRead \
--filter HyperTwist.FirstParty.Skill.PhaseS3A.SerializationRoundTrip
```
- when recovering from a stale listener, run a split sequence:
1. smoke login/identity check
2. canonical Unreal build command with explicit result markers
@ -305,11 +354,52 @@ Operational reading:
before building; preserving old mtimes can leave stale
`Intermediate\Build\Win64\UnrealEditor\Inc\UnrealHyperTwist` outputs in place
and surface misleading reflected-type or generated-header failures
- when the reverse-SSH Windows lane only has about `1.2 GB` of free physical
memory and the host still has large resident `chrome.exe` / `Code.exe`
workloads, expect UnrealBuildTool to serialize down to one active compiler
worker; treat that as a slow-but-healthy memory-pressure condition rather than
as tunnel corruption or a looping build unless the compile output itself
stalls or errors
- when a logical slice authors new `.umap` or `.uasset` authority surfaces in an
isolated Windows worktree, pull those assets back into the tracked repo before
calling the slice landed; remote-only authored assets are validation evidence,
not final repo truth
## Addendum - 2026-06-23 (skill-memory fixture repair and full `S3` proof)
Live follow-up on `2026-06-23` established these additional facts:
- the maintained validation root again stayed
`C:\HyperTwist_worktrees\phase10validate`
- Windows-side `scp.exe` running on the remote host was re-proved as a safe
narrow-sync route from the VPS into that isolated worktree for touched
source files, avoiding a broad reverse-sync just to refresh a few Unreal
translation units
- after the touched skill-memory source files were hash-matched into that
worktree, the authoritative incremental editor rebuild succeeded there with
`Result: Succeeded` and UnrealBuildTool `Total execution time: 104.88
seconds`
- a fresh focused `S3A` rerun then passed on that rebuilt binary
- the widened same-lane follow-up then produced all `9` expected
`Skill-S3-Full-PostFixture-*` automation report folders under
`Saved\AutomationReports`
- each of those `9` report `index.json` files recorded a green result with
`Succeeded: true`, `SucceededCount: 1`, and `FailedCount: 0`
- that green set covered:
- `HyperTwist.FirstParty.Skill.PhaseS3A.ContinuityResumeCoverage`
- `HyperTwist.FirstParty.Skill.PhaseS3A.AuthoritativeStoreRead`
- `HyperTwist.FirstParty.Skill.PhaseS3A.SerializationRoundTrip`
- `HyperTwist.FirstParty.Skill.PhaseS3B.RecallCompactViewCoverage`
- `HyperTwist.FirstParty.Skill.PhaseS3B.AuthoritativeCompactViewLinkage`
- `HyperTwist.FirstParty.Skill.PhaseS3B.SerializationRoundTrip`
- `HyperTwist.FirstParty.Skill.PhaseS3C.WorkflowMemoryCaptureCoverage`
- `HyperTwist.FirstParty.Skill.PhaseS3C.AuthoritativeWorkflowCaptureBoundaries`
- `HyperTwist.FirstParty.Skill.PhaseS3C.SerializationRoundTrip`
This extends the doctrine from classic-cube, package, higher-dimensional, and
media-export proof into the real remote skill-memory validation lane on the
same maintained reverse-SSH path.
## Closeout wording requirement
Every Unreal C++ closeout should say one of these explicitly:

View file

@ -71,6 +71,18 @@ Current truthful product wording should say:
- full VR/controller/settings polish lane: not yet complete enough to market as
finished
## Public-surface consequence
The same truth should remain visible on the public website and public operator
manual:
- docs/resources/support surfaces should explicitly distinguish current keyboard
and higher-dimensional control ownership from unfinished VR/controller claims
- public copy should not imply that `EnhancedInput` plus motion-controller axis
groundwork already equals a finished OpenXR/runtime or rebinding lane
- browser/distribution pages may describe the simulator input posture, but they
must not market browser control parity with the native runtime
## Next clean implementation packet
If the project wants to raise this lane from “groundwork exists” to “shipping

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,82 @@
#!/usr/bin/env bash
set -euo pipefail
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
dest_dir="$repo_root/tools/sentrux/bin"
dest_linux="$dest_dir/sentrux"
dest_windows="$dest_dir/sentrux.exe"
vector_sentrux_binary="/home/dev/src/VectorShell/sentrux/target/release/sentrux"
vector_sentrux_manifest="/home/dev/src/VectorShell/sentrux/Cargo.toml"
scriptorium_sentrux_windows="/home/dev/src/ScriptoriumAI/sentrux.exe"
usage() {
cat <<'EOF'
Usage:
scripts/bootstrap-hypertwist-sentrux.sh [--if-missing]
Materializes a repo-local sentrux binary under tools/sentrux/bin/ using the
best available retained source on this machine.
Resolution order:
1. existing VectorShell Linux build artifact
2. local VectorShell source build via cargo
3. local ScriptoriumAI Windows binary
EOF
}
copy_binary() {
local source_path="$1"
local destination_path="$2"
mkdir -p "$dest_dir"
cp "$source_path" "$destination_path"
chmod +x "$destination_path" 2>/dev/null || true
printf 'Materialized sentrux at %s from %s\n' "$destination_path" "$source_path"
}
if [[ "${1:-}" == "--help" ]]; then
usage
exit 0
fi
if [[ "${1:-}" == "--if-missing" ]]; then
if [[ -x "$dest_linux" || -x "$dest_windows" ]]; then
printf 'Repo-local sentrux already present under %s\n' "$dest_dir"
exit 0
fi
elif [[ $# -gt 0 ]]; then
usage >&2
exit 1
fi
if [[ -x "$vector_sentrux_binary" ]]; then
copy_binary "$vector_sentrux_binary" "$dest_linux"
exit 0
fi
if command -v cargo >/dev/null 2>&1 && [[ -f "$vector_sentrux_manifest" ]]; then
cargo build --quiet --release --manifest-path "$vector_sentrux_manifest" --bin sentrux
if [[ -x "$vector_sentrux_binary" ]]; then
copy_binary "$vector_sentrux_binary" "$dest_linux"
exit 0
fi
fi
if [[ -f "$scriptorium_sentrux_windows" ]]; then
copy_binary "$scriptorium_sentrux_windows" "$dest_windows"
exit 0
fi
cat >&2 <<EOF
Unable to materialize a repo-local sentrux binary.
Checked:
- $vector_sentrux_binary
- $vector_sentrux_manifest
- $scriptorium_sentrux_windows
Provide HYPERTWIST_SENTRUX_BINARY directly or place a compatible sentrux binary
under tools/sentrux/bin/.
EOF
exit 1

View file

@ -0,0 +1,102 @@
#!/usr/bin/env bash
set -euo pipefail
usage() {
cat <<'EOF'
Usage:
HYPERTWIST_REMOTE_WINDOWS_PASSWORD=... \
scripts/run-hypertwist-remote-unreal-automation-sequence.sh \
--filter HyperTwist.FirstParty.Skill.PhaseS3A.ContinuityResumeCoverage \
--filter HyperTwist.FirstParty.Skill.PhaseS3A.AuthoritativeStoreRead
Options:
--filter <automation-filter>
Required. May be repeated. Filters are run sequentially in the order given.
--report-prefix <name>
Optional prefix for per-filter report names.
--extra-arg <value>
Append an extra UnrealEditor-Cmd.exe argument to every filter run.
--dry-run
Print the underlying wrapper invocations instead of executing them.
EOF
}
filters=()
report_prefix=""
dry_run="false"
extra_args=()
while [[ $# -gt 0 ]]; do
case "$1" in
--filter)
filters+=("${2:-}")
shift 2
;;
--report-prefix)
report_prefix="${2:-}"
shift 2
;;
--extra-arg)
extra_args+=("${2:-}")
shift 2
;;
--dry-run)
dry_run="true"
shift
;;
-h|--help)
usage
exit 0
;;
*)
usage >&2
exit 1
;;
esac
done
if [[ ${#filters[@]} -eq 0 ]]; then
echo "Provide at least one --filter." >&2
exit 1
fi
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
single_wrapper="${script_dir}/run-hypertwist-remote-unreal-automation.sh"
if [[ ! -x "$single_wrapper" ]]; then
echo "Expected executable wrapper at $single_wrapper" >&2
exit 1
fi
sanitize_report_name() {
printf '%s' "$1" | sed 's/[^[:alnum:]._+-]/_/g'
}
for filter in "${filters[@]}"; do
report_name="$(sanitize_report_name "$filter")"
if [[ -n "$report_prefix" ]]; then
report_name="${report_prefix}-$(sanitize_report_name "$filter")"
fi
command=(
"$single_wrapper"
--filter "$filter"
--report-name "$report_name"
)
for extra_arg in "${extra_args[@]}"; do
command+=(--extra-arg "$extra_arg")
done
if [[ "$dry_run" == "true" ]]; then
printf '%q ' "${command[@]}"
printf '\n'
continue
fi
echo "Running remote Unreal automation filter: $filter"
"${command[@]}"
done

View file

@ -0,0 +1,161 @@
#!/usr/bin/env bash
set -euo pipefail
usage() {
cat <<'EOF'
Usage:
HYPERTWIST_REMOTE_WINDOWS_PASSWORD=... \
scripts/run-hypertwist-remote-unreal-automation.sh --filter HyperTwist.FirstParty.Skill
Options:
--filter <automation-filter>
Required Unreal automation filter.
--report-name <name>
Optional report/log folder suffix. Defaults to a sanitized filter name.
--extra-arg <value>
Append an extra UnrealEditor-Cmd.exe argument. May be repeated.
--dry-run
Print the generated remote PowerShell payload instead of executing it.
Environment:
HYPERTWIST_REMOTE_WINDOWS_PASSWORD Required by the underlying tunnel wrapper.
HYPERTWIST_REMOTE_WINDOWS_WORKTREE_ROOT Optional, defaults to C:\HyperTwist_worktrees\phase10validate
HYPERTWIST_REMOTE_WINDOWS_PROJECT_PATH Optional, defaults beneath the worktree root.
HYPERTWIST_REMOTE_WINDOWS_UNREAL_EDITOR_CMD
Optional, defaults to the UE 5.7 UnrealEditor-Cmd.exe path.
HYPERTWIST_REMOTE_WINDOWS_AUTOMATION_REPORT_ROOT
Optional, defaults beneath Saved\AutomationReports.
HYPERTWIST_REMOTE_WINDOWS_LOG_ROOT Optional, defaults beneath Saved\Logs.
EOF
}
filter=""
report_name=""
dry_run="false"
extra_args=()
while [[ $# -gt 0 ]]; do
case "$1" in
--filter)
filter="${2:-}"
shift 2
;;
--report-name)
report_name="${2:-}"
shift 2
;;
--extra-arg)
extra_args+=("${2:-}")
shift 2
;;
--dry-run)
dry_run="true"
shift
;;
-h|--help)
usage
exit 0
;;
*)
usage >&2
exit 1
;;
esac
done
if [[ -z "$filter" ]]; then
echo "Provide --filter." >&2
exit 1
fi
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
remote_ps_wrapper="${script_dir}/run-hypertwist-remote-windows-powershell.sh"
if [[ ! -x "$remote_ps_wrapper" ]]; then
echo "Expected executable wrapper at $remote_ps_wrapper" >&2
exit 1
fi
worktree_root="${HYPERTWIST_REMOTE_WINDOWS_WORKTREE_ROOT:-C:\\HyperTwist_worktrees\\phase10validate}"
project_path="${HYPERTWIST_REMOTE_WINDOWS_PROJECT_PATH:-${worktree_root}\\UnrealHyperTwist\\UnrealHyperTwist.uproject}"
editor_cmd_path="${HYPERTWIST_REMOTE_WINDOWS_UNREAL_EDITOR_CMD:-C:\\Program Files\\Epic Games\\UE_5.7\\Engine\\Binaries\\Win64\\UnrealEditor-Cmd.exe}"
report_root="${HYPERTWIST_REMOTE_WINDOWS_AUTOMATION_REPORT_ROOT:-${worktree_root}\\UnrealHyperTwist\\Saved\\AutomationReports}"
log_root="${HYPERTWIST_REMOTE_WINDOWS_LOG_ROOT:-${worktree_root}\\UnrealHyperTwist\\Saved\\Logs}"
if [[ -z "$report_name" ]]; then
report_name="$(printf '%s' "$filter" | sed 's/[^[:alnum:]._+-]/_/g')"
fi
report_export_path="${report_root}\\${report_name}"
abs_log_path="${log_root}\\${report_name}.log"
powershell_payload="$(
python3 - <<'PY' \
"$editor_cmd_path" \
"$project_path" \
"$report_export_path" \
"$abs_log_path" \
"$filter" \
"${extra_args[@]}"
import sys
editor_cmd_path, project_path, report_export_path, abs_log_path, filter_name, *extra_args = sys.argv[1:]
def ps_single_quote(value: str) -> str:
return "'" + value.replace("'", "''") + "'"
lines = [
f"$EditorCmdPath = {ps_single_quote(editor_cmd_path)}",
f"$ProjectPath = {ps_single_quote(project_path)}",
f"$ReportExportPath = {ps_single_quote(report_export_path)}",
f"$AbsLogPath = {ps_single_quote(abs_log_path)}",
f"$Filter = {ps_single_quote(filter_name)}",
"",
"New-Item -ItemType Directory -Force -Path $ReportExportPath | Out-Null",
"New-Item -ItemType Directory -Force -Path (Split-Path -Parent $AbsLogPath) | Out-Null",
"",
"if (-not (Test-Path -LiteralPath $EditorCmdPath)) {",
" throw \"UnrealEditor-Cmd.exe was not found at '$EditorCmdPath'.\"",
"}",
"",
"if (-not (Test-Path -LiteralPath $ProjectPath)) {",
" throw \"Project file was not found at '$ProjectPath'.\"",
"}",
"",
"& $EditorCmdPath `",
" $ProjectPath `",
" -unattended `",
" -nop4 `",
" -nosplash `",
" -NullRHI `",
" -log `",
" -stdout `",
" -FullStdOutLogOutput `",
" \"-AbsLog=$AbsLogPath\" `",
" \"-ReportExportPath=$ReportExportPath\" `",
" \"-ExecCmds=Automation RunTests $Filter\" `",
]
if extra_args:
for extra_arg in extra_args:
lines.append(f" {ps_single_quote(extra_arg)} `")
lines.extend([
" \"-TestExit=Automation Test Queue Empty\"",
"",
"exit $LASTEXITCODE",
])
print("\n".join(lines))
PY
)"
if [[ "$dry_run" == "true" ]]; then
printf '%s\n' "$powershell_payload"
exit 0
fi
exec "$remote_ps_wrapper" --command "$powershell_payload"

View file

@ -0,0 +1,213 @@
#!/usr/bin/env bash
set -euo pipefail
usage() {
cat <<'EOF'
Usage:
HYPERTWIST_REMOTE_WINDOWS_PASSWORD=... \
scripts/run-hypertwist-remote-unreal-build.sh
Options:
--target <name>
Optional Unreal build target. Defaults to UnrealHyperTwistEditor.
--platform <name>
Optional Unreal platform. Defaults to Win64.
--configuration <name>
Optional Unreal configuration. Defaults to Development.
--worktree-root <path>
Optional Windows worktree root. Defaults to C:\HyperTwist_worktrees\phase10validate.
--project-path <path>
Optional Windows .uproject path. Defaults beneath the worktree root.
--build-batch-path <path>
Optional Build.bat path. Defaults to the UE 5.7 installed-engine path.
--max-parallel-actions <count>
Optional MaxParallelActions override. Defaults to 2 for the remote lane.
--allow-uba
Allow UBA instead of forcing the verified remote-lane -NoUBA posture.
--extra-arg <value>
Append an extra Build.bat argument. May be repeated.
--dry-run
Print the generated remote PowerShell payload instead of executing it.
Environment:
HYPERTWIST_REMOTE_WINDOWS_PASSWORD Required by the underlying tunnel wrapper.
HYPERTWIST_REMOTE_WINDOWS_WORKTREE_ROOT Optional default for --worktree-root.
HYPERTWIST_REMOTE_WINDOWS_PROJECT_PATH Optional default for --project-path.
HYPERTWIST_REMOTE_WINDOWS_BUILD_BAT Optional default for --build-batch-path.
HYPERTWIST_REMOTE_WINDOWS_MAX_PARALLEL_ACTIONS
Optional default for --max-parallel-actions.
EOF
}
target_name="UnrealHyperTwistEditor"
platform_name="Win64"
configuration_name="Development"
worktree_root="${HYPERTWIST_REMOTE_WINDOWS_WORKTREE_ROOT:-C:\\HyperTwist_worktrees\\phase10validate}"
project_path=""
build_batch_path="${HYPERTWIST_REMOTE_WINDOWS_BUILD_BAT:-C:\\Program Files\\Epic Games\\UE_5.7\\Engine\\Build\\BatchFiles\\Build.bat}"
max_parallel_actions="${HYPERTWIST_REMOTE_WINDOWS_MAX_PARALLEL_ACTIONS:-2}"
allow_uba="false"
dry_run="false"
extra_args=()
while [[ $# -gt 0 ]]; do
case "$1" in
--target)
target_name="${2:-}"
shift 2
;;
--platform)
platform_name="${2:-}"
shift 2
;;
--configuration)
configuration_name="${2:-}"
shift 2
;;
--worktree-root)
worktree_root="${2:-}"
shift 2
;;
--project-path)
project_path="${2:-}"
shift 2
;;
--build-batch-path)
build_batch_path="${2:-}"
shift 2
;;
--max-parallel-actions)
max_parallel_actions="${2:-}"
shift 2
;;
--allow-uba)
allow_uba="true"
shift
;;
--extra-arg)
extra_args+=("${2:-}")
shift 2
;;
--dry-run)
dry_run="true"
shift
;;
-h|--help)
usage
exit 0
;;
*)
usage >&2
exit 1
;;
esac
done
if [[ -z "$project_path" ]]; then
project_path="${HYPERTWIST_REMOTE_WINDOWS_PROJECT_PATH:-${worktree_root}\\UnrealHyperTwist\\UnrealHyperTwist.uproject}"
fi
if [[ -z "$target_name" || -z "$platform_name" || -z "$configuration_name" || -z "$project_path" || -z "$build_batch_path" ]]; then
echo "Target, platform, configuration, project path, and Build.bat path must all be populated." >&2
exit 1
fi
if [[ -n "$max_parallel_actions" && ! "$max_parallel_actions" =~ ^[0-9]+$ ]]; then
echo "--max-parallel-actions must be numeric." >&2
exit 1
fi
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
remote_ps_wrapper="${script_dir}/run-hypertwist-remote-windows-powershell.sh"
if [[ ! -x "$remote_ps_wrapper" ]]; then
echo "Expected executable wrapper at $remote_ps_wrapper" >&2
exit 1
fi
powershell_payload="$(
python3 - <<'PY' \
"$build_batch_path" \
"$target_name" \
"$platform_name" \
"$configuration_name" \
"$project_path" \
"$max_parallel_actions" \
"$allow_uba" \
"${extra_args[@]}"
import sys
build_batch_path, target_name, platform_name, configuration_name, project_path, max_parallel_actions, allow_uba, *extra_args = sys.argv[1:]
def ps_single_quote(value: str) -> str:
return "'" + value.replace("'", "''") + "'"
lines = [
f"$BuildBatchPath = {ps_single_quote(build_batch_path)}",
f"$TargetName = {ps_single_quote(target_name)}",
f"$PlatformName = {ps_single_quote(platform_name)}",
f"$ConfigurationName = {ps_single_quote(configuration_name)}",
f"$ProjectPath = {ps_single_quote(project_path)}",
f"$MaxParallelActions = {max_parallel_actions}",
f"$AllowUba = ${'true' if allow_uba == 'true' else 'false'}",
"$ExtraArgs = @(",
]
for value in extra_args:
lines.append(f" {ps_single_quote(value)}")
lines.extend([
")",
"",
"if (-not (Test-Path -LiteralPath $BuildBatchPath)) {",
" throw \"Build.bat was not found at '$BuildBatchPath'.\"",
"}",
"",
"if (-not (Test-Path -LiteralPath $ProjectPath)) {",
" throw \"Project file was not found at '$ProjectPath'.\"",
"}",
"",
"$BuildArgs = @(",
" $TargetName",
" $PlatformName",
" $ConfigurationName",
" $ProjectPath",
" '-WaitMutex'",
" '-NoHotReloadFromIDE'",
")",
"",
"if (-not $AllowUba) {",
" $BuildArgs += '-NoUBA'",
"}",
"",
"if ($MaxParallelActions -gt 0) {",
" $BuildArgs += \"-MaxParallelActions=$MaxParallelActions\"",
"}",
"",
"if ($ExtraArgs.Count -gt 0) {",
" $BuildArgs += $ExtraArgs",
"}",
"",
"& $BuildBatchPath @BuildArgs",
"exit $LASTEXITCODE",
])
print("\n".join(lines))
PY
)"
if [[ "$dry_run" == "true" ]]; then
printf '%s\n' "$powershell_payload"
exit 0
fi
exec "$remote_ps_wrapper" --command "$powershell_payload"

View file

@ -0,0 +1,142 @@
#!/usr/bin/env bash
set -euo pipefail
usage() {
cat <<'EOF'
Usage:
HYPERTWIST_REMOTE_WINDOWS_PASSWORD=... \
scripts/run-hypertwist-remote-windows-file-sync.sh \
--file UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistBootstrap/HyperTwistContractLibrary.cpp
Options:
--file <path>
Relative repo path to copy into the remote Windows worktree. May be repeated.
--remote-root <path>
Optional Windows worktree root. Defaults to C:\HyperTwist_worktrees\phase10validate.
--dry-run
Print the copy plan without transferring files.
Environment:
HYPERTWIST_REMOTE_WINDOWS_PASSWORD Required password for the reverse-SSH Windows user.
HYPERTWIST_REMOTE_TUNNEL_PORT Optional, defaults to 22022.
HYPERTWIST_REMOTE_WINDOWS_USER Optional, defaults to "anthracite ace".
HYPERTWIST_REMOTE_TUNNEL_HOST Optional, defaults to "localhost".
EOF
}
if ! command -v sshpass >/dev/null 2>&1; then
echo "sshpass is required but was not found on PATH." >&2
exit 1
fi
if ! command -v sha256sum >/dev/null 2>&1; then
echo "sha256sum is required but was not found on PATH." >&2
exit 1
fi
if [[ -z "${HYPERTWIST_REMOTE_WINDOWS_PASSWORD:-}" ]]; then
echo "Set HYPERTWIST_REMOTE_WINDOWS_PASSWORD before using this wrapper." >&2
exit 1
fi
remote_root='C:\HyperTwist_worktrees\phase10validate'
chunk_size_bytes=65536
dry_run="false"
files=()
while [[ $# -gt 0 ]]; do
case "$1" in
--file)
files+=("${2:-}")
shift 2
;;
--remote-root)
remote_root="${2:-}"
shift 2
;;
--dry-run)
dry_run="true"
shift
;;
-h|--help)
usage
exit 0
;;
*)
usage >&2
exit 1
;;
esac
done
if [[ ${#files[@]} -eq 0 ]]; then
echo "Provide at least one --file." >&2
exit 1
fi
remote_port="${HYPERTWIST_REMOTE_TUNNEL_PORT:-22022}"
remote_user="${HYPERTWIST_REMOTE_WINDOWS_USER:-anthracite ace}"
remote_host="${HYPERTWIST_REMOTE_TUNNEL_HOST:-localhost}"
for relative_path in "${files[@]}"; do
if [[ "$relative_path" = /* ]]; then
echo "Use repo-relative paths only: $relative_path" >&2
exit 1
fi
if [[ ! -f "$relative_path" ]]; then
echo "File not found: $relative_path" >&2
exit 1
fi
windows_relative_path="${relative_path//\//\\}"
windows_dest_path="${remote_root}\\${windows_relative_path}"
local_hash="$(sha256sum "$relative_path" | awk '{print tolower($1)}')"
if [[ "$dry_run" == "true" ]]; then
printf '%s -> %s (%s)\n' "$relative_path" "$windows_dest_path" "$local_hash"
continue
fi
ssh_base=(
sshpass -p "${HYPERTWIST_REMOTE_WINDOWS_PASSWORD}"
ssh
-o StrictHostKeyChecking=no
-o PreferredAuthentications=password
-o PubkeyAuthentication=no
-p "${remote_port}"
-l "${remote_user}"
"${remote_host}"
)
"${ssh_base[@]}" \
"powershell -NoProfile -Command \"\$dest='${windows_dest_path}'; \$destDir = Split-Path -Parent \$dest; New-Item -ItemType Directory -Force -Path \$destDir | Out-Null; \$outputStream = [IO.File]::Open(\$dest, [IO.FileMode]::Create, [IO.FileAccess]::Write, [IO.FileShare]::None); \$outputStream.Dispose()\""
tmp_chunk_dir="$(mktemp -d)"
split -b "${chunk_size_bytes}" --numeric-suffixes=1 --suffix-length=4 \
"$relative_path" "${tmp_chunk_dir}/chunk-"
for chunk_path in "${tmp_chunk_dir}"/chunk-*; do
cat "$chunk_path" | \
"${ssh_base[@]}" \
"powershell -NoProfile -Command \"\$dest='${windows_dest_path}'; \$outputStream = [IO.File]::Open(\$dest, [IO.FileMode]::Append, [IO.FileAccess]::Write, [IO.FileShare]::None); try { [Console]::OpenStandardInput().CopyTo(\$outputStream) } finally { \$outputStream.Dispose() }\""
done
remote_hash="$(
"${ssh_base[@]}" \
"powershell -NoProfile -Command \"[Console]::Out.Write((Get-FileHash -LiteralPath '${windows_dest_path}' -Algorithm SHA256).Hash.ToLowerInvariant())\""
)"
rm -rf "$tmp_chunk_dir"
if [[ "$remote_hash" != "$local_hash" ]]; then
echo "Hash mismatch for $relative_path" >&2
echo " local : $local_hash" >&2
echo " remote: $remote_hash" >&2
exit 1
fi
printf 'Synced %s -> %s (%s)\n' "$relative_path" "$windows_dest_path" "$local_hash"
done

View file

@ -0,0 +1,90 @@
#!/usr/bin/env bash
set -euo pipefail
usage() {
cat <<'EOF'
Usage:
HYPERTWIST_REMOTE_WINDOWS_PASSWORD=... \
scripts/run-hypertwist-remote-windows-powershell.sh --command "Write-Output 'hello'"
HYPERTWIST_REMOTE_WINDOWS_PASSWORD=... \
scripts/run-hypertwist-remote-windows-powershell.sh --script-file ./script.ps1
Options:
--command <powershell>
Run the provided PowerShell source text.
--script-file <path>
Read PowerShell source from the given file.
Environment:
HYPERTWIST_REMOTE_WINDOWS_PASSWORD Required password for the reverse-SSH Windows user.
HYPERTWIST_REMOTE_TUNNEL_PORT Optional, defaults to 22022.
HYPERTWIST_REMOTE_WINDOWS_USER Optional, defaults to "anthracite ace".
HYPERTWIST_REMOTE_TUNNEL_HOST Optional, defaults to "localhost".
EOF
}
if [[ $# -lt 2 ]]; then
usage >&2
exit 1
fi
if ! command -v sshpass >/dev/null 2>&1; then
echo "sshpass is required but was not found on PATH." >&2
exit 1
fi
if [[ -z "${HYPERTWIST_REMOTE_WINDOWS_PASSWORD:-}" ]]; then
echo "Set HYPERTWIST_REMOTE_WINDOWS_PASSWORD before using this wrapper." >&2
exit 1
fi
script_text=""
case "$1" in
--command)
script_text="$2"
;;
--script-file)
if [[ ! -f "$2" ]]; then
echo "Script file not found: $2" >&2
exit 1
fi
script_text="$(<"$2")"
;;
-h|--help)
usage
exit 0
;;
*)
usage >&2
exit 1
;;
esac
remote_port="${HYPERTWIST_REMOTE_TUNNEL_PORT:-22022}"
remote_user="${HYPERTWIST_REMOTE_WINDOWS_USER:-anthracite ace}"
remote_host="${HYPERTWIST_REMOTE_TUNNEL_HOST:-localhost}"
script_preamble=$'$ProgressPreference = \'SilentlyContinue\'\n$ErrorActionPreference = \'Stop\'\n'
script_payload="${script_preamble}${script_text}"
encoded_command="$(
python3 - <<'PY' "$script_payload"
import base64
import sys
script = sys.argv[1]
print(base64.b64encode(script.encode("utf-16le")).decode("ascii"))
PY
)"
exec sshpass -p "${HYPERTWIST_REMOTE_WINDOWS_PASSWORD}" \
ssh \
-o StrictHostKeyChecking=no \
-o PreferredAuthentications=password \
-o PubkeyAuthentication=no \
-p "${remote_port}" \
-l "${remote_user}" \
"${remote_host}" \
"powershell -NoProfile -EncodedCommand ${encoded_command}"

View file

@ -5,6 +5,8 @@ repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
temp_root="${TMPDIR:-/tmp}/hypertwist-sentrux-source-only"
repo_local_sentrux_binary="$repo_root/sentrux"
repo_local_sentrux_windows_binary="$repo_root/sentrux.exe"
repo_tools_sentrux_binary="$repo_root/tools/sentrux/bin/sentrux"
repo_tools_sentrux_windows_binary="$repo_root/tools/sentrux/bin/sentrux.exe"
local_sentrux_binary="/home/dev/src/VectorShell/sentrux/target/release/sentrux"
local_sentrux_manifest="/home/dev/src/VectorShell/sentrux/Cargo.toml"
@ -24,6 +26,16 @@ resolve_sentrux_command() {
return 0
fi
if [[ -x "$repo_tools_sentrux_binary" ]]; then
printf '%s\n' "$repo_tools_sentrux_binary"
return 0
fi
if [[ -x "$repo_tools_sentrux_windows_binary" ]]; then
printf '%s\n' "$repo_tools_sentrux_windows_binary"
return 0
fi
if command -v sentrux >/dev/null 2>&1; then
printf 'sentrux\n'
return 0
@ -43,7 +55,7 @@ resolve_sentrux_command() {
}
sentrux_command="$(resolve_sentrux_command)" || {
echo "Unable to locate sentrux. Provide HYPERTWIST_SENTRUX_BINARY, add sentrux to PATH, place a repo-local sentrux binary at $repo_root, or keep /home/dev/src/VectorShell/sentrux available." >&2
echo "Unable to locate sentrux. Provide HYPERTWIST_SENTRUX_BINARY, run scripts/bootstrap-hypertwist-sentrux.sh, add sentrux to PATH, place a repo-local sentrux binary at $repo_root, or keep /home/dev/src/VectorShell/sentrux available." >&2
exit 1
}

15
tools/sentrux/README.md Normal file
View file

@ -0,0 +1,15 @@
# HyperTwist-local sentrux landing zone
This directory is the HyperTwist-owned location for a repo-local `sentrux`
binary.
Do not commit platform binaries here.
Use:
```bash
scripts/bootstrap-hypertwist-sentrux.sh
```
That helper materializes a local binary under `tools/sentrux/bin/` from the
best retained source available on this machine.

View file

@ -0,0 +1 @@

View file

@ -2,6 +2,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
import { cleanup, render, screen } from '@testing-library/react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { MemoryRouter } from 'react-router-dom'
import { ROUTER_FUTURE_FLAGS } from '../router/router-future'
const mockUsePlatformAuth = vi.fn()
const mockGetAuthHealth = vi.fn()
@ -31,7 +32,7 @@ function renderPage(page: React.ReactNode, initialEntry: string) {
return render(
<QueryClientProvider client={queryClient}>
<MemoryRouter initialEntries={[initialEntry]}>
<MemoryRouter initialEntries={[initialEntry]} future={ROUTER_FUTURE_FLAGS}>
{page}
</MemoryRouter>
</QueryClientProvider>,

View file

@ -547,6 +547,8 @@ describe('public marketing pages', () => {
expect(screen.getByText('Selected help lane')).toBeTruthy()
expect(screen.getByText('Launch readiness')).toBeTruthy()
expect(screen.getByText(/turning the preview lane into a public launch/i)).toBeTruthy()
expect(screen.getByText('If the desktop app is primary, why keep the web version?')).toBeTruthy()
expect(screen.getByText('Is VR/controller support already fully finished?')).toBeTruthy()
expect(screen.getByText('Support lanes')).toBeTruthy()
})
@ -650,6 +652,10 @@ describe('public marketing pages', () => {
expect(screen.getAllByText(/MagicCube5D dedicated-family training map: passed/i).length).toBeGreaterThan(0)
expect(screen.getByText('Operator playbooks')).toBeTruthy()
expect(screen.getByText('Simulator use today')).toBeTruthy()
expect(screen.getByText('Higher-dimensional runtime guide')).toBeTruthy()
expect(screen.getByText('Current control and device posture')).toBeTruthy()
expect(screen.getByText('Deployment readiness snapshot')).toBeTruthy()
expect(screen.getByText('XR groundwork exists, but the full VR lane is not finished')).toBeTruthy()
expect(screen.getByText('Higher-dimensional runtime ownership')).toBeTruthy()
})
@ -715,6 +721,10 @@ describe('public marketing pages', () => {
expect(screen.getByText('Operator manual')).toBeTruthy()
expect(screen.getByText('1. Start in the browser shell')).toBeTruthy()
expect(screen.getByText('Simulator manual')).toBeTruthy()
expect(screen.getByText('Higher-dimensional family guide')).toBeTruthy()
expect(screen.getByText('Deployment readiness manual')).toBeTruthy()
expect(screen.getByText('Input and device posture')).toBeTruthy()
expect(screen.getAllByText('Keyboard and mouse ship today').length).toBeGreaterThan(0)
expect(screen.getByText('Feature-registry-backed wording only')).toBeTruthy()
expect(await screen.findByRole('link', { name: /open public docs portal/i })).toBeTruthy()
})

View file

@ -0,0 +1,88 @@
import type { ReactNode } from 'react'
import { Link } from 'react-router-dom'
import {
brandConfig,
downloadTargets,
mplSourceUrl,
openSourceRepoUrl,
planCatalog,
publicDocsUrl,
releaseNotesUrl,
} from '../site-config'
import { isExternalHref } from '../site-routes'
export const supportTopicGuidance: Record<string, { title: string; description: string }> = {
'launch-readiness': {
title: 'Launch readiness',
description:
'Need help turning the preview lane into a public launch? We can walk through checkout wiring, download release targets, notices, and corresponding-source publication.',
},
'operator-access': {
title: 'Operator access',
description:
'Use this lane when you need operator checkout, entitlement enablement, or help reaching the protected desktop-download surface.',
},
'studio-rollout': {
title: 'Studio rollout',
description:
'Use this lane for higher-dimensional rollout planning, deployment coordination, or production-lane package and notice readiness.',
},
}
export const explorerFallbackPlan = planCatalog.find((plan) => plan.key === 'explorer') ?? planCatalog[0]
export const operatorFallbackPlan = planCatalog.find((plan) => plan.key === 'operator') ?? planCatalog[1]
export const studioFallbackPlan = planCatalog.find((plan) => plan.key === 'studio') ?? planCatalog[2]
export const releaseCommerceFallback = {
operatorCheckoutUrl: isExternalHref(operatorFallbackPlan.ctaHref) ? operatorFallbackPlan.ctaHref : '',
studioCheckoutUrl: isExternalHref(studioFallbackPlan.ctaHref) ? studioFallbackPlan.ctaHref : '',
planPriceOperator: operatorFallbackPlan.price,
planPriceStudio: studioFallbackPlan.price,
}
export function buildPublicReleaseManifestFallback(supportEmail = brandConfig.contact.email) {
return {
downloadTargets,
publicDocsUrl,
releaseNotesUrl,
correspondingSourceUrl: mplSourceUrl,
openSourceRepoUrl,
supportEmail,
}
}
export function Section({
title,
description,
children,
}: {
title: string
description?: string
children: ReactNode
}) {
return (
<section className="page-section">
<div className="section-heading">
<h2>{title}</h2>
{description ? <p>{description}</p> : null}
</div>
{children}
</section>
)
}
export function PlanActionLink({ href, label }: { href: string; label: string }) {
if (isExternalHref(href)) {
return (
<a className="button button--primary button--full" href={href} target="_blank" rel="noreferrer">
{label}
</a>
)
}
return (
<Link className="button button--primary button--full" to={href}>
{label}
</Link>
)
}

View file

@ -0,0 +1,536 @@
import { useMemo } from 'react'
import { useQuery } from '@tanstack/react-query'
import { Link } from 'react-router-dom'
import { getReleaseManifest } from '../auth/auth-api'
import { MarketingShell } from '../components/layout/MarketingShell'
import { SiteMetadata } from '../components/seo/SiteMetadata'
import { PublicLaunchStatus } from '../components/ui/PublicLaunchStatus'
import { ReleaseValidationSummary } from '../components/ui/ReleaseValidationSummary'
import { paddleReadyDescription } from '../site-config'
import {
buildReleaseMetadataItems,
resolveReleaseCommerceView,
resolveReleaseManifestView,
} from '../release-manifest'
import { buildProtectedDownloadPath, buildSupportPath } from '../site-routes'
import {
deliverySurfaceCards,
desktopDownloadSteps,
desktopReleaseSignals,
digitalDeliveryCards,
distributionDoctrineCards,
openSourceNotices,
privacyBoundaryCards,
termsBoundaryCards,
} from '../site-data'
import {
buildPublicReleaseManifestFallback,
explorerFallbackPlan,
operatorFallbackPlan,
PlanActionLink,
releaseCommerceFallback,
Section,
studioFallbackPlan,
} from './public-page-helpers'
export function PricingPage() {
const releaseManifestQuery = useQuery({
queryKey: ['release-manifest', 'public'],
queryFn: getReleaseManifest,
retry: false,
})
const releaseCommerce = useMemo(
() => resolveReleaseCommerceView(releaseManifestQuery.data?.manifest, releaseCommerceFallback),
[releaseManifestQuery.data?.manifest],
)
const runtimePlanCatalog = useMemo(() => ([
explorerFallbackPlan,
{
...operatorFallbackPlan,
price: releaseCommerce.plan_price_operator,
ctaLabel: releaseCommerce.operator_checkout_url ? 'Open Paddle checkout' : 'Request operator access',
ctaHref: releaseCommerce.operator_checkout_url || buildSupportPath('operator-access'),
},
{
...studioFallbackPlan,
price: releaseCommerce.plan_price_studio,
ctaLabel: releaseCommerce.studio_checkout_url ? 'Open Paddle checkout' : 'Talk to HyperTwist',
ctaHref: releaseCommerce.studio_checkout_url || buildSupportPath('studio-rollout'),
},
]), [releaseCommerce])
return (
<>
<SiteMetadata
title="HyperTwist pricing"
description="View HyperTwist browser-access, operator, and studio pricing with Paddle-ready checkout posture and launch-honest download/legal guidance."
canonicalPath="/pricing"
/>
<MarketingShell
eyebrow="Paddle-ready plans"
title="Pricing that matches the actual delivery model."
lede="The browser shell handles account, release, and billing access. The simulator remains desktop-first. Prices and checkouts can be switched live through the same Paddle-ready structure used across the broader product family."
>
<Section title="Plan lineup" description={paddleReadyDescription}>
<div className="card-grid card-grid--pricing">
{runtimePlanCatalog.map((plan) => (
<article key={plan.key} className="card card--pricing">
<p className="status-pill">{plan.name}</p>
<h3>{plan.price}</h3>
<p>{plan.notes}</p>
<ul className="list">
{plan.features.map((feature) => (
<li key={feature}>{feature}</li>
))}
</ul>
<PlanActionLink href={plan.ctaHref} label={plan.ctaLabel} />
</article>
))}
</div>
</Section>
<Section title="Launch posture">
<PublicLaunchStatus />
</Section>
<Section
title="Why plans live in the browser while training stays native"
description="Commercial access, entitlement, and launch-readiness posture belong to the browser shell so the simulator can stay focused on training quality."
>
<div className="card-grid">
{deliverySurfaceCards.slice(0, 3).map((surface) => (
<article key={surface.title} className="card">
<h3>{surface.title}</h3>
<p>{surface.description}</p>
</article>
))}
</div>
</Section>
<Section title="Important launch note">
<article className="callout">
<p>
Public pricing, checkout, and download pages are distribution surfaces. Before external launch,
keep their legal footer and open-source notices link live and ensure the corresponding-source URL is configured for any downloadable build containing MPL-covered material.
</p>
</article>
</Section>
</MarketingShell>
</>
)
}
export function DownloadPage() {
const releaseManifestQuery = useQuery({
queryKey: ['release-manifest', 'public'],
queryFn: getReleaseManifest,
retry: false,
})
const releaseManifest = useMemo(
() => resolveReleaseManifestView(releaseManifestQuery.data?.manifest, buildPublicReleaseManifestFallback()),
[releaseManifestQuery.data?.manifest],
)
return (
<>
<SiteMetadata
title="Download HyperTwist desktop"
description="Download the HyperTwist desktop build, preserve your target platform into the protected release surface, and pair the installed app with your browser account."
canonicalPath="/download"
/>
<MarketingShell
eyebrow="Desktop distribution"
title="Download the desktop build and pair it with your browser account."
lede="The website provides account, release, and legal surfaces. The actual simulator ships through the desktop lane, with package validation and release discipline carried over from the HyperTwist roadmap."
>
{releaseManifestQuery.isLoading ? (
<Section title="Release manifest status">
<article className="callout">
<p>Loading the current server-backed release manifest. Static preview metadata remains visible until the live manifest arrives.</p>
</article>
</Section>
) : null}
{releaseManifestQuery.isError ? (
<Section title="Release manifest status">
<article className="callout">
<p>
The live release manifest could not be loaded from the auth server right now.
This page is showing bounded fallback site metadata instead of current runtime release authority.
</p>
</article>
</Section>
) : null}
<Section title="Available targets">
<div className="card-grid">
{releaseManifest.platforms.map((platform) => {
const metadataItems = buildReleaseMetadataItems(platform)
return (
<article key={platform.platform_key} className="card">
<h3>{platform.platform}</h3>
<p className="status-pill">{platform.subtitle}</p>
<p>{platform.details}</p>
{metadataItems.length > 0 ? (
<ul className="list top-gap">
{metadataItems.map((item) => (
<li key={`${platform.platform_key}-${item.label}`}>
{item.label}: {item.value}
</li>
))}
</ul>
) : null}
<ReleaseValidationSummary platform={platform} />
{platform.configured ? (
<Link className="button button--primary button--full" to={buildProtectedDownloadPath(platform.platform_key)}>
Sign in for {platform.platform} access
</Link>
) : (
<div className="button button--ghost button--full is-disabled" aria-disabled="true">
Release URL not configured yet
</div>
)}
</article>
)
})}
</div>
</Section>
<Section title="How the release lane works">
<div className="card-grid">
{desktopDownloadSteps.map((step, index) => (
<article key={step} className="card card--compact">
<p className="status-pill">{index + 1}</p>
<p>{step}</p>
</article>
))}
</div>
</Section>
<Section title="Release posture">
<PublicLaunchStatus title="Desktop release access stays launch-honest" />
</Section>
<Section
title="Browser and desktop responsibilities"
description="The release lane is easier to trust when the site explains why some actions stay public, some stay protected, and the simulator itself stays native."
>
<div className="card-grid">
{deliverySurfaceCards.map((surface) => (
<article key={surface.title} className="card">
<h3>{surface.title}</h3>
<p>{surface.description}</p>
</article>
))}
</div>
</Section>
<Section title="Release integrity and documentation">
<div className="card-grid">
{desktopReleaseSignals.map((signal) => (
<article key={signal.title} className="card">
<h3>{signal.title}</h3>
<p>{signal.description}</p>
</article>
))}
<article className="card">
<h3>Operator rollout references</h3>
<ul className="list">
{releaseManifest.public_docs_url ? (
<li>
Public docs:{' '}
<a href={releaseManifest.public_docs_url} target="_blank" rel="noreferrer">
{releaseManifest.public_docs_url}
</a>
</li>
) : (
<li>Public docs URL not configured yet.</li>
)}
{releaseManifest.release_notes_url ? (
<li>
Release notes:{' '}
<a href={releaseManifest.release_notes_url} target="_blank" rel="noreferrer">
{releaseManifest.release_notes_url}
</a>
</li>
) : (
<li>Release notes URL not configured yet.</li>
)}
<li>
Notices and source posture:{' '}
{releaseManifest.corresponding_source_url ? (
<a href={releaseManifest.corresponding_source_url} target="_blank" rel="noreferrer">
Corresponding source
</a>
) : (
'configure the corresponding-source URL before external launch'
)}
</li>
</ul>
</article>
</div>
</Section>
<Section title="Why this page does not expose raw download URLs">
<article className="callout">
<p>
HyperTwist treats desktop distribution as an account-gated release surface.
Public pages can describe supported targets and release posture, but the actual
download links live behind the protected dashboard where plan and entitlement
state are resolved.
</p>
<Link className="button button--ghost" to="/login">
Sign in to check access
</Link>
</article>
</Section>
<Section title="Pair the desktop app with your browser account">
<article className="callout">
<p>
After sign-in, open the operator dashboard to generate a desktop-link token.
That token is designed to hand browser identity and plan posture over to the local desktop app without exposing your password.
</p>
<Link className="button button--ghost" to="/app">
Open dashboard
</Link>
</article>
</Section>
</MarketingShell>
</>
)
}
export function OpenSourceNoticesPage() {
const releaseManifestQuery = useQuery({
queryKey: ['release-manifest', 'public'],
queryFn: getReleaseManifest,
retry: false,
})
const releaseManifest = useMemo(
() => resolveReleaseManifestView(releaseManifestQuery.data?.manifest, buildPublicReleaseManifestFallback()),
[releaseManifestQuery.data?.manifest],
)
return (
<>
<SiteMetadata
title="HyperTwist open-source notices"
description="Review HyperTwist public open-source notices and corresponding-source guidance for downloadable distribution surfaces."
canonicalPath="/open-source-notices"
/>
<MarketingShell
eyebrow="Legal and notices"
title="Open-source notices for public distribution surfaces."
lede="HyperTwist pricing, checkout, release, and download pages must make legal and corresponding-source guidance visible whenever shipped builds include MPL-covered material."
>
<Section title="Key components">
<div className="card-grid">
{openSourceNotices.map((item) => (
<article className="card" key={item.component}>
<h3>{item.component}</h3>
<p className="status-pill">{item.license}</p>
<p>{item.whyItMatters}</p>
</article>
))}
</div>
</Section>
<Section title="Corresponding source">
<div className="card">
<p>
MPL-covered shipped builds need a stable corresponding-source location for the exact distributed material.
</p>
<ul className="list">
<li>
Public corresponding-source URL:{' '}
{releaseManifest.corresponding_source_url ? (
<a href={releaseManifest.corresponding_source_url} target="_blank" rel="noreferrer">{releaseManifest.corresponding_source_url}</a>
) : (
'configure the public corresponding-source URL before external launch'
)}
</li>
<li>
Public repository / notices reference:{' '}
{releaseManifest.open_source_repo_url ? (
<a href={releaseManifest.open_source_repo_url} target="_blank" rel="noreferrer">{releaseManifest.open_source_repo_url}</a>
) : (
'configure the public repository/notices URL before external launch'
)}
</li>
</ul>
<p>
Official MPL 2.0 license text:{' '}
<a href="https://www.mozilla.org/en-US/MPL/2.0/" target="_blank" rel="noreferrer">
https://www.mozilla.org/en-US/MPL/2.0/
</a>
</p>
</div>
</Section>
<Section title="Distribution readiness">
<PublicLaunchStatus title="Notices and corresponding-source readiness" />
</Section>
<Section
title="Distribution doctrine"
description="These public legal surfaces should explain why the website is part of the release story without pretending it has replaced the native simulator."
>
<div className="card-grid">
{distributionDoctrineCards.map((card) => (
<article className="card" key={card.title}>
<h3>{card.title}</h3>
<p>{card.description}</p>
<ul className="list top-gap">
{card.bullets.map((bullet) => (
<li key={bullet}>{bullet}</li>
))}
</ul>
</article>
))}
</div>
</Section>
</MarketingShell>
</>
)
}
export function PrivacyPage() {
return (
<>
<SiteMetadata
title="HyperTwist privacy"
description="Understand the HyperTwist privacy posture for browser account access, desktop-link issuance, and the desktop-first simulator boundary."
canonicalPath="/privacy"
/>
<MarketingShell
eyebrow="Privacy"
title="Privacy posture"
lede="HyperTwist keeps the browser shell narrow and the simulator desktop-first. Privacy descriptions must reflect that separation clearly."
>
<Section title="Core points">
<article className="card">
<ul className="list">
<li>The public website stores account/session data needed for authentication, plan access, and desktop-link issuance.</li>
<li>The browser shell does not claim ownership over the full simulator runtime state unless a future browser-client packet is explicitly opened.</li>
<li>Support, billing, and release operations should collect only the data required to deliver digital access and maintain legal compliance.</li>
</ul>
</article>
</Section>
<Section
title="Practical privacy boundary"
description="Privacy wording should follow the actual product split instead of flattening the browser shell and native simulator into one vague surface."
>
<div className="card-grid">
{privacyBoundaryCards.map((card) => (
<article key={card.title} className="card">
<h3>{card.title}</h3>
<p>{card.description}</p>
<ul className="list top-gap">
{card.bullets.map((bullet) => (
<li key={bullet}>{bullet}</li>
))}
</ul>
</article>
))}
</div>
</Section>
</MarketingShell>
</>
)
}
export function TermsPage() {
return (
<>
<SiteMetadata
title="HyperTwist terms"
description="Review the HyperTwist terms of access for browser account routes, desktop delivery, and open-source notice obligations."
canonicalPath="/terms"
/>
<MarketingShell
eyebrow="Terms"
title="Terms of access"
lede="HyperTwist access is digital-first and plan-gated. Terms should match the actual delivery and account model."
>
<Section title="Service posture">
<article className="card">
<ul className="list">
<li>Browser access covers public pages, account, release, download, and operator/dashboard surfaces.</li>
<li>The simulator itself is delivered through the desktop lane unless a later browser-client branch is explicitly opened.</li>
<li>Downloaded builds and their public distribution pages remain subject to open-source notice and corresponding-source disclosure rules where applicable.</li>
</ul>
</article>
</Section>
<Section
title="Terms in practice"
description="These terms-oriented boundaries keep the public site, protected dashboard, and desktop simulator aligned with the actual delivery model."
>
<div className="card-grid">
{termsBoundaryCards.map((card) => (
<article key={card.title} className="card">
<h3>{card.title}</h3>
<p>{card.description}</p>
<ul className="list top-gap">
{card.bullets.map((bullet) => (
<li key={bullet}>{bullet}</li>
))}
</ul>
</article>
))}
</div>
</Section>
</MarketingShell>
</>
)
}
export function ShippingPaymentPage() {
return (
<>
<SiteMetadata
title="HyperTwist shipping and payment"
description="HyperTwist is delivered digitally through account access, release pages, and desktop downloads with Paddle-ready billing posture."
canonicalPath="/shipping-payment"
/>
<MarketingShell
eyebrow="Shipping & payment"
title="Digital delivery only"
lede="HyperTwist is not a physical-goods storefront. Delivery happens through authenticated account access, release pages, and desktop downloads."
>
<Section title="Delivery model">
<article className="card">
<p>{paddleReadyDescription}</p>
<ul className="list">
<li>No physical goods ship through this site.</li>
<li>Pricing and checkout are structured for Paddle-backed digital plans.</li>
<li>Desktop downloads must remain paired with public notices and legal links when required by shipped-code obligations.</li>
</ul>
</article>
</Section>
<Section
title="Digital delivery workflow"
description="A professional digital-delivery lane does more than expose a buy button. It keeps release posture, entitlement, and the desktop handoff coherent."
>
<div className="card-grid">
{digitalDeliveryCards.map((card) => (
<article key={card.title} className="card">
<h3>{card.title}</h3>
<p>{card.description}</p>
<ul className="list top-gap">
{card.bullets.map((bullet) => (
<li key={bullet}>{bullet}</li>
))}
</ul>
</article>
))}
</div>
</Section>
</MarketingShell>
</>
)
}

View file

@ -0,0 +1,733 @@
import { useDeferredValue, useMemo, useState } from 'react'
import { useQuery } from '@tanstack/react-query'
import { ArrowRight, BookOpenText, Boxes, Download, ExternalLink, Landmark, MonitorCog, Sparkles } from 'lucide-react'
import { Link, useSearchParams } from 'react-router-dom'
import { getReleaseManifest } from '../auth/auth-api'
import { MarketingShell } from '../components/layout/MarketingShell'
import { SiteMetadata } from '../components/seo/SiteMetadata'
import { PublicLaunchStatus } from '../components/ui/PublicLaunchStatus'
import { brandConfig } from '../site-config'
import { formatReleasePublishedAt, resolveReleaseManifestView } from '../release-manifest'
import { getReleasePlatformValidationSummary } from '../shared/package-validation'
import {
capabilityPillars,
changelogEntries,
companyNarrative,
deliverySurfaceCards,
deploymentReadinessTracks,
heroMetrics,
higherDimensionalRuntimeGuideCards,
inputAndDevicePostureCards,
operatorManualTracks,
operatorPlaybooks,
publicDocumentationPrinciples,
releaseStoryCards,
resourceCollections,
roadmapHonestyCards,
shippingNowCards,
simulatorManualCards,
supportFaqs,
} from '../site-data'
import { buildPublicReleaseManifestFallback, Section, supportTopicGuidance } from './public-page-helpers'
export function HomeLanding() {
return (
<>
<SiteMetadata
title="HyperTwist"
description="HyperTwist is a native cube and hypercube training environment for recognition, replay, coaching, higher-dimensional runtime ownership, and desktop-first operator workflows."
canonicalPath="/"
/>
<MarketingShell
eyebrow="Desktop-first training. Browser-first operator access."
title="HyperTwist turns cube practice into a real operator-grade training stack."
lede="Recognition, replay, coaching, analytics, higher-dimensional runtime ownership, public distribution, and browser-based account access all live under one honest product story."
>
<section className="hero-panel">
<div className="hero-grid">
<div className="hero-copy">
<p>
HyperTwist is a native training environment for classic cube, higher-dimensional
families, browser-assisted recognition, replay explanation, and desktop packaging.
The public site is intentionally honest: the desktop runtime is real, the browser
account/dashboard is real, and the optional full-browser simulator path remains spec-only.
</p>
<div className="button-row">
<Link className="button button--primary" to="/download">
Download desktop app
</Link>
<Link className="button button--ghost" to="/app">
Open operator dashboard
</Link>
<Link className="button button--ghost" to="/pricing">
View pricing
</Link>
</div>
</div>
<div className="hero-visual-card">
<img
src="/branding/hypertwist-3d-symbol.png"
alt="HyperTwist symbol"
className="hero-visual-card__image"
/>
<p className="hero-visual-card__caption">
Browser account shell outside the simulator. Native Unreal runtime inside the simulator.
</p>
</div>
</div>
<div className="metric-grid">
{heroMetrics.map((metric) => (
<article key={metric.label} className="metric-card">
<strong>{metric.value}</strong>
<span>{metric.label}</span>
</article>
))}
</div>
</section>
<Section
title="Current public site status"
description="The homepage now exposes the same bounded preview-versus-launch truth that governs the release and pricing lanes."
>
<PublicLaunchStatus title="Public website and release posture" />
</Section>
<Section
title="What ships now"
description="The public site only describes current product truth or explicitly marked retained/spec-only branches."
>
<div className="card-grid">
{shippingNowCards.map((item) => (
<article key={item} className="card card--compact">
<Sparkles size={18} />
<p>{item}</p>
</article>
))}
</div>
</Section>
<Section
title="Capability pillars"
description="The page structure borrows the FamiliarOS and ScriptoriumAI public-shell discipline, then rebrands the actual product around HyperTwist runtime authority."
>
<div className="card-grid">
{capabilityPillars.map((pillar) => (
<article key={pillar.title} className="card">
<h3>{pillar.title}</h3>
<p>{pillar.description}</p>
</article>
))}
</div>
</Section>
<Section
title="Roadmap-honest posture"
description="Important boundaries stay visible instead of being blurred into vague marketing claims."
>
<div className="split-grid">
{roadmapHonestyCards.map((item) => (
<article key={item} className="callout">
<p>{item}</p>
</article>
))}
</div>
</Section>
<Section
title="Delivery surfaces"
description="Use the website for account, release, pricing, and notices. Use the desktop runtime for the core simulator."
>
<div className="feature-band">
<article className="feature-band__card">
<MonitorCog size={22} />
<h3>Browser account and operator shell</h3>
<p>Authenticated browser access for release posture, desktop pairing, notices, and operator state.</p>
<Link to="/app" className="inline-link">
Open dashboard <ArrowRight size={15} />
</Link>
</article>
<article className="feature-band__card">
<Download size={22} />
<h3>Desktop download and package lane</h3>
<p>Public download posture for the native Unreal build, with legal linkage already wired in.</p>
<Link to="/download" className="inline-link">
Open download center <ArrowRight size={15} />
</Link>
</article>
<article className="feature-band__card">
<Landmark size={22} />
<h3>Checkout and notices discipline</h3>
<p>Paddle-ready pricing plus public notices surfaces for any downloadable build containing MPL-covered material.</p>
<Link to="/open-source-notices" className="inline-link">
Review notices <ArrowRight size={15} />
</Link>
</article>
</div>
</Section>
<Section
title="Why both browser and desktop stay"
description="The public site owns operator and distribution work the simulator should not dilute, while the simulator stays native for the runtime-heavy training job."
>
<div className="card-grid">
{deliverySurfaceCards.map((surface) => (
<article key={surface.title} className="card">
<h3>{surface.title}</h3>
<p>{surface.description}</p>
<ul className="list top-gap">
{surface.bullets.map((bullet) => (
<li key={bullet}>{bullet}</li>
))}
</ul>
</article>
))}
</div>
</Section>
</MarketingShell>
</>
)
}
export function AboutPage() {
return (
<>
<SiteMetadata
title="About HyperTwist"
description="Learn why HyperTwist exists, how it treats higher-dimensional training as first-class work, and why the public site stays honest about desktop-first simulator truth."
canonicalPath="/about"
/>
<MarketingShell
eyebrow="Why HyperTwist exists"
title="A training stack serious enough for higher-dimensional cubing."
lede="HyperTwist exists because cubers deserve one coherent system for physical recognition, explanation, practice, replay, analytics, and hyper puzzle ownership."
>
<Section title="Mission">
<div className="card">
<p>{companyNarrative.mission}</p>
<p>{companyNarrative.posture}</p>
<p>{companyNarrative.distribution}</p>
</div>
</Section>
<Section
title="Why the web surface remains necessary"
description="Keeping the website does not weaken the desktop-first thesis. It keeps public distribution, release, and operator-governance work outside the simulator proper."
>
<div className="card-grid">
{deliverySurfaceCards.map((surface) => (
<article key={surface.title} className="card">
<h3>{surface.title}</h3>
<p>{surface.description}</p>
</article>
))}
</div>
</Section>
<Section title="What makes the product different">
<div className="card-grid">
<article className="card">
<Boxes size={22} />
<h3>It treats higher-dimensional puzzles as first-class work</h3>
<p>120-cell and 5D runtime ownership are not hand-wavy aspirations. They are part of the current product truth.</p>
</article>
<article className="card">
<BookOpenText size={22} />
<h3>It stays roadmap-honest</h3>
<p>Shipped, retained, and spec-only surfaces remain clearly separated so public copy matches actual authority.</p>
</article>
<article className="card">
<MonitorCog size={22} />
<h3>It separates browser shell from simulator truth</h3>
<p>The public web surface helps operators access the product without pretending the browser already replaces the desktop runtime.</p>
</article>
</div>
</Section>
</MarketingShell>
</>
)
}
export function ResourcesPage() {
const [query, setQuery] = useState('')
const deferredQuery = useDeferredValue(query)
const windowsValidationSummary = getReleasePlatformValidationSummary('windows')
const filteredCollections = useMemo(() => {
const normalized = deferredQuery.trim().toLowerCase()
if (!normalized) return resourceCollections
return resourceCollections
.map((collection) => ({
...collection,
items: collection.items.filter((item) => item.toLowerCase().includes(normalized) || collection.title.toLowerCase().includes(normalized)),
}))
.filter((collection) => collection.items.length > 0)
}, [deferredQuery])
return (
<>
<SiteMetadata
title="HyperTwist resources"
description="Browse product-safe HyperTwist resources for rollout, release notes, documentation, operator onboarding, and higher-dimensional product truth."
canonicalPath="/resources"
/>
<MarketingShell
eyebrow="Public resources"
title="Resources that explain the product without leaking operator-only internals."
lede="This surface is shaped after the FamiliarOS and ScriptoriumAI public resource pages, but constrained to safe HyperTwist product-facing material."
>
<Section title="Resource finder" description="Search the public resource categories that matter to operators and buyers.">
<label className="input-label" htmlFor="resource-query">Filter resources</label>
<input
id="resource-query"
className="input"
value={query}
onChange={(event) => setQuery(event.target.value)}
placeholder="Search training, rollout, notices..."
/>
<div className="card-grid top-gap">
{filteredCollections.map((collection) => (
<article key={collection.title} className="card">
<h3>{collection.title}</h3>
<ul className="list">
{collection.items.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
</article>
))}
</div>
</Section>
<Section title="Direct routes">
<div className="feature-band">
<Link to="/docs" className="feature-band__card feature-band__card--link">
<BookOpenText size={22} />
<h3>Docs landing</h3>
<p>Product-facing documentation, boundaries, and rollout guidance.</p>
</Link>
<Link to="/support" className="feature-band__card feature-band__card--link">
<ExternalLink size={22} />
<h3>Support</h3>
<p>Contact, rollout questions, and account/download help.</p>
</Link>
<Link to="/changelog" className="feature-band__card feature-band__card--link">
<Sparkles size={22} />
<h3>Release notes</h3>
<p>Recent public-facing packets and posture updates.</p>
</Link>
</div>
</Section>
<Section
title="Operator playbooks"
description="These are the public-safe working patterns that matter once a team moves from curiosity into real rollout."
>
<div className="card-grid">
{operatorPlaybooks.map((playbook) => (
<article key={playbook.title} className="card">
<h3>{playbook.title}</h3>
<ul className="list top-gap">
{playbook.steps.map((step) => (
<li key={step}>{step}</li>
))}
</ul>
</article>
))}
</div>
</Section>
<Section
title="Simulator use today"
description="This summary is deliberately practical: what you actually do in the desktop runtime once browser identity and release posture are already resolved."
>
<div className="card-grid">
{simulatorManualCards.map((card) => (
<article key={card.title} className="card">
<h3>{card.title}</h3>
<p>{card.description}</p>
<ul className="list top-gap">
{card.bullets.map((bullet) => (
<li key={bullet}>{bullet}</li>
))}
</ul>
</article>
))}
</div>
</Section>
<Section
title="Higher-dimensional runtime guide"
description="These public-safe cards explain which higher-dimensional family lanes are already real and what runtime posture each one actually uses."
>
<div className="card-grid">
{higherDimensionalRuntimeGuideCards.map((card) => (
<article key={card.title} className="card">
<h3>{card.title}</h3>
<p>{card.description}</p>
<ul className="list top-gap">
{card.bullets.map((bullet) => (
<li key={bullet}>{bullet}</li>
))}
</ul>
</article>
))}
</div>
</Section>
<Section
title="Current control and device posture"
description="This keeps public resources honest about what input/runtime ownership is already strong and what still remains a later native completion packet."
>
<div className="card-grid">
{inputAndDevicePostureCards.map((card) => (
<article key={card.title} className="card">
<h3>{card.title}</h3>
<p>{card.description}</p>
<ul className="list top-gap">
{card.bullets.map((bullet) => (
<li key={bullet}>{bullet}</li>
))}
</ul>
</article>
))}
</div>
</Section>
<Section
title="Deployment readiness snapshot"
description="The public site can be detailed without becoming misleading when rollout guidance stays separated into identity, package, and legal lanes."
>
<div className="card-grid">
{deploymentReadinessTracks.map((track) => (
<article key={track.title} className="card">
<h3>{track.title}</h3>
<ul className="list top-gap">
{track.steps.map((step) => (
<li key={step}>{step}</li>
))}
</ul>
</article>
))}
</div>
</Section>
{windowsValidationSummary ? (
<Section title="Current packaged desktop proof">
<article className="card">
<h3>{windowsValidationSummary.lane}</h3>
<p>
Latest public-safe package evidence was generated{' '}
{formatReleasePublishedAt(windowsValidationSummary.generated_at) || windowsValidationSummary.generated_at}
{' '}in {windowsValidationSummary.configuration} mode and passed across{' '}
{windowsValidationSummary.smoke_map_count} dedicated-family higher-dimensional training map{windowsValidationSummary.smoke_map_count === 1 ? '' : 's'}.
</p>
<ul className="list top-gap">
{windowsValidationSummary.smoke_maps.map((map) => (
<li key={map.map_url}>
{map.label}: {map.result}
</li>
))}
</ul>
<div className="button-row top-gap">
<Link className="button button--ghost" to="/download">
Open download center
</Link>
<Link className="button button--ghost" to="/app">
Open operator dashboard
</Link>
</div>
</article>
</Section>
) : null}
</MarketingShell>
</>
)
}
export function DocsPage() {
const releaseManifestQuery = useQuery({
queryKey: ['release-manifest', 'public'],
queryFn: getReleaseManifest,
retry: false,
})
const releaseManifest = useMemo(
() => resolveReleaseManifestView(releaseManifestQuery.data?.manifest, buildPublicReleaseManifestFallback()),
[releaseManifestQuery.data?.manifest],
)
return (
<>
<SiteMetadata
title="HyperTwist documentation"
description="Open the HyperTwist public documentation lane for feature-registry-backed product truth, roadmap honesty, and distribution guidance."
canonicalPath="/docs"
/>
<MarketingShell
eyebrow="Documentation posture"
title="HyperTwist documentation stays capability-accurate."
lede="The public docs surface points users to product-safe truth: feature registry discipline, roadmap honesty, release notes, and distribution/legal guidance."
>
<Section title="Public documentation lanes">
<div className="card-grid">
{publicDocumentationPrinciples.map((principle) => (
<article key={principle.title} className="card">
<h3>{principle.title}</h3>
<p>{principle.description}</p>
</article>
))}
</div>
</Section>
<Section
title="Operator manual"
description="This is the public-facing manual for how HyperTwist is actually used today: browser first for identity and release posture, desktop first for the simulator."
>
<div className="card-grid">
{operatorManualTracks.map((track) => (
<article key={track.title} className="card">
<h3>{track.title}</h3>
<p>{track.description}</p>
<ul className="list top-gap">
{track.steps.map((step) => (
<li key={step}>{step}</li>
))}
</ul>
</article>
))}
</div>
</Section>
<Section
title="Browser versus simulator boundary"
description="The docs stay professional by being explicit about what each surface does better."
>
<div className="card-grid">
{deliverySurfaceCards.map((surface) => (
<article key={surface.title} className="card">
<h3>{surface.title}</h3>
<p>{surface.description}</p>
</article>
))}
</div>
</Section>
<Section
title="Simulator manual"
description="These are the current product-safe usage tracks for the native runtime itself."
>
<div className="card-grid">
{simulatorManualCards.map((card) => (
<article key={card.title} className="card">
<h3>{card.title}</h3>
<p>{card.description}</p>
<ul className="list top-gap">
{card.bullets.map((bullet) => (
<li key={bullet}>{bullet}</li>
))}
</ul>
</article>
))}
</div>
</Section>
<Section
title="Higher-dimensional family guide"
description="These are the currently represented higher-dimensional lanes and the truthful host/runtime posture for each."
>
<div className="card-grid">
{higherDimensionalRuntimeGuideCards.map((card) => (
<article key={card.title} className="card">
<h3>{card.title}</h3>
<p>{card.description}</p>
<ul className="list top-gap">
{card.bullets.map((bullet) => (
<li key={bullet}>{bullet}</li>
))}
</ul>
</article>
))}
</div>
</Section>
<Section
title="Deployment readiness manual"
description="This is the public-safe checklist for moving from preview posture to operator-grade rollout."
>
<div className="card-grid">
{deploymentReadinessTracks.map((track) => (
<article key={track.title} className="card">
<h3>{track.title}</h3>
<ul className="list top-gap">
{track.steps.map((step) => (
<li key={step}>{step}</li>
))}
</ul>
</article>
))}
</div>
</Section>
<Section
title="Input and device posture"
description="Public documentation should be explicit about the current control/runtime truth instead of blurring groundwork and finished VR claims together."
>
<div className="card-grid">
{inputAndDevicePostureCards.map((card) => (
<article key={card.title} className="card">
<h3>{card.title}</h3>
<p>{card.description}</p>
<ul className="list top-gap">
{card.bullets.map((bullet) => (
<li key={bullet}>{bullet}</li>
))}
</ul>
</article>
))}
</div>
</Section>
{releaseManifest.public_docs_url ? (
<Section title="External docs portal">
<a className="button button--primary" href={releaseManifest.public_docs_url} target="_blank" rel="noreferrer">
Open public docs portal
</a>
</Section>
) : null}
</MarketingShell>
</>
)
}
export function SupportPage() {
const [searchParams] = useSearchParams()
const supportTopic = searchParams.get('topic')
const selectedSupportTopic = supportTopic ? supportTopicGuidance[supportTopic] : null
return (
<>
<SiteMetadata
title="HyperTwist support"
description="Get help with HyperTwist rollout, desktop downloads, pricing, legal readiness, and browser-to-desktop operator access."
canonicalPath="/support"
/>
<MarketingShell
eyebrow="Operator help"
title="Support for rollout, downloads, pricing, and browser-to-desktop access."
lede="Support is focused on helping operators understand what the browser shell does, what the desktop build does, and how the two connect."
>
{selectedSupportTopic ? (
<Section title="Selected help lane">
<article className="callout">
<p className="status-pill status-pill--info">{selectedSupportTopic.title}</p>
<p>{selectedSupportTopic.description}</p>
</article>
</Section>
) : null}
<Section title="Contact">
<article className="card">
<p>
Email <a href={brandConfig.contact.emailHref}>{brandConfig.contact.email}</a> for account activation,
release enablement, pricing configuration, or deployment help.
</p>
</article>
</Section>
<Section title="Frequently asked questions">
<div className="card-grid">
{supportFaqs.map((faq) => (
<article className="card" key={faq.question}>
<h3>{faq.question}</h3>
<p>{faq.answer}</p>
</article>
))}
</div>
</Section>
<Section
title="Support lanes"
description="Support works best when operators know whether they need public guidance, protected browser access, or native desktop follow-through."
>
<div className="card-grid">
{operatorPlaybooks.map((playbook) => (
<article key={playbook.title} className="card">
<h3>{playbook.title}</h3>
<ul className="list top-gap">
{playbook.steps.map((step) => (
<li key={step}>{step}</li>
))}
</ul>
</article>
))}
</div>
</Section>
</MarketingShell>
</>
)
}
export function ChangelogPage() {
const releaseManifestQuery = useQuery({
queryKey: ['release-manifest', 'public'],
queryFn: getReleaseManifest,
retry: false,
})
const releaseManifest = useMemo(
() => resolveReleaseManifestView(releaseManifestQuery.data?.manifest, buildPublicReleaseManifestFallback()),
[releaseManifestQuery.data?.manifest],
)
return (
<>
<SiteMetadata
title="HyperTwist release notes"
description="Review recent public-facing HyperTwist changes across browser operator access, package hardening, diagnostics, and distribution readiness."
canonicalPath="/changelog"
/>
<MarketingShell
eyebrow="Release notes"
title="Recent public-facing HyperTwist changes."
lede="This page focuses on user-visible posture changes: browser operator access, package hardening, diagnostics, and distribution readiness."
>
<Section title="Latest changes">
<div className="timeline">
{changelogEntries.map((entry) => (
<article key={`${entry.date}-${entry.title}`} className="timeline-entry">
<p className="timeline-entry__date">{entry.date}</p>
<h3>{entry.title}</h3>
<p>{entry.details}</p>
</article>
))}
</div>
</Section>
<Section
title="How to read the release feed"
description="HyperTwist release notes stay useful when they distinguish simulator/runtime work, browser-operator work, and distribution/legal hardening instead of collapsing them together."
>
<div className="card-grid">
{releaseStoryCards.map((card) => (
<article key={card.title} className="card">
<h3>{card.title}</h3>
<p>{card.description}</p>
<ul className="list top-gap">
{card.bullets.map((bullet) => (
<li key={bullet}>{bullet}</li>
))}
</ul>
</article>
))}
</div>
</Section>
{releaseManifest.release_notes_url ? (
<Section title="External release notes">
<a className="button button--ghost" href={releaseManifest.release_notes_url} target="_blank" rel="noreferrer">
Open release feed
</a>
</Section>
) : null}
</MarketingShell>
</>
)
}

File diff suppressed because it is too large Load diff

View file

@ -2,18 +2,18 @@ import { Suspense, lazy, type ReactNode } from 'react'
import { Route } from 'react-router-dom'
import { GeneralPageLoader } from '../components/ui/Skeletons'
const HomeLanding = lazy(() => import('../pages/public-pages').then((m) => ({ default: m.HomeLanding })))
const AboutPage = lazy(() => import('../pages/public-pages').then((m) => ({ default: m.AboutPage })))
const ResourcesPage = lazy(() => import('../pages/public-pages').then((m) => ({ default: m.ResourcesPage })))
const DocsPage = lazy(() => import('../pages/public-pages').then((m) => ({ default: m.DocsPage })))
const SupportPage = lazy(() => import('../pages/public-pages').then((m) => ({ default: m.SupportPage })))
const ChangelogPage = lazy(() => import('../pages/public-pages').then((m) => ({ default: m.ChangelogPage })))
const PricingPage = lazy(() => import('../pages/public-pages').then((m) => ({ default: m.PricingPage })))
const DownloadPage = lazy(() => import('../pages/public-pages').then((m) => ({ default: m.DownloadPage })))
const OpenSourceNoticesPage = lazy(() => import('../pages/public-pages').then((m) => ({ default: m.OpenSourceNoticesPage })))
const PrivacyPage = lazy(() => import('../pages/public-pages').then((m) => ({ default: m.PrivacyPage })))
const TermsPage = lazy(() => import('../pages/public-pages').then((m) => ({ default: m.TermsPage })))
const ShippingPaymentPage = lazy(() => import('../pages/public-pages').then((m) => ({ default: m.ShippingPaymentPage })))
const HomeLanding = lazy(() => import('../pages/public-pages-marketing').then((m) => ({ default: m.HomeLanding })))
const AboutPage = lazy(() => import('../pages/public-pages-marketing').then((m) => ({ default: m.AboutPage })))
const ResourcesPage = lazy(() => import('../pages/public-pages-marketing').then((m) => ({ default: m.ResourcesPage })))
const DocsPage = lazy(() => import('../pages/public-pages-marketing').then((m) => ({ default: m.DocsPage })))
const SupportPage = lazy(() => import('../pages/public-pages-marketing').then((m) => ({ default: m.SupportPage })))
const ChangelogPage = lazy(() => import('../pages/public-pages-marketing').then((m) => ({ default: m.ChangelogPage })))
const PricingPage = lazy(() => import('../pages/public-pages-commerce').then((m) => ({ default: m.PricingPage })))
const DownloadPage = lazy(() => import('../pages/public-pages-commerce').then((m) => ({ default: m.DownloadPage })))
const OpenSourceNoticesPage = lazy(() => import('../pages/public-pages-commerce').then((m) => ({ default: m.OpenSourceNoticesPage })))
const PrivacyPage = lazy(() => import('../pages/public-pages-commerce').then((m) => ({ default: m.PrivacyPage })))
const TermsPage = lazy(() => import('../pages/public-pages-commerce').then((m) => ({ default: m.TermsPage })))
const ShippingPaymentPage = lazy(() => import('../pages/public-pages-commerce').then((m) => ({ default: m.ShippingPaymentPage })))
const LoginPage = lazy(() => import('../pages/auth-pages').then((m) => ({ default: m.LoginPage })))
const RegisterPage = lazy(() => import('../pages/auth-pages').then((m) => ({ default: m.RegisterPage })))

View file

@ -168,6 +168,93 @@ export const simulatorManualCards = [
},
] as const
export const higherDimensionalRuntimeGuideCards = [
{
title: 'Magic120Cell packaged runtime',
description: 'Use the packaged native training lane when you need real 120-cell runtime-state, projection ownership, and persistence-aware family behavior.',
bullets: [
'Launch the dedicated Magic120Cell training map from the desktop runtime.',
'Use the current symmetry, focus, and logical-visibility posture as the authoritative first-party runtime owner.',
'Treat the public website as documentation and rollout support, not as the runtime that executes this family.',
],
},
{
title: 'MagicCube5D packaged runtime',
description: 'Use the packaged native training lane when you need real 5D projection, stereo, focus, and face-visibility ownership.',
bullets: [
'Launch the dedicated MagicCube5D training map from the desktop runtime.',
'Use the current projection-distance, stereo, and visibility defaults as the bounded first-party runtime posture.',
'Keep this lane described honestly as packaged native behavior rather than browser simulator parity.',
],
},
{
title: 'MagicTile embedded-browser runtime',
description: 'Use the embedded browser lane for the current non-Euclidean tiling host posture while native renderer widening remains intentionally gated.',
bullets: [
'Treat the embedded browser/CEF shell as the current shipped host for the live MagicTile interaction lane.',
'Keep shared scramble normalization, timer transport, and state-bridge ownership attached to the first-party native shell and bridge.',
'Do not describe a separate native renderer port as live while the renderer-widening gate stays explicit No-Go.',
],
},
] as const
export const inputAndDevicePostureCards = [
{
title: 'Keyboard and mouse ship today',
description: 'Classic-cube play and bounded keyboard-driven higher-dimensional interaction are already real current product lanes.',
bullets: [
'Classic-cube runtime input already includes click, touch, orbit, zoom, and bounded keyboard move intent.',
'The current classic keyboard profile is the shipped `classic-wca-keyboard/v1` mapping.',
'Treat this as real simulator input ownership, not as a browser-side placeholder.',
],
},
{
title: 'Higher-dimensional view controls are already owned',
description: 'Magic120Cell and MagicCube5D already carry first-party projection, focus, symmetry or stereo, and visibility defaults in the packaged runtime.',
bullets: [
'Magic120Cell keeps symmetry, logical-visibility depth, and center-cell focus posture explicit.',
'MagicCube5D keeps projection-distance, stereo, face-visibility, and focus posture explicit.',
'These controls belong to the dedicated-family desktop runtime lanes, not to the public website.',
],
},
{
title: 'XR groundwork exists, but the full VR lane is not finished',
description: 'EnhancedInput posture and motion-controller groundwork exist, but HyperTwist does not yet market a fully finished OpenXR/controller/rebinding runtime lane.',
bullets: [
'Project config already carries EnhancedInput plus Vive, Oculus Touch, Mixed Reality, and Valve Index axis groundwork.',
'Current product truth should not overclaim headset-specific runtime ownership or polished user-facing input rebinding.',
'A later native XR completion packet still needs dedicated runtime owners, user-facing settings, and Windows package validation with controller truth.',
],
},
] as const
export const deploymentReadinessTracks = [
{
title: '1. Identity and access posture',
steps: [
'Confirm shared browser auth is live before inviting operators into the protected release lane.',
'Use the protected dashboard to resolve plan, entitlement, and desktop-link token posture.',
'Keep browser-to-desktop handoff explicit so the installed app never depends on password reuse.',
],
},
{
title: '2. Release and package posture',
steps: [
'Publish release-manifest truth for the active desktop targets before widening any public launch language.',
'Keep package validation proof visible beside download posture so rollout remains evidence-backed.',
'Differentiate browser-shell changes from simulator/package changes in release notes and support guidance.',
],
},
{
title: '3. Legal and source posture',
steps: [
'Keep notices and corresponding-source links visible anywhere pricing, checkout, or downloads are exposed.',
'Treat public pricing/download surfaces as part of the distributed product, not detached brochure pages.',
'Do not let launch copy outrun the actual checkout, release, or source-availability configuration.',
],
},
] as const
export const publicDocumentationPrinciples = [
{
title: 'Feature-registry-backed wording only',
@ -388,6 +475,15 @@ export const resourceCollections = [
'120-cell and 5D dedicated-family runtime ownership overview',
],
},
{
title: 'Deployment readiness',
items: [
'Shared auth and browser-to-desktop pairing posture',
'Package validation proof and release-manifest interpretation',
'Pricing, checkout, notices, and corresponding-source coordination',
'Launch-readiness distinction between preview, protected, and public lanes',
],
},
] as const
export const changelogEntries = [
@ -454,6 +550,18 @@ export const supportFaqs = [
question: 'Is the simulator fully in the browser?',
answer: 'No. The current shipping lane is desktop-first and Unreal-backed. The public website offers account, operator, support, and download access, while the optional full-browser simulator path remains spec-only.',
},
{
question: 'If the desktop app is primary, why keep the web version?',
answer: 'Because the browser shell owns the parts that should stay outside the simulator: public positioning, account access, billing, release posture, download gating, notices, and browser-to-desktop pairing. Keeping that work on the web makes the native runtime easier to trust and easier to operate.',
},
{
question: 'Is VR/controller support already fully finished?',
answer: 'Not yet. HyperTwist already has real EnhancedInput posture and motion-controller groundwork, but it does not yet claim a fully finished OpenXR/controller/runtime or polished rebinding lane.',
},
{
question: 'Can I already customize controls and higher-dimensional view posture?',
answer: 'Partly. The current desktop runtime already owns the classic keyboard profile plus higher-dimensional projection, focus, and visibility defaults, but a broader polished user-facing preferences and rebinding layer is still a later native packet.',
},
{
question: 'Can I download a build immediately after sign-in?',
answer: 'Yes, once a release URL is configured for your plan. The dashboard also exposes a desktop-link token so the browser account can pair with the desktop app safely.',