diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp index c3628c2..4267860 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp @@ -15275,6 +15275,110 @@ UHyperTwistCoachDashboardWidget::GetDisplayedSelectedQueueEntryDetailInspectSurf return Surface; } +FHyperTwistTrainingCoachDashboardSelectedQueueBandInspectSurface +UHyperTwistCoachDashboardWidget::GetDisplayedSelectedQueueBandInspectSurface() const +{ + FHyperTwistTrainingCoachDashboardSelectedQueueBandInspectSurface Surface; + Surface.Headline = TEXT("Selected-queue band"); + + const FHyperTwistTrainingCoachDashboardSelectedQueueNavigationInspectSurface NavigationSurface = + GetDisplayedSelectedQueueNavigationInspectSurface(); + const FHyperTwistTrainingCoachDashboardStartSelectedQueueActionInspectSurface StartSurface = + GetDisplayedStartSelectedQueueActionInspectSurface(); + const FHyperTwistTrainingCoachDashboardSelectedQueueSummaryInspectSurface SummarySurface = + GetDisplayedSelectedQueueSummaryInspectSurface(); + const FHyperTwistTrainingCoachDashboardSelectedQueueEntryDetailInspectSurface DetailSurface = + GetDisplayedSelectedQueueEntryDetailInspectSurface(); + + Surface.NavigationStatusLine = NavigationSurface.StatusLine.IsEmpty() + ? TEXT("Selected-queue navigation: unavailable.") + : NavigationSurface.StatusLine; + Surface.SummaryStatusLine = SummarySurface.StatusLine.IsEmpty() + ? TEXT("Selected queue summary: unavailable.") + : SummarySurface.StatusLine; + Surface.EntryDetailLine = DetailSurface.DetailLine.IsEmpty() + ? TEXT("Selected queue detail: unavailable.") + : DetailSurface.DetailLine; + Surface.StartSelectedStatusLine = StartSurface.StatusLine.IsEmpty() + ? TEXT("Start selected action: unavailable.") + : StartSurface.StatusLine; + Surface.PreviousLabel = NavigationSurface.PreviousLabel.IsEmpty() ? TEXT("Prev Queue") : NavigationSurface.PreviousLabel; + Surface.NextLabel = NavigationSurface.NextLabel.IsEmpty() ? TEXT("Next Queue") : NavigationSurface.NextLabel; + Surface.StartSelectedLabel = StartSurface.StartSelectedLabel.IsEmpty() + ? TEXT("Start Selected") + : StartSurface.StartSelectedLabel; + Surface.SelectedQueueEntryId = !SummarySurface.SelectedQueueEntryId.IsEmpty() + ? SummarySurface.SelectedQueueEntryId + : (DetailSurface.SelectedQueueEntryId.IsEmpty() ? TEXT("none") : DetailSurface.SelectedQueueEntryId); + Surface.SelectedQueueSourceLabel = !SummarySurface.SelectedQueueSourceLabel.IsEmpty() + ? SummarySurface.SelectedQueueSourceLabel + : (NavigationSurface.SelectedQueueSourceLabel.IsEmpty() + ? TEXT("n/a") + : NavigationSurface.SelectedQueueSourceLabel); + Surface.SelectedQueueStateLabel = !SummarySurface.SelectedQueueStateLabel.IsEmpty() + ? SummarySurface.SelectedQueueStateLabel + : (NavigationSurface.SelectedQueueStateLabel.IsEmpty() + ? TEXT("n/a") + : NavigationSurface.SelectedQueueStateLabel); + Surface.SelectedQueuePriorityLabel = SummarySurface.SelectedQueuePriorityLabel.IsEmpty() + ? TEXT("n/a") + : SummarySurface.SelectedQueuePriorityLabel; + Surface.SelectedQueueOrdinal = !SummarySurface.SelectedQueueOrdinal.IsEmpty() + ? SummarySurface.SelectedQueueOrdinal + : (NavigationSurface.SelectedQueueOrdinal.IsEmpty() + ? TEXT("none") + : NavigationSurface.SelectedQueueOrdinal); + Surface.EntryHeadline = DetailSurface.EntryHeadline.IsEmpty() ? TEXT("n/a") : DetailSurface.EntryHeadline; + Surface.FocusDeckId = DetailSurface.FocusDeckId.IsEmpty() ? TEXT("n/a") : DetailSurface.FocusDeckId; + Surface.FocusMethodSegmentId = DetailSurface.FocusMethodSegmentId.IsEmpty() + ? TEXT("n/a") + : DetailSurface.FocusMethodSegmentId; + Surface.SelectedQueuePriorityScore = SummarySurface.SelectedQueuePriorityScore; + Surface.SelectedQueueEntryIndex = SummarySurface.SelectedQueueEntryIndex; + Surface.TotalQueueEntries = SummarySurface.TotalQueueEntries; + Surface.FocusCaseCount = DetailSurface.FocusCaseCount; + Surface.bHasSelectedQueueEntry = + NavigationSurface.bHasSelectedQueueEntry + || SummarySurface.bHasSelectedQueueEntry + || DetailSurface.bHasSelectedQueueEntry + || StartSurface.bHasSelectedQueueEntry; + Surface.bHasLiveAttemptTimer = NavigationSurface.bHasLiveAttemptTimer || StartSurface.bHasLiveAttemptTimer; + Surface.bSelectedEntryMatchesActiveQueue = SummarySurface.bSelectedEntryMatchesActiveQueue; + Surface.bPreviousEnabled = NavigationSurface.bPreviousEnabled; + Surface.bNextEnabled = NavigationSurface.bNextEnabled; + Surface.bSelectedEntryReady = StartSurface.bSelectedEntryReady; + Surface.bSelectedEntryPendingStartImmediate = StartSurface.bSelectedEntryPendingStartImmediate; + Surface.bStartSelectedEnabled = StartSurface.bStartSelectedEnabled; + Surface.bRequiresFollowUp = DetailSurface.bRequiresFollowUp; + Surface.bRequiresArchiveRetentionTuning = DetailSurface.bRequiresArchiveRetentionTuning; + Surface.bPinned = DetailSurface.bPinned; + Surface.bCanStartImmediately = DetailSurface.bCanStartImmediately; + Surface.StatusLine = FString::Printf( + TEXT("Selected queue band: %s | %s | Start: %s (%s)"), + *Surface.SelectedQueueOrdinal, + *Surface.SelectedQueueStateLabel, + *Surface.StartSelectedLabel, + Surface.bStartSelectedEnabled ? TEXT("enabled") : TEXT("disabled")); + Surface.DetailLine = FString::Printf( + TEXT("%s | %s | %s | entry %s | source %s | priority %s (%.1f) | focus deck %s | method %s | cases %d | active queue match %s | prev %s | next %s | pinned %s | immediate %s"), + *Surface.NavigationStatusLine, + *Surface.SummaryStatusLine, + *Surface.StartSelectedStatusLine, + *Surface.SelectedQueueEntryId, + *Surface.SelectedQueueSourceLabel, + *Surface.SelectedQueuePriorityLabel, + Surface.SelectedQueuePriorityScore, + *Surface.FocusDeckId, + *Surface.FocusMethodSegmentId, + Surface.FocusCaseCount, + Surface.bSelectedEntryMatchesActiveQueue ? TEXT("yes") : TEXT("no"), + Surface.bPreviousEnabled ? TEXT("enabled") : TEXT("disabled"), + Surface.bNextEnabled ? TEXT("enabled") : TEXT("disabled"), + Surface.bPinned ? TEXT("yes") : TEXT("no"), + Surface.bCanStartImmediately ? TEXT("yes") : TEXT("no")); + return Surface; +} + FHyperTwistTrainingCoachDashboardScheduleHorizonStatusInspectSurface UHyperTwistCoachDashboardWidget::GetDisplayedScheduleHorizonStatusInspectSurface() const { diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h index 58ae194..6eae2c5 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h @@ -1043,6 +1043,10 @@ public: FHyperTwistTrainingCoachDashboardSelectedQueueEntryDetailInspectSurface GetDisplayedSelectedQueueEntryDetailInspectSurface() const; + UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard") + FHyperTwistTrainingCoachDashboardSelectedQueueBandInspectSurface + GetDisplayedSelectedQueueBandInspectSurface() const; + UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard") FHyperTwistTrainingCoachDashboardScheduleHorizonStatusInspectSurface GetDisplayedScheduleHorizonStatusInspectSurface() const; diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h index 741cfab..5761a0d 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h @@ -14276,6 +14276,124 @@ struct FHyperTwistTrainingCoachDashboardSelectedQueueEntryDetailInspectSurface } }; +USTRUCT(BlueprintType) +struct FHyperTwistTrainingCoachDashboardSelectedQueueBandInspectSurface +{ + 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 NavigationStatusLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SummaryStatusLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString EntryDetailLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString StartSelectedStatusLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString PreviousLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString NextLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString StartSelectedLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SelectedQueueEntryId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SelectedQueueSourceLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SelectedQueueStateLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SelectedQueuePriorityLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SelectedQueueOrdinal; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString EntryHeadline; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString FocusDeckId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString FocusMethodSegmentId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + float SelectedQueuePriorityScore = 0.0f; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 SelectedQueueEntryIndex = INDEX_NONE; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 TotalQueueEntries = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 FocusCaseCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasSelectedQueueEntry = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasLiveAttemptTimer = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bSelectedEntryMatchesActiveQueue = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bPreviousEnabled = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bNextEnabled = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bSelectedEntryReady = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bSelectedEntryPendingStartImmediate = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bStartSelectedEnabled = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bRequiresFollowUp = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bRequiresArchiveRetentionTuning = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bPinned = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bCanStartImmediately = false; + + bool IsStructurallyValid() const + { + return !StatusLine.IsEmpty() + || !DetailLine.IsEmpty() + || bHasSelectedQueueEntry + || bStartSelectedEnabled + || bPreviousEnabled + || bNextEnabled; + } +}; + USTRUCT(BlueprintType) struct FHyperTwistTrainingCoachDashboardScheduleHorizonStatusInspectSurface { diff --git a/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md b/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md index a24b94e..e03e03f 100644 --- a/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md +++ b/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md @@ -73,7 +73,8 @@ Current correction call from the source-exposed audit and current execution refr - 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 - 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 - 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 - - with the retained-history text-band lane, the template-launch / preview action-control band, the execution-action-control band, and the verification / recognition / review-policy status 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/status surfaces by drift + - 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 + - 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, and the selected-queue 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/status/queue 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_SELECTED_QUEUE_BAND_INSPECT_SURFACE_PACKET_2026-05-11.md b/docs/arch/HYPERTWIST_PHASE4_DASHBOARD_SELECTED_QUEUE_BAND_INSPECT_SURFACE_PACKET_2026-05-11.md new file mode 100644 index 0000000..09fceb8 --- /dev/null +++ b/docs/arch/HYPERTWIST_PHASE4_DASHBOARD_SELECTED_QUEUE_BAND_INSPECT_SURFACE_PACKET_2026-05-11.md @@ -0,0 +1,53 @@ +# HyperTwist Phase 4 dashboard selected queue 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 selected-queue navigation, start-selected action, selected-queue summary, and selected queue-entry detail cluster as one inspectable gameplay and Blueprint seam. + +## Why this packet exists + +`UHyperTwistCoachDashboardWidget` already exposed four adjacent selected-queue surfaces: + +- `GetDisplayedSelectedQueueNavigationInspectSurface()` +- `GetDisplayedStartSelectedQueueActionInspectSurface()` +- `GetDisplayedSelectedQueueSummaryInspectSurface()` +- `GetDisplayedSelectedQueueEntryDetailInspectSurface()` + +But callers that wanted to reason about that whole queue-focused dashboard cluster still had to stitch those four getters together manually even though the widget presents them as one adjacent selected-queue band. + +## What changed + +- added `FHyperTwistTrainingCoachDashboardSelectedQueueBandInspectSurface` +- added `GetDisplayedSelectedQueueBandInspectSurface()` +- composed the new surface entirely over the already-landed selected-queue navigation, start-selected action, selected-queue summary, and selected queue-entry detail 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 selected-queue dashboard band through one surface +- the selected-queue navigation, summary, entry-detail, and start-selected status lines together +- queue navigation labels, start-selected label, selected queue id/source/state/priority/ordinal, and entry headline/deck/method context +- selected-queue matching, navigation enablement, start-selected enablement, readiness/immediacy posture, and pinned/follow-up/archive-tuning posture + +without stitching four 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, and the selected-queue band as landed baseline, then deliberately choose another adjacent live dashboard consumer band instead of reopening already-landed surfaces by drift.