Expose dashboard template launch history status and detail surfaces

This commit is contained in:
axiomlogicnexus 2026-05-10 19:13:47 +02:00
parent 3e09d3737f
commit 9fdd090d28
5 changed files with 300 additions and 2 deletions

View file

@ -9638,6 +9638,96 @@ UHyperTwistCoachDashboardWidget::GetSelectedTemplateLaunchHistoryInspectSurface(
return Surface;
}
FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryStatusInspectSurface
UHyperTwistCoachDashboardWidget::GetDisplayedTemplateLaunchHistoryStatusInspectSurface() const
{
FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryStatusInspectSurface Surface;
Surface.Headline = TEXT("Template launch history status");
const FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryInspectSurface HistorySurface =
GetSelectedTemplateLaunchHistoryInspectSurface();
const FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryNavigationInspectSurface NavigationSurface =
GetDisplayedTemplateLaunchHistoryNavigationInspectSurface();
Surface.StatusLine = !DisplayedTemplateLaunchHistoryStatusLine.IsEmpty()
? DisplayedTemplateLaunchHistoryStatusLine
: HistorySurface.StatusLine;
Surface.SelectedEntryOrdinal = NavigationSurface.SelectedEntryOrdinal.IsEmpty()
? TEXT("none")
: NavigationSurface.SelectedEntryOrdinal;
Surface.RecordedAtUtc =
HistorySurface.RecordedAtUtc.IsEmpty() ? TEXT("n/a") : HistorySurface.RecordedAtUtc;
Surface.CompletedAtUtc =
HistorySurface.CompletedAtUtc.IsEmpty() ? TEXT("n/a") : HistorySurface.CompletedAtUtc;
Surface.TemplateId = HistorySurface.TemplateId.IsEmpty() ? TEXT("n/a") : HistorySurface.TemplateId;
Surface.SessionStateLabel = HistorySurface.SessionStateLabel.IsEmpty()
? TEXT("n/a")
: HistorySurface.SessionStateLabel;
Surface.AnalyticsOutcomeLine = HistorySurface.AnalyticsOutcomeLine.IsEmpty()
? TEXT("n/a")
: HistorySurface.AnalyticsOutcomeLine;
Surface.SelectedEntryIndex = HistorySurface.SelectedEntryIndex;
Surface.HistoryEntryCount = HistorySurface.HistoryEntryCount;
Surface.bHasSelectedEntry = HistorySurface.bHasSelectedEntry;
Surface.bSelectedEntryIsLatest = NavigationSurface.bSelectedEntryIsLatest;
Surface.bHasScopedStats = HistorySurface.bHasScopedStats;
return Surface;
}
FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryDetailInspectSurface
UHyperTwistCoachDashboardWidget::GetDisplayedTemplateLaunchHistoryDetailInspectSurface() const
{
FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryDetailInspectSurface Surface;
Surface.Headline = TEXT("Template launch history detail");
const FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryInspectSurface HistorySurface =
GetSelectedTemplateLaunchHistoryInspectSurface();
Surface.DetailLine = !DisplayedTemplateLaunchHistoryDetailLine.IsEmpty()
? DisplayedTemplateLaunchHistoryDetailLine
: HistorySurface.DetailLine;
Surface.SelectionDetailLine = HistorySurface.SelectionDetailLine.IsEmpty()
? TEXT("")
: HistorySurface.SelectionDetailLine;
Surface.AnalyticsDetailLine = HistorySurface.AnalyticsDetailLine.IsEmpty()
? TEXT("n/a")
: HistorySurface.AnalyticsDetailLine;
Surface.SourceSessionId =
HistorySurface.SourceSessionId.IsEmpty() ? TEXT("n/a") : HistorySurface.SourceSessionId;
Surface.SourceReviewPlanId = HistorySurface.SourceReviewPlanId.IsEmpty()
? TEXT("none")
: HistorySurface.SourceReviewPlanId;
Surface.TemplateId = HistorySurface.TemplateId.IsEmpty() ? TEXT("n/a") : HistorySurface.TemplateId;
Surface.TemplateTitle =
HistorySurface.TemplateTitle.IsEmpty() ? TEXT("n/a") : HistorySurface.TemplateTitle;
Surface.UserId = HistorySurface.UserId.IsEmpty() ? TEXT("n/a") : HistorySurface.UserId;
Surface.FocusDeckId =
HistorySurface.FocusDeckId.IsEmpty() ? TEXT("n/a") : HistorySurface.FocusDeckId;
Surface.TemplateKindLabel = HistorySurface.TemplateKindLabel.IsEmpty()
? TEXT("n/a")
: HistorySurface.TemplateKindLabel;
Surface.SuggestedModeLabel = HistorySurface.SuggestedModeLabel.IsEmpty()
? TEXT("n/a")
: HistorySurface.SuggestedModeLabel;
Surface.SuggestedSelectionLabel = HistorySurface.SuggestedSelectionLabel.IsEmpty()
? TEXT("n/a")
: HistorySurface.SuggestedSelectionLabel;
Surface.SelectedEntryIndex = HistorySurface.SelectedEntryIndex;
Surface.HistoryEntryCount = HistorySurface.HistoryEntryCount;
Surface.RecommendedCaseCount = HistorySurface.RecommendedCaseCount;
Surface.FocusCaseCount = HistorySurface.FocusCaseCount;
Surface.CompletedAttemptCount = HistorySurface.CompletedAttemptCount;
Surface.TotalMistakes = HistorySurface.TotalMistakes;
Surface.SuccessRate = HistorySurface.SuccessRate;
Surface.bHasSelectedEntry = HistorySurface.bHasSelectedEntry;
Surface.bHasScopedStats = HistorySurface.bHasScopedStats;
Surface.bHasSelectionProvenance = HistorySurface.bHasSelectionProvenance;
Surface.bPreferReviewRun = HistorySurface.bPreferReviewRun;
Surface.bCoachReview = HistorySurface.bCoachReview;
Surface.bPreferShortReviewSet = HistorySurface.bPreferShortReviewSet;
return Surface;
}
FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryNavigationInspectSurface
UHyperTwistCoachDashboardWidget::GetDisplayedTemplateLaunchHistoryNavigationInspectSurface() const
{
@ -26393,11 +26483,13 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
TemplateLaunchHistoryHeaderTextBlock->SetText(FText::FromString(
TEXT("[Template Launch History]")));
}
DisplayedTemplateLaunchHistoryStatusLine = TemplateLaunchHistoryStatusLine;
if (TemplateLaunchHistoryStatusTextBlock != nullptr)
{
TemplateLaunchHistoryStatusTextBlock->SetText(FText::FromString(
TemplateLaunchHistoryStatusLine));
}
DisplayedTemplateLaunchHistoryDetailLine = TemplateLaunchHistoryDetailLine;
if (TemplateLaunchHistoryDetailTextBlock != nullptr)
{
TemplateLaunchHistoryDetailTextBlock->SetText(FText::FromString(

View file

@ -807,6 +807,14 @@ public:
FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryInspectSurface
GetSelectedTemplateLaunchHistoryInspectSurface() const;
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryStatusInspectSurface
GetDisplayedTemplateLaunchHistoryStatusInspectSurface() const;
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryDetailInspectSurface
GetDisplayedTemplateLaunchHistoryDetailInspectSurface() const;
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryNavigationInspectSurface
GetDisplayedTemplateLaunchHistoryNavigationInspectSurface() const;
@ -2056,6 +2064,8 @@ private:
FString DisplayedActiveRunSummaryLine;
FString DisplayedTemplateLaunchStatusLine;
FString DisplayedTemplateLaunchDetailLine;
FString DisplayedTemplateLaunchHistoryStatusLine;
FString DisplayedTemplateLaunchHistoryDetailLine;
FString DisplayedRunRecapStatusLine;
FString DisplayedRunRecapDetailLine;
FString DisplayedTemplateLaunchActionLabel;

View file

@ -10604,6 +10604,149 @@ struct FHyperTwistTrainingCoachDashboardGuidanceDecisionHistoryInspectSurface
}
};
USTRUCT(BlueprintType)
struct FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryStatusInspectSurface
{
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 CompletedAtUtc;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString TemplateId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString SessionStateLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString AnalyticsOutcomeLine;
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 bHasScopedStats = false;
bool IsStructurallyValid() const
{
return !StatusLine.IsEmpty()
|| bHasSelectedEntry
|| HistoryEntryCount > 0;
}
};
USTRUCT(BlueprintType)
struct FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryDetailInspectSurface
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString Headline;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString DetailLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString SelectionDetailLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString AnalyticsDetailLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString SourceSessionId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString SourceReviewPlanId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString TemplateId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString TemplateTitle;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString UserId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString FocusDeckId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString TemplateKindLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString SuggestedModeLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString SuggestedSelectionLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 SelectedEntryIndex = INDEX_NONE;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 HistoryEntryCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 RecommendedCaseCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 FocusCaseCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 CompletedAttemptCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 TotalMistakes = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
float SuccessRate = 0.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasSelectedEntry = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasScopedStats = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasSelectionProvenance = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bPreferReviewRun = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bCoachReview = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bPreferShortReviewSet = false;
bool IsStructurallyValid() const
{
return !DetailLine.IsEmpty()
|| bHasSelectedEntry
|| bHasSelectionProvenance;
}
};
USTRUCT(BlueprintType)
struct FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryNavigationInspectSurface
{

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 adjacent in that same live dashboard consumer lane and adds the dedicated template-launch status/detail inspect pair over the exact displayed template-launch lines already cached in the widget, so gameplay/Blueprint callers can inspect the live template-launch text band directly without routing through the broader preferred-template action-control surface
- the primary template-launch band is now functionally complete enough to stop widening it by drift; the next best clean move is to stay adjacent in the same dashboard neighborhood and expose the displayed template-launch history status/detail pair over the current retained-history text band
- 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 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,53 @@
# HyperTwist Phase 4 dashboard template-launch 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 template-launch history text band directly to gameplay and Blueprint callers.
## Why this packet exists
`UHyperTwistCoachDashboardWidget` already displayed:
- the current `Template launch history` status line
- the current `Template launch history` detail line
But those two lines only surfaced through `TemplateLaunchHistoryStatusTextBlock` and `TemplateLaunchHistoryDetailTextBlock`. Callers could inspect the selected retained 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 `FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryStatusInspectSurface`
- added `FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryDetailInspectSurface`
- added `GetDisplayedTemplateLaunchHistoryStatusInspectSurface()`
- added `GetDisplayedTemplateLaunchHistoryDetailInspectSurface()`
- retained the exact displayed template-launch 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-history and 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 template-launch history status line
- the exact displayed template-launch history detail line
- selected retained entry ordinal, template id, state, and aggregate outcome context
- selected retained entry title, mode, selection, focus-deck, source-plan, and analytics detail 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 template-launch history band as functionally complete enough and stay adjacent in the same retained-history dashboard neighborhood to expose the displayed handoff history status/detail pair over the current handoff-history text band.