From 5b99bc83b3cd200b11cf433a84558528bb785b2a Mon Sep 17 00:00:00 2001 From: axiomlogicnexus Date: Mon, 11 May 2026 15:27:11 +0200 Subject: [PATCH] Expose dashboard closure recovery band --- .../HyperTwistCoachDashboardWidget.cpp | 101 ++++++++++++++ .../HyperTwistCoachDashboardWidget.h | 4 + .../HyperTwistTrainingTypes.h | 126 ++++++++++++++++++ ...RTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md | 3 +- ..._BAND_INSPECT_SURFACE_PACKET_2026-05-11.md | 52 ++++++++ 5 files changed, 285 insertions(+), 1 deletion(-) create mode 100644 docs/arch/HYPERTWIST_PHASE4_DASHBOARD_CLOSURE_RECOVERY_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 40f9784..420ab5c 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp @@ -15782,6 +15782,107 @@ UHyperTwistCoachDashboardWidget::GetDisplayedClosureRecoveryDetailInspectSurface return Surface; } +FHyperTwistTrainingCoachDashboardClosureRecoveryBandInspectSurface +UHyperTwistCoachDashboardWidget::GetDisplayedClosureRecoveryBandInspectSurface() const +{ + FHyperTwistTrainingCoachDashboardClosureRecoveryBandInspectSurface Surface; + Surface.Headline = TEXT("Closure-recovery band"); + + const FHyperTwistTrainingCoachDashboardClosureRecoveryStatusInspectSurface StatusSurface = + GetDisplayedClosureRecoveryStatusInspectSurface(); + const FHyperTwistTrainingCoachDashboardClosureRecoveryDetailInspectSurface DetailSurface = + GetDisplayedClosureRecoveryDetailInspectSurface(); + const FHyperTwistTrainingCoachDashboardClosureRecoveryHistoryNavigationInspectSurface NavigationSurface = + GetDisplayedClosureRecoveryHistoryNavigationInspectSurface(); + + Surface.ClosureRecoveryStatusLine = StatusSurface.StatusLine.IsEmpty() + ? TEXT("Closure recovery status: unavailable.") + : StatusSurface.StatusLine; + Surface.ClosureRecoveryDetailLine = DetailSurface.DetailLine.IsEmpty() + ? TEXT("Closure recovery detail: unavailable.") + : DetailSurface.DetailLine; + Surface.ClosureRecoveryNavigationStatusLine = NavigationSurface.StatusLine.IsEmpty() + ? TEXT("Closure recovery navigation: unavailable.") + : NavigationSurface.StatusLine; + Surface.ClosureRecoveryNavigationDetailLine = NavigationSurface.DetailLine.IsEmpty() + ? TEXT("Closure recovery navigation detail: unavailable.") + : NavigationSurface.DetailLine; + Surface.ClosureRecoveryHistoryLabel = StatusSurface.ClosureRecoveryHistoryLabel.IsEmpty() + ? TEXT("n/a") + : StatusSurface.ClosureRecoveryHistoryLabel; + Surface.ClosurePolicyLine = !DetailSurface.ClosurePolicyLine.IsEmpty() + ? DetailSurface.ClosurePolicyLine + : (StatusSurface.ClosurePolicyLine.IsEmpty() ? TEXT("n/a") : StatusSurface.ClosurePolicyLine); + Surface.GuidanceLaneLabel = !DetailSurface.GuidanceLaneLabel.IsEmpty() + ? DetailSurface.GuidanceLaneLabel + : (StatusSurface.GuidanceLaneLabel.IsEmpty() ? TEXT("none") : StatusSurface.GuidanceLaneLabel); + Surface.PreferredGuidanceSourceLabel = DetailSurface.PreferredGuidanceSourceLabel.IsEmpty() + ? TEXT("none") + : DetailSurface.PreferredGuidanceSourceLabel; + Surface.PreferredGuidanceSourceDescription = !DetailSurface.PreferredGuidanceSourceDescription.IsEmpty() + ? DetailSurface.PreferredGuidanceSourceDescription + : NavigationSurface.PreferredGuidanceSourceDescription; + Surface.ActiveSignalId = !DetailSurface.ActiveSignalId.IsEmpty() + ? DetailSurface.ActiveSignalId + : (StatusSurface.ActiveSignalId.IsEmpty() ? TEXT("none") : StatusSurface.ActiveSignalId); + Surface.ActiveSignalHeadline = StatusSurface.ActiveSignalHeadline.IsEmpty() + ? TEXT("n/a") + : StatusSurface.ActiveSignalHeadline; + Surface.ActiveSignalPriorityLabel = StatusSurface.ActiveSignalPriorityLabel.IsEmpty() + ? TEXT("n/a") + : StatusSurface.ActiveSignalPriorityLabel; + Surface.ActiveSignalDetail = DetailSurface.ActiveSignalDetail.IsEmpty() + ? TEXT("") + : DetailSurface.ActiveSignalDetail; + Surface.PreviousLabel = NavigationSurface.PreviousLabel.IsEmpty() ? TEXT("Prev Closure Recovery") : NavigationSurface.PreviousLabel; + Surface.NextLabel = NavigationSurface.NextLabel.IsEmpty() ? TEXT("Next Closure Recovery") : NavigationSurface.NextLabel; + Surface.SelectedEntryOrdinal = NavigationSurface.SelectedEntryOrdinal.IsEmpty() + ? TEXT("none") + : NavigationSurface.SelectedEntryOrdinal; + Surface.RecordedAtUtc = NavigationSurface.RecordedAtUtc.IsEmpty() ? TEXT("n/a") : NavigationSurface.RecordedAtUtc; + Surface.SelectedLaneLabel = NavigationSurface.SelectedLaneLabel.IsEmpty() ? TEXT("none") : NavigationSurface.SelectedLaneLabel; + Surface.SelectedEntryIndex = NavigationSurface.SelectedEntryIndex; + Surface.HistoryEntryCount = NavigationSurface.HistoryEntryCount; + Surface.HistoricalFollowUpContinuationCount = StatusSurface.HistoricalFollowUpContinuationCount; + Surface.HistoricalBorderlineFollowUpSuppressionCount = + StatusSurface.HistoricalBorderlineFollowUpSuppressionCount; + Surface.ActiveSignalScore = StatusSurface.ActiveSignalScore; + Surface.PreferredGuidanceLane = StatusSurface.PreferredGuidanceLane; + Surface.bHasClosureRecoveryHistory = + StatusSurface.bHasClosureRecoveryHistory || DetailSurface.bHasClosureRecoveryHistory; + Surface.bHasActiveSignal = StatusSurface.bHasActiveSignal || DetailSurface.bHasActiveSignal; + Surface.bActiveSignalPromoted = StatusSurface.bActiveSignalPromoted; + Surface.bFollowUpContinuationFromRecoveryHistory = + DetailSurface.bFollowUpContinuationFromRecoveryHistory; + Surface.bBorderlineFollowUpSuppressedByRecoveryHistory = + DetailSurface.bBorderlineFollowUpSuppressedByRecoveryHistory; + Surface.bHasSelectedEntry = NavigationSurface.bHasSelectedEntry; + Surface.bSelectedEntryIsLatest = NavigationSurface.bSelectedEntryIsLatest; + Surface.bPreviousEnabled = NavigationSurface.bPreviousEnabled; + Surface.bNextEnabled = NavigationSurface.bNextEnabled; + Surface.StatusLine = FString::Printf( + TEXT("Closure-recovery band: %s | lane %s | selected %s | signal %s | navigation %s/%s"), + *Surface.ClosureRecoveryHistoryLabel, + *Surface.GuidanceLaneLabel, + *Surface.SelectedEntryOrdinal, + *Surface.ActiveSignalId, + Surface.bPreviousEnabled ? TEXT("enabled") : TEXT("disabled"), + Surface.bNextEnabled ? TEXT("enabled") : TEXT("disabled")); + Surface.DetailLine = FString::Printf( + TEXT("%s | %s | %s | %s | policy %s | source %s | signal headline %s | signal priority %s | recorded %s | latest %s"), + *Surface.ClosureRecoveryStatusLine, + *Surface.ClosureRecoveryDetailLine, + *Surface.ClosureRecoveryNavigationStatusLine, + *Surface.ClosureRecoveryNavigationDetailLine, + *Surface.ClosurePolicyLine, + *Surface.PreferredGuidanceSourceDescription, + *Surface.ActiveSignalHeadline, + *Surface.ActiveSignalPriorityLabel, + *Surface.RecordedAtUtc, + Surface.bSelectedEntryIsLatest ? TEXT("yes") : TEXT("no")); + return Surface; +} + FHyperTwistTrainingCoachDashboardLastAttemptReviewSummaryInspectSurface UHyperTwistCoachDashboardWidget::GetDisplayedLastAttemptReviewSummaryInspectSurface() const { diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h index ea03c8e..faf66ff 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h @@ -1067,6 +1067,10 @@ public: FHyperTwistTrainingCoachDashboardClosureRecoveryDetailInspectSurface GetDisplayedClosureRecoveryDetailInspectSurface() const; + UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard") + FHyperTwistTrainingCoachDashboardClosureRecoveryBandInspectSurface + GetDisplayedClosureRecoveryBandInspectSurface() const; + UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard") FHyperTwistTrainingCoachDashboardLastAttemptReviewSummaryInspectSurface GetDisplayedLastAttemptReviewSummaryInspectSurface() const; diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h index 571e542..fc43cab 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h @@ -14808,6 +14808,132 @@ struct FHyperTwistTrainingCoachDashboardClosureRecoveryDetailInspectSurface } }; +USTRUCT(BlueprintType) +struct FHyperTwistTrainingCoachDashboardClosureRecoveryBandInspectSurface +{ + 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 ClosureRecoveryStatusLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString ClosureRecoveryDetailLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString ClosureRecoveryNavigationStatusLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString ClosureRecoveryNavigationDetailLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString ClosureRecoveryHistoryLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString ClosurePolicyLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString GuidanceLaneLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString PreferredGuidanceSourceLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString PreferredGuidanceSourceDescription; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString ActiveSignalId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString ActiveSignalHeadline; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString ActiveSignalPriorityLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString ActiveSignalDetail; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString PreviousLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString NextLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SelectedEntryOrdinal; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString RecordedAtUtc; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SelectedLaneLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 SelectedEntryIndex = INDEX_NONE; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 HistoryEntryCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 HistoricalFollowUpContinuationCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 HistoricalBorderlineFollowUpSuppressionCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + float ActiveSignalScore = 0.0f; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + EHyperTwistTrainingCoachGuidanceLane PreferredGuidanceLane = + EHyperTwistTrainingCoachGuidanceLane::None; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasClosureRecoveryHistory = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasActiveSignal = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bActiveSignalPromoted = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bFollowUpContinuationFromRecoveryHistory = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bBorderlineFollowUpSuppressedByRecoveryHistory = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasSelectedEntry = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bSelectedEntryIsLatest = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bPreviousEnabled = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bNextEnabled = false; + + bool IsStructurallyValid() const + { + return !StatusLine.IsEmpty() + || !DetailLine.IsEmpty() + || bHasClosureRecoveryHistory + || bHasActiveSignal + || bHasSelectedEntry + || bPreviousEnabled + || bNextEnabled; + } +}; + USTRUCT(BlueprintType) struct FHyperTwistTrainingCoachDashboardLastAttemptReviewSummaryInspectSurface { diff --git a/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md b/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md index 4dc5dd3..063991d 100644 --- a/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md +++ b/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md @@ -75,7 +75,8 @@ Current correction call from the source-exposed audit and current execution refr - the latest landed bounded `Phase 4` packet deliberately chooses another adjacent live dashboard consumer band and adds a single composite verification / recognition / review-policy seam over the already-landed verification action, repository verification status, recognition status, and review-policy status surfaces, so gameplay/Blueprint callers can inspect that whole status cluster without stitching four adjacent getters together - the latest landed bounded `Phase 4` packet deliberately chooses another adjacent live dashboard consumer band and adds a single composite selected-queue seam over the already-landed selected-queue navigation, start-selected action, selected-queue summary, and selected queue-entry detail surfaces, so gameplay/Blueprint callers can inspect that whole queue-focused dashboard cluster without stitching four adjacent getters together - the latest landed bounded `Phase 4` packet deliberately chooses another adjacent live dashboard consumer band and adds a single queue scheduling / recovery seam over the already-landed queue counts / status, schedule horizon, schedule policy / friction, and queue recovery live status/detail surfaces, so gameplay/Blueprint callers can inspect that whole scheduling-and-recovery dashboard cluster without stitching five adjacent getters together - - with the retained-history text-band lane, the template-launch / preview action-control band, the execution-action-control band, the verification / recognition / review-policy status band, the selected-queue band, and the queue scheduling / recovery 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 surfaces by drift + - the latest landed bounded `Phase 4` packet deliberately chooses another adjacent live dashboard consumer band and adds a single closure-recovery seam over the already-landed closure-recovery live status/detail and closure-recovery history navigation surfaces, so gameplay/Blueprint callers can inspect that whole closure-recovery dashboard cluster without stitching three adjacent getters together + - with the retained-history text-band lane, the template-launch / preview action-control band, the execution-action-control band, the verification / recognition / review-policy status band, the selected-queue band, the queue scheduling / recovery band, and the closure-recovery 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 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_CLOSURE_RECOVERY_BAND_INSPECT_SURFACE_PACKET_2026-05-11.md b/docs/arch/HYPERTWIST_PHASE4_DASHBOARD_CLOSURE_RECOVERY_BAND_INSPECT_SURFACE_PACKET_2026-05-11.md new file mode 100644 index 0000000..0910148 --- /dev/null +++ b/docs/arch/HYPERTWIST_PHASE4_DASHBOARD_CLOSURE_RECOVERY_BAND_INSPECT_SURFACE_PACKET_2026-05-11.md @@ -0,0 +1,52 @@ +# HyperTwist Phase 4 dashboard closure recovery band inspect surface packet + +- bounded Phase `4` dashboard-consumer slice +- date: `2026-05-11` + +## Intent + +Deliberately choose another adjacent live dashboard consumer band and expose the closure-recovery status, closure-recovery detail, and closure-recovery history navigation cluster as one inspectable gameplay and Blueprint seam. + +## Why this packet exists + +`UHyperTwistCoachDashboardWidget` already exposed three adjacent closure-recovery surfaces: + +- `GetDisplayedClosureRecoveryStatusInspectSurface()` +- `GetDisplayedClosureRecoveryDetailInspectSurface()` +- `GetDisplayedClosureRecoveryHistoryNavigationInspectSurface()` + +But callers that wanted to reason about that whole closure-recovery dashboard cluster still had to stitch those adjacent getters together manually. + +## What changed + +- added `FHyperTwistTrainingCoachDashboardClosureRecoveryBandInspectSurface` +- added `GetDisplayedClosureRecoveryBandInspectSurface()` +- composed the new surface entirely over the already-landed closure-recovery live status, closure-recovery detail, and closure-recovery history navigation 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 closure-recovery dashboard band through one surface +- closure-recovery live status/detail plus history-navigation status/detail lines together +- closure history label, closure policy, guidance lane, preferred guidance source, active signal context, entry ordinal, recorded time, and selected lane context +- closure-recovery history posture, active-signal posture, follow-up continuation/suppression posture, and navigation enablement posture + +without stitching three separate adjacent 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, the execution-action-control band, the verification / recognition / review-policy status band, the selected-queue band, the queue scheduling / recovery band, and the closure-recovery band as landed baseline, then deliberately choose another adjacent live dashboard consumer band instead of reopening already-landed surfaces by drift.