Bias coach queue by drill follow-up memory

This commit is contained in:
axiomlogicnexus 2026-04-29 03:08:17 +02:00
parent 6d02a2a3fc
commit 9d7d0f52d5

View file

@ -301,6 +301,111 @@ namespace HyperTwistTrainingCoachLibraryInternal
);
}
float ResolveMethodDrillFollowUpContinuationPressure(
const FHyperTwistTrainingCoachMemorySnapshot& CoachMemorySnapshot)
{
const bool bPreferredGuidanceSource =
CoachMemorySnapshot.PreferredGuidanceSourceLabel
== TEXT("coach-memory-method-drill-follow-up-strong");
const bool bPreferredHandoffSource =
CoachMemorySnapshot.PreferredCoachHandoffSourceLabel
== TEXT("coach-memory-method-drill-follow-up-strong");
if (CoachMemorySnapshot.MethodDrillFollowUpHistoryCount <= 0
&& !bPreferredGuidanceSource
&& !bPreferredHandoffSource)
{
return 0.0f;
}
const bool bStrongHistoryDominant =
CoachMemorySnapshot.StrongMethodDrillFollowUpHistoryCount
>= CoachMemorySnapshot.WeakMethodDrillFollowUpHistoryCount
&& CoachMemorySnapshot.MethodDrillFollowUpAverageOutcomeScore >= 60.0f;
if (!bStrongHistoryDominant && !bPreferredGuidanceSource && !bPreferredHandoffSource)
{
return 0.0f;
}
return FMath::Clamp(
(static_cast<float>(CoachMemorySnapshot.StrongMethodDrillFollowUpHistoryCount) * 1.25f)
+ (static_cast<float>(CoachMemorySnapshot.MethodDrillFollowUpHistoryCount) * 0.35f)
+ (bPreferredGuidanceSource ? 2.0f : 0.0f)
+ (bPreferredHandoffSource ? 2.0f : 0.0f),
0.0f,
8.0f
);
}
float ResolveMethodDrillFollowUpRedirectPressure(
const FHyperTwistTrainingCoachMemorySnapshot& CoachMemorySnapshot)
{
const bool bPreferredGuidanceSource =
CoachMemorySnapshot.PreferredGuidanceSourceLabel
== TEXT("coach-memory-method-drill-follow-up-weak");
const bool bPreferredHandoffSource =
CoachMemorySnapshot.PreferredCoachHandoffSourceLabel
== TEXT("coach-memory-method-drill-follow-up-weak");
if (CoachMemorySnapshot.MethodDrillFollowUpHistoryCount <= 0
&& !bPreferredGuidanceSource
&& !bPreferredHandoffSource)
{
return 0.0f;
}
const bool bWeakHistoryDominant =
CoachMemorySnapshot.WeakMethodDrillFollowUpHistoryCount
> CoachMemorySnapshot.StrongMethodDrillFollowUpHistoryCount
&& CoachMemorySnapshot.MethodDrillFollowUpAverageOutcomeScore <= 55.0f;
if (!bWeakHistoryDominant && !bPreferredGuidanceSource && !bPreferredHandoffSource)
{
return 0.0f;
}
return FMath::Clamp(
(static_cast<float>(CoachMemorySnapshot.WeakMethodDrillFollowUpHistoryCount) * 1.5f)
+ (static_cast<float>(CoachMemorySnapshot.MethodDrillFollowUpHistoryCount) * 0.25f)
+ (bPreferredGuidanceSource ? 2.0f : 0.0f)
+ (bPreferredHandoffSource ? 2.0f : 0.0f),
0.0f,
8.0f
);
}
float ResolveMethodDrillFollowUpQueueBias(
const FString& SourceLabel,
const FHyperTwistTrainingCoachMemorySnapshot& CoachMemorySnapshot,
const bool bHasCompetingGuidanceEntry)
{
const float ContinuationPressure =
ResolveMethodDrillFollowUpContinuationPressure(CoachMemorySnapshot);
const float RedirectPressure =
ResolveMethodDrillFollowUpRedirectPressure(CoachMemorySnapshot);
if (FMath::IsNearlyZero(ContinuationPressure)
&& FMath::IsNearlyZero(RedirectPressure))
{
return 0.0f;
}
if (SourceLabel == TEXT("follow-up-brief"))
{
return FMath::Clamp(
ContinuationPressure - (RedirectPressure * 0.75f),
-5.0f,
6.0f
);
}
if (SourceLabel == TEXT("primary-brief") && bHasCompetingGuidanceEntry)
{
return FMath::Clamp(
RedirectPressure - (ContinuationPressure * 0.55f),
-4.0f,
5.0f
);
}
return 0.0f;
}
float ResolvePreferredGuidanceQueueBias(
const FString& SourceLabel,
const FHyperTwistTrainingCoachMemorySnapshot& CoachMemorySnapshot,
@ -556,6 +661,10 @@ namespace HyperTwistTrainingCoachLibraryInternal
)
: TEXT("successful deferred-first continuation history"));
const bool bDeferredFirstFollowUpHistoryPreferred = DeferredFirstPacketPressure > 0.0f;
const float MethodDrillContinuationPressure =
ResolveMethodDrillFollowUpContinuationPressure(CoachMemorySnapshot);
const float MethodDrillRedirectPressure =
ResolveMethodDrillFollowUpRedirectPressure(CoachMemorySnapshot);
const bool bScheduleRecoveryPrefersFollowUp =
CoachMemorySnapshot.bNeedsScheduleFrictionRecovery
&& CoachMemorySnapshot.PreferredQueueRecoveryAction
@ -563,7 +672,9 @@ namespace HyperTwistTrainingCoachLibraryInternal
&& CoachMemorySnapshot.PreferredGuidanceLane == EHyperTwistTrainingCoachGuidanceLane::FollowUp;
if (!bScheduleRecoveryPrefersFollowUp
&& !bNeedsDeferredLaunchCompetition
&& !bDeferredFirstFollowUpHistoryPreferred)
&& !bDeferredFirstFollowUpHistoryPreferred
&& FMath::IsNearlyZero(MethodDrillContinuationPressure)
&& FMath::IsNearlyZero(MethodDrillRedirectPressure))
{
return true;
}
@ -571,14 +682,16 @@ namespace HyperTwistTrainingCoachLibraryInternal
const float DeferredLaunchPressure = ResolveDeferredLaunchRecoveryPressure(FollowUpBrief);
const float RecommendedRetentionScore =
CurrentBrief.PriorityScore
+ static_cast<float>(CoachMemorySnapshot.RecommendedGuidanceContinueBias);
+ static_cast<float>(CoachMemorySnapshot.RecommendedGuidanceContinueBias)
+ (MethodDrillRedirectPressure * 1.5f);
const float FollowUpPressureScore =
FollowUpBrief.PriorityScore
+ static_cast<float>(CoachMemorySnapshot.FollowUpGuidanceContinueBias)
+ (static_cast<float>(CoachMemorySnapshot.SuppressedPrimaryQueuePressureCount) * 2.0f)
+ (FollowUpBrief.bNeedsCoachReview ? 8.0f : 0.0f)
+ DeferredLaunchPressure
+ DeferredFirstPacketPressure;
+ DeferredFirstPacketPressure
+ (MethodDrillContinuationPressure * 1.5f);
const float RecommendedRetentionThreshold =
bDeferredFirstFollowUpHistoryPreferred ? 10.0f : 8.0f;
const bool bShouldCreate =
@ -615,6 +728,16 @@ namespace HyperTwistTrainingCoachLibraryInternal
CoachMemorySnapshot.DeferredFirstFollowUpPacketHistoryCount
);
}
else if (MethodDrillContinuationPressure > MethodDrillRedirectPressure)
{
*OutSuppressionReason = FString::Printf(
TEXT("Recommended queue creation was suppressed because successful method-drill follow-up history is reinforcing narrow continuation before broader recommendation work resumes (recommended %.1f vs follow-up %.1f, drillHistory=%d, avgDrillOutcome=%.1f)."),
RecommendedRetentionScore,
FollowUpPressureScore,
CoachMemorySnapshot.MethodDrillFollowUpHistoryCount,
CoachMemorySnapshot.MethodDrillFollowUpAverageOutcomeScore
);
}
else
{
*OutSuppressionReason = FString::Printf(
@ -645,10 +768,17 @@ namespace HyperTwistTrainingCoachLibraryInternal
{
return true;
}
if (!CoachMemorySnapshot.bNeedsScheduleFrictionRecovery
|| CoachMemorySnapshot.PreferredQueueRecoveryAction
!= EHyperTwistTrainingQueueRecoveryAction::LaunchRecovery
|| CoachMemorySnapshot.PreferredGuidanceLane != EHyperTwistTrainingCoachGuidanceLane::Recommended)
const float MethodDrillContinuationPressure =
ResolveMethodDrillFollowUpContinuationPressure(CoachMemorySnapshot);
const float MethodDrillRedirectPressure =
ResolveMethodDrillFollowUpRedirectPressure(CoachMemorySnapshot);
const bool bRecommendedLaunchRecoveryGate =
CoachMemorySnapshot.bNeedsScheduleFrictionRecovery
&& CoachMemorySnapshot.PreferredQueueRecoveryAction
== EHyperTwistTrainingQueueRecoveryAction::LaunchRecovery
&& CoachMemorySnapshot.PreferredGuidanceLane
== EHyperTwistTrainingCoachGuidanceLane::Recommended;
if (!bRecommendedLaunchRecoveryGate && FMath::IsNearlyZero(MethodDrillRedirectPressure))
{
return true;
}
@ -661,18 +791,33 @@ namespace HyperTwistTrainingCoachLibraryInternal
CurrentBrief.PriorityScore
+ static_cast<float>(CoachMemorySnapshot.RecommendedGuidanceContinueBias)
+ (static_cast<float>(CoachMemorySnapshot.SuppressedFollowUpQueuePressureCount) * 2.0f)
+ (CoachMemorySnapshot.bHasRepeatRecommendationPressure ? 4.0f : 0.0f);
+ (CoachMemorySnapshot.bHasRepeatRecommendationPressure ? 4.0f : 0.0f)
+ (MethodDrillRedirectPressure * 1.5f);
const float FollowUpRetentionScore =
FollowUpBrief.PriorityScore
+ static_cast<float>(CoachMemorySnapshot.FollowUpGuidanceContinueBias);
+ static_cast<float>(CoachMemorySnapshot.FollowUpGuidanceContinueBias)
+ (MethodDrillContinuationPressure * 1.25f);
const bool bShouldCreate = FollowUpRetentionScore >= RecommendedPressureScore + 8.0f;
if (!bShouldCreate && OutSuppressionReason != nullptr)
{
*OutSuppressionReason = FString::Printf(
TEXT("Follow-up queue creation was suppressed because recommended-lane launch recovery is preferred (follow-up %.1f vs recommended %.1f)."),
FollowUpRetentionScore,
RecommendedPressureScore
);
if (MethodDrillRedirectPressure > MethodDrillContinuationPressure)
{
*OutSuppressionReason = FString::Printf(
TEXT("Follow-up queue creation was suppressed because weak method-drill follow-up history is pushing control back toward broader recommended work (follow-up %.1f vs recommended %.1f, drillHistory=%d, avgDrillOutcome=%.1f)."),
FollowUpRetentionScore,
RecommendedPressureScore,
CoachMemorySnapshot.MethodDrillFollowUpHistoryCount,
CoachMemorySnapshot.MethodDrillFollowUpAverageOutcomeScore
);
}
else
{
*OutSuppressionReason = FString::Printf(
TEXT("Follow-up queue creation was suppressed because recommended-lane launch recovery is preferred (follow-up %.1f vs recommended %.1f)."),
FollowUpRetentionScore,
RecommendedPressureScore
);
}
}
return bShouldCreate;
}
@ -1896,12 +2041,19 @@ FHyperTwistCoachSessionQueueSummary UHyperTwistTrainingCoachLibrary::DeriveCoach
bHasCompetingGuidanceEntry,
bHasArchiveEntry
);
const float MethodDrillQueueBias =
HyperTwistTrainingCoachLibraryInternal::ResolveMethodDrillFollowUpQueueBias(
SourceLabel,
CoachMemorySnapshot,
bHasCompetingGuidanceEntry
);
Entry.PriorityScore = FMath::Clamp(
Entry.PriorityScore
+ GuidanceBias
+ ArchiveCompetitionBias
+ RecoveryActionBias
+ DeferredLaunchBias,
+ DeferredLaunchBias
+ MethodDrillQueueBias,
0.0f,
100.0f
);