Expose dashboard queue suppression history navigation surface

This commit is contained in:
axiomlogicnexus 2026-05-10 01:10:52 +02:00
parent ef342525bd
commit d0ff8927f5
5 changed files with 207 additions and 4 deletions

View file

@ -7309,6 +7309,84 @@ UHyperTwistCoachDashboardWidget::GetSelectedQueueSuppressionHistoryInspectSurfac
return Surface;
}
FHyperTwistTrainingCoachDashboardQueueSuppressionHistoryNavigationInspectSurface
UHyperTwistCoachDashboardWidget::GetDisplayedQueueSuppressionHistoryNavigationInspectSurface() const
{
FHyperTwistTrainingCoachDashboardQueueSuppressionHistoryNavigationInspectSurface Surface;
Surface.Headline = TEXT("Queue suppression history navigation");
const FHyperTwistCoachDashboardQueueSuppressionEntry* SelectedEntry =
SelectedQueueSuppressionIndex >= 0
&& SelectedQueueSuppressionIndex < QueueSuppressionHistoryEntries.Num()
? &QueueSuppressionHistoryEntries[SelectedQueueSuppressionIndex]
: nullptr;
const bool bNavigationEnabled = QueueSuppressionHistoryEntries.Num() > 1;
Surface.PreviousLabel = !DisplayedPreviousQueueSuppressionNavigationLabel.IsEmpty()
? DisplayedPreviousQueueSuppressionNavigationLabel
: TEXT("Prev Suppression");
Surface.NextLabel = !DisplayedNextQueueSuppressionNavigationLabel.IsEmpty()
? DisplayedNextQueueSuppressionNavigationLabel
: TEXT("Next Suppression");
Surface.SelectedEntryIndex = SelectedQueueSuppressionIndex;
Surface.HistoryEntryCount = QueueSuppressionHistoryEntries.Num();
Surface.bHasSelectedEntry =
SelectedEntry != nullptr && SelectedEntry->IsStructurallyValid();
Surface.bSelectedEntryIsLatest =
Surface.bHasSelectedEntry
&& SelectedQueueSuppressionIndex == QueueSuppressionHistoryEntries.Num() - 1;
Surface.bPreviousEnabled = bNavigationEnabled;
Surface.bNextEnabled = bNavigationEnabled;
if (!Surface.bHasSelectedEntry)
{
Surface.SelectedEntryOrdinal = TEXT("none");
Surface.RecordedAtUtc = TEXT("n/a");
Surface.SelectedLaneLabel = TEXT("none");
Surface.PreferredRecoveryActionLabel = TEXT("n/a");
Surface.DominantDeferralReasonLabel = TEXT("n/a");
Surface.StatusLine =
TEXT("Suppression history navigation: no retained recovery-driven queue suppressions recorded yet.");
Surface.DetailLine = FString::Printf(
TEXT("%s: %s | %s: %s | selected latest: no"),
*Surface.PreviousLabel,
Surface.bPreviousEnabled ? TEXT("enabled") : TEXT("disabled"),
*Surface.NextLabel,
Surface.bNextEnabled ? TEXT("enabled") : TEXT("disabled"));
return Surface;
}
Surface.SelectedEntryOrdinal = FString::Printf(
TEXT("%d/%d"),
SelectedQueueSuppressionIndex + 1,
QueueSuppressionHistoryEntries.Num());
Surface.RecordedAtUtc = SelectedEntry->RecordedAtUtc.IsEmpty()
? TEXT("n/a")
: SelectedEntry->RecordedAtUtc;
Surface.SelectedLaneLabel = HyperTwistCoachDashboardWidgetInternal::DescribeGuidanceLane(
SelectedEntry->PreferredGuidanceLane);
Surface.PreferredRecoveryActionLabel =
HyperTwistCoachDashboardWidgetInternal::EnumDisplayName(
SelectedEntry->PreferredRecoveryAction);
Surface.DominantDeferralReasonLabel = SelectedEntry->DominantDeferralReasonLabel.IsEmpty()
? TEXT("n/a")
: SelectedEntry->DominantDeferralReasonLabel;
Surface.StatusLine = FString::Printf(
TEXT("Suppression history navigation: selected %s | Lane: %s | Recovery: %s | Recorded: %s"),
*Surface.SelectedEntryOrdinal,
*Surface.SelectedLaneLabel,
*Surface.PreferredRecoveryActionLabel,
*Surface.RecordedAtUtc);
Surface.DetailLine = FString::Printf(
TEXT("%s: %s | %s: %s | dominant reason: %s | selected latest: %s"),
*Surface.PreviousLabel,
Surface.bPreviousEnabled ? TEXT("enabled") : TEXT("disabled"),
*Surface.NextLabel,
Surface.bNextEnabled ? TEXT("enabled") : TEXT("disabled"),
*Surface.DominantDeferralReasonLabel,
Surface.bSelectedEntryIsLatest ? TEXT("yes") : TEXT("no"));
return Surface;
}
FHyperTwistTrainingCoachDashboardClosureRecoveryHistoryInspectSurface
UHyperTwistCoachDashboardWidget::GetSelectedClosureRecoveryHistoryInspectSurface() const
{
@ -24823,7 +24901,9 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
}
if (PreviousQueueSuppressionButtonLabel != nullptr)
{
PreviousQueueSuppressionButtonLabel->SetText(FText::FromString(TEXT("Prev Suppression")));
DisplayedPreviousQueueSuppressionNavigationLabel = TEXT("Prev Suppression");
PreviousQueueSuppressionButtonLabel->SetText(
FText::FromString(DisplayedPreviousQueueSuppressionNavigationLabel));
}
if (PreviousQueueSuppressionButton != nullptr)
{
@ -24831,7 +24911,9 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
}
if (NextQueueSuppressionButtonLabel != nullptr)
{
NextQueueSuppressionButtonLabel->SetText(FText::FromString(TEXT("Next Suppression")));
DisplayedNextQueueSuppressionNavigationLabel = TEXT("Next Suppression");
NextQueueSuppressionButtonLabel->SetText(
FText::FromString(DisplayedNextQueueSuppressionNavigationLabel));
}
if (NextQueueSuppressionButton != nullptr)
{

View file

@ -735,6 +735,10 @@ public:
FHyperTwistTrainingCoachDashboardQueueSuppressionHistoryInspectSurface
GetSelectedQueueSuppressionHistoryInspectSurface() const;
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
FHyperTwistTrainingCoachDashboardQueueSuppressionHistoryNavigationInspectSurface
GetDisplayedQueueSuppressionHistoryNavigationInspectSurface() const;
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
FHyperTwistTrainingCoachDashboardClosureRecoveryHistoryInspectSurface
GetSelectedClosureRecoveryHistoryInspectSurface() const;
@ -1994,6 +1998,8 @@ private:
FString DisplayedPreviousQueueNavigationLabel;
FString DisplayedStartSelectedQueueActionLabel;
FString DisplayedNextQueueNavigationLabel;
FString DisplayedPreviousQueueSuppressionNavigationLabel;
FString DisplayedNextQueueSuppressionNavigationLabel;
FString DisplayedPreviousClosureRecoveryNavigationLabel;
FString DisplayedNextClosureRecoveryNavigationLabel;
FString DisplayedPreviousAttemptNavigationLabel;

View file

@ -8576,6 +8576,69 @@ struct FHyperTwistTrainingCoachDashboardQueueSuppressionHistoryInspectSurface
}
};
USTRUCT(BlueprintType)
struct FHyperTwistTrainingCoachDashboardQueueSuppressionHistoryNavigationInspectSurface
{
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 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")
FString PreferredRecoveryActionLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString DominantDeferralReasonLabel;
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;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bPreviousEnabled = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bNextEnabled = false;
bool IsStructurallyValid() const
{
return !StatusLine.IsEmpty()
|| !DetailLine.IsEmpty()
|| bHasSelectedEntry
|| bPreviousEnabled
|| bNextEnabled;
}
};
USTRUCT(BlueprintType)
struct FHyperTwistTrainingCoachDashboardClosureRecoveryHistoryInspectSurface
{

View file

@ -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 on that same live `UHyperTwistCoachDashboardWidget` guidance-consumer lane and adds the closure-recovery history navigation control inspect surface over already-retained history state, so gameplay/Blueprint callers can inspect the live prev/next closure-history labels, enablement posture, selected retained entry ordinal, and source/latest-selection context without scraping button text or reopening retained-history derivation
- the next clean move is to pivot deliberately into the adjacent retained-history navigation/control lane and expose the queue-suppression history navigation control surface rather than drifting back into backend continuity or widening the now-complete closure-recovery live/history seam
- the latest landed bounded `Phase 4` packet pivots into the adjacent retained-history navigation/control lane and adds the queue-suppression history navigation control inspect surface over already-retained history state, so gameplay/Blueprint callers can inspect the live prev/next suppression-history labels, enablement posture, selected retained entry ordinal, and recovery/latest-selection context without scraping button text or reopening retained-history derivation
- the next clean move is to continue that same retained-history navigation/control lane and expose the method-drill recovery outcome history navigation control surface rather than drifting back into backend continuity or reopening the already-inspectable history detail seams
- 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 queue-suppression history navigation control inspect surface packet
- bounded Phase `4` dashboard-consumer slice
- date: `2026-05-10`
## Intent
Pivot into the retained-history navigation/control lane inside `UHyperTwistCoachDashboardWidget` and expose the queue-suppression history navigation controls directly to gameplay and Blueprint callers.
## Why this packet exists
The dashboard already derived and displayed:
- the previous queue-suppression-history button label
- the next queue-suppression-history button label
- the enablement posture for both controls
But that control state still only surfaced through button text and button enabled state. Callers still had to inspect widget controls directly to understand whether retained suppression-history navigation is available and which retained entry is currently selected.
## What changed
- added `FHyperTwistTrainingCoachDashboardQueueSuppressionHistoryNavigationInspectSurface`
- added `GetDisplayedQueueSuppressionHistoryNavigationInspectSurface()`
- retained the exact displayed previous/next suppression-history labels inside the widget so the new inspect surface reports the same live strings the dashboard is already presenting
- kept the packet bounded to `UHyperTwistCoachDashboardWidget` plus shared surface types, with no dashboard redesign and no backend continuity changes
## 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 live previous/next suppression-history labels
- whether suppression-history navigation is currently enabled
- the selected retained suppression-history ordinal, lane, recovery action, and recorded time
- the dominant deferral reason and whether the current selection is the latest retained entry
without scraping button text or reopening retained-history derivation.
## Validation
- full `Development Editor | Win64` MSBuild on `UnrealHyperTwist.sln`
- passed with `0 Warning(s), 0 Error(s)`
## Next clean slice
Stay on the retained-history navigation/control lane and expose the method-drill recovery outcome history navigation control surface.