From 481d13d8f2a5226db172fd6dcf22ab3921d7b300 Mon Sep 17 00:00:00 2001 From: axiomlogicnexus Date: Mon, 11 May 2026 05:30:34 +0200 Subject: [PATCH] Expose dashboard template launch preview action control band --- .../HyperTwistCoachDashboardWidget.cpp | 87 +++++++++++++++++++ .../HyperTwistCoachDashboardWidget.h | 4 + .../HyperTwistTrainingTypes.h | 85 ++++++++++++++++++ ...RTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md | 3 +- ..._BAND_INSPECT_SURFACE_PACKET_2026-05-11.md | 51 +++++++++++ 5 files changed, 229 insertions(+), 1 deletion(-) create mode 100644 docs/arch/HYPERTWIST_PHASE4_DASHBOARD_TEMPLATE_LAUNCH_PREVIEW_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 2da8834..a812bbe 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp @@ -13976,6 +13976,93 @@ UHyperTwistCoachDashboardWidget::GetDisplayedFollowUpPreviewActionInspectSurface return Surface; } +FHyperTwistTrainingCoachDashboardTemplateLaunchPreviewActionControlBandInspectSurface +UHyperTwistCoachDashboardWidget::GetDisplayedTemplateLaunchPreviewActionControlBandInspectSurface() const +{ + FHyperTwistTrainingCoachDashboardTemplateLaunchPreviewActionControlBandInspectSurface Surface; + Surface.Headline = TEXT("Template-launch / preview action control band"); + + const FHyperTwistTrainingCoachDashboardPreferredTemplateLaunchActionInspectSurface TemplateSurface = + GetDisplayedPreferredTemplateLaunchActionInspectSurface(); + const FHyperTwistTrainingCoachDashboardGuidancePreviewActionInspectSurface RecommendedSurface = + GetDisplayedRecommendedPreviewActionInspectSurface(); + const FHyperTwistTrainingCoachDashboardGuidancePreviewActionInspectSurface FollowUpSurface = + GetDisplayedFollowUpPreviewActionInspectSurface(); + + Surface.PreferredTemplateActionLabel = TemplateSurface.ActionLabel.IsEmpty() + ? TEXT("No Template") + : TemplateSurface.ActionLabel; + Surface.RecommendedPreviewActionLabel = RecommendedSurface.ActionLabel.IsEmpty() + ? TEXT("Preview Recommended") + : RecommendedSurface.ActionLabel; + Surface.FollowUpPreviewActionLabel = FollowUpSurface.ActionLabel.IsEmpty() + ? TEXT("Preview Follow-Up") + : FollowUpSurface.ActionLabel; + Surface.PreferredTemplateStatusLine = TemplateSurface.StatusLine.IsEmpty() + ? TEXT("Template launch action: unavailable.") + : TemplateSurface.StatusLine; + Surface.RecommendedPreviewStatusLine = RecommendedSurface.StatusLine.IsEmpty() + ? TEXT("Recommended preview action: unavailable.") + : RecommendedSurface.StatusLine; + Surface.FollowUpPreviewStatusLine = FollowUpSurface.StatusLine.IsEmpty() + ? TEXT("Follow-up preview action: unavailable.") + : FollowUpSurface.StatusLine; + Surface.PreferredTemplateTitle = TemplateSurface.TemplateTitle.IsEmpty() + ? TEXT("n/a") + : TemplateSurface.TemplateTitle; + Surface.RecommendedDeckLabel = RecommendedSurface.DeckLabel.IsEmpty() + ? TEXT("n/a") + : RecommendedSurface.DeckLabel; + Surface.FollowUpDeckLabel = FollowUpSurface.DeckLabel.IsEmpty() + ? TEXT("n/a") + : FollowUpSurface.DeckLabel; + Surface.ActivePreviewLaneLabel = !RecommendedSurface.ActivePreviewLaneLabel.IsEmpty() + ? RecommendedSurface.ActivePreviewLaneLabel + : (FollowUpSurface.ActivePreviewLaneLabel.IsEmpty() + ? TEXT("none") + : FollowUpSurface.ActivePreviewLaneLabel); + Surface.bHasPreferredTemplate = TemplateSurface.bHasPreferredTemplate; + Surface.bRecommendedGuidanceReady = + RecommendedSurface.bHasGuidancePayload || RecommendedSurface.bGuidanceReadyToLaunch; + Surface.bFollowUpGuidanceReady = + FollowUpSurface.bHasGuidancePayload || FollowUpSurface.bGuidanceReadyToLaunch; + Surface.bHasLiveAttemptTimer = + TemplateSurface.bHasLiveAttemptTimer + || RecommendedSurface.bHasLiveAttemptTimer + || FollowUpSurface.bHasLiveAttemptTimer; + Surface.bHasActiveRun = TemplateSurface.bHasActiveRun; + Surface.bPreferredTemplateActionEnabled = TemplateSurface.bActionEnabled; + Surface.bRecommendedPreviewActionEnabled = RecommendedSurface.bActionEnabled; + Surface.bFollowUpPreviewActionEnabled = FollowUpSurface.bActionEnabled; + Surface.bAnyActionEnabled = + Surface.bPreferredTemplateActionEnabled + || Surface.bRecommendedPreviewActionEnabled + || Surface.bFollowUpPreviewActionEnabled; + Surface.bClosedLoopIdleDashboard = + RecommendedSurface.bClosedLoopIdleDashboard || FollowUpSurface.bClosedLoopIdleDashboard; + Surface.StatusLine = FString::Printf( + TEXT("Action control band: template %s (%s) | recommended %s (%s) | follow-up %s (%s)"), + *Surface.PreferredTemplateActionLabel, + Surface.bPreferredTemplateActionEnabled ? TEXT("enabled") : TEXT("disabled"), + *Surface.RecommendedPreviewActionLabel, + Surface.bRecommendedPreviewActionEnabled ? TEXT("enabled") : TEXT("disabled"), + *Surface.FollowUpPreviewActionLabel, + Surface.bFollowUpPreviewActionEnabled ? TEXT("enabled") : TEXT("disabled")); + Surface.DetailLine = FString::Printf( + TEXT("Template: %s | Recommended: %s | Follow-up: %s | preferred template %s | recommended deck %s | follow-up deck %s | active preview lane %s | live timer %s | active run %s | closed-loop idle %s"), + *Surface.PreferredTemplateStatusLine, + *Surface.RecommendedPreviewStatusLine, + *Surface.FollowUpPreviewStatusLine, + *Surface.PreferredTemplateTitle, + *Surface.RecommendedDeckLabel, + *Surface.FollowUpDeckLabel, + *Surface.ActivePreviewLaneLabel, + Surface.bHasLiveAttemptTimer ? TEXT("yes") : TEXT("no"), + Surface.bHasActiveRun ? TEXT("yes") : TEXT("no"), + Surface.bClosedLoopIdleDashboard ? TEXT("yes") : TEXT("no")); + return Surface; +} + FHyperTwistTrainingCoachDashboardActiveAttemptTimerStatusInspectSurface UHyperTwistCoachDashboardWidget::GetDisplayedActiveAttemptTimerStatusInspectSurface() const { diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h index a978f64..9f9e845 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h @@ -963,6 +963,10 @@ public: FHyperTwistTrainingCoachDashboardGuidancePreviewActionInspectSurface GetDisplayedFollowUpPreviewActionInspectSurface() const; + UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard") + FHyperTwistTrainingCoachDashboardTemplateLaunchPreviewActionControlBandInspectSurface + GetDisplayedTemplateLaunchPreviewActionControlBandInspectSurface() const; + UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard") FHyperTwistTrainingCoachDashboardActiveAttemptTimerStatusInspectSurface GetDisplayedActiveAttemptTimerStatusInspectSurface() const; diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h index 819ad2e..a7ca6ee 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h @@ -15097,6 +15097,91 @@ struct FHyperTwistTrainingCoachDashboardGuidancePreviewActionInspectSurface } }; +USTRUCT(BlueprintType) +struct FHyperTwistTrainingCoachDashboardTemplateLaunchPreviewActionControlBandInspectSurface +{ + 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 PreferredTemplateActionLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString RecommendedPreviewActionLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString FollowUpPreviewActionLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString PreferredTemplateStatusLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString RecommendedPreviewStatusLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString FollowUpPreviewStatusLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString PreferredTemplateTitle; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString RecommendedDeckLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString FollowUpDeckLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString ActivePreviewLaneLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasPreferredTemplate = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bRecommendedGuidanceReady = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bFollowUpGuidanceReady = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasLiveAttemptTimer = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasActiveRun = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bPreferredTemplateActionEnabled = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bRecommendedPreviewActionEnabled = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bFollowUpPreviewActionEnabled = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bAnyActionEnabled = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bClosedLoopIdleDashboard = false; + + bool IsStructurallyValid() const + { + return !StatusLine.IsEmpty() + || !DetailLine.IsEmpty() + || bHasPreferredTemplate + || bRecommendedGuidanceReady + || bFollowUpGuidanceReady + || bAnyActionEnabled; + } +}; + USTRUCT(BlueprintType) struct FHyperTwistTrainingCoachDashboardActiveAttemptTimerStatusInspectSurface { diff --git a/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md b/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md index 68caaf0..a08e4b4 100644 --- a/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md +++ b/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md @@ -70,7 +70,8 @@ Current correction call from the source-exposed audit and current execution refr - the retained idle widget surface now keeps retained comparison and decision history inspectable without continuing to advertise live launch or guidance-outcome actions once the coach-to-review loop has already collapsed to truthful closed-loop idle - 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 retained method-drill-recovery-memory-history band is now functionally complete enough to stop widening it by drift; the adjacent preferred template-launch plus recommended/follow-up preview action control band should also be treated as landed baseline, so 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 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 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_TEMPLATE_LAUNCH_PREVIEW_ACTION_CONTROL_BAND_INSPECT_SURFACE_PACKET_2026-05-11.md b/docs/arch/HYPERTWIST_PHASE4_DASHBOARD_TEMPLATE_LAUNCH_PREVIEW_ACTION_CONTROL_BAND_INSPECT_SURFACE_PACKET_2026-05-11.md new file mode 100644 index 0000000..14b4651 --- /dev/null +++ b/docs/arch/HYPERTWIST_PHASE4_DASHBOARD_TEMPLATE_LAUNCH_PREVIEW_ACTION_CONTROL_BAND_INSPECT_SURFACE_PACKET_2026-05-11.md @@ -0,0 +1,51 @@ +# HyperTwist Phase 4 dashboard template-launch preview action control band inspect surface packet + +- bounded Phase `4` dashboard-consumer slice +- date: `2026-05-11` + +## Intent + +Stay on the adjacent live dashboard consumer lane and expose the preferred template-launch plus recommended/follow-up preview action control band as one inspectable gameplay and Blueprint seam. + +## Why this packet exists + +`UHyperTwistCoachDashboardWidget` already exposed three adjacent action surfaces: + +- `GetDisplayedPreferredTemplateLaunchActionInspectSurface()` +- `GetDisplayedRecommendedPreviewActionInspectSurface()` +- `GetDisplayedFollowUpPreviewActionInspectSurface()` + +But callers that wanted to reason about that whole action-control cluster still had to stitch those three getters together manually even though the widget presents them as one adjacent band. + +## What changed + +- added `FHyperTwistTrainingCoachDashboardTemplateLaunchPreviewActionControlBandInspectSurface` +- added `GetDisplayedTemplateLaunchPreviewActionControlBandInspectSurface()` +- composed the new surface entirely over the already-landed preferred template-launch action surface plus recommended/follow-up preview action 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 template-launch / preview action-control band through one surface +- each action label and each action status line for template, recommended preview, and follow-up preview +- preferred template title, recommended/follow-up deck labels, active preview lane, live-timer posture, active-run posture, closed-loop-idle posture, and aggregate action enablement + +without stitching three separate action getters together manually. + +## Validation + +- full `Development Editor | Win64` MSBuild on `UnrealHyperTwist.sln` + - passed with `0 Warning(s), 0 Error(s)` + +## Next clean slice + +Treat both the retained-history text-band lane and the adjacent template-launch / preview action-control band as landed baseline, then deliberately choose a new adjacent live dashboard consumer band instead of reopening already-landed surfaces by drift.