From cc6c71923474eb50e40aa235444b8f61ecb62fe2 Mon Sep 17 00:00:00 2001 From: axiomlogicnexus Date: Mon, 11 May 2026 05:37:59 +0200 Subject: [PATCH] Expose dashboard execution action control band --- .../HyperTwistCoachDashboardWidget.cpp | 89 +++++++++++++++ .../HyperTwistCoachDashboardWidget.h | 4 + .../HyperTwistTrainingTypes.h | 101 ++++++++++++++++++ ...RTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md | 3 +- ..._BAND_INSPECT_SURFACE_PACKET_2026-05-11.md | 52 +++++++++ 5 files changed, 248 insertions(+), 1 deletion(-) create mode 100644 docs/arch/HYPERTWIST_PHASE4_DASHBOARD_EXECUTION_ACTION_CONTROL_BAND_INSPECT_SURFACE_PACKET_2026-05-11.md diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp index a812bbe..6609da1 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp @@ -14636,6 +14636,95 @@ UHyperTwistCoachDashboardWidget::GetDisplayedQueueActionEnablementInspectSurface return Surface; } +FHyperTwistTrainingCoachDashboardExecutionActionControlBandInspectSurface +UHyperTwistCoachDashboardWidget::GetDisplayedExecutionActionControlBandInspectSurface() const +{ + FHyperTwistTrainingCoachDashboardExecutionActionControlBandInspectSurface Surface; + Surface.Headline = TEXT("Execution action control band"); + + const FHyperTwistTrainingCoachDashboardAttemptResultActionEnablementInspectSurface AttemptSurface = + GetDisplayedAttemptResultActionEnablementInspectSurface(); + const FHyperTwistTrainingCoachDashboardRunControlEnablementInspectSurface RunSurface = + GetDisplayedRunControlEnablementInspectSurface(); + const FHyperTwistTrainingCoachDashboardQueueActionEnablementInspectSurface QueueSurface = + GetDisplayedQueueActionEnablementInspectSurface(); + + Surface.AttemptResultStatusLine = AttemptSurface.StatusLine.IsEmpty() + ? TEXT("Attempt-result action: unavailable.") + : AttemptSurface.StatusLine; + Surface.RunControlStatusLine = RunSurface.StatusLine.IsEmpty() + ? TEXT("Run control: unavailable.") + : RunSurface.StatusLine; + Surface.QueueActionStatusLine = QueueSurface.StatusLine.IsEmpty() + ? TEXT("Queue action: unavailable.") + : QueueSurface.StatusLine; + Surface.SuccessLabel = AttemptSurface.SuccessLabel.IsEmpty() ? TEXT("Record Success") : AttemptSurface.SuccessLabel; + Surface.FailureLabel = AttemptSurface.FailureLabel.IsEmpty() ? TEXT("Record Failure") : AttemptSurface.FailureLabel; + Surface.TimeoutLabel = AttemptSurface.TimeoutLabel.IsEmpty() ? TEXT("Record Timeout") : AttemptSurface.TimeoutLabel; + Surface.DnfLabel = AttemptSurface.DnfLabel.IsEmpty() ? TEXT("Record DNF") : AttemptSurface.DnfLabel; + Surface.PrimaryLabel = RunSurface.PrimaryLabel.IsEmpty() ? TEXT("Start Run") : RunSurface.PrimaryLabel; + Surface.ContinueLabel = RunSurface.ContinueLabel.IsEmpty() ? TEXT("Continue Run") : RunSurface.ContinueLabel; + Surface.CompleteLabel = RunSurface.CompleteLabel.IsEmpty() ? TEXT("Complete Run") : RunSurface.CompleteLabel; + Surface.ClearLabel = RunSurface.ClearLabel.IsEmpty() ? TEXT("Clear Run") : RunSurface.ClearLabel; + Surface.DeferLabel = QueueSurface.DeferLabel.IsEmpty() ? TEXT("Defer 24h") : QueueSurface.DeferLabel; + Surface.PromoteLabel = QueueSurface.PromoteLabel.IsEmpty() ? TEXT("Promote Deferred") : QueueSurface.PromoteLabel; + Surface.RecoveryLabel = QueueSurface.RecoveryLabel.IsEmpty() ? TEXT("Apply Recovery") : QueueSurface.RecoveryLabel; + Surface.SelectedQueueEntryId = QueueSurface.SelectedQueueEntryId.IsEmpty() + ? TEXT("none") + : QueueSurface.SelectedQueueEntryId; + Surface.DeferredQueueEntryId = QueueSurface.DeferredQueueEntryId.IsEmpty() + ? TEXT("none") + : QueueSurface.DeferredQueueEntryId; + Surface.bHasRunnableCurrentCase = AttemptSurface.bHasRunnableCurrentCase || RunSurface.bHasRunnableCurrentCase; + Surface.bHasActiveRun = RunSurface.bHasActiveRun; + Surface.bHasLiveAttemptTimer = + AttemptSurface.bHasLiveAttemptTimer || RunSurface.bHasLiveAttemptTimer || QueueSurface.bHasLiveAttemptTimer; + Surface.bLiveSolvePhase = AttemptSurface.bLiveSolvePhase; + Surface.bLiveInspectionPhase = RunSurface.bLiveInspectionPhase; + Surface.bHasSelectedQueueEntry = QueueSurface.bHasSelectedQueueEntry; + Surface.bHasDeferredQueueEntry = QueueSurface.bHasDeferredQueueEntry; + Surface.bClosedLoopIdleDashboard = QueueSurface.bClosedLoopIdleDashboard; + Surface.bAnyActionEnabled = + AttemptSurface.bSuccessEnabled + || AttemptSurface.bFailureEnabled + || AttemptSurface.bTimeoutEnabled + || AttemptSurface.bDnfEnabled + || RunSurface.bPrimaryEnabled + || RunSurface.bContinueEnabled + || RunSurface.bCompleteEnabled + || RunSurface.bClearEnabled + || QueueSurface.bDeferEnabled + || QueueSurface.bPromoteEnabled + || QueueSurface.bRecoveryEnabled; + Surface.StatusLine = FString::Printf( + TEXT("Execution controls: attempts %s | run %s | queue %s"), + (AttemptSurface.bSuccessEnabled || AttemptSurface.bFailureEnabled + || AttemptSurface.bTimeoutEnabled || AttemptSurface.bDnfEnabled) + ? TEXT("available") + : TEXT("idle"), + (RunSurface.bPrimaryEnabled || RunSurface.bContinueEnabled + || RunSurface.bCompleteEnabled || RunSurface.bClearEnabled) + ? TEXT("available") + : TEXT("idle"), + (QueueSurface.bDeferEnabled || QueueSurface.bPromoteEnabled || QueueSurface.bRecoveryEnabled) + ? TEXT("available") + : TEXT("idle")); + Surface.DetailLine = FString::Printf( + TEXT("%s | %s | %s | runnable case %s | active run %s | selected queue %s | deferred queue %s | live timer %s | solve %s | inspection %s | closed-loop idle %s"), + *Surface.AttemptResultStatusLine, + *Surface.RunControlStatusLine, + *Surface.QueueActionStatusLine, + Surface.bHasRunnableCurrentCase ? TEXT("yes") : TEXT("no"), + Surface.bHasActiveRun ? TEXT("yes") : TEXT("no"), + Surface.bHasSelectedQueueEntry ? TEXT("yes") : TEXT("no"), + Surface.bHasDeferredQueueEntry ? TEXT("yes") : TEXT("no"), + Surface.bHasLiveAttemptTimer ? TEXT("yes") : TEXT("no"), + Surface.bLiveSolvePhase ? TEXT("yes") : TEXT("no"), + Surface.bLiveInspectionPhase ? TEXT("yes") : TEXT("no"), + Surface.bClosedLoopIdleDashboard ? TEXT("yes") : TEXT("no")); + return Surface; +} + FHyperTwistTrainingCoachDashboardVerificationActionInspectSurface UHyperTwistCoachDashboardWidget::GetDisplayedVerificationActionInspectSurface() const { diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h index 9f9e845..31a490d 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h @@ -999,6 +999,10 @@ public: FHyperTwistTrainingCoachDashboardQueueActionEnablementInspectSurface GetDisplayedQueueActionEnablementInspectSurface() const; + UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard") + FHyperTwistTrainingCoachDashboardExecutionActionControlBandInspectSurface + GetDisplayedExecutionActionControlBandInspectSurface() const; + UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard") FHyperTwistTrainingCoachDashboardVerificationActionInspectSurface GetDisplayedVerificationActionInspectSurface() const; diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h index a7ca6ee..8788740 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h @@ -13537,6 +13537,107 @@ struct FHyperTwistTrainingCoachDashboardQueueActionEnablementInspectSurface } }; +USTRUCT(BlueprintType) +struct FHyperTwistTrainingCoachDashboardExecutionActionControlBandInspectSurface +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString Headline; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString StatusLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString DetailLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString AttemptResultStatusLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString RunControlStatusLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString QueueActionStatusLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SuccessLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString FailureLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString TimeoutLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString DnfLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString PrimaryLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString ContinueLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString CompleteLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString ClearLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString DeferLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString PromoteLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString RecoveryLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SelectedQueueEntryId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString DeferredQueueEntryId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasRunnableCurrentCase = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasActiveRun = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasLiveAttemptTimer = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bLiveSolvePhase = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bLiveInspectionPhase = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasSelectedQueueEntry = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasDeferredQueueEntry = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bClosedLoopIdleDashboard = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bAnyActionEnabled = false; + + bool IsStructurallyValid() const + { + return !StatusLine.IsEmpty() + || !DetailLine.IsEmpty() + || bAnyActionEnabled + || bHasRunnableCurrentCase + || bHasActiveRun + || bHasSelectedQueueEntry + || bHasDeferredQueueEntry; + } +}; + USTRUCT(BlueprintType) struct FHyperTwistTrainingCoachDashboardVerificationActionInspectSurface { diff --git a/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md b/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md index a08e4b4..e6edfeb 100644 --- a/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md +++ b/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md @@ -71,7 +71,8 @@ Current correction call from the source-exposed audit and current execution refr - the now-complete deliberate `UHyperTwistTrainingRuntimeLibrary` world-context consumer lane reaches through active generated-mode selector option owned-execution split-phase current-selection merged ordered roster phase-id lookup, normalized-order lookup, and evaluation-order lookup inspect surfaces, so gameplay/Blueprint callers can inspect one retained merged-roster row directly by phase id, normalized order, or evaluation order without scanning the merged roster array or re-running inspect derivation details directly - the latest landed bounded `Phase 4` packet stays adjacent in that same retained-history dashboard lane and adds the dedicated method-drill recovery memory history status/detail inspect pair over the exact displayed retained-history lines already shown by the widget, so gameplay/Blueprint callers can inspect the current retained drill-recovery-memory text band directly without scraping text blocks or routing only through the broader selected-history and navigation surfaces - the latest landed bounded `Phase 4` packet also closes the adjacent preferred template-launch plus recommended/follow-up preview action control band with a single composite inspect seam over those three already-landed action surfaces, so gameplay/Blueprint callers can inspect that whole action cluster without stitching three separate action getters together - - with the retained-history text-band lane and that adjacent action-control band now both closed baseline, the next best clean move is to deliberately choose a new adjacent live dashboard consumer band rather than reopen already-landed text-band or action-control surfaces by drift + - the latest landed bounded `Phase 4` packet deliberately chooses the next adjacent live dashboard consumer band and adds a single composite execution-action-control seam over attempt-result action enablement, run-control enablement, and queue-action enablement, so gameplay/Blueprint callers can inspect that whole execution-control cluster without stitching three separate control surfaces together + - with the retained-history text-band lane, the template-launch / preview action-control band, and the execution-action-control band now all closed baseline, the next best clean move is to deliberately choose another adjacent live dashboard consumer band rather than reopen already-landed text-band or action-control surfaces by drift - the current execution-discipline rule that broad refactor / monolith-splitting work should not interrupt the active bounded roadmap packet unless structure is actually blocking it ## Donor portfolio phase taxonomy diff --git a/docs/arch/HYPERTWIST_PHASE4_DASHBOARD_EXECUTION_ACTION_CONTROL_BAND_INSPECT_SURFACE_PACKET_2026-05-11.md b/docs/arch/HYPERTWIST_PHASE4_DASHBOARD_EXECUTION_ACTION_CONTROL_BAND_INSPECT_SURFACE_PACKET_2026-05-11.md new file mode 100644 index 0000000..9d83977 --- /dev/null +++ b/docs/arch/HYPERTWIST_PHASE4_DASHBOARD_EXECUTION_ACTION_CONTROL_BAND_INSPECT_SURFACE_PACKET_2026-05-11.md @@ -0,0 +1,52 @@ +# HyperTwist Phase 4 dashboard execution action control band inspect surface packet + +- bounded Phase `4` dashboard-consumer slice +- date: `2026-05-11` + +## Intent + +Deliberately choose the next adjacent live dashboard consumer band and expose the attempt-result, run-control, and queue-action cluster as one inspectable gameplay and Blueprint seam. + +## Why this packet exists + +`UHyperTwistCoachDashboardWidget` already exposed three adjacent execution-control surfaces: + +- `GetDisplayedAttemptResultActionEnablementInspectSurface()` +- `GetDisplayedRunControlEnablementInspectSurface()` +- `GetDisplayedQueueActionEnablementInspectSurface()` + +But callers that wanted to reason about that whole execution-control cluster still had to stitch those three getters together manually even though the widget presents them as one adjacent action band. + +## What changed + +- added `FHyperTwistTrainingCoachDashboardExecutionActionControlBandInspectSurface` +- added `GetDisplayedExecutionActionControlBandInspectSurface()` +- composed the new surface entirely over the already-landed attempt-result action enablement, run-control enablement, and queue-action enablement surfaces +- kept the packet bounded by avoiding any new backend derivation or new widget-state caching + +## Files + +- `C:\HyperTwist\UnrealHyperTwist\Source\UnrealHyperTwist\Public\HyperTwistTraining\HyperTwistTrainingTypes.h` +- `C:\HyperTwist\UnrealHyperTwist\Source\UnrealHyperTwist\Public\HyperTwistTraining\HyperTwistCoachDashboardWidget.h` +- `C:\HyperTwist\UnrealHyperTwist\Source\UnrealHyperTwist\Private\HyperTwistTraining\HyperTwistCoachDashboardWidget.cpp` +- `C:\HyperTwist\docs\HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md` + +## Outcome + +Gameplay and Blueprint callers can now inspect: + +- the whole adjacent execution-action-control band through one surface +- the attempt-result, run-control, and queue-action status lines together +- all key action labels for recording attempts, controlling runs, and queue defer/promote/recovery actions +- runnable-case, active-run, live-timer, live-solve, inspection, selected/deferred queue, closed-loop-idle, and aggregate action-availability posture + +without stitching three separate control getters together manually. + +## Validation + +- full `Development Editor | Win64` MSBuild on `UnrealHyperTwist.sln` + - passed with `0 Warning(s), 0 Error(s)` + +## Next clean slice + +Treat the retained-history text-band lane, the template-launch / preview action-control band, and the execution-action-control band as landed baseline, then deliberately choose another adjacent live dashboard consumer band instead of reopening already-landed text-band or action-control surfaces by drift.