Expose dashboard follow-up and handoff history inspect surfaces

This commit is contained in:
axiomlogicnexus 2026-05-09 17:56:33 +02:00
parent 28d846ec1d
commit 0c16748821
5 changed files with 783 additions and 2 deletions

View file

@ -7828,6 +7828,351 @@ UHyperTwistCoachDashboardWidget::GetSelectedMethodDrillRecoveryMemoryHistoryInsp
return Surface;
}
FHyperTwistTrainingCoachDashboardMethodDrillFollowUpHistoryInspectSurface
UHyperTwistCoachDashboardWidget::GetSelectedMethodDrillFollowUpHistoryInspectSurface() const
{
FHyperTwistTrainingCoachDashboardMethodDrillFollowUpHistoryInspectSurface Surface;
Surface.Headline = TEXT("Method-drill follow-up history");
Surface.SelectedEntryIndex = SelectedMethodDrillFollowUpHistoryIndex;
Surface.HistoryEntryCount = MethodDrillFollowUpHistoryEntries.Num();
const FHyperTwistCoachDashboardMethodDrillFollowUpWeighting Weighting =
BuildMethodDrillFollowUpWeighting();
Surface.MatchingHistoryCount = Weighting.MatchingHistoryCount;
Surface.UpstreamPacketStructureHistoryCount = Weighting.UpstreamPacketStructureHistoryCount;
Surface.UpstreamNarrowPacketStructureHistoryCount =
Weighting.UpstreamNarrowPacketStructureHistoryCount;
Surface.UpstreamBroadPacketStructureHistoryCount =
Weighting.UpstreamBroadPacketStructureHistoryCount;
Surface.StrongOutcomeCount = Weighting.StrongOutcomeCount;
Surface.WeakOutcomeCount = Weighting.WeakOutcomeCount;
Surface.ContinueNarrowBias = Weighting.ContinueNarrowBias;
Surface.RedirectCoachBias = Weighting.RedirectCoachBias;
Surface.StrongPacketContinuationCount = Weighting.StrongPacketContinuationCount;
Surface.WeakPacketRedirectCount = Weighting.WeakPacketRedirectCount;
Surface.QueueEntryFirstStructureCount = Weighting.QueueEntryFirstStructureCount;
Surface.FollowUpPacketFirstStructureCount = Weighting.FollowUpPacketFirstStructureCount;
Surface.RecommendedBriefFirstStructureCount = Weighting.RecommendedBriefFirstStructureCount;
Surface.RecommendedRedirectStructureCount = Weighting.RecommendedRedirectStructureCount;
Surface.AverageSuccessRate = Weighting.AverageSuccessRate;
Surface.AverageMistakes = Weighting.AverageMistakes;
Surface.UpstreamNarrowPacketStructureAverageOutcomeScore =
Weighting.UpstreamNarrowPacketStructureAverageOutcomeScore;
Surface.UpstreamBroadPacketStructureAverageOutcomeScore =
Weighting.UpstreamBroadPacketStructureAverageOutcomeScore;
Surface.bHasHistoryWeighting = Weighting.IsStructurallyValid();
Surface.bPreferDrillFollowUp = Weighting.bPreferDrillFollowUp;
Surface.bPreferCoachHandoff = Weighting.bPreferCoachHandoff;
Surface.bHasUpstreamStructureSignal = Weighting.bHasUpstreamStructureSignal;
Surface.bUsedUpstreamNarrowStructureSignal = Weighting.bUsedUpstreamNarrowStructureSignal;
Surface.bUsedUpstreamBroadStructureSignal = Weighting.bUsedUpstreamBroadStructureSignal;
Surface.OutcomePreferenceLine = !Weighting.IsStructurallyValid()
? TEXT("no retained drill follow-up history yet")
: (Weighting.bPreferDrillFollowUp
? (Weighting.bUsedUpstreamNarrowStructureSignal
? TEXT("retained drill-follow-up packet structure history favors staying narrow with drill follow-up")
: TEXT("retained drill history favors staying narrow with drill follow-up"))
: (Weighting.bPreferCoachHandoff
? (Weighting.bUsedUpstreamBroadStructureSignal
? TEXT("retained drill-follow-up packet structure history favors handing control back to broader coach guidance")
: TEXT("retained drill history favors handing control back to broader coach guidance"))
: TEXT("retained drill history is balanced")));
const FHyperTwistCoachDashboardMethodDrillFollowUpHistoryEntry* SelectedEntry =
SelectedMethodDrillFollowUpHistoryIndex >= 0
&& SelectedMethodDrillFollowUpHistoryIndex < MethodDrillFollowUpHistoryEntries.Num()
? &MethodDrillFollowUpHistoryEntries[SelectedMethodDrillFollowUpHistoryIndex]
: nullptr;
Surface.bHasSelectedEntry =
SelectedEntry != nullptr && SelectedEntry->IsStructurallyValid();
if (!Surface.bHasSelectedEntry)
{
Surface.StatusLine =
TEXT("Drill follow-up history: no retained drill follow-up outcomes recorded yet.");
Surface.DetailLine =
TEXT("Drill follow-up history detail: once drill-derived follow-up runs complete, their recap outcomes will accumulate here and feed later drill-vs-handoff judgment.");
return Surface;
}
Surface.RecordedAtUtc = SelectedEntry->RecordedAtUtc;
Surface.SourceRunId = SelectedEntry->SourceRunId;
Surface.SourceDrillId = SelectedEntry->SourceDrillId;
Surface.SourceSessionId = SelectedEntry->SourceSessionId;
Surface.StageLabel =
SelectedEntry->StageLabel.IsEmpty() ? TEXT("n/a") : SelectedEntry->StageLabel;
Surface.DiagnosticState = SelectedEntry->DiagnosticState;
Surface.DiagnosticStateLabel =
HyperTwistCoachDashboardWidgetInternal::EnumDisplayName(
SelectedEntry->DiagnosticState);
Surface.RecommendedReviewGrade = SelectedEntry->RecommendedReviewGrade;
Surface.RecommendedReviewGradeLabel =
HyperTwistCoachDashboardWidgetInternal::EnumDisplayName(
SelectedEntry->RecommendedReviewGrade);
Surface.TemplateKind = SelectedEntry->TemplateKind;
Surface.TemplateKindLabel =
HyperTwistCoachDashboardWidgetInternal::EnumDisplayName(
SelectedEntry->TemplateKind);
Surface.SuggestedMode = SelectedEntry->SuggestedMode;
Surface.SuggestedModeLabel =
HyperTwistCoachDashboardWidgetInternal::EnumDisplayName(
SelectedEntry->SuggestedMode);
Surface.SuggestedSelectionPolicy = SelectedEntry->SuggestedSelectionPolicy;
Surface.SuggestedSelectionLabel =
HyperTwistCoachDashboardWidgetInternal::EnumDisplayName(
SelectedEntry->SuggestedSelectionPolicy);
Surface.PacketStructureLabel =
SelectedEntry->PacketStructureLabel.IsEmpty()
? TEXT("default")
: SelectedEntry->PacketStructureLabel;
Surface.PacketLaneLabel =
SelectedEntry->PacketLaneLabel.IsEmpty()
? TEXT("none")
: SelectedEntry->PacketLaneLabel;
Surface.PacketStanceLabel =
SelectedEntry->PacketStanceLabel.IsEmpty()
? TEXT("none")
: SelectedEntry->PacketStanceLabel;
Surface.FocusCaseCount = SelectedEntry->FocusCaseCount;
Surface.LaunchedCaseCount = SelectedEntry->LaunchedCaseCount;
Surface.CompletedAttemptCount = SelectedEntry->CompletedAttemptCount;
Surface.TotalMistakes = SelectedEntry->TotalMistakes;
Surface.SuccessRate = SelectedEntry->SuccessRate;
Surface.bBoundaryPending = SelectedEntry->bBoundaryPending;
Surface.bBoundaryRepeatBurden = SelectedEntry->bBoundaryRepeatBurden;
Surface.bBoundaryAssistance = SelectedEntry->bBoundaryAssistance;
Surface.bPacketProvenStrongContinuation =
SelectedEntry->bPacketProvenStrongContinuation;
Surface.bPacketProvenWeakRedirect = SelectedEntry->bPacketProvenWeakRedirect;
Surface.StatusLine = FString::Printf(
TEXT("Drill follow-up history: %d entries | selected %d/%d | Stage: %s | review %s | Recorded: %s"),
MethodDrillFollowUpHistoryEntries.Num(),
SelectedMethodDrillFollowUpHistoryIndex + 1,
MethodDrillFollowUpHistoryEntries.Num(),
*Surface.StageLabel,
*Surface.RecommendedReviewGradeLabel,
*SelectedEntry->RecordedAtUtc);
Surface.DetailLine = FString::Printf(
TEXT("State: %s | template: %s | mode: %s | selection: %s | focus %d | launched %d | success %.2f | attempts %d | mistakes %d | packet structure: %s | packet lane: %s | packet stance: %s | pending: %s | repeat burden: %s | assistance: %s"),
*Surface.DiagnosticStateLabel,
*Surface.TemplateKindLabel,
*Surface.SuggestedModeLabel,
*Surface.SuggestedSelectionLabel,
SelectedEntry->FocusCaseCount,
SelectedEntry->LaunchedCaseCount,
SelectedEntry->SuccessRate,
SelectedEntry->CompletedAttemptCount,
SelectedEntry->TotalMistakes,
*Surface.PacketStructureLabel,
*Surface.PacketLaneLabel,
*Surface.PacketStanceLabel,
SelectedEntry->bBoundaryPending ? TEXT("yes") : TEXT("no"),
SelectedEntry->bBoundaryRepeatBurden ? TEXT("yes") : TEXT("no"),
SelectedEntry->bBoundaryAssistance ? TEXT("yes") : TEXT("no"));
return Surface;
}
FHyperTwistTrainingCoachDashboardHandoffHistoryInspectSurface
UHyperTwistCoachDashboardWidget::GetSelectedHandoffHistoryInspectSurface() const
{
FHyperTwistTrainingCoachDashboardHandoffHistoryInspectSurface Surface;
Surface.Headline = TEXT("Handoff history");
Surface.SelectedEntryIndex = SelectedHandoffHistoryIndex;
Surface.HistoryEntryCount = HandoffHistoryEntries.Num();
const FHyperTwistCoachDashboardHandoffHistoryEntry* SelectedEntry =
SelectedHandoffHistoryIndex >= 0
&& SelectedHandoffHistoryIndex < HandoffHistoryEntries.Num()
? &HandoffHistoryEntries[SelectedHandoffHistoryIndex]
: nullptr;
Surface.bHasSelectedEntry =
SelectedEntry != nullptr && SelectedEntry->IsStructurallyValid();
if (!Surface.bHasSelectedEntry)
{
Surface.StatusLine =
TEXT("Handoff history: no retained handoff-pattern shifts recorded yet.");
Surface.DetailLine =
TEXT("Handoff history detail: retained recommendation shifts and accepted queued/follow-up/recommended handoff patterns will accumulate here over time.");
return Surface;
}
Surface.RecordedAtUtc = SelectedEntry->RecordedAtUtc;
Surface.RecommendedHandoffKindLabel =
SelectedEntry->RecommendedHandoffKindLabel.IsEmpty()
? TEXT("none")
: SelectedEntry->RecommendedHandoffKindLabel;
Surface.RecommendationStatusLine = SelectedEntry->RecommendationStatusLine;
Surface.RecommendationDetailLine =
SelectedEntry->RecommendationDetailLine.IsEmpty()
? SelectedEntry->RecommendationStatusLine
: SelectedEntry->RecommendationDetailLine;
Surface.QueueSourceLabel =
SelectedEntry->QueueSourceLabel.IsEmpty()
? TEXT("n/a")
: SelectedEntry->QueueSourceLabel;
Surface.PreferredGuidanceLane = SelectedEntry->PreferredGuidanceLane;
Surface.PreferredLaneLine =
HyperTwistCoachDashboardWidgetInternal::DescribeGuidanceLane(
SelectedEntry->PreferredGuidanceLane);
Surface.PreferredGuidanceSourceLabel = SelectedEntry->PreferredGuidanceSourceLabel;
Surface.PreferredGuidanceSourceDescription =
SelectedEntry->PreferredGuidanceSourceLabel.IsEmpty()
? TEXT("n/a")
: HyperTwistCoachDashboardWidgetInternal::DescribeCoachMemorySourceLabel(
SelectedEntry->PreferredGuidanceSourceLabel);
Surface.PreferredRecoveryAction = SelectedEntry->PreferredRecoveryAction;
Surface.PreferredRecoveryActionLabel =
SelectedEntry->PreferredRecoveryAction
== EHyperTwistTrainingQueueRecoveryAction::None
? TEXT("none")
: HyperTwistCoachDashboardWidgetInternal::EnumDisplayName(
SelectedEntry->PreferredRecoveryAction);
Surface.PreferredRecoveryActionSourceLabel =
SelectedEntry->PreferredRecoveryActionSourceLabel;
Surface.PreferredRecoveryActionSourceDescription =
SelectedEntry->PreferredRecoveryActionSourceLabel.IsEmpty()
? TEXT("n/a")
: HyperTwistCoachDashboardWidgetInternal::DescribeCoachMemorySourceLabel(
SelectedEntry->PreferredRecoveryActionSourceLabel);
Surface.RetainedPostureLine =
HyperTwistCoachDashboardWidgetInternal::DescribeRetainedMethodDrillRecoveryPosture(
SelectedEntry->bUsedStrongRetainedMethodDrillRecoveryPosture,
SelectedEntry->bUsedWeakRetainedMethodDrillRecoveryPosture);
Surface.ReliablePlanLine = [&]() -> FString
{
if (SelectedEntry->bUsedReliableAlignedTrustedTightStructurePlanOutcomeHistory)
{
return TEXT("aligned trusted tight launched-plan continuation");
}
if (SelectedEntry->bUsedReliableAlignedTrustedBroadStructurePlanOutcomeHistory)
{
return TEXT("aligned trusted broad launched-plan redirect");
}
if (SelectedEntry->bUsedReliableAlignedTrustedTightStructurePlanHistory)
{
return TEXT("aligned trusted tight continuation");
}
if (SelectedEntry->bUsedReliableAlignedTrustedBroadStructurePlanHistory)
{
return TEXT("aligned trusted broad redirect");
}
if (SelectedEntry->bUsedReliableTrustedTightStructurePlanHistory)
{
return TEXT("trusted tight continuation");
}
if (SelectedEntry->bUsedReliableTrustedBroadStructurePlanHistory)
{
return TEXT("trusted broad redirect");
}
return TEXT("none");
}();
Surface.AcceptedQueuedHandoffCount = SelectedEntry->AcceptedQueuedHandoffCount;
Surface.AcceptedFollowUpHandoffCount = SelectedEntry->AcceptedFollowUpHandoffCount;
Surface.AcceptedRecommendedHandoffCount =
SelectedEntry->AcceptedRecommendedHandoffCount;
Surface.AcceptedDeferredOverflowQueuedHandoffCount =
SelectedEntry->AcceptedDeferredOverflowQueuedHandoffCount;
Surface.AcceptedDeferredOverflowFollowUpHandoffCount =
SelectedEntry->AcceptedDeferredOverflowFollowUpHandoffCount;
Surface.AcceptedDeferredOverflowRecommendedHandoffCount =
SelectedEntry->AcceptedDeferredOverflowRecommendedHandoffCount;
Surface.AcceptedMethodDrillQueuedHandoffCount =
SelectedEntry->AcceptedMethodDrillQueuedHandoffCount;
Surface.AcceptedMethodDrillFollowUpHandoffCount =
SelectedEntry->AcceptedMethodDrillFollowUpHandoffCount;
Surface.AcceptedMethodDrillRecommendedHandoffCount =
SelectedEntry->AcceptedMethodDrillRecommendedHandoffCount;
Surface.AcceptedAlignedTightFollowUpOutcomeHandoffCount =
SelectedEntry->AcceptedAlignedTightFollowUpOutcomeHandoffCount;
Surface.AcceptedAlignedBroadRecommendedOutcomeHandoffCount =
SelectedEntry->AcceptedAlignedBroadRecommendedOutcomeHandoffCount;
Surface.AcceptedAlignedTightFollowUpPacketHandoffCount =
SelectedEntry->AcceptedAlignedTightFollowUpPacketHandoffCount;
Surface.AcceptedAlignedBroadRecommendedPacketHandoffCount =
SelectedEntry->AcceptedAlignedBroadRecommendedPacketHandoffCount;
Surface.ReliableAcceptedAlignedTightFollowUpPacketOutcomeHandoffCount =
SelectedEntry->ReliableAcceptedAlignedTightFollowUpPacketOutcomeHandoffCount;
Surface.ReliableAcceptedAlignedBroadRecommendedPacketOutcomeHandoffCount =
SelectedEntry->ReliableAcceptedAlignedBroadRecommendedPacketOutcomeHandoffCount;
Surface.ReliableAlignedTrustedTightPlanOutcomeHistoryCount =
SelectedEntry->ReliableAlignedTrustedTightPlanOutcomeHistoryCount;
Surface.ReliableAlignedTrustedBroadPlanOutcomeHistoryCount =
SelectedEntry->ReliableAlignedTrustedBroadPlanOutcomeHistoryCount;
Surface.ReliableAlignedTrustedTightPlanOutcomeAverageScore =
SelectedEntry->ReliableAlignedTrustedTightPlanOutcomeAverageScore;
Surface.ReliableAlignedTrustedBroadPlanOutcomeAverageScore =
SelectedEntry->ReliableAlignedTrustedBroadPlanOutcomeAverageScore;
Surface.ClosureContinuationBias = SelectedEntry->ClosureContinuationBias;
Surface.ClosureSuppressionBias = SelectedEntry->ClosureSuppressionBias;
Surface.bQueueReady = SelectedEntry->bQueueReady;
Surface.bFollowUpReady = SelectedEntry->bFollowUpReady;
Surface.bRecommendedReady = SelectedEntry->bRecommendedReady;
Surface.bUsedDeferredFirstSuppressionSignal =
SelectedEntry->bUsedDeferredFirstSuppressionSignal;
Surface.bUsedMethodDrillWeighting = SelectedEntry->bUsedMethodDrillWeighting;
Surface.bUsedStrongRetainedMethodDrillRecoveryPosture =
SelectedEntry->bUsedStrongRetainedMethodDrillRecoveryPosture;
Surface.bUsedWeakRetainedMethodDrillRecoveryPosture =
SelectedEntry->bUsedWeakRetainedMethodDrillRecoveryPosture;
Surface.bUsedReliableTrustedTightStructurePlanHistory =
SelectedEntry->bUsedReliableTrustedTightStructurePlanHistory;
Surface.bUsedReliableTrustedBroadStructurePlanHistory =
SelectedEntry->bUsedReliableTrustedBroadStructurePlanHistory;
Surface.bUsedReliableAlignedTrustedTightStructurePlanHistory =
SelectedEntry->bUsedReliableAlignedTrustedTightStructurePlanHistory;
Surface.bUsedReliableAlignedTrustedBroadStructurePlanHistory =
SelectedEntry->bUsedReliableAlignedTrustedBroadStructurePlanHistory;
Surface.bUsedReliableAlignedTrustedTightStructurePlanOutcomeHistory =
SelectedEntry->bUsedReliableAlignedTrustedTightStructurePlanOutcomeHistory;
Surface.bUsedReliableAlignedTrustedBroadStructurePlanOutcomeHistory =
SelectedEntry->bUsedReliableAlignedTrustedBroadStructurePlanOutcomeHistory;
Surface.StatusLine = FString::Printf(
TEXT("Handoff history: %d entries | selected %d/%d | Recommendation: %s | Stance: %s | Reliable plan: %s | Recorded: %s"),
HandoffHistoryEntries.Num(),
SelectedHandoffHistoryIndex + 1,
HandoffHistoryEntries.Num(),
*Surface.RecommendedHandoffKindLabel,
*Surface.RetainedPostureLine,
*Surface.ReliablePlanLine,
*SelectedEntry->RecordedAtUtc);
Surface.DetailLine = FString::Printf(
TEXT("Accepted queued/follow-up/recommended: %d/%d/%d | aligned guidance accepted follow-up/recommended: %d/%d | aligned packet accepted follow-up/recommended: %d/%d | reliable accepted aligned packet handoff follow-up/recommended: %d/%d | deferred-overflow queued/follow-up/recommended: %d/%d/%d | drill-driven queued/follow-up/recommended: %d/%d/%d | aligned reliable handoff outcomes tight/broad %d/%d avg %.1f/%.1f | deferred-first suppression recommendation used: %s | drill weighting used: %s | reliable trusted plan: %s | retained posture: %s | queue source: %s | preferred lane: %s | memory source: %s | recovery action: %s | recovery source: %s | closure continuation bias %d | closure suppression bias %d | readiness queue/follow-up/recommended: %s/%s/%s || %s"),
SelectedEntry->AcceptedQueuedHandoffCount,
SelectedEntry->AcceptedFollowUpHandoffCount,
SelectedEntry->AcceptedRecommendedHandoffCount,
SelectedEntry->AcceptedAlignedTightFollowUpOutcomeHandoffCount,
SelectedEntry->AcceptedAlignedBroadRecommendedOutcomeHandoffCount,
SelectedEntry->AcceptedAlignedTightFollowUpPacketHandoffCount,
SelectedEntry->AcceptedAlignedBroadRecommendedPacketHandoffCount,
SelectedEntry->ReliableAcceptedAlignedTightFollowUpPacketOutcomeHandoffCount,
SelectedEntry->ReliableAcceptedAlignedBroadRecommendedPacketOutcomeHandoffCount,
SelectedEntry->AcceptedDeferredOverflowQueuedHandoffCount,
SelectedEntry->AcceptedDeferredOverflowFollowUpHandoffCount,
SelectedEntry->AcceptedDeferredOverflowRecommendedHandoffCount,
SelectedEntry->AcceptedMethodDrillQueuedHandoffCount,
SelectedEntry->AcceptedMethodDrillFollowUpHandoffCount,
SelectedEntry->AcceptedMethodDrillRecommendedHandoffCount,
SelectedEntry->ReliableAlignedTrustedTightPlanOutcomeHistoryCount,
SelectedEntry->ReliableAlignedTrustedBroadPlanOutcomeHistoryCount,
SelectedEntry->ReliableAlignedTrustedTightPlanOutcomeAverageScore,
SelectedEntry->ReliableAlignedTrustedBroadPlanOutcomeAverageScore,
SelectedEntry->bUsedDeferredFirstSuppressionSignal ? TEXT("yes") : TEXT("no"),
SelectedEntry->bUsedMethodDrillWeighting ? TEXT("yes") : TEXT("no"),
*Surface.ReliablePlanLine,
*Surface.RetainedPostureLine,
*Surface.QueueSourceLabel,
*Surface.PreferredLaneLine,
*Surface.PreferredGuidanceSourceDescription,
*Surface.PreferredRecoveryActionLabel,
*Surface.PreferredRecoveryActionSourceDescription,
SelectedEntry->ClosureContinuationBias,
SelectedEntry->ClosureSuppressionBias,
SelectedEntry->bQueueReady ? TEXT("yes") : TEXT("no"),
SelectedEntry->bFollowUpReady ? TEXT("yes") : TEXT("no"),
SelectedEntry->bRecommendedReady ? TEXT("yes") : TEXT("no"),
*Surface.RecommendationDetailLine);
return Surface;
}
bool UHyperTwistCoachDashboardWidget::SelectPreviousMethodDrillFollowUpHistoryEntry()
{
if (MethodDrillFollowUpHistoryEntries.Num() <= 0)

View file

@ -747,6 +747,14 @@ public:
FHyperTwistTrainingCoachDashboardMethodDrillRecoveryMemoryHistoryInspectSurface
GetSelectedMethodDrillRecoveryMemoryHistoryInspectSurface() const;
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
FHyperTwistTrainingCoachDashboardMethodDrillFollowUpHistoryInspectSurface
GetSelectedMethodDrillFollowUpHistoryInspectSurface() const;
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
FHyperTwistTrainingCoachDashboardHandoffHistoryInspectSurface
GetSelectedHandoffHistoryInspectSurface() const;
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Coach|Dashboard")
bool SelectPreviousMethodDrillFollowUpHistoryEntry();

View file

@ -9037,6 +9037,384 @@ struct FHyperTwistTrainingCoachDashboardMethodDrillRecoveryMemoryHistoryInspectS
}
};
USTRUCT(BlueprintType)
struct FHyperTwistTrainingCoachDashboardMethodDrillFollowUpHistoryInspectSurface
{
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 RecordedAtUtc;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString SourceRunId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString SourceDrillId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString SourceSessionId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString StageLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString DiagnosticStateLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString RecommendedReviewGradeLabel;
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")
FString OutcomePreferenceLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString PacketStructureLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString PacketLaneLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString PacketStanceLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 SelectedEntryIndex = INDEX_NONE;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 HistoryEntryCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 MatchingHistoryCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 UpstreamPacketStructureHistoryCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 UpstreamNarrowPacketStructureHistoryCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 UpstreamBroadPacketStructureHistoryCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 StrongOutcomeCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 WeakOutcomeCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 ContinueNarrowBias = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 RedirectCoachBias = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 StrongPacketContinuationCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 WeakPacketRedirectCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 QueueEntryFirstStructureCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 FollowUpPacketFirstStructureCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 RecommendedBriefFirstStructureCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 RecommendedRedirectStructureCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 FocusCaseCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 LaunchedCaseCount = 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")
float AverageSuccessRate = 0.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
float AverageMistakes = 0.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
float UpstreamNarrowPacketStructureAverageOutcomeScore = 0.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
float UpstreamBroadPacketStructureAverageOutcomeScore = 0.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
EHyperTwistTrainingMethodDrillDiagnosticState DiagnosticState =
EHyperTwistTrainingMethodDrillDiagnosticState::Unknown;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
EHyperTwistTrainingReviewGrade RecommendedReviewGrade =
EHyperTwistTrainingReviewGrade::Good;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
EHyperTwistTrainingSessionTemplateKind TemplateKind =
EHyperTwistTrainingSessionTemplateKind::ReviewPlan;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
EHyperTwistTrainingDeliveryMode SuggestedMode =
EHyperTwistTrainingDeliveryMode::Timer;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
EHyperTwistTrainingSelectionPolicy SuggestedSelectionPolicy =
EHyperTwistTrainingSelectionPolicy::Weighted;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasSelectedEntry = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasHistoryWeighting = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bBoundaryPending = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bBoundaryRepeatBurden = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bBoundaryAssistance = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bPacketProvenStrongContinuation = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bPacketProvenWeakRedirect = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bPreferDrillFollowUp = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bPreferCoachHandoff = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasUpstreamStructureSignal = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bUsedUpstreamNarrowStructureSignal = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bUsedUpstreamBroadStructureSignal = false;
bool IsStructurallyValid() const
{
return !StatusLine.IsEmpty()
|| !DetailLine.IsEmpty()
|| bHasSelectedEntry
|| bHasHistoryWeighting
|| HistoryEntryCount > 0;
}
};
USTRUCT(BlueprintType)
struct FHyperTwistTrainingCoachDashboardHandoffHistoryInspectSurface
{
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 RecordedAtUtc;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString RecommendedHandoffKindLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString RecommendationStatusLine;
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 PreferredGuidanceSourceLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString PreferredGuidanceSourceDescription;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString PreferredRecoveryActionLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString PreferredRecoveryActionSourceLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString PreferredRecoveryActionSourceDescription;
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")
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 AcceptedDeferredOverflowQueuedHandoffCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 AcceptedDeferredOverflowFollowUpHandoffCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 AcceptedDeferredOverflowRecommendedHandoffCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 AcceptedMethodDrillQueuedHandoffCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 AcceptedMethodDrillFollowUpHandoffCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 AcceptedMethodDrillRecommendedHandoffCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 AcceptedAlignedTightFollowUpOutcomeHandoffCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 AcceptedAlignedBroadRecommendedOutcomeHandoffCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 AcceptedAlignedTightFollowUpPacketHandoffCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 AcceptedAlignedBroadRecommendedPacketHandoffCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 ReliableAcceptedAlignedTightFollowUpPacketOutcomeHandoffCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 ReliableAcceptedAlignedBroadRecommendedPacketOutcomeHandoffCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 ReliableAlignedTrustedTightPlanOutcomeHistoryCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 ReliableAlignedTrustedBroadPlanOutcomeHistoryCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 ClosureContinuationBias = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 ClosureSuppressionBias = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
float ReliableAlignedTrustedTightPlanOutcomeAverageScore = 0.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
float ReliableAlignedTrustedBroadPlanOutcomeAverageScore = 0.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
EHyperTwistTrainingCoachGuidanceLane PreferredGuidanceLane =
EHyperTwistTrainingCoachGuidanceLane::None;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
EHyperTwistTrainingQueueRecoveryAction PreferredRecoveryAction =
EHyperTwistTrainingQueueRecoveryAction::None;
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;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bUsedStrongRetainedMethodDrillRecoveryPosture = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bUsedWeakRetainedMethodDrillRecoveryPosture = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bUsedReliableTrustedTightStructurePlanHistory = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bUsedReliableTrustedBroadStructurePlanHistory = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bUsedReliableAlignedTrustedTightStructurePlanHistory = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bUsedReliableAlignedTrustedBroadStructurePlanHistory = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bUsedReliableAlignedTrustedTightStructurePlanOutcomeHistory = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bUsedReliableAlignedTrustedBroadStructurePlanOutcomeHistory = false;
bool IsStructurallyValid() const
{
return !StatusLine.IsEmpty()
|| !DetailLine.IsEmpty()
|| bHasSelectedEntry
|| HistoryEntryCount > 0;
}
};
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 method-drill recovery outcome history and selected method-drill recovery memory history inspect surfaces over already-retained dashboard state, so gameplay/Blueprint callers can inspect retained drill-recovery outcome shifts and upstream recovery-memory posture without scraping dashboard text blocks or reopening recovery-memory comparison derivation
- the current next bounded packet should stay on that same dashboard retained-history inspect lane only while a real gameplay or Blueprint caller still needs one more thin inspect contract over already-retained dashboard history state; the next clean move inside that lane is the method-drill follow-up history and handoff history inspect pair rather than widening back into backend continuity or runtime-library drift
- the latest landed bounded `Phase 4` packet stays on that same deliberate `UHyperTwistCoachDashboardWidget` retained-history inspect lane and adds selected method-drill follow-up history and selected handoff history inspect surfaces over already-retained dashboard state, so gameplay/Blueprint callers can inspect retained drill follow-up recap posture and retained handoff-pattern shifts without scraping dashboard text blocks or reopening follow-up weighting or handoff-memory derivation
- the current next bounded packet should stay on that same dashboard retained-history inspect lane only while a real gameplay or Blueprint caller still needs one more thin inspect contract over already-retained dashboard history state; the next clean move inside that lane is the guidance decision history and template launch history inspect pair rather than widening back into backend continuity or runtime-library drift
- the current execution-discipline rule that broad refactor / monolith-splitting work should not interrupt the active bounded roadmap packet unless structure is actually blocking it
## Current execution-reality references

View file

@ -0,0 +1,50 @@
# HyperTwist Phase 4 dashboard method-drill follow-up and handoff history inspect surface packet
- bounded Phase `4` dashboard-consumer slice
- date: `2026-05-09`
## Intent
Stay on the deliberate `UHyperTwistCoachDashboardWidget` retained-history inspect lane and expose the next two retained dashboard history families directly to gameplay and Blueprint callers.
## Why this packet exists
The dashboard already retained:
- selected method-drill follow-up history entries and their current drill-vs-handoff weighting posture
- selected handoff history entries and their retained recommendation-shift memory
But that state still only surfaced through dashboard text blocks and selection actions. Callers still had to scrape widget presentation or reopen follow-up weighting and handoff-memory derivation to inspect retained orchestration posture directly.
## What changed
- added `FHyperTwistTrainingCoachDashboardMethodDrillFollowUpHistoryInspectSurface`
- added `FHyperTwistTrainingCoachDashboardHandoffHistoryInspectSurface`
- added `GetSelectedMethodDrillFollowUpHistoryInspectSurface()`
- added `GetSelectedHandoffHistoryInspectSurface()`
- 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 selected retained method-drill follow-up history entry with drill source ids, stage, diagnostic/review/template posture, launch shape, packet posture, boundary state, and retained follow-up weighting summary
- the selected retained handoff history entry with recommendation label, reliable-plan posture, retained drill-recovery stance, queue/guidance/recovery source attribution, readiness posture, and retained accepted-handoff counts
without scraping dashboard text blocks or reopening follow-up weighting or handoff-memory derivation.
## Validation
- full `Development Editor | Win64` MSBuild on `UnrealHyperTwist.sln`
- passed with `0 Warning(s), 0 Error(s)`
## Next clean slice
Stay on this dashboard retained-history inspect lane only while a real gameplay or Blueprint caller still needs one more thin inspect contract over already-retained dashboard history state. The next clean move is the guidance decision history and template launch history inspect pair.