Expose dashboard live guidance inspect surfaces

This commit is contained in:
axiomlogicnexus 2026-05-09 18:49:42 +02:00
parent 6246f41e5c
commit db016a0789
5 changed files with 1027 additions and 2 deletions

View file

@ -8509,6 +8509,603 @@ UHyperTwistCoachDashboardWidget::GetSelectedTemplateLaunchHistoryInspectSurface(
return Surface;
}
FHyperTwistTrainingCoachDashboardGuidanceComparisonInspectSurface
UHyperTwistCoachDashboardWidget::GetDisplayedGuidanceComparisonInspectSurface() const
{
FHyperTwistTrainingCoachDashboardGuidanceComparisonInspectSurface Surface;
Surface.Headline = TEXT("Guidance comparison");
Surface.bClosedLoopIdleActionability = IsCoachLoopActionabilityClosed();
const auto BuildLaneLabel =
[](const EHyperTwistCoachDashboardGuidancePreviewLane Lane) -> FString
{
return Lane == EHyperTwistCoachDashboardGuidancePreviewLane::Recommended
? TEXT("recommended")
: (Lane == EHyperTwistCoachDashboardGuidancePreviewLane::FollowUp
? TEXT("follow-up")
: TEXT("none"));
};
const auto BuildDeckLabel =
[](const FHyperTwistTrainingDeck* Deck) -> FString
{
if (Deck == nullptr || !Deck->IsStructurallyValid())
{
return TEXT("n/a");
}
return Deck->Title.IsEmpty() ? Deck->DeckId : Deck->Title;
};
const bool bHasCurrentRunRecap = CachedRunState.Session.IsStructurallyValid()
&& (CachedRunState.Session.SessionState == EHyperTwistTrainingSessionState::Completed
|| CachedRunState.Session.SessionState == EHyperTwistTrainingSessionState::Aborted);
const FHyperTwistTrainingSessionSummary* DisplayedRunRecap = bHasCurrentRunRecap
? &CachedRunSummary
: (bHasRetainedRunRecap ? &RetainedRunRecapSummary : nullptr);
const FHyperTwistTrainingDeck* DisplayedRunRecapDeck = bHasCurrentRunRecap
? &CachedRunState.ActiveDeck
: (bHasRetainedRunRecap ? &RetainedRunRecapDeck : nullptr);
const EHyperTwistTrainingDeliveryMode DisplayedRunRecapMode = bHasCurrentRunRecap
? CachedRunState.Session.Mode
: RetainedRunRecapMode;
const bool bHasDisplayedRunRecap = DisplayedRunRecap != nullptr
&& !DisplayedRunRecap->TrainingSessionId.IsEmpty();
Surface.bHasDisplayedRunRecap = bHasDisplayedRunRecap;
Surface.RunRecapSourceLabel = bHasDisplayedRunRecap
? (bHasCurrentRunRecap ? TEXT("current run") : TEXT("last completed run"))
: TEXT("none");
Surface.TrainingSessionId = bHasDisplayedRunRecap
? DisplayedRunRecap->TrainingSessionId
: TEXT("n/a");
Surface.ActualDeckLabel = BuildDeckLabel(DisplayedRunRecapDeck);
Surface.ActualModeLabel =
bHasDisplayedRunRecap
? HyperTwistCoachDashboardWidgetInternal::EnumDisplayName(DisplayedRunRecapMode)
: TEXT("n/a");
Surface.ActualSelectionLabel =
DisplayedRunRecapDeck != nullptr && DisplayedRunRecapDeck->IsStructurallyValid()
? HyperTwistCoachDashboardWidgetInternal::EnumDisplayName(
DisplayedRunRecapDeck->SelectionPolicy)
: TEXT("n/a");
Surface.LastCaseId =
bHasDisplayedRunRecap && !DisplayedRunRecap->LastCaseId.IsEmpty()
? DisplayedRunRecap->LastCaseId
: TEXT("n/a");
Surface.CompletedAttemptCount =
bHasDisplayedRunRecap ? DisplayedRunRecap->CompletedAttemptCount : 0;
Surface.FailureCount = bHasDisplayedRunRecap ? DisplayedRunRecap->FailureCount : 0;
Surface.TimeoutCount = bHasDisplayedRunRecap ? DisplayedRunRecap->TimeoutCount : 0;
Surface.DNFCount = bHasDisplayedRunRecap ? DisplayedRunRecap->DNFCount : 0;
Surface.TotalMistakes = bHasDisplayedRunRecap ? DisplayedRunRecap->TotalMistakes : 0;
Surface.SuccessRate = bHasDisplayedRunRecap ? DisplayedRunRecap->SuccessRate : 0.0f;
const FHyperTwistTrainingSessionSummary* DisplayedGuidanceComparisonRunRecap = nullptr;
const FHyperTwistCoachBrief* DisplayedGuidanceComparisonBrief = nullptr;
const FHyperTwistTrainingDeck* DisplayedGuidanceComparisonDeck = nullptr;
FString DisplayedGuidanceComparisonSelectedCaseId;
bool bDisplayedGuidanceComparisonSingleCase = false;
Surface.bHasComparisonContext = ResolveDisplayedGuidanceComparisonContext(
DisplayedGuidanceComparisonRunRecap,
DisplayedGuidanceComparisonBrief,
DisplayedGuidanceComparisonDeck,
DisplayedGuidanceComparisonSelectedCaseId,
bDisplayedGuidanceComparisonSingleCase);
Surface.bHasDisplayedGuidanceBrief = DisplayedGuidanceComparisonBrief != nullptr;
Surface.bHasDisplayedGuidanceDeck =
DisplayedGuidanceComparisonDeck != nullptr
&& DisplayedGuidanceComparisonDeck->IsStructurallyValid();
Surface.bSingleCaseScope = bDisplayedGuidanceComparisonSingleCase;
Surface.ScopeLabel = Surface.bHasComparisonContext
? (Surface.bSingleCaseScope ? TEXT("selected case") : TEXT("full preview deck"))
: TEXT("none");
EHyperTwistCoachDashboardGuidancePreviewLane DisplayedGuidanceComparisonLane =
EHyperTwistCoachDashboardGuidancePreviewLane::None;
if (DisplayedGuidanceComparisonBrief == &ActiveGuidanceLaunchBrief)
{
DisplayedGuidanceComparisonLane = ActiveGuidanceLaunchLane;
}
else if (DisplayedGuidanceComparisonBrief == &RetainedGuidanceComparisonBrief)
{
DisplayedGuidanceComparisonLane = RetainedGuidanceComparisonLane;
}
Surface.GuidanceLaneLabel = BuildLaneLabel(DisplayedGuidanceComparisonLane);
Surface.BriefHeadline =
DisplayedGuidanceComparisonBrief != nullptr
&& !DisplayedGuidanceComparisonBrief->Headline.IsEmpty()
? DisplayedGuidanceComparisonBrief->Headline
: TEXT("n/a");
Surface.PrimaryActionLabel =
DisplayedGuidanceComparisonBrief != nullptr
&& !DisplayedGuidanceComparisonBrief->PrimaryActionLabel.IsEmpty()
? DisplayedGuidanceComparisonBrief->PrimaryActionLabel
: TEXT("n/a");
Surface.PreviewDeckLabel = BuildDeckLabel(DisplayedGuidanceComparisonDeck);
Surface.ExpectedModeLabel =
DisplayedGuidanceComparisonBrief != nullptr
? HyperTwistCoachDashboardWidgetInternal::EnumDisplayName(
DisplayedGuidanceComparisonBrief->SuggestedMode)
: TEXT("n/a");
Surface.ExpectedSelectionLabel =
DisplayedGuidanceComparisonBrief != nullptr
? HyperTwistCoachDashboardWidgetInternal::EnumDisplayName(
DisplayedGuidanceComparisonBrief->SuggestedSelectionPolicy)
: TEXT("n/a");
Surface.FocusLaneLabel =
DisplayedGuidanceComparisonBrief != nullptr
? HyperTwistCoachDashboardWidgetInternal::EnumDisplayName(
DisplayedGuidanceComparisonBrief->FocusLane)
: TEXT("n/a");
Surface.SelectedCaseId =
!DisplayedGuidanceComparisonSelectedCaseId.IsEmpty()
? DisplayedGuidanceComparisonSelectedCaseId
: TEXT("n/a");
Surface.ExpectedCaseCount =
DisplayedGuidanceComparisonDeck != nullptr ? DisplayedGuidanceComparisonDeck->Cases.Num() : 0;
Surface.FocusCaseCount =
DisplayedGuidanceComparisonBrief != nullptr
? DisplayedGuidanceComparisonBrief->FocusCaseIds.Num()
: 0;
Surface.bSelectedCaseMatchesLastCase =
bHasDisplayedRunRecap
&& !DisplayedGuidanceComparisonSelectedCaseId.IsEmpty()
&& DisplayedRunRecap->LastCaseId == DisplayedGuidanceComparisonSelectedCaseId;
Surface.StatusLine = Surface.bHasComparisonContext
? FString::Printf(
TEXT("Comparison: %s recap vs %s preview | Scope: %s | Focus lane: %s | Expected cases: %d | Completed attempts: %d | Success rate: %.2f"),
*Surface.RunRecapSourceLabel,
*Surface.GuidanceLaneLabel,
Surface.bSingleCaseScope ? TEXT("selected case") : TEXT("full preview deck"),
*Surface.FocusLaneLabel,
Surface.ExpectedCaseCount,
Surface.CompletedAttemptCount,
Surface.SuccessRate)
: TEXT("Comparison: complete a run launched from previewed guidance to compare the recap against the original coach intent.");
Surface.DetailLine = Surface.bHasComparisonContext
? FString::Printf(
TEXT("Launch brief: %s | Action: %s | Preview deck: %s | Actual deck: %s | Mode expected/actual: %s / %s | Selection expected/actual: %s / %s | Selected case: %s | Last case matched: %s | Focus cases: %d | Last case: %s"),
*Surface.BriefHeadline,
*Surface.PrimaryActionLabel,
*Surface.PreviewDeckLabel,
*Surface.ActualDeckLabel,
*Surface.ExpectedModeLabel,
*Surface.ActualModeLabel,
*Surface.ExpectedSelectionLabel,
*Surface.ActualSelectionLabel,
*Surface.SelectedCaseId,
Surface.bSelectedCaseMatchesLastCase ? TEXT("yes") : TEXT("no"),
Surface.FocusCaseCount,
*Surface.LastCaseId)
: TEXT("Comparison detail: no preview-launched recap is currently selected.");
if (Surface.bClosedLoopIdleActionability
&& !Surface.bHasComparisonContext)
{
Surface.StatusLine =
TEXT("Comparison: retained comparison history remains inspectable, but no preview-launched recap is currently selected in the closed-loop idle state.");
Surface.DetailLine =
TEXT("Comparison detail: the coach-to-review loop is closed and idle, so no live recommended or follow-up comparison target remains active.");
}
return Surface;
}
FHyperTwistTrainingCoachDashboardGuidanceOutcomeInspectSurface
UHyperTwistCoachDashboardWidget::GetDisplayedGuidanceOutcomeInspectSurface() const
{
FHyperTwistTrainingCoachDashboardGuidanceOutcomeInspectSurface Surface;
Surface.Headline = TEXT("Guidance outcome");
Surface.bClosedLoopIdleActionability = IsCoachLoopActionabilityClosed();
const auto BuildLaneLabel =
[](const EHyperTwistCoachDashboardGuidancePreviewLane Lane) -> FString
{
return Lane == EHyperTwistCoachDashboardGuidancePreviewLane::Recommended
? TEXT("recommended")
: (Lane == EHyperTwistCoachDashboardGuidancePreviewLane::FollowUp
? TEXT("follow-up")
: TEXT("none"));
};
const auto BuildDecisionActionLabel =
[this](const EHyperTwistCoachDashboardOutcomeAction Action) -> FString
{
return Action == EHyperTwistCoachDashboardOutcomeAction::None
? TEXT("none")
: BuildGuidanceOutcomeActionLabel(Action);
};
const bool bHasCurrentRunRecap = CachedRunState.Session.IsStructurallyValid()
&& (CachedRunState.Session.SessionState == EHyperTwistTrainingSessionState::Completed
|| CachedRunState.Session.SessionState == EHyperTwistTrainingSessionState::Aborted);
const FHyperTwistTrainingSessionSummary* DisplayedRunRecap = bHasCurrentRunRecap
? &CachedRunSummary
: (bHasRetainedRunRecap ? &RetainedRunRecapSummary : nullptr);
Surface.bHasDisplayedRunRecap =
DisplayedRunRecap != nullptr && !DisplayedRunRecap->TrainingSessionId.IsEmpty();
Surface.RunRecapSourceLabel = Surface.bHasDisplayedRunRecap
? (bHasCurrentRunRecap ? TEXT("current run") : TEXT("last completed run"))
: TEXT("none");
Surface.TrainingSessionId = Surface.bHasDisplayedRunRecap
? DisplayedRunRecap->TrainingSessionId
: TEXT("n/a");
const FHyperTwistTrainingSessionSummary* DisplayedGuidanceComparisonRunRecap = nullptr;
const FHyperTwistCoachBrief* DisplayedGuidanceComparisonBrief = nullptr;
const FHyperTwistTrainingDeck* DisplayedGuidanceComparisonDeck = nullptr;
FString DisplayedGuidanceComparisonSelectedCaseId;
bool bDisplayedGuidanceComparisonSingleCase = false;
Surface.bHasComparisonContext = ResolveDisplayedGuidanceComparisonContext(
DisplayedGuidanceComparisonRunRecap,
DisplayedGuidanceComparisonBrief,
DisplayedGuidanceComparisonDeck,
DisplayedGuidanceComparisonSelectedCaseId,
bDisplayedGuidanceComparisonSingleCase);
Surface.bHasDisplayedGuidanceBrief = DisplayedGuidanceComparisonBrief != nullptr;
Surface.bHasDisplayedGuidanceDeck =
DisplayedGuidanceComparisonDeck != nullptr
&& DisplayedGuidanceComparisonDeck->IsStructurallyValid();
Surface.bSingleCaseScope = bDisplayedGuidanceComparisonSingleCase;
EHyperTwistCoachDashboardGuidancePreviewLane DisplayedGuidanceComparisonLane =
EHyperTwistCoachDashboardGuidancePreviewLane::None;
if (DisplayedGuidanceComparisonBrief == &ActiveGuidanceLaunchBrief)
{
DisplayedGuidanceComparisonLane = ActiveGuidanceLaunchLane;
}
else if (DisplayedGuidanceComparisonBrief == &RetainedGuidanceComparisonBrief)
{
DisplayedGuidanceComparisonLane = RetainedGuidanceComparisonLane;
}
Surface.GuidanceLaneLabel = BuildLaneLabel(DisplayedGuidanceComparisonLane);
Surface.ScopeLabel = Surface.bHasComparisonContext
? (Surface.bSingleCaseScope ? TEXT("selected case") : TEXT("preview deck"))
: TEXT("none");
Surface.BriefHeadline =
DisplayedGuidanceComparisonBrief != nullptr
&& !DisplayedGuidanceComparisonBrief->Headline.IsEmpty()
? DisplayedGuidanceComparisonBrief->Headline
: TEXT("n/a");
Surface.SelectedCaseId =
!DisplayedGuidanceComparisonSelectedCaseId.IsEmpty()
? DisplayedGuidanceComparisonSelectedCaseId
: TEXT("n/a");
Surface.ExpectedCaseCount =
DisplayedGuidanceComparisonDeck != nullptr ? DisplayedGuidanceComparisonDeck->Cases.Num() : 0;
Surface.CompletedAttemptCount =
DisplayedRunRecap != nullptr ? DisplayedRunRecap->CompletedAttemptCount : 0;
Surface.NonSuccessCount =
DisplayedRunRecap != nullptr
? (DisplayedRunRecap->FailureCount
+ DisplayedRunRecap->TimeoutCount
+ DisplayedRunRecap->DNFCount)
: 0;
Surface.TotalMistakes = DisplayedRunRecap != nullptr ? DisplayedRunRecap->TotalMistakes : 0;
Surface.SuccessRate = DisplayedRunRecap != nullptr ? DisplayedRunRecap->SuccessRate : 0.0f;
Surface.StatusLine =
TEXT("Outcome: complete a run launched from previewed guidance to derive a repeat, broaden, or redirect verdict.");
Surface.DetailLine =
TEXT("Outcome detail: no preview-launched recap is currently selected.");
if (DisplayedRunRecap != nullptr
&& DisplayedGuidanceComparisonBrief != nullptr
&& DisplayedGuidanceComparisonDeck != nullptr
&& DisplayedRunRecap->CompletedAttemptCount > 0)
{
if (Surface.bSingleCaseScope)
{
if (DisplayedRunRecap->SuccessRate >= 0.85f
&& DisplayedRunRecap->TimeoutCount == 0
&& DisplayedRunRecap->DNFCount == 0
&& DisplayedRunRecap->TotalMistakes <= 1)
{
Surface.StatusLine =
TEXT("Outcome: broaden guidance. The selected case looks stable enough to expand back to the wider preview deck.");
Surface.DetailLine = FString::Printf(
TEXT("Recommendation: move from the single-case launch into the broader %s preview deck or the next coach-directed handoff. Success rate %.2f across %d completed attempts with %d mistakes."),
*Surface.GuidanceLaneLabel,
DisplayedRunRecap->SuccessRate,
DisplayedRunRecap->CompletedAttemptCount,
DisplayedRunRecap->TotalMistakes);
}
else if (DisplayedRunRecap->SuccessRate >= 0.5f)
{
Surface.StatusLine =
TEXT("Outcome: stabilize, then broaden. The selected case is moving, but it is not yet clean enough for a wider shift.");
Surface.DetailLine = FString::Printf(
TEXT("Recommendation: repeat the selected preview case or a very small scope before broadening. Success rate %.2f with %d non-success outcomes and %d mistakes."),
DisplayedRunRecap->SuccessRate,
Surface.NonSuccessCount,
DisplayedRunRecap->TotalMistakes);
}
else
{
Surface.StatusLine =
TEXT("Outcome: repeat selected focus. The previewed case is still weak enough that broadening would be premature.");
Surface.DetailLine = FString::Printf(
TEXT("Recommendation: stay on the selected preview case until the recap is cleaner. Success rate %.2f with %d non-success outcomes and %d mistakes."),
DisplayedRunRecap->SuccessRate,
Surface.NonSuccessCount,
DisplayedRunRecap->TotalMistakes);
}
}
else if (DisplayedRunRecap->SuccessRate >= 0.8f
&& Surface.NonSuccessCount <= FMath::Max(1, DisplayedRunRecap->CompletedAttemptCount / 4)
&& DisplayedRunRecap->TotalMistakes <= FMath::Max(1, DisplayedRunRecap->CompletedAttemptCount / 2))
{
Surface.StatusLine =
TEXT("Outcome: change guidance. The full preview deck looks stable enough to move on from this exact focus.");
Surface.DetailLine = FString::Printf(
TEXT("Recommendation: use follow-up, queued, or recommended coach handoff rather than repeating the same deck. Success rate %.2f across %d completed attempts with %d mistakes."),
DisplayedRunRecap->SuccessRate,
DisplayedRunRecap->CompletedAttemptCount,
DisplayedRunRecap->TotalMistakes);
}
else if (DisplayedRunRecap->SuccessRate >= 0.55f)
{
Surface.StatusLine =
TEXT("Outcome: repeat and stabilize. The deck is moving, but not cleanly enough to abandon this scope.");
Surface.DetailLine = FString::Printf(
TEXT("Recommendation: repeat the preview deck or stay near this focus before changing guidance. Success rate %.2f with %d non-success outcomes and %d mistakes."),
DisplayedRunRecap->SuccessRate,
Surface.NonSuccessCount,
DisplayedRunRecap->TotalMistakes);
}
else
{
Surface.StatusLine =
TEXT("Outcome: narrow or redirect guidance. The broad preview scope is still too unstable.");
Surface.DetailLine = FString::Printf(
TEXT("Recommendation: narrow back to a smaller focus case set or switch guidance lanes before repeating the full deck. Success rate %.2f with %d non-success outcomes and %d mistakes."),
DisplayedRunRecap->SuccessRate,
Surface.NonSuccessCount,
DisplayedRunRecap->TotalMistakes);
}
}
const EHyperTwistCoachDashboardOutcomeAction BaseGuidanceOutcomeAction =
DeriveGuidanceOutcomeAction();
const FHyperTwistCoachDashboardDecisionWeighting GuidanceDecisionWeighting =
BuildGuidanceDecisionWeighting(BaseGuidanceOutcomeAction);
const EHyperTwistCoachDashboardOutcomeAction GuidanceOutcomeAction =
GuidanceDecisionWeighting.WeightedAction != EHyperTwistCoachDashboardOutcomeAction::None
? GuidanceDecisionWeighting.WeightedAction
: BaseGuidanceOutcomeAction;
Surface.BaseActionLabel = BuildDecisionActionLabel(BaseGuidanceOutcomeAction);
Surface.WeightedActionLabel =
BuildDecisionActionLabel(GuidanceDecisionWeighting.WeightedAction);
Surface.bHasWeightingOverride = GuidanceDecisionWeighting.bHasOverride;
Surface.bUsedClosureHistorySignal =
GuidanceDecisionWeighting.bUsedClosureHistorySignal;
Surface.bUsedDeferredOverflowSignal =
GuidanceDecisionWeighting.bUsedDeferredOverflowSignal;
if (GuidanceDecisionWeighting.bUsedClosureHistorySignal)
{
Surface.StatusLine += TEXT(" Closure-recovery history adjusted this recommendation.");
}
if (GuidanceDecisionWeighting.bUsedDeferredOverflowSignal)
{
Surface.StatusLine +=
TEXT(" Deferred-overflow continuation history adjusted this recommendation.");
}
Surface.bCanRedirectAction =
CachedCoachPanelState.bCanStartCoachFollowUpRun
|| CachedCoachPanelState.bCanStartQueuedRun
|| CachedCoachPanelState.bCanStartCoachRecommendedRun;
const bool bHasActiveRun = CachedRunState.Session.IsStructurallyValid()
&& CachedRunState.ActiveDeck.IsStructurallyValid();
Surface.bCanApplyAction =
GuidanceOutcomeAction != EHyperTwistCoachDashboardOutcomeAction::None
&& !bHasLiveAttemptTimer
&& (!bHasActiveRun
|| CachedRunState.Session.SessionState == EHyperTwistTrainingSessionState::Completed
|| CachedRunState.Session.SessionState == EHyperTwistTrainingSessionState::Aborted)
&& (GuidanceOutcomeAction != EHyperTwistCoachDashboardOutcomeAction::RedirectCoachGuidance
|| Surface.bCanRedirectAction);
Surface.ActionLabel = BuildGuidanceOutcomeActionLabel(GuidanceOutcomeAction);
if (Surface.bClosedLoopIdleActionability)
{
Surface.StatusLine =
TEXT("Outcome: retained comparison history remains inspectable, but the coach-to-review loop is closed and idle.");
Surface.DetailLine =
TEXT("Outcome detail: no live repeat, broaden, or redirect action remains while the closed-loop idle boundary holds.");
Surface.ActionLabel = TEXT("Loop Idle");
Surface.bCanApplyAction = false;
}
return Surface;
}
FHyperTwistTrainingCoachDashboardGuidanceDecisionWeightingInspectSurface
UHyperTwistCoachDashboardWidget::GetDisplayedGuidanceDecisionWeightingInspectSurface() const
{
FHyperTwistTrainingCoachDashboardGuidanceDecisionWeightingInspectSurface Surface;
Surface.Headline = TEXT("Decision weighting");
Surface.bClosedLoopIdleActionability = IsCoachLoopActionabilityClosed();
const auto BuildLaneLabel =
[](const EHyperTwistCoachDashboardGuidancePreviewLane Lane) -> FString
{
return Lane == EHyperTwistCoachDashboardGuidancePreviewLane::Recommended
? TEXT("recommended")
: (Lane == EHyperTwistCoachDashboardGuidancePreviewLane::FollowUp
? TEXT("follow-up")
: TEXT("none"));
};
const auto BuildDecisionActionLabel =
[this](const EHyperTwistCoachDashboardOutcomeAction Action) -> FString
{
return Action == EHyperTwistCoachDashboardOutcomeAction::None
? TEXT("none")
: BuildGuidanceOutcomeActionLabel(Action);
};
const bool bHasCurrentRunRecap = CachedRunState.Session.IsStructurallyValid()
&& (CachedRunState.Session.SessionState == EHyperTwistTrainingSessionState::Completed
|| CachedRunState.Session.SessionState == EHyperTwistTrainingSessionState::Aborted);
const FHyperTwistTrainingSessionSummary* DisplayedRunRecap = bHasCurrentRunRecap
? &CachedRunSummary
: (bHasRetainedRunRecap ? &RetainedRunRecapSummary : nullptr);
Surface.bHasDisplayedRunRecap =
DisplayedRunRecap != nullptr && !DisplayedRunRecap->TrainingSessionId.IsEmpty();
Surface.RunRecapSourceLabel = Surface.bHasDisplayedRunRecap
? (bHasCurrentRunRecap ? TEXT("current run") : TEXT("last completed run"))
: TEXT("none");
Surface.TrainingSessionId = Surface.bHasDisplayedRunRecap
? DisplayedRunRecap->TrainingSessionId
: TEXT("n/a");
const FHyperTwistTrainingSessionSummary* DisplayedGuidanceComparisonRunRecap = nullptr;
const FHyperTwistCoachBrief* DisplayedGuidanceComparisonBrief = nullptr;
const FHyperTwistTrainingDeck* DisplayedGuidanceComparisonDeck = nullptr;
FString DisplayedGuidanceComparisonSelectedCaseId;
bool bDisplayedGuidanceComparisonSingleCase = false;
Surface.bHasComparisonContext = ResolveDisplayedGuidanceComparisonContext(
DisplayedGuidanceComparisonRunRecap,
DisplayedGuidanceComparisonBrief,
DisplayedGuidanceComparisonDeck,
DisplayedGuidanceComparisonSelectedCaseId,
bDisplayedGuidanceComparisonSingleCase);
Surface.bHasDisplayedGuidanceBrief = DisplayedGuidanceComparisonBrief != nullptr;
Surface.bHasDisplayedGuidanceDeck =
DisplayedGuidanceComparisonDeck != nullptr
&& DisplayedGuidanceComparisonDeck->IsStructurallyValid();
Surface.bSingleCaseScope = bDisplayedGuidanceComparisonSingleCase;
EHyperTwistCoachDashboardGuidancePreviewLane DisplayedGuidanceComparisonLane =
EHyperTwistCoachDashboardGuidancePreviewLane::None;
if (DisplayedGuidanceComparisonBrief == &ActiveGuidanceLaunchBrief)
{
DisplayedGuidanceComparisonLane = ActiveGuidanceLaunchLane;
}
else if (DisplayedGuidanceComparisonBrief == &RetainedGuidanceComparisonBrief)
{
DisplayedGuidanceComparisonLane = RetainedGuidanceComparisonLane;
}
Surface.GuidanceLaneLabel = BuildLaneLabel(DisplayedGuidanceComparisonLane);
Surface.ScopeLabel = Surface.bHasComparisonContext
? (Surface.bSingleCaseScope ? TEXT("selected case") : TEXT("preview deck"))
: TEXT("none");
Surface.BriefHeadline =
DisplayedGuidanceComparisonBrief != nullptr
&& !DisplayedGuidanceComparisonBrief->Headline.IsEmpty()
? DisplayedGuidanceComparisonBrief->Headline
: TEXT("n/a");
Surface.SelectedCaseId =
!DisplayedGuidanceComparisonSelectedCaseId.IsEmpty()
? DisplayedGuidanceComparisonSelectedCaseId
: TEXT("n/a");
const EHyperTwistCoachDashboardOutcomeAction BaseAction = DeriveGuidanceOutcomeAction();
const FHyperTwistCoachDashboardDecisionWeighting Weighting =
BuildGuidanceDecisionWeighting(BaseAction);
const EHyperTwistCoachDashboardOutcomeAction ResolvedAction =
Weighting.WeightedAction != EHyperTwistCoachDashboardOutcomeAction::None
? Weighting.WeightedAction
: BaseAction;
Surface.ResolvedActionLabel = BuildGuidanceOutcomeActionLabel(ResolvedAction);
Surface.BaseActionLabel = BuildDecisionActionLabel(Weighting.BaseAction);
Surface.WeightedActionLabel = BuildDecisionActionLabel(Weighting.WeightedAction);
Surface.LastAppliedActionLabel = BuildDecisionActionLabel(Weighting.LastAppliedAction);
Surface.MatchingDecisionCount = Weighting.MatchingDecisionCount;
Surface.RepeatSelectedCaseCount = Weighting.RepeatSelectedCaseCount;
Surface.RepeatPreviewDeckCount = Weighting.RepeatPreviewDeckCount;
Surface.BroadenPreviewDeckCount = Weighting.BroadenPreviewDeckCount;
Surface.RedirectCoachGuidanceCount = Weighting.RedirectCoachGuidanceCount;
Surface.BroadenedLaunchCount = Weighting.BroadenedLaunchCount;
Surface.TightenedLaunchCount = Weighting.TightenedLaunchCount;
Surface.ClosureContinuationBias = Weighting.ClosureContinuationBias;
Surface.ClosureSuppressionBias = Weighting.ClosureSuppressionBias;
Surface.DeferredOverflowContinuationBias =
Weighting.DeferredOverflowContinuationBias;
Surface.DeferredOverflowCaseCount = Weighting.DeferredOverflowCaseCount;
Surface.ReliableAlignedTrustedTightPlanOutcomeHistoryCount =
Weighting.ReliableAlignedTrustedTightPlanOutcomeHistoryCount;
Surface.ReliableAlignedTrustedBroadPlanOutcomeHistoryCount =
Weighting.ReliableAlignedTrustedBroadPlanOutcomeHistoryCount;
Surface.ReliableAlignedTrustedTightContinuationDecisionCount =
Weighting.ReliableAlignedTrustedTightContinuationDecisionCount;
Surface.ReliableAlignedTrustedBroadRedirectDecisionCount =
Weighting.ReliableAlignedTrustedBroadRedirectDecisionCount;
Surface.AverageSuccessRate = Weighting.AverageSuccessRate;
Surface.AverageLaunchCaseCount = Weighting.AverageLaunchCaseCount;
Surface.BroadenedLaunchAverageSuccessRate =
Weighting.BroadenedLaunchAverageSuccessRate;
Surface.TightenedLaunchAverageSuccessRate =
Weighting.TightenedLaunchAverageSuccessRate;
Surface.ReliableAlignedTrustedTightPlanOutcomeAverageScore =
Weighting.ReliableAlignedTrustedTightPlanOutcomeAverageScore;
Surface.ReliableAlignedTrustedBroadPlanOutcomeAverageScore =
Weighting.ReliableAlignedTrustedBroadPlanOutcomeAverageScore;
Surface.bHasWeighting = Weighting.IsStructurallyValid();
Surface.bHasWeightingOverride = Weighting.bHasOverride;
Surface.bUsedClosureHistorySignal = Weighting.bUsedClosureHistorySignal;
Surface.bUsedDeferredOverflowSignal = Weighting.bUsedDeferredOverflowSignal;
Surface.bUsedReliableAlignedPlanOutcomeSignal =
Weighting.bUsedReliableAlignedPlanOutcomeSignal;
Surface.StatusLine = Weighting.IsStructurallyValid()
? FString::Printf(
TEXT("Weighting: %d matching decisions | Base: %s | Weighted: %s | Last applied: %s"),
Weighting.MatchingDecisionCount,
*BuildGuidanceOutcomeActionLabel(Weighting.BaseAction),
*BuildGuidanceOutcomeActionLabel(Weighting.WeightedAction),
*BuildGuidanceOutcomeActionLabel(Weighting.LastAppliedAction))
: TEXT("Weighting: no matching authored decision history yet; the current outcome action is recap-derived only.");
Surface.DetailLine = Weighting.IsStructurallyValid()
? FString::Printf(
TEXT("Decision weighting for this lane/scope: repeat case %d | repeat deck %d | broaden %d | redirect %d | Avg success %.2f | Avg launch cases %.2f | broadened launches %d (avg %.2f) | tightened launches %d (avg %.2f) | Closure continue bias %d | Closure suppress bias %d | Deferred overflow bias %d | Deferred overflow cases %d | %s"),
Weighting.RepeatSelectedCaseCount,
Weighting.RepeatPreviewDeckCount,
Weighting.BroadenPreviewDeckCount,
Weighting.RedirectCoachGuidanceCount,
Weighting.AverageSuccessRate,
Weighting.AverageLaunchCaseCount,
Weighting.BroadenedLaunchCount,
Weighting.BroadenedLaunchAverageSuccessRate,
Weighting.TightenedLaunchCount,
Weighting.TightenedLaunchAverageSuccessRate,
Weighting.ClosureContinuationBias,
Weighting.ClosureSuppressionBias,
Weighting.DeferredOverflowContinuationBias,
Weighting.DeferredOverflowCaseCount,
Weighting.bHasOverride
? (Weighting.bUsedDeferredOverflowSignal
? TEXT("Deferred-overflow continuation history and authored choices adjusted the current guidance-outcome action.")
: (Weighting.bUsedClosureHistorySignal
? TEXT("Recent closure-recovery history and authored choices adjusted the current guidance-outcome action.")
: TEXT("Recent authored choices adjusted the current guidance-outcome action.")))
: TEXT("Recent authored choices reinforced the recap-derived guidance-outcome action."))
: TEXT("Weighting detail: apply outcome actions on the same guidance lane and scope to let the dashboard bias future recommendations.");
if (Weighting.ReliableAlignedTrustedTightPlanOutcomeHistoryCount > 0
|| Weighting.ReliableAlignedTrustedBroadPlanOutcomeHistoryCount > 0
|| Weighting.ReliableAlignedTrustedTightContinuationDecisionCount > 0
|| Weighting.ReliableAlignedTrustedBroadRedirectDecisionCount > 0)
{
Surface.DetailLine += FString::Printf(
TEXT(" | Aligned launched-plan trust: tight history %d (avg %.2f, continuation decisions %d) | broad history %d (avg %.2f, redirect decisions %d)%s"),
Weighting.ReliableAlignedTrustedTightPlanOutcomeHistoryCount,
Weighting.ReliableAlignedTrustedTightPlanOutcomeAverageScore,
Weighting.ReliableAlignedTrustedTightContinuationDecisionCount,
Weighting.ReliableAlignedTrustedBroadPlanOutcomeHistoryCount,
Weighting.ReliableAlignedTrustedBroadPlanOutcomeAverageScore,
Weighting.ReliableAlignedTrustedBroadRedirectDecisionCount,
Weighting.bUsedReliableAlignedPlanOutcomeSignal
? TEXT(" | Aligned launched-plan trust adjusted the current guidance-outcome action.")
: TEXT(""));
}
if (Surface.bClosedLoopIdleActionability)
{
Surface.ResolvedActionLabel = TEXT("Loop Idle");
Surface.StatusLine =
TEXT("Weighting: retained outcome history remains inspectable, but no live guidance-outcome action is active.");
Surface.DetailLine =
TEXT("Weighting detail: closed-loop idle preserves authored outcome history for review, but it is not surfacing another repeat, broaden, or redirect action.");
}
return Surface;
}
bool UHyperTwistCoachDashboardWidget::SelectPreviousMethodDrillFollowUpHistoryEntry()
{
if (MethodDrillFollowUpHistoryEntries.Num() <= 0)

View file

@ -763,6 +763,18 @@ public:
FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryInspectSurface
GetSelectedTemplateLaunchHistoryInspectSurface() const;
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
FHyperTwistTrainingCoachDashboardGuidanceComparisonInspectSurface
GetDisplayedGuidanceComparisonInspectSurface() const;
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
FHyperTwistTrainingCoachDashboardGuidanceOutcomeInspectSurface
GetDisplayedGuidanceOutcomeInspectSurface() const;
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
FHyperTwistTrainingCoachDashboardGuidanceDecisionWeightingInspectSurface
GetDisplayedGuidanceDecisionWeightingInspectSurface() const;
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Coach|Dashboard")
bool SelectPreviousMethodDrillFollowUpHistoryEntry();

View file

@ -9729,6 +9729,368 @@ struct FHyperTwistTrainingCoachDashboardTemplateLaunchHistoryInspectSurface
}
};
USTRUCT(BlueprintType)
struct FHyperTwistTrainingCoachDashboardGuidanceComparisonInspectSurface
{
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 RunRecapSourceLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString TrainingSessionId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString GuidanceLaneLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString ScopeLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString FocusLaneLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString BriefHeadline;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString PrimaryActionLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString PreviewDeckLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString ActualDeckLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString ExpectedModeLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString ActualModeLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString ExpectedSelectionLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString ActualSelectionLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString SelectedCaseId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString LastCaseId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 ExpectedCaseCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 FocusCaseCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 CompletedAttemptCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 FailureCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 TimeoutCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 DNFCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 TotalMistakes = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
float SuccessRate = 0.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasDisplayedRunRecap = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasDisplayedGuidanceBrief = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasDisplayedGuidanceDeck = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasComparisonContext = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bSingleCaseScope = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bSelectedCaseMatchesLastCase = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bClosedLoopIdleActionability = false;
bool IsStructurallyValid() const
{
return !StatusLine.IsEmpty()
|| !DetailLine.IsEmpty()
|| bHasDisplayedRunRecap
|| bHasComparisonContext;
}
};
USTRUCT(BlueprintType)
struct FHyperTwistTrainingCoachDashboardGuidanceOutcomeInspectSurface
{
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 RunRecapSourceLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString TrainingSessionId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString GuidanceLaneLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString ScopeLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString BriefHeadline;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString ActionLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString BaseActionLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString WeightedActionLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString SelectedCaseId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 ExpectedCaseCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 CompletedAttemptCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 NonSuccessCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 TotalMistakes = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
float SuccessRate = 0.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasDisplayedRunRecap = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasDisplayedGuidanceBrief = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasDisplayedGuidanceDeck = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasComparisonContext = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bSingleCaseScope = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bCanApplyAction = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bCanRedirectAction = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasWeightingOverride = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bUsedClosureHistorySignal = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bUsedDeferredOverflowSignal = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bClosedLoopIdleActionability = false;
bool IsStructurallyValid() const
{
return !StatusLine.IsEmpty()
|| !DetailLine.IsEmpty()
|| !ActionLabel.IsEmpty()
|| bHasDisplayedRunRecap
|| bHasComparisonContext;
}
};
USTRUCT(BlueprintType)
struct FHyperTwistTrainingCoachDashboardGuidanceDecisionWeightingInspectSurface
{
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 RunRecapSourceLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString TrainingSessionId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString GuidanceLaneLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString ScopeLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString BriefHeadline;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString SelectedCaseId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString ResolvedActionLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString BaseActionLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString WeightedActionLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString LastAppliedActionLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 MatchingDecisionCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 RepeatSelectedCaseCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 RepeatPreviewDeckCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 BroadenPreviewDeckCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 RedirectCoachGuidanceCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 BroadenedLaunchCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 TightenedLaunchCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 ClosureContinuationBias = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 ClosureSuppressionBias = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 DeferredOverflowContinuationBias = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 DeferredOverflowCaseCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 ReliableAlignedTrustedTightPlanOutcomeHistoryCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 ReliableAlignedTrustedBroadPlanOutcomeHistoryCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 ReliableAlignedTrustedTightContinuationDecisionCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 ReliableAlignedTrustedBroadRedirectDecisionCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
float AverageSuccessRate = 0.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
float AverageLaunchCaseCount = 0.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
float BroadenedLaunchAverageSuccessRate = 0.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
float TightenedLaunchAverageSuccessRate = 0.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
float ReliableAlignedTrustedTightPlanOutcomeAverageScore = 0.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
float ReliableAlignedTrustedBroadPlanOutcomeAverageScore = 0.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasDisplayedRunRecap = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasDisplayedGuidanceBrief = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasDisplayedGuidanceDeck = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasComparisonContext = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bSingleCaseScope = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasWeighting = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasWeightingOverride = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bUsedClosureHistorySignal = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bUsedDeferredOverflowSignal = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bUsedReliableAlignedPlanOutcomeSignal = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bClosedLoopIdleActionability = false;
bool IsStructurallyValid() const
{
return !StatusLine.IsEmpty()
|| !DetailLine.IsEmpty()
|| bHasDisplayedRunRecap
|| bHasComparisonContext
|| bHasWeighting;
}
};
USTRUCT(BlueprintType)
struct FHyperTwistTrainingCoachGeneratedModeLaunchExecutionContextSurface
{

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 deliberate `UHyperTwistCoachDashboardWidget` retained-history inspect lane and adds selected guidance decision history and selected template launch history inspect surfaces over already-retained dashboard state, so gameplay/Blueprint callers can inspect authored decision retention, launch analytics fragments, and selection provenance without scraping dashboard text blocks or reopening decision-weighting or template-analytics derivation
- the dashboard retained-history inspect lane now appears functionally complete through queue-recovery outcome, queue-suppression history, closure-recovery history, method-drill recovery outcome history, method-drill recovery memory history, method-drill follow-up history, handoff history, guidance decision history, and template launch history inspect surfaces; the next clean move is to pivot deliberately to the live dashboard comparison / guidance-outcome / decision-weighting inspect surface trio rather than widening the retained-history seam by drift
- the latest landed bounded `Phase 4` packet pivots deliberately off that now-closed `UHyperTwistCoachDashboardWidget` retained-history inspect lane and adds displayed guidance comparison, displayed guidance outcome, and displayed guidance decision-weighting inspect surfaces over the live dashboard recap/comparison state and cached coach actionability state, so gameplay/Blueprint callers can inspect the active comparison target, current outcome action posture, and current authored weighting posture without scraping dashboard text blocks or reopening comparison/outcome derivation
- the next clean move is to stay on that same live dashboard guidance-consumer lane and land the active guidance preview selection, preview-case detail, rationale, and guidance-preference inspect surface group rather than drifting back into backend continuity or reopening the already-complete retained-history seam
- 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
## Current execution-reality references

View file

@ -0,0 +1,54 @@
# HyperTwist Phase 4 dashboard live guidance comparison, outcome, and decision-weighting inspect surface packet
- bounded Phase `4` dashboard-consumer slice
- date: `2026-05-09`
## Intent
Pivot deliberately off the now-complete retained-history inspect lane and expose the live dashboard guidance comparison, guidance-outcome, and decision-weighting state directly to gameplay and Blueprint callers.
## Why this packet exists
The dashboard already derived:
- the active recap-vs-preview comparison target
- the current repeat / broaden / redirect guidance-outcome posture
- the current authored decision-weighting bias over that same lane and scope
But that live state still only surfaced through dashboard text blocks and the live action button state. Callers still had to scrape widget presentation or reopen comparison/outcome weighting derivation to inspect what the dashboard was currently showing.
## What changed
- added `FHyperTwistTrainingCoachDashboardGuidanceComparisonInspectSurface`
- added `FHyperTwistTrainingCoachDashboardGuidanceOutcomeInspectSurface`
- added `FHyperTwistTrainingCoachDashboardGuidanceDecisionWeightingInspectSurface`
- added `GetDisplayedGuidanceComparisonInspectSurface()`
- added `GetDisplayedGuidanceOutcomeInspectSurface()`
- added `GetDisplayedGuidanceDecisionWeightingInspectSurface()`
- 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 currently displayed recap-vs-preview comparison target with lane, scope, preview-vs-actual deck/mode/selection posture, selected-case alignment, and closed-loop idle comparison posture
- the currently displayed guidance-outcome verdict with the live action button label, applyability posture, and closure-history / deferred-overflow adjustments
- the currently displayed decision-weighting summary with authored lane/scope bias, aligned launched-plan trust posture, and closed-loop idle weighting posture
without scraping dashboard text blocks or reopening comparison/outcome/weighting derivation.
## Validation
- full `Development Editor | Win64` MSBuild on `UnrealHyperTwist.sln`
- passed with `0 Warning(s), 0 Error(s)`
## Next clean slice
Stay on the same live dashboard guidance-consumer lane and land the active guidance preview selection, preview-case detail, rationale, and guidance-preference inspect surface group.