Harden public manual surfaces and owned refactor tooling
This commit is contained in:
parent
30bec87f9d
commit
3ccfe617ab
32 changed files with 3622 additions and 734 deletions
12
.sentrux/source-only-baseline.json
Normal file
12
.sentrux/source-only-baseline.json
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"timestamp": 1782739148.1063952,
|
||||||
|
"quality_signal": 0.623355968371853,
|
||||||
|
"coupling_score": 0.1492204899777283,
|
||||||
|
"cycle_count": 0,
|
||||||
|
"god_file_count": 1,
|
||||||
|
"hotspot_count": 0,
|
||||||
|
"complex_fn_count": 15,
|
||||||
|
"max_depth": 11,
|
||||||
|
"total_import_edges": 898,
|
||||||
|
"cross_module_edges": 134
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,42 @@
|
||||||
import { defineConfig } from 'vite';
|
import { defineConfig } from 'vite';
|
||||||
import { resolve } from 'path';
|
import { resolve } from 'path';
|
||||||
|
|
||||||
|
function annotateGltfViewerMikktspaceFallback()
|
||||||
|
{
|
||||||
|
const OriginalFallbackExpression =
|
||||||
|
"new URL('mikktspace_bg.wasm', import.meta.url)";
|
||||||
|
const AnnotatedFallbackExpression =
|
||||||
|
"new URL(/* @vite-ignore */ 'mikktspace_bg.wasm', import.meta.url)";
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: 'annotate-gltf-viewer-mikktspace-fallback',
|
||||||
|
transform(Code: string, Id: string)
|
||||||
|
{
|
||||||
|
if (!Id.includes('@khronosgroup/gltf-viewer/dist/gltf-viewer.module.js'))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Code.includes(OriginalFallbackExpression))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
code: Code.replaceAll(
|
||||||
|
OriginalFallbackExpression,
|
||||||
|
AnnotatedFallbackExpression
|
||||||
|
),
|
||||||
|
map: null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
plugins: [
|
||||||
|
annotateGltfViewerMikktspaceFallback()
|
||||||
|
],
|
||||||
build: {
|
build: {
|
||||||
outDir: 'dist',
|
outDir: 'dist',
|
||||||
emptyOutDir: true,
|
emptyOutDir: true,
|
||||||
|
|
|
||||||
|
|
@ -19383,6 +19383,14 @@ void UHyperTwistCoachDashboardWidget::EnsureDefaultDashboardBuilt()
|
||||||
4
|
4
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
ControlProfileRosterStructuredTextBlocks.Add(
|
||||||
|
HyperTwistCoachDashboardWidgetInternal::AddTextRow(
|
||||||
|
WidgetTree,
|
||||||
|
RootLayout,
|
||||||
|
TEXT("CoachControlProfileRosterPreferencesContinuity"),
|
||||||
|
4
|
||||||
|
)
|
||||||
|
);
|
||||||
ControlProfileRosterStructuredTextBlocks.Add(
|
ControlProfileRosterStructuredTextBlocks.Add(
|
||||||
HyperTwistCoachDashboardWidgetInternal::AddTextRow(
|
HyperTwistCoachDashboardWidgetInternal::AddTextRow(
|
||||||
WidgetTree,
|
WidgetTree,
|
||||||
|
|
@ -30546,6 +30554,7 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
||||||
ControlProfileRosterSurface.MagicCube5DProfileLine,
|
ControlProfileRosterSurface.MagicCube5DProfileLine,
|
||||||
ControlProfileRosterSurface.ActiveHigherDimensionalProfileLine,
|
ControlProfileRosterSurface.ActiveHigherDimensionalProfileLine,
|
||||||
ControlProfileRosterSurface.SelectorRecallLine,
|
ControlProfileRosterSurface.SelectorRecallLine,
|
||||||
|
ControlProfileRosterSurface.PreferencesContinuityLine,
|
||||||
ControlProfileRosterSurface.PreferencesGapLine,
|
ControlProfileRosterSurface.PreferencesGapLine,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,257 @@
|
||||||
|
// Copyright HyperTwist, Inc. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
|
||||||
|
namespace HyperTwistTrainingControlSurfaceFormatting
|
||||||
|
{
|
||||||
|
inline FString DescribeBool(const bool bValue)
|
||||||
|
{
|
||||||
|
return bValue ? TEXT("yes") : TEXT("no");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline FString DescribeReadyState(const bool bValue)
|
||||||
|
{
|
||||||
|
return bValue ? TEXT("ready") : TEXT("not ready");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline FString DescribeAggregateReadyState(
|
||||||
|
const bool bPrimaryReady,
|
||||||
|
const bool bSecondaryReady
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (bPrimaryReady && bSecondaryReady)
|
||||||
|
{
|
||||||
|
return TEXT("ready");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bPrimaryReady || bSecondaryReady)
|
||||||
|
{
|
||||||
|
return TEXT("partial");
|
||||||
|
}
|
||||||
|
|
||||||
|
return TEXT("missing");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline FString DescribeOwnedContinuityState(
|
||||||
|
const bool bOwnershipReady,
|
||||||
|
const bool bContinuityReady
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!bOwnershipReady)
|
||||||
|
{
|
||||||
|
return TEXT("missing");
|
||||||
|
}
|
||||||
|
|
||||||
|
return bContinuityReady ? TEXT("ready") : TEXT("partial");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline FString DescribeIdOrFallback(const FString& Value)
|
||||||
|
{
|
||||||
|
return !Value.IsEmpty() ? Value : FString(TEXT("n/a"));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline FString DescribeIdIfReady(
|
||||||
|
const bool bReady,
|
||||||
|
const FString& Value
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return DescribeIdOrFallback(bReady ? Value : FString());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int32 DescribeCountIfReady(
|
||||||
|
const bool bReady,
|
||||||
|
const int32 Count
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return bReady ? Count : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline FString BuildControlInputPreferencesStatusLine(
|
||||||
|
const bool bCameraSettingsContinuityReady,
|
||||||
|
const FString& CameraExportArtifactId,
|
||||||
|
const bool bImmersiveSessionRecallReady,
|
||||||
|
const FString& ImmersiveSessionRecallBoundaryId,
|
||||||
|
const int32 ImmersiveSessionRecallScopeCount,
|
||||||
|
const int32 ImmersiveSessionRecallPreferenceFieldTagCount
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return FString::Printf(
|
||||||
|
TEXT("Preferences continuity: %s | camera export %s | immersive recall %s | recall scopes %d | preference fields %d | polished rebinding and broader control-settings UI are not yet shipped."),
|
||||||
|
*DescribeAggregateReadyState(
|
||||||
|
bCameraSettingsContinuityReady,
|
||||||
|
bImmersiveSessionRecallReady),
|
||||||
|
*DescribeIdIfReady(
|
||||||
|
bCameraSettingsContinuityReady,
|
||||||
|
CameraExportArtifactId),
|
||||||
|
*DescribeIdIfReady(
|
||||||
|
bImmersiveSessionRecallReady,
|
||||||
|
ImmersiveSessionRecallBoundaryId),
|
||||||
|
DescribeCountIfReady(
|
||||||
|
bImmersiveSessionRecallReady,
|
||||||
|
ImmersiveSessionRecallScopeCount),
|
||||||
|
DescribeCountIfReady(
|
||||||
|
bImmersiveSessionRecallReady,
|
||||||
|
ImmersiveSessionRecallPreferenceFieldTagCount)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline FString BuildControlSettingsCameraSettingsLine(
|
||||||
|
const bool bCameraSettingsReady,
|
||||||
|
const bool bCameraSettingsContinuityReady,
|
||||||
|
const FString& CameraSettingsToolId,
|
||||||
|
const FString& CameraSettingsExportArtifactId,
|
||||||
|
const int32 CameraSettingsWorkflowTagCount,
|
||||||
|
const int32 CameraSettingsPreviewStateTagCount,
|
||||||
|
const int32 CameraSettingsExportArtifactCount
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return FString::Printf(
|
||||||
|
TEXT("Viewer camera settings: %s | tool %s | camera export %s | workflow tags %d | preview states %d | export artifacts %d | orbit/framing/export surface is owned."),
|
||||||
|
*DescribeOwnedContinuityState(
|
||||||
|
bCameraSettingsReady,
|
||||||
|
bCameraSettingsContinuityReady),
|
||||||
|
*DescribeIdIfReady(
|
||||||
|
bCameraSettingsReady,
|
||||||
|
CameraSettingsToolId),
|
||||||
|
*DescribeIdIfReady(
|
||||||
|
bCameraSettingsContinuityReady,
|
||||||
|
CameraSettingsExportArtifactId),
|
||||||
|
DescribeCountIfReady(
|
||||||
|
bCameraSettingsReady,
|
||||||
|
CameraSettingsWorkflowTagCount),
|
||||||
|
DescribeCountIfReady(
|
||||||
|
bCameraSettingsReady,
|
||||||
|
CameraSettingsPreviewStateTagCount),
|
||||||
|
DescribeCountIfReady(
|
||||||
|
bCameraSettingsReady,
|
||||||
|
CameraSettingsExportArtifactCount)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline FString BuildControlSettingsImmersiveSettingsLine(
|
||||||
|
const bool bImmersivePresenceSettingsReady,
|
||||||
|
const bool bImmersiveSessionRecallReady,
|
||||||
|
const FString& ImmersivePresenceContractId,
|
||||||
|
const FString& ImmersiveSessionRecallBoundaryId,
|
||||||
|
const int32 ImmersionIntensityPresetCount,
|
||||||
|
const int32 ReducedDistractionPresetCount,
|
||||||
|
const int32 ImmersivePresenceSurfaceTagCount,
|
||||||
|
const int32 ImmersiveSessionRecallScopeCount,
|
||||||
|
const int32 ImmersiveSessionRecallPreferenceFieldTagCount,
|
||||||
|
const int32 ImmersiveSessionRecallResetSurfaceTagCount
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return FString::Printf(
|
||||||
|
TEXT("Immersive presence settings: %s | contract %s | session recall %s | intensity presets %d | reduced-distraction presets %d | presence tags %d | recall scopes %d | preference fields %d | reset surfaces %d."),
|
||||||
|
*DescribeOwnedContinuityState(
|
||||||
|
bImmersivePresenceSettingsReady,
|
||||||
|
bImmersiveSessionRecallReady),
|
||||||
|
*DescribeIdIfReady(
|
||||||
|
bImmersivePresenceSettingsReady,
|
||||||
|
ImmersivePresenceContractId),
|
||||||
|
*DescribeIdIfReady(
|
||||||
|
bImmersiveSessionRecallReady,
|
||||||
|
ImmersiveSessionRecallBoundaryId),
|
||||||
|
DescribeCountIfReady(
|
||||||
|
bImmersivePresenceSettingsReady,
|
||||||
|
ImmersionIntensityPresetCount),
|
||||||
|
DescribeCountIfReady(
|
||||||
|
bImmersivePresenceSettingsReady,
|
||||||
|
ReducedDistractionPresetCount),
|
||||||
|
DescribeCountIfReady(
|
||||||
|
bImmersivePresenceSettingsReady,
|
||||||
|
ImmersivePresenceSurfaceTagCount),
|
||||||
|
DescribeCountIfReady(
|
||||||
|
bImmersiveSessionRecallReady,
|
||||||
|
ImmersiveSessionRecallScopeCount),
|
||||||
|
DescribeCountIfReady(
|
||||||
|
bImmersiveSessionRecallReady,
|
||||||
|
ImmersiveSessionRecallPreferenceFieldTagCount),
|
||||||
|
DescribeCountIfReady(
|
||||||
|
bImmersiveSessionRecallReady,
|
||||||
|
ImmersiveSessionRecallResetSurfaceTagCount)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline FString BuildControlSettingsStatusLine(
|
||||||
|
const bool bCameraSettingsReady,
|
||||||
|
const bool bCameraSettingsContinuityReady,
|
||||||
|
const bool bImmersivePresenceSettingsReady,
|
||||||
|
const bool bImmersiveSessionRecallReady,
|
||||||
|
const bool bMagic120CellOwnedSettingsReady,
|
||||||
|
const bool bMagicCube5DOwnedSettingsReady,
|
||||||
|
const bool bHigherDimensionalSelectorSettingsReady,
|
||||||
|
const bool bRepositoryBackedSelectorRecallReady
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return FString::Printf(
|
||||||
|
TEXT("camera %s | immersive %s | 120-cell owned settings %s | 5D owned settings %s | selectors %s | selector recall %s | XR rebinding not yet shipped"),
|
||||||
|
*DescribeOwnedContinuityState(
|
||||||
|
bCameraSettingsReady,
|
||||||
|
bCameraSettingsContinuityReady),
|
||||||
|
*DescribeOwnedContinuityState(
|
||||||
|
bImmersivePresenceSettingsReady,
|
||||||
|
bImmersiveSessionRecallReady),
|
||||||
|
bMagic120CellOwnedSettingsReady ? TEXT("ready") : TEXT("partial"),
|
||||||
|
bMagicCube5DOwnedSettingsReady ? TEXT("ready") : TEXT("partial"),
|
||||||
|
bHigherDimensionalSelectorSettingsReady ? TEXT("ready") : TEXT("partial"),
|
||||||
|
bRepositoryBackedSelectorRecallReady ? TEXT("ready") : TEXT("unavailable")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline FString BuildControlProfilePreferencesContinuityLine(
|
||||||
|
const bool bCameraSettingsContinuityReady,
|
||||||
|
const FString& CameraSettingsExportArtifactId,
|
||||||
|
const bool bImmersiveSessionRecallReady,
|
||||||
|
const FString& ImmersiveSessionRecallBoundaryId,
|
||||||
|
const int32 ImmersiveSessionRecallScopeCount,
|
||||||
|
const int32 ImmersiveSessionRecallPreferenceFieldTagCount
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return FString::Printf(
|
||||||
|
TEXT("Profile continuity: %s | camera export %s | immersive recall %s | recall scopes %d | preference fields %d."),
|
||||||
|
*DescribeAggregateReadyState(
|
||||||
|
bCameraSettingsContinuityReady,
|
||||||
|
bImmersiveSessionRecallReady),
|
||||||
|
*DescribeIdIfReady(
|
||||||
|
bCameraSettingsContinuityReady,
|
||||||
|
CameraSettingsExportArtifactId),
|
||||||
|
*DescribeIdIfReady(
|
||||||
|
bImmersiveSessionRecallReady,
|
||||||
|
ImmersiveSessionRecallBoundaryId),
|
||||||
|
DescribeCountIfReady(
|
||||||
|
bImmersiveSessionRecallReady,
|
||||||
|
ImmersiveSessionRecallScopeCount),
|
||||||
|
DescribeCountIfReady(
|
||||||
|
bImmersiveSessionRecallReady,
|
||||||
|
ImmersiveSessionRecallPreferenceFieldTagCount)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline FString BuildControlProfileStatusLine(
|
||||||
|
const bool bClassicKeyboardProfileReady,
|
||||||
|
const bool bImmersivePresenceProfileReady,
|
||||||
|
const bool bMagic120CellProfileReady,
|
||||||
|
const bool bMagicCube5DProfileReady,
|
||||||
|
const bool bActiveHigherDimensionalProfileVisible,
|
||||||
|
const bool bRepositoryBackedSelectorRecallReady,
|
||||||
|
const bool bCameraSettingsContinuityReady,
|
||||||
|
const bool bImmersiveSessionRecallReady
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return FString::Printf(
|
||||||
|
TEXT("classic keyboard %s | immersive presets %s | 120-cell family %s | 5D family %s | active selection %s | selector recall %s | profile continuity %s | controller rebinding not yet shipped"),
|
||||||
|
bClassicKeyboardProfileReady ? TEXT("ready") : TEXT("missing"),
|
||||||
|
bImmersivePresenceProfileReady ? TEXT("ready") : TEXT("missing"),
|
||||||
|
bMagic120CellProfileReady ? TEXT("ready") : TEXT("missing"),
|
||||||
|
bMagicCube5DProfileReady ? TEXT("ready") : TEXT("missing"),
|
||||||
|
bActiveHigherDimensionalProfileVisible ? TEXT("visible") : TEXT("not loaded"),
|
||||||
|
bRepositoryBackedSelectorRecallReady ? TEXT("ready") : TEXT("unavailable"),
|
||||||
|
*DescribeAggregateReadyState(
|
||||||
|
bCameraSettingsContinuityReady,
|
||||||
|
bImmersiveSessionRecallReady)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
#include "HyperTwistTraining/HyperTwistTrainingPanelWidget.h"
|
#include "HyperTwistTraining/HyperTwistTrainingPanelWidget.h"
|
||||||
|
|
||||||
#include "HyperTwistAlgorithm/HyperTwistAlgorithmKeyboard.h"
|
#include "HyperTwistAlgorithm/HyperTwistAlgorithmKeyboard.h"
|
||||||
|
#include "HyperTwistAlgorithm/HyperTwistAlgorithmSerializer.h"
|
||||||
#include "HyperTwistBrowser/HyperTwistBrowserWidget.h"
|
#include "HyperTwistBrowser/HyperTwistBrowserWidget.h"
|
||||||
#include "HyperTwistSimulation/HyperTwistClassicCubeOrbitPawn.h"
|
#include "HyperTwistSimulation/HyperTwistClassicCubeOrbitPawn.h"
|
||||||
#include "HyperTwistSimulation/HyperTwistClassicCubePlayerController.h"
|
#include "HyperTwistSimulation/HyperTwistClassicCubePlayerController.h"
|
||||||
#include "HyperTwistSimulation/HyperTwistVirtual3333ProjectionPlayerController.h"
|
#include "HyperTwistSimulation/HyperTwistVirtual3333ProjectionPlayerController.h"
|
||||||
|
#include "HyperTwistTraining/HyperTwistTrainingControlSurfaceFormatting.h"
|
||||||
#include "HyperTwistTraining/HyperTwistTrainingImmersiveEnvironmentLibrary.h"
|
#include "HyperTwistTraining/HyperTwistTrainingImmersiveEnvironmentLibrary.h"
|
||||||
#include "HyperTwistTraining/HyperTwistTrainingMagic120CellLibrary.h"
|
#include "HyperTwistTraining/HyperTwistTrainingMagic120CellLibrary.h"
|
||||||
#include "HyperTwistTraining/HyperTwistTrainingMagicCube5DLibrary.h"
|
#include "HyperTwistTraining/HyperTwistTrainingMagicCube5DLibrary.h"
|
||||||
|
|
@ -62,14 +64,28 @@ namespace HyperTwistTrainingPanelWidgetInternal
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FViewerCameraSettingsFacts
|
||||||
|
{
|
||||||
|
FHyperTwistTrainingViewerEditorToolReference Tool;
|
||||||
|
FString ExportArtifactId;
|
||||||
|
bool bToolReady = false;
|
||||||
|
bool bExportArtifactReady = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FImmersiveSessionRecallFacts
|
||||||
|
{
|
||||||
|
FHyperTwistTrainingImmersiveSessionRecallBoundary Boundary;
|
||||||
|
bool bReady = false;
|
||||||
|
};
|
||||||
|
|
||||||
FString DescribeBool(const bool bValue)
|
FString DescribeBool(const bool bValue)
|
||||||
{
|
{
|
||||||
return bValue ? TEXT("yes") : TEXT("no");
|
return HyperTwistTrainingControlSurfaceFormatting::DescribeBool(bValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
FString DescribeReadyState(const bool bValue)
|
FString DescribeReadyState(const bool bValue)
|
||||||
{
|
{
|
||||||
return bValue ? TEXT("ready") : TEXT("not ready");
|
return HyperTwistTrainingControlSurfaceFormatting::DescribeReadyState(bValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
FString DescribeAggregateReadyState(
|
FString DescribeAggregateReadyState(
|
||||||
|
|
@ -77,17 +93,9 @@ namespace HyperTwistTrainingPanelWidgetInternal
|
||||||
const bool bSecondaryReady
|
const bool bSecondaryReady
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (bPrimaryReady && bSecondaryReady)
|
return HyperTwistTrainingControlSurfaceFormatting::DescribeAggregateReadyState(
|
||||||
{
|
bPrimaryReady,
|
||||||
return TEXT("ready");
|
bSecondaryReady);
|
||||||
}
|
|
||||||
|
|
||||||
if (bPrimaryReady || bSecondaryReady)
|
|
||||||
{
|
|
||||||
return TEXT("partial");
|
|
||||||
}
|
|
||||||
|
|
||||||
return TEXT("missing");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FString DescribeOwnedContinuityState(
|
FString DescribeOwnedContinuityState(
|
||||||
|
|
@ -95,17 +103,14 @@ namespace HyperTwistTrainingPanelWidgetInternal
|
||||||
const bool bContinuityReady
|
const bool bContinuityReady
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (!bOwnershipReady)
|
return HyperTwistTrainingControlSurfaceFormatting::DescribeOwnedContinuityState(
|
||||||
{
|
bOwnershipReady,
|
||||||
return TEXT("missing");
|
bContinuityReady);
|
||||||
}
|
|
||||||
|
|
||||||
return bContinuityReady ? TEXT("ready") : TEXT("partial");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FString DescribeIdOrFallback(const FString& Value)
|
FString DescribeIdOrFallback(const FString& Value)
|
||||||
{
|
{
|
||||||
return !Value.IsEmpty() ? Value : FString(TEXT("n/a"));
|
return HyperTwistTrainingControlSurfaceFormatting::DescribeIdOrFallback(Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
FString DescribeKeyForRoster(const FKey& Key)
|
FString DescribeKeyForRoster(const FKey& Key)
|
||||||
|
|
@ -120,17 +125,16 @@ namespace HyperTwistTrainingPanelWidgetInternal
|
||||||
return TEXT("n/a");
|
return TEXT("n/a");
|
||||||
}
|
}
|
||||||
|
|
||||||
FString Text = Move.Family;
|
FHyperTwistAlgorithmNode Node;
|
||||||
if (Move.Amount < 0)
|
Node.NodeType = EHyperTwistAlgorithmNodeType::BlockMove;
|
||||||
{
|
Node.BlockMove = Move;
|
||||||
Text += TEXT("'");
|
|
||||||
}
|
|
||||||
else if (FMath::Abs(Move.Amount) > 1)
|
|
||||||
{
|
|
||||||
Text += FString::FromInt(FMath::Abs(Move.Amount));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Text;
|
FHyperTwistAlgorithmSequence Sequence;
|
||||||
|
Sequence.Nodes.Add(Node);
|
||||||
|
|
||||||
|
const FString CanonicalText =
|
||||||
|
UHyperTwistAlgorithmSerializer::SerializeAlgorithm(Sequence);
|
||||||
|
return !CanonicalText.IsEmpty() ? CanonicalText : TEXT("n/a");
|
||||||
}
|
}
|
||||||
|
|
||||||
FString BuildClassicKeyboardMoveRosterLine(
|
FString BuildClassicKeyboardMoveRosterLine(
|
||||||
|
|
@ -286,6 +290,43 @@ namespace HyperTwistTrainingPanelWidgetInternal
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FViewerCameraSettingsFacts BuildViewerCameraSettingsFacts()
|
||||||
|
{
|
||||||
|
FViewerCameraSettingsFacts Facts;
|
||||||
|
const FHyperTwistTrainingViewerReferenceBundle Bundle =
|
||||||
|
UHyperTwistTrainingViewerLibrary::BuildBundledBrowserViewerReferenceBundle();
|
||||||
|
Facts.bToolReady =
|
||||||
|
Bundle.IsStructurallyValid()
|
||||||
|
&& TryFindViewerEditorToolById(
|
||||||
|
Bundle,
|
||||||
|
TEXT("tool/camera-settings"),
|
||||||
|
Facts.Tool
|
||||||
|
);
|
||||||
|
if (Facts.bToolReady)
|
||||||
|
{
|
||||||
|
FHyperTwistTrainingViewerQaArtifactReference ExportArtifact;
|
||||||
|
Facts.bExportArtifactReady = TryFindFirstViewerQaArtifactByIds(
|
||||||
|
Bundle,
|
||||||
|
Facts.Tool.ExportArtifactIds,
|
||||||
|
Facts.ExportArtifactId,
|
||||||
|
ExportArtifact
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Facts;
|
||||||
|
}
|
||||||
|
|
||||||
|
FImmersiveSessionRecallFacts BuildImmersiveSessionRecallFacts()
|
||||||
|
{
|
||||||
|
FImmersiveSessionRecallFacts Facts;
|
||||||
|
Facts.bReady =
|
||||||
|
UHyperTwistTrainingRuntimeLibrary::TryGetBundledImmersiveSessionRecallBoundary(
|
||||||
|
TEXT("immersive-training-session-recall-boundary"),
|
||||||
|
Facts.Boundary
|
||||||
|
) && Facts.Boundary.IsStructurallyValid();
|
||||||
|
return Facts;
|
||||||
|
}
|
||||||
|
|
||||||
bool AxisConfigEntriesContainToken(
|
bool AxisConfigEntriesContainToken(
|
||||||
const TArray<FString>& AxisConfigEntries,
|
const TArray<FString>& AxisConfigEntries,
|
||||||
const TCHAR* Token
|
const TCHAR* Token
|
||||||
|
|
@ -1253,29 +1294,17 @@ UHyperTwistTrainingPanelWidget::GetDisplayedControlInputReadinessInspectSurface(
|
||||||
TEXT("immersive-training-presence-control-contract"),
|
TEXT("immersive-training-presence-control-contract"),
|
||||||
PresenceControlContract
|
PresenceControlContract
|
||||||
);
|
);
|
||||||
const FHyperTwistTrainingViewerReferenceBundle ViewerBundle =
|
const HyperTwistTrainingPanelWidgetInternal::FViewerCameraSettingsFacts
|
||||||
UHyperTwistTrainingViewerLibrary::BuildBundledBrowserViewerReferenceBundle();
|
CameraSettingsFacts =
|
||||||
FHyperTwistTrainingViewerEditorToolReference CameraSettingsTool;
|
HyperTwistTrainingPanelWidgetInternal::BuildViewerCameraSettingsFacts();
|
||||||
FHyperTwistTrainingViewerQaArtifactReference CameraExportArtifact;
|
|
||||||
FString CameraExportArtifactId;
|
|
||||||
const bool bCameraSettingsContinuityReady =
|
const bool bCameraSettingsContinuityReady =
|
||||||
ViewerBundle.IsStructurallyValid()
|
CameraSettingsFacts.bExportArtifactReady;
|
||||||
&& HyperTwistTrainingPanelWidgetInternal::TryFindViewerEditorToolById(
|
const FString CameraExportArtifactId = CameraSettingsFacts.ExportArtifactId;
|
||||||
ViewerBundle,
|
const HyperTwistTrainingPanelWidgetInternal::FImmersiveSessionRecallFacts
|
||||||
TEXT("tool/camera-settings"),
|
ImmersiveSessionRecallFacts =
|
||||||
CameraSettingsTool
|
HyperTwistTrainingPanelWidgetInternal::BuildImmersiveSessionRecallFacts();
|
||||||
) && HyperTwistTrainingPanelWidgetInternal::TryFindFirstViewerQaArtifactByIds(
|
|
||||||
ViewerBundle,
|
|
||||||
CameraSettingsTool.ExportArtifactIds,
|
|
||||||
CameraExportArtifactId,
|
|
||||||
CameraExportArtifact
|
|
||||||
);
|
|
||||||
FHyperTwistTrainingImmersiveSessionRecallBoundary ImmersiveSessionRecallBoundary;
|
|
||||||
const bool bImmersiveSessionRecallReady =
|
const bool bImmersiveSessionRecallReady =
|
||||||
UHyperTwistTrainingRuntimeLibrary::TryGetBundledImmersiveSessionRecallBoundary(
|
ImmersiveSessionRecallFacts.bReady;
|
||||||
TEXT("immersive-training-session-recall-boundary"),
|
|
||||||
ImmersiveSessionRecallBoundary
|
|
||||||
) && ImmersiveSessionRecallBoundary.IsStructurallyValid();
|
|
||||||
const bool bBoundedPreferencesContinuityReady =
|
const bool bBoundedPreferencesContinuityReady =
|
||||||
bCameraSettingsContinuityReady && bImmersiveSessionRecallReady;
|
bCameraSettingsContinuityReady && bImmersiveSessionRecallReady;
|
||||||
|
|
||||||
|
|
@ -1347,24 +1376,15 @@ UHyperTwistTrainingPanelWidget::GetDisplayedControlInputReadinessInspectSurface(
|
||||||
*HyperTwistTrainingPanelWidgetInternal::DescribeBool(
|
*HyperTwistTrainingPanelWidgetInternal::DescribeBool(
|
||||||
Surface.bImmersivePresenceContractReady)
|
Surface.bImmersivePresenceContractReady)
|
||||||
);
|
);
|
||||||
Surface.PreferencesStatusLine = FString::Printf(
|
Surface.PreferencesStatusLine =
|
||||||
TEXT("Preferences continuity: %s | camera export %s | immersive recall %s | recall scopes %d | preference fields %d | polished rebinding and broader control-settings UI are not yet shipped."),
|
HyperTwistTrainingControlSurfaceFormatting::BuildControlInputPreferencesStatusLine(
|
||||||
*HyperTwistTrainingPanelWidgetInternal::DescribeAggregateReadyState(
|
|
||||||
bCameraSettingsContinuityReady,
|
bCameraSettingsContinuityReady,
|
||||||
bImmersiveSessionRecallReady),
|
CameraExportArtifactId,
|
||||||
*HyperTwistTrainingPanelWidgetInternal::DescribeIdOrFallback(
|
bImmersiveSessionRecallReady,
|
||||||
bCameraSettingsContinuityReady ? CameraExportArtifactId : FString()),
|
ImmersiveSessionRecallFacts.Boundary.BoundaryId,
|
||||||
*HyperTwistTrainingPanelWidgetInternal::DescribeIdOrFallback(
|
ImmersiveSessionRecallFacts.Boundary.RecallScopeIds.Num(),
|
||||||
bImmersiveSessionRecallReady
|
ImmersiveSessionRecallFacts.Boundary.PreferenceFieldTags.Num()
|
||||||
? ImmersiveSessionRecallBoundary.BoundaryId
|
);
|
||||||
: FString()),
|
|
||||||
bImmersiveSessionRecallReady
|
|
||||||
? ImmersiveSessionRecallBoundary.RecallScopeIds.Num()
|
|
||||||
: 0,
|
|
||||||
bImmersiveSessionRecallReady
|
|
||||||
? ImmersiveSessionRecallBoundary.PreferenceFieldTags.Num()
|
|
||||||
: 0
|
|
||||||
);
|
|
||||||
Surface.NextPacketLine =
|
Surface.NextPacketLine =
|
||||||
HyperTwistTrainingPanelWidgetInternal::BuildControlInputXrBoundaryLine();
|
HyperTwistTrainingPanelWidgetInternal::BuildControlInputXrBoundaryLine();
|
||||||
Surface.StatusLine = FString::Printf(
|
Surface.StatusLine = FString::Printf(
|
||||||
|
|
@ -1404,36 +1424,23 @@ UHyperTwistTrainingPanelWidget::GetDisplayedControlSettingsOwnershipInspectSurfa
|
||||||
FHyperTwistTrainingControlSettingsOwnershipInspectSurface Surface;
|
FHyperTwistTrainingControlSettingsOwnershipInspectSurface Surface;
|
||||||
Surface.Headline = TEXT("Control settings ownership");
|
Surface.Headline = TEXT("Control settings ownership");
|
||||||
|
|
||||||
const FHyperTwistTrainingViewerReferenceBundle ViewerBundle =
|
const HyperTwistTrainingPanelWidgetInternal::FViewerCameraSettingsFacts
|
||||||
UHyperTwistTrainingViewerLibrary::BuildBundledBrowserViewerReferenceBundle();
|
CameraSettingsFacts =
|
||||||
FHyperTwistTrainingViewerEditorToolReference CameraSettingsTool;
|
HyperTwistTrainingPanelWidgetInternal::BuildViewerCameraSettingsFacts();
|
||||||
Surface.bCameraSettingsReady =
|
Surface.bCameraSettingsReady = CameraSettingsFacts.bToolReady;
|
||||||
ViewerBundle.IsStructurallyValid()
|
|
||||||
&& HyperTwistTrainingPanelWidgetInternal::TryFindViewerEditorToolById(
|
|
||||||
ViewerBundle,
|
|
||||||
TEXT("tool/camera-settings"),
|
|
||||||
CameraSettingsTool
|
|
||||||
);
|
|
||||||
if (Surface.bCameraSettingsReady)
|
if (Surface.bCameraSettingsReady)
|
||||||
{
|
{
|
||||||
Surface.CameraSettingsToolId = CameraSettingsTool.ToolId;
|
Surface.CameraSettingsToolId = CameraSettingsFacts.Tool.ToolId;
|
||||||
Surface.CameraSettingsWorkflowTagCount = CameraSettingsTool.WorkflowTags.Num();
|
Surface.CameraSettingsWorkflowTagCount =
|
||||||
|
CameraSettingsFacts.Tool.WorkflowTags.Num();
|
||||||
Surface.CameraSettingsPreviewStateTagCount =
|
Surface.CameraSettingsPreviewStateTagCount =
|
||||||
CameraSettingsTool.PreviewStateTags.Num();
|
CameraSettingsFacts.Tool.PreviewStateTags.Num();
|
||||||
Surface.CameraSettingsExportArtifactCount =
|
Surface.CameraSettingsExportArtifactCount =
|
||||||
CameraSettingsTool.ExportArtifactIds.Num();
|
CameraSettingsFacts.Tool.ExportArtifactIds.Num();
|
||||||
}
|
}
|
||||||
FHyperTwistTrainingViewerQaArtifactReference CameraExportArtifact;
|
|
||||||
FString CameraExportArtifactId;
|
|
||||||
Surface.bCameraSettingsContinuityReady =
|
Surface.bCameraSettingsContinuityReady =
|
||||||
Surface.bCameraSettingsReady
|
CameraSettingsFacts.bExportArtifactReady;
|
||||||
&& HyperTwistTrainingPanelWidgetInternal::TryFindFirstViewerQaArtifactByIds(
|
Surface.CameraSettingsExportArtifactId = CameraSettingsFacts.ExportArtifactId;
|
||||||
ViewerBundle,
|
|
||||||
CameraSettingsTool.ExportArtifactIds,
|
|
||||||
CameraExportArtifactId,
|
|
||||||
CameraExportArtifact
|
|
||||||
);
|
|
||||||
Surface.CameraSettingsExportArtifactId = CameraExportArtifactId;
|
|
||||||
|
|
||||||
FHyperTwistTrainingImmersivePresenceControlContract ImmersivePresenceContract;
|
FHyperTwistTrainingImmersivePresenceControlContract ImmersivePresenceContract;
|
||||||
Surface.bImmersivePresenceSettingsReady =
|
Surface.bImmersivePresenceSettingsReady =
|
||||||
|
|
@ -1447,22 +1454,20 @@ UHyperTwistTrainingPanelWidget::GetDisplayedControlSettingsOwnershipInspectSurfa
|
||||||
Surface.ImmersivePresenceSurfaceTagCount =
|
Surface.ImmersivePresenceSurfaceTagCount =
|
||||||
ImmersivePresenceContract.PresenceSurfaceTags.Num();
|
ImmersivePresenceContract.PresenceSurfaceTags.Num();
|
||||||
}
|
}
|
||||||
FHyperTwistTrainingImmersiveSessionRecallBoundary ImmersiveSessionRecallBoundary;
|
const HyperTwistTrainingPanelWidgetInternal::FImmersiveSessionRecallFacts
|
||||||
Surface.bImmersiveSessionRecallReady =
|
ImmersiveSessionRecallFacts =
|
||||||
UHyperTwistTrainingRuntimeLibrary::TryGetBundledImmersiveSessionRecallBoundary(
|
HyperTwistTrainingPanelWidgetInternal::BuildImmersiveSessionRecallFacts();
|
||||||
TEXT("immersive-training-session-recall-boundary"),
|
Surface.bImmersiveSessionRecallReady = ImmersiveSessionRecallFacts.bReady;
|
||||||
ImmersiveSessionRecallBoundary
|
|
||||||
) && ImmersiveSessionRecallBoundary.IsStructurallyValid();
|
|
||||||
if (Surface.bImmersiveSessionRecallReady)
|
if (Surface.bImmersiveSessionRecallReady)
|
||||||
{
|
{
|
||||||
Surface.ImmersiveSessionRecallBoundaryId =
|
Surface.ImmersiveSessionRecallBoundaryId =
|
||||||
ImmersiveSessionRecallBoundary.BoundaryId;
|
ImmersiveSessionRecallFacts.Boundary.BoundaryId;
|
||||||
Surface.ImmersiveSessionRecallScopeCount =
|
Surface.ImmersiveSessionRecallScopeCount =
|
||||||
ImmersiveSessionRecallBoundary.RecallScopeIds.Num();
|
ImmersiveSessionRecallFacts.Boundary.RecallScopeIds.Num();
|
||||||
Surface.ImmersiveSessionRecallPreferenceFieldTagCount =
|
Surface.ImmersiveSessionRecallPreferenceFieldTagCount =
|
||||||
ImmersiveSessionRecallBoundary.PreferenceFieldTags.Num();
|
ImmersiveSessionRecallFacts.Boundary.PreferenceFieldTags.Num();
|
||||||
Surface.ImmersiveSessionRecallResetSurfaceTagCount =
|
Surface.ImmersiveSessionRecallResetSurfaceTagCount =
|
||||||
ImmersiveSessionRecallBoundary.ResetSurfaceTags.Num();
|
ImmersiveSessionRecallFacts.Boundary.ResetSurfaceTags.Num();
|
||||||
}
|
}
|
||||||
|
|
||||||
FHyperTwistTrainingHigherDimensionalRuntimeViewContextSurface Magic120CellViewContextSurface;
|
FHyperTwistTrainingHigherDimensionalRuntimeViewContextSurface Magic120CellViewContextSurface;
|
||||||
|
|
@ -1622,8 +1627,6 @@ UHyperTwistTrainingPanelWidget::GetDisplayedControlSettingsOwnershipInspectSurfa
|
||||||
Surface.bRequiresWindowsPackagedControllerValidationForReopen =
|
Surface.bRequiresWindowsPackagedControllerValidationForReopen =
|
||||||
XrBoundaryFacts.bRequiresWindowsPackagedControllerValidationForReopen;
|
XrBoundaryFacts.bRequiresWindowsPackagedControllerValidationForReopen;
|
||||||
|
|
||||||
const FString CameraSettingsToolId =
|
|
||||||
!Surface.CameraSettingsToolId.IsEmpty() ? Surface.CameraSettingsToolId : TEXT("n/a");
|
|
||||||
const FString ActiveViewContextId =
|
const FString ActiveViewContextId =
|
||||||
!Surface.ActiveHigherDimensionalViewContextId.IsEmpty()
|
!Surface.ActiveHigherDimensionalViewContextId.IsEmpty()
|
||||||
? Surface.ActiveHigherDimensionalViewContextId
|
? Surface.ActiveHigherDimensionalViewContextId
|
||||||
|
|
@ -1682,51 +1685,32 @@ UHyperTwistTrainingPanelWidget::GetDisplayedControlSettingsOwnershipInspectSurfa
|
||||||
const bool bMagicCube5DOwnedSettingsReady =
|
const bool bMagicCube5DOwnedSettingsReady =
|
||||||
Surface.bMagicCube5DViewSettingsReady
|
Surface.bMagicCube5DViewSettingsReady
|
||||||
&& Surface.bMagicCube5DPersistenceSettingsReady;
|
&& Surface.bMagicCube5DPersistenceSettingsReady;
|
||||||
const bool bCameraSettingsOwnedContinuityReady =
|
|
||||||
Surface.bCameraSettingsReady && Surface.bCameraSettingsContinuityReady;
|
|
||||||
const bool bImmersiveOwnedContinuityReady =
|
|
||||||
Surface.bImmersivePresenceSettingsReady
|
|
||||||
&& Surface.bImmersiveSessionRecallReady;
|
|
||||||
const FString DisplayCameraExportArtifactId =
|
|
||||||
!Surface.CameraSettingsExportArtifactId.IsEmpty()
|
|
||||||
? Surface.CameraSettingsExportArtifactId
|
|
||||||
: TEXT("n/a");
|
|
||||||
const FString ImmersivePresenceContractId =
|
|
||||||
!Surface.ImmersivePresenceContractId.IsEmpty()
|
|
||||||
? Surface.ImmersivePresenceContractId
|
|
||||||
: TEXT("n/a");
|
|
||||||
const FString ImmersiveSessionRecallBoundaryId =
|
|
||||||
!Surface.ImmersiveSessionRecallBoundaryId.IsEmpty()
|
|
||||||
? Surface.ImmersiveSessionRecallBoundaryId
|
|
||||||
: TEXT("n/a");
|
|
||||||
|
|
||||||
Surface.SummaryLine =
|
Surface.SummaryLine =
|
||||||
TEXT("Camera, immersive, and dedicated-family projection, selector, continuity, and persistence settings are already first-party owned, while XR/controller rebinding still remains unfinished.");
|
TEXT("Camera, immersive, and dedicated-family projection, selector, continuity, and persistence settings are already first-party owned, while XR/controller rebinding still remains unfinished.");
|
||||||
Surface.CameraSettingsLine = FString::Printf(
|
Surface.CameraSettingsLine =
|
||||||
TEXT("Viewer camera settings: %s | tool %s | camera export %s | workflow tags %d | preview states %d | export artifacts %d | orbit/framing/export surface is owned."),
|
HyperTwistTrainingControlSurfaceFormatting::BuildControlSettingsCameraSettingsLine(
|
||||||
*HyperTwistTrainingPanelWidgetInternal::DescribeOwnedContinuityState(
|
|
||||||
Surface.bCameraSettingsReady,
|
Surface.bCameraSettingsReady,
|
||||||
Surface.bCameraSettingsContinuityReady),
|
Surface.bCameraSettingsContinuityReady,
|
||||||
*CameraSettingsToolId,
|
Surface.CameraSettingsToolId,
|
||||||
*DisplayCameraExportArtifactId,
|
Surface.CameraSettingsExportArtifactId,
|
||||||
Surface.CameraSettingsWorkflowTagCount,
|
Surface.CameraSettingsWorkflowTagCount,
|
||||||
Surface.CameraSettingsPreviewStateTagCount,
|
Surface.CameraSettingsPreviewStateTagCount,
|
||||||
Surface.CameraSettingsExportArtifactCount
|
Surface.CameraSettingsExportArtifactCount
|
||||||
);
|
);
|
||||||
Surface.ImmersiveSettingsLine = FString::Printf(
|
Surface.ImmersiveSettingsLine =
|
||||||
TEXT("Immersive presence settings: %s | contract %s | session recall %s | intensity presets %d | reduced-distraction presets %d | presence tags %d | recall scopes %d | preference fields %d | reset surfaces %d."),
|
HyperTwistTrainingControlSurfaceFormatting::BuildControlSettingsImmersiveSettingsLine(
|
||||||
*HyperTwistTrainingPanelWidgetInternal::DescribeOwnedContinuityState(
|
|
||||||
Surface.bImmersivePresenceSettingsReady,
|
Surface.bImmersivePresenceSettingsReady,
|
||||||
Surface.bImmersiveSessionRecallReady),
|
Surface.bImmersiveSessionRecallReady,
|
||||||
*ImmersivePresenceContractId,
|
Surface.ImmersivePresenceContractId,
|
||||||
*ImmersiveSessionRecallBoundaryId,
|
Surface.ImmersiveSessionRecallBoundaryId,
|
||||||
ImmersivePresenceContract.ImmersionIntensityIds.Num(),
|
ImmersivePresenceContract.ImmersionIntensityIds.Num(),
|
||||||
ImmersivePresenceContract.ReducedDistractionPresetIds.Num(),
|
ImmersivePresenceContract.ReducedDistractionPresetIds.Num(),
|
||||||
Surface.ImmersivePresenceSurfaceTagCount,
|
Surface.ImmersivePresenceSurfaceTagCount,
|
||||||
Surface.ImmersiveSessionRecallScopeCount,
|
Surface.ImmersiveSessionRecallScopeCount,
|
||||||
Surface.ImmersiveSessionRecallPreferenceFieldTagCount,
|
Surface.ImmersiveSessionRecallPreferenceFieldTagCount,
|
||||||
Surface.ImmersiveSessionRecallResetSurfaceTagCount
|
Surface.ImmersiveSessionRecallResetSurfaceTagCount
|
||||||
);
|
);
|
||||||
Surface.Magic120CellSettingsLine = FString::Printf(
|
Surface.Magic120CellSettingsLine = FString::Printf(
|
||||||
TEXT("Magic120Cell owned settings: %s | profile %s | session %s | scene %s | persistence %s | semantics %s | selectors %d | projection tags %d | symmetry presets %d | visibility presets %d | focus surfaces %d."),
|
TEXT("Magic120Cell owned settings: %s | profile %s | session %s | scene %s | persistence %s | semantics %s | selectors %d | projection tags %d | symmetry presets %d | visibility presets %d | focus surfaces %d."),
|
||||||
*HyperTwistTrainingPanelWidgetInternal::DescribeReadyState(
|
*HyperTwistTrainingPanelWidgetInternal::DescribeReadyState(
|
||||||
|
|
@ -1774,19 +1758,17 @@ UHyperTwistTrainingPanelWidget::GetDisplayedControlSettingsOwnershipInspectSurfa
|
||||||
HyperTwistTrainingPanelWidgetInternal::BuildControlSettingsXrBoundaryLine(
|
HyperTwistTrainingPanelWidgetInternal::BuildControlSettingsXrBoundaryLine(
|
||||||
Surface.bOpenXrProjectPluginEnabled
|
Surface.bOpenXrProjectPluginEnabled
|
||||||
);
|
);
|
||||||
Surface.StatusLine = FString::Printf(
|
Surface.StatusLine =
|
||||||
TEXT("camera %s | immersive %s | 120-cell owned settings %s | 5D owned settings %s | selectors %s | selector recall %s | XR rebinding not yet shipped"),
|
HyperTwistTrainingControlSurfaceFormatting::BuildControlSettingsStatusLine(
|
||||||
*HyperTwistTrainingPanelWidgetInternal::DescribeOwnedContinuityState(
|
|
||||||
Surface.bCameraSettingsReady,
|
Surface.bCameraSettingsReady,
|
||||||
Surface.bCameraSettingsContinuityReady),
|
Surface.bCameraSettingsContinuityReady,
|
||||||
*HyperTwistTrainingPanelWidgetInternal::DescribeOwnedContinuityState(
|
|
||||||
Surface.bImmersivePresenceSettingsReady,
|
Surface.bImmersivePresenceSettingsReady,
|
||||||
Surface.bImmersiveSessionRecallReady),
|
Surface.bImmersiveSessionRecallReady,
|
||||||
bMagic120CellOwnedSettingsReady ? TEXT("ready") : TEXT("partial"),
|
bMagic120CellOwnedSettingsReady,
|
||||||
bMagicCube5DOwnedSettingsReady ? TEXT("ready") : TEXT("partial"),
|
bMagicCube5DOwnedSettingsReady,
|
||||||
Surface.bHigherDimensionalSelectorSettingsReady ? TEXT("ready") : TEXT("partial"),
|
Surface.bHigherDimensionalSelectorSettingsReady,
|
||||||
Surface.bRepositoryBackedSelectorRecallReady ? TEXT("ready") : TEXT("unavailable")
|
Surface.bRepositoryBackedSelectorRecallReady
|
||||||
);
|
);
|
||||||
Surface.DetailLine = FString::Printf(
|
Surface.DetailLine = FString::Printf(
|
||||||
TEXT("%s | %s | %s | %s | %s | %s | %s"),
|
TEXT("%s | %s | %s | %s | %s | %s | %s"),
|
||||||
*Surface.CameraSettingsLine,
|
*Surface.CameraSettingsLine,
|
||||||
|
|
@ -1827,6 +1809,25 @@ UHyperTwistTrainingPanelWidget::GetDisplayedControlProfileRosterInspectSurface()
|
||||||
Surface.ReducedDistractionPresetCount =
|
Surface.ReducedDistractionPresetCount =
|
||||||
PresenceContract.ReducedDistractionPresetIds.Num();
|
PresenceContract.ReducedDistractionPresetIds.Num();
|
||||||
}
|
}
|
||||||
|
const HyperTwistTrainingPanelWidgetInternal::FViewerCameraSettingsFacts
|
||||||
|
CameraSettingsFacts =
|
||||||
|
HyperTwistTrainingPanelWidgetInternal::BuildViewerCameraSettingsFacts();
|
||||||
|
Surface.bCameraSettingsContinuityReady =
|
||||||
|
CameraSettingsFacts.bExportArtifactReady;
|
||||||
|
Surface.CameraSettingsExportArtifactId = CameraSettingsFacts.ExportArtifactId;
|
||||||
|
const HyperTwistTrainingPanelWidgetInternal::FImmersiveSessionRecallFacts
|
||||||
|
ImmersiveSessionRecallFacts =
|
||||||
|
HyperTwistTrainingPanelWidgetInternal::BuildImmersiveSessionRecallFacts();
|
||||||
|
Surface.bImmersiveSessionRecallReady = ImmersiveSessionRecallFacts.bReady;
|
||||||
|
if (Surface.bImmersiveSessionRecallReady)
|
||||||
|
{
|
||||||
|
Surface.ImmersiveSessionRecallBoundaryId =
|
||||||
|
ImmersiveSessionRecallFacts.Boundary.BoundaryId;
|
||||||
|
Surface.ImmersiveSessionRecallScopeCount =
|
||||||
|
ImmersiveSessionRecallFacts.Boundary.RecallScopeIds.Num();
|
||||||
|
Surface.ImmersiveSessionRecallPreferenceFieldTagCount =
|
||||||
|
ImmersiveSessionRecallFacts.Boundary.PreferenceFieldTags.Num();
|
||||||
|
}
|
||||||
|
|
||||||
const FHyperTwistTrainingMagic120CellReferenceBundle Magic120CellBundle =
|
const FHyperTwistTrainingMagic120CellReferenceBundle Magic120CellBundle =
|
||||||
UHyperTwistTrainingRuntimeLibrary::GetBundledMagic120CellReferenceBundle();
|
UHyperTwistTrainingRuntimeLibrary::GetBundledMagic120CellReferenceBundle();
|
||||||
|
|
@ -1900,6 +1901,10 @@ UHyperTwistTrainingPanelWidget::GetDisplayedControlProfileRosterInspectSurface()
|
||||||
HasDisplayedHigherDimensionalRuntimeSessionSurface()
|
HasDisplayedHigherDimensionalRuntimeSessionSurface()
|
||||||
? GetDisplayedHigherDimensionalRuntimeSessionSurface()
|
? GetDisplayedHigherDimensionalRuntimeSessionSurface()
|
||||||
: FHyperTwistTrainingHigherDimensionalRuntimeSessionSurface();
|
: FHyperTwistTrainingHigherDimensionalRuntimeSessionSurface();
|
||||||
|
const FHyperTwistTrainingHigherDimensionalInteractiveSceneSurface ActiveSceneSurface =
|
||||||
|
HasDisplayedHigherDimensionalInteractiveSceneSurface()
|
||||||
|
? GetDisplayedHigherDimensionalInteractiveSceneSurface()
|
||||||
|
: FHyperTwistTrainingHigherDimensionalInteractiveSceneSurface();
|
||||||
Surface.bActiveHigherDimensionalProfileVisible = ActiveActivationProfile.IsStructurallyValid();
|
Surface.bActiveHigherDimensionalProfileVisible = ActiveActivationProfile.IsStructurallyValid();
|
||||||
Surface.ActiveHigherDimensionalActivationProfileId =
|
Surface.ActiveHigherDimensionalActivationProfileId =
|
||||||
Surface.bActiveHigherDimensionalProfileVisible
|
Surface.bActiveHigherDimensionalProfileVisible
|
||||||
|
|
@ -1911,6 +1916,10 @@ UHyperTwistTrainingPanelWidget::GetDisplayedControlProfileRosterInspectSurface()
|
||||||
Surface.ActiveHigherDimensionalSessionSurfaceId = ActiveSessionSurface.IsStructurallyValid()
|
Surface.ActiveHigherDimensionalSessionSurfaceId = ActiveSessionSurface.IsStructurallyValid()
|
||||||
? ActiveSessionSurface.SessionSurfaceId
|
? ActiveSessionSurface.SessionSurfaceId
|
||||||
: TEXT("none");
|
: TEXT("none");
|
||||||
|
Surface.ActiveHigherDimensionalInteractiveSceneSurfaceId =
|
||||||
|
ActiveSceneSurface.IsStructurallyValid()
|
||||||
|
? ActiveSceneSurface.SceneSurfaceId
|
||||||
|
: TEXT("none");
|
||||||
Surface.ActiveHigherDimensionalSelectorCount = ActiveViewContextSurface.IsStructurallyValid()
|
Surface.ActiveHigherDimensionalSelectorCount = ActiveViewContextSurface.IsStructurallyValid()
|
||||||
? ActiveViewContextSurface.Selectors.Num()
|
? ActiveViewContextSurface.Selectors.Num()
|
||||||
: 0;
|
: 0;
|
||||||
|
|
@ -1975,9 +1984,12 @@ UHyperTwistTrainingPanelWidget::GetDisplayedControlProfileRosterInspectSurface()
|
||||||
!Surface.ActiveHigherDimensionalSessionSurfaceId.IsEmpty()
|
!Surface.ActiveHigherDimensionalSessionSurfaceId.IsEmpty()
|
||||||
? Surface.ActiveHigherDimensionalSessionSurfaceId
|
? Surface.ActiveHigherDimensionalSessionSurfaceId
|
||||||
: TEXT("none");
|
: TEXT("none");
|
||||||
|
const FString ActiveSceneSurfaceId =
|
||||||
|
!Surface.ActiveHigherDimensionalInteractiveSceneSurfaceId.IsEmpty()
|
||||||
|
? Surface.ActiveHigherDimensionalInteractiveSceneSurfaceId
|
||||||
|
: TEXT("none");
|
||||||
Surface.SummaryLine =
|
Surface.SummaryLine =
|
||||||
TEXT("The shipped selectable roster currently covers the classic keyboard mapping, scenic immersive presets, and dedicated 120-cell/5D view-selector families, while controller rebinding still remains unfinished.");
|
TEXT("The shipped selectable roster currently covers the classic keyboard mapping, scenic immersive presets, bounded camera or immersive continuity, and dedicated 120-cell/5D view-selector families, while controller rebinding still remains unfinished.");
|
||||||
Surface.ClassicKeyboardProfileLine = FString::Printf(
|
Surface.ClassicKeyboardProfileLine = FString::Printf(
|
||||||
TEXT("Classic keyboard profile: %s | bindings %d | ctrl suppressed %s | alt suppressed %s | meta suppressed %s | repeat suppressed %s."),
|
TEXT("Classic keyboard profile: %s | bindings %d | ctrl suppressed %s | alt suppressed %s | meta suppressed %s | repeat suppressed %s."),
|
||||||
*ClassicKeyboardProfileName,
|
*ClassicKeyboardProfileName,
|
||||||
|
|
@ -2022,10 +2034,11 @@ UHyperTwistTrainingPanelWidget::GetDisplayedControlProfileRosterInspectSurface()
|
||||||
Surface.ActiveHigherDimensionalProfileLine =
|
Surface.ActiveHigherDimensionalProfileLine =
|
||||||
Surface.bActiveHigherDimensionalProfileVisible
|
Surface.bActiveHigherDimensionalProfileVisible
|
||||||
? FString::Printf(
|
? FString::Printf(
|
||||||
TEXT("Active higher-dimensional selection: activation %s | view context %s | session %s | visible selectors %d."),
|
TEXT("Active higher-dimensional selection: activation %s | view context %s | session %s | scene %s | visible selectors %d."),
|
||||||
*ActiveActivationProfileId,
|
*ActiveActivationProfileId,
|
||||||
*ActiveViewContextId,
|
*ActiveViewContextId,
|
||||||
*ActiveSessionSurfaceId,
|
*ActiveSessionSurfaceId,
|
||||||
|
*ActiveSceneSurfaceId,
|
||||||
Surface.ActiveHigherDimensionalSelectorCount
|
Surface.ActiveHigherDimensionalSelectorCount
|
||||||
)
|
)
|
||||||
: TEXT("Active higher-dimensional selection: none currently displayed in this widget.");
|
: TEXT("Active higher-dimensional selection: none currently displayed in this widget.");
|
||||||
|
|
@ -2033,21 +2046,32 @@ UHyperTwistTrainingPanelWidget::GetDisplayedControlProfileRosterInspectSurface()
|
||||||
HyperTwistTrainingPanelWidgetInternal::BuildSelectorRecallLine(
|
HyperTwistTrainingPanelWidgetInternal::BuildSelectorRecallLine(
|
||||||
SelectorRecallFacts
|
SelectorRecallFacts
|
||||||
);
|
);
|
||||||
|
Surface.PreferencesContinuityLine =
|
||||||
|
HyperTwistTrainingControlSurfaceFormatting::BuildControlProfilePreferencesContinuityLine(
|
||||||
|
Surface.bCameraSettingsContinuityReady,
|
||||||
|
Surface.CameraSettingsExportArtifactId,
|
||||||
|
Surface.bImmersiveSessionRecallReady,
|
||||||
|
Surface.ImmersiveSessionRecallBoundaryId,
|
||||||
|
Surface.ImmersiveSessionRecallScopeCount,
|
||||||
|
Surface.ImmersiveSessionRecallPreferenceFieldTagCount
|
||||||
|
);
|
||||||
Surface.PreferencesGapLine =
|
Surface.PreferencesGapLine =
|
||||||
HyperTwistTrainingPanelWidgetInternal::BuildControlProfileRosterXrBoundaryLine(
|
HyperTwistTrainingPanelWidgetInternal::BuildControlProfileRosterXrBoundaryLine(
|
||||||
Surface.bOpenXrProjectPluginEnabled
|
Surface.bOpenXrProjectPluginEnabled
|
||||||
);
|
);
|
||||||
Surface.StatusLine = FString::Printf(
|
Surface.StatusLine =
|
||||||
TEXT("classic keyboard %s | immersive presets %s | 120-cell family %s | 5D family %s | active selection %s | selector recall %s | controller rebinding not yet shipped"),
|
HyperTwistTrainingControlSurfaceFormatting::BuildControlProfileStatusLine(
|
||||||
Surface.bClassicKeyboardProfileReady ? TEXT("ready") : TEXT("missing"),
|
Surface.bClassicKeyboardProfileReady,
|
||||||
Surface.bImmersivePresenceProfileReady ? TEXT("ready") : TEXT("missing"),
|
Surface.bImmersivePresenceProfileReady,
|
||||||
Surface.bMagic120CellProfileReady ? TEXT("ready") : TEXT("missing"),
|
Surface.bMagic120CellProfileReady,
|
||||||
Surface.bMagicCube5DProfileReady ? TEXT("ready") : TEXT("missing"),
|
Surface.bMagicCube5DProfileReady,
|
||||||
Surface.bActiveHigherDimensionalProfileVisible ? TEXT("visible") : TEXT("not loaded"),
|
Surface.bActiveHigherDimensionalProfileVisible,
|
||||||
Surface.bRepositoryBackedSelectorRecallReady ? TEXT("ready") : TEXT("unavailable")
|
Surface.bRepositoryBackedSelectorRecallReady,
|
||||||
);
|
Surface.bCameraSettingsContinuityReady,
|
||||||
|
Surface.bImmersiveSessionRecallReady
|
||||||
|
);
|
||||||
Surface.DetailLine = FString::Printf(
|
Surface.DetailLine = FString::Printf(
|
||||||
TEXT("%s | %s | %s | %s | %s | %s | %s | %s"),
|
TEXT("%s | %s | %s | %s | %s | %s | %s | %s | %s"),
|
||||||
*Surface.ClassicKeyboardProfileLine,
|
*Surface.ClassicKeyboardProfileLine,
|
||||||
*Surface.ClassicKeyboardMoveRosterLine,
|
*Surface.ClassicKeyboardMoveRosterLine,
|
||||||
*Surface.ImmersivePresenceProfileLine,
|
*Surface.ImmersivePresenceProfileLine,
|
||||||
|
|
@ -2055,6 +2079,7 @@ UHyperTwistTrainingPanelWidget::GetDisplayedControlProfileRosterInspectSurface()
|
||||||
*Surface.MagicCube5DProfileLine,
|
*Surface.MagicCube5DProfileLine,
|
||||||
*Surface.ActiveHigherDimensionalProfileLine,
|
*Surface.ActiveHigherDimensionalProfileLine,
|
||||||
*Surface.SelectorRecallLine,
|
*Surface.SelectorRecallLine,
|
||||||
|
*Surface.PreferencesContinuityLine,
|
||||||
*Surface.PreferencesGapLine
|
*Surface.PreferencesGapLine
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10353,6 +10353,9 @@ struct FHyperTwistTrainingControlProfileRosterInspectSurface
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||||
FString SelectorRecallLine;
|
FString SelectorRecallLine;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||||
|
FString PreferencesContinuityLine;
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||||
FString PreferencesGapLine;
|
FString PreferencesGapLine;
|
||||||
|
|
||||||
|
|
@ -10365,6 +10368,12 @@ struct FHyperTwistTrainingControlProfileRosterInspectSurface
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||||
FString ImmersivePresenceContractId;
|
FString ImmersivePresenceContractId;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||||
|
FString CameraSettingsExportArtifactId;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||||
|
FString ImmersiveSessionRecallBoundaryId;
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||||
FString Magic120CellRuntimeProfileContractId;
|
FString Magic120CellRuntimeProfileContractId;
|
||||||
|
|
||||||
|
|
@ -10386,6 +10395,9 @@ struct FHyperTwistTrainingControlProfileRosterInspectSurface
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||||
FString ActiveHigherDimensionalSessionSurfaceId;
|
FString ActiveHigherDimensionalSessionSurfaceId;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||||
|
FString ActiveHigherDimensionalInteractiveSceneSurfaceId;
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||||
int32 ClassicKeyboardBindingCount = 0;
|
int32 ClassicKeyboardBindingCount = 0;
|
||||||
|
|
||||||
|
|
@ -10407,12 +10419,24 @@ struct FHyperTwistTrainingControlProfileRosterInspectSurface
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||||
int32 RecalledHigherDimensionalSelectorCount = 0;
|
int32 RecalledHigherDimensionalSelectorCount = 0;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||||
|
int32 ImmersiveSessionRecallScopeCount = 0;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||||
|
int32 ImmersiveSessionRecallPreferenceFieldTagCount = 0;
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||||
bool bClassicKeyboardProfileReady = false;
|
bool bClassicKeyboardProfileReady = false;
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||||
bool bImmersivePresenceProfileReady = false;
|
bool bImmersivePresenceProfileReady = false;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||||
|
bool bCameraSettingsContinuityReady = false;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||||
|
bool bImmersiveSessionRecallReady = false;
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||||
bool bMagic120CellProfileReady = false;
|
bool bMagic120CellProfileReady = false;
|
||||||
|
|
||||||
|
|
@ -10454,8 +10478,11 @@ struct FHyperTwistTrainingControlProfileRosterInspectSurface
|
||||||
|| !MagicCube5DProfileLine.IsEmpty()
|
|| !MagicCube5DProfileLine.IsEmpty()
|
||||||
|| !ActiveHigherDimensionalProfileLine.IsEmpty()
|
|| !ActiveHigherDimensionalProfileLine.IsEmpty()
|
||||||
|| !SelectorRecallLine.IsEmpty()
|
|| !SelectorRecallLine.IsEmpty()
|
||||||
|
|| !PreferencesContinuityLine.IsEmpty()
|
||||||
|| bClassicKeyboardProfileReady
|
|| bClassicKeyboardProfileReady
|
||||||
|| bImmersivePresenceProfileReady
|
|| bImmersivePresenceProfileReady
|
||||||
|
|| bCameraSettingsContinuityReady
|
||||||
|
|| bImmersiveSessionRecallReady
|
||||||
|| bMagic120CellProfileReady
|
|| bMagic120CellProfileReady
|
||||||
|| bMagicCube5DProfileReady
|
|| bMagicCube5DProfileReady
|
||||||
|| bActiveHigherDimensionalProfileVisible
|
|| bActiveHigherDimensionalProfileVisible
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,492 @@
|
||||||
|
// Copyright HyperTwist, Inc. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "Misc/AutomationTest.h"
|
||||||
|
|
||||||
|
#include "Blueprint/WidgetTree.h"
|
||||||
|
#include "Components/TextBlock.h"
|
||||||
|
#include "HyperTwistTraining/HyperTwistCoachDashboardWidget.h"
|
||||||
|
#include "HyperTwistTraining/HyperTwistTrainingControlSurfaceFormatting.h"
|
||||||
|
#include "HyperTwistTraining/HyperTwistTrainingPanelWidget.h"
|
||||||
|
#include "HyperTwistTraining/HyperTwistTrainingRuntimeLibrary.h"
|
||||||
|
|
||||||
|
#if WITH_AUTOMATION_TESTS
|
||||||
|
|
||||||
|
namespace HyperTwistControlProfileContinuityParityTestInternal
|
||||||
|
{
|
||||||
|
UTextBlock* FindDashboardTextBlock(
|
||||||
|
const UHyperTwistCoachDashboardWidget* CoachDashboard,
|
||||||
|
const TCHAR* WidgetName
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (CoachDashboard == nullptr)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
UWidgetTree* WidgetTree = CoachDashboard->WidgetTree;
|
||||||
|
if (WidgetTree == nullptr)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Cast<UTextBlock>(WidgetTree->FindWidget(FName(WidgetName)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
|
||||||
|
FHyperTwistControlInputContinuityStateFormattingTest,
|
||||||
|
"HyperTwist.Browser.ControlInputContinuityStateFormatting",
|
||||||
|
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
|
||||||
|
)
|
||||||
|
|
||||||
|
bool FHyperTwistControlInputContinuityStateFormattingTest::RunTest(
|
||||||
|
const FString& Parameters
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const FString MissingLine =
|
||||||
|
HyperTwistTrainingControlSurfaceFormatting::BuildControlInputPreferencesStatusLine(
|
||||||
|
false,
|
||||||
|
FString(),
|
||||||
|
false,
|
||||||
|
FString(),
|
||||||
|
7,
|
||||||
|
9
|
||||||
|
);
|
||||||
|
TestTrue(
|
||||||
|
TEXT("The control/input continuity formatter must render a fully absent continuity lane as missing with explicit fallback ids and zero recall counts."),
|
||||||
|
MissingLine.Contains(TEXT("Preferences continuity: missing"))
|
||||||
|
&& MissingLine.Contains(TEXT("camera export n/a"))
|
||||||
|
&& MissingLine.Contains(TEXT("immersive recall n/a"))
|
||||||
|
&& MissingLine.Contains(TEXT("recall scopes 0"))
|
||||||
|
&& MissingLine.Contains(TEXT("preference fields 0"))
|
||||||
|
);
|
||||||
|
|
||||||
|
const FString PartialLine =
|
||||||
|
HyperTwistTrainingControlSurfaceFormatting::BuildControlInputPreferencesStatusLine(
|
||||||
|
true,
|
||||||
|
TEXT("artifact/camera-export-json"),
|
||||||
|
false,
|
||||||
|
FString(),
|
||||||
|
7,
|
||||||
|
9
|
||||||
|
);
|
||||||
|
TestTrue(
|
||||||
|
TEXT("The control/input continuity formatter must render a one-sided continuity lane as partial while preserving the ready id and withholding the missing one."),
|
||||||
|
PartialLine.Contains(TEXT("Preferences continuity: partial"))
|
||||||
|
&& PartialLine.Contains(TEXT("camera export artifact/camera-export-json"))
|
||||||
|
&& PartialLine.Contains(TEXT("immersive recall n/a"))
|
||||||
|
&& PartialLine.Contains(TEXT("recall scopes 0"))
|
||||||
|
&& PartialLine.Contains(TEXT("preference fields 0"))
|
||||||
|
);
|
||||||
|
|
||||||
|
const FString ReadyLine =
|
||||||
|
HyperTwistTrainingControlSurfaceFormatting::BuildControlInputPreferencesStatusLine(
|
||||||
|
true,
|
||||||
|
TEXT("artifact/camera-export-json"),
|
||||||
|
true,
|
||||||
|
TEXT("immersive-training-session-recall-boundary"),
|
||||||
|
3,
|
||||||
|
5
|
||||||
|
);
|
||||||
|
TestTrue(
|
||||||
|
TEXT("The control/input continuity formatter must render a fully ready continuity lane with the shipped ids and live recall counts."),
|
||||||
|
ReadyLine.Contains(TEXT("Preferences continuity: ready"))
|
||||||
|
&& ReadyLine.Contains(TEXT("camera export artifact/camera-export-json"))
|
||||||
|
&& ReadyLine.Contains(TEXT("immersive recall immersive-training-session-recall-boundary"))
|
||||||
|
&& ReadyLine.Contains(TEXT("recall scopes 3"))
|
||||||
|
&& ReadyLine.Contains(TEXT("preference fields 5"))
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
|
||||||
|
FHyperTwistControlSettingsContinuityStateFormattingTest,
|
||||||
|
"HyperTwist.Browser.ControlSettingsContinuityStateFormatting",
|
||||||
|
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
|
||||||
|
)
|
||||||
|
|
||||||
|
bool FHyperTwistControlSettingsContinuityStateFormattingTest::RunTest(
|
||||||
|
const FString& Parameters
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const FString MissingCameraLine =
|
||||||
|
HyperTwistTrainingControlSurfaceFormatting::BuildControlSettingsCameraSettingsLine(
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
TEXT("tool/camera-settings"),
|
||||||
|
TEXT("artifact/camera-export-json"),
|
||||||
|
3,
|
||||||
|
2,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
TestTrue(
|
||||||
|
TEXT("The control/settings camera continuity formatter must render a fully absent camera lane as missing with fallback ids and zero out stale tool counts."),
|
||||||
|
MissingCameraLine.Contains(TEXT("Viewer camera settings: missing"))
|
||||||
|
&& MissingCameraLine.Contains(TEXT("tool n/a"))
|
||||||
|
&& MissingCameraLine.Contains(TEXT("camera export n/a"))
|
||||||
|
&& MissingCameraLine.Contains(TEXT("workflow tags 0"))
|
||||||
|
&& MissingCameraLine.Contains(TEXT("preview states 0"))
|
||||||
|
&& MissingCameraLine.Contains(TEXT("export artifacts 0"))
|
||||||
|
);
|
||||||
|
|
||||||
|
const FString PartialCameraLine =
|
||||||
|
HyperTwistTrainingControlSurfaceFormatting::BuildControlSettingsCameraSettingsLine(
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
TEXT("tool/camera-settings"),
|
||||||
|
FString(),
|
||||||
|
3,
|
||||||
|
2,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
TestTrue(
|
||||||
|
TEXT("The control/settings camera continuity formatter must render owned-but-not-continuous camera state as partial."),
|
||||||
|
PartialCameraLine.Contains(TEXT("Viewer camera settings: partial"))
|
||||||
|
&& PartialCameraLine.Contains(TEXT("tool tool/camera-settings"))
|
||||||
|
&& PartialCameraLine.Contains(TEXT("camera export n/a"))
|
||||||
|
);
|
||||||
|
|
||||||
|
const FString ReadyCameraLine =
|
||||||
|
HyperTwistTrainingControlSurfaceFormatting::BuildControlSettingsCameraSettingsLine(
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
TEXT("tool/camera-settings"),
|
||||||
|
TEXT("artifact/camera-export-json"),
|
||||||
|
3,
|
||||||
|
2,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
TestTrue(
|
||||||
|
TEXT("The control/settings camera continuity formatter must render a fully ready camera lane with the shipped export id."),
|
||||||
|
ReadyCameraLine.Contains(TEXT("Viewer camera settings: ready"))
|
||||||
|
&& ReadyCameraLine.Contains(TEXT("tool tool/camera-settings"))
|
||||||
|
&& ReadyCameraLine.Contains(TEXT("camera export artifact/camera-export-json"))
|
||||||
|
);
|
||||||
|
|
||||||
|
const FString MissingImmersiveLine =
|
||||||
|
HyperTwistTrainingControlSurfaceFormatting::BuildControlSettingsImmersiveSettingsLine(
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
TEXT("immersive-training-presence-control-contract"),
|
||||||
|
TEXT("immersive-training-session-recall-boundary"),
|
||||||
|
3,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
7,
|
||||||
|
9,
|
||||||
|
11
|
||||||
|
);
|
||||||
|
TestTrue(
|
||||||
|
TEXT("The control/settings immersive continuity formatter must render a fully absent immersive lane as missing with fallback ids and zero out stale presence and recall counts."),
|
||||||
|
MissingImmersiveLine.Contains(TEXT("Immersive presence settings: missing"))
|
||||||
|
&& MissingImmersiveLine.Contains(TEXT("contract n/a"))
|
||||||
|
&& MissingImmersiveLine.Contains(TEXT("session recall n/a"))
|
||||||
|
&& MissingImmersiveLine.Contains(TEXT("intensity presets 0"))
|
||||||
|
&& MissingImmersiveLine.Contains(TEXT("reduced-distraction presets 0"))
|
||||||
|
&& MissingImmersiveLine.Contains(TEXT("presence tags 0"))
|
||||||
|
&& MissingImmersiveLine.Contains(TEXT("recall scopes 0"))
|
||||||
|
&& MissingImmersiveLine.Contains(TEXT("preference fields 0"))
|
||||||
|
&& MissingImmersiveLine.Contains(TEXT("reset surfaces 0"))
|
||||||
|
);
|
||||||
|
|
||||||
|
const FString PartialImmersiveLine =
|
||||||
|
HyperTwistTrainingControlSurfaceFormatting::BuildControlSettingsImmersiveSettingsLine(
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
TEXT("immersive-training-presence-control-contract"),
|
||||||
|
FString(),
|
||||||
|
3,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
7,
|
||||||
|
9,
|
||||||
|
11
|
||||||
|
);
|
||||||
|
TestTrue(
|
||||||
|
TEXT("The control/settings immersive continuity formatter must render owned-but-not-recalled immersive state as partial while masking stale recall counts."),
|
||||||
|
PartialImmersiveLine.Contains(TEXT("Immersive presence settings: partial"))
|
||||||
|
&& PartialImmersiveLine.Contains(TEXT("contract immersive-training-presence-control-contract"))
|
||||||
|
&& PartialImmersiveLine.Contains(TEXT("session recall n/a"))
|
||||||
|
&& PartialImmersiveLine.Contains(TEXT("recall scopes 0"))
|
||||||
|
&& PartialImmersiveLine.Contains(TEXT("preference fields 0"))
|
||||||
|
&& PartialImmersiveLine.Contains(TEXT("reset surfaces 0"))
|
||||||
|
);
|
||||||
|
|
||||||
|
const FString ReadyImmersiveLine =
|
||||||
|
HyperTwistTrainingControlSurfaceFormatting::BuildControlSettingsImmersiveSettingsLine(
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
TEXT("immersive-training-presence-control-contract"),
|
||||||
|
TEXT("immersive-training-session-recall-boundary"),
|
||||||
|
3,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
3,
|
||||||
|
5,
|
||||||
|
3
|
||||||
|
);
|
||||||
|
TestTrue(
|
||||||
|
TEXT("The control/settings immersive continuity formatter must render a fully ready immersive lane with the shipped recall id and counts."),
|
||||||
|
ReadyImmersiveLine.Contains(TEXT("Immersive presence settings: ready"))
|
||||||
|
&& ReadyImmersiveLine.Contains(TEXT("contract immersive-training-presence-control-contract"))
|
||||||
|
&& ReadyImmersiveLine.Contains(TEXT("session recall immersive-training-session-recall-boundary"))
|
||||||
|
&& ReadyImmersiveLine.Contains(TEXT("recall scopes 3"))
|
||||||
|
&& ReadyImmersiveLine.Contains(TEXT("preference fields 5"))
|
||||||
|
);
|
||||||
|
|
||||||
|
const FString MixedStatusLine =
|
||||||
|
HyperTwistTrainingControlSurfaceFormatting::BuildControlSettingsStatusLine(
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
TestTrue(
|
||||||
|
TEXT("The control/settings status formatter must keep mixed missing-versus-partial continuity truth explicit instead of collapsing it into one generic degraded label."),
|
||||||
|
MixedStatusLine.Contains(TEXT("camera missing"))
|
||||||
|
&& MixedStatusLine.Contains(TEXT("immersive partial"))
|
||||||
|
&& MixedStatusLine.Contains(TEXT("120-cell owned settings ready"))
|
||||||
|
&& MixedStatusLine.Contains(TEXT("5D owned settings partial"))
|
||||||
|
&& MixedStatusLine.Contains(TEXT("selectors partial"))
|
||||||
|
&& MixedStatusLine.Contains(TEXT("selector recall unavailable"))
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
|
||||||
|
FHyperTwistControlProfileContinuityStateFormattingTest,
|
||||||
|
"HyperTwist.Browser.ControlProfileContinuityStateFormatting",
|
||||||
|
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
|
||||||
|
)
|
||||||
|
|
||||||
|
bool FHyperTwistControlProfileContinuityStateFormattingTest::RunTest(
|
||||||
|
const FString& Parameters
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const FString MissingContinuityLine =
|
||||||
|
HyperTwistTrainingControlSurfaceFormatting::BuildControlProfilePreferencesContinuityLine(
|
||||||
|
false,
|
||||||
|
FString(),
|
||||||
|
false,
|
||||||
|
FString(),
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
TestTrue(
|
||||||
|
TEXT("The control/profile continuity formatter must render a fully absent continuity lane as missing with fallback ids."),
|
||||||
|
MissingContinuityLine.Contains(TEXT("Profile continuity: missing"))
|
||||||
|
&& MissingContinuityLine.Contains(TEXT("camera export n/a"))
|
||||||
|
&& MissingContinuityLine.Contains(TEXT("immersive recall n/a"))
|
||||||
|
);
|
||||||
|
|
||||||
|
const FString PartialContinuityLine =
|
||||||
|
HyperTwistTrainingControlSurfaceFormatting::BuildControlProfilePreferencesContinuityLine(
|
||||||
|
true,
|
||||||
|
TEXT("artifact/camera-export-json"),
|
||||||
|
false,
|
||||||
|
FString(),
|
||||||
|
7,
|
||||||
|
9
|
||||||
|
);
|
||||||
|
TestTrue(
|
||||||
|
TEXT("The control/profile continuity formatter must render a one-sided continuity lane as partial while preserving the ready id and masking stale recall counts."),
|
||||||
|
PartialContinuityLine.Contains(TEXT("Profile continuity: partial"))
|
||||||
|
&& PartialContinuityLine.Contains(TEXT("camera export artifact/camera-export-json"))
|
||||||
|
&& PartialContinuityLine.Contains(TEXT("immersive recall n/a"))
|
||||||
|
&& PartialContinuityLine.Contains(TEXT("recall scopes 0"))
|
||||||
|
&& PartialContinuityLine.Contains(TEXT("preference fields 0"))
|
||||||
|
);
|
||||||
|
|
||||||
|
const FString ReadyContinuityLine =
|
||||||
|
HyperTwistTrainingControlSurfaceFormatting::BuildControlProfilePreferencesContinuityLine(
|
||||||
|
true,
|
||||||
|
TEXT("artifact/camera-export-json"),
|
||||||
|
true,
|
||||||
|
TEXT("immersive-training-session-recall-boundary"),
|
||||||
|
3,
|
||||||
|
5
|
||||||
|
);
|
||||||
|
TestTrue(
|
||||||
|
TEXT("The control/profile continuity formatter must render a fully ready continuity lane with the shipped ids and counts."),
|
||||||
|
ReadyContinuityLine.Contains(TEXT("Profile continuity: ready"))
|
||||||
|
&& ReadyContinuityLine.Contains(TEXT("camera export artifact/camera-export-json"))
|
||||||
|
&& ReadyContinuityLine.Contains(TEXT("immersive recall immersive-training-session-recall-boundary"))
|
||||||
|
&& ReadyContinuityLine.Contains(TEXT("recall scopes 3"))
|
||||||
|
&& ReadyContinuityLine.Contains(TEXT("preference fields 5"))
|
||||||
|
);
|
||||||
|
|
||||||
|
const FString MixedStatusLine =
|
||||||
|
HyperTwistTrainingControlSurfaceFormatting::BuildControlProfileStatusLine(
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
TestTrue(
|
||||||
|
TEXT("The control/profile status formatter must keep partial continuity truth explicit alongside unloaded active-selection and unavailable selector-recall posture."),
|
||||||
|
MixedStatusLine.Contains(TEXT("classic keyboard ready"))
|
||||||
|
&& MixedStatusLine.Contains(TEXT("active selection not loaded"))
|
||||||
|
&& MixedStatusLine.Contains(TEXT("selector recall unavailable"))
|
||||||
|
&& MixedStatusLine.Contains(TEXT("profile continuity partial"))
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
|
||||||
|
FHyperTwistTrainingPanelControlProfileContinuityParityTest,
|
||||||
|
"HyperTwist.Browser.TrainingPanel.ControlProfileContinuityParity",
|
||||||
|
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
|
||||||
|
)
|
||||||
|
|
||||||
|
bool FHyperTwistTrainingPanelControlProfileContinuityParityTest::RunTest(
|
||||||
|
const FString& Parameters
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UHyperTwistTrainingPanelWidget* TrainingPanel = NewObject<UHyperTwistTrainingPanelWidget>();
|
||||||
|
TestNotNull(TEXT("The training panel widget must be constructible."), TrainingPanel);
|
||||||
|
if (TrainingPanel == nullptr)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FHyperTwistTrainingControlProfileRosterInspectSurface Surface =
|
||||||
|
TrainingPanel->GetDisplayedControlProfileRosterInspectSurface();
|
||||||
|
TestTrue(
|
||||||
|
TEXT("The control/profile roster surface must keep bounded camera and immersive continuity explicit in structured form."),
|
||||||
|
Surface.bCameraSettingsContinuityReady
|
||||||
|
&& Surface.CameraSettingsExportArtifactId
|
||||||
|
== TEXT("artifact/camera-export-json")
|
||||||
|
&& Surface.bImmersiveSessionRecallReady
|
||||||
|
&& Surface.ImmersiveSessionRecallBoundaryId
|
||||||
|
== TEXT("immersive-training-session-recall-boundary")
|
||||||
|
&& Surface.ImmersiveSessionRecallScopeCount == 3
|
||||||
|
&& Surface.ImmersiveSessionRecallPreferenceFieldTagCount == 5
|
||||||
|
);
|
||||||
|
TestTrue(
|
||||||
|
TEXT("The control/profile roster surface must keep the bounded continuity ids visible in the rendered detail line."),
|
||||||
|
Surface.PreferencesContinuityLine.Contains(TEXT("artifact/camera-export-json"))
|
||||||
|
&& Surface.PreferencesContinuityLine.Contains(
|
||||||
|
TEXT("immersive-training-session-recall-boundary"))
|
||||||
|
&& Surface.DetailLine.Contains(TEXT("artifact/camera-export-json"))
|
||||||
|
&& Surface.DetailLine.Contains(
|
||||||
|
TEXT("immersive-training-session-recall-boundary"))
|
||||||
|
);
|
||||||
|
|
||||||
|
FHyperTwistTrainingHigherDimensionalRuntimeActivationProfile ActiveActivationProfile;
|
||||||
|
FHyperTwistTrainingHigherDimensionalRuntimeViewContextSurface ActiveViewContextSurface;
|
||||||
|
FHyperTwistTrainingHigherDimensionalRuntimeSessionSurface ActiveSessionSurface;
|
||||||
|
FHyperTwistTrainingHigherDimensionalInteractiveSceneSurface ActiveSceneSurface;
|
||||||
|
const bool bLoadedActiveSelection =
|
||||||
|
UHyperTwistTrainingRuntimeLibrary::TryGetBundledHigherDimensionalRuntimeActivationProfileById(
|
||||||
|
TEXT("magic120cell-cleanroom-runtime-activation"),
|
||||||
|
ActiveActivationProfile
|
||||||
|
) && UHyperTwistTrainingRuntimeLibrary::TryGetBundledHigherDimensionalRuntimeViewContextSurfaceByActivationProfileId(
|
||||||
|
TEXT("magic120cell-cleanroom-runtime-activation"),
|
||||||
|
ActiveViewContextSurface
|
||||||
|
) && UHyperTwistTrainingRuntimeLibrary::TryGetBundledHigherDimensionalRuntimeSessionSurfaceByActivationProfileId(
|
||||||
|
TEXT("magic120cell-cleanroom-runtime-activation"),
|
||||||
|
ActiveSessionSurface
|
||||||
|
) && UHyperTwistTrainingRuntimeLibrary::TryGetBundledHigherDimensionalInteractiveSceneSurfaceByActivationProfileId(
|
||||||
|
TEXT("magic120cell-cleanroom-runtime-activation"),
|
||||||
|
ActiveSceneSurface
|
||||||
|
);
|
||||||
|
TestTrue(
|
||||||
|
TEXT("The control/profile roster active-selection proof must be able to load the bundled dedicated-family activation, session, and scene surfaces."),
|
||||||
|
bLoadedActiveSelection
|
||||||
|
);
|
||||||
|
if (bLoadedActiveSelection)
|
||||||
|
{
|
||||||
|
TrainingPanel->CachedHigherDimensionalRuntimeActivationProfile =
|
||||||
|
ActiveActivationProfile;
|
||||||
|
TrainingPanel->CachedHigherDimensionalRuntimeViewContextSurface =
|
||||||
|
ActiveViewContextSurface;
|
||||||
|
TrainingPanel->CachedHigherDimensionalRuntimeSessionSurface =
|
||||||
|
ActiveSessionSurface;
|
||||||
|
TrainingPanel->CachedHigherDimensionalInteractiveSceneSurface =
|
||||||
|
ActiveSceneSurface;
|
||||||
|
const FHyperTwistTrainingControlProfileRosterInspectSurface ActiveSurface =
|
||||||
|
TrainingPanel->GetDisplayedControlProfileRosterInspectSurface();
|
||||||
|
TestEqual(
|
||||||
|
TEXT("The control/profile roster surface must keep the active higher-dimensional scene surface id in structured form."),
|
||||||
|
ActiveSurface.ActiveHigherDimensionalInteractiveSceneSurfaceId,
|
||||||
|
TEXT("phase6c/magic120cell/interactive-scene-surface")
|
||||||
|
);
|
||||||
|
TestTrue(
|
||||||
|
TEXT("The control/profile roster surface must keep the active higher-dimensional scene surface visible in the rendered detail line."),
|
||||||
|
ActiveSurface.ActiveHigherDimensionalProfileLine.Contains(
|
||||||
|
TEXT("phase6c/magic120cell/interactive-scene-surface"))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
|
||||||
|
FHyperTwistCoachDashboardControlProfileContinuityArtifactsTest,
|
||||||
|
"HyperTwist.Browser.CoachDashboard.ControlProfileContinuityArtifacts",
|
||||||
|
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
|
||||||
|
)
|
||||||
|
|
||||||
|
bool FHyperTwistCoachDashboardControlProfileContinuityArtifactsTest::RunTest(
|
||||||
|
const FString& Parameters
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UHyperTwistCoachDashboardWidget* CoachDashboard = NewObject<UHyperTwistCoachDashboardWidget>();
|
||||||
|
TestNotNull(TEXT("The coach dashboard widget must be constructible."), CoachDashboard);
|
||||||
|
if (CoachDashboard == nullptr)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CoachDashboard->TakeWidget();
|
||||||
|
CoachDashboard->RefreshCoachDashboardView();
|
||||||
|
|
||||||
|
const FHyperTwistTrainingControlProfileRosterInspectSurface Surface =
|
||||||
|
CoachDashboard->GetDisplayedControlProfileRosterInspectSurface();
|
||||||
|
TestTrue(
|
||||||
|
TEXT("The coach dashboard control/profile roster surface must retain the bounded continuity ids in its detail line."),
|
||||||
|
Surface.DetailLine.Contains(TEXT("artifact/camera-export-json"))
|
||||||
|
&& Surface.DetailLine.Contains(
|
||||||
|
TEXT("immersive-training-session-recall-boundary"))
|
||||||
|
);
|
||||||
|
|
||||||
|
UTextBlock* PreferencesContinuityTextBlock =
|
||||||
|
HyperTwistControlProfileContinuityParityTestInternal::FindDashboardTextBlock(
|
||||||
|
CoachDashboard,
|
||||||
|
TEXT("CoachControlProfileRosterPreferencesContinuity")
|
||||||
|
);
|
||||||
|
TestNotNull(
|
||||||
|
TEXT("The coach dashboard must build the structured preferences-continuity roster row."),
|
||||||
|
PreferencesContinuityTextBlock
|
||||||
|
);
|
||||||
|
if (PreferencesContinuityTextBlock != nullptr)
|
||||||
|
{
|
||||||
|
TestEqual(
|
||||||
|
TEXT("The structured preferences-continuity roster row must mirror the inspect surface."),
|
||||||
|
PreferencesContinuityTextBlock->GetText().ToString(),
|
||||||
|
Surface.PreferencesContinuityLine
|
||||||
|
);
|
||||||
|
TestTrue(
|
||||||
|
TEXT("The structured preferences-continuity roster row must expose the shipped camera-export and immersive recall ids."),
|
||||||
|
PreferencesContinuityTextBlock->GetText().ToString().Contains(
|
||||||
|
TEXT("artifact/camera-export-json"))
|
||||||
|
&& PreferencesContinuityTextBlock->GetText().ToString().Contains(
|
||||||
|
TEXT("immersive-training-session-recall-boundary"))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -178,7 +178,7 @@ closeout must now explicitly state one of the following:
|
||||||
|
|
||||||
Required shape example:
|
Required shape example:
|
||||||
|
|
||||||
- recommendation-adoption status: `continue` may adopt `A D / O:B C E F / X`
|
- recommendation-adoption status: `continue` may adopt `A D / O:B C E / HO:F`
|
||||||
|
|
||||||
or
|
or
|
||||||
|
|
||||||
|
|
@ -203,6 +203,14 @@ The governing interpretation is now explicit:
|
||||||
- future instances must not infer adoption from `continue` alone when the
|
- future instances must not infer adoption from `continue` alone when the
|
||||||
closeout does not authorize that adoption
|
closeout does not authorize that adoption
|
||||||
|
|
||||||
|
Compact-string note:
|
||||||
|
|
||||||
|
- `HO:<codes>` is the canonical hard-omit prefix in new closeouts and prepared
|
||||||
|
decision packets
|
||||||
|
- older historical closeouts may still use `X:<codes>` for hard omit; read that older form as
|
||||||
|
legacy shorthand for `HO:<codes>`
|
||||||
|
- `O:<codes>` remains the omit-from-current-lane / reroute-later bucket
|
||||||
|
|
||||||
Expanded closeout-shape repertoire:
|
Expanded closeout-shape repertoire:
|
||||||
|
|
||||||
- recommendation-adoption status: plain `continue` may adopt the displayed
|
- recommendation-adoption status: plain `continue` may adopt the displayed
|
||||||
|
|
|
||||||
|
|
@ -491,3 +491,41 @@ This packet does not claim any of the following:
|
||||||
|
|
||||||
Those are deployment/runtime configuration tasks, not missing ownership of the
|
Those are deployment/runtime configuration tasks, not missing ownership of the
|
||||||
public website lane itself.
|
public website lane itself.
|
||||||
|
|
||||||
|
Latest authoritative launch-summary consumption alignment follow-up on `2026-06-29`:
|
||||||
|
|
||||||
|
- the current same-family continuation tightened one remaining rollout-truth
|
||||||
|
seam inside the browser lane instead of widening product scope again
|
||||||
|
- the shared website launch-status resolver under
|
||||||
|
`website/src/shared/public-launch.ts` now prefers the auth server's
|
||||||
|
authoritative `launch` summary from `GET /api/auth/health` when that summary
|
||||||
|
is present, instead of always reconstructing checklist, blocker, and target
|
||||||
|
posture only from lower-level booleans on the client
|
||||||
|
- that matters because the packet authority had already declared that the auth
|
||||||
|
server-owned `launch` summary exists so public and protected browser surfaces
|
||||||
|
do not have to duplicate launch-blocker evaluation client-side
|
||||||
|
- the public `/launch-status` surface and the protected `/app/launch-status`
|
||||||
|
surface now both keep server-owned blocker labels and checkout-target truth
|
||||||
|
visible directly when the auth server provides them, while still falling back
|
||||||
|
to local derived checklist truth if the richer summary is absent
|
||||||
|
- focused validation for that alignment pass stayed green under:
|
||||||
|
- `npm --prefix website run type-check`
|
||||||
|
- `npm --prefix website test -- --run src/__tests__/public-launch.test.ts src/__tests__/public-marketing-pages.test.tsx src/__tests__/protected-app-pages.test.tsx`
|
||||||
|
- `3` files passed
|
||||||
|
- `29` tests passed
|
||||||
|
- the broader owned website/runtime umbrella then also stayed green:
|
||||||
|
- `scripts/run-hypertwist-web-surface-validation.sh`
|
||||||
|
- focused website route/auth/release validation: `13` files, `79` tests
|
||||||
|
passed
|
||||||
|
- `website/server` suite: `10` files, `36` tests passed
|
||||||
|
- `Content/Browser` shell verification and production build passed
|
||||||
|
- `website/` and `Content/Browser/` production audits stayed at
|
||||||
|
`found 0 vulnerabilities`
|
||||||
|
- `website/server/` again retained only the already-documented upstream
|
||||||
|
`supertokens-node -> nodemailer` residual advisory
|
||||||
|
- current truthful reading after this pass:
|
||||||
|
- the auth server's launch summary is now not only emitted, but actually
|
||||||
|
consumed as the preferred browser authority surface
|
||||||
|
- public and protected launch pages remain conservative because they still
|
||||||
|
derive bounded local checklist truth whenever the richer server summary is
|
||||||
|
unavailable
|
||||||
|
|
|
||||||
|
|
@ -835,3 +835,370 @@ Latest shared-release-bundle follow-up on `2026-06-25`:
|
||||||
- `16,253` nodes, `38,116` edges, `665` clusters, `300` flows
|
- `16,253` nodes, `38,116` edges, `665` clusters, `300` flows
|
||||||
- `scripts/run-hypertwist-gitnexus-status.sh`
|
- `scripts/run-hypertwist-gitnexus-status.sh`
|
||||||
- bounded mirror `Status: up-to-date`
|
- bounded mirror `Status: up-to-date`
|
||||||
|
|
||||||
|
Latest onboarding-manual depth follow-up on `2026-06-28`:
|
||||||
|
|
||||||
|
- the canonical public `/getting-started` route was widened again so it no
|
||||||
|
longer depends on the docs or resources pages alone for the two most
|
||||||
|
simulator-specific public manual seams:
|
||||||
|
- the same first-session route now includes the current
|
||||||
|
higher-dimensional family guide directly, covering the dedicated native
|
||||||
|
`Magic120Cell` and `MagicCube5D` lanes plus the current embedded-browser
|
||||||
|
`MagicTile` host posture
|
||||||
|
- that same route now also includes the public runtime control guide
|
||||||
|
directly, including the shipped classic desktop control posture, the
|
||||||
|
current higher-dimensional desktop-control truth, the native diagnostics
|
||||||
|
check, and the explicit desktop-hosted `No-Go` XR/controller boundary
|
||||||
|
- this keeps the canonical onboarding page closer to a genuine operator manual
|
||||||
|
instead of requiring users to reconstruct the real first-session path from
|
||||||
|
scattered public pages
|
||||||
|
- focused validation for that follow-up stayed green under:
|
||||||
|
- `npm --prefix website test -- --run src/__tests__/public-marketing-pages.test.tsx`
|
||||||
|
- `1` file passed
|
||||||
|
- `15` tests passed
|
||||||
|
- the same packet also rechecked the owned structural and graph-analysis
|
||||||
|
posture so the public-manual widening did not quietly degrade the refactor
|
||||||
|
baseline:
|
||||||
|
- `scripts/run-hypertwist-sentrux-source-only.sh`
|
||||||
|
- `Quality: 6228`
|
||||||
|
- all `7` rules pass
|
||||||
|
- `scripts/run-hypertwist-gitnexus-analyze.sh`
|
||||||
|
- `16,380` nodes, `38,646` edges, `679` clusters, `300` flows
|
||||||
|
- `scripts/run-hypertwist-gitnexus-status.sh`
|
||||||
|
- bounded mirror `Status: up-to-date`
|
||||||
|
|
||||||
|
Latest feature-atlas parity follow-up on `2026-06-28`:
|
||||||
|
|
||||||
|
- the public `/features` route then widened again so the feature atlas no
|
||||||
|
longer stops at capability and roster summaries when the rest of the manual
|
||||||
|
already carries a more practical desktop-usage seam
|
||||||
|
- that same atlas now also includes the shared runtime control guide directly,
|
||||||
|
including:
|
||||||
|
- the shipped classic desktop control posture
|
||||||
|
- the current higher-dimensional desktop-control posture
|
||||||
|
- the native diagnostics check
|
||||||
|
- the explicit desktop-hosted `No-Go` XR/controller boundary
|
||||||
|
- this keeps the public feature atlas closer to the broader operator/distribution
|
||||||
|
manual instead of forcing advanced readers to leave `/features` for docs,
|
||||||
|
resources, or getting-started just to find the practical control and
|
||||||
|
diagnostics truth
|
||||||
|
- focused validation for that atlas-parity follow-up stayed green under:
|
||||||
|
- `npm --prefix website test -- --run src/__tests__/public-marketing-pages.test.tsx`
|
||||||
|
- `1` file passed
|
||||||
|
- `15` tests passed
|
||||||
|
- the broader owned website/runtime/server umbrella then also stayed green
|
||||||
|
again under:
|
||||||
|
- `scripts/run-hypertwist-web-surface-validation.sh`
|
||||||
|
- focused website route/auth/release validation: `12` files, `74` tests
|
||||||
|
passed
|
||||||
|
- `npm --prefix website run build`
|
||||||
|
- `npm --prefix website/server run type-check`
|
||||||
|
- `npm --prefix website/server test -- --run`
|
||||||
|
- `10` website/server files passed, `36` tests passed
|
||||||
|
- `npm --prefix Content/Browser run verify:shell`
|
||||||
|
- `npm --prefix Content/Browser run build`
|
||||||
|
- `website/` and `Content/Browser/` production audits: `found 0
|
||||||
|
vulnerabilities`
|
||||||
|
- `website/server` again retained only the already-documented upstream
|
||||||
|
`supertokens-node -> nodemailer` residual advisory
|
||||||
|
- the owned structural loop stayed green on the same continuation:
|
||||||
|
- `scripts/run-hypertwist-sentrux-source-only.sh`
|
||||||
|
- `Quality: 6228`
|
||||||
|
- all `7` rules pass
|
||||||
|
|
||||||
|
Latest responsive manual-route proof expansion on `2026-06-29`:
|
||||||
|
|
||||||
|
- the next same-family production-hardening packet then widened the existing
|
||||||
|
public responsive Playwright proof so the newer canonical public manual and
|
||||||
|
launch-authority routes are no longer outside the browser-level viewport
|
||||||
|
evidence lane
|
||||||
|
- `website/tests/e2e/responsive-public-pages.spec.ts` now also covers:
|
||||||
|
- `/features`
|
||||||
|
- `/docs`
|
||||||
|
- `/getting-started`
|
||||||
|
- `/launch-status`
|
||||||
|
- that means the responsive public-route proof now covers the practical public
|
||||||
|
operator/distribution surfaces that were widened most heavily in the recent
|
||||||
|
manual packet, rather than only the older marketing and commerce routes
|
||||||
|
- current validation truth for that responsive-proof expansion is green:
|
||||||
|
- `npm --prefix website run test:e2e:responsive`
|
||||||
|
- responsive public-route Playwright proof: `22` tests passed
|
||||||
|
- `scripts/run-hypertwist-web-surface-validation.sh --with-responsive-e2e`
|
||||||
|
- focused website route/auth/release validation: `12` files, `74` tests
|
||||||
|
passed
|
||||||
|
- responsive public-route Playwright proof: `22` tests passed
|
||||||
|
- responsive protected-route Playwright proof: `12` tests passed
|
||||||
|
- `website/server` suite: `10` files, `36` tests passed
|
||||||
|
- `Content/Browser` shell verification and production build passed
|
||||||
|
- `website/` and `Content/Browser/` production audits stayed at
|
||||||
|
`found 0 vulnerabilities`
|
||||||
|
- `website/server/` again retained only the already-documented upstream
|
||||||
|
`supertokens-node -> nodemailer` residual advisory
|
||||||
|
|
||||||
|
Latest commerce/download manual deepening follow-up on `2026-06-29`:
|
||||||
|
|
||||||
|
- the public pricing and download routes were widened again so the commercial
|
||||||
|
and release-access lanes no longer stop too early at entitlement, package
|
||||||
|
choice, and browser-to-desktop handoff
|
||||||
|
- `/pricing` now also carries:
|
||||||
|
- the practical simulator-use manual for the installed software
|
||||||
|
- the higher-dimensional family guide covering `Magic120Cell`,
|
||||||
|
`MagicCube5D`, and the current embedded-browser `MagicTile` posture
|
||||||
|
- the current input/device plus runtime-control truth, including the
|
||||||
|
explicit desktop-hosted `No-Go` XR/controller boundary
|
||||||
|
- `/download` now also carries:
|
||||||
|
- the practical installed-runtime manual
|
||||||
|
- the higher-dimensional family guide directly on the package route
|
||||||
|
- the same current input/device plus runtime-control truth before first
|
||||||
|
launch
|
||||||
|
- this keeps the public commerce and package lanes professional and
|
||||||
|
self-sufficient instead of forcing operators to jump into docs/resources
|
||||||
|
before they can understand what the entitled desktop software actually does
|
||||||
|
- current validation truth for that manual-deepening continuation is green:
|
||||||
|
- `npm --prefix website test -- --run src/__tests__/public-marketing-pages.test.tsx`
|
||||||
|
- `1` file passed
|
||||||
|
- `15` tests passed
|
||||||
|
- `npm --prefix website run build`
|
||||||
|
- production website build passed
|
||||||
|
- `scripts/run-hypertwist-web-surface-validation.sh`
|
||||||
|
- focused website route/auth/release validation: `12` files, `74` tests
|
||||||
|
passed
|
||||||
|
- `website/server` suite: `10` files, `36` tests passed
|
||||||
|
- `Content/Browser` shell verification and production build passed
|
||||||
|
- `website/` and `Content/Browser/` production audits stayed at
|
||||||
|
`found 0 vulnerabilities`
|
||||||
|
- `website/server/` again retained only the already-documented upstream
|
||||||
|
`supertokens-node -> nodemailer` residual advisory
|
||||||
|
|
||||||
|
Latest shared public-manual refactor follow-up on `2026-06-29`:
|
||||||
|
|
||||||
|
- the same-family continuation then tightened the public-manual ownership
|
||||||
|
layer itself so the widened page set stays easier to evolve without silent
|
||||||
|
copy drift
|
||||||
|
- shared first-party public-manual card sections now live in:
|
||||||
|
- `website/src/pages/public-page-helpers.tsx`
|
||||||
|
- `PrincipleCardSection`
|
||||||
|
- `BulletCardSection`
|
||||||
|
- `StepCardSection`
|
||||||
|
- `FaqCardSection`
|
||||||
|
- the current public/manual consumers now route through those shared helpers
|
||||||
|
instead of each page re-implementing the same card-grid structure:
|
||||||
|
- `website/src/pages/public-pages-marketing.tsx`
|
||||||
|
- `website/src/pages/public-pages-features.tsx`
|
||||||
|
- `website/src/pages/public-pages-commerce.tsx`
|
||||||
|
- this does not widen product scope or alter the browser-versus-desktop truth;
|
||||||
|
it keeps the existing operator-manual packet more coherent and less likely to
|
||||||
|
diverge across the public route family
|
||||||
|
- current validation truth for that shared-ownership follow-up is green:
|
||||||
|
- `npm --prefix website run type-check`
|
||||||
|
- `npm --prefix website test -- --run src/__tests__/public-marketing-pages.test.tsx`
|
||||||
|
- `1` file passed
|
||||||
|
- `15` tests passed
|
||||||
|
- `npm --prefix website run build`
|
||||||
|
- production website build passed
|
||||||
|
|
||||||
|
Latest responsive-proof revalidation after the shared-manual continuation on `2026-06-29`:
|
||||||
|
|
||||||
|
- the current same-family continuation then re-proved the widened public and
|
||||||
|
protected browser lanes at real browser viewport sizes after the newer
|
||||||
|
shared-section and commerce/manual deepening work
|
||||||
|
- this did not widen product claims; it re-validated that the now-richer page
|
||||||
|
set still behaves like a production operator/distribution surface on mobile
|
||||||
|
and tablet breakpoints
|
||||||
|
- the owned responsive route proof stayed green under:
|
||||||
|
- `scripts/run-hypertwist-web-surface-validation.sh --with-responsive-e2e`
|
||||||
|
- focused website route/auth/release validation: `12` files, `74` tests
|
||||||
|
passed
|
||||||
|
- responsive public-route Playwright proof: `22` tests passed
|
||||||
|
- responsive protected-route Playwright proof: `12` tests passed
|
||||||
|
- `website/server` suite: `10` files, `36` tests passed
|
||||||
|
- `Content/Browser` shell verification and production build passed
|
||||||
|
- `website/` and `Content/Browser/` production audits stayed at
|
||||||
|
`found 0 vulnerabilities`
|
||||||
|
- `website/server/` again retained only the already-documented upstream
|
||||||
|
`supertokens-node -> nodemailer` residual advisory
|
||||||
|
- the responsive public-route proof still covers the heavier manual and
|
||||||
|
authority routes that matter most to this packet:
|
||||||
|
- `/features`
|
||||||
|
- `/docs`
|
||||||
|
- `/getting-started`
|
||||||
|
- `/launch-status`
|
||||||
|
- plus the already-covered homepage, about, resources, pricing, download,
|
||||||
|
support, and register routes
|
||||||
|
- the responsive protected-route proof also stayed current for:
|
||||||
|
- `/app`
|
||||||
|
- `/app/launch-status`
|
||||||
|
- `/app/downloads`
|
||||||
|
- `/app/browser-access`
|
||||||
|
- `/app/account`
|
||||||
|
- `/app/notices`
|
||||||
|
- current truthful reading after this revalidation:
|
||||||
|
- the public/manual website lane remains intentional and professional rather
|
||||||
|
than brochure-only
|
||||||
|
- the richer manual/commerce copy introduced by the recent continuations did
|
||||||
|
not regress the owned browser delivery surfaces
|
||||||
|
|
||||||
|
Latest launch-authority alignment follow-up on `2026-06-29`:
|
||||||
|
|
||||||
|
- the next same-family continuation then closed a remaining authority-gap seam
|
||||||
|
between the documented auth-server launch summary and the browser surfaces
|
||||||
|
that read it
|
||||||
|
- `website/src/shared/public-launch.ts` now prefers the richer server-provided
|
||||||
|
`launch` summary from `GET /api/auth/health` when available, including its
|
||||||
|
explicit blocker labels, checklist truth, and operator/studio checkout
|
||||||
|
targets, instead of always reconstructing launch posture only from lower
|
||||||
|
rollout booleans on the client
|
||||||
|
- that keeps the public `/launch-status` route and the protected
|
||||||
|
`/app/launch-status` route better aligned with the intended server-owned
|
||||||
|
rollout authority while still preserving bounded local derivation as a safe
|
||||||
|
fallback if the richer summary is absent
|
||||||
|
- current validation truth for that authority-alignment continuation is green:
|
||||||
|
- `npm --prefix website run type-check`
|
||||||
|
- `npm --prefix website test -- --run src/__tests__/public-launch.test.ts src/__tests__/public-marketing-pages.test.tsx src/__tests__/protected-app-pages.test.tsx`
|
||||||
|
- `3` files passed
|
||||||
|
- `29` tests passed
|
||||||
|
- `scripts/run-hypertwist-web-surface-validation.sh`
|
||||||
|
- focused website route/auth/release validation: `13` files, `79` tests
|
||||||
|
passed
|
||||||
|
- `website/server` suite: `10` files, `36` tests passed
|
||||||
|
- `Content/Browser` shell verification and production build passed
|
||||||
|
- `website/` and `Content/Browser/` production audits stayed at
|
||||||
|
`found 0 vulnerabilities`
|
||||||
|
- `website/server/` again retained only the already-documented upstream
|
||||||
|
`supertokens-node -> nodemailer` residual advisory
|
||||||
|
|
||||||
|
Latest shared public-manual section consolidation later on `2026-06-29`:
|
||||||
|
|
||||||
|
- the next same-family continuation stayed inside the owned public-manual lane
|
||||||
|
and reduced drift risk by moving more repeated section rendering into shared
|
||||||
|
helper ownership
|
||||||
|
- `website/src/pages/public-page-helpers.tsx` now also owns reusable public
|
||||||
|
sections for:
|
||||||
|
- simulator manual
|
||||||
|
- higher-dimensional runtime guide
|
||||||
|
- input and device posture
|
||||||
|
- control-profile roster
|
||||||
|
- runtime control guide
|
||||||
|
- the current page consumers now route those shared sections through:
|
||||||
|
- `website/src/pages/public-pages-marketing.tsx`
|
||||||
|
- `website/src/pages/public-pages-commerce.tsx`
|
||||||
|
- this does not widen product claims; it keeps the public docs/about/resources/
|
||||||
|
pricing/download/getting-started family aligned as one professional operator
|
||||||
|
manual instead of a set of near-copy pages that can drift separately
|
||||||
|
- validation stayed green on the same consolidation pass:
|
||||||
|
- `npm --prefix website run type-check`
|
||||||
|
- `scripts/run-hypertwist-web-surface-validation.sh`
|
||||||
|
- focused website route/auth/release validation: `13` files, `79` tests
|
||||||
|
passed
|
||||||
|
- `website/server` suite: `10` files, `36` tests passed
|
||||||
|
- `Content/Browser` shell verification and production build passed
|
||||||
|
- `website/` and `Content/Browser/` production audits stayed at
|
||||||
|
`found 0 vulnerabilities`
|
||||||
|
- `website/server/` again retained only the already-documented upstream
|
||||||
|
`supertokens-node -> nodemailer` residual advisory
|
||||||
|
|
||||||
|
Latest protected responsive recovery follow-up later on `2026-06-29`:
|
||||||
|
|
||||||
|
- the next same-family website quality pass fixed a real protected-route mobile
|
||||||
|
regression instead of widening scope again
|
||||||
|
- the affected route was the signed-in `/app/launch-status` surface, where the
|
||||||
|
stacked action rows could widen the viewport by a couple of pixels on narrow
|
||||||
|
mobile widths because the button links still sized themselves to long labels
|
||||||
|
- `website/src/styles/global.css` now hardens the owned small-screen button-row
|
||||||
|
posture so stacked protected actions fill the available column width and
|
||||||
|
allow wrapped labels
|
||||||
|
- this correction stayed entirely inside the existing protected operator shell
|
||||||
|
and did not alter the browser-versus-desktop truth or release-lane claims
|
||||||
|
- the full owned browser validation lane then re-ran green under:
|
||||||
|
- `scripts/run-hypertwist-web-surface-validation.sh --with-responsive-e2e`
|
||||||
|
- focused website route/auth/release validation: `13` files, `79` tests
|
||||||
|
passed
|
||||||
|
- responsive public-route Playwright proof: `22` tests passed
|
||||||
|
- responsive protected-route Playwright proof: `12` tests passed
|
||||||
|
- `website/server` suite: `10` files, `36` tests passed
|
||||||
|
- `Content/Browser` shell verification and production build passed
|
||||||
|
- `website/` and `Content/Browser/` production audits stayed at
|
||||||
|
`found 0 vulnerabilities`
|
||||||
|
- `website/server/` again retained only the already-documented upstream
|
||||||
|
`supertokens-node -> nodemailer` residual advisory
|
||||||
|
- current truthful reading after this follow-up:
|
||||||
|
- the richer public/protected manual lane is not only source-accurate, but
|
||||||
|
also still behaves like a deliberate operator/distribution surface at real
|
||||||
|
mobile and tablet breakpoints after the latest content widening
|
||||||
|
|
||||||
|
Latest feature-atlas shared-section completion plus public legal-route responsive expansion later on `2026-06-29`:
|
||||||
|
|
||||||
|
- the next same-family continuation stayed inside the owned public/manual lane
|
||||||
|
and closed a remaining drift-risk gap instead of widening product scope
|
||||||
|
- the public feature-atlas route now also routes its repeated manual sections
|
||||||
|
through the same shared helper ownership already used by the broader
|
||||||
|
marketing and commerce families:
|
||||||
|
- `HigherDimensionalRuntimeGuideSection`
|
||||||
|
- `InputAndDevicePostureSection`
|
||||||
|
- `ControlProfileRosterSection`
|
||||||
|
- `RuntimeControlGuideSection`
|
||||||
|
- that means the higher-dimensional runtime guide, current input/device truth,
|
||||||
|
selectable roster, and practical runtime-control guidance now share one
|
||||||
|
first-party rendering path across the main public route family instead of
|
||||||
|
leaving `/features` on a separate near-copy structure
|
||||||
|
- the same continuation then widened browser-level responsive proof across the
|
||||||
|
remaining public legal/reference routes that were already content-complete
|
||||||
|
but not yet inside the explicit mobile/tablet viewport lane:
|
||||||
|
- `/changelog`
|
||||||
|
- `/open-source-notices`
|
||||||
|
- `/privacy`
|
||||||
|
- `/terms`
|
||||||
|
- `/shipping-payment`
|
||||||
|
- a later adjacent auth-entry parity continuation then also added `/login` to
|
||||||
|
that same owned responsive public-route matrix so the real browser-entry
|
||||||
|
surface sits under the same mobile/tablet proof lane as `/register`
|
||||||
|
- the owned responsive public-route proof therefore now covers the broader
|
||||||
|
public operator/distribution family rather than only the marketing,
|
||||||
|
onboarding, support, and core commerce subset
|
||||||
|
- current validation truth for that continuation is green:
|
||||||
|
- `scripts/run-hypertwist-web-surface-validation.sh --with-responsive-e2e`
|
||||||
|
- focused website route/auth/release validation: `13` files, `79` tests
|
||||||
|
passed
|
||||||
|
- responsive public-route Playwright proof: `34` tests passed
|
||||||
|
- responsive protected-route Playwright proof: `12` tests passed
|
||||||
|
- `website/server` suite: `10` files, `36` tests passed
|
||||||
|
- `Content/Browser` shell verification and production build passed
|
||||||
|
- `website/` and `Content/Browser/` production audits stayed at
|
||||||
|
`found 0 vulnerabilities`
|
||||||
|
- `website/server/` again retained only the already-documented upstream
|
||||||
|
`supertokens-node -> nodemailer` residual advisory
|
||||||
|
- current truthful reading after this continuation:
|
||||||
|
- the feature atlas now sits on the same shared public-manual ownership path
|
||||||
|
as the surrounding major public routes
|
||||||
|
- the broader public legal/reference family now has real browser-level
|
||||||
|
mobile and tablet overflow proof instead of relying only on route tests and
|
||||||
|
source-level review
|
||||||
|
|
||||||
|
Latest feature-atlas capability-FAQ continuity follow-up on `2026-06-29`:
|
||||||
|
|
||||||
|
- the next same-family continuation stayed inside the owned public/manual lane
|
||||||
|
and widened the public `/features` route from a capability matrix plus
|
||||||
|
runtime-guide surface into a cleaner question-answering route as well
|
||||||
|
- the feature atlas now also renders a dedicated `Common capability questions`
|
||||||
|
section backed by the same shared FAQ authority already used on the broader
|
||||||
|
docs/support family
|
||||||
|
- those answers now keep the exact product-boundary questions visible directly
|
||||||
|
on the capability route, including:
|
||||||
|
- why the browser surface is intentionally narrower than the desktop runtime
|
||||||
|
- why HyperTwist still keeps the web product surface even though the
|
||||||
|
simulator is desktop-first
|
||||||
|
- why XR/controller completion is not yet marketed as finished
|
||||||
|
- how current control, settings, and bounded higher-dimensional continuity
|
||||||
|
should be read honestly
|
||||||
|
- the FAQ wording itself was also tightened so the public manual now states the
|
||||||
|
key inferiority points explicitly instead of leaving them implicit:
|
||||||
|
- the browser surface does not own package-validated training behavior,
|
||||||
|
low-latency native input, higher-dimensional packaged execution, or
|
||||||
|
device/runtime integration authority
|
||||||
|
- the current desktop runtime does own real keyboard or mouse or touch plus
|
||||||
|
settings and higher-dimensional selector posture, but it still does not
|
||||||
|
claim finished packaged XR/controller proof or polished rebinding
|
||||||
|
- focused validation for that continuation stayed green under:
|
||||||
|
- `npm --prefix website test -- --run src/__tests__/public-marketing-pages.test.tsx`
|
||||||
|
- `1` file passed
|
||||||
|
- `16` tests passed
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ VectorShell.
|
||||||
- `.sentrux/rules.toml`
|
- `.sentrux/rules.toml`
|
||||||
- `scripts/bootstrap-hypertwist-sentrux.sh`
|
- `scripts/bootstrap-hypertwist-sentrux.sh`
|
||||||
- `scripts/run-hypertwist-sentrux-source-only.sh`
|
- `scripts/run-hypertwist-sentrux-source-only.sh`
|
||||||
|
- `scripts/run-hypertwist-sentrux-gate.sh`
|
||||||
- `scripts/run-hypertwist-gitnexus-analyze.sh`
|
- `scripts/run-hypertwist-gitnexus-analyze.sh`
|
||||||
- `scripts/run-hypertwist-gitnexus-status.sh`
|
- `scripts/run-hypertwist-gitnexus-status.sh`
|
||||||
|
|
||||||
|
|
@ -53,6 +54,24 @@ Run:
|
||||||
scripts/run-hypertwist-sentrux-source-only.sh
|
scripts/run-hypertwist-sentrux-source-only.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
For the owned regression-gate loop, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
scripts/run-hypertwist-sentrux-gate.sh --save
|
||||||
|
scripts/run-hypertwist-sentrux-gate.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
The gate wrapper uses the same bounded source-only mirror, but it now persists
|
||||||
|
its baseline at:
|
||||||
|
|
||||||
|
- `.sentrux/source-only-baseline.json`
|
||||||
|
|
||||||
|
That matters because upstream `sentrux gate --save` writes
|
||||||
|
`.sentrux/baseline.json` inside the scanned root. HyperTwist therefore copies
|
||||||
|
the repo-owned source-only baseline into and out of the disposable mirror so
|
||||||
|
the gate remains usable across hygiene-cleaned temp roots instead of forgetting
|
||||||
|
its own saved state on every run.
|
||||||
|
|
||||||
Resolution order for the analyzer binary is now HyperTwist-owned first:
|
Resolution order for the analyzer binary is now HyperTwist-owned first:
|
||||||
|
|
||||||
- `HYPERTWIST_SENTRUX_BINARY` if explicitly provided
|
- `HYPERTWIST_SENTRUX_BINARY` if explicitly provided
|
||||||
|
|
@ -114,12 +133,21 @@ Behavior:
|
||||||
available or is not runnable
|
available or is not runnable
|
||||||
- always uses `--skip-agents-md` so HyperTwist authority files are not
|
- always uses `--skip-agents-md` so HyperTwist authority files are not
|
||||||
rewritten just to refresh analysis state
|
rewritten just to refresh analysis state
|
||||||
|
- `scripts/run-hypertwist-gitnexus-status.sh` is now hygiene-aware by default:
|
||||||
|
- if the disposable `.gitnexus-source-only-root/` mirror has already been
|
||||||
|
deleted during a correct cleanup pass, the wrapper reports that as an
|
||||||
|
informational state instead of pretending the repo is corrupted
|
||||||
|
- if the mirror exists but `.gitnexus/meta.json` is missing, the wrapper now
|
||||||
|
reports that as an interrupted or rebuilding index state by default
|
||||||
|
- `HYPERTWIST_GITNEXUS_STATUS_REQUIRE_INDEX=1` restores strict non-zero
|
||||||
|
failure when a caller truly needs status to fail on those absent/incomplete
|
||||||
|
disposable-root cases
|
||||||
|
|
||||||
## Working-reference note
|
## Working-reference note
|
||||||
|
|
||||||
The retained HyperTwist `mirrors/GitNexus` working reference already contains
|
The retained HyperTwist `mirrors/GitNexus` working reference already contains
|
||||||
the newer stack-overflow and cycle-hardening work recorded in its
|
the newer stack-overflow and cycle-hardening work visible in its retained
|
||||||
`CHANGELOG.md`, including:
|
source tree and tests, including:
|
||||||
|
|
||||||
- iterative stdio newline handling to prevent stack overflow on empty-line
|
- iterative stdio newline handling to prevent stack overflow on empty-line
|
||||||
bursts
|
bursts
|
||||||
|
|
@ -132,11 +160,15 @@ It is not a signal to absorb GitNexus runtime code into the shipped product.
|
||||||
|
|
||||||
1. run `scripts/run-hypertwist-gitnexus-analyze.sh`
|
1. run `scripts/run-hypertwist-gitnexus-analyze.sh`
|
||||||
2. review impact/freshness through `scripts/run-hypertwist-gitnexus-status.sh`
|
2. review impact/freshness through `scripts/run-hypertwist-gitnexus-status.sh`
|
||||||
3. run `scripts/run-hypertwist-sentrux-source-only.sh` for a structural
|
3. run `scripts/run-hypertwist-sentrux-gate.sh --save` when you need to stamp
|
||||||
baseline
|
a fresh bounded baseline for the current refactor lane
|
||||||
4. make the bounded packet
|
4. run `scripts/run-hypertwist-sentrux-source-only.sh` for the immediate
|
||||||
5. rerun `scripts/run-hypertwist-sentrux-source-only.sh`
|
structural snapshot
|
||||||
6. rerun product tests for the affected lane
|
5. make the bounded packet
|
||||||
|
6. rerun `scripts/run-hypertwist-sentrux-source-only.sh`
|
||||||
|
7. rerun `scripts/run-hypertwist-sentrux-gate.sh` to compare against the saved
|
||||||
|
bounded baseline
|
||||||
|
8. rerun product tests for the affected lane
|
||||||
|
|
||||||
## Current findings snapshot
|
## Current findings snapshot
|
||||||
|
|
||||||
|
|
@ -1014,3 +1046,371 @@ This note does not:
|
||||||
- make `GitNexus` a product runtime dependency
|
- make `GitNexus` a product runtime dependency
|
||||||
- claim `sentrux` replaces product validation
|
- claim `sentrux` replaces product validation
|
||||||
- widen HyperTwist into a generic code-intelligence product
|
- widen HyperTwist into a generic code-intelligence product
|
||||||
|
|
||||||
|
Latest refresh on `2026-06-28`:
|
||||||
|
|
||||||
|
- the current same-family public-manual continuation rechecked the owned
|
||||||
|
structural loop instead of treating the earlier website/runtime results as
|
||||||
|
permanently sufficient:
|
||||||
|
- `scripts/run-hypertwist-sentrux-source-only.sh`
|
||||||
|
- `Quality: 6228`
|
||||||
|
- all `7` rules pass
|
||||||
|
- the HyperTwist-owned graph refresh also completed again on the bounded
|
||||||
|
source-only mirror:
|
||||||
|
- `scripts/run-hypertwist-gitnexus-analyze.sh`
|
||||||
|
- the retained local CLI again failed cleanly on this Linux host because of
|
||||||
|
the cross-platform `LadybugDB` native payload mismatch, so the wrapper
|
||||||
|
truthfully fell back to `npx -y gitnexus@latest`
|
||||||
|
- fallback analyze run completed successfully in `84.5s`
|
||||||
|
- bounded mirror result:
|
||||||
|
- `16,380` nodes
|
||||||
|
- `38,646` edges
|
||||||
|
- `679` clusters
|
||||||
|
- `300` flows
|
||||||
|
- `scripts/run-hypertwist-gitnexus-status.sh` then reported:
|
||||||
|
- `Indexed commit: a4a50b8`
|
||||||
|
- `Current commit: a4a50b8`
|
||||||
|
- `Status: up-to-date`
|
||||||
|
- current truthful reading after this refresh:
|
||||||
|
- the broad vanilla-refactor lane is no longer blocked by tool adoption,
|
||||||
|
broken wrappers, or an active failing structural gate
|
||||||
|
- HyperTwist now has a stable owned analyzer loop for day-to-day bounded
|
||||||
|
refactor review even though the retained local GitNexus native payload is
|
||||||
|
still not runnable on this Linux host
|
||||||
|
- the next worthwhile refactor work is selective readability or ownership
|
||||||
|
cleanup driven by product/runtime value, not emergency analyzer setup debt
|
||||||
|
|
||||||
|
Latest refresh on `2026-06-29`:
|
||||||
|
|
||||||
|
- the current public commerce/download manual deepening slice rechecked the
|
||||||
|
owned analyzer loop instead of assuming the previous refresh was still
|
||||||
|
sufficient after another website/manual continuation
|
||||||
|
- the owned structural gate stayed green:
|
||||||
|
- `scripts/run-hypertwist-sentrux-source-only.sh`
|
||||||
|
- `Quality: 6228`
|
||||||
|
- all `7` rules pass
|
||||||
|
- the HyperTwist-owned graph refresh again completed on the bounded
|
||||||
|
source-only mirror:
|
||||||
|
- `scripts/run-hypertwist-gitnexus-analyze.sh`
|
||||||
|
- the retained local CLI again failed cleanly on this Linux host because of
|
||||||
|
the cross-platform `LadybugDB` native payload mismatch, so the wrapper
|
||||||
|
truthfully fell back to `npx -y gitnexus@latest`
|
||||||
|
- fallback analyze run completed successfully in `87.8s`
|
||||||
|
- bounded mirror result:
|
||||||
|
- `16,380` nodes
|
||||||
|
- `38,646` edges
|
||||||
|
- `679` clusters
|
||||||
|
- `300` flows
|
||||||
|
- `scripts/run-hypertwist-gitnexus-status.sh` then reported:
|
||||||
|
- `Indexed commit: bbcd877`
|
||||||
|
- `Current commit: bbcd877`
|
||||||
|
- `Status: up-to-date`
|
||||||
|
- the same continuation also stayed green under product-surface validation:
|
||||||
|
- `npm --prefix website test -- --run src/__tests__/public-marketing-pages.test.tsx`
|
||||||
|
- `1` file passed
|
||||||
|
- `15` tests passed
|
||||||
|
- `npm --prefix website run build`
|
||||||
|
- production website build passed
|
||||||
|
- `scripts/run-hypertwist-web-surface-validation.sh`
|
||||||
|
- focused website route/auth/release validation: `12` files, `74` tests
|
||||||
|
passed
|
||||||
|
- `website/server` suite: `10` files, `36` tests passed
|
||||||
|
- `Content/Browser` shell verification and production build passed
|
||||||
|
- `website/` and `Content/Browser/` production audits stayed at
|
||||||
|
`found 0 vulnerabilities`
|
||||||
|
- `website/server/` again retained only the already-documented upstream
|
||||||
|
`supertokens-node -> nodemailer` residual advisory
|
||||||
|
- current truthful reading after this refresh:
|
||||||
|
- the broad vanilla-refactor lane is complete as a tooling-adoption task
|
||||||
|
- the current remaining high-value refactor work is product-driven cleanup,
|
||||||
|
not missing `sentrux` or GitNexus ownership inside HyperTwist
|
||||||
|
|
||||||
|
Latest shared-section refactor follow-up on `2026-06-29`:
|
||||||
|
|
||||||
|
- the current public-manual continuation then spent that already-proven owned
|
||||||
|
refactor headroom on a bounded maintainability pass instead of widening
|
||||||
|
product claims again
|
||||||
|
- shared card-section ownership for the public website now lives in:
|
||||||
|
- `website/src/pages/public-page-helpers.tsx`
|
||||||
|
- `PrincipleCardSection`
|
||||||
|
- `BulletCardSection`
|
||||||
|
- `StepCardSection`
|
||||||
|
- `FaqCardSection`
|
||||||
|
- the current public manual consumers now route through those shared helpers
|
||||||
|
instead of each page hand-rolling the same grid logic:
|
||||||
|
- `website/src/pages/public-pages-marketing.tsx`
|
||||||
|
- `website/src/pages/public-pages-features.tsx`
|
||||||
|
- `website/src/pages/public-pages-commerce.tsx`
|
||||||
|
- that keeps the browser-versus-desktop product truth, runtime-boundary copy,
|
||||||
|
and operator-manual structure less drift-prone across future public-page
|
||||||
|
continuations
|
||||||
|
- the owned structural loop stayed green after that refactor packet:
|
||||||
|
- `scripts/run-hypertwist-sentrux-source-only.sh`
|
||||||
|
- `Quality: 6228`
|
||||||
|
- all `7` rules pass
|
||||||
|
- the HyperTwist-owned graph refresh also stayed healthy:
|
||||||
|
- `scripts/run-hypertwist-gitnexus-analyze.sh`
|
||||||
|
- the retained local CLI again failed cleanly on this Linux host because of
|
||||||
|
the cross-platform `LadybugDB` native payload mismatch, so the wrapper
|
||||||
|
truthfully fell back to `npx -y gitnexus@latest`
|
||||||
|
- bounded mirror result:
|
||||||
|
- `16,387` nodes
|
||||||
|
- `38,682` edges
|
||||||
|
- `676` clusters
|
||||||
|
- `300` flows
|
||||||
|
- `scripts/run-hypertwist-gitnexus-status.sh` then reported:
|
||||||
|
- `Indexed commit: 1deca95`
|
||||||
|
- `Current commit: 1deca95`
|
||||||
|
- `Status: up-to-date`
|
||||||
|
- the same refactor packet also stayed green under product-surface validation:
|
||||||
|
- `npm --prefix website run type-check`
|
||||||
|
- `npm --prefix website test -- --run src/__tests__/public-marketing-pages.test.tsx`
|
||||||
|
- `1` file passed
|
||||||
|
- `15` tests passed
|
||||||
|
- `npm --prefix website run build`
|
||||||
|
- current truthful reading after this follow-up:
|
||||||
|
- the broad refactor/tooling lane remains healthy and HyperTwist-owned
|
||||||
|
- the next worthwhile refactors should continue to be selected for real
|
||||||
|
product-surface clarity or native/runtime ownership value, not for missing
|
||||||
|
analyzer setup or duplicate manual-section scaffolding
|
||||||
|
|
||||||
|
Latest GitNexus status-wrapper hardening plus responsive-proof refresh on `2026-06-29`:
|
||||||
|
|
||||||
|
- the current same-family tooling follow-up tightened operator-facing
|
||||||
|
GitNexus status truth instead of widening product scope again
|
||||||
|
- `scripts/run-hypertwist-gitnexus-status.sh` now explicitly distinguishes:
|
||||||
|
- no bounded analysis root exists yet
|
||||||
|
- bounded source-only mirror exists but no completed `.gitnexus/meta.json`
|
||||||
|
index metadata is present yet
|
||||||
|
- that means a status check during an in-progress bounded-mirror refresh now
|
||||||
|
reports that the index is not ready yet, rather than looking corrupted or
|
||||||
|
failing opaquely
|
||||||
|
- the new pre-index message was exercised directly by temporarily withholding
|
||||||
|
the disposable `.gitnexus/meta.json` file and rerunning the wrapper:
|
||||||
|
- reported:
|
||||||
|
`HyperTwist GitNexus source-only analysis root exists, but no completed index metadata is available yet.`
|
||||||
|
- follow-up guidance:
|
||||||
|
`If scripts/run-hypertwist-gitnexus-analyze.sh is currently refreshing the bounded mirror, wait for it to finish and rerun status.`
|
||||||
|
- the owned structural and graph loop remained healthy on the same pass:
|
||||||
|
- `scripts/run-hypertwist-sentrux-source-only.sh`
|
||||||
|
- `Quality: 6228`
|
||||||
|
- all `7` rules pass
|
||||||
|
- `scripts/run-hypertwist-gitnexus-analyze.sh`
|
||||||
|
- retained local CLI again fell back cleanly to `npx -y gitnexus@latest`
|
||||||
|
on this Linux host because of the cross-platform `LadybugDB` native payload
|
||||||
|
mismatch
|
||||||
|
- bounded mirror result:
|
||||||
|
- `16,387` nodes
|
||||||
|
- `38,686` edges
|
||||||
|
- `676` clusters
|
||||||
|
- `300` flows
|
||||||
|
- `scripts/run-hypertwist-gitnexus-status.sh`
|
||||||
|
- `Indexed commit: a41d7ef`
|
||||||
|
- `Current commit: a41d7ef`
|
||||||
|
- `Status: up-to-date`
|
||||||
|
- the adjacent owned web/runtime validation umbrella also stayed green on the
|
||||||
|
same refresh:
|
||||||
|
- `scripts/run-hypertwist-web-surface-validation.sh --with-responsive-e2e`
|
||||||
|
- focused website route/auth/release validation: `12` files, `74` tests
|
||||||
|
passed
|
||||||
|
- responsive public-route Playwright proof: `22` tests passed
|
||||||
|
- responsive protected-route Playwright proof: `12` tests passed
|
||||||
|
- `website/server` suite: `10` files, `36` tests passed
|
||||||
|
- `Content/Browser` shell verification and production build passed
|
||||||
|
- `website/` and `Content/Browser/` production audits stayed at
|
||||||
|
`found 0 vulnerabilities`
|
||||||
|
- `website/server/` again retained only the already-documented upstream
|
||||||
|
`supertokens-node -> nodemailer` residual advisory
|
||||||
|
- current truthful reading after this hardening pass:
|
||||||
|
- the HyperTwist-owned refactor/tooling lane is not merely present, but now
|
||||||
|
gives clearer operator feedback during bounded mirror refresh windows
|
||||||
|
- the remaining worthwhile work continues to be product or runtime-driven
|
||||||
|
refinement, not missing analyzer ownership or opaque wrapper behavior
|
||||||
|
|
||||||
|
Latest shared-manual helper consolidation follow-up later on `2026-06-29`:
|
||||||
|
|
||||||
|
- the next same-family quality pass stayed inside the owned public-website
|
||||||
|
manual lane and removed more repeated section rendering without widening
|
||||||
|
product scope
|
||||||
|
- `website/src/pages/public-page-helpers.tsx` now also owns the reusable
|
||||||
|
simulator-manual, higher-dimensional-runtime, input/device-posture,
|
||||||
|
control-profile-roster, and runtime-control-guide public-manual sections
|
||||||
|
- the current public/manual consumers now read those shared sections through:
|
||||||
|
- `website/src/pages/public-pages-marketing.tsx`
|
||||||
|
- `website/src/pages/public-pages-commerce.tsx`
|
||||||
|
- the owned tool and validation loop stayed green on the same pass:
|
||||||
|
- `scripts/run-hypertwist-sentrux-source-only.sh`
|
||||||
|
- `Quality: 6227`
|
||||||
|
- all `7` rules pass
|
||||||
|
- `scripts/run-hypertwist-gitnexus-analyze.sh`
|
||||||
|
- retained local CLI again fell back cleanly to `npx -y gitnexus@latest`
|
||||||
|
on this Linux host because of the cross-platform `LadybugDB` native payload
|
||||||
|
mismatch
|
||||||
|
- bounded mirror result:
|
||||||
|
- `16,389` nodes
|
||||||
|
- `38,702` edges
|
||||||
|
- `674` clusters
|
||||||
|
- `300` flows
|
||||||
|
- `scripts/run-hypertwist-gitnexus-status.sh`
|
||||||
|
- `Indexed commit: f1f5cce`
|
||||||
|
- `Current commit: f1f5cce`
|
||||||
|
- `Status: up-to-date`
|
||||||
|
- `scripts/run-hypertwist-web-surface-validation.sh`
|
||||||
|
- focused website route/auth/release validation: `13` files, `79` tests
|
||||||
|
passed
|
||||||
|
- `website/server` suite: `10` files, `36` tests passed
|
||||||
|
- `Content/Browser` shell verification and production build passed
|
||||||
|
- `website/` and `Content/Browser/` production audits stayed at
|
||||||
|
`found 0 vulnerabilities`
|
||||||
|
- `website/server/` again retained only the already-documented upstream
|
||||||
|
`supertokens-node -> nodemailer` residual advisory
|
||||||
|
- current truthful reading after this consolidation:
|
||||||
|
- vanilla refactoring is healthy and HyperTwist-owned; the next worthwhile
|
||||||
|
refactors should continue to be chosen for product clarity or native/runtime
|
||||||
|
value, not because the website manual lane is still drifting by duplication
|
||||||
|
|
||||||
|
Latest browser responsive recovery plus tooling rerun later on `2026-06-29`:
|
||||||
|
|
||||||
|
- the next same-family pass used the owned analyzer and browser-validation loop
|
||||||
|
to fix a real small-screen regression on protected launch-status instead of
|
||||||
|
manufacturing a new scope branch
|
||||||
|
- the current correction lived in `website/src/styles/global.css`, where the
|
||||||
|
small-screen button-row posture now forces stacked action links to respect
|
||||||
|
the available column width and allows long labels to wrap
|
||||||
|
- the owned structural and graph loop then stayed green again under:
|
||||||
|
- `scripts/run-hypertwist-sentrux-source-only.sh`
|
||||||
|
- `Quality: 6228`
|
||||||
|
- all `7` rules pass
|
||||||
|
- `scripts/run-hypertwist-gitnexus-analyze.sh`
|
||||||
|
- retained local CLI again fell back cleanly to `npx -y gitnexus@latest`
|
||||||
|
on this Linux host because of the cross-platform `LadybugDB` native payload
|
||||||
|
mismatch
|
||||||
|
- bounded mirror result:
|
||||||
|
- `16,394` nodes
|
||||||
|
- `38,737` edges
|
||||||
|
- `674` clusters
|
||||||
|
- `300` flows
|
||||||
|
- `scripts/run-hypertwist-gitnexus-status.sh`
|
||||||
|
- `Indexed commit: a863f79`
|
||||||
|
- `Current commit: a863f79`
|
||||||
|
- `Status: up-to-date`
|
||||||
|
- the adjacent owned browser/runtime validation umbrella also stayed green
|
||||||
|
after that recovery:
|
||||||
|
- `scripts/run-hypertwist-web-surface-validation.sh --with-responsive-e2e`
|
||||||
|
- focused website route/auth/release validation: `13` files, `79` tests
|
||||||
|
passed
|
||||||
|
- responsive public-route Playwright proof: `22` tests passed
|
||||||
|
- responsive protected-route Playwright proof: `12` tests passed
|
||||||
|
- `website/server` suite: `10` files, `36` tests passed
|
||||||
|
- `Content/Browser` shell verification and production build passed
|
||||||
|
- `website/` and `Content/Browser/` production audits stayed at
|
||||||
|
`found 0 vulnerabilities`
|
||||||
|
- `website/server/` again retained only the already-documented upstream
|
||||||
|
`supertokens-node -> nodemailer` residual advisory
|
||||||
|
- current truthful reading after this rerun:
|
||||||
|
- the HyperTwist-owned refactor/tooling lane remains healthy enough to catch
|
||||||
|
and verify small real product regressions, not just abstract structural
|
||||||
|
debt
|
||||||
|
|
||||||
|
Latest final auth-entry and authority-sync rerun later on `2026-06-29`:
|
||||||
|
|
||||||
|
- the next same-family quality pass rechecked the owned analyzer loop after the
|
||||||
|
final public-route authority sync instead of assuming the earlier `2026-06-29`
|
||||||
|
refreshes were still sufficient
|
||||||
|
- the owned structural gate stayed green:
|
||||||
|
- `scripts/run-hypertwist-sentrux-source-only.sh`
|
||||||
|
- `Quality: 6228`
|
||||||
|
- all `7` rules pass
|
||||||
|
- the HyperTwist-owned graph refresh again completed on the bounded
|
||||||
|
source-only mirror:
|
||||||
|
- `scripts/run-hypertwist-gitnexus-analyze.sh`
|
||||||
|
- the retained local CLI again failed cleanly on this Linux host because of
|
||||||
|
the cross-platform `LadybugDB` native payload mismatch, so the wrapper
|
||||||
|
truthfully fell back to `npx -y gitnexus@latest`
|
||||||
|
- fallback analyze run completed successfully in `80.2s`
|
||||||
|
- bounded mirror result:
|
||||||
|
- `16,393` nodes
|
||||||
|
- `38,742` edges
|
||||||
|
- `673` clusters
|
||||||
|
- `300` flows
|
||||||
|
- `scripts/run-hypertwist-gitnexus-status.sh` then reported:
|
||||||
|
- `Indexed commit: e7f266f`
|
||||||
|
- `Current commit: e7f266f`
|
||||||
|
- `Status: up-to-date`
|
||||||
|
- current truthful reading after this rerun:
|
||||||
|
- the broad vanilla-refactor lane remains complete as a tooling-adoption and
|
||||||
|
analyzer-ownership job inside HyperTwist
|
||||||
|
- the retained GitNexus local native payload still is not runnable on this
|
||||||
|
Linux host, but the HyperTwist-owned wrapper keeps that host fact explicit
|
||||||
|
instead of masking it
|
||||||
|
- the next worthwhile refactor work should keep being chosen for real
|
||||||
|
simulator, website-manual, or native-ownership value rather than for
|
||||||
|
missing analyzer setup debt
|
||||||
|
|
||||||
|
Latest hygiene-aware status-wrapper follow-up later on `2026-06-29`:
|
||||||
|
|
||||||
|
- the next bounded refactor-tool pass stayed inside the already-owned
|
||||||
|
GitNexus wrapper lane and corrected an operator-friction seam that appeared
|
||||||
|
after proper post-task cleanup
|
||||||
|
- `scripts/run-hypertwist-gitnexus-status.sh` no longer treats the absence of
|
||||||
|
the disposable `.gitnexus-source-only-root/` mirror as an automatic repo
|
||||||
|
failure in default mode; it now states plainly that this is normal after
|
||||||
|
hygiene and points operators back to
|
||||||
|
`scripts/run-hypertwist-gitnexus-analyze.sh` to recreate the bounded mirror
|
||||||
|
- the same wrapper now also distinguishes an interrupted or rebuilding mirror
|
||||||
|
where `.gitnexus/meta.json` is not yet present, instead of collapsing that
|
||||||
|
into the same generic missing-root failure
|
||||||
|
- strict automation can still request the old fail-fast posture explicitly
|
||||||
|
through:
|
||||||
|
- `HYPERTWIST_GITNEXUS_STATUS_REQUIRE_INDEX=1`
|
||||||
|
- this keeps HyperTwist’s refactor-tool posture aligned with the doctrine that
|
||||||
|
the GitNexus mirror is disposable analysis state, not release evidence or a
|
||||||
|
committed product artifact
|
||||||
|
|
||||||
|
Latest owned regression-gate and final refresh follow-up later on `2026-06-29`:
|
||||||
|
|
||||||
|
- the next same-family hardening pass then closed the remaining “wrapper is
|
||||||
|
present” versus “owned regression loop is actually proven” gap
|
||||||
|
- the HyperTwist-owned `sentrux` baseline loop is now explicitly re-proved:
|
||||||
|
- `scripts/run-hypertwist-sentrux-gate.sh --save`
|
||||||
|
- persisted baseline:
|
||||||
|
`.sentrux/source-only-baseline.json`
|
||||||
|
- `scripts/run-hypertwist-sentrux-gate.sh`
|
||||||
|
- comparison result:
|
||||||
|
- `Quality: 6234 -> 6234`
|
||||||
|
- `Coupling: 0.15 -> 0.15`
|
||||||
|
- `Cycles: 0 -> 0`
|
||||||
|
- `God files: 1 -> 1`
|
||||||
|
- `No degradation detected`
|
||||||
|
- the adjacent owned structural snapshot also stayed green:
|
||||||
|
- `scripts/run-hypertwist-sentrux-source-only.sh`
|
||||||
|
- `Quality: 6234`
|
||||||
|
- all `7` rules pass
|
||||||
|
- the HyperTwist-owned graph refresh again completed successfully on the
|
||||||
|
bounded source-only mirror:
|
||||||
|
- `scripts/run-hypertwist-gitnexus-analyze.sh`
|
||||||
|
- the retained local CLI again failed cleanly on this Linux host because of
|
||||||
|
the cross-platform `LadybugDB` native payload mismatch, so the wrapper
|
||||||
|
truthfully fell back to `npx -y gitnexus@latest`
|
||||||
|
- bounded mirror result:
|
||||||
|
- `16,397` nodes
|
||||||
|
- `38,754` edges
|
||||||
|
- `673` clusters
|
||||||
|
- `300` flows
|
||||||
|
- `scripts/run-hypertwist-gitnexus-status.sh`
|
||||||
|
- `Indexed commit: ab10931`
|
||||||
|
- `Current commit: ab10931`
|
||||||
|
- `Status: up-to-date`
|
||||||
|
- the same owned-refresh pass also kept the current public/protected browser
|
||||||
|
product surface green under:
|
||||||
|
- `scripts/run-hypertwist-web-surface-validation.sh --skip-audits`
|
||||||
|
- focused website route/auth/release validation: `13` files, `79` tests
|
||||||
|
passed
|
||||||
|
- `website/server` suite: `10` files, `36` tests passed
|
||||||
|
- `Content/Browser` shell verification and production build passed
|
||||||
|
- current truthful reading after this refresh:
|
||||||
|
- vanilla refactoring is complete as an owned toolchain-adoption and
|
||||||
|
regression-loop task inside HyperTwist
|
||||||
|
- the current remaining worthwhile refactors should be product or
|
||||||
|
runtime-driven improvements, not missing `sentrux`/GitNexus ownership or
|
||||||
|
an unproven baseline-comparison loop
|
||||||
|
|
|
||||||
|
|
@ -259,9 +259,47 @@ truthfully claim:
|
||||||
- `TrainingPanel.ControlSettingsOwnershipInspectSurface`
|
- `TrainingPanel.ControlSettingsOwnershipInspectSurface`
|
||||||
- `CoachDashboard.ControlProfileRosterInspectSurface`
|
- `CoachDashboard.ControlProfileRosterInspectSurface`
|
||||||
- `TrainingPanel.ControlProfileRosterInspectSurface`
|
- `TrainingPanel.ControlProfileRosterInspectSurface`
|
||||||
|
- a later interrupted-session recovery proof on `2026-06-29` then treated the
|
||||||
|
previously detached remote automation run as incomplete instead of assuming
|
||||||
|
success, repaired a stale remote
|
||||||
|
`HyperTwistBrowserBridgeObjectTest.cpp` copy on the broader maintained root,
|
||||||
|
re-synced the exact touched continuity slice into the short-root lane
|
||||||
|
`C:\HTpp`, rebuilt that exact-source lane cleanly with `Result: Succeeded`
|
||||||
|
and UnrealBuildTool `Total execution time: 4645.02 seconds`, then
|
||||||
|
sequentially re-exported fresh exact-source continuity proof with all
|
||||||
|
`Result={Success}` for:
|
||||||
|
- `HyperTwist.Browser.ControlProfileContinuityStateFormatting`
|
||||||
|
- `HyperTwist.Browser.ControlInputContinuityStateFormatting`
|
||||||
|
- `HyperTwist.Browser.ControlSettingsContinuityStateFormatting`
|
||||||
|
- that recovery matters for this audit because it keeps the current
|
||||||
|
desktop-hosted `No-Go` XR/controller boundary and the bounded
|
||||||
|
camera/immersive continuity wording grounded in fresh Windows evidence after
|
||||||
|
an interrupted host session rather than leaving the latest packet only on an
|
||||||
|
assumed-success trail
|
||||||
- the unattended run still emitted the already-accepted
|
- the unattended run still emitted the already-accepted
|
||||||
`Failed to create the web browser window.` message, but that noise did not
|
`Failed to create the web browser window.` message, but that noise did not
|
||||||
block report export or any of the focused browser automation proof
|
block report export or any of the focused browser automation proof
|
||||||
|
- a later exact-source maintained-root hardening follow-up on `2026-06-29`
|
||||||
|
then tightened the shared continuity formatting itself so stale ids and
|
||||||
|
counts are masked whenever the corresponding readiness booleans are false,
|
||||||
|
rather than letting degraded state accidentally render carried-over values:
|
||||||
|
- the touched training-panel, coach-dashboard, type, shared formatter, and
|
||||||
|
focused automation-test files were re-synced into maintained validation
|
||||||
|
root `C:\HyperTwist_worktrees\phase10validate`
|
||||||
|
- the maintained validation root rebuilt cleanly with `Result: Succeeded`
|
||||||
|
and UnrealBuildTool `Total execution time: 3325.07 seconds`
|
||||||
|
- focused browser automation then exported the maintained-root report family
|
||||||
|
`Continuity-CountMasking-20260629-*` with all `Result={Success}` for:
|
||||||
|
- `HyperTwist.Browser.ControlInputContinuityStateFormatting`
|
||||||
|
- `HyperTwist.Browser.ControlSettingsContinuityStateFormatting`
|
||||||
|
- `HyperTwist.Browser.ControlProfileContinuityStateFormatting`
|
||||||
|
- `HyperTwist.Browser.TrainingPanel.ControlProfileContinuityParity`
|
||||||
|
- `HyperTwist.Browser.CoachDashboard.ControlProfileContinuityArtifacts`
|
||||||
|
- that same follow-up matters for this audit because the current
|
||||||
|
desktop-hosted `No-Go` XR/controller boundary and the bounded
|
||||||
|
camera/immersive/profile continuity wording are now grounded not only in
|
||||||
|
current Windows proof, but also in explicit degraded-state count-masking
|
||||||
|
behavior instead of merely assuming absent readiness will hide stale values
|
||||||
|
|
||||||
### Explicit project OpenXR plugin posture now exists
|
### Explicit project OpenXR plugin posture now exists
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ claims over the same capability.
|
||||||
HyperTwist now has its own bounded refactor/analyzer entry points:
|
HyperTwist now has its own bounded refactor/analyzer entry points:
|
||||||
|
|
||||||
- `scripts/run-hypertwist-sentrux-source-only.sh`
|
- `scripts/run-hypertwist-sentrux-source-only.sh`
|
||||||
|
- `scripts/run-hypertwist-sentrux-gate.sh`
|
||||||
- `scripts/run-hypertwist-gitnexus-analyze.sh`
|
- `scripts/run-hypertwist-gitnexus-analyze.sh`
|
||||||
- `scripts/run-hypertwist-gitnexus-status.sh`
|
- `scripts/run-hypertwist-gitnexus-status.sh`
|
||||||
- `scripts/run-hypertwist-web-surface-validation.sh`
|
- `scripts/run-hypertwist-web-surface-validation.sh`
|
||||||
|
|
@ -55,10 +56,29 @@ Use them with this posture:
|
||||||
- `HYPERTWIST_GITNEXUS_DEBUG_LOCAL=1` keeps local GitNexus stderr visible so
|
- `HYPERTWIST_GITNEXUS_DEBUG_LOCAL=1` keeps local GitNexus stderr visible so
|
||||||
retained-runtime problems can be diagnosed instead of being silently
|
retained-runtime problems can be diagnosed instead of being silently
|
||||||
suppressed during the normal fallback path
|
suppressed during the normal fallback path
|
||||||
|
- `scripts/run-hypertwist-gitnexus-status.sh` is now hygiene-aware in default
|
||||||
|
mode:
|
||||||
|
- if the disposable `.gitnexus-source-only-root/` mirror has already been
|
||||||
|
removed during a correct cleanup pass, the wrapper reports that as normal
|
||||||
|
disposable-state absence instead of treating it as repo corruption
|
||||||
|
- if the disposable mirror exists but `.gitnexus/meta.json` is missing, the
|
||||||
|
wrapper reports an interrupted or rebuilding index state instead of the
|
||||||
|
same generic failure
|
||||||
|
- `HYPERTWIST_GITNEXUS_STATUS_REQUIRE_INDEX=1` restores strict non-zero
|
||||||
|
failure when an automation caller truly requires a completed bounded index
|
||||||
- `scripts/run-hypertwist-sentrux-source-only.sh` now prefers a HyperTwist
|
- `scripts/run-hypertwist-sentrux-source-only.sh` now prefers a HyperTwist
|
||||||
owned entry path first: `HYPERTWIST_SENTRUX_BINARY`, repo-local `./sentrux`
|
owned entry path first: `HYPERTWIST_SENTRUX_BINARY`, repo-local `./sentrux`
|
||||||
or `./sentrux.exe`, then repo-local `tools/sentrux/bin/`, then a bootstrap
|
or `./sentrux.exe`, then repo-local `tools/sentrux/bin/`, then a bootstrap
|
||||||
attempt, then `PATH`
|
attempt, then `PATH`
|
||||||
|
- `scripts/run-hypertwist-sentrux-gate.sh` now gives HyperTwist the same
|
||||||
|
bounded source-only regression loop as the broader Sentrux doctrine, but
|
||||||
|
without trusting a disposable temp mirror to remember its own baseline:
|
||||||
|
- `--save` refreshes the owned baseline at
|
||||||
|
`.sentrux/source-only-baseline.json`
|
||||||
|
- comparison runs restore that repo-owned baseline into the disposable
|
||||||
|
mirror before calling `sentrux gate`
|
||||||
|
- the wrapper therefore survives normal post-task hygiene that deletes temp
|
||||||
|
mirrors instead of silently losing the last saved architecture baseline
|
||||||
- the current `2026-06-24` wrapper hardening tightens that posture further:
|
- the current `2026-06-24` wrapper hardening tightens that posture further:
|
||||||
- the source-only wrapper now auto-attempts
|
- the source-only wrapper now auto-attempts
|
||||||
`scripts/bootstrap-hypertwist-sentrux.sh --if-missing` before it gives up
|
`scripts/bootstrap-hypertwist-sentrux.sh --if-missing` before it gives up
|
||||||
|
|
@ -82,9 +102,13 @@ Suggested loop:
|
||||||
1. run `scripts/run-hypertwist-gitnexus-analyze.sh` before a larger rename or
|
1. run `scripts/run-hypertwist-gitnexus-analyze.sh` before a larger rename or
|
||||||
subsystem split
|
subsystem split
|
||||||
2. use `scripts/run-hypertwist-gitnexus-status.sh` to confirm index freshness
|
2. use `scripts/run-hypertwist-gitnexus-status.sh` to confirm index freshness
|
||||||
3. run `scripts/run-hypertwist-sentrux-source-only.sh` before and after the
|
3. if the packet needs a before/after regression comparison, stamp the owned
|
||||||
|
bounded baseline with `scripts/run-hypertwist-sentrux-gate.sh --save`
|
||||||
|
4. run `scripts/run-hypertwist-sentrux-source-only.sh` before and after the
|
||||||
packet
|
packet
|
||||||
4. treat `sentrux` failures as structural review signals, then confirm with
|
5. rerun `scripts/run-hypertwist-sentrux-gate.sh` when you want the saved
|
||||||
|
source-only baseline comparison itself, not just the latest raw score
|
||||||
|
6. treat `sentrux` failures as structural review signals, then confirm with
|
||||||
focused product tests
|
focused product tests
|
||||||
|
|
||||||
Additional dependency-health loop for the current browser and website family:
|
Additional dependency-health loop for the current browser and website family:
|
||||||
|
|
@ -1313,10 +1337,14 @@ Current audit note:
|
||||||
- `npm --prefix website run test:e2e:responsive:list`
|
- `npm --prefix website run test:e2e:responsive:list`
|
||||||
- that responsive packet covers the real current HyperTwist public routes for:
|
- that responsive packet covers the real current HyperTwist public routes for:
|
||||||
- homepage
|
- homepage
|
||||||
|
- feature atlas
|
||||||
- about
|
- about
|
||||||
- resources
|
- resources
|
||||||
|
- docs
|
||||||
- pricing
|
- pricing
|
||||||
- download
|
- download
|
||||||
|
- getting-started
|
||||||
|
- launch-status
|
||||||
- support
|
- support
|
||||||
- register
|
- register
|
||||||
- each route now has a browser-level proof for:
|
- each route now has a browser-level proof for:
|
||||||
|
|
@ -1353,6 +1381,34 @@ Current audit note:
|
||||||
responsive browser proofs when `--with-responsive-e2e` is explicitly
|
responsive browser proofs when `--with-responsive-e2e` is explicitly
|
||||||
requested
|
requested
|
||||||
|
|
||||||
|
Latest same-family responsive public-route expansion follow-up on `2026-06-29`:
|
||||||
|
|
||||||
|
- the responsive public-route browser proof then widened again so the newer
|
||||||
|
canonical manual and authority routes are no longer outside the production-
|
||||||
|
shaped viewport evidence lane
|
||||||
|
- `website/tests/e2e/responsive-public-pages.spec.ts` now also covers:
|
||||||
|
- `/features`
|
||||||
|
- `/docs`
|
||||||
|
- `/getting-started`
|
||||||
|
- `/launch-status`
|
||||||
|
- the widened public-route proof therefore now covers `11` public routes
|
||||||
|
across both mobile and tablet classes instead of the earlier narrower public
|
||||||
|
shell set
|
||||||
|
- current validation truth for that widened browser-level packet is green:
|
||||||
|
- `npm --prefix website run test:e2e:responsive`
|
||||||
|
- responsive public-route Playwright proof: `22` tests passed
|
||||||
|
- `scripts/run-hypertwist-web-surface-validation.sh --with-responsive-e2e`
|
||||||
|
- focused website route/auth/release validation: `12` files, `74` tests
|
||||||
|
passed
|
||||||
|
- responsive public-route Playwright proof: `22` tests passed
|
||||||
|
- responsive protected-route Playwright proof: `12` tests passed
|
||||||
|
- `website/server` suite: `10` files, `36` tests passed
|
||||||
|
- `Content/Browser` shell verification and production build passed
|
||||||
|
- `website/` and `Content/Browser/` production audits stayed at
|
||||||
|
`found 0 vulnerabilities`
|
||||||
|
- `website/server/` again retained only the already-documented upstream
|
||||||
|
`supertokens-node -> nodemailer` residual
|
||||||
|
|
||||||
## Latest native/public control-roster parity follow-up (`2026-06-25`)
|
## Latest native/public control-roster parity follow-up (`2026-06-25`)
|
||||||
|
|
||||||
- the same-family native/operator continuity lane then aligned the shipped
|
- the same-family native/operator continuity lane then aligned the shipped
|
||||||
|
|
@ -1393,3 +1449,627 @@ Current audit note:
|
||||||
- `CoachDashboard.ControlProfileRosterInspectSurface`
|
- `CoachDashboard.ControlProfileRosterInspectSurface`
|
||||||
- `TrainingPanel.ControlProfileRosterInspectSurface`
|
- `TrainingPanel.ControlProfileRosterInspectSurface`
|
||||||
- `CoachDashboard.ControlSurfaceStructuredTextArtifacts`
|
- `CoachDashboard.ControlSurfaceStructuredTextArtifacts`
|
||||||
|
|
||||||
|
## Latest control-profile continuity and diagnostics follow-up (`2026-06-28`)
|
||||||
|
|
||||||
|
- the next same-family native/operator continuity packet then tightened the
|
||||||
|
control-profile roster seam itself instead of leaving the newest continuity
|
||||||
|
truth stranded only on sibling control-settings surfaces:
|
||||||
|
- `FHyperTwistTrainingControlProfileRosterInspectSurface` now carries the
|
||||||
|
active higher-dimensional interactive-scene id alongside the active
|
||||||
|
activation, view-context, and session ids
|
||||||
|
- that same roster seam now resolves the first valid viewer camera-export
|
||||||
|
artifact instead of trusting only the first listed id, and it keeps the
|
||||||
|
shipped `artifact/camera-export-json` plus
|
||||||
|
`immersive-training-session-recall-boundary` visible with recall-scope and
|
||||||
|
preference-field counts
|
||||||
|
- `UHyperTwistCoachDashboardWidget` now mirrors that same bounded continuity
|
||||||
|
truth into a dedicated `CoachControlProfileRosterPreferencesContinuity`
|
||||||
|
structured row instead of collapsing it into broader detail prose only
|
||||||
|
- `HyperTwistTrainingPanelWidget.cpp` now resolves the bounded camera and
|
||||||
|
immersive continuity facts through shared local helper builders so the
|
||||||
|
control-input, control-settings, and control-profile seams do not drift
|
||||||
|
apart when the same continuity truth changes again later
|
||||||
|
- the public manual and operator-facing site truth now also reflect that same
|
||||||
|
native diagnostics reality more directly:
|
||||||
|
- `website/src/site-data.ts` now adds a dedicated native diagnostics-check
|
||||||
|
card to the runtime control guide
|
||||||
|
- the public control-roster copy now explicitly mentions the live scene id
|
||||||
|
and the continuity-count readout instead of leaving those facts implied
|
||||||
|
- current local validation for that same packet is green:
|
||||||
|
- focused public/protected/manual website coverage:
|
||||||
|
`47` tests passed across `public-marketing-pages`, `public-auth-pages`,
|
||||||
|
`protected-app-pages`, and `app-route-tree`
|
||||||
|
- `scripts/run-hypertwist-web-surface-validation.sh`
|
||||||
|
- website focused suite: `74` tests passed
|
||||||
|
- website/server suite: `36` tests passed
|
||||||
|
- `Content/Browser` shell verification and production build passed
|
||||||
|
- `website/` and `Content/Browser/` production audits stayed at
|
||||||
|
`found 0 vulnerabilities`
|
||||||
|
- `website/server/` retained only the already-documented upstream
|
||||||
|
`supertokens-node -> nodemailer` residual
|
||||||
|
- `scripts/run-hypertwist-sentrux-source-only.sh`
|
||||||
|
- `Quality: 6228`
|
||||||
|
- all `7` rules passing
|
||||||
|
- `scripts/run-hypertwist-gitnexus-analyze.sh`
|
||||||
|
- bounded mirror refreshed at:
|
||||||
|
- `16,382` nodes
|
||||||
|
- `38,653` edges
|
||||||
|
- `679` clusters
|
||||||
|
- `300` flows
|
||||||
|
- `scripts/run-hypertwist-gitnexus-status.sh`
|
||||||
|
- bounded mirror `Status: up-to-date`
|
||||||
|
- the authoritative Windows proof for the exact-source continuity state also
|
||||||
|
completed cleanly on the short-root recovery lane `C:\HTpp`:
|
||||||
|
- synced the exact touched Unreal source files through
|
||||||
|
`scripts/run-hypertwist-remote-windows-file-sync.sh --remote-root 'C:\HTpp'`
|
||||||
|
- remote Unreal rebuild through
|
||||||
|
`scripts/run-hypertwist-remote-unreal-build.sh --worktree-root 'C:\HTpp' --max-parallel-actions 8`
|
||||||
|
- `Result: Succeeded`
|
||||||
|
- UnrealBuildTool `Total execution time: 2374.44 seconds`
|
||||||
|
- focused remote automation then exported both report roots with
|
||||||
|
`Result={Success}`:
|
||||||
|
- `Browser-ControlProfileContinuityParity-20260628-HyperTwist.Browser.TrainingPanel.ControlProfileContinuityParity`
|
||||||
|
- `Browser-ControlProfileContinuityParity-20260628-HyperTwist.Browser.CoachDashboard.ControlProfileContinuityArtifacts`
|
||||||
|
- the accepted unattended `Failed to create the web browser window.` dialog
|
||||||
|
still appeared on both editor launches, but it remained non-blocking and
|
||||||
|
the focused automation proofs completed successfully
|
||||||
|
|
||||||
|
## Latest onboarding-manual and refactor-refresh follow-up (`2026-06-28`)
|
||||||
|
|
||||||
|
- the canonical public `/getting-started` route then widened again so the
|
||||||
|
shortest complete onboarding page now also carries the same
|
||||||
|
higher-dimensional family guide and runtime control guide already present on
|
||||||
|
the broader docs/resources lanes
|
||||||
|
- that means the first-session route now directly teaches:
|
||||||
|
- the dedicated native `Magic120Cell` and `MagicCube5D` families
|
||||||
|
- the current embedded-browser `MagicTile` host posture
|
||||||
|
- the shipped classic desktop control posture
|
||||||
|
- the current higher-dimensional control posture
|
||||||
|
- the native diagnostics check
|
||||||
|
- the explicit desktop-hosted `No-Go` XR/controller boundary
|
||||||
|
- focused validation for that public-manual continuation stayed green under:
|
||||||
|
- `npm --prefix website test -- --run src/__tests__/public-marketing-pages.test.tsx`
|
||||||
|
- `1` file passed
|
||||||
|
- `15` tests passed
|
||||||
|
- the same packet also refreshed the owned analyzer loop so the current
|
||||||
|
refactor posture stayed source-backed instead of inherited from older notes:
|
||||||
|
- `scripts/run-hypertwist-sentrux-source-only.sh`
|
||||||
|
- `Quality: 6228`
|
||||||
|
- all `7` rules pass
|
||||||
|
- `scripts/run-hypertwist-gitnexus-analyze.sh`
|
||||||
|
- retained local CLI again fell back cleanly to `npx -y gitnexus@latest`
|
||||||
|
on this Linux host because of the cross-platform `LadybugDB` native
|
||||||
|
payload mismatch
|
||||||
|
- bounded mirror refreshed at:
|
||||||
|
- `16,380` nodes
|
||||||
|
- `38,646` edges
|
||||||
|
- `679` clusters
|
||||||
|
- `300` flows
|
||||||
|
- `scripts/run-hypertwist-gitnexus-status.sh`
|
||||||
|
- `Indexed commit: a4a50b8`
|
||||||
|
- `Current commit: a4a50b8`
|
||||||
|
- `Status: up-to-date`
|
||||||
|
- current truthful reading after that refresh:
|
||||||
|
- the broad vanilla-refactor lane is no longer blocked by broken wrappers or
|
||||||
|
a failing structural gate
|
||||||
|
- the next worthwhile cleanup is selective readability or ownership work
|
||||||
|
chosen for product value, not emergency analyzer adoption
|
||||||
|
|
||||||
|
## Latest feature-atlas runtime-guide parity follow-up (`2026-06-28`)
|
||||||
|
|
||||||
|
- the public `FeaturesPage` then widened again so the feature atlas no longer
|
||||||
|
stops at capability tracks, higher-dimensional host posture, and roster
|
||||||
|
summaries when the broader public manual already carries a more practical
|
||||||
|
runtime-usage seam
|
||||||
|
- the same route now also renders the shared runtime control guide directly,
|
||||||
|
including:
|
||||||
|
- the shipped classic desktop control posture
|
||||||
|
- the current higher-dimensional desktop-control posture
|
||||||
|
- the native diagnostics check
|
||||||
|
- the explicit desktop-hosted `No-Go` XR/controller boundary
|
||||||
|
- this keeps the public feature atlas closer to a genuine capability-plus-usage
|
||||||
|
reference instead of requiring advanced readers to leave the atlas for docs,
|
||||||
|
resources, or getting-started just to find the current practical control and
|
||||||
|
diagnostics truth
|
||||||
|
- focused validation for that continuation stayed green under:
|
||||||
|
- `npm --prefix website test -- --run src/__tests__/public-marketing-pages.test.tsx`
|
||||||
|
- `1` file passed
|
||||||
|
- `15` tests passed
|
||||||
|
- the broader owned website/runtime/server umbrella then also stayed green
|
||||||
|
again under:
|
||||||
|
- `scripts/run-hypertwist-web-surface-validation.sh`
|
||||||
|
- focused website route/auth/release validation: `12` files, `74` tests
|
||||||
|
passed
|
||||||
|
- `npm --prefix website run build`
|
||||||
|
- `npm --prefix website/server run type-check`
|
||||||
|
- `npm --prefix website/server test -- --run`
|
||||||
|
- `10` website/server files passed, `36` tests passed
|
||||||
|
- `npm --prefix Content/Browser run verify:shell`
|
||||||
|
- `npm --prefix Content/Browser run build`
|
||||||
|
- `website/` and `Content/Browser/` production audits stayed at
|
||||||
|
`found 0 vulnerabilities`
|
||||||
|
- `website/server/` again retained only the already-documented upstream
|
||||||
|
`supertokens-node -> nodemailer` residual
|
||||||
|
- the owned structural gate stayed clean on the same packet:
|
||||||
|
- `scripts/run-hypertwist-sentrux-source-only.sh`
|
||||||
|
- `Quality: 6228`
|
||||||
|
- all `7` rules pass
|
||||||
|
|
||||||
|
## Latest commerce/download manual deepening follow-up (`2026-06-29`)
|
||||||
|
|
||||||
|
- the public commerce and package routes were then widened again so the pages
|
||||||
|
where operators actually decide to buy access or fetch the build no longer
|
||||||
|
stop at entitlement, target choice, and browser-to-desktop handoff
|
||||||
|
- the public `/pricing` route now also carries:
|
||||||
|
- the practical installed-software simulator manual
|
||||||
|
- the shared higher-dimensional family guide
|
||||||
|
- the same current input/device and runtime-control truth, including the
|
||||||
|
explicit desktop-hosted `No-Go` XR/controller boundary
|
||||||
|
- the public `/download` route now also carries:
|
||||||
|
- the installed-runtime manual directly on the package page
|
||||||
|
- the higher-dimensional family guide before first launch
|
||||||
|
- the current input/device and runtime-control truth before the operator
|
||||||
|
leaves the public release lane
|
||||||
|
- this keeps pricing/download closer to genuine public operator-manual
|
||||||
|
surfaces instead of leaving the practical product explanation scattered
|
||||||
|
across docs/resources/getting-started alone
|
||||||
|
- validation for that continuation stayed green under:
|
||||||
|
- `npm --prefix website test -- --run src/__tests__/public-marketing-pages.test.tsx`
|
||||||
|
- `1` file passed
|
||||||
|
- `15` tests passed
|
||||||
|
- `npm --prefix website run build`
|
||||||
|
- production website build passed
|
||||||
|
- `scripts/run-hypertwist-web-surface-validation.sh`
|
||||||
|
- focused website route/auth/release validation: `12` files, `74` tests
|
||||||
|
passed
|
||||||
|
- `website/server` suite: `10` files, `36` tests passed
|
||||||
|
- `Content/Browser` shell verification and production build passed
|
||||||
|
- `website/` and `Content/Browser/` production audits stayed at
|
||||||
|
`found 0 vulnerabilities`
|
||||||
|
- `website/server/` again retained only the already-documented upstream
|
||||||
|
`supertokens-node -> nodemailer` residual advisory
|
||||||
|
|
||||||
|
## Latest shared public-manual plus control-continuity validation follow-up (`2026-06-29`)
|
||||||
|
|
||||||
|
- the same-family continuation then spent its next bounded packet on shared
|
||||||
|
public-manual ownership plus additional native continuity proof instead of
|
||||||
|
widening claims
|
||||||
|
- the public website now centralizes repeated manual-card rendering in:
|
||||||
|
- `website/src/pages/public-page-helpers.tsx`
|
||||||
|
- `PrincipleCardSection`
|
||||||
|
- `BulletCardSection`
|
||||||
|
- `StepCardSection`
|
||||||
|
- `FaqCardSection`
|
||||||
|
- the current public/manual consumers now route through those shared helpers:
|
||||||
|
- `website/src/pages/public-pages-marketing.tsx`
|
||||||
|
- `website/src/pages/public-pages-features.tsx`
|
||||||
|
- `website/src/pages/public-pages-commerce.tsx`
|
||||||
|
- local public-surface validation for that refactor stayed green under:
|
||||||
|
- `npm --prefix website run type-check`
|
||||||
|
- `npm --prefix website test -- --run src/__tests__/public-marketing-pages.test.tsx`
|
||||||
|
- `1` file passed
|
||||||
|
- `15` tests passed
|
||||||
|
- `npm --prefix website run build`
|
||||||
|
- production website build passed
|
||||||
|
- the owned structural and graph loop also stayed green on the same packet:
|
||||||
|
- `scripts/run-hypertwist-sentrux-source-only.sh`
|
||||||
|
- `Quality: 6228`
|
||||||
|
- all `7` rules pass
|
||||||
|
- `scripts/run-hypertwist-gitnexus-analyze.sh`
|
||||||
|
- retained local CLI again fell back cleanly to `npx -y gitnexus@latest`
|
||||||
|
on this Linux host because of the cross-platform `LadybugDB` native payload
|
||||||
|
mismatch
|
||||||
|
- bounded mirror result:
|
||||||
|
- `16,387` nodes
|
||||||
|
- `38,682` edges
|
||||||
|
- `676` clusters
|
||||||
|
- `300` flows
|
||||||
|
- `scripts/run-hypertwist-gitnexus-status.sh`
|
||||||
|
- `Indexed commit: 1deca95`
|
||||||
|
- `Current commit: 1deca95`
|
||||||
|
- `Status: up-to-date`
|
||||||
|
- the adjacent native continuity-formatting proof also landed successfully on
|
||||||
|
the exact-source Windows lane `C:\HTpp` after the shared formatter extraction:
|
||||||
|
- authoritative short-root Unreal rebuild succeeded before the automation
|
||||||
|
reruns
|
||||||
|
- `HyperTwist.Browser.ControlInputContinuityStateFormatting`
|
||||||
|
- `State=Success`
|
||||||
|
- report:
|
||||||
|
`Saved\AutomationReports\Browser-ControlInputContinuityStateFormatting-Verify`
|
||||||
|
- `HyperTwist.Browser.ControlSettingsContinuityStateFormatting`
|
||||||
|
- `State=Success`
|
||||||
|
- report:
|
||||||
|
`Saved\AutomationReports\Browser-ControlSettingsContinuityStateFormatting-Verify`
|
||||||
|
- `HyperTwist.Browser.ControlProfileContinuityStateFormatting`
|
||||||
|
- `State=Success`
|
||||||
|
- report:
|
||||||
|
`Saved\AutomationReports\Browser-ControlProfileContinuityStateFormatting-Verify`
|
||||||
|
- the widget-level training-panel integration path also stayed green after
|
||||||
|
the formatter extraction:
|
||||||
|
- `HyperTwist.Browser.TrainingPanel.ControlProfileContinuityParity`
|
||||||
|
- `State=Success`
|
||||||
|
- report:
|
||||||
|
`Saved\AutomationReports\Browser-ControlProfileContinuityParity-Rerun`
|
||||||
|
- this keeps the native training/operator continuity packet honest after the
|
||||||
|
shared formatter extraction: the browser/public manual side now has lower
|
||||||
|
drift risk, and the sibling Unreal-side continuity text still has exact-source
|
||||||
|
proof for input, settings, and profile degraded-state rendering
|
||||||
|
|
||||||
|
## Latest exact-source short-root continuity recovery proof (`2026-06-29`)
|
||||||
|
|
||||||
|
- the next adjacent recovery pass closed one important validation gap instead
|
||||||
|
of widening scope again: the earlier short-root rerun had only matched the
|
||||||
|
formatter-name subset, so the exact-source Windows lane was re-proved again
|
||||||
|
against the broader continuity family on `C:\HTpp`
|
||||||
|
- the authoritative short-root Unreal rebuild stayed green before the reruns:
|
||||||
|
- `scripts/run-hypertwist-remote-unreal-build.sh --worktree-root 'C:\HTpp' --max-parallel-actions 8`
|
||||||
|
- `Result: Succeeded`
|
||||||
|
- UnrealBuildTool `Total execution time: 78.51 seconds`
|
||||||
|
- the exact-source formatting-family rerun then passed on the same short-root
|
||||||
|
lane:
|
||||||
|
- report:
|
||||||
|
`Saved\AutomationReports\ContinuityStateFormatting-Rerun`
|
||||||
|
- `HyperTwist.Browser.ControlInputContinuityStateFormatting`
|
||||||
|
- `HyperTwist.Browser.ControlProfileContinuityStateFormatting`
|
||||||
|
- `HyperTwist.Browser.ControlSettingsContinuityStateFormatting`
|
||||||
|
- all `3` tests completed with `Result={Success}`
|
||||||
|
- the exact-source broader profile-continuity rerun then also passed on the
|
||||||
|
same short-root lane:
|
||||||
|
- report:
|
||||||
|
`Saved\AutomationReports\ControlProfileContinuity-Rerun`
|
||||||
|
- `HyperTwist.Browser.CoachDashboard.ControlProfileContinuityArtifacts`
|
||||||
|
- `HyperTwist.Browser.TrainingPanel.ControlProfileContinuityParity`
|
||||||
|
- `HyperTwist.Browser.ControlProfileContinuityStateFormatting`
|
||||||
|
- all `3` tests completed with `Result={Success}`
|
||||||
|
- the repeated unattended editor dialog `Failed to create the web browser
|
||||||
|
window.` again remained non-blocking on this Windows automation lane
|
||||||
|
- this keeps the native continuity packet truthful after recovery:
|
||||||
|
- the shared formatter extraction is now backed by current exact-source
|
||||||
|
Windows proof
|
||||||
|
- the training-panel and coach-dashboard parity seams are explicitly
|
||||||
|
re-proved, not merely inferred from the narrower formatter-only rerun
|
||||||
|
|
||||||
|
## Latest interrupted-session exact-source continuity completion proof (`2026-06-29`)
|
||||||
|
|
||||||
|
- the next same-family recovery pass then treated the previously detached
|
||||||
|
remote automation session as incomplete instead of assuming success
|
||||||
|
- the broader maintained validation root had drifted on one sibling test file:
|
||||||
|
- remote `C:\HyperTwist_worktrees\phase10validate\UnrealHyperTwist\Source\UnrealHyperTwist\Tests\HyperTwistBrowserBridgeObjectTest.cpp`
|
||||||
|
still carried stale extra lines and failed the first rebuild with:
|
||||||
|
`error C2816: invocation of function-like macro 'IMPLEMENT_SIMPLE_AUTOMATION_TEST' is missing terminating ')'`
|
||||||
|
- the exact local file was re-synced to repair that stale remote source
|
||||||
|
instead of accepting the older broken copy as current truth
|
||||||
|
- after that repair, the exact touched continuity slice was re-synced into the
|
||||||
|
short-root recovery lane `C:\HTpp`, which was then used as the authoritative
|
||||||
|
exact-source completion lane for the interrupted packet
|
||||||
|
- the recovered short-root Unreal rebuild stayed green under:
|
||||||
|
- `scripts/run-hypertwist-remote-unreal-build.sh --worktree-root 'C:\HTpp'`
|
||||||
|
- `Result: Succeeded`
|
||||||
|
- UnrealBuildTool `Total execution time: 4645.02 seconds`
|
||||||
|
- the exact-source recovered continuity reruns then completed sequentially on
|
||||||
|
the same short-root lane and all stayed green:
|
||||||
|
- report root:
|
||||||
|
`Saved\AutomationReports\Continuity-Rerun-20260629-HyperTwist.Browser.ControlProfileContinuity`
|
||||||
|
- `HyperTwist.Browser.ControlProfileContinuityStateFormatting`
|
||||||
|
- `Result={Success}`
|
||||||
|
- report root:
|
||||||
|
`Saved\AutomationReports\Continuity-Rerun-20260629-HyperTwist.Browser.ControlInputContinuityStateFormatting`
|
||||||
|
- `HyperTwist.Browser.ControlInputContinuityStateFormatting`
|
||||||
|
- `Result={Success}`
|
||||||
|
- report root:
|
||||||
|
`Saved\AutomationReports\Continuity-Rerun-20260629-HyperTwist.Browser.ControlSettingsContinuityStateFormatting`
|
||||||
|
- `HyperTwist.Browser.ControlSettingsContinuityStateFormatting`
|
||||||
|
- `Result={Success}`
|
||||||
|
- the repeated unattended editor dialog `Failed to create the web browser
|
||||||
|
window.` again remained a non-blocking Windows editor artifact during these
|
||||||
|
recovered reruns
|
||||||
|
- this closes the interrupted-session gap truthfully:
|
||||||
|
- the prior detached remote session is no longer merely presumed green
|
||||||
|
- the current exact-source continuity family has fresh post-recovery Windows
|
||||||
|
proof on the short-root lane
|
||||||
|
- the stale remote-source issue is recorded as a repaired host-state problem,
|
||||||
|
not misdescribed as a current repository defect
|
||||||
|
|
||||||
|
## Latest owned regression-gate plus maintained-root continuity-count masking follow-up (`2026-06-29`)
|
||||||
|
|
||||||
|
- the next same-family finish-quality pass then closed two remaining “almost
|
||||||
|
there” gaps instead of widening scope again:
|
||||||
|
- the owned `sentrux` baseline-comparison loop was re-proved explicitly
|
||||||
|
- the broader maintained validation root re-proved degraded-state
|
||||||
|
continuity/count masking on the exact touched Unreal slice
|
||||||
|
- the HyperTwist-owned refactor loop is now backed by fresh before/after gate
|
||||||
|
evidence instead of only wrapper presence:
|
||||||
|
- `scripts/run-hypertwist-sentrux-gate.sh --save`
|
||||||
|
- persisted baseline:
|
||||||
|
`.sentrux/source-only-baseline.json`
|
||||||
|
- `scripts/run-hypertwist-sentrux-gate.sh`
|
||||||
|
- comparison result:
|
||||||
|
- `Quality: 6234 -> 6234`
|
||||||
|
- `Coupling: 0.15 -> 0.15`
|
||||||
|
- `Cycles: 0 -> 0`
|
||||||
|
- `God files: 1 -> 1`
|
||||||
|
- `No degradation detected`
|
||||||
|
- `scripts/run-hypertwist-sentrux-source-only.sh`
|
||||||
|
- `Quality: 6234`
|
||||||
|
- all `7` rules pass
|
||||||
|
- `scripts/run-hypertwist-gitnexus-analyze.sh`
|
||||||
|
- bounded mirror result:
|
||||||
|
- `16,397` nodes
|
||||||
|
- `38,754` edges
|
||||||
|
- `673` clusters
|
||||||
|
- `300` flows
|
||||||
|
- `scripts/run-hypertwist-gitnexus-status.sh`
|
||||||
|
- `Indexed commit: ab10931`
|
||||||
|
- `Current commit: ab10931`
|
||||||
|
- `Status: up-to-date`
|
||||||
|
- the exact touched continuity slice then also stayed green on the maintained
|
||||||
|
Windows validation root `C:\HyperTwist_worktrees\phase10validate`:
|
||||||
|
- exact-source rebuild:
|
||||||
|
- `Result: Succeeded`
|
||||||
|
- UnrealBuildTool `Total execution time: 3325.07 seconds`
|
||||||
|
- focused automation report family:
|
||||||
|
`Continuity-CountMasking-20260629-*`
|
||||||
|
- successful filters:
|
||||||
|
- `HyperTwist.Browser.ControlInputContinuityStateFormatting`
|
||||||
|
- `HyperTwist.Browser.ControlSettingsContinuityStateFormatting`
|
||||||
|
- `HyperTwist.Browser.ControlProfileContinuityStateFormatting`
|
||||||
|
- `HyperTwist.Browser.TrainingPanel.ControlProfileContinuityParity`
|
||||||
|
- `HyperTwist.Browser.CoachDashboard.ControlProfileContinuityArtifacts`
|
||||||
|
- this keeps the lane honest in two useful ways:
|
||||||
|
- the owned analyzer/tooling posture is proven as a real regression loop,
|
||||||
|
not just a documented wrapper set
|
||||||
|
- the native control/input, control/settings, and control/profile continuity
|
||||||
|
seams now have fresh maintained-root Windows proof that degraded readiness
|
||||||
|
masks stale counts and ids instead of overreporting continuity state
|
||||||
|
|
||||||
|
## Latest responsive website revalidation plus GitNexus status hardening follow-up (`2026-06-29`)
|
||||||
|
|
||||||
|
- the next same-family continuation stayed inside the current owned
|
||||||
|
website/tooling lane instead of reopening any new runtime branch
|
||||||
|
- the public/protected browser product surface was revalidated at real browser
|
||||||
|
breakpoints after the recent public-manual widening:
|
||||||
|
- `scripts/run-hypertwist-web-surface-validation.sh --with-responsive-e2e`
|
||||||
|
- focused website route/auth/release validation: `12` files, `74` tests
|
||||||
|
passed
|
||||||
|
- responsive public-route Playwright proof: `22` tests passed
|
||||||
|
- responsive protected-route Playwright proof: `12` tests passed
|
||||||
|
- `website/server` suite: `10` files, `36` tests passed
|
||||||
|
- `Content/Browser` shell verification and production build passed
|
||||||
|
- `website/` and `Content/Browser/` production audits stayed at
|
||||||
|
`found 0 vulnerabilities`
|
||||||
|
- `website/server/` again retained only the already-documented upstream
|
||||||
|
`supertokens-node -> nodemailer` residual advisory
|
||||||
|
- the adjacent HyperTwist-owned refactor/tooling wrapper was also hardened:
|
||||||
|
- `scripts/run-hypertwist-gitnexus-status.sh` now reports when the bounded
|
||||||
|
source-only mirror exists but a completed `.gitnexus/meta.json` index does
|
||||||
|
not yet, so refresh-window checks no longer look corrupted
|
||||||
|
- that message was exercised directly by temporarily withholding the
|
||||||
|
disposable index metadata and rerunning the wrapper
|
||||||
|
- the graph loop then re-proved current freshness under:
|
||||||
|
- `scripts/run-hypertwist-gitnexus-analyze.sh`
|
||||||
|
- `16,387` nodes
|
||||||
|
- `38,686` edges
|
||||||
|
- `676` clusters
|
||||||
|
- `300` flows
|
||||||
|
- `scripts/run-hypertwist-gitnexus-status.sh`
|
||||||
|
- `Indexed commit: a41d7ef`
|
||||||
|
- `Current commit: a41d7ef`
|
||||||
|
- `Status: up-to-date`
|
||||||
|
- `scripts/run-hypertwist-sentrux-source-only.sh` also stayed green at
|
||||||
|
`Quality: 6228` with all `7` rules passing
|
||||||
|
- current truthful interpretation:
|
||||||
|
- the current website/public-manual lane is not just implemented, but
|
||||||
|
revalidated at product-shaped breakpoints after the latest copy/structure
|
||||||
|
deepening work
|
||||||
|
- the HyperTwist-owned refactor/tooling posture is healthy and now clearer
|
||||||
|
for operators during GitNexus mirror refresh windows
|
||||||
|
|
||||||
|
## Latest launch-summary authority alignment follow-up (`2026-06-29`)
|
||||||
|
|
||||||
|
- the next same-family continuation stayed in the owned browser rollout lane
|
||||||
|
and corrected a real code-versus-authority mismatch
|
||||||
|
- the shared launch-status resolver in
|
||||||
|
`website/src/shared/public-launch.ts` now prefers the auth server's richer
|
||||||
|
`launch` summary when `GET /api/auth/health` provides it, instead of always
|
||||||
|
recomputing checklist, blockers, and checkout targets only from lower-level
|
||||||
|
booleans
|
||||||
|
- that means the public `/launch-status` and protected `/app/launch-status`
|
||||||
|
surfaces now directly consume server-owned launch blocker labels and current
|
||||||
|
operator/studio checkout targets when present, while still degrading safely
|
||||||
|
into bounded local derived checklist truth if the richer summary is missing
|
||||||
|
- validation stayed green under:
|
||||||
|
- `npm --prefix website run type-check`
|
||||||
|
- `npm --prefix website test -- --run src/__tests__/public-launch.test.ts src/__tests__/public-marketing-pages.test.tsx src/__tests__/protected-app-pages.test.tsx`
|
||||||
|
- `3` files passed
|
||||||
|
- `29` tests passed
|
||||||
|
- `scripts/run-hypertwist-web-surface-validation.sh`
|
||||||
|
- focused website route/auth/release validation: `13` files, `79` tests
|
||||||
|
passed
|
||||||
|
- `website/server` suite: `10` files, `36` tests passed
|
||||||
|
- `Content/Browser` shell verification and production build passed
|
||||||
|
- `website/` and `Content/Browser/` production audits stayed at
|
||||||
|
`found 0 vulnerabilities`
|
||||||
|
- `website/server/` again retained only the already-documented upstream
|
||||||
|
`supertokens-node -> nodemailer` residual advisory
|
||||||
|
- current truthful interpretation:
|
||||||
|
- the browser launch-authority lane now matches the already-declared
|
||||||
|
server-owned contract more closely instead of merely being consistent with
|
||||||
|
it by coincidence
|
||||||
|
|
||||||
|
## Latest shared public-manual helper consolidation follow-up (`2026-06-29`)
|
||||||
|
|
||||||
|
- the next same-family website quality pass stayed inside the owned public
|
||||||
|
manual lane and removed more repeated route-local section rendering
|
||||||
|
- `website/src/pages/public-page-helpers.tsx` now also owns reusable sections
|
||||||
|
for:
|
||||||
|
- simulator manual
|
||||||
|
- higher-dimensional runtime guide
|
||||||
|
- input and device posture
|
||||||
|
- control-profile roster
|
||||||
|
- runtime control guide
|
||||||
|
- the current browser-manual consumers now route those sections through:
|
||||||
|
- `website/src/pages/public-pages-marketing.tsx`
|
||||||
|
- `website/src/pages/public-pages-commerce.tsx`
|
||||||
|
- this keeps the docs/about/resources/pricing/download/getting-started family
|
||||||
|
aligned as one operator/distribution manual instead of separate near-copy
|
||||||
|
route implementations
|
||||||
|
- validation stayed green under:
|
||||||
|
- `npm --prefix website run type-check`
|
||||||
|
- `scripts/run-hypertwist-web-surface-validation.sh`
|
||||||
|
- focused website route/auth/release validation: `13` files, `79` tests
|
||||||
|
passed
|
||||||
|
- `website/server` suite: `10` files, `36` tests passed
|
||||||
|
- `Content/Browser` shell verification and production build passed
|
||||||
|
- `website/` and `Content/Browser/` production audits stayed at
|
||||||
|
`found 0 vulnerabilities`
|
||||||
|
- `website/server/` again retained only the already-documented upstream
|
||||||
|
`supertokens-node -> nodemailer` residual advisory
|
||||||
|
- the owned refactor/tooling loop also stayed healthy on the same pass:
|
||||||
|
- `scripts/run-hypertwist-sentrux-source-only.sh`
|
||||||
|
- `Quality: 6227`
|
||||||
|
- all `7` rules pass
|
||||||
|
- `scripts/run-hypertwist-gitnexus-analyze.sh`
|
||||||
|
- bounded mirror result:
|
||||||
|
- `16,389` nodes
|
||||||
|
- `38,702` edges
|
||||||
|
- `674` clusters
|
||||||
|
- `300` flows
|
||||||
|
- `scripts/run-hypertwist-gitnexus-status.sh`
|
||||||
|
- `Indexed commit: f1f5cce`
|
||||||
|
- `Current commit: f1f5cce`
|
||||||
|
- `Status: up-to-date`
|
||||||
|
|
||||||
|
## Latest protected launch-status responsive recovery plus tooling rerun (`2026-06-29`)
|
||||||
|
|
||||||
|
- the next same-family browser pass fixed a real small-screen regression on the
|
||||||
|
protected `/app/launch-status` route instead of widening scope again
|
||||||
|
- the current mobile overflow came from stacked action rows whose button links
|
||||||
|
still sized to long label text rather than the available column width
|
||||||
|
- `website/src/styles/global.css` now tightens the owned small-screen
|
||||||
|
button-row posture so stacked actions take the full column width and allow
|
||||||
|
wrapped labels instead of widening the viewport by a couple of pixels
|
||||||
|
- that correction stayed inside the existing protected browser shell and did
|
||||||
|
not alter the browser-versus-desktop product boundary
|
||||||
|
- the owned browser validation lane then re-ran fully and stayed green under:
|
||||||
|
- `scripts/run-hypertwist-web-surface-validation.sh --with-responsive-e2e`
|
||||||
|
- focused website route/auth/release validation: `13` files, `79` tests
|
||||||
|
passed
|
||||||
|
- responsive public-route Playwright proof: `22` tests passed
|
||||||
|
- responsive protected-route Playwright proof: `12` tests passed
|
||||||
|
- `website/server` suite: `10` files, `36` tests passed
|
||||||
|
- `Content/Browser` shell verification and production build passed
|
||||||
|
- `website/` and `Content/Browser/` production audits stayed at
|
||||||
|
`found 0 vulnerabilities`
|
||||||
|
- `website/server/` again retained only the already-documented upstream
|
||||||
|
`supertokens-node -> nodemailer` residual advisory
|
||||||
|
- the owned structural and graph refresh also stayed healthy on the same pass:
|
||||||
|
- `scripts/run-hypertwist-sentrux-source-only.sh`
|
||||||
|
- `Quality: 6228`
|
||||||
|
- all `7` rules pass
|
||||||
|
- `scripts/run-hypertwist-gitnexus-analyze.sh`
|
||||||
|
- bounded mirror result:
|
||||||
|
- `16,394` nodes
|
||||||
|
- `38,737` edges
|
||||||
|
- `674` clusters
|
||||||
|
- `300` flows
|
||||||
|
- `scripts/run-hypertwist-gitnexus-status.sh`
|
||||||
|
- `Indexed commit: a863f79`
|
||||||
|
- `Current commit: a863f79`
|
||||||
|
- `Status: up-to-date`
|
||||||
|
- current truthful reading after this recovery pass:
|
||||||
|
- the public and protected website/manual surfaces are still professional at
|
||||||
|
real mobile/tablet breakpoints after the recent manual widening
|
||||||
|
- the HyperTwist-owned refactor loop remains healthy enough that the next
|
||||||
|
worthwhile work continues to be native/runtime truth and product-boundary
|
||||||
|
refinement, not missing browser or analyzer hygiene
|
||||||
|
|
||||||
|
## Latest feature-atlas shared-section completion plus public legal-route responsive proof (`2026-06-29`)
|
||||||
|
|
||||||
|
- the next same-family continuation stayed inside the owned website/manual lane
|
||||||
|
and closed a remaining public-route drift-risk gap instead of widening scope
|
||||||
|
- `website/src/pages/public-pages-features.tsx` now routes the repeated manual
|
||||||
|
sections through the same shared helper ownership already used by the
|
||||||
|
broader public family:
|
||||||
|
- `HigherDimensionalRuntimeGuideSection`
|
||||||
|
- `InputAndDevicePostureSection`
|
||||||
|
- `ControlProfileRosterSection`
|
||||||
|
- `RuntimeControlGuideSection`
|
||||||
|
- this keeps the public feature atlas aligned with the surrounding
|
||||||
|
docs/resources/pricing/download/getting-started surfaces instead of leaving
|
||||||
|
`/features` on a separate near-copy structure for the same manual truth
|
||||||
|
- the same continuation then widened responsive browser proof across the
|
||||||
|
remaining public legal/reference routes:
|
||||||
|
- `/changelog`
|
||||||
|
- `/open-source-notices`
|
||||||
|
- `/privacy`
|
||||||
|
- `/terms`
|
||||||
|
- `/shipping-payment`
|
||||||
|
- a later adjacent auth-entry parity continuation then also added `/login` to
|
||||||
|
that same public matrix so both real browser account-entry routes sit under
|
||||||
|
explicit mobile/tablet proof
|
||||||
|
- the owned public responsive route matrix therefore now covers:
|
||||||
|
- homepage
|
||||||
|
- features
|
||||||
|
- about
|
||||||
|
- resources
|
||||||
|
- docs
|
||||||
|
- pricing
|
||||||
|
- download
|
||||||
|
- getting-started
|
||||||
|
- launch-status
|
||||||
|
- support
|
||||||
|
- changelog
|
||||||
|
- open-source-notices
|
||||||
|
- privacy
|
||||||
|
- terms
|
||||||
|
- shipping-payment
|
||||||
|
- login
|
||||||
|
- register
|
||||||
|
- validation stayed green under:
|
||||||
|
- `scripts/run-hypertwist-web-surface-validation.sh --with-responsive-e2e`
|
||||||
|
- focused website route/auth/release validation: `13` files, `79` tests
|
||||||
|
passed
|
||||||
|
- responsive public-route Playwright proof: `34` tests passed
|
||||||
|
- responsive protected-route Playwright proof: `12` tests passed
|
||||||
|
- `website/server` suite: `10` files, `36` tests passed
|
||||||
|
- `Content/Browser` shell verification and production build passed
|
||||||
|
- `website/` and `Content/Browser/` production audits stayed at
|
||||||
|
`found 0 vulnerabilities`
|
||||||
|
- `website/server/` again retained only the already-documented upstream
|
||||||
|
`supertokens-node -> nodemailer` residual advisory
|
||||||
|
- current truthful reading after this continuation:
|
||||||
|
- the feature atlas now sits on the same shared public-manual ownership path
|
||||||
|
as the surrounding major public routes
|
||||||
|
- the lower-traffic public legal/reference routes now have real
|
||||||
|
mobile/tablet browser proof instead of relying only on unit tests and
|
||||||
|
source review
|
||||||
|
|
||||||
|
## Latest hygiene-aware GitNexus status plus feature-atlas FAQ continuity (`2026-06-29`)
|
||||||
|
|
||||||
|
- the next bounded continuation stayed inside two already-open owned lanes:
|
||||||
|
the HyperTwist refactor wrapper surface and the public/manual feature-atlas
|
||||||
|
surface
|
||||||
|
- `scripts/run-hypertwist-gitnexus-status.sh` now treats a missing disposable
|
||||||
|
`.gitnexus-source-only-root/` mirror as normal post-hygiene absence in
|
||||||
|
default mode and points the operator back to
|
||||||
|
`scripts/run-hypertwist-gitnexus-analyze.sh` to recreate it
|
||||||
|
- the same wrapper now also distinguishes an interrupted or rebuilding mirror
|
||||||
|
whose `.gitnexus/meta.json` is not yet present, so a half-built analysis
|
||||||
|
root no longer looks identical to a fully cleaned one
|
||||||
|
- callers that still want fail-fast behavior can restore it with:
|
||||||
|
- `HYPERTWIST_GITNEXUS_STATUS_REQUIRE_INDEX=1`
|
||||||
|
- the adjacent public/manual follow-up then widened the public feature atlas
|
||||||
|
with an explicit capability FAQ seam so the route itself now answers the
|
||||||
|
common product-boundary questions advanced readers usually ask there:
|
||||||
|
- why the browser surface is intentionally narrower than the desktop runtime
|
||||||
|
- why HyperTwist still keeps the web product surface even though the
|
||||||
|
simulator is desktop-first
|
||||||
|
- why XR/controller completion is not yet marketed as finished
|
||||||
|
- how current control, settings, and bounded higher-dimensional continuity
|
||||||
|
should be understood
|
||||||
|
- current truthful reading after this continuation:
|
||||||
|
- the HyperTwist-owned analyzer lane now behaves more professionally after
|
||||||
|
correct hygiene instead of manufacturing a false corruption signal
|
||||||
|
- the public feature atlas is now closer to a real operator-facing manual,
|
||||||
|
not just a capability list
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -139,6 +139,11 @@ immersive settings now keep session-local recall ownership explicit, and the
|
||||||
current product story stays honest that this is real local continuity rather
|
current product story stays honest that this is real local continuity rather
|
||||||
than a finished global preferences or rebinding suite.
|
than a finished global preferences or rebinding suite.
|
||||||
|
|
||||||
|
The same-family truth pass also carried that bounded continuity and active
|
||||||
|
scene ownership into the native control-profile roster seam, so the selectable
|
||||||
|
roster truth now stays aligned with the sibling control-settings and active
|
||||||
|
runtime surfaces instead of leaving those facts implied.
|
||||||
|
|
||||||
Canonical audit note:
|
Canonical audit note:
|
||||||
|
|
||||||
- `C:\HyperTwist\docs\ops\HYPERTWIST_UNREAL_INPUT_AND_XR_COMPLETENESS_AUDIT_2026-06-22.md`
|
- `C:\HyperTwist\docs\ops\HYPERTWIST_UNREAL_INPUT_AND_XR_COMPLETENESS_AUDIT_2026-06-22.md`
|
||||||
|
|
|
||||||
88
scripts/lib-hypertwist-sentrux.sh
Normal file
88
scripts/lib-hypertwist-sentrux.sh
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
hypertwist_sentrux_repo_root() {
|
||||||
|
cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd
|
||||||
|
}
|
||||||
|
|
||||||
|
hypertwist_resolve_sentrux_command() {
|
||||||
|
local repo_root="${1:-$(hypertwist_sentrux_repo_root)}"
|
||||||
|
local repo_local_sentrux_binary="$repo_root/sentrux"
|
||||||
|
local repo_local_sentrux_windows_binary="$repo_root/sentrux.exe"
|
||||||
|
local repo_tools_sentrux_binary="$repo_root/tools/sentrux/bin/sentrux"
|
||||||
|
local repo_tools_sentrux_windows_binary="$repo_root/tools/sentrux/bin/sentrux.exe"
|
||||||
|
local bootstrap_script="$repo_root/scripts/bootstrap-hypertwist-sentrux.sh"
|
||||||
|
|
||||||
|
if [[ -n "${HYPERTWIST_SENTRUX_BINARY:-}" && -x "${HYPERTWIST_SENTRUX_BINARY}" ]]; then
|
||||||
|
printf '%s\n' "${HYPERTWIST_SENTRUX_BINARY}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -x "$repo_local_sentrux_binary" ]]; then
|
||||||
|
printf '%s\n' "$repo_local_sentrux_binary"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -x "$repo_local_sentrux_windows_binary" ]]; then
|
||||||
|
printf '%s\n' "$repo_local_sentrux_windows_binary"
|
||||||
|
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 [[ -x "$bootstrap_script" ]]; then
|
||||||
|
"$bootstrap_script" --if-missing >/dev/null 2>&1 || true
|
||||||
|
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
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
hypertwist_populate_sentrux_source_only_root() {
|
||||||
|
local repo_root="$1"
|
||||||
|
local temp_root="$2"
|
||||||
|
|
||||||
|
mkdir -p "$temp_root/.sentrux"
|
||||||
|
cp "$repo_root/.sentrux/rules.toml" "$temp_root/.sentrux/rules.toml"
|
||||||
|
|
||||||
|
local copy_targets=(
|
||||||
|
"UnrealHyperTwist/Source"
|
||||||
|
"Content/Browser/src"
|
||||||
|
"website/src"
|
||||||
|
"website/server/src"
|
||||||
|
"scripts"
|
||||||
|
)
|
||||||
|
|
||||||
|
local target=""
|
||||||
|
for target in "${copy_targets[@]}"; do
|
||||||
|
local source_path="$repo_root/$target"
|
||||||
|
if [[ ! -e "$source_path" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
local destination_path="$temp_root/$target"
|
||||||
|
mkdir -p "$(dirname "$destination_path")"
|
||||||
|
cp -R "$source_path" "$destination_path"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
@ -5,10 +5,32 @@ repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
source "$repo_root/scripts/lib-hypertwist-gitnexus.sh"
|
source "$repo_root/scripts/lib-hypertwist-gitnexus.sh"
|
||||||
local_gitnexus_cli="$repo_root/mirrors/GitNexus/gitnexus/dist/cli/index.js"
|
local_gitnexus_cli="$repo_root/mirrors/GitNexus/gitnexus/dist/cli/index.js"
|
||||||
analysis_root="$repo_root/.gitnexus-source-only-root"
|
analysis_root="$repo_root/.gitnexus-source-only-root"
|
||||||
|
analysis_meta_path="$analysis_root/.gitnexus/meta.json"
|
||||||
|
require_index="${HYPERTWIST_GITNEXUS_STATUS_REQUIRE_INDEX:-0}"
|
||||||
|
|
||||||
if [[ ! -d "$analysis_root" ]]; then
|
if [[ ! -d "$analysis_root" ]]; then
|
||||||
echo "No HyperTwist GitNexus source-only analysis root exists yet. Run scripts/run-hypertwist-gitnexus-analyze.sh first." >&2
|
message="HyperTwist GitNexus source-only analysis root is currently absent. This is normal after hygiene because .gitnexus-source-only-root is disposable. Run scripts/run-hypertwist-gitnexus-analyze.sh to recreate it before requesting status."
|
||||||
exit 1
|
if [[ "$require_index" == "1" ]]; then
|
||||||
|
echo "$message" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$message"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f "$analysis_meta_path" ]]; then
|
||||||
|
first_message="HyperTwist GitNexus source-only analysis root exists, but no completed index metadata is available yet."
|
||||||
|
second_message="This can happen during an interrupted refresh or immediately after rebuilding the disposable bounded mirror. Rerun scripts/run-hypertwist-gitnexus-analyze.sh to recreate a finished index before requesting status again."
|
||||||
|
if [[ "$require_index" == "1" ]]; then
|
||||||
|
echo "$first_message" >&2
|
||||||
|
echo "$second_message" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$first_message"
|
||||||
|
echo "$second_message"
|
||||||
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd "$analysis_root"
|
cd "$analysis_root"
|
||||||
|
|
|
||||||
88
scripts/run-hypertwist-sentrux-gate.sh
Normal file
88
scripts/run-hypertwist-sentrux-gate.sh
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
source "$repo_root/scripts/lib-hypertwist-sentrux.sh"
|
||||||
|
temp_root_parent="${TMPDIR:-/tmp}"
|
||||||
|
source_only_baseline_path="${HYPERTWIST_SENTRUX_SOURCE_ONLY_BASELINE_PATH:-$repo_root/.sentrux/source-only-baseline.json}"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage:
|
||||||
|
scripts/run-hypertwist-sentrux-gate.sh [--save]
|
||||||
|
|
||||||
|
Runs sentrux gate against the HyperTwist-owned source-only mirror.
|
||||||
|
|
||||||
|
Behavior:
|
||||||
|
--save refreshes the persisted source-only baseline at:
|
||||||
|
$source_only_baseline_path
|
||||||
|
|
||||||
|
Without --save, the wrapper restores that persisted baseline into the disposable
|
||||||
|
mirror before running the comparison gate.
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
save_mode=0
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--save)
|
||||||
|
save_mode=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown argument: $1" >&2
|
||||||
|
usage >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
sentrux_command="$(hypertwist_resolve_sentrux_command "$repo_root")" || {
|
||||||
|
echo "Unable to locate sentrux. Provide HYPERTWIST_SENTRUX_BINARY, place a repo-local sentrux binary under $repo_root/tools/sentrux/bin, add sentrux to PATH, or run scripts/bootstrap-hypertwist-sentrux.sh (set HYPERTWIST_ALLOW_SIBLING_SENTRUX_BOOTSTRAP=1 only if you intentionally want legacy sibling-repo seeding on this machine)." >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
temp_root="$(mktemp -d "${temp_root_parent%/}/hypertwist-sentrux-gate.XXXXXX")"
|
||||||
|
cleanup() {
|
||||||
|
rm -rf "$temp_root"
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
hypertwist_populate_sentrux_source_only_root "$repo_root" "$temp_root"
|
||||||
|
|
||||||
|
temp_baseline_path="$temp_root/.sentrux/baseline.json"
|
||||||
|
|
||||||
|
if [[ "$save_mode" -eq 0 ]]; then
|
||||||
|
if [[ ! -f "$source_only_baseline_path" ]]; then
|
||||||
|
echo "No HyperTwist source-only sentrux baseline exists yet at $source_only_baseline_path." >&2
|
||||||
|
echo "Run scripts/run-hypertwist-sentrux-gate.sh --save once to create the baseline before requesting a comparison gate." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cp "$source_only_baseline_path" "$temp_baseline_path"
|
||||||
|
fi
|
||||||
|
|
||||||
|
(
|
||||||
|
cd "$repo_root"
|
||||||
|
if [[ "$save_mode" -eq 1 ]]; then
|
||||||
|
"$sentrux_command" gate --save "$temp_root"
|
||||||
|
else
|
||||||
|
"$sentrux_command" gate "$temp_root"
|
||||||
|
fi
|
||||||
|
)
|
||||||
|
|
||||||
|
if [[ "$save_mode" -eq 1 ]]; then
|
||||||
|
if [[ ! -f "$temp_baseline_path" ]]; then
|
||||||
|
echo "sentrux gate --save completed but no baseline was produced at $temp_baseline_path." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$(dirname "$source_only_baseline_path")"
|
||||||
|
cp "$temp_baseline_path" "$source_only_baseline_path"
|
||||||
|
echo "Persisted HyperTwist source-only sentrux baseline to $source_only_baseline_path."
|
||||||
|
fi
|
||||||
|
|
@ -2,90 +2,22 @@
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
temp_root="${TMPDIR:-/tmp}/hypertwist-sentrux-source-only"
|
source "$repo_root/scripts/lib-hypertwist-sentrux.sh"
|
||||||
repo_local_sentrux_binary="$repo_root/sentrux"
|
temp_root_parent="${TMPDIR:-/tmp}"
|
||||||
repo_local_sentrux_windows_binary="$repo_root/sentrux.exe"
|
sentrux_command="$(hypertwist_resolve_sentrux_command "$repo_root")" || {
|
||||||
repo_tools_sentrux_binary="$repo_root/tools/sentrux/bin/sentrux"
|
|
||||||
repo_tools_sentrux_windows_binary="$repo_root/tools/sentrux/bin/sentrux.exe"
|
|
||||||
bootstrap_script="$repo_root/scripts/bootstrap-hypertwist-sentrux.sh"
|
|
||||||
|
|
||||||
resolve_sentrux_command() {
|
|
||||||
if [[ -n "${HYPERTWIST_SENTRUX_BINARY:-}" && -x "${HYPERTWIST_SENTRUX_BINARY}" ]]; then
|
|
||||||
printf '%s\n' "${HYPERTWIST_SENTRUX_BINARY}"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -x "$repo_local_sentrux_binary" ]]; then
|
|
||||||
printf '%s\n' "$repo_local_sentrux_binary"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -x "$repo_local_sentrux_windows_binary" ]]; then
|
|
||||||
printf '%s\n' "$repo_local_sentrux_windows_binary"
|
|
||||||
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 [[ -x "$bootstrap_script" ]]; then
|
|
||||||
"$bootstrap_script" --if-missing >/dev/null 2>&1 || true
|
|
||||||
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
|
|
||||||
fi
|
|
||||||
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
sentrux_command="$(resolve_sentrux_command)" || {
|
|
||||||
echo "Unable to locate sentrux. Provide HYPERTWIST_SENTRUX_BINARY, place a repo-local sentrux binary under $repo_root/tools/sentrux/bin, add sentrux to PATH, or run scripts/bootstrap-hypertwist-sentrux.sh (set HYPERTWIST_ALLOW_SIBLING_SENTRUX_BOOTSTRAP=1 only if you intentionally want legacy sibling-repo seeding on this machine)." >&2
|
echo "Unable to locate sentrux. Provide HYPERTWIST_SENTRUX_BINARY, place a repo-local sentrux binary under $repo_root/tools/sentrux/bin, add sentrux to PATH, or run scripts/bootstrap-hypertwist-sentrux.sh (set HYPERTWIST_ALLOW_SIBLING_SENTRUX_BOOTSTRAP=1 only if you intentionally want legacy sibling-repo seeding on this machine)." >&2
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
rm -rf "$temp_root"
|
temp_root="$(mktemp -d "${temp_root_parent%/}/hypertwist-sentrux-source-only.XXXXXX")"
|
||||||
mkdir -p "$temp_root/.sentrux"
|
cleanup() {
|
||||||
cp "$repo_root/.sentrux/rules.toml" "$temp_root/.sentrux/rules.toml"
|
rm -rf "$temp_root"
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
copy_targets=(
|
hypertwist_populate_sentrux_source_only_root "$repo_root" "$temp_root"
|
||||||
"UnrealHyperTwist/Source"
|
|
||||||
"Content/Browser/src"
|
|
||||||
"website/src"
|
|
||||||
"website/server/src"
|
|
||||||
"scripts"
|
|
||||||
)
|
|
||||||
|
|
||||||
for target in "${copy_targets[@]}"; do
|
|
||||||
source_path="$repo_root/$target"
|
|
||||||
if [[ ! -e "$source_path" ]]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
destination_path="$temp_root/$target"
|
|
||||||
mkdir -p "$(dirname "$destination_path")"
|
|
||||||
cp -R "$source_path" "$destination_path"
|
|
||||||
done
|
|
||||||
|
|
||||||
(
|
(
|
||||||
cd "$repo_root"
|
cd "$repo_root"
|
||||||
eval "$sentrux_command" check "$temp_root"
|
"$sentrux_command" check "$temp_root"
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -153,6 +153,7 @@ run_step \
|
||||||
src/__tests__/package-validation.test.ts \
|
src/__tests__/package-validation.test.ts \
|
||||||
src/__tests__/platform-auth.bootstrap.test.tsx \
|
src/__tests__/platform-auth.bootstrap.test.tsx \
|
||||||
src/__tests__/download-center-page.test.tsx \
|
src/__tests__/download-center-page.test.tsx \
|
||||||
|
src/__tests__/public-launch.test.ts \
|
||||||
src/__tests__/protected-app-pages.test.tsx \
|
src/__tests__/protected-app-pages.test.tsx \
|
||||||
src/__tests__/DashboardOverviewPage.test.tsx \
|
src/__tests__/DashboardOverviewPage.test.tsx \
|
||||||
src/__tests__/app-route-tree.test.tsx \
|
src/__tests__/app-route-tree.test.tsx \
|
||||||
|
|
|
||||||
|
|
@ -175,6 +175,10 @@ Repo-owned structural-tool posture:
|
||||||
- `scripts/run-hypertwist-sentrux-source-only.sh` still prefers
|
- `scripts/run-hypertwist-sentrux-source-only.sh` still prefers
|
||||||
`HYPERTWIST_SENTRUX_BINARY`, repo-local `./sentrux` or `./sentrux.exe`, then
|
`HYPERTWIST_SENTRUX_BINARY`, repo-local `./sentrux` or `./sentrux.exe`, then
|
||||||
`tools/sentrux/bin/`, then `PATH`
|
`tools/sentrux/bin/`, then `PATH`
|
||||||
|
- `scripts/run-hypertwist-sentrux-gate.sh` now gives the website lane the same
|
||||||
|
bounded source-only before/after regression loop through the HyperTwist-owned
|
||||||
|
mirror and a persisted repo baseline at
|
||||||
|
`.sentrux/source-only-baseline.json`
|
||||||
- `scripts/bootstrap-hypertwist-sentrux.sh` now keeps sibling-repo seed lookup
|
- `scripts/bootstrap-hypertwist-sentrux.sh` now keeps sibling-repo seed lookup
|
||||||
opt-in behind `HYPERTWIST_ALLOW_SIBLING_SENTRUX_BOOTSTRAP=1`, so ordinary
|
opt-in behind `HYPERTWIST_ALLOW_SIBLING_SENTRUX_BOOTSTRAP=1`, so ordinary
|
||||||
HyperTwist analyzer recovery does not silently drift back into cross-repo
|
HyperTwist analyzer recovery does not silently drift back into cross-repo
|
||||||
|
|
|
||||||
|
|
@ -227,6 +227,79 @@ describe('protected app pages', () => {
|
||||||
expect(screen.getByRole('link', { name: 'Public notices' }).getAttribute('href')).toBe('/open-source-notices')
|
expect(screen.getByRole('link', { name: 'Public notices' }).getAttribute('href')).toBe('/open-source-notices')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('uses the authoritative auth-health launch summary on the protected launch route when the server provides it', async () => {
|
||||||
|
mockGetAuthHealth.mockResolvedValue({
|
||||||
|
ok: true,
|
||||||
|
service: 'hypertwist-auth-server',
|
||||||
|
supertokens: {
|
||||||
|
configured: true,
|
||||||
|
reachable: true,
|
||||||
|
ready: true,
|
||||||
|
apiVersion: '5.0',
|
||||||
|
oauth: {
|
||||||
|
github: false,
|
||||||
|
google: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fallback: {
|
||||||
|
enabled: true,
|
||||||
|
active: false,
|
||||||
|
reason: null,
|
||||||
|
},
|
||||||
|
billing: {
|
||||||
|
statePath: '/tmp/hypertwist-billing.json',
|
||||||
|
processedEventCount: 1,
|
||||||
|
pricePlanMapConfigured: true,
|
||||||
|
productPlanMapConfigured: true,
|
||||||
|
webhookSecretConfigured: true,
|
||||||
|
},
|
||||||
|
runtime: {
|
||||||
|
mode: 'public',
|
||||||
|
public_origin_ready: true,
|
||||||
|
cookie_secure: true,
|
||||||
|
api_domain: 'https://hypertwist.app',
|
||||||
|
website_domain: 'https://hypertwist.app',
|
||||||
|
warnings: [],
|
||||||
|
errors: [],
|
||||||
|
},
|
||||||
|
launch: {
|
||||||
|
posture: 'preview',
|
||||||
|
ready: false,
|
||||||
|
readiness: {
|
||||||
|
windowsDownloadConfigured: true,
|
||||||
|
operatorCheckoutConfigured: true,
|
||||||
|
studioCheckoutConfigured: true,
|
||||||
|
mplSourceConfigured: true,
|
||||||
|
openSourceRepoConfigured: true,
|
||||||
|
billingProductPlanMapConfigured: true,
|
||||||
|
billingPricePlanMapConfigured: true,
|
||||||
|
billingWebhookSecretConfigured: true,
|
||||||
|
publicAuthRuntimeReady: true,
|
||||||
|
},
|
||||||
|
checklist: [
|
||||||
|
{
|
||||||
|
id: 'windows-download',
|
||||||
|
label: 'Windows release authority',
|
||||||
|
configured: true,
|
||||||
|
requiredForPublicLaunch: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
missingLabels: ['preview-tier launch gate'],
|
||||||
|
targets: {
|
||||||
|
operatorCheckoutTarget: 'https://buy.paddle.com/operator-authoritative',
|
||||||
|
studioCheckoutTarget: 'https://buy.paddle.com/studio-authoritative',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
renderPage(<ProtectedLaunchStatusPage />, '/app/launch-status')
|
||||||
|
|
||||||
|
expect(await screen.findByText('Windows release authority: configured')).toBeTruthy()
|
||||||
|
expect(screen.getByText('Operator checkout target: https://buy.paddle.com/operator-authoritative')).toBeTruthy()
|
||||||
|
expect(screen.getByText('Studio checkout target: https://buy.paddle.com/studio-authoritative')).toBeTruthy()
|
||||||
|
expect(screen.getByText(/Public launch is not fully configured yet: preview-tier launch gate\./i)).toBeTruthy()
|
||||||
|
})
|
||||||
|
|
||||||
it('keeps the protected download center aligned with packaged proof, notices, and escalation guidance', async () => {
|
it('keeps the protected download center aligned with packaged proof, notices, and escalation guidance', async () => {
|
||||||
renderPage(<DownloadCenterPage />, '/app/downloads?platform=windows')
|
renderPage(<DownloadCenterPage />, '/app/downloads?platform=windows')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import {
|
||||||
getMissingPublicLaunchChecklistItems,
|
getMissingPublicLaunchChecklistItems,
|
||||||
getPublicLaunchChecklist,
|
getPublicLaunchChecklist,
|
||||||
isPublicLaunchReady,
|
isPublicLaunchReady,
|
||||||
|
resolvePublicLaunchStatusSummary,
|
||||||
} from '../public-launch'
|
} from '../public-launch'
|
||||||
|
|
||||||
describe('public launch readiness helpers', () => {
|
describe('public launch readiness helpers', () => {
|
||||||
|
|
@ -65,4 +66,123 @@ describe('public launch readiness helpers', () => {
|
||||||
publicAuthRuntimeReady: true,
|
publicAuthRuntimeReady: true,
|
||||||
})).toBe(true)
|
})).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('prefers the authoritative auth-health launch summary when the server already resolved rollout posture', () => {
|
||||||
|
const launchStatus = resolvePublicLaunchStatusSummary(
|
||||||
|
{
|
||||||
|
ok: true,
|
||||||
|
service: 'hypertwist-auth-server',
|
||||||
|
supertokens: {
|
||||||
|
configured: true,
|
||||||
|
reachable: true,
|
||||||
|
ready: true,
|
||||||
|
},
|
||||||
|
fallback: {
|
||||||
|
enabled: true,
|
||||||
|
active: false,
|
||||||
|
reason: null,
|
||||||
|
},
|
||||||
|
billing: {
|
||||||
|
statePath: '/tmp/hypertwist-billing.json',
|
||||||
|
processedEventCount: 3,
|
||||||
|
pricePlanMapConfigured: true,
|
||||||
|
productPlanMapConfigured: true,
|
||||||
|
webhookSecretConfigured: true,
|
||||||
|
},
|
||||||
|
runtime: {
|
||||||
|
mode: 'public',
|
||||||
|
public_origin_ready: true,
|
||||||
|
cookie_secure: true,
|
||||||
|
api_domain: 'https://hypertwist.app',
|
||||||
|
website_domain: 'https://hypertwist.app',
|
||||||
|
warnings: [],
|
||||||
|
errors: [],
|
||||||
|
},
|
||||||
|
launch: {
|
||||||
|
posture: 'preview',
|
||||||
|
ready: false,
|
||||||
|
readiness: {
|
||||||
|
windowsDownloadConfigured: true,
|
||||||
|
macosDownloadConfigured: false,
|
||||||
|
linuxDownloadConfigured: false,
|
||||||
|
operatorCheckoutConfigured: true,
|
||||||
|
studioCheckoutConfigured: true,
|
||||||
|
mplSourceConfigured: true,
|
||||||
|
openSourceRepoConfigured: true,
|
||||||
|
billingProductPlanMapConfigured: true,
|
||||||
|
billingPricePlanMapConfigured: true,
|
||||||
|
billingWebhookSecretConfigured: true,
|
||||||
|
publicAuthRuntimeReady: true,
|
||||||
|
},
|
||||||
|
checklist: [
|
||||||
|
{
|
||||||
|
id: 'windows-download',
|
||||||
|
label: 'Windows release authority',
|
||||||
|
configured: true,
|
||||||
|
requiredForPublicLaunch: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
missingLabels: ['preview-tier launch gate'],
|
||||||
|
targets: {
|
||||||
|
operatorCheckoutTarget: 'https://buy.paddle.com/operator-authoritative',
|
||||||
|
studioCheckoutTarget: 'https://buy.paddle.com/studio-authoritative',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
generated_at: '2026-06-29T12:00:00.000Z',
|
||||||
|
support_email: 'hello@hypertwist.app',
|
||||||
|
public_docs_url: 'https://docs.hypertwist.app',
|
||||||
|
release_notes_url: 'https://notes.hypertwist.app',
|
||||||
|
platforms: [
|
||||||
|
{
|
||||||
|
platform_key: 'windows',
|
||||||
|
platform: 'Windows',
|
||||||
|
subtitle: 'Primary shipping lane',
|
||||||
|
details: 'Current packaged validation is strongest on the Windows Unreal lane.',
|
||||||
|
configured: true,
|
||||||
|
channel: 'preview',
|
||||||
|
version: null,
|
||||||
|
build_id: null,
|
||||||
|
published_at: null,
|
||||||
|
file_name: null,
|
||||||
|
file_size_bytes: null,
|
||||||
|
checksum_sha256: null,
|
||||||
|
download_url: null,
|
||||||
|
download_available: false,
|
||||||
|
validation_summary: null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
commerce: {
|
||||||
|
operator_checkout_url: null,
|
||||||
|
studio_checkout_url: null,
|
||||||
|
plan_price_operator: 'Launch pricing via Paddle',
|
||||||
|
plan_price_studio: 'Contact for launch readiness',
|
||||||
|
},
|
||||||
|
corresponding_source_url: null,
|
||||||
|
open_source_repo_url: null,
|
||||||
|
viewer: {
|
||||||
|
authenticated: false,
|
||||||
|
canDownload: false,
|
||||||
|
plan: null,
|
||||||
|
role: null,
|
||||||
|
accessStatus: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
windowsDownloadConfigured: true,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(launchStatus.ready).toBe(false)
|
||||||
|
expect(launchStatus.posture).toBe('preview')
|
||||||
|
expect(launchStatus.missingLabels).toEqual(['preview-tier launch gate'])
|
||||||
|
expect(launchStatus.targets).toEqual({
|
||||||
|
operatorCheckoutTarget: 'https://buy.paddle.com/operator-authoritative',
|
||||||
|
studioCheckoutTarget: 'https://buy.paddle.com/studio-authoritative',
|
||||||
|
})
|
||||||
|
expect(launchStatus.checklist.find((item) => item.id === 'windows-download')?.label).toBe('Windows release authority')
|
||||||
|
expect(launchStatus.readiness.operatorCheckoutConfigured).toBe(true)
|
||||||
|
expect(launchStatus.readiness.publicAuthRuntimeReady).toBe(true)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -268,6 +268,9 @@ describe('public marketing pages', () => {
|
||||||
expect(screen.getByText('Operator checkout URL: missing')).toBeTruthy()
|
expect(screen.getByText('Operator checkout URL: missing')).toBeTruthy()
|
||||||
expect(screen.getByText('Current packaged desktop proof')).toBeTruthy()
|
expect(screen.getByText('Current packaged desktop proof')).toBeTruthy()
|
||||||
expect(screen.getByText('How the release lane works')).toBeTruthy()
|
expect(screen.getByText('How the release lane works')).toBeTruthy()
|
||||||
|
expect(screen.getByText('What the installed runtime already owns')).toBeTruthy()
|
||||||
|
expect(screen.getByText('Higher-dimensional family guide')).toBeTruthy()
|
||||||
|
expect(screen.getByText('Current input and runtime control truth')).toBeTruthy()
|
||||||
expect(screen.getByText('Why HyperTwist keeps both a website and a desktop runtime')).toBeTruthy()
|
expect(screen.getByText('Why HyperTwist keeps both a website and a desktop runtime')).toBeTruthy()
|
||||||
expect(screen.getByText('Why the browser is intentionally narrower')).toBeTruthy()
|
expect(screen.getByText('Why the browser is intentionally narrower')).toBeTruthy()
|
||||||
expect(screen.getByRole('heading', { name: 'Browser account access methods' })).toBeTruthy()
|
expect(screen.getByRole('heading', { name: 'Browser account access methods' })).toBeTruthy()
|
||||||
|
|
@ -293,6 +296,10 @@ describe('public marketing pages', () => {
|
||||||
expect(screen.getByRole('link', { name: 'https://docs.hypertwist.app' })).toBeTruthy()
|
expect(screen.getByRole('link', { name: 'https://docs.hypertwist.app' })).toBeTruthy()
|
||||||
expect(screen.getByRole('link', { name: 'https://notes.hypertwist.app' })).toBeTruthy()
|
expect(screen.getByRole('link', { name: 'https://notes.hypertwist.app' })).toBeTruthy()
|
||||||
expect(screen.getByText('Pair desktop access to the browser account')).toBeTruthy()
|
expect(screen.getByText('Pair desktop access to the browser account')).toBeTruthy()
|
||||||
|
expect(screen.getByText('Higher-dimensional runtime ownership')).toBeTruthy()
|
||||||
|
expect(screen.getByText('Magic120Cell packaged runtime')).toBeTruthy()
|
||||||
|
expect(screen.getByText('Current input and runtime control truth')).toBeTruthy()
|
||||||
|
expect(screen.getByText('Native diagnostics check')).toBeTruthy()
|
||||||
expect(await screen.findByText('Version: 1.0.0')).toBeTruthy()
|
expect(await screen.findByText('Version: 1.0.0')).toBeTruthy()
|
||||||
expect(screen.getByText('SHA-256: abc123')).toBeTruthy()
|
expect(screen.getByText('SHA-256: abc123')).toBeTruthy()
|
||||||
expect(screen.getAllByText('Packaged validation passed').length).toBeGreaterThan(0)
|
expect(screen.getAllByText('Packaged validation passed').length).toBeGreaterThan(0)
|
||||||
|
|
@ -714,6 +721,11 @@ describe('public marketing pages', () => {
|
||||||
expect(screen.getByText('Current shipped capability')).toBeTruthy()
|
expect(screen.getByText('Current shipped capability')).toBeTruthy()
|
||||||
expect(screen.getByText('Current selectable control roster')).toBeTruthy()
|
expect(screen.getByText('Current selectable control roster')).toBeTruthy()
|
||||||
expect(screen.getAllByText('Selectable immersive and family-specific settings').length).toBeGreaterThan(0)
|
expect(screen.getAllByText('Selectable immersive and family-specific settings').length).toBeGreaterThan(0)
|
||||||
|
expect(screen.getByText('Runtime control guide')).toBeTruthy()
|
||||||
|
expect(screen.getByText('Native diagnostics check')).toBeTruthy()
|
||||||
|
expect(screen.getByText('Common capability questions')).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('Current public rollout posture')).toBeTruthy()
|
expect(screen.getByText('Current public rollout posture')).toBeTruthy()
|
||||||
expect(screen.getByText('Public feature and launch posture')).toBeTruthy()
|
expect(screen.getByText('Public feature and launch posture')).toBeTruthy()
|
||||||
const featuresDecisionGuideHeading = screen.getByRole('heading', { name: 'Choose the next release move' })
|
const featuresDecisionGuideHeading = screen.getByRole('heading', { name: 'Choose the next release move' })
|
||||||
|
|
@ -897,6 +909,9 @@ describe('public marketing pages', () => {
|
||||||
expect(screen.getByText('$99 / month')).toBeTruthy()
|
expect(screen.getByText('$99 / month')).toBeTruthy()
|
||||||
expect(screen.getByText('Current packaged desktop proof')).toBeTruthy()
|
expect(screen.getByText('Current packaged desktop proof')).toBeTruthy()
|
||||||
expect(screen.getAllByText('What happens after access is granted').length).toBeGreaterThan(0)
|
expect(screen.getAllByText('What happens after access is granted').length).toBeGreaterThan(0)
|
||||||
|
expect(screen.getByText('What the software actually does after access is granted')).toBeTruthy()
|
||||||
|
expect(screen.getByText('Higher-dimensional families behind the plans')).toBeTruthy()
|
||||||
|
expect(screen.getAllByText('Current input and runtime control truth').length).toBeGreaterThan(0)
|
||||||
expect(screen.getByText('Choose the right HyperTwist surface')).toBeTruthy()
|
expect(screen.getByText('Choose the right HyperTwist surface')).toBeTruthy()
|
||||||
const pricingDecisionGuideHeading = screen.getByRole('heading', { name: 'Choose the next release move' })
|
const pricingDecisionGuideHeading = screen.getByRole('heading', { name: 'Choose the next release move' })
|
||||||
const pricingDecisionGuideSection = pricingDecisionGuideHeading.closest('section')
|
const pricingDecisionGuideSection = pricingDecisionGuideHeading.closest('section')
|
||||||
|
|
@ -916,6 +931,10 @@ describe('public marketing pages', () => {
|
||||||
expect(screen.getByText('Owns recognition, replay, coaching, and packaged training behavior')).toBeTruthy()
|
expect(screen.getByText('Owns recognition, replay, coaching, and packaged training behavior')).toBeTruthy()
|
||||||
expect(screen.getByText('Commercial distribution doctrine')).toBeTruthy()
|
expect(screen.getByText('Commercial distribution doctrine')).toBeTruthy()
|
||||||
expect(screen.getByText('Public pages are distribution surfaces')).toBeTruthy()
|
expect(screen.getByText('Public pages are distribution surfaces')).toBeTruthy()
|
||||||
|
expect(screen.getByText('Higher-dimensional runtime ownership')).toBeTruthy()
|
||||||
|
expect(screen.getByText('MagicTile embedded-browser runtime')).toBeTruthy()
|
||||||
|
expect(screen.getByText('XR groundwork exists, but the full VR lane is not finished')).toBeTruthy()
|
||||||
|
expect(screen.getByText('Native diagnostics check')).toBeTruthy()
|
||||||
expect(screen.getByText('Release references and source availability')).toBeTruthy()
|
expect(screen.getByText('Release references and source availability')).toBeTruthy()
|
||||||
expect(screen.getByRole('link', { name: 'https://docs.hypertwist.app' })).toBeTruthy()
|
expect(screen.getByRole('link', { name: 'https://docs.hypertwist.app' })).toBeTruthy()
|
||||||
expect(screen.getByRole('link', { name: 'https://notes.hypertwist.app' })).toBeTruthy()
|
expect(screen.getByRole('link', { name: 'https://notes.hypertwist.app' })).toBeTruthy()
|
||||||
|
|
@ -1330,7 +1349,7 @@ describe('public marketing pages', () => {
|
||||||
expect(screen.getByRole('link', { name: 'Review public notices' }).getAttribute('href')).toBe('/open-source-notices')
|
expect(screen.getByRole('link', { name: 'Review public notices' }).getAttribute('href')).toBe('/open-source-notices')
|
||||||
expect(screen.getByText('Common operator questions')).toBeTruthy()
|
expect(screen.getByText('Common operator questions')).toBeTruthy()
|
||||||
expect(screen.getByText('If the desktop app is primary, why keep the web version?')).toBeTruthy()
|
expect(screen.getByText('If the desktop app is primary, why keep the web version?')).toBeTruthy()
|
||||||
expect(screen.getByText(/intentionally narrower than the simulator for training and device\/runtime work/i)).toBeTruthy()
|
expect(screen.getByText(/it does not own package-validated training behavior, low-latency native input, higher-dimensional packaged execution, or device\/runtime integration authority/i)).toBeTruthy()
|
||||||
expect(screen.getByText('Packaged validation passed')).toBeTruthy()
|
expect(screen.getByText('Packaged validation passed')).toBeTruthy()
|
||||||
expect(screen.getByText('Release references and source availability')).toBeTruthy()
|
expect(screen.getByText('Release references and source availability')).toBeTruthy()
|
||||||
expect(screen.getByRole('link', { name: 'https://docs.hypertwist.app' })).toBeTruthy()
|
expect(screen.getByRole('link', { name: 'https://docs.hypertwist.app' })).toBeTruthy()
|
||||||
|
|
@ -1438,8 +1457,11 @@ describe('public marketing pages', () => {
|
||||||
expect(screen.getByText('Browser account access methods')).toBeTruthy()
|
expect(screen.getByText('Browser account access methods')).toBeTruthy()
|
||||||
expect(screen.getByText('First launch and desktop setup')).toBeTruthy()
|
expect(screen.getByText('First launch and desktop setup')).toBeTruthy()
|
||||||
expect(screen.getByText('Simulator use today')).toBeTruthy()
|
expect(screen.getByText('Simulator use today')).toBeTruthy()
|
||||||
|
expect(screen.getByText('Higher-dimensional family guide')).toBeTruthy()
|
||||||
expect(screen.getByText('Current control and device truth')).toBeTruthy()
|
expect(screen.getByText('Current control and device truth')).toBeTruthy()
|
||||||
expect(screen.getAllByText('Selectable control and settings roster').length).toBeGreaterThan(0)
|
expect(screen.getAllByText('Selectable control and settings roster').length).toBeGreaterThan(0)
|
||||||
|
expect(screen.getByText('Runtime control guide')).toBeTruthy()
|
||||||
|
expect(screen.getByText('Native diagnostics check')).toBeTruthy()
|
||||||
expect(screen.getByText('Choose the right HyperTwist surface')).toBeTruthy()
|
expect(screen.getByText('Choose the right HyperTwist surface')).toBeTruthy()
|
||||||
expect(screen.getByText('Current packaged desktop proof')).toBeTruthy()
|
expect(screen.getByText('Current packaged desktop proof')).toBeTruthy()
|
||||||
expect(screen.getByText('Need help on the way in?')).toBeTruthy()
|
expect(screen.getByText('Need help on the way in?')).toBeTruthy()
|
||||||
|
|
@ -1682,6 +1704,142 @@ describe('public marketing pages', () => {
|
||||||
expect(document.head.querySelector('meta[property=\"og:url\"]')?.getAttribute('content')).toBe('https://hypertwist.app/changelog')
|
expect(document.head.querySelector('meta[property=\"og:url\"]')?.getAttribute('content')).toBe('https://hypertwist.app/changelog')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('uses the authoritative auth-health launch summary on the public launch-status route when the server provides it', async () => {
|
||||||
|
mockGetAuthHealth.mockResolvedValue({
|
||||||
|
ok: true,
|
||||||
|
service: 'hypertwist-auth-server',
|
||||||
|
supertokens: {
|
||||||
|
configured: true,
|
||||||
|
reachable: true,
|
||||||
|
ready: true,
|
||||||
|
apiVersion: '5.4',
|
||||||
|
error: null,
|
||||||
|
oauth: {
|
||||||
|
github: false,
|
||||||
|
google: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fallback: {
|
||||||
|
enabled: true,
|
||||||
|
active: false,
|
||||||
|
reason: null,
|
||||||
|
},
|
||||||
|
billing: {
|
||||||
|
statePath: '/var/lib/hypertwist/auth/hypertwist-billing-state.json',
|
||||||
|
processedEventCount: 2,
|
||||||
|
pricePlanMapConfigured: true,
|
||||||
|
productPlanMapConfigured: true,
|
||||||
|
webhookSecretConfigured: true,
|
||||||
|
},
|
||||||
|
runtime: {
|
||||||
|
mode: 'public',
|
||||||
|
public_origin_ready: true,
|
||||||
|
cookie_secure: true,
|
||||||
|
api_domain: 'https://hypertwist.app',
|
||||||
|
website_domain: 'https://hypertwist.app',
|
||||||
|
warnings: [],
|
||||||
|
errors: [],
|
||||||
|
},
|
||||||
|
launch: {
|
||||||
|
posture: 'preview',
|
||||||
|
ready: false,
|
||||||
|
readiness: {
|
||||||
|
windowsDownloadConfigured: true,
|
||||||
|
operatorCheckoutConfigured: true,
|
||||||
|
studioCheckoutConfigured: true,
|
||||||
|
mplSourceConfigured: true,
|
||||||
|
openSourceRepoConfigured: true,
|
||||||
|
billingProductPlanMapConfigured: true,
|
||||||
|
billingPricePlanMapConfigured: true,
|
||||||
|
billingWebhookSecretConfigured: true,
|
||||||
|
publicAuthRuntimeReady: true,
|
||||||
|
},
|
||||||
|
checklist: [
|
||||||
|
{
|
||||||
|
id: 'windows-download',
|
||||||
|
label: 'Windows release authority',
|
||||||
|
configured: true,
|
||||||
|
requiredForPublicLaunch: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
missingLabels: ['preview-tier launch gate'],
|
||||||
|
targets: {
|
||||||
|
operatorCheckoutTarget: 'https://buy.paddle.com/operator-authoritative',
|
||||||
|
studioCheckoutTarget: 'https://buy.paddle.com/studio-authoritative',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
mockGetReleaseManifest.mockResolvedValue({
|
||||||
|
ok: true,
|
||||||
|
manifest: {
|
||||||
|
generated_at: '2026-06-29T12:00:00.000Z',
|
||||||
|
support_email: 'hello@hypertwist.app',
|
||||||
|
public_docs_url: 'https://docs.hypertwist.app',
|
||||||
|
release_notes_url: 'https://notes.hypertwist.app',
|
||||||
|
corresponding_source_url: null,
|
||||||
|
open_source_repo_url: null,
|
||||||
|
commerce: {
|
||||||
|
operator_checkout_url: null,
|
||||||
|
studio_checkout_url: null,
|
||||||
|
plan_price_operator: '$29 / month',
|
||||||
|
plan_price_studio: '$99 / month',
|
||||||
|
},
|
||||||
|
viewer: {
|
||||||
|
authenticated: false,
|
||||||
|
canDownload: false,
|
||||||
|
plan: null,
|
||||||
|
role: null,
|
||||||
|
accessStatus: null,
|
||||||
|
},
|
||||||
|
platforms: [
|
||||||
|
{
|
||||||
|
platform_key: 'windows',
|
||||||
|
platform: 'Windows',
|
||||||
|
subtitle: 'Primary shipping lane',
|
||||||
|
details: 'Current packaged validation is strongest on the Windows Unreal lane.',
|
||||||
|
configured: true,
|
||||||
|
channel: 'preview',
|
||||||
|
version: '1.0.0',
|
||||||
|
build_id: 'win64-1000',
|
||||||
|
published_at: '2026-06-29T00:00:00.000Z',
|
||||||
|
file_name: 'HyperTwist-Windows.zip',
|
||||||
|
file_size_bytes: 1048576,
|
||||||
|
checksum_sha256: 'abc123',
|
||||||
|
download_url: null,
|
||||||
|
download_available: false,
|
||||||
|
validation_summary: {
|
||||||
|
lane: 'Windows Unreal packaged validation',
|
||||||
|
result: 'passed',
|
||||||
|
generated_at: '2026-06-29T01:43:08.7625247Z',
|
||||||
|
configuration: 'Development',
|
||||||
|
skip_build: true,
|
||||||
|
smoke_map_count: 2,
|
||||||
|
smoke_maps: [
|
||||||
|
{
|
||||||
|
map_url: '/Game/HyperTwistTraining/Maps/L_HyperTwist_Magic120CellTraining',
|
||||||
|
label: 'Magic120Cell dedicated-family training map',
|
||||||
|
result: 'passed',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
map_url: '/Game/HyperTwistTraining/Maps/L_HyperTwist_MagicCube5DTraining',
|
||||||
|
label: 'MagicCube5D dedicated-family training map',
|
||||||
|
result: 'passed',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
renderWithProviders(<LaunchStatusPage />, ['/launch-status'])
|
||||||
|
|
||||||
|
expect(await screen.findByText(/external launch still needs preview-tier launch gate/i)).toBeTruthy()
|
||||||
|
expect(screen.getByText('Windows release authority: configured')).toBeTruthy()
|
||||||
|
expect(screen.getByText('Operator checkout target: https://buy.paddle.com/operator-authoritative')).toBeTruthy()
|
||||||
|
expect(screen.getByText('Studio checkout target: https://buy.paddle.com/studio-authoritative')).toBeTruthy()
|
||||||
|
})
|
||||||
|
|
||||||
it('renders the expanded legal and digital-delivery guidance across public support surfaces', async () => {
|
it('renders the expanded legal and digital-delivery guidance across public support surfaces', async () => {
|
||||||
mockGetAuthHealth.mockResolvedValue({
|
mockGetAuthHealth.mockResolvedValue({
|
||||||
ok: true,
|
ok: true,
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,14 @@ import {
|
||||||
} from '../site-config'
|
} from '../site-config'
|
||||||
import {
|
import {
|
||||||
browserDesktopRealityCards,
|
browserDesktopRealityCards,
|
||||||
|
controlProfileRosterCards,
|
||||||
deliverySurfaceCards,
|
deliverySurfaceCards,
|
||||||
|
higherDimensionalRuntimeGuideCards,
|
||||||
|
inputAndDevicePostureCards,
|
||||||
operatorDesktopQuickstartCards,
|
operatorDesktopQuickstartCards,
|
||||||
publicManualRouteAtlasCards,
|
publicManualRouteAtlasCards,
|
||||||
|
runtimeControlGuideCards,
|
||||||
|
simulatorManualCards,
|
||||||
} from '../site-data'
|
} from '../site-data'
|
||||||
import {
|
import {
|
||||||
buildLoginPath,
|
buildLoginPath,
|
||||||
|
|
@ -159,6 +164,28 @@ type StepOnlyCard = {
|
||||||
bullets?: readonly string[]
|
bullets?: readonly string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PrincipleCard = {
|
||||||
|
title: string
|
||||||
|
description: string
|
||||||
|
}
|
||||||
|
|
||||||
|
type BulletCard = {
|
||||||
|
title: string
|
||||||
|
description: string
|
||||||
|
bullets: readonly string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
type StepCard = {
|
||||||
|
title: string
|
||||||
|
description: string
|
||||||
|
steps: readonly string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
type FaqCard = {
|
||||||
|
question: string
|
||||||
|
answer: string
|
||||||
|
}
|
||||||
|
|
||||||
type SupportTopicCard = (typeof supportTopicDirectory)[number]
|
type SupportTopicCard = (typeof supportTopicDirectory)[number]
|
||||||
|
|
||||||
type PublicManualRouteAtlasCard = (typeof publicManualRouteAtlasCards)[number]
|
type PublicManualRouteAtlasCard = (typeof publicManualRouteAtlasCards)[number]
|
||||||
|
|
@ -350,6 +377,159 @@ export function OperatorDesktopQuickstartSection({
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function PrincipleCardSection({
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
cards,
|
||||||
|
}: {
|
||||||
|
title: string
|
||||||
|
description?: string
|
||||||
|
cards: readonly PrincipleCard[]
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Section title={title} description={description}>
|
||||||
|
<div className="card-grid">
|
||||||
|
{cards.map((card) => (
|
||||||
|
<article key={card.title} className="card">
|
||||||
|
<h3>{card.title}</h3>
|
||||||
|
<p>{card.description}</p>
|
||||||
|
</article>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</Section>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SimulatorManualSection({
|
||||||
|
title = 'Simulator manual',
|
||||||
|
description = 'These are the current product-safe usage tracks for the native runtime itself.',
|
||||||
|
}: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
}) {
|
||||||
|
return <BulletCardSection title={title} description={description} cards={simulatorManualCards} />
|
||||||
|
}
|
||||||
|
|
||||||
|
export function HigherDimensionalRuntimeGuideSection({
|
||||||
|
title = 'Higher-dimensional family guide',
|
||||||
|
description = 'These are the currently represented higher-dimensional lanes and the truthful host/runtime posture for each.',
|
||||||
|
}: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<BulletCardSection
|
||||||
|
title={title}
|
||||||
|
description={description}
|
||||||
|
cards={higherDimensionalRuntimeGuideCards}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function InputAndDevicePostureSection({
|
||||||
|
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.',
|
||||||
|
}: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<BulletCardSection
|
||||||
|
title={title}
|
||||||
|
description={description}
|
||||||
|
cards={inputAndDevicePostureCards}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ControlProfileRosterSection({
|
||||||
|
title = 'Selectable control and settings roster',
|
||||||
|
description = 'This manual section answers the concrete user question: what settings, profiles, selectors, and persistence surfaces are already real today?',
|
||||||
|
}: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<BulletCardSection
|
||||||
|
title={title}
|
||||||
|
description={description}
|
||||||
|
cards={controlProfileRosterCards}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function RuntimeControlGuideSection({
|
||||||
|
title = 'Runtime control guide',
|
||||||
|
description = 'This manual section explains how to approach the current desktop runtime without pretending the currently closed XR/controller branch has already been reopened.',
|
||||||
|
}: {
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<BulletCardSection
|
||||||
|
title={title}
|
||||||
|
description={description}
|
||||||
|
cards={runtimeControlGuideCards}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function BulletCardSection({
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
cards,
|
||||||
|
}: {
|
||||||
|
title: string
|
||||||
|
description?: string
|
||||||
|
cards: readonly BulletCard[]
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Section title={title} description={description}>
|
||||||
|
<div className="card-grid">
|
||||||
|
{cards.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>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function StepCardSection({
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
cards,
|
||||||
|
}: {
|
||||||
|
title: string
|
||||||
|
description?: string
|
||||||
|
cards: readonly StepCard[]
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Section title={title} description={description}>
|
||||||
|
<div className="card-grid">
|
||||||
|
{cards.map((card) => (
|
||||||
|
<article key={card.title} className="card">
|
||||||
|
<h3>{card.title}</h3>
|
||||||
|
<p>{card.description}</p>
|
||||||
|
<ul className="list top-gap">
|
||||||
|
{card.steps.map((step) => (
|
||||||
|
<li key={step}>{step}</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</article>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</Section>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export function StepOnlyCardSection({
|
export function StepOnlyCardSection({
|
||||||
title,
|
title,
|
||||||
description,
|
description,
|
||||||
|
|
@ -377,6 +557,29 @@ export function StepOnlyCardSection({
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function FaqCardSection({
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
cards,
|
||||||
|
}: {
|
||||||
|
title: string
|
||||||
|
description?: string
|
||||||
|
cards: readonly FaqCard[]
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Section title={title} description={description}>
|
||||||
|
<div className="card-grid">
|
||||||
|
{cards.map((card) => (
|
||||||
|
<article key={card.question} className="card">
|
||||||
|
<h3>{card.question}</h3>
|
||||||
|
<p>{card.answer}</p>
|
||||||
|
</article>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</Section>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export function SupportTopicDirectorySection({
|
export function SupportTopicDirectorySection({
|
||||||
title,
|
title,
|
||||||
description,
|
description,
|
||||||
|
|
|
||||||
|
|
@ -15,19 +15,23 @@ import {
|
||||||
desktopReleaseSignals,
|
desktopReleaseSignals,
|
||||||
digitalDeliveryCards,
|
digitalDeliveryCards,
|
||||||
distributionDoctrineCards,
|
distributionDoctrineCards,
|
||||||
|
inputAndDevicePostureCards,
|
||||||
openSourceNotices,
|
openSourceNotices,
|
||||||
operatorManualTracks,
|
operatorManualTracks,
|
||||||
privacyBoundaryCards,
|
privacyBoundaryCards,
|
||||||
productSurfaceMatrixRows,
|
productSurfaceMatrixRows,
|
||||||
releaseRolloutChecklist,
|
releaseRolloutChecklist,
|
||||||
|
runtimeControlGuideCards,
|
||||||
supportEscalationCards,
|
supportEscalationCards,
|
||||||
termsBoundaryCards,
|
termsBoundaryCards,
|
||||||
} from '../site-data'
|
} from '../site-data'
|
||||||
import {
|
import {
|
||||||
|
BulletCardSection,
|
||||||
BrowserAuthMethodsSection,
|
BrowserAuthMethodsSection,
|
||||||
BrowserDesktopRealitySection,
|
BrowserDesktopRealitySection,
|
||||||
DeliverySurfaceResponsibilitiesGrid,
|
DeliverySurfaceResponsibilitiesGrid,
|
||||||
explorerFallbackPlan,
|
explorerFallbackPlan,
|
||||||
|
HigherDimensionalRuntimeGuideSection,
|
||||||
OperatorDesktopQuickstartSection,
|
OperatorDesktopQuickstartSection,
|
||||||
operatorFallbackPlan,
|
operatorFallbackPlan,
|
||||||
PlanActionLink,
|
PlanActionLink,
|
||||||
|
|
@ -36,6 +40,8 @@ import {
|
||||||
ReleaseAuthorityBundleSection,
|
ReleaseAuthorityBundleSection,
|
||||||
releaseCommerceFallback,
|
releaseCommerceFallback,
|
||||||
Section,
|
Section,
|
||||||
|
SimulatorManualSection,
|
||||||
|
StepCardSection,
|
||||||
studioFallbackPlan,
|
studioFallbackPlan,
|
||||||
SurfaceChoiceGuideSection,
|
SurfaceChoiceGuideSection,
|
||||||
usePublicReleaseManifestView,
|
usePublicReleaseManifestView,
|
||||||
|
|
@ -114,24 +120,27 @@ export function PricingPage() {
|
||||||
description="Pricing decisions are safer when the current shared-auth sign-in lineup is visible before checkout, protected release access, or browser-account follow-through."
|
description="Pricing decisions are safer when the current shared-auth sign-in lineup is visible before checkout, protected release access, or browser-account follow-through."
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Section
|
<StepCardSection
|
||||||
title="What happens after access is granted"
|
title="What happens after access is granted"
|
||||||
description="Pricing only stays professional when it explains the real path from browser entitlement into the packaged simulator instead of stopping at the checkout button."
|
description="Pricing only stays professional when it explains the real path from browser entitlement into the packaged simulator instead of stopping at the checkout button."
|
||||||
>
|
cards={operatorManualTracks.slice(0, 3)}
|
||||||
<div className="card-grid">
|
/>
|
||||||
{operatorManualTracks.slice(0, 3).map((track) => (
|
|
||||||
<article key={track.title} className="card">
|
<SimulatorManualSection
|
||||||
<h3>{track.title}</h3>
|
title="What the software actually does after access is granted"
|
||||||
<p>{track.description}</p>
|
description="Plans only make sense if the public pricing lane also says what the entitled desktop software is for once it is installed."
|
||||||
<ul className="list top-gap">
|
/>
|
||||||
{track.steps.map((step) => (
|
|
||||||
<li key={step}>{step}</li>
|
<HigherDimensionalRuntimeGuideSection
|
||||||
))}
|
title="Higher-dimensional families behind the plans"
|
||||||
</ul>
|
description="This keeps commercial copy tied to the real runtime families the desktop product already owns instead of leaving serious capability buried elsewhere in the manual."
|
||||||
</article>
|
/>
|
||||||
))}
|
|
||||||
</div>
|
<BulletCardSection
|
||||||
</Section>
|
title="Current input and runtime control truth"
|
||||||
|
description="The pricing page should also be explicit about the present control quality bar so buyers can see what is real today and what still remains gated."
|
||||||
|
cards={[...inputAndDevicePostureCards, ...runtimeControlGuideCards]}
|
||||||
|
/>
|
||||||
|
|
||||||
<SurfaceChoiceGuideSection description="This keeps pricing honest about what should happen next: stay public for plan comparison, move protected for account-aware access, and move native for the actual simulator." />
|
<SurfaceChoiceGuideSection description="This keeps pricing honest about what should happen next: stay public for plan comparison, move protected for account-aware access, and move native for the actual simulator." />
|
||||||
|
|
||||||
|
|
@ -149,43 +158,17 @@ export function PricingPage() {
|
||||||
<DeliverySurfaceResponsibilitiesGrid limit={3} />
|
<DeliverySurfaceResponsibilitiesGrid limit={3} />
|
||||||
</Section>
|
</Section>
|
||||||
|
|
||||||
<Section
|
<BulletCardSection
|
||||||
title="Commercial distribution doctrine"
|
title="Commercial distribution doctrine"
|
||||||
description="Commercial pages should stay as explicit about release and legal posture as the rest of the public site."
|
description="Commercial pages should stay as explicit about release and legal posture as the rest of the public site."
|
||||||
>
|
cards={distributionDoctrineCards}
|
||||||
<div className="card-grid">
|
/>
|
||||||
{distributionDoctrineCards.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
|
<BulletCardSection
|
||||||
title="Terms of access in practice"
|
title="Terms of access in practice"
|
||||||
description="Pricing is easier to trust when the access model, simulator boundary, and operator obligations stay visible before checkout."
|
description="Pricing is easier to trust when the access model, simulator boundary, and operator obligations stay visible before checkout."
|
||||||
>
|
cards={termsBoundaryCards}
|
||||||
<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>
|
|
||||||
|
|
||||||
<Section title="Important launch note">
|
<Section title="Important launch note">
|
||||||
<article className="callout">
|
<article className="callout">
|
||||||
|
|
@ -305,6 +288,22 @@ export function DownloadPage() {
|
||||||
</div>
|
</div>
|
||||||
</Section>
|
</Section>
|
||||||
|
|
||||||
|
<SimulatorManualSection
|
||||||
|
title="What the installed runtime already owns"
|
||||||
|
description="Download posture is stronger when the page also explains the real software lane operators receive after the package handoff."
|
||||||
|
/>
|
||||||
|
|
||||||
|
<HigherDimensionalRuntimeGuideSection
|
||||||
|
title="Higher-dimensional family guide"
|
||||||
|
description="This keeps the download lane concrete about which serious family runtimes are already real and what host posture each one currently uses."
|
||||||
|
/>
|
||||||
|
|
||||||
|
<BulletCardSection
|
||||||
|
title="Current input and runtime control truth"
|
||||||
|
description="The download lane should also teach the real control boundary before the first session starts, including what is strong now and what still remains gated."
|
||||||
|
cards={[...inputAndDevicePostureCards, ...runtimeControlGuideCards]}
|
||||||
|
/>
|
||||||
|
|
||||||
<BrowserDesktopRealitySection />
|
<BrowserDesktopRealitySection />
|
||||||
|
|
||||||
<SurfaceChoiceGuideSection description="Download posture is clearer when the current best surface is explicit: public for target and release context, protected for entitlement, and desktop for the real training runtime." />
|
<SurfaceChoiceGuideSection description="Download posture is clearer when the current best surface is explicit: public for target and release context, protected for entitlement, and desktop for the real training runtime." />
|
||||||
|
|
@ -318,24 +317,11 @@ export function DownloadPage() {
|
||||||
description="Download posture is clearer when the current shared-auth sign-in lineup is visible before operators cross into the protected entitlement and package-delivery lane."
|
description="Download posture is clearer when the current shared-auth sign-in lineup is visible before operators cross into the protected entitlement and package-delivery lane."
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Section
|
<BulletCardSection
|
||||||
title="First launch and desktop setup"
|
title="First launch and desktop setup"
|
||||||
description="This keeps the download page useful after the archive is in hand: what to verify, how to pair the app, and which current runtime lanes matter first."
|
description="This keeps the download page useful after the archive is in hand: what to verify, how to pair the app, and which current runtime lanes matter first."
|
||||||
>
|
cards={desktopFirstLaunchCards}
|
||||||
<div className="card-grid">
|
/>
|
||||||
{desktopFirstLaunchCards.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>
|
|
||||||
|
|
||||||
<OperatorDesktopQuickstartSection title="First desktop session after install" />
|
<OperatorDesktopQuickstartSection title="First desktop session after install" />
|
||||||
|
|
||||||
|
|
@ -351,24 +337,11 @@ export function DownloadPage() {
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Section
|
<BulletCardSection
|
||||||
title="Digital delivery workflow"
|
title="Digital delivery workflow"
|
||||||
description="The download page should explain the real delivery sequence from platform selection to protected entitlement and first desktop launch."
|
description="The download page should explain the real delivery sequence from platform selection to protected entitlement and first desktop launch."
|
||||||
>
|
cards={digitalDeliveryCards}
|
||||||
<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>
|
|
||||||
|
|
||||||
<Section
|
<Section
|
||||||
title="Browser and desktop responsibilities"
|
title="Browser and desktop responsibilities"
|
||||||
|
|
@ -377,24 +350,11 @@ export function DownloadPage() {
|
||||||
<DeliverySurfaceResponsibilitiesGrid />
|
<DeliverySurfaceResponsibilitiesGrid />
|
||||||
</Section>
|
</Section>
|
||||||
|
|
||||||
<Section
|
<BulletCardSection
|
||||||
title="Distribution doctrine"
|
title="Distribution doctrine"
|
||||||
description="Download posture should stay tied to package proof, notices, and the desktop-first simulator boundary."
|
description="Download posture should stay tied to package proof, notices, and the desktop-first simulator boundary."
|
||||||
>
|
cards={distributionDoctrineCards}
|
||||||
<div className="card-grid">
|
/>
|
||||||
{distributionDoctrineCards.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="Release integrity and documentation">
|
<Section title="Release integrity and documentation">
|
||||||
<div className="card-grid">
|
<div className="card-grid">
|
||||||
|
|
|
||||||
|
|
@ -4,21 +4,25 @@ import { SiteMetadata } from '../components/seo/SiteMetadata'
|
||||||
import { PublicLaunchStatus } from '../components/ui/PublicLaunchStatus'
|
import { PublicLaunchStatus } from '../components/ui/PublicLaunchStatus'
|
||||||
import { ProductSurfaceMatrix } from '../components/ui/ProductSurfaceMatrix'
|
import { ProductSurfaceMatrix } from '../components/ui/ProductSurfaceMatrix'
|
||||||
import {
|
import {
|
||||||
controlProfileRosterCards,
|
|
||||||
deploymentReadinessTracks,
|
deploymentReadinessTracks,
|
||||||
featureAtlasCurrentTracks,
|
featureAtlasCurrentTracks,
|
||||||
featureRegistryTierCards,
|
featureRegistryTierCards,
|
||||||
higherDimensionalRuntimeGuideCards,
|
|
||||||
inputAndDevicePostureCards,
|
|
||||||
productSurfaceMatrixRows,
|
productSurfaceMatrixRows,
|
||||||
releaseStoryCards,
|
releaseStoryCards,
|
||||||
roadmapHonestyCards,
|
roadmapHonestyCards,
|
||||||
|
supportFaqs,
|
||||||
} from '../site-data'
|
} from '../site-data'
|
||||||
import {
|
import {
|
||||||
|
BulletCardSection,
|
||||||
BrowserDesktopRealitySection,
|
BrowserDesktopRealitySection,
|
||||||
|
ControlProfileRosterSection,
|
||||||
|
FaqCardSection,
|
||||||
|
HigherDimensionalRuntimeGuideSection,
|
||||||
|
InputAndDevicePostureSection,
|
||||||
PublicPackagedDesktopProofSection,
|
PublicPackagedDesktopProofSection,
|
||||||
PublicReleaseDecisionGuideSection,
|
PublicReleaseDecisionGuideSection,
|
||||||
ReleaseAuthorityBundleSection,
|
ReleaseAuthorityBundleSection,
|
||||||
|
RuntimeControlGuideSection,
|
||||||
Section,
|
Section,
|
||||||
SurfaceChoiceGuideSection,
|
SurfaceChoiceGuideSection,
|
||||||
usePublicReleaseManifestView,
|
usePublicReleaseManifestView,
|
||||||
|
|
@ -39,43 +43,17 @@ export function FeaturesPage() {
|
||||||
title="Feature truth without the roadmap archaeology."
|
title="Feature truth without the roadmap archaeology."
|
||||||
lede="This page condenses the real HyperTwist product surface into one public map: what ships now, what stays desktop-first, what the browser shell owns, and which branches remain intentionally gated."
|
lede="This page condenses the real HyperTwist product surface into one public map: what ships now, what stays desktop-first, what the browser shell owns, and which branches remain intentionally gated."
|
||||||
>
|
>
|
||||||
<Section
|
<BulletCardSection
|
||||||
title="How to read the product truth"
|
title="How to read the product truth"
|
||||||
description="The public website now mirrors the same discipline used in the internal feature registry so advanced readers do not have to guess which surfaces are live, retained, or still gated."
|
description="The public website now mirrors the same discipline used in the internal feature registry so advanced readers do not have to guess which surfaces are live, retained, or still gated."
|
||||||
>
|
cards={featureRegistryTierCards}
|
||||||
<div className="card-grid">
|
/>
|
||||||
{featureRegistryTierCards.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
|
<BulletCardSection
|
||||||
title="Current shipped capability"
|
title="Current shipped capability"
|
||||||
description="These are the major product tracks that are already first-party owned and safe to describe as current HyperTwist capability."
|
description="These are the major product tracks that are already first-party owned and safe to describe as current HyperTwist capability."
|
||||||
>
|
cards={featureAtlasCurrentTracks}
|
||||||
<div className="card-grid">
|
/>
|
||||||
{featureAtlasCurrentTracks.map((track) => (
|
|
||||||
<article key={track.title} className="card">
|
|
||||||
<h3>{track.title}</h3>
|
|
||||||
<p>{track.description}</p>
|
|
||||||
<ul className="list top-gap">
|
|
||||||
{track.bullets.map((bullet) => (
|
|
||||||
<li key={bullet}>{bullet}</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</article>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</Section>
|
|
||||||
|
|
||||||
<Section
|
<Section
|
||||||
title="Current surface authority map"
|
title="Current surface authority map"
|
||||||
|
|
@ -93,62 +71,31 @@ export function FeaturesPage() {
|
||||||
|
|
||||||
<BrowserDesktopRealitySection />
|
<BrowserDesktopRealitySection />
|
||||||
|
|
||||||
<Section
|
<HigherDimensionalRuntimeGuideSection
|
||||||
title="Higher-dimensional families and runtime posture"
|
title="Higher-dimensional families and runtime posture"
|
||||||
description="These are the current public-safe explanations of the serious hypercubing lanes and the runtime host each one actually uses."
|
description="These are the current public-safe explanations of the serious hypercubing lanes and the runtime host 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
|
<InputAndDevicePostureSection
|
||||||
title="Current control and XR posture"
|
title="Current control and XR posture"
|
||||||
description="The public product surface stays stronger when it is explicit about what input quality exists now and what still belongs to a later native completion packet."
|
description="The public product surface stays stronger when it is explicit about what input quality exists now and what still belongs to 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
|
<ControlProfileRosterSection
|
||||||
title="Current selectable control roster"
|
title="Current selectable control roster"
|
||||||
description="This keeps the feature atlas concrete about the shipped keyboard profile, scenic presets, dedicated-family selectors, and the current persistence boundary."
|
description="This keeps the feature atlas concrete about the shipped keyboard profile, scenic presets, dedicated-family selectors, and the current persistence boundary."
|
||||||
>
|
/>
|
||||||
<div className="card-grid">
|
|
||||||
{controlProfileRosterCards.map((card) => (
|
<RuntimeControlGuideSection
|
||||||
<article key={card.title} className="card">
|
title="Runtime control guide"
|
||||||
<h3>{card.title}</h3>
|
description="The feature atlas is more useful when it also teaches the current practical desktop control posture instead of stopping at capability labels and roster summaries."
|
||||||
<p>{card.description}</p>
|
/>
|
||||||
<ul className="list top-gap">
|
|
||||||
{card.bullets.map((bullet) => (
|
<FaqCardSection
|
||||||
<li key={bullet}>{bullet}</li>
|
title="Common capability questions"
|
||||||
))}
|
description="These are the short, public-safe answers to the product-boundary questions advanced readers usually ask after reading the capability atlas."
|
||||||
</ul>
|
cards={supportFaqs.slice(1, 6)}
|
||||||
</article>
|
/>
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</Section>
|
|
||||||
|
|
||||||
<Section
|
<Section
|
||||||
title="Release and distribution maturity"
|
title="Release and distribution maturity"
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,6 @@ import {
|
||||||
digitalDeliveryCards,
|
digitalDeliveryCards,
|
||||||
featureAtlasCurrentTracks,
|
featureAtlasCurrentTracks,
|
||||||
heroMetrics,
|
heroMetrics,
|
||||||
higherDimensionalRuntimeGuideCards,
|
|
||||||
controlProfileRosterCards,
|
|
||||||
inputAndDevicePostureCards,
|
|
||||||
operatorManualTracks,
|
operatorManualTracks,
|
||||||
operatorPlaybooks,
|
operatorPlaybooks,
|
||||||
publicDocumentationPrinciples,
|
publicDocumentationPrinciples,
|
||||||
|
|
@ -27,23 +24,30 @@ import {
|
||||||
releaseStoryCards,
|
releaseStoryCards,
|
||||||
resourceCollections,
|
resourceCollections,
|
||||||
roadmapHonestyCards,
|
roadmapHonestyCards,
|
||||||
runtimeControlGuideCards,
|
|
||||||
shippingNowCards,
|
shippingNowCards,
|
||||||
privacyBoundaryCards,
|
privacyBoundaryCards,
|
||||||
supportEscalationCards,
|
supportEscalationCards,
|
||||||
simulatorManualCards,
|
|
||||||
supportFaqs,
|
supportFaqs,
|
||||||
} from '../site-data'
|
} from '../site-data'
|
||||||
import {
|
import {
|
||||||
BrowserAuthMethodsSection,
|
BrowserAuthMethodsSection,
|
||||||
BrowserDesktopRealitySection,
|
BrowserDesktopRealitySection,
|
||||||
|
ControlProfileRosterSection,
|
||||||
DeliverySurfaceResponsibilitiesGrid,
|
DeliverySurfaceResponsibilitiesGrid,
|
||||||
|
BulletCardSection,
|
||||||
|
FaqCardSection,
|
||||||
|
HigherDimensionalRuntimeGuideSection,
|
||||||
|
InputAndDevicePostureSection,
|
||||||
OperatorDesktopQuickstartSection,
|
OperatorDesktopQuickstartSection,
|
||||||
|
PrincipleCardSection,
|
||||||
PublicManualRouteAtlasSection,
|
PublicManualRouteAtlasSection,
|
||||||
PublicPackagedDesktopProofSection,
|
PublicPackagedDesktopProofSection,
|
||||||
PublicReleaseDecisionGuideSection,
|
PublicReleaseDecisionGuideSection,
|
||||||
ReleaseAuthorityBundleSection,
|
ReleaseAuthorityBundleSection,
|
||||||
|
RuntimeControlGuideSection,
|
||||||
Section,
|
Section,
|
||||||
|
SimulatorManualSection,
|
||||||
|
StepCardSection,
|
||||||
StepOnlyCardSection,
|
StepOnlyCardSection,
|
||||||
SupportTopicDirectorySection,
|
SupportTopicDirectorySection,
|
||||||
SurfaceChoiceGuideSection,
|
SurfaceChoiceGuideSection,
|
||||||
|
|
@ -52,130 +56,6 @@ import {
|
||||||
usePublicReleaseManifestView,
|
usePublicReleaseManifestView,
|
||||||
} from './public-page-helpers'
|
} from './public-page-helpers'
|
||||||
|
|
||||||
type PrincipleCard = {
|
|
||||||
title: string
|
|
||||||
description: string
|
|
||||||
}
|
|
||||||
|
|
||||||
type BulletCard = {
|
|
||||||
title: string
|
|
||||||
description: string
|
|
||||||
bullets: readonly string[]
|
|
||||||
}
|
|
||||||
|
|
||||||
type StepCard = {
|
|
||||||
title: string
|
|
||||||
description: string
|
|
||||||
steps: readonly string[]
|
|
||||||
}
|
|
||||||
|
|
||||||
type FaqCard = {
|
|
||||||
question: string
|
|
||||||
answer: string
|
|
||||||
}
|
|
||||||
|
|
||||||
function PrincipleCardSection({
|
|
||||||
title,
|
|
||||||
description,
|
|
||||||
cards,
|
|
||||||
}: {
|
|
||||||
title: string
|
|
||||||
description?: string
|
|
||||||
cards: readonly PrincipleCard[]
|
|
||||||
}) {
|
|
||||||
return (
|
|
||||||
<Section title={title} description={description}>
|
|
||||||
<div className="card-grid">
|
|
||||||
{cards.map((card) => (
|
|
||||||
<article key={card.title} className="card">
|
|
||||||
<h3>{card.title}</h3>
|
|
||||||
<p>{card.description}</p>
|
|
||||||
</article>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</Section>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function BulletCardSection({
|
|
||||||
title,
|
|
||||||
description,
|
|
||||||
cards,
|
|
||||||
}: {
|
|
||||||
title: string
|
|
||||||
description?: string
|
|
||||||
cards: readonly BulletCard[]
|
|
||||||
}) {
|
|
||||||
return (
|
|
||||||
<Section title={title} description={description}>
|
|
||||||
<div className="card-grid">
|
|
||||||
{cards.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>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function StepCardSection({
|
|
||||||
title,
|
|
||||||
description,
|
|
||||||
cards,
|
|
||||||
}: {
|
|
||||||
title: string
|
|
||||||
description?: string
|
|
||||||
cards: readonly StepCard[]
|
|
||||||
}) {
|
|
||||||
return (
|
|
||||||
<Section title={title} description={description}>
|
|
||||||
<div className="card-grid">
|
|
||||||
{cards.map((card) => (
|
|
||||||
<article key={card.title} className="card">
|
|
||||||
<h3>{card.title}</h3>
|
|
||||||
<p>{card.description}</p>
|
|
||||||
<ul className="list top-gap">
|
|
||||||
{card.steps.map((step) => (
|
|
||||||
<li key={step}>{step}</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</article>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</Section>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function FaqCardSection({
|
|
||||||
title,
|
|
||||||
description,
|
|
||||||
cards,
|
|
||||||
}: {
|
|
||||||
title: string
|
|
||||||
description?: string
|
|
||||||
cards: readonly FaqCard[]
|
|
||||||
}) {
|
|
||||||
return (
|
|
||||||
<Section title={title} description={description}>
|
|
||||||
<div className="card-grid">
|
|
||||||
{cards.map((card) => (
|
|
||||||
<article key={card.question} className="card">
|
|
||||||
<h3>{card.question}</h3>
|
|
||||||
<p>{card.answer}</p>
|
|
||||||
</article>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</Section>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function HomeLanding() {
|
export function HomeLanding() {
|
||||||
const { releaseManifest, windowsValidationPlatform } = usePublicReleaseManifestView('public-home')
|
const { releaseManifest, windowsValidationPlatform } = usePublicReleaseManifestView('public-home')
|
||||||
|
|
||||||
|
|
@ -458,43 +338,15 @@ export function AboutPage() {
|
||||||
description="The about page should also say what the next honest operator move is, not only why the product exists."
|
description="The about page should also say what the next honest operator move is, not only why the product exists."
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Section
|
<InputAndDevicePostureSection
|
||||||
title="Current desktop control and XR truth"
|
title="Current desktop control and XR truth"
|
||||||
description="The product can be ambitious without overclaiming. This page now makes the current input, controller, and XR posture explicit."
|
description="The product can be ambitious without overclaiming. This page now makes the current input, controller, and XR posture explicit."
|
||||||
>
|
/>
|
||||||
<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
|
<ControlProfileRosterSection
|
||||||
title="Selectable control and settings roster"
|
title="Selectable control and settings roster"
|
||||||
description="This keeps the public manual concrete about what users can already choose or persist today without inflating that into finished controller rebinding or headset-runtime completion."
|
description="This keeps the public manual concrete about what users can already choose or persist today without inflating that into finished controller rebinding or headset-runtime completion."
|
||||||
>
|
/>
|
||||||
<div className="card-grid">
|
|
||||||
{controlProfileRosterCards.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
|
<Section
|
||||||
title="Release and deployment maturity"
|
title="Release and deployment maturity"
|
||||||
|
|
@ -661,100 +513,30 @@ export function ResourcesPage() {
|
||||||
</div>
|
</div>
|
||||||
</Section>
|
</Section>
|
||||||
|
|
||||||
<Section
|
<SimulatorManualSection
|
||||||
title="Simulator use today"
|
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."
|
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
|
<HigherDimensionalRuntimeGuideSection
|
||||||
title="Higher-dimensional runtime guide"
|
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."
|
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
|
<InputAndDevicePostureSection
|
||||||
title="Current control and device posture"
|
title="Current control and device posture"
|
||||||
description="This keeps public resources honest about what input/runtime ownership is already strong and what remains outside the current desktop-hosted No-Go XR/controller branch."
|
description="This keeps public resources honest about what input/runtime ownership is already strong and what remains outside the current desktop-hosted No-Go XR/controller branch."
|
||||||
>
|
/>
|
||||||
<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
|
<ControlProfileRosterSection
|
||||||
title="Selectable control and settings roster"
|
title="Selectable control and settings roster"
|
||||||
description="This keeps the public resources lane concrete about the shipped keyboard profile, scenic presets, family selectors, and current persistence boundary."
|
description="This keeps the public resources lane concrete about the shipped keyboard profile, scenic presets, family selectors, and current persistence boundary."
|
||||||
>
|
/>
|
||||||
<div className="card-grid">
|
|
||||||
{controlProfileRosterCards.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
|
<RuntimeControlGuideSection
|
||||||
title="Runtime control guide"
|
title="Runtime control guide"
|
||||||
description="This public-safe guide focuses on how operators and trainees actually drive the current desktop runtime today."
|
description="This public-safe guide focuses on how operators and trainees actually drive the current desktop runtime today."
|
||||||
>
|
/>
|
||||||
<div className="card-grid">
|
|
||||||
{runtimeControlGuideCards.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
|
<Section
|
||||||
title="Deployment readiness snapshot"
|
title="Deployment readiness snapshot"
|
||||||
|
|
@ -833,35 +615,29 @@ function GettingStartedPageContent({
|
||||||
|
|
||||||
<BrowserDesktopRealitySection />
|
<BrowserDesktopRealitySection />
|
||||||
|
|
||||||
<Section
|
<SimulatorManualSection
|
||||||
title="Simulator use today"
|
title="Simulator use today"
|
||||||
description="This keeps onboarding anchored to the lanes that actually execute in the current native runtime."
|
description="This keeps onboarding anchored to the lanes that actually execute in the current native runtime."
|
||||||
>
|
|
||||||
<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>
|
|
||||||
|
|
||||||
<BulletCardSection
|
|
||||||
title="Current control and device truth"
|
|
||||||
description="This is the practical runtime boundary that first-session onboarding should teach directly instead of leaving as a later surprise."
|
|
||||||
cards={inputAndDevicePostureCards}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<BulletCardSection
|
<HigherDimensionalRuntimeGuideSection
|
||||||
|
title="Higher-dimensional family guide"
|
||||||
|
description="The onboarding route is stronger when it also teaches which higher-dimensional lanes already exist and what host/runtime posture each one actually uses."
|
||||||
|
/>
|
||||||
|
|
||||||
|
<InputAndDevicePostureSection
|
||||||
|
title="Current control and device truth"
|
||||||
|
description="This is the practical runtime boundary that first-session onboarding should teach directly instead of leaving as a later surprise."
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ControlProfileRosterSection
|
||||||
title="Selectable control and settings roster"
|
title="Selectable control and settings roster"
|
||||||
description="The current desktop runtime already has real profile and settings ownership, but it stays narrower than a finished XR/controller/preferences suite."
|
description="The current desktop runtime already has real profile and settings ownership, but it stays narrower than a finished XR/controller/preferences suite."
|
||||||
cards={controlProfileRosterCards}
|
/>
|
||||||
|
|
||||||
|
<RuntimeControlGuideSection
|
||||||
|
title="Runtime control guide"
|
||||||
|
description="This onboarding route should also show the practical desktop control posture so operators do not have to leave the canonical first-session page just to find the real input and diagnostics guidance."
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<SurfaceChoiceGuideSection description="Onboarding is smoother when the right next surface is explicit too: public for orientation, protected for entitled access, and desktop for simulator execution." />
|
<SurfaceChoiceGuideSection description="Onboarding is smoother when the right next surface is explicit too: public for orientation, protected for entitled access, and desktop for simulator execution." />
|
||||||
|
|
@ -992,17 +768,9 @@ export function DocsPage() {
|
||||||
description="The public manual should not only explain the surface split. It should also tell operators whether the next honest move is pricing, protected browser/account work, protected desktop access, or notices/source follow-through."
|
description="The public manual should not only explain the surface split. It should also tell operators whether the next honest move is pricing, protected browser/account work, protected desktop access, or notices/source follow-through."
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<BulletCardSection
|
<SimulatorManualSection />
|
||||||
title="Simulator manual"
|
|
||||||
description="These are the current product-safe usage tracks for the native runtime itself."
|
|
||||||
cards={simulatorManualCards}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<BulletCardSection
|
<HigherDimensionalRuntimeGuideSection />
|
||||||
title="Higher-dimensional family guide"
|
|
||||||
description="These are the currently represented higher-dimensional lanes and the truthful host/runtime posture for each."
|
|
||||||
cards={higherDimensionalRuntimeGuideCards}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<StepOnlyCardSection
|
<StepOnlyCardSection
|
||||||
title="Deployment readiness manual"
|
title="Deployment readiness manual"
|
||||||
|
|
@ -1010,23 +778,11 @@ export function DocsPage() {
|
||||||
cards={deploymentReadinessTracks}
|
cards={deploymentReadinessTracks}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<BulletCardSection
|
<InputAndDevicePostureSection />
|
||||||
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."
|
|
||||||
cards={inputAndDevicePostureCards}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<BulletCardSection
|
<ControlProfileRosterSection />
|
||||||
title="Selectable control and settings roster"
|
|
||||||
description="This manual section answers the concrete user question: what settings, profiles, selectors, and persistence surfaces are already real today?"
|
|
||||||
cards={controlProfileRosterCards}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<BulletCardSection
|
<RuntimeControlGuideSection />
|
||||||
title="Runtime control guide"
|
|
||||||
description="This manual section explains how to approach the current desktop runtime without pretending the currently closed XR/controller branch has already been reopened."
|
|
||||||
cards={runtimeControlGuideCards}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<PublicPackagedDesktopProofSection
|
<PublicPackagedDesktopProofSection
|
||||||
platform={windowsValidationPlatform}
|
platform={windowsValidationPlatform}
|
||||||
|
|
|
||||||
|
|
@ -304,6 +304,60 @@ export function buildPublicLaunchStatusSummary(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resolveHealthLaunchChecklist(
|
||||||
|
launch: NonNullable<AuthHealthLike['launch']>,
|
||||||
|
readiness: PublicLaunchReadiness,
|
||||||
|
): PublicLaunchChecklistItem[] {
|
||||||
|
const derivedChecklist = getPublicLaunchChecklist(readiness)
|
||||||
|
if (!Array.isArray(launch.checklist) || launch.checklist.length === 0) {
|
||||||
|
return derivedChecklist
|
||||||
|
}
|
||||||
|
|
||||||
|
const launchChecklistById = new Map(
|
||||||
|
launch.checklist.map((item) => [item.id, item]),
|
||||||
|
)
|
||||||
|
|
||||||
|
return derivedChecklist.map((item) => {
|
||||||
|
const launchItem = launchChecklistById.get(item.id)
|
||||||
|
if (!launchItem) {
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
label:
|
||||||
|
typeof launchItem.label === 'string' && launchItem.label.trim().length > 0
|
||||||
|
? launchItem.label
|
||||||
|
: item.label,
|
||||||
|
configured: normalizeConfiguredValue(launchItem.configured),
|
||||||
|
requiredForPublicLaunch:
|
||||||
|
typeof launchItem.requiredForPublicLaunch === 'boolean'
|
||||||
|
? launchItem.requiredForPublicLaunch
|
||||||
|
: item.requiredForPublicLaunch,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveHealthLaunchMissingLabels(
|
||||||
|
launch: NonNullable<AuthHealthLike['launch']>,
|
||||||
|
checklist: readonly PublicLaunchChecklistItem[],
|
||||||
|
ready: boolean,
|
||||||
|
): string[] {
|
||||||
|
const launchMissingLabels = Array.isArray(launch.missingLabels)
|
||||||
|
? launch.missingLabels
|
||||||
|
.map((label) => String(label || '').trim())
|
||||||
|
.filter(Boolean)
|
||||||
|
: []
|
||||||
|
|
||||||
|
if (launchMissingLabels.length > 0 || ready) {
|
||||||
|
return launchMissingLabels
|
||||||
|
}
|
||||||
|
|
||||||
|
return checklist
|
||||||
|
.filter((item) => item.requiredForPublicLaunch && !item.configured)
|
||||||
|
.map((item) => item.label)
|
||||||
|
}
|
||||||
|
|
||||||
export function resolvePublicLaunchStatusSummary({
|
export function resolvePublicLaunchStatusSummary({
|
||||||
manifest,
|
manifest,
|
||||||
health,
|
health,
|
||||||
|
|
@ -313,7 +367,7 @@ export function resolvePublicLaunchStatusSummary({
|
||||||
health?: AuthHealthLike | null
|
health?: AuthHealthLike | null
|
||||||
fallback?: PublicLaunchReadinessInput | null
|
fallback?: PublicLaunchReadinessInput | null
|
||||||
}): PublicLaunchStatusSummary {
|
}): PublicLaunchStatusSummary {
|
||||||
return buildPublicLaunchStatusSummary(
|
const derivedSummary = buildPublicLaunchStatusSummary(
|
||||||
resolveHealthPublicLaunchReadiness({
|
resolveHealthPublicLaunchReadiness({
|
||||||
manifest,
|
manifest,
|
||||||
health,
|
health,
|
||||||
|
|
@ -321,4 +375,27 @@ export function resolvePublicLaunchStatusSummary({
|
||||||
}),
|
}),
|
||||||
resolvePublicLaunchTargets(manifest, health),
|
resolvePublicLaunchTargets(manifest, health),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (!health?.launch) {
|
||||||
|
return derivedSummary
|
||||||
|
}
|
||||||
|
|
||||||
|
const readiness = normalizePublicLaunchReadiness({
|
||||||
|
...derivedSummary.readiness,
|
||||||
|
...health.launch.readiness,
|
||||||
|
})
|
||||||
|
const checklist = resolveHealthLaunchChecklist(health.launch, readiness)
|
||||||
|
const ready =
|
||||||
|
typeof health.launch.ready === 'boolean'
|
||||||
|
? health.launch.ready && health.launch.posture === 'launch-ready'
|
||||||
|
: derivedSummary.ready
|
||||||
|
|
||||||
|
return {
|
||||||
|
posture: ready ? 'launch-ready' : 'preview',
|
||||||
|
ready,
|
||||||
|
readiness,
|
||||||
|
checklist,
|
||||||
|
missingLabels: resolveHealthLaunchMissingLabels(health.launch, checklist, ready),
|
||||||
|
targets: resolvePublicLaunchTargets(manifest, health),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -548,6 +548,16 @@ export const runtimeControlGuideCards = [
|
||||||
'Treat symmetry, stereo, visibility, and focus posture as current packaged runtime ownership rather than as a fully generalized preferences suite.',
|
'Treat symmetry, stereo, visibility, and focus posture as current packaged runtime ownership rather than as a fully generalized preferences suite.',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: 'Native diagnostics check',
|
||||||
|
description: 'Use the native training panel or coach dashboard to confirm the runtime you are actually operating before longer sessions, support escalation, or rollout review.',
|
||||||
|
bullets: [
|
||||||
|
'Read the active higher-dimensional selection line to confirm the current activation, view-context, session, and displayed scene ids instead of inferring them from the launched map alone.',
|
||||||
|
'Read the profile continuity line to confirm the shipped camera-export artifact `artifact/camera-export-json`, immersive recall boundary `immersive-training-session-recall-boundary`, and the current recall-scope and preference-field counts when bounded continuity is available.',
|
||||||
|
'Use the same native surfaces to verify that the desktop-hosted No-Go XR/controller boundary is still the live truth before assuming headset-runtime or controller-rebinding support.',
|
||||||
|
'If behavior and rollout posture disagree, capture the native diagnostics first and then move into the protected browser support or release lanes with the exact runtime state in hand.',
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: 'Current control boundary',
|
title: 'Current control boundary',
|
||||||
description: 'This keeps the manual useful by being explicit about what is supported now and what remains outside the current desktop-hosted No-Go XR/controller branch.',
|
description: 'This keeps the manual useful by being explicit about what is supported now and what remains outside the current desktop-hosted No-Go XR/controller branch.',
|
||||||
|
|
@ -578,7 +588,7 @@ export const controlProfileRosterCards = [
|
||||||
'The current scenic immersive roster includes 3 immersive-intensity presets and 3 reduced-distraction presets.',
|
'The current scenic immersive roster includes 3 immersive-intensity presets and 3 reduced-distraction presets.',
|
||||||
'Magic120Cell currently exposes 4 selector options alongside its symmetry, focus, and visibility owners.',
|
'Magic120Cell currently exposes 4 selector options alongside its symmetry, focus, and visibility owners.',
|
||||||
'MagicCube5D currently exposes 4 selector options alongside its projection-distance, stereo, focus, and visibility owners.',
|
'MagicCube5D currently exposes 4 selector options alongside its projection-distance, stereo, focus, and visibility owners.',
|
||||||
'Both higher-dimensional families now also surface their dedicated session, interactive-scene, persistence-boundary, and state-semantics ownership directly in the native diagnostics lane.',
|
'Both higher-dimensional families now also surface their dedicated session, interactive-scene, persistence-boundary, and state-semantics ownership directly in the native diagnostics lane, and the live roster surface keeps the currently displayed scene id visible too.',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -586,7 +596,7 @@ export const controlProfileRosterCards = [
|
||||||
description: 'Current continuity is real, but it is still narrower than a finished global preferences and controller-rebinding suite.',
|
description: 'Current continuity is real, but it is still narrower than a finished global preferences and controller-rebinding suite.',
|
||||||
bullets: [
|
bullets: [
|
||||||
'The native operator and training surfaces can recall the latest persisted generated-mode selector posture when a structurally valid launch request exists.',
|
'The native operator and training surfaces can recall the latest persisted generated-mode selector posture when a structurally valid launch request exists.',
|
||||||
'Those same native surfaces now also keep the shipped camera-export artifact and immersive session-recall boundary explicit, so bounded local continuity is no longer implied only through summary prose.',
|
'Those same native surfaces now also keep the shipped camera-export artifact and immersive session-recall boundary explicit together with recall-scope and preference-field counts, so bounded local continuity is no longer implied only through summary prose.',
|
||||||
'Those same native surfaces now also prove which family-specific persistence boundary and state-semantics contract currently owns the higher-dimensional settings lane.',
|
'Those same native surfaces now also prove which family-specific persistence boundary and state-semantics contract currently owns the higher-dimensional settings lane.',
|
||||||
'Viewer camera settings and immersive-presence settings are already first-party owned in the desktop runtime.',
|
'Viewer camera settings and immersive-presence settings are already first-party owned in the desktop runtime.',
|
||||||
'Finished headset-specific controller rebinding and broad VR onboarding remain outside the current desktop-hosted No-Go lane unless a later reopen proves the need.',
|
'Finished headset-specific controller rebinding and broad VR onboarding remain outside the current desktop-hosted No-Go lane unless a later reopen proves the need.',
|
||||||
|
|
@ -1026,6 +1036,11 @@ export const publicManualRouteAtlasCards = [
|
||||||
] as const
|
] as const
|
||||||
|
|
||||||
export const changelogEntries = [
|
export const changelogEntries = [
|
||||||
|
{
|
||||||
|
date: 'June 28, 2026',
|
||||||
|
title: 'Native control roster now exposes active scene and bounded continuity truth',
|
||||||
|
details: 'The desktop training-panel and coach-dashboard roster surfaces now keep the active higher-dimensional scene id visible alongside the active activation, view-context, and session ids, while also rendering the shipped camera-export artifact and immersive session-recall boundary with bounded continuity counts instead of leaving those facts implied behind sibling settings surfaces.',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
date: 'June 28, 2026',
|
date: 'June 28, 2026',
|
||||||
title: 'Public pages now explain what each route is actually for',
|
title: 'Public pages now explain what each route is actually for',
|
||||||
|
|
@ -1278,11 +1293,11 @@ export const supportFaqs = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
question: 'If the desktop app is primary, why keep the web version?',
|
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. It is intentionally narrower than the simulator for training and device/runtime work, and that narrower boundary makes the native runtime easier to trust and easier to operate.',
|
answer: 'Because the browser shell owns the parts that should stay outside the simulator: public positioning, account access, billing, release posture, download gating, notices, support-safe rollout guidance, and browser-to-desktop pairing. It is intentionally inferior for the core simulator job: it does not own package-validated training behavior, low-latency native input, higher-dimensional packaged execution, or device/runtime integration authority. That narrower boundary is a strength, not a weakness, because it keeps the native runtime easier to trust, easier to operate, and easier to ship honestly.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
question: 'Is VR/controller support already fully finished?',
|
question: 'Is VR/controller support already fully finished?',
|
||||||
answer: 'Not yet. HyperTwist already has real EnhancedInput posture, motion-controller groundwork, and a desktop-hosted scenic immersive lane, but the current host decision remains desktop-hosted No-Go on native OpenXR/controller widening, so it does not claim a fully finished OpenXR/controller/runtime or polished rebinding lane today.',
|
answer: 'Not yet. HyperTwist already has real classic keyboard and mouse or touch ownership, viewer camera and immersive settings ownership, higher-dimensional selector and view ownership, EnhancedInput posture, and motion-controller groundwork. But the current host decision remains desktop-hosted No-Go on native OpenXR/controller widening, so it does not yet claim a fully finished headset/runtime lane, packaged controller proof, or polished controller rebinding and preferences suite.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
question: 'Can I already customize controls and higher-dimensional view posture?',
|
question: 'Can I already customize controls and higher-dimensional view posture?',
|
||||||
|
|
|
||||||
|
|
@ -839,4 +839,14 @@ code {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.button-row > * {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-row .button {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,10 @@ const responsivePublicRoutes: readonly PublicRouteExpectation[] = [
|
||||||
heading: 'HyperTwist turns cube practice into a real operator-grade training stack.',
|
heading: 'HyperTwist turns cube practice into a real operator-grade training stack.',
|
||||||
cta: 'Download desktop app',
|
cta: 'Download desktop app',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/features',
|
||||||
|
heading: 'Feature truth without the roadmap archaeology.',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/about',
|
path: '/about',
|
||||||
heading: 'A training stack serious enough for higher-dimensional cubing.',
|
heading: 'A training stack serious enough for higher-dimensional cubing.',
|
||||||
|
|
@ -22,6 +26,10 @@ const responsivePublicRoutes: readonly PublicRouteExpectation[] = [
|
||||||
path: '/resources',
|
path: '/resources',
|
||||||
heading: 'Resources that explain the product without leaking operator-only internals.',
|
heading: 'Resources that explain the product without leaking operator-only internals.',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/docs',
|
||||||
|
heading: 'HyperTwist documentation stays capability-accurate.',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/pricing',
|
path: '/pricing',
|
||||||
heading: 'Pricing that matches the actual delivery model.',
|
heading: 'Pricing that matches the actual delivery model.',
|
||||||
|
|
@ -30,10 +38,43 @@ const responsivePublicRoutes: readonly PublicRouteExpectation[] = [
|
||||||
path: '/download',
|
path: '/download',
|
||||||
heading: 'Download the desktop build and pair it with your browser account.',
|
heading: 'Download the desktop build and pair it with your browser account.',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/getting-started',
|
||||||
|
heading: 'Start in the browser. Train in the desktop runtime.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/launch-status',
|
||||||
|
heading: 'See exactly what still separates preview from public launch.',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/support',
|
path: '/support',
|
||||||
heading: 'Support for rollout, downloads, pricing, and browser-to-desktop access.',
|
heading: 'Support for rollout, downloads, pricing, and browser-to-desktop access.',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/login',
|
||||||
|
heading: 'Log in to HyperTwist',
|
||||||
|
cta: 'Log in',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/changelog',
|
||||||
|
heading: 'Recent public-facing HyperTwist changes.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/open-source-notices',
|
||||||
|
heading: 'Open-source notices for public distribution surfaces.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/privacy',
|
||||||
|
heading: 'Privacy posture',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/terms',
|
||||||
|
heading: 'Terms of access',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/shipping-payment',
|
||||||
|
heading: 'Digital delivery only',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/register',
|
path: '/register',
|
||||||
heading: 'Create a HyperTwist account',
|
heading: 'Create a HyperTwist account',
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue