From 5ac8ff9169cb40535eb8b7b7504ad270cb53a049 Mon Sep 17 00:00:00 2001 From: axiomlogicnexus Date: Tue, 28 Apr 2026 04:09:25 +0200 Subject: [PATCH] Generalize deferred-first continuation coaching --- .../HyperTwistCoachDashboardWidget.cpp | 8 +- .../HyperTwistTrainingCoachLibrary.cpp | 185 ++++++++++++------ 2 files changed, 125 insertions(+), 68 deletions(-) diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp index 2441783..9d4e0d0 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp @@ -772,7 +772,7 @@ bool UHyperTwistCoachDashboardWidget::ApplyQueueRecoveryPosture() const FHyperTwistCoachSignal* DeferredFirstSuppressionSignal = HyperTwistCoachDashboardWidgetInternal::FindCoachSignalById( CachedCoachSignals, - TEXT("queue_suppression_deferred_first_follow_up")); + TEXT("queue_suppression_deferred_first_continuation")); const bool bHasDeferredFirstSuppressionSignal = DeferredFirstSuppressionSignal != nullptr; const bool bPrefersFollowUp = @@ -5207,13 +5207,13 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation() const FHyperTwistCoachSignal* DeferredFirstSuppressionSignal = HyperTwistCoachDashboardWidgetInternal::FindCoachSignalById( CachedCoachSignals, - TEXT("queue_suppression_deferred_first_follow_up")); + TEXT("queue_suppression_deferred_first_continuation")); const bool bHasDeferredFirstSuppressionSignal = DeferredFirstSuppressionSignal != nullptr; const bool bDeferredFirstSuppressionSignalPromoted = CachedCoachBrief.Signals.Num() > 0 && CachedCoachBrief.Signals[0].SignalId - == TEXT("queue_suppression_deferred_first_follow_up"); + == TEXT("queue_suppression_deferred_first_continuation"); HyperTwistCoachDashboardWidgetInternal::EHandoffRecommendationKind HandoffRecommendationKind = HyperTwistCoachDashboardWidgetInternal::EHandoffRecommendationKind::None; DisplayedCoachHandoffRecommendationKind = EHyperTwistTrainingCoachHandoffKind::None; @@ -5743,7 +5743,7 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation() const FHyperTwistCoachSignal* QueueDeferredFirstSuppressionSignal = HyperTwistCoachDashboardWidgetInternal::FindCoachSignalById( CachedCoachSignals, - TEXT("queue_suppression_deferred_first_follow_up")); + TEXT("queue_suppression_deferred_first_continuation")); const bool bHasDeferredFirstQueueSuppressionSignal = QueueDeferredFirstSuppressionSignal != nullptr; const bool bCanLaunchQueueRecovery = diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp index 5bdf050..adae20d 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp @@ -23,12 +23,17 @@ namespace HyperTwistTrainingCoachLibraryInternal return SourceLabel.StartsWith(TEXT("coach-memory-dashboard-")); } + bool IsDeferredFirstContinuationSource(const FString& SourceLabel) + { + return SourceLabel.StartsWith(TEXT("coach-memory-dashboard-deferred-first-")) + || SourceLabel.StartsWith(TEXT("dashboard-handoff-deferred-first-")) + || SourceLabel == TEXT("recommendation-history-deferred-first-follow-up"); + } + bool IsDeferredOverflowDashboardHandoffSource(const FString& SourceLabel) { return SourceLabel.StartsWith(TEXT("coach-memory-dashboard-deferred-overflow-")) - || SourceLabel.StartsWith(TEXT("coach-memory-dashboard-deferred-first-")) - || SourceLabel.StartsWith(TEXT("dashboard-handoff-deferred-first-")) - || SourceLabel == TEXT("recommendation-history-deferred-first-follow-up"); + || IsDeferredFirstContinuationSource(SourceLabel); } FString DescribeCoachHandoffKind(const EHyperTwistTrainingCoachHandoffKind HandoffKind) @@ -265,11 +270,13 @@ namespace HyperTwistTrainingCoachLibraryInternal const FHyperTwistTrainingCoachMemorySnapshot& CoachMemorySnapshot) { const bool bPreferredGuidanceSource = - CoachMemorySnapshot.PreferredGuidanceSourceLabel - == TEXT("recommendation-history-deferred-first-follow-up"); + IsDeferredFirstContinuationSource( + CoachMemorySnapshot.PreferredGuidanceSourceLabel + ); const bool bPreferredHandoffSource = - CoachMemorySnapshot.PreferredCoachHandoffSourceLabel - == TEXT("recommendation-history-deferred-first-follow-up"); + IsDeferredFirstContinuationSource( + CoachMemorySnapshot.PreferredCoachHandoffSourceLabel + ); if (CoachMemorySnapshot.DeferredFirstFollowUpPacketHistoryCount <= 0 && !bPreferredGuidanceSource && !bPreferredHandoffSource) @@ -526,6 +533,20 @@ namespace HyperTwistTrainingCoachLibraryInternal const float DeferredFirstPacketPressure = ResolveDeferredFirstFollowUpPacketPressure( CoachMemorySnapshot ); + const FString DeferredFirstHistorySourceLabel = + HyperTwistTrainingCoachLibraryInternal::IsDeferredFirstContinuationSource( + CoachMemorySnapshot.PreferredCoachHandoffSourceLabel + ) + ? HyperTwistTrainingCoachLibraryInternal::DescribeCoachMemorySourceLabel( + CoachMemorySnapshot.PreferredCoachHandoffSourceLabel + ) + : (HyperTwistTrainingCoachLibraryInternal::IsDeferredFirstContinuationSource( + CoachMemorySnapshot.PreferredGuidanceSourceLabel + ) + ? HyperTwistTrainingCoachLibraryInternal::DescribeCoachMemorySourceLabel( + CoachMemorySnapshot.PreferredGuidanceSourceLabel + ) + : TEXT("successful deferred-first continuation history")); const bool bDeferredFirstFollowUpHistoryPreferred = DeferredFirstPacketPressure > 0.0f; const bool bScheduleRecoveryPrefersFollowUp = CoachMemorySnapshot.bNeedsScheduleFrictionRecovery @@ -559,7 +580,8 @@ namespace HyperTwistTrainingCoachLibraryInternal if (bNeedsDeferredLaunchCompetition && bDeferredFirstFollowUpHistoryPreferred) { *OutSuppressionReason = FString::Printf( - TEXT("Recommended queue creation was suppressed because successful deferred-first follow-up history is reinforcing narrowed continuation while tightened-budget deferred coach work remains unresolved (recommended %.1f vs follow-up %.1f, deferredLaunchCases=%d, deferredFirstHistory=%d)."), + TEXT("Recommended queue creation was suppressed because %s is reinforcing narrowed continuation while tightened-budget deferred coach work remains unresolved (recommended %.1f vs follow-up %.1f, deferredLaunchCases=%d, deferredFirstHistory=%d)."), + *DeferredFirstHistorySourceLabel, RecommendedRetentionScore, FollowUpPressureScore, FollowUpBrief.DeferredLaunchCaseCount, @@ -578,7 +600,8 @@ namespace HyperTwistTrainingCoachLibraryInternal else if (bDeferredFirstFollowUpHistoryPreferred) { *OutSuppressionReason = FString::Printf( - TEXT("Recommended queue creation was suppressed because successful deferred-first follow-up history is reinforcing narrowed continuation before broader recommendation work resumes (recommended %.1f vs follow-up %.1f, deferredFirstHistory=%d)."), + TEXT("Recommended queue creation was suppressed because %s is reinforcing narrowed continuation before broader recommendation work resumes (recommended %.1f vs follow-up %.1f, deferredFirstHistory=%d)."), + *DeferredFirstHistorySourceLabel, RecommendedRetentionScore, FollowUpPressureScore, CoachMemorySnapshot.DeferredFirstFollowUpPacketHistoryCount @@ -1458,18 +1481,22 @@ FHyperTwistCoachBrief UHyperTwistTrainingCoachLibrary::DeriveCoachFollowUpBrief( || OutcomeSummary.RecognitionAttemptCount > 0; const bool bHasDeferredLaunchCases = OutcomeSummary.DeferredLaunchCaseIds.Num() > 0; const bool bHasLaunchedFollowUpCases = OutcomeSummary.FollowUpCaseIds.Num() > 0; - const bool bDeferredOverflowContinuationSource = + const bool bNarrowedContinuationSource = HyperTwistTrainingCoachLibraryInternal::IsDeferredOverflowDashboardHandoffSource( ActionPlan.PreferredCoachHandoffSourceLabel ); - const FString DeferredOverflowSourceLabel = - bDeferredOverflowContinuationSource + const bool bDeferredFirstContinuationSource = + HyperTwistTrainingCoachLibraryInternal::IsDeferredFirstContinuationSource( + ActionPlan.PreferredCoachHandoffSourceLabel + ); + const FString NarrowedContinuationSourceLabel = + bNarrowedContinuationSource ? HyperTwistTrainingCoachLibraryInternal::DescribeCoachMemorySourceLabel( ActionPlan.PreferredCoachHandoffSourceLabel ) : TEXT("none"); const bool bPrioritizeDeferredLaunchCasesInFollowUpPacket = - bDeferredOverflowContinuationSource && bHasDeferredLaunchCases; + bNarrowedContinuationSource && bHasDeferredLaunchCases; Brief.DeferredLaunchCaseCount = OutcomeSummary.DeferredLaunchCaseIds.Num(); Brief.bNeedsDeferredLaunchRecovery = bHasDeferredLaunchCases; Brief.bHasTightenedLaunchOverflow = @@ -1541,32 +1568,44 @@ FHyperTwistCoachBrief UHyperTwistTrainingCoachLibrary::DeriveCoachFollowUpBrief( switch (ActionPlan.PreferredCoachHandoffKind) { case EHyperTwistTrainingCoachHandoffKind::Queue: - Brief.Headline = bDeferredOverflowContinuationSource - ? TEXT("Resume the narrowed queued coach slice before broadening again") - : TEXT("Resume the deferred coach slice excluded by the tighter launch budget"); - Brief.PrimaryActionLabel = bDeferredOverflowContinuationSource - ? TEXT("resume_narrowed_queue_slice") - : TEXT("resume_deferred_launch_slice"); + Brief.Headline = bDeferredFirstContinuationSource + ? TEXT("Resume the deferred-first queued coach slice before broadening again") + : (bNarrowedContinuationSource + ? TEXT("Resume the narrowed queued coach slice before broadening again") + : TEXT("Resume the deferred coach slice excluded by the tighter launch budget")); + Brief.PrimaryActionLabel = bDeferredFirstContinuationSource + ? TEXT("resume_deferred_first_queue_slice") + : (bNarrowedContinuationSource + ? TEXT("resume_narrowed_queue_slice") + : TEXT("resume_deferred_launch_slice")); break; case EHyperTwistTrainingCoachHandoffKind::Recommended: - Brief.Headline = bDeferredOverflowContinuationSource - ? TEXT("Restore the narrowed recommended coach slice before broadening again") - : TEXT("Resume the deferred coach slice excluded by the tighter launch budget"); - Brief.PrimaryActionLabel = bDeferredOverflowContinuationSource - ? TEXT("restore_narrowed_recommended_slice") - : TEXT("resume_deferred_launch_slice"); + Brief.Headline = bDeferredFirstContinuationSource + ? TEXT("Restore the deferred-first recommended coach slice before broadening again") + : (bNarrowedContinuationSource + ? TEXT("Restore the narrowed recommended coach slice before broadening again") + : TEXT("Resume the deferred coach slice excluded by the tighter launch budget")); + Brief.PrimaryActionLabel = bDeferredFirstContinuationSource + ? TEXT("restore_deferred_first_recommended_slice") + : (bNarrowedContinuationSource + ? TEXT("restore_narrowed_recommended_slice") + : TEXT("resume_deferred_launch_slice")); break; case EHyperTwistTrainingCoachHandoffKind::FollowUp: default: - Brief.Headline = bDeferredOverflowContinuationSource - ? TEXT("Continue the narrowed follow-up coach slice before broadening again") - : TEXT("Resume the deferred coach slice excluded by the tighter launch budget"); - Brief.PrimaryActionLabel = bDeferredOverflowContinuationSource - ? TEXT("continue_narrowed_follow_up_slice") - : TEXT("resume_deferred_launch_slice"); + Brief.Headline = bDeferredFirstContinuationSource + ? TEXT("Continue the deferred-first follow-up coach slice before broadening again") + : (bNarrowedContinuationSource + ? TEXT("Continue the narrowed follow-up coach slice before broadening again") + : TEXT("Resume the deferred coach slice excluded by the tighter launch budget")); + Brief.PrimaryActionLabel = bDeferredFirstContinuationSource + ? TEXT("continue_deferred_first_follow_up_slice") + : (bNarrowedContinuationSource + ? TEXT("continue_narrowed_follow_up_slice") + : TEXT("resume_deferred_launch_slice")); break; } - Brief.SuggestedMode = bDeferredOverflowContinuationSource + Brief.SuggestedMode = bNarrowedContinuationSource ? (Brief.bPreferRecognitionReplayReview ? EHyperTwistTrainingDeliveryMode::RecognitionAssisted : EHyperTwistTrainingDeliveryMode::CoachReviewed) @@ -1611,12 +1650,12 @@ FHyperTwistCoachBrief UHyperTwistTrainingCoachLibrary::DeriveCoachFollowUpBrief( *Brief.Headline ); } - if (bDeferredOverflowContinuationSource && bHasDeferredLaunchCases) + if (bNarrowedContinuationSource && bHasDeferredLaunchCases) { Brief.Headline = FString::Printf( TEXT("%s (%s)"), *Brief.Headline, - *DeferredOverflowSourceLabel + *NarrowedContinuationSourceLabel ); } @@ -1626,7 +1665,7 @@ FHyperTwistCoachBrief UHyperTwistTrainingCoachLibrary::DeriveCoachFollowUpBrief( Brief.PriorityScore, Brief.Headline, FString::Printf( - TEXT("followUpCases=%d, deferredLaunchCases=%d, success=%d, failure=%d, timeout=%d, dnf=%d, launchBudget=%s, plannedLaunchCases=%d, requestedLaunchCases=%d, launchBudgetReason=%s, preferredHandoff=%s, preferredHandoffSource=%s, deferredOverflowContinuation=%d, deferredPacketOrdering=%s"), + TEXT("followUpCases=%d, deferredLaunchCases=%d, success=%d, failure=%d, timeout=%d, dnf=%d, launchBudget=%s, plannedLaunchCases=%d, requestedLaunchCases=%d, launchBudgetReason=%s, preferredHandoff=%s, preferredHandoffSource=%s, narrowedContinuation=%d, deferredFirstContinuation=%d, deferredPacketOrdering=%s"), Brief.FocusCaseIds.Num(), OutcomeSummary.DeferredLaunchCaseIds.Num(), OutcomeSummary.SuccessCount, @@ -1644,8 +1683,9 @@ FHyperTwistCoachBrief UHyperTwistTrainingCoachLibrary::DeriveCoachFollowUpBrief( *HyperTwistTrainingCoachLibraryInternal::DescribeCoachHandoffKind( ActionPlan.PreferredCoachHandoffKind ), - *DeferredOverflowSourceLabel, - bDeferredOverflowContinuationSource ? 1 : 0, + *NarrowedContinuationSourceLabel, + bNarrowedContinuationSource ? 1 : 0, + bDeferredFirstContinuationSource ? 1 : 0, bPrioritizeDeferredLaunchCasesInFollowUpPacket ? TEXT("deferred-first") : TEXT("default")), @@ -1749,34 +1789,44 @@ FHyperTwistCoachSessionQueueSummary UHyperTwistTrainingCoachLibrary::DeriveCoach Entry.FocusCaseIds = Brief.FocusCaseIds; Entry.bRequiresFollowUp = bRequiresFollowUp; Entry.bRequiresArchiveRetentionTuning = bRequiresArchiveRetentionTuning; - const bool bDeferredOverflowContinuationPreferred = + const bool bNarrowedContinuationPreferred = HyperTwistTrainingCoachLibraryInternal::IsDeferredOverflowDashboardHandoffSource( CoachMemorySnapshot.PreferredCoachHandoffSourceLabel ); - const bool bDeferredOverflowQueueContinuation = - bDeferredOverflowContinuationPreferred + const bool bDeferredFirstContinuationPreferred = + HyperTwistTrainingCoachLibraryInternal::IsDeferredFirstContinuationSource( + CoachMemorySnapshot.PreferredCoachHandoffSourceLabel + ); + const bool bNarrowedQueueContinuation = + bNarrowedContinuationPreferred && CoachMemorySnapshot.PreferredCoachHandoffKind == EHyperTwistTrainingCoachHandoffKind::Queue && Brief.bNeedsDeferredLaunchRecovery; - const bool bDeferredOverflowFollowUpContinuation = - bDeferredOverflowContinuationPreferred + const bool bNarrowedFollowUpContinuation = + bNarrowedContinuationPreferred && CoachMemorySnapshot.PreferredCoachHandoffKind == EHyperTwistTrainingCoachHandoffKind::FollowUp && SourceLabel == TEXT("follow-up-brief"); - const bool bDeferredOverflowRecommendedContinuation = - bDeferredOverflowContinuationPreferred + const bool bNarrowedRecommendedContinuation = + bNarrowedContinuationPreferred && CoachMemorySnapshot.PreferredCoachHandoffKind == EHyperTwistTrainingCoachHandoffKind::Recommended && SourceLabel == TEXT("primary-brief"); - if (bDeferredOverflowQueueContinuation - || bDeferredOverflowFollowUpContinuation - || bDeferredOverflowRecommendedContinuation) + if (bNarrowedQueueContinuation + || bNarrowedFollowUpContinuation + || bNarrowedRecommendedContinuation) { - const FString ContinuationLabel = bDeferredOverflowQueueContinuation - ? TEXT("queue-first narrowed continuation") - : (bDeferredOverflowFollowUpContinuation - ? TEXT("narrowed follow-up continuation") - : TEXT("narrowed recommended continuation")); + const FString ContinuationLabel = bNarrowedQueueContinuation + ? (bDeferredFirstContinuationPreferred + ? TEXT("queue-first deferred-first continuation") + : TEXT("queue-first narrowed continuation")) + : (bNarrowedFollowUpContinuation + ? (bDeferredFirstContinuationPreferred + ? TEXT("deferred-first narrowed follow-up continuation") + : TEXT("narrowed follow-up continuation")) + : (bDeferredFirstContinuationPreferred + ? TEXT("deferred-first narrowed recommended continuation") + : TEXT("narrowed recommended continuation"))); Entry.Headline = FString::Printf( TEXT("%s (%s)"), *Entry.Headline, @@ -1965,27 +2015,34 @@ FHyperTwistCoachSignal UHyperTwistTrainingCoachLibrary::DeriveQueueSuppressionSi const bool bLaunchRecovery = CoachMemorySnapshot.PreferredQueueRecoveryAction == EHyperTwistTrainingQueueRecoveryAction::LaunchRecovery; - const bool bDeferredFirstFollowUpSource = - CoachMemorySnapshot.PreferredGuidanceSourceLabel - == TEXT("recommendation-history-deferred-first-follow-up") - || CoachMemorySnapshot.PreferredCoachHandoffSourceLabel - == TEXT("recommendation-history-deferred-first-follow-up"); + const FString DeferredFirstContinuationSourceLabel = + HyperTwistTrainingCoachLibraryInternal::IsDeferredFirstContinuationSource( + CoachMemorySnapshot.PreferredCoachHandoffSourceLabel + ) + ? CoachMemorySnapshot.PreferredCoachHandoffSourceLabel + : (HyperTwistTrainingCoachLibraryInternal::IsDeferredFirstContinuationSource( + CoachMemorySnapshot.PreferredGuidanceSourceLabel + ) + ? CoachMemorySnapshot.PreferredGuidanceSourceLabel + : FString()); + const bool bDeferredFirstContinuationSource = + !DeferredFirstContinuationSourceLabel.IsEmpty(); const bool bFollowUpPreferred = CoachMemorySnapshot.PreferredGuidanceLane == EHyperTwistTrainingCoachGuidanceLane::FollowUp; const bool bRecommendedPreferred = CoachMemorySnapshot.PreferredGuidanceLane == EHyperTwistTrainingCoachGuidanceLane::Recommended; const FString SignalId = - bDeferredFirstFollowUpSource && bSuppressedPrimaryQueueCreation - ? TEXT("queue_suppression_deferred_first_follow_up") + bDeferredFirstContinuationSource && bSuppressedPrimaryQueueCreation + ? TEXT("queue_suppression_deferred_first_continuation") : (bSuppressedPrimaryQueueCreation && bSuppressedFollowUpQueueCreation ? TEXT("queue_suppression_competing_guidance") : (bSuppressedPrimaryQueueCreation ? TEXT("queue_suppression_recommended") : TEXT("queue_suppression_follow_up"))); const FString Headline = - bDeferredFirstFollowUpSource && bSuppressedPrimaryQueueCreation - ? TEXT("Keep the narrowed follow-up slice ahead of broader recommendation work") + bDeferredFirstContinuationSource && bSuppressedPrimaryQueueCreation + ? TEXT("Keep the narrowed continuation slice ahead of broader recommendation work") : (bSuppressedPrimaryQueueCreation && bSuppressedFollowUpQueueCreation ? TEXT("Queue recovery is suppressing competing guidance lanes") : (bSuppressedPrimaryQueueCreation @@ -1996,9 +2053,9 @@ FHyperTwistCoachSignal UHyperTwistTrainingCoachLibrary::DeriveQueueSuppressionSi ? TEXT("Keep recommended recovery primary while follow-up queue regeneration stays suppressed") : TEXT("Recommended recovery remains primary while follow-up queue work is intentionally held back")))); const FString DeferredFirstSourceLabel = - bDeferredFirstFollowUpSource + bDeferredFirstContinuationSource ? HyperTwistTrainingCoachLibraryInternal::DescribeCoachMemorySourceLabel( - TEXT("recommendation-history-deferred-first-follow-up") + DeferredFirstContinuationSourceLabel ) : TEXT("n/a"); const FString Detail = FString::Printf( @@ -2026,7 +2083,7 @@ FHyperTwistCoachSignal UHyperTwistTrainingCoachLibrary::DeriveQueueSuppressionSi + (CoachMemorySnapshot.bHasBlockedFollowUpScheduleFriction ? 6.0f : 0.0f) + (CoachMemorySnapshot.bHasOutstandingDeferredScheduleWork ? 4.0f : 0.0f) + (bSuppressedPrimaryQueueCreation && bSuppressedFollowUpQueueCreation ? 5.0f : 0.0f) - + (bDeferredFirstFollowUpSource ? 4.0f : 0.0f) + + (bDeferredFirstContinuationSource ? 4.0f : 0.0f) + (bPromoteDeferredRecovery ? 2.0f : 0.0f); const EHyperTwistCoachFocusLane FocusLane = CoachMemorySnapshot.bHasArchiveAwareScheduleFriction