Add native browser runtime diagnostics panel

This commit is contained in:
axiomlogicnexus 2026-06-19 07:31:36 +00:00
parent 2392dfd5fa
commit 47620d1af6
12 changed files with 632 additions and 1 deletions

View file

@ -12782,6 +12782,15 @@ UHyperTwistCoachDashboardWidget::GetDisplayedMethodDrillOperationalBandInspectSu
return Surface;
}
FHyperTwistTrainingBrowserRuntimeInspectSurface
UHyperTwistCoachDashboardWidget::GetDisplayedBrowserRuntimeInspectSurface() const
{
FHyperTwistTrainingBrowserRuntimeInspectSurface Surface =
UHyperTwistTrainingPanelWidget::GetDisplayedBrowserRuntimeInspectSurface();
Surface.Headline = TEXT("Browser runtime diagnostics");
return Surface;
}
FHyperTwistTrainingCoachDashboardGuidanceRationaleInspectSurface
UHyperTwistCoachDashboardWidget::GetDisplayedGuidanceRationaleInspectSurface() const
{
@ -19082,6 +19091,24 @@ void UHyperTwistCoachDashboardWidget::EnsureDefaultDashboardBuilt()
TEXT("CoachQueueSuppressionHistoryDetail"),
8
);
BrowserRuntimeHeaderTextBlock = HyperTwistCoachDashboardWidgetInternal::AddTextRow(
WidgetTree,
RootLayout,
TEXT("CoachBrowserRuntimeHeader"),
2
);
BrowserRuntimeStatusTextBlock = HyperTwistCoachDashboardWidgetInternal::AddTextRow(
WidgetTree,
RootLayout,
TEXT("CoachBrowserRuntimeStatus"),
2
);
BrowserRuntimeDetailTextBlock = HyperTwistCoachDashboardWidgetInternal::AddTextRow(
WidgetTree,
RootLayout,
TEXT("CoachBrowserRuntimeDetail"),
8
);
RecognitionStatusTextBlock = HyperTwistCoachDashboardWidgetInternal::AddTextRow(
WidgetTree,
RootLayout,
@ -30122,6 +30149,20 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
{
NextQueueSuppressionButton->SetIsEnabled(QueueSuppressionHistoryEntries.Num() > 1);
}
const FHyperTwistTrainingBrowserRuntimeInspectSurface BrowserRuntimeSurface =
UHyperTwistTrainingPanelWidget::GetDisplayedBrowserRuntimeInspectSurface();
if (BrowserRuntimeHeaderTextBlock != nullptr)
{
BrowserRuntimeHeaderTextBlock->SetText(FText::FromString(TEXT("[Browser Runtime Diagnostics]")));
}
if (BrowserRuntimeStatusTextBlock != nullptr)
{
BrowserRuntimeStatusTextBlock->SetText(FText::FromString(BrowserRuntimeSurface.StatusLine));
}
if (BrowserRuntimeDetailTextBlock != nullptr)
{
BrowserRuntimeDetailTextBlock->SetText(FText::FromString(BrowserRuntimeSurface.DetailLine));
}
if (VerificationStatusTextBlock != nullptr)
{
DisplayedVerificationStatusLine = CachedCoachPanelState.VerificationStatusLine;

View file

@ -1,5 +1,6 @@
#include "HyperTwistTraining/HyperTwistTrainingPanelWidget.h"
#include "HyperTwistBrowser/HyperTwistBrowserWidget.h"
#include "HyperTwistTraining/HyperTwistTrainingRuntimeLibrary.h"
namespace HyperTwistTrainingPanelWidgetInternal
@ -83,6 +84,33 @@ namespace HyperTwistTrainingPanelWidgetInternal
return FallbackSourceLabel;
}
FString BuildBrowserRuntimeStatusLine(
const FHyperTwistBrowserOperatorStatusSurface& OperatorStatusSurface
)
{
return FString::Printf(
TEXT("%s | %s | %s"),
*OperatorStatusSurface.Headline,
*OperatorStatusSurface.SummaryLine,
*OperatorStatusSurface.QueueStatusLine
);
}
FString BuildBrowserRuntimeDetailLine(
const FHyperTwistBrowserOperatorStatusSurface& OperatorStatusSurface
)
{
return FString::Printf(
TEXT("%s | %s | stage %s | ready %s | runtime-ready payload %s | runtime-status envelope %s"),
*OperatorStatusSurface.BridgeStatusLine,
*OperatorStatusSurface.ShellAuthorityLine,
*OperatorStatusSurface.RuntimeStageId,
OperatorStatusSurface.bBrowserRuntimeReady ? TEXT("yes") : TEXT("no"),
OperatorStatusSurface.bHasRuntimeReadyPayload ? TEXT("yes") : TEXT("no"),
OperatorStatusSurface.bHasRuntimeStatusEnvelope ? TEXT("yes") : TEXT("no")
);
}
}
void UHyperTwistTrainingPanelWidget::NativeConstruct()
@ -507,6 +535,66 @@ UHyperTwistTrainingPanelWidget::GetDisplayedHigherDimensionalInteractiveSceneSur
return CachedHigherDimensionalInteractiveSceneSurface;
}
void UHyperTwistTrainingPanelWidget::SetObservedBrowserWidget(
UHyperTwistBrowserWidget* InBrowserWidget
)
{
ObservedBrowserWidget = InBrowserWidget;
}
void UHyperTwistTrainingPanelWidget::ClearObservedBrowserWidget()
{
ObservedBrowserWidget.Reset();
}
bool UHyperTwistTrainingPanelWidget::HasObservedBrowserWidget() const
{
return ObservedBrowserWidget.IsValid();
}
FHyperTwistTrainingBrowserRuntimeInspectSurface
UHyperTwistTrainingPanelWidget::GetDisplayedBrowserRuntimeInspectSurface() const
{
FHyperTwistTrainingBrowserRuntimeInspectSurface Surface;
UHyperTwistBrowserWidget* BrowserWidget = ObservedBrowserWidget.Get();
if (BrowserWidget == nullptr)
{
Surface.Headline = TEXT("Browser runtime unavailable");
Surface.SummaryLine = TEXT("no observed browser widget is attached");
Surface.RuntimeStageId = TEXT("unobserved");
Surface.RuntimeMode = TEXT("unobserved");
Surface.StatusLine =
TEXT("Browser runtime: no observed browser widget is attached to this training/operator surface.");
Surface.DetailLine =
TEXT("Attach the embedded UHyperTwistBrowserWidget through SetObservedBrowserWidget before expecting waiting, ready, or live runtime diagnostics here.");
return Surface;
}
const FHyperTwistBrowserOperatorStatusSurface OperatorStatusSurface =
BrowserWidget->GetBrowserOperatorStatusSurface();
Surface.Headline = OperatorStatusSurface.Headline;
Surface.SummaryLine = OperatorStatusSurface.SummaryLine;
Surface.StatusLine =
HyperTwistTrainingPanelWidgetInternal::BuildBrowserRuntimeStatusLine(OperatorStatusSurface);
Surface.DetailLine =
HyperTwistTrainingPanelWidgetInternal::BuildBrowserRuntimeDetailLine(OperatorStatusSurface);
Surface.QueueStatusLine = OperatorStatusSurface.QueueStatusLine;
Surface.BridgeStatusLine = OperatorStatusSurface.BridgeStatusLine;
Surface.ShellAuthorityLine = OperatorStatusSurface.ShellAuthorityLine;
Surface.RuntimeStageId = OperatorStatusSurface.RuntimeStageId;
Surface.RuntimeMode = OperatorStatusSurface.RuntimeMode;
Surface.BridgeTrafficStatus = OperatorStatusSurface.BridgeTrafficStatus;
Surface.AdapterCount = OperatorStatusSurface.AdapterCount;
Surface.PendingCommandCount = OperatorStatusSurface.PendingCommandCount;
Surface.PendingShellStateCount = OperatorStatusSurface.PendingShellStateCount;
Surface.bHasObservedBrowserWidget = true;
Surface.bBrowserRuntimeReady = OperatorStatusSurface.bBrowserRuntimeReady;
Surface.bHasRuntimeReadyPayload = OperatorStatusSurface.bHasRuntimeReadyPayload;
Surface.bHasRuntimeStatusEnvelope = OperatorStatusSurface.bHasRuntimeStatusEnvelope;
return Surface;
}
FHyperTwistTrainingDeck UHyperTwistTrainingPanelWidget::BuildActiveCoachRecommendedDeck(const int32 MaxCases)
{
CachedCoachRecommendedDeck = UHyperTwistTrainingRuntimeLibrary::BuildActiveCoachRecommendedDeck(

View file

@ -932,6 +932,9 @@ public:
FHyperTwistTrainingCoachDashboardMethodDrillOperationalBandInspectSurface
GetDisplayedMethodDrillOperationalBandInspectSurface() const;
FHyperTwistTrainingBrowserRuntimeInspectSurface
GetDisplayedBrowserRuntimeInspectSurface() const override;
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
FHyperTwistTrainingCoachDashboardGuidanceRationaleInspectSurface
GetDisplayedGuidanceRationaleInspectSurface() const;
@ -1634,6 +1637,15 @@ protected:
UPROPERTY(Transient)
TObjectPtr<UTextBlock> NextQueueSuppressionButtonLabel = nullptr;
UPROPERTY(Transient)
TObjectPtr<UTextBlock> BrowserRuntimeHeaderTextBlock = nullptr;
UPROPERTY(Transient)
TObjectPtr<UTextBlock> BrowserRuntimeStatusTextBlock = nullptr;
UPROPERTY(Transient)
TObjectPtr<UTextBlock> BrowserRuntimeDetailTextBlock = nullptr;
UPROPERTY(Transient)
TObjectPtr<UTextBlock> RecognitionStatusTextBlock = nullptr;

View file

@ -7,6 +7,8 @@
#include "HyperTwistTraining/HyperTwistTrainingTypes.h"
#include "HyperTwistTrainingPanelWidget.generated.h"
class UHyperTwistBrowserWidget;
UCLASS(BlueprintType, Blueprintable)
class UNREALHYPERTWIST_API UHyperTwistTrainingPanelWidget : public UUserWidget
{
@ -276,6 +278,19 @@ public:
FHyperTwistTrainingHigherDimensionalInteractiveSceneSurface
GetDisplayedHigherDimensionalInteractiveSceneSurface() const;
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Browser")
void SetObservedBrowserWidget(UHyperTwistBrowserWidget* InBrowserWidget);
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Browser")
void ClearObservedBrowserWidget();
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Browser")
bool HasObservedBrowserWidget() const;
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Browser")
virtual FHyperTwistTrainingBrowserRuntimeInspectSurface
GetDisplayedBrowserRuntimeInspectSurface() const;
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Coach")
FHyperTwistTrainingDeck BuildActiveCoachRecommendedDeck(int32 MaxCases);
@ -626,4 +641,7 @@ public:
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training")
FHyperTwistTrainingRepositoryRoundTripVerification VerifyTrainingRepositoryRoundTrip();
protected:
TWeakObjectPtr<UHyperTwistBrowserWidget> ObservedBrowserWidget;
};

View file

@ -9894,6 +9894,74 @@ struct FHyperTwistTrainingCoachVerificationRecognitionReviewContextSurface
}
};
USTRUCT(BlueprintType)
struct FHyperTwistTrainingBrowserRuntimeInspectSurface
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString Headline;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString SummaryLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString StatusLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString DetailLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString QueueStatusLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString BridgeStatusLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString ShellAuthorityLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString RuntimeStageId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString RuntimeMode;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString BridgeTrafficStatus;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 AdapterCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 PendingCommandCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 PendingShellStateCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasObservedBrowserWidget = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bBrowserRuntimeReady = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasRuntimeReadyPayload = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasRuntimeStatusEnvelope = false;
bool IsStructurallyValid() const
{
return !SummaryLine.IsEmpty()
|| !StatusLine.IsEmpty()
|| !DetailLine.IsEmpty()
|| bHasObservedBrowserWidget
|| bBrowserRuntimeReady
|| bHasRuntimeReadyPayload
|| bHasRuntimeStatusEnvelope;
}
};
USTRUCT(BlueprintType)
struct FHyperTwistTrainingCoachDashboardQueueRecoveryStatusInspectSurface
{

View file

@ -6,6 +6,8 @@
#include "HyperTwistBrowser/HyperTwistBrowserBridgeObject.h"
#include "HyperTwistBrowser/HyperTwistBrowserWidget.h"
#include "HyperTwistTraining/HyperTwistCoachDashboardWidget.h"
#include "HyperTwistTraining/HyperTwistTrainingPanelWidget.h"
#include "HyperTwistTraining/HyperTwistTrainingRuntimeLibrary.h"
#if WITH_AUTOMATION_TESTS
@ -36,6 +38,76 @@ namespace HyperTwistBrowserBridgeObjectTestInternal
return Envelope;
}
FString MakeSampleBrowserRuntimeReadyJson(
const int32 QueuedCommandCountAtRuntimeReady,
const int32 QueuedShellStateCountAtRuntimeReady
)
{
return FString::Printf(
TEXT("{\"status\":\"ready\",\"runtime\":\"hypertwist-browser-runtime\",")
TEXT("\"mode\":\"bundled-module\",\"adapterCount\":21,")
TEXT("\"shellAuthority\":\"Content/Browser/index.html\",")
TEXT("\"queuedCommandCountAtRuntimeReady\":%d,")
TEXT("\"queuedShellStateCountAtRuntimeReady\":%d}"),
QueuedCommandCountAtRuntimeReady,
QueuedShellStateCountAtRuntimeReady
);
}
FString MakeSampleBrowserRuntimeStatusEnvelopeJson(
const int32 QueuedCommandCountAtRuntimeReady,
const int32 QueuedShellStateCountAtRuntimeReady,
const int32 CommandReceiveCount,
const int32 ShellStateReceiveCount
)
{
return FString::Printf(
TEXT("{\"type\":\"browser-runtime-status\",\"source\":\"browser-runtime-shell\",")
TEXT("\"status\":{\"runtimeStatusId\":\"runtime-ready\",\"runtimeMode\":\"bundled-module\",")
TEXT("\"bootstrapStartedAtUtc\":\"2026-06-19T04:30:00Z\",")
TEXT("\"runtimeReadyAtUtc\":\"2026-06-19T04:31:00Z\",")
TEXT("\"shellAuthority\":\"Content/Browser/index.html\",")
TEXT("\"adapterCount\":21,")
TEXT("\"queuedCommandCountAtRuntimeReady\":%d,")
TEXT("\"queuedShellStateCountAtRuntimeReady\":%d,")
TEXT("\"commandReceiveCount\":%d,")
TEXT("\"shellStateReceiveCount\":%d,")
TEXT("\"lastCommandReceivedAtUtc\":\"2026-06-19T04:31:10Z\",")
TEXT("\"lastShellStateReceivedAtUtc\":\"2026-06-19T04:31:11Z\",")
TEXT("\"bridgeTrafficStatus\":\"shell-state-live\",")
TEXT("\"fallbackReason\":null}}"),
QueuedCommandCountAtRuntimeReady,
QueuedShellStateCountAtRuntimeReady,
CommandReceiveCount,
ShellStateReceiveCount
);
}
void SimulateLiveBrowserRuntimeStatus(
UHyperTwistBrowserWidget& BrowserWidget,
const int32 QueuedCommandCountAtRuntimeReady,
const int32 QueuedShellStateCountAtRuntimeReady,
const int32 CommandReceiveCount,
const int32 ShellStateReceiveCount
)
{
BrowserWidget.SetBrowserRuntimeDispatchReadyForTesting(true);
BrowserWidget.SimulateBrowserRuntimeReadyForTesting(
MakeSampleBrowserRuntimeReadyJson(
QueuedCommandCountAtRuntimeReady,
QueuedShellStateCountAtRuntimeReady
)
);
BrowserWidget.SimulateBrowserEnvelopeForTesting(
MakeSampleBrowserRuntimeStatusEnvelopeJson(
QueuedCommandCountAtRuntimeReady,
QueuedShellStateCountAtRuntimeReady,
CommandReceiveCount,
ShellStateReceiveCount
)
);
}
}
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
@ -694,6 +766,193 @@ bool FHyperTwistBrowserWidgetOperatorStatusSurfaceResetOnShellChangeTest::RunTes
return true;
}
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
FHyperTwistBrowserTrainingPanelRuntimeInspectSurfaceTest,
"HyperTwist.Browser.TrainingPanel.RuntimeInspectSurface",
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)
bool FHyperTwistBrowserTrainingPanelRuntimeInspectSurfaceTest::RunTest(
const FString& Parameters
)
{
UHyperTwistTrainingPanelWidget* TrainingPanel = NewObject<UHyperTwistTrainingPanelWidget>();
TestNotNull(TEXT("The training panel widget must be constructible."), TrainingPanel);
if (TrainingPanel == nullptr)
{
return false;
}
const FHyperTwistTrainingBrowserRuntimeInspectSurface UnobservedSurface =
TrainingPanel->GetDisplayedBrowserRuntimeInspectSurface();
TestFalse(
TEXT("The training panel browser runtime surface must begin without an observed browser widget."),
UnobservedSurface.bHasObservedBrowserWidget
);
TestTrue(
TEXT("The unobserved browser runtime surface must explain the missing widget attachment."),
UnobservedSurface.StatusLine.Contains(TEXT("no observed browser widget"))
);
TestTrue(
TEXT("The unobserved browser runtime surface must preserve a compact summary line."),
UnobservedSurface.SummaryLine.Contains(TEXT("no observed browser widget"))
);
UHyperTwistBrowserWidget* BrowserWidget = NewObject<UHyperTwistBrowserWidget>();
TestNotNull(TEXT("The observed browser widget must be constructible."), BrowserWidget);
if (BrowserWidget == nullptr)
{
return false;
}
TrainingPanel->SetObservedBrowserWidget(BrowserWidget);
BrowserWidget->DispatchCommandJson(TEXT("{\"command\":\"alpha\"}"));
BrowserWidget->PushShellStateJson(TEXT("{\"phase\":\"8A\"}"));
const FHyperTwistTrainingBrowserRuntimeInspectSurface WaitingSurface =
TrainingPanel->GetDisplayedBrowserRuntimeInspectSurface();
TestTrue(
TEXT("The training panel browser runtime surface must acknowledge the observed browser widget."),
WaitingSurface.bHasObservedBrowserWidget
);
TestTrue(
TEXT("The training panel browser runtime surface must surface the waiting stage before runtime-ready."),
WaitingSurface.StatusLine.Contains(TEXT("Browser runtime waiting"))
);
TestTrue(
TEXT("The training panel browser runtime surface must preserve the queued outbound counts."),
WaitingSurface.QueueStatusLine.Contains(TEXT("commands 1"))
&& WaitingSurface.QueueStatusLine.Contains(TEXT("shell states 1"))
);
TestTrue(
TEXT("The training panel browser runtime surface must preserve the waiting handshake summary."),
WaitingSurface.SummaryLine.Contains(TEXT("awaiting runtime-ready handshake"))
);
HyperTwistBrowserBridgeObjectTestInternal::SimulateLiveBrowserRuntimeStatus(
*BrowserWidget,
2,
1,
3,
2
);
const FHyperTwistTrainingBrowserRuntimeInspectSurface LiveSurface =
TrainingPanel->GetDisplayedBrowserRuntimeInspectSurface();
TestTrue(
TEXT("The training panel browser runtime surface must remain structurally valid once live runtime status is present."),
LiveSurface.IsStructurallyValid()
);
TestTrue(
TEXT("The training panel browser runtime surface must surface the live stage."),
LiveSurface.StatusLine.Contains(TEXT("Browser runtime live"))
);
TestTrue(
TEXT("The training panel browser runtime surface must surface the bridge receive counts in the detail line."),
LiveSurface.DetailLine.Contains(TEXT("bridge commands 3"))
&& LiveSurface.DetailLine.Contains(TEXT("shell states 2"))
);
TestTrue(
TEXT("The training panel browser runtime surface must preserve the shell authority line."),
LiveSurface.ShellAuthorityLine.Contains(TEXT("Content/Browser/index.html"))
);
TrainingPanel->ClearObservedBrowserWidget();
const FHyperTwistTrainingBrowserRuntimeInspectSurface ClearedSurface =
TrainingPanel->GetDisplayedBrowserRuntimeInspectSurface();
TestFalse(
TEXT("Clearing the observed browser widget must return the panel to the unobserved browser runtime state."),
ClearedSurface.bHasObservedBrowserWidget
);
return true;
}
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
FHyperTwistBrowserCoachDashboardRuntimeInspectSurfaceTest,
"HyperTwist.Browser.CoachDashboard.RuntimeInspectSurface",
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)
bool FHyperTwistBrowserCoachDashboardRuntimeInspectSurfaceTest::RunTest(
const FString& Parameters
)
{
UHyperTwistCoachDashboardWidget* CoachDashboard = NewObject<UHyperTwistCoachDashboardWidget>();
TestNotNull(TEXT("The coach dashboard widget must be constructible."), CoachDashboard);
if (CoachDashboard == nullptr)
{
return false;
}
UHyperTwistBrowserWidget* BrowserWidget = NewObject<UHyperTwistBrowserWidget>();
TestNotNull(TEXT("The observed browser widget must be constructible."), BrowserWidget);
if (BrowserWidget == nullptr)
{
return false;
}
CoachDashboard->SetObservedBrowserWidget(BrowserWidget);
BrowserWidget->DispatchCommandJson(TEXT("{\"command\":\"alpha\"}"));
BrowserWidget->PushShellStateJson(TEXT("{\"phase\":\"8A\"}"));
const FHyperTwistTrainingBrowserRuntimeInspectSurface WaitingSurface =
CoachDashboard->GetDisplayedBrowserRuntimeInspectSurface();
TestEqual(
TEXT("The coach dashboard browser runtime inspect surface must always expose the diagnostics headline."),
WaitingSurface.Headline,
TEXT("Browser runtime diagnostics")
);
TestTrue(
TEXT("The coach dashboard browser runtime inspect surface must surface the waiting stage even before a presentation refresh."),
WaitingSurface.StatusLine.Contains(TEXT("Browser runtime waiting"))
);
TestTrue(
TEXT("The coach dashboard browser runtime inspect surface must preserve the waiting handshake summary."),
WaitingSurface.SummaryLine.Contains(TEXT("awaiting runtime-ready handshake"))
);
HyperTwistBrowserBridgeObjectTestInternal::SimulateLiveBrowserRuntimeStatus(
*BrowserWidget,
2,
1,
3,
2
);
const FHyperTwistTrainingBrowserRuntimeInspectSurface LiveInspectSurface =
CoachDashboard->GetDisplayedBrowserRuntimeInspectSurface();
TestEqual(
TEXT("The coach dashboard browser runtime inspect surface must expose the diagnostics headline."),
LiveInspectSurface.Headline,
TEXT("Browser runtime diagnostics")
);
TestTrue(
TEXT("The coach dashboard browser runtime inspect surface must project the live browser runtime stage before a presentation refresh."),
LiveInspectSurface.StatusLine.Contains(TEXT("Browser runtime live"))
);
TestTrue(
TEXT("The coach dashboard browser runtime inspect surface must preserve the live bridge summary."),
LiveInspectSurface.SummaryLine.Contains(TEXT("shell-state-live"))
);
CoachDashboard->RefreshCoachDashboardView();
const FHyperTwistTrainingBrowserRuntimeInspectSurface BrowserRuntimeSurface =
CoachDashboard->GetDisplayedBrowserRuntimeInspectSurface();
TestTrue(
TEXT("The coach dashboard browser runtime inspect surface must carry the bridge detail line through the dashboard presentation."),
BrowserRuntimeSurface.DetailLine.Contains(TEXT("bridge commands 3"))
&& BrowserRuntimeSurface.DetailLine.Contains(TEXT("runtime-status envelope yes"))
);
TestTrue(
TEXT("The coach dashboard browser runtime inspect surface must retain shell authority visibility."),
BrowserRuntimeSurface.DetailLine.Contains(TEXT("Content/Browser/index.html"))
);
return true;
}
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
FHyperTwistBrowserWidgetAuthoritativeShellArtifactsTest,
"HyperTwist.Browser.Widget.AuthoritativeShellArtifacts",

View file

@ -0,0 +1,120 @@
# HyperTwist Phase 8A browser native operator diagnostics-panel implementation packet
Created on `2026-06-19`
## Status
- first-party HyperTwist packet
- bounded first-party `Phase 8A` continuation slice
## Purpose
This packet continues the already-landed native/operator browser-runtime
status surface by wiring it into small native training/operator HUD seams
inside Unreal.
The current implementation slice is:
- retain a first-party typed
`FHyperTwistTrainingBrowserRuntimeInspectSurface` above the browser-widget
operator surface instead of flattening those facts into browser-only text
- let `UHyperTwistTrainingPanelWidget` explicitly observe an attached
`UHyperTwistBrowserWidget` and expose waiting, ready, and live browser
runtime state through a native inspect seam
- wire that seam into `UHyperTwistCoachDashboardWidget` through a compact
`[Browser Runtime Diagnostics]` native dashboard section so operators can
read the same browser-runtime posture without opening the embedded browser
shell
- preserve a live-authoritative dashboard inspect seam even before a
presentation refresh, so native state consumers do not fall back to stale
rendered strings
- widen focused browser automation for both the training-panel seam and the
coach-dashboard seam
It is not:
- a topology widening into the optional full-browser client branch
- a native `MagicTile` renderer-port packet
- a replacement of the browser shell as the authoritative browser-owned UI
## Current authority basis
This implementation packet stands on:
- `docs/ops/HYPERTWIST_COMPREHENSIVE_RECONSTRUCTION_ROADMAP_2026-06-10.md`
- `docs/v6_5_deep_manual_pack/HyperTwist/ROADMAP.md`
- `docs/v6_5_deep_manual_pack/HyperTwist/FEATURE_REGISTRY.md`
- `docs/v6_5_deep_manual_pack/HyperTwist/ARCHITECTURE.md`
- `docs/ops/HYPERTWIST_IMPLEMENTATION_PHASE_1_KICKOFF.md`
- `docs/arch/HYPERTWIST_PHASE8A_BROWSER_NATIVE_OPERATOR_STATUS_SURFACE_IMPLEMENTATION_PACKET_2026-06-19.md`
## Current implementation scope
Current code now extends the live embedded-browser lane through:
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h`
with typed native
`FHyperTwistTrainingBrowserRuntimeInspectSurface` ownership for native
training/operator consumption
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingPanelWidget.h`
and
`UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingPanelWidget.cpp`
with observed-browser attachment control plus native waiting, ready, and
live runtime projection for training/operator surfaces
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h`
and
`UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp`
with a compact `[Browser Runtime Diagnostics]` dashboard band plus a
live-authoritative inspect getter
- focused browser automation in
`UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistBrowserBridgeObjectTest.cpp`
for the new training-panel and coach-dashboard browser-runtime inspect seams
## Why this continuation mattered
The earlier `Phase 8A` continuation already gave Unreal a compact native
browser-runtime operator surface, but operators still had no small training or
dashboard-native seam that consumed it directly.
Without this continuation, the typed ready/status ownership lived below the
browser shell yet still required either direct browser inspection or ad hoc
native consumers to be useful in operator-facing practice. This packet closes
that gap without widening topology.
## Validation
Local validation:
- `git diff --check`
- result on `2026-06-19`: passed
Windows build validation:
- `Build.bat UnrealHyperTwistEditor Win64 Development -Project='C:\HyperTwist_worktrees\phase10validate\UnrealHyperTwist\UnrealHyperTwist.uproject' -WaitMutex -NoHotReloadFromIDE -NoUba`
- result on `2026-06-19`: `Result: Succeeded` with UnrealBuildTool
`Total execution time: 3258.26 seconds` on isolated worktree
`C:\HyperTwist_worktrees\phase10validate`
Focused browser validation:
- `Automation RunTests HyperTwist.Browser`
- result on `2026-06-19`: report `index.json` exported to
`Saved\AutomationReports\Browser-NativeOperatorDiagnosticsPanel-Verify`
with `14` `HyperTwist.Browser.*` tests succeeded, `0` failed, including:
- `HyperTwist.Browser.CoachDashboard.RuntimeInspectSurface`
- `HyperTwist.Browser.TrainingPanel.RuntimeInspectSurface`
- `HyperTwist.Browser.Widget.OperatorStatusSurfaceWaiting`
- `HyperTwist.Browser.Widget.OperatorStatusSurfaceLive`
- `HyperTwist.Browser.Widget.OperatorStatusSurfaceResetOnShellChange`
## Product effect
This packet keeps the embedded browser/CEF shipping lane intact, but extends
native operator usefulness:
- Unreal training/operator surfaces can now consume the same waiting, ready,
and live browser-runtime facts that the browser shell projects
- coach/dashboard-native diagnostics no longer depend on opening the browser
shell to read handshake or bridge posture
- inspect-surface consumers stay tied to live browser-runtime ownership rather
than cached rendered strings

View file

@ -430,6 +430,8 @@ Closure read:
- Runtime-ready continuation on `2026-06-19`: current code now closes the adjacent handshake gap as well by decoding first-party `hypertwist-runtime-ready` payloads into typed Unreal-owned structs, retaining the last valid runtime-ready payload through `UHyperTwistBrowserBridgeObject` and `UHyperTwistBrowserWidget`, and keeping the existing browser-ready queue-flush behavior intact
- Validation evidence on `2026-06-19`: the same primary reverse-SSH `localhost:22022` lane rebuilt isolated worktree `C:\HyperTwist_worktrees\phase10validate` with `Result: Succeeded` and UnrealBuildTool `Total execution time: 88.20 seconds`, then `Automation RunTests HyperTwist.Browser` found `9` `HyperTwist.Browser.*` tests and passed all `9` at `Saved\AutomationReports\Browser-RuntimeReadyPayload-Verify`
- Native operator-surface continuation on `2026-06-19`: current code now projects a compact native/operator-facing browser runtime status surface from the typed Unreal-owned runtime-ready and runtime-status caches, exposing waiting/ready/live stages, queue carryover, bridge receive counts, runtime mode, adapter count, and shell authority while clearing retained runtime ownership whenever shell authority changes so stale live state cannot survive a browser reload
- Native diagnostics-panel continuation on `2026-06-19`: current implementation now wires that typed browser runtime operator surface into `UHyperTwistTrainingPanelWidget` and `UHyperTwistCoachDashboardWidget`, adds explicit observed-browser attachment control plus a compact `[Browser Runtime Diagnostics]` native dashboard section, and keeps the dashboard inspect seam live-authoritative even before presentation refresh so operators can read waiting/ready/live browser state without opening the embedded browser shell
- Validation evidence on `2026-06-19`: the same primary reverse-SSH `localhost:22022` lane rebuilt isolated worktree `C:\HyperTwist_worktrees\phase10validate` with `Result: Succeeded` and UnrealBuildTool `Total execution time: 3258.26 seconds`, then `Automation RunTests HyperTwist.Browser` exported `Saved\AutomationReports\Browser-NativeOperatorDiagnosticsPanel-Verify\index.json` with `14` `HyperTwist.Browser.*` tests succeeded and `0` failed, including `CoachDashboard.RuntimeInspectSurface` and `TrainingPanel.RuntimeInspectSurface`
- Validation evidence on `2026-06-19`: the same primary reverse-SSH `localhost:22022` lane rebuilt isolated worktree `C:\HyperTwist_worktrees\phase10validate` with `Result: Succeeded` and UnrealBuildTool `Total execution time: 59.53 seconds`, then `Automation RunTests HyperTwist.Browser` exported `Saved\AutomationReports\Browser-NativeOperatorStatusSurface-Reset-Verify\index.json` with `12` `HyperTwist.Browser.*` tests succeeded and `0` failed, including `Widget.OperatorStatusSurfaceWaiting`, `Widget.OperatorStatusSurfaceLive`, and `Widget.OperatorStatusSurfaceResetOnShellChange`
### 8B — State Synchronization

View file

@ -145,6 +145,12 @@ Use these as the current governing docs:
waiting/ready/live status surface built from those typed ready/status seams,
and changing shell authority now clears retained runtime ownership so stale
live state does not survive a reload
- that same shipping/browser posture is now also being continued into a small
native training/operator diagnostics panel: `UHyperTwistTrainingPanelWidget`
can observe an attached `UHyperTwistBrowserWidget`, and the coach dashboard
can surface a compact `[Browser Runtime Diagnostics]` section without making
its inspect seam depend on cached rendered strings
- Validation evidence on `2026-06-19`: the same primary reverse-SSH `localhost:22022` lane rebuilt isolated worktree `C:\HyperTwist_worktrees\phase10validate` with `Result: Succeeded` and UnrealBuildTool `Total execution time: 3258.26 seconds`, then `Automation RunTests HyperTwist.Browser` exported `Saved\AutomationReports\Browser-NativeOperatorDiagnosticsPanel-Verify\index.json` with `14` `HyperTwist.Browser.*` tests succeeded and `0` failed, including `CoachDashboard.RuntimeInspectSurface` and `TrainingPanel.RuntimeInspectSurface`
- `MagicTile` `Phase 7C` is now landed separately through the bundled tiling native-behavior
proof contract/probe seam, runtime-library proof helpers, and focused Windows validation on
isolated worktree `C:\HyperTwist_worktrees\phase10validate`

View file

@ -117,6 +117,13 @@ including queue carryover, bridge receive counts, runtime mode, adapter count,
and shell authority, and clears retained runtime ownership whenever shell
authority changes so stale live state cannot survive a shell reload.
That same native/operator-facing seam is now also wired into small Unreal
training/operator HUD consumers: `UHyperTwistTrainingPanelWidget` can observe
an attached `UHyperTwistBrowserWidget`, and
`UHyperTwistCoachDashboardWidget` now surfaces a compact
`[Browser Runtime Diagnostics]` panel while keeping its inspect getter tied to
live browser-runtime ownership rather than cached rendered strings.
The optional full-browser client path now exists only as a spec-defined
first-party branch:

View file

@ -144,7 +144,7 @@ Do not collapse those three tiers into one undifferentiated "features" voice.
| First-party provider-neutral custom-endpoint runtime routing | Implemented now | landed first-party `Phase 6R-AI` | First-party per-session provider-profile endpoint selection, runtime routing, fallback-health reflection, and bounded provider-backed transport-failure posture are now live above the landed provider-profile/BYOK and provider-routing seams. Provider-specific overlays, payment execution, provider-portal ownership, and payload shipping remain deferred. |
| Analytics/reporting surfaces | Implemented now | landed analytics/reporting packets | Reporting is real, but bounded to accepted retained slices. |
| Rewritten training analytics and report reference grounding | Implemented now | `apache/echarts` retained permissive lane + first-party current code | Current live `Training Analytics` reference side includes four rewritten first-party targets grounded in retained `apache/echarts`: session outcome and progress reporting, analytics data-view and export, timing-trend history and overview interaction, and the optional richer explainer or sidecar boundary. This does not displace the landed `Phase 3R-C` first-party analytics/reporting owner or elevate `ecomfe/echarts-gl` and `ecomfe/zrender` beyond support-only sidecars. |
| Browser/spatial/media adjunct surfaces | Implemented now | landed `three.js`, `react-three-fiber`, `xr`, `model-viewer`, `remotion` packets | These are implemented bounded families, and the current Phase 1 browser-runtime landing now includes a first-party authoritative `Content/Browser/index.html` shell, bundled-runtime upgrade path, committed clean-checkout plain-JS fallback runtime, embedded `UHyperTwistBrowserWidget` bridge, the `2026-06-19` runtime-ready queue hardening that retains outbound Unreal shell traffic until the browser runtime is ready, a same-day first-party `Browser Runtime Status` surface with shared boot-state ownership across bundled and fallback shells, a follow-on typed Unreal-side `browser-runtime-status` capture seam that retains the last valid runtime snapshot across unrelated later envelope traffic until explicit reset, a second follow-on typed Unreal-side `hypertwist-runtime-ready` capture seam that raises the original handshake payload out of raw JSON-only handling without changing queue flush behavior, and a third same-day native/operator-facing status surface that consumes those typed seams inside Unreal while clearing retained runtime ownership on shell-authority change. This still is not proof of unlimited browser-shell parity. |
| Browser/spatial/media adjunct surfaces | Implemented now | landed `three.js`, `react-three-fiber`, `xr`, `model-viewer`, `remotion` packets | These are implemented bounded families, and the current Phase 1 browser-runtime landing now includes a first-party authoritative `Content/Browser/index.html` shell, bundled-runtime upgrade path, committed clean-checkout plain-JS fallback runtime, embedded `UHyperTwistBrowserWidget` bridge, the `2026-06-19` runtime-ready queue hardening that retains outbound Unreal shell traffic until the browser runtime is ready, a same-day first-party `Browser Runtime Status` surface with shared boot-state ownership across bundled and fallback shells, a follow-on typed Unreal-side `browser-runtime-status` capture seam that retains the last valid runtime snapshot across unrelated later envelope traffic until explicit reset, a second follow-on typed Unreal-side `hypertwist-runtime-ready` capture seam that raises the original handshake payload out of raw JSON-only handling without changing queue flush behavior, a third same-day native/operator-facing status surface that consumes those typed seams inside Unreal while clearing retained runtime ownership on shell-authority change, and a fourth same-day native training/operator diagnostics-panel continuation that wires that typed status ownership into `UHyperTwistTrainingPanelWidget` and the coach dashboard without making the dashboard inspect seam depend on stale rendered strings. This still is not proof of unlimited browser-shell parity. |
| Optional full-browser client path above Unreal backend authority | Deep-source grounded retained | landed first-party `Phase 8B` preparation packet + spec/evidence continuation | This branch remains a spec-only first-party option: a browser-owned rendering and input shell may sit above explicit Unreal backend seams while Unreal remains authoritative for puzzle, training, timer, replay, and persistence state. The current continuation now fixes the allowed seam families to catalog, session, action, state, continuity push, replay, persistence status, and runtime health, while keeping offline-first, public-hosted, and native renderer widening posture deferred. The landed embedded browser/CEF shell remains the current shipping posture, and this branch stays separate from any native `MagicTile` behavior or renderer widening. |
| Rewritten browser spatial scene and renderer reference grounding | Implemented now | `mrdoob/three.js` retained permissive lane + first-party current code | Current live `Browser 3D and XR Support` reference side includes one rewritten first-party target grounded in retained `mrdoob/three.js`: the browser spatial scene and renderer contract. This does not displace the landed `Phase 3R-F` first-party browser spatial owner trio or absorb the adjacent `react-three-fiber` renderer-bridge and `xr` session slices. |
| Rewritten React-side browser renderer and event-bridge grounding | Implemented now | `pmndrs/react-three-fiber` retained permissive lane + first-party current code | Current live `Browser 3D and XR Support` reference side includes one rewritten first-party target grounded in retained `react-three-fiber`: the React scene renderer and event bridge. This does not displace the landed `Phase 3R-F` first-party browser spatial owner trio or absorb the adjacent `three.js` scene substrate and `xr` session slices. |

View file

@ -145,6 +145,16 @@ Current consolidated milestone snapshot:
`Widget.OperatorStatusSurfaceWaiting`,
`Widget.OperatorStatusSurfaceLive`, and
`Widget.OperatorStatusSurfaceResetOnShellChange`
- that same embedded-browser lane then gained a bounded native training/operator
diagnostics-panel continuation on `2026-06-19`, wiring that typed status
ownership into `UHyperTwistTrainingPanelWidget` and
`UHyperTwistCoachDashboardWidget`, adding a compact
`[Browser Runtime Diagnostics]` native dashboard section, and keeping the
dashboard inspect seam live-authoritative even before presentation refresh,
with refreshed primary-lane `localhost:22022` validation at `14` green
`HyperTwist.Browser.*` tests including
`CoachDashboard.RuntimeInspectSurface` and
`TrainingPanel.RuntimeInspectSurface`
- classic-cube `Phase 9A` replay recording is now closed through first-party
runtime capture, `.json` replay persistence, local playback reconstruction,
schema-light replay normalization across save/load/viewer import, and live