From 3adfb010f5d3d65b412844e368e19a3485f3bc52 Mon Sep 17 00:00:00 2001 From: axiomlogicnexus Date: Sun, 10 May 2026 19:29:39 +0200 Subject: [PATCH] Expose dashboard handoff history status and detail surfaces --- .../HyperTwistCoachDashboardWidget.cpp | 92 +++++++++++++ .../HyperTwistCoachDashboardWidget.h | 10 ++ .../HyperTwistTrainingTypes.h | 128 ++++++++++++++++++ ...RTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md | 4 +- ...ETAIL_INSPECT_SURFACE_PACKET_2026-05-10.md | 53 ++++++++ 5 files changed, 285 insertions(+), 2 deletions(-) create mode 100644 docs/arch/HYPERTWIST_PHASE4_DASHBOARD_HANDOFF_HISTORY_STATUS_DETAIL_INSPECT_SURFACE_PACKET_2026-05-10.md diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp index b9fe5f0..338c994 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp @@ -9034,6 +9034,96 @@ UHyperTwistCoachDashboardWidget::GetSelectedHandoffHistoryInspectSurface() const return Surface; } +FHyperTwistTrainingCoachDashboardHandoffHistoryStatusInspectSurface +UHyperTwistCoachDashboardWidget::GetDisplayedHandoffHistoryStatusInspectSurface() const +{ + FHyperTwistTrainingCoachDashboardHandoffHistoryStatusInspectSurface Surface; + Surface.Headline = TEXT("Handoff history status"); + + const FHyperTwistTrainingCoachDashboardHandoffHistoryInspectSurface HistorySurface = + GetSelectedHandoffHistoryInspectSurface(); + const FHyperTwistTrainingCoachDashboardHandoffHistoryNavigationInspectSurface NavigationSurface = + GetDisplayedHandoffHistoryNavigationInspectSurface(); + + Surface.StatusLine = !DisplayedHandoffHistoryStatusLine.IsEmpty() + ? DisplayedHandoffHistoryStatusLine + : HistorySurface.StatusLine; + Surface.SelectedEntryOrdinal = NavigationSurface.SelectedEntryOrdinal.IsEmpty() + ? TEXT("none") + : NavigationSurface.SelectedEntryOrdinal; + Surface.RecordedAtUtc = + HistorySurface.RecordedAtUtc.IsEmpty() ? TEXT("n/a") : HistorySurface.RecordedAtUtc; + Surface.RecommendedHandoffKindLabel = HistorySurface.RecommendedHandoffKindLabel.IsEmpty() + ? TEXT("none") + : HistorySurface.RecommendedHandoffKindLabel; + Surface.RetainedPostureLine = HistorySurface.RetainedPostureLine.IsEmpty() + ? TEXT("n/a") + : HistorySurface.RetainedPostureLine; + Surface.ReliablePlanLine = HistorySurface.ReliablePlanLine.IsEmpty() + ? TEXT("none") + : HistorySurface.ReliablePlanLine; + Surface.SelectedEntryIndex = HistorySurface.SelectedEntryIndex; + Surface.HistoryEntryCount = HistorySurface.HistoryEntryCount; + Surface.bHasSelectedEntry = HistorySurface.bHasSelectedEntry; + Surface.bSelectedEntryIsLatest = NavigationSurface.bSelectedEntryIsLatest; + return Surface; +} + +FHyperTwistTrainingCoachDashboardHandoffHistoryDetailInspectSurface +UHyperTwistCoachDashboardWidget::GetDisplayedHandoffHistoryDetailInspectSurface() const +{ + FHyperTwistTrainingCoachDashboardHandoffHistoryDetailInspectSurface Surface; + Surface.Headline = TEXT("Handoff history detail"); + + const FHyperTwistTrainingCoachDashboardHandoffHistoryInspectSurface HistorySurface = + GetSelectedHandoffHistoryInspectSurface(); + + Surface.DetailLine = !DisplayedHandoffHistoryDetailLine.IsEmpty() + ? DisplayedHandoffHistoryDetailLine + : HistorySurface.DetailLine; + Surface.RecommendationDetailLine = HistorySurface.RecommendationDetailLine.IsEmpty() + ? TEXT("n/a") + : HistorySurface.RecommendationDetailLine; + Surface.QueueSourceLabel = + HistorySurface.QueueSourceLabel.IsEmpty() ? TEXT("n/a") : HistorySurface.QueueSourceLabel; + Surface.PreferredLaneLine = + HistorySurface.PreferredLaneLine.IsEmpty() ? TEXT("none") : HistorySurface.PreferredLaneLine; + Surface.PreferredGuidanceSourceDescription = + HistorySurface.PreferredGuidanceSourceDescription.IsEmpty() + ? TEXT("n/a") + : HistorySurface.PreferredGuidanceSourceDescription; + Surface.PreferredRecoveryActionLabel = + HistorySurface.PreferredRecoveryActionLabel.IsEmpty() + ? TEXT("n/a") + : HistorySurface.PreferredRecoveryActionLabel; + Surface.PreferredRecoveryActionSourceDescription = + HistorySurface.PreferredRecoveryActionSourceDescription.IsEmpty() + ? TEXT("n/a") + : HistorySurface.PreferredRecoveryActionSourceDescription; + Surface.ReliablePlanLine = HistorySurface.ReliablePlanLine.IsEmpty() + ? TEXT("none") + : HistorySurface.ReliablePlanLine; + Surface.RetainedPostureLine = HistorySurface.RetainedPostureLine.IsEmpty() + ? TEXT("n/a") + : HistorySurface.RetainedPostureLine; + Surface.SelectedEntryIndex = HistorySurface.SelectedEntryIndex; + Surface.HistoryEntryCount = HistorySurface.HistoryEntryCount; + Surface.AcceptedQueuedHandoffCount = HistorySurface.AcceptedQueuedHandoffCount; + Surface.AcceptedFollowUpHandoffCount = HistorySurface.AcceptedFollowUpHandoffCount; + Surface.AcceptedRecommendedHandoffCount = + HistorySurface.AcceptedRecommendedHandoffCount; + Surface.ClosureContinuationBias = HistorySurface.ClosureContinuationBias; + Surface.ClosureSuppressionBias = HistorySurface.ClosureSuppressionBias; + Surface.bHasSelectedEntry = HistorySurface.bHasSelectedEntry; + Surface.bQueueReady = HistorySurface.bQueueReady; + Surface.bFollowUpReady = HistorySurface.bFollowUpReady; + Surface.bRecommendedReady = HistorySurface.bRecommendedReady; + Surface.bUsedDeferredFirstSuppressionSignal = + HistorySurface.bUsedDeferredFirstSuppressionSignal; + Surface.bUsedMethodDrillWeighting = HistorySurface.bUsedMethodDrillWeighting; + return Surface; +} + FHyperTwistTrainingCoachDashboardHandoffHistoryNavigationInspectSurface UHyperTwistCoachDashboardWidget::GetDisplayedHandoffHistoryNavigationInspectSurface() const { @@ -26519,10 +26609,12 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation() { HandoffHistoryHeaderTextBlock->SetText(FText::FromString(TEXT("[Handoff History]"))); } + DisplayedHandoffHistoryStatusLine = HandoffHistoryStatusLine; if (HandoffHistoryStatusTextBlock != nullptr) { HandoffHistoryStatusTextBlock->SetText(FText::FromString(HandoffHistoryStatusLine)); } + DisplayedHandoffHistoryDetailLine = HandoffHistoryDetailLine; if (HandoffHistoryDetailTextBlock != nullptr) { HandoffHistoryDetailTextBlock->SetText(FText::FromString(HandoffHistoryDetailLine)); diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h index 3c976d4..43b50f1 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h @@ -791,6 +791,14 @@ public: FHyperTwistTrainingCoachDashboardHandoffHistoryInspectSurface GetSelectedHandoffHistoryInspectSurface() const; + UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard") + FHyperTwistTrainingCoachDashboardHandoffHistoryStatusInspectSurface + GetDisplayedHandoffHistoryStatusInspectSurface() const; + + UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard") + FHyperTwistTrainingCoachDashboardHandoffHistoryDetailInspectSurface + GetDisplayedHandoffHistoryDetailInspectSurface() const; + UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard") FHyperTwistTrainingCoachDashboardHandoffHistoryNavigationInspectSurface GetDisplayedHandoffHistoryNavigationInspectSurface() const; @@ -2128,6 +2136,8 @@ private: FString DisplayedSchedulePolicyLine; FString DisplayedClosureRecoveryStatusLine; FString DisplayedClosureRecoveryDetailLine; + FString DisplayedHandoffHistoryStatusLine; + FString DisplayedHandoffHistoryDetailLine; FString DisplayedPreviousQueueNavigationLabel; FString DisplayedStartSelectedQueueActionLabel; FString DisplayedNextQueueNavigationLabel; diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h index 82e58c6..be0d008 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h @@ -10073,6 +10073,134 @@ struct FHyperTwistTrainingCoachDashboardMethodDrillFollowUpHistoryInspectSurface } }; +USTRUCT(BlueprintType) +struct FHyperTwistTrainingCoachDashboardHandoffHistoryStatusInspectSurface +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString Headline; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString StatusLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SelectedEntryOrdinal; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString RecordedAtUtc; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString RecommendedHandoffKindLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString RetainedPostureLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString ReliablePlanLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 SelectedEntryIndex = INDEX_NONE; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 HistoryEntryCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasSelectedEntry = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bSelectedEntryIsLatest = false; + + bool IsStructurallyValid() const + { + return !StatusLine.IsEmpty() + || bHasSelectedEntry + || HistoryEntryCount > 0; + } +}; + +USTRUCT(BlueprintType) +struct FHyperTwistTrainingCoachDashboardHandoffHistoryDetailInspectSurface +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString Headline; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString DetailLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString RecommendationDetailLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString QueueSourceLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString PreferredLaneLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString PreferredGuidanceSourceDescription; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString PreferredRecoveryActionLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString PreferredRecoveryActionSourceDescription; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString ReliablePlanLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString RetainedPostureLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 SelectedEntryIndex = INDEX_NONE; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 HistoryEntryCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 AcceptedQueuedHandoffCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 AcceptedFollowUpHandoffCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 AcceptedRecommendedHandoffCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 ClosureContinuationBias = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 ClosureSuppressionBias = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasSelectedEntry = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bQueueReady = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bFollowUpReady = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bRecommendedReady = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bUsedDeferredFirstSuppressionSignal = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bUsedMethodDrillWeighting = false; + + bool IsStructurallyValid() const + { + return !DetailLine.IsEmpty() + || bHasSelectedEntry + || HistoryEntryCount > 0; + } +}; + USTRUCT(BlueprintType) struct FHyperTwistTrainingCoachDashboardHandoffHistoryNavigationInspectSurface { diff --git a/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md b/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md index 70a61a8..918925a 100644 --- a/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md +++ b/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md @@ -69,8 +69,8 @@ Current correction call from the source-exposed audit and current execution refr - the latest landed bounded `Phase 4` packet closes the retained-idle comparison/outcome actionability gap at the end of the recognition-assisted coach-to-review continuity lane, and the final retained-surface confirmation pass now leaves that closure lane functionally complete - 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 live dashboard consumer lane and adds the dedicated template-launch 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 template-launch history text band directly without scraping text blocks or routing only through the broader selected-history and navigation surfaces - - the retained template-launch history band is now functionally complete enough to stop widening it by drift; the next best clean move is to stay adjacent in the same retained-history dashboard neighborhood and expose the displayed handoff history status/detail pair over the current handoff-history text band + - the latest landed bounded `Phase 4` packet stays adjacent in that same retained-history dashboard lane and adds the dedicated handoff 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 handoff-history text band directly without scraping text blocks or routing only through the broader selected-history and navigation surfaces + - the retained handoff-history band is now functionally complete enough to stop widening it by drift; the next best clean move is to stay in that same retained-history dashboard neighborhood and expose the displayed guidance-decision history status/detail pair over the current guidance-decision-history text band - 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_HANDOFF_HISTORY_STATUS_DETAIL_INSPECT_SURFACE_PACKET_2026-05-10.md b/docs/arch/HYPERTWIST_PHASE4_DASHBOARD_HANDOFF_HISTORY_STATUS_DETAIL_INSPECT_SURFACE_PACKET_2026-05-10.md new file mode 100644 index 0000000..4180fa9 --- /dev/null +++ b/docs/arch/HYPERTWIST_PHASE4_DASHBOARD_HANDOFF_HISTORY_STATUS_DETAIL_INSPECT_SURFACE_PACKET_2026-05-10.md @@ -0,0 +1,53 @@ +# HyperTwist Phase 4 dashboard handoff history status detail inspect surface packet + +- bounded Phase `4` dashboard-consumer slice +- date: `2026-05-10` + +## Intent + +Stay adjacent in the retained-history dashboard lane and expose the dedicated handoff-history text band directly to gameplay and Blueprint callers. + +## Why this packet exists + +`UHyperTwistCoachDashboardWidget` already displayed: + +- the current `Handoff history` status line +- the current `Handoff history` detail line + +But those two lines only surfaced through `HandoffHistoryStatusTextBlock` and `HandoffHistoryDetailTextBlock`. Callers could inspect the selected retained handoff entry and the prev/next navigation posture separately, but there was still no dedicated inspect surface for the exact retained-history text band the dashboard was already presenting. + +## What changed + +- added `FHyperTwistTrainingCoachDashboardHandoffHistoryStatusInspectSurface` +- added `FHyperTwistTrainingCoachDashboardHandoffHistoryDetailInspectSurface` +- added `GetDisplayedHandoffHistoryStatusInspectSurface()` +- added `GetDisplayedHandoffHistoryDetailInspectSurface()` +- retained the exact displayed handoff-history status/detail lines inside the widget so the new surfaces report the same live strings the dashboard is already presenting +- composed both surfaces over the already-landed selected-handoff-history and handoff-history-navigation surfaces so the packet stayed bounded and reused the same retained-history derivation + +## 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 exact displayed handoff-history status line +- the exact displayed handoff-history detail line +- selected retained entry ordinal, recommendation kind, retained posture, and reliable-plan context +- queue source, preferred lane/source, preferred recovery action/source, readiness posture, and closure-bias context + +without scraping widget text blocks or stitching together the selected-history and navigation wrappers manually. + +## Validation + +- full `Development Editor | Win64` MSBuild on `UnrealHyperTwist.sln` + - passed with `0 Warning(s), 0 Error(s)` + +## Next clean slice + +Treat the retained handoff-history band as functionally complete enough and stay in the same retained-history dashboard neighborhood to expose the displayed guidance-decision history status/detail pair over the current guidance-decision-history text band.