Expose dashboard execution action control band

This commit is contained in:
axiomlogicnexus 2026-05-11 05:37:59 +02:00
parent 481d13d8f2
commit cc6c719234
5 changed files with 248 additions and 1 deletions

View file

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

View file

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

View file

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

View file

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

View file

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