Persist launch budget learning upstream

This commit is contained in:
axiomlogicnexus 2026-04-27 23:45:54 +02:00
parent b04acb7248
commit 377b57954d
5 changed files with 258 additions and 12 deletions

View file

@ -1279,7 +1279,10 @@ FHyperTwistTrainingCoachActionPlan UHyperTwistContractLibrary::MakeSampleTrainin
MakeSampleTrainingCoachBrief(),
MakeSampleTrainingCoachMemorySnapshot(),
TEXT("coach_plan_training_session_01"),
TEXT("2026-04-28T12:05:00Z")
TEXT("2026-04-28T12:05:00Z"),
0,
0,
FString()
);
}
@ -1317,7 +1320,10 @@ FHyperTwistTrainingCoachActionSequenceSummary UHyperTwistContractLibrary::MakeSa
FollowUpBrief,
MakeSampleTrainingCoachMemorySnapshot(),
TEXT("coach_follow_up_training_session_02"),
TEXT("2026-04-28T12:20:00Z")
TEXT("2026-04-28T12:20:00Z"),
0,
0,
FString()
);
if (FollowUpPlan.IsStructurallyValid())
{
@ -1349,7 +1355,10 @@ FHyperTwistTrainingCoachActionClosureSummary UHyperTwistContractLibrary::MakeSam
FollowUpBrief,
MakeSampleTrainingCoachMemorySnapshot(),
TEXT("coach_follow_up_training_session_02"),
TEXT("2026-04-28T12:20:00Z")
TEXT("2026-04-28T12:20:00Z"),
0,
0,
FString()
);
if (FollowUpPlan.IsStructurallyValid())
{
@ -1401,7 +1410,10 @@ FHyperTwistTrainingCoachRecommendationHistorySummary UHyperTwistContractLibrary:
FollowUpBrief,
MakeSampleTrainingCoachMemorySnapshot(),
TEXT("coach_follow_up_training_session_02"),
TEXT("2026-04-28T12:20:00Z")
TEXT("2026-04-28T12:20:00Z"),
0,
0,
FString()
);
if (FollowUpPlan.IsStructurallyValid())
{
@ -1433,7 +1445,10 @@ FHyperTwistTrainingCoachCarryForwardPolicySummary UHyperTwistContractLibrary::Ma
FollowUpBrief,
MakeSampleTrainingCoachMemorySnapshot(),
TEXT("coach_follow_up_training_session_02"),
TEXT("2026-04-28T12:20:00Z")
TEXT("2026-04-28T12:20:00Z"),
0,
0,
FString()
);
if (FollowUpPlan.IsStructurallyValid())
{
@ -1465,7 +1480,10 @@ FHyperTwistTrainingCoachArchivePolicySummary UHyperTwistContractLibrary::MakeSam
FollowUpBrief,
MakeSampleTrainingCoachMemorySnapshot(),
TEXT("coach_follow_up_training_session_02"),
TEXT("2026-04-28T12:20:00Z")
TEXT("2026-04-28T12:20:00Z"),
0,
0,
FString()
);
if (FollowUpPlan.IsStructurallyValid())
{

View file

@ -546,6 +546,18 @@ namespace HyperTwistTrainingRepositoryLibraryInternal
}
}
bool ContainsLaunchBudgetBroadeningHint(const FString& ReasonLine)
{
return ReasonLine.Contains(TEXT("broaden"), ESearchCase::IgnoreCase)
|| ReasonLine.Contains(TEXT("widen"), ESearchCase::IgnoreCase);
}
bool ContainsLaunchBudgetTighteningHint(const FString& ReasonLine)
{
return ReasonLine.Contains(TEXT("tight"), ESearchCase::IgnoreCase)
|| ReasonLine.Contains(TEXT("narrow"), ESearchCase::IgnoreCase);
}
EHyperTwistTrainingCoachGuidanceLane GuidanceLaneFromQueueSourceLabel(const FString& SourceLabel)
{
if (SourceLabel == TEXT("follow-up-brief"))
@ -5305,7 +5317,23 @@ FHyperTwistTrainingCoachMemorySnapshot UHyperTwistTrainingRepositoryLibrary::Der
Snapshot.FollowUpGuidancePlanCount = RecommendationHistory.FollowUpLanePlanCount;
Snapshot.RecommendedGuidanceContinueBias = RecommendationHistory.RecommendedLaneContinueBias;
Snapshot.FollowUpGuidanceContinueBias = RecommendationHistory.FollowUpLaneContinueBias;
Snapshot.BroadenedLaunchBudgetHistoryCount = RecommendationHistory.BroadenedLaunchPlanCount;
Snapshot.TightenedLaunchBudgetHistoryCount = RecommendationHistory.TightenedLaunchPlanCount;
Snapshot.bHasRepeatRecommendationPressure = RecommendationHistory.bHasRepeatRecommendationPressure;
if (RecommendationHistory.BroadenedLaunchPlanCount >= 2
&& RecommendationHistory.BroadenedLaunchAverageOutcomeScore
>= RecommendationHistory.TightenedLaunchAverageOutcomeScore + 5.0f)
{
Snapshot.PreferredLaunchBudgetBias = 1;
Snapshot.PreferredLaunchBudgetSourceLabel = TEXT("recommendation-history-broadened-launch");
}
else if (RecommendationHistory.TightenedLaunchPlanCount >= 2
&& RecommendationHistory.TightenedLaunchAverageOutcomeScore
>= RecommendationHistory.BroadenedLaunchAverageOutcomeScore + 5.0f)
{
Snapshot.PreferredLaunchBudgetBias = -1;
Snapshot.PreferredLaunchBudgetSourceLabel = TEXT("recommendation-history-tightened-launch");
}
if (!RecommendationHistory.FocusDeckId.IsEmpty()
&& (Snapshot.FocusDeckId.IsEmpty()
@ -6513,7 +6541,10 @@ FHyperTwistTrainingCoachActionPlan UHyperTwistTrainingRepositoryLibrary::BuildCo
const FHyperTwistCoachBrief& CoachBrief,
const FHyperTwistTrainingCoachMemorySnapshot& CoachMemorySnapshot,
const FString& PlanId,
const FString& ReferenceUtc
const FString& ReferenceUtc,
const int32 RequestedLaunchCaseCount,
const int32 PlannedLaunchCaseCount,
const FString& LaunchBudgetReasonLine
)
{
FHyperTwistTrainingCoachActionPlan ActionPlan;
@ -6556,6 +6587,21 @@ FHyperTwistTrainingCoachActionPlan UHyperTwistTrainingRepositoryLibrary::BuildCo
ActionPlan.PreferredGuidanceSourceLabel = CoachMemorySnapshot.PreferredGuidanceSourceLabel;
ActionPlan.PreferredCoachHandoffKind = CoachMemorySnapshot.PreferredCoachHandoffKind;
ActionPlan.PreferredCoachHandoffSourceLabel = CoachMemorySnapshot.PreferredCoachHandoffSourceLabel;
ActionPlan.RequestedLaunchCaseCount = RequestedLaunchCaseCount > 0
? RequestedLaunchCaseCount
: FMath::Max(1, CoachBrief.FocusCaseIds.Num());
ActionPlan.PlannedLaunchCaseCount = PlannedLaunchCaseCount > 0
? PlannedLaunchCaseCount
: ActionPlan.RequestedLaunchCaseCount;
ActionPlan.LaunchBudgetReasonLine = LaunchBudgetReasonLine;
ActionPlan.bBroadenedLaunchBudget =
ActionPlan.PlannedLaunchCaseCount > ActionPlan.RequestedLaunchCaseCount
|| HyperTwistTrainingRepositoryLibraryInternal::ContainsLaunchBudgetBroadeningHint(
ActionPlan.LaunchBudgetReasonLine);
ActionPlan.bTightenedLaunchBudget =
ActionPlan.PlannedLaunchCaseCount < ActionPlan.RequestedLaunchCaseCount
|| HyperTwistTrainingRepositoryLibraryInternal::ContainsLaunchBudgetTighteningHint(
ActionPlan.LaunchBudgetReasonLine);
ActionPlan.FocusCaseIds = CoachBrief.FocusCaseIds;
ActionPlan.PlanState = EHyperTwistTrainingCoachActionPlanState::Draft;
ActionPlan.FollowUpDepth = FMath::Max(0, CoachBrief.FollowUpDepth);
@ -7796,6 +7842,11 @@ FHyperTwistTrainingCoachActionPlanOutcomeSummary UHyperTwistTrainingRepositoryLi
Summary.SuggestedMode = NormalizedPlan.SuggestedMode;
Summary.PreferredCoachHandoffKind = NormalizedPlan.PreferredCoachHandoffKind;
Summary.PreferredCoachHandoffSourceLabel = NormalizedPlan.PreferredCoachHandoffSourceLabel;
Summary.RequestedLaunchCaseCount = NormalizedPlan.RequestedLaunchCaseCount;
Summary.PlannedLaunchCaseCount = NormalizedPlan.PlannedLaunchCaseCount;
Summary.bBroadenedLaunchBudget = NormalizedPlan.bBroadenedLaunchBudget;
Summary.bTightenedLaunchBudget = NormalizedPlan.bTightenedLaunchBudget;
Summary.LaunchBudgetReasonLine = NormalizedPlan.LaunchBudgetReasonLine;
TSet<FString> FocusCaseIds;
for (const FString& FocusCaseId : NormalizedPlan.FocusCaseIds)
@ -8591,6 +8642,10 @@ FHyperTwistTrainingCoachRecommendationHistorySummary UHyperTwistTrainingReposito
TMap<EHyperTwistTrainingSelectionPolicy, int32> PolicyCountMap;
TMap<FString, int32> RecommendedCaseCounts;
float FollowUpDepthAccumulator = 0.0f;
float PlannedLaunchCaseCountAccumulator = 0.0f;
int32 PlannedLaunchSampleCount = 0;
float BroadenedLaunchOutcomeAccumulator = 0.0f;
float TightenedLaunchOutcomeAccumulator = 0.0f;
FString LatestPlanSortUtc;
for (const FHyperTwistTrainingCoachActionPlan& Plan : UserPlans)
@ -8747,6 +8802,12 @@ FHyperTwistTrainingCoachRecommendationHistorySummary UHyperTwistTrainingReposito
for (const TPair<FString, FHyperTwistTrainingCoachActionPlan>& Pair : LatestPlanByRootId)
{
const FHyperTwistTrainingCoachActionPlanOutcomeSummary OutcomeSummary =
UHyperTwistTrainingRepositoryLibrary::DeriveCoachActionPlanOutcomeSummary(
RepositoryState,
Pair.Value,
Summary.ReferenceUtc
);
const FHyperTwistTrainingCoachActionClosureSummary ClosureSummary =
HyperTwistTrainingRepositoryLibraryInternal::DeriveCoachActionClosureSummaryWithCoachMemory(
RepositoryState,
@ -8759,6 +8820,26 @@ FHyperTwistTrainingCoachRecommendationHistorySummary UHyperTwistTrainingReposito
continue;
}
if (OutcomeSummary.IsStructurallyValid())
{
if (OutcomeSummary.PlannedLaunchCaseCount > 0)
{
PlannedLaunchCaseCountAccumulator +=
static_cast<float>(OutcomeSummary.PlannedLaunchCaseCount);
PlannedLaunchSampleCount += 1;
}
if (OutcomeSummary.bBroadenedLaunchBudget)
{
Summary.BroadenedLaunchPlanCount += 1;
BroadenedLaunchOutcomeAccumulator += OutcomeSummary.OutcomeScore;
}
if (OutcomeSummary.bTightenedLaunchBudget)
{
Summary.TightenedLaunchPlanCount += 1;
TightenedLaunchOutcomeAccumulator += OutcomeSummary.OutcomeScore;
}
}
Summary.SequenceCount += 1;
Summary.EscalatedSequenceCount += ClosureSummary.bNeedsEscalation ? 1 : 0;
Summary.FollowUpReadySequenceCount += ClosureSummary.bShouldSpawnFollowUp ? 1 : 0;
@ -8849,6 +8930,21 @@ FHyperTwistTrainingCoachRecommendationHistorySummary UHyperTwistTrainingReposito
Summary.EscalationCaseCount = Summary.EscalationCaseIds.Num();
Summary.AverageClosureScore = ClosureScoreAccumulator / static_cast<float>(Summary.SequenceCount);
Summary.AverageFollowUpDepth = FollowUpDepthAccumulator / static_cast<float>(Summary.PlanCount);
if (PlannedLaunchSampleCount > 0)
{
Summary.AveragePlannedLaunchCaseCount =
PlannedLaunchCaseCountAccumulator / static_cast<float>(PlannedLaunchSampleCount);
}
if (Summary.BroadenedLaunchPlanCount > 0)
{
Summary.BroadenedLaunchAverageOutcomeScore =
BroadenedLaunchOutcomeAccumulator / static_cast<float>(Summary.BroadenedLaunchPlanCount);
}
if (Summary.TightenedLaunchPlanCount > 0)
{
Summary.TightenedLaunchAverageOutcomeScore =
TightenedLaunchOutcomeAccumulator / static_cast<float>(Summary.TightenedLaunchPlanCount);
}
Summary.bHasRepeatRecommendationPressure =
Summary.RepeatRecommendationSequenceCount > 0
&& (Summary.RecurringCaseCount > 0

View file

@ -163,6 +163,26 @@ namespace HyperTwistTrainingSubsystemInternal
BudgetReasons.Add(TEXT("recommended-first handoff is widening recommendation work"));
}
const bool bMatchesPreferredGuidanceLane =
DeckLane != EHyperTwistTrainingCoachGuidanceLane::None
&& DeckLane == CoachMemorySnapshot.PreferredGuidanceLane;
if (CoachMemorySnapshot.PreferredLaunchBudgetBias > 0
&& Result.ResolvedCaseCount <= 4
&& (bMatchesPreferredGuidanceLane || bQueuedLaunch))
{
Result.ResolvedCaseCount += 1;
BudgetReasons.Add(TEXT("successful broadened-launch history is widening the next launch"));
}
else if (CoachMemorySnapshot.PreferredLaunchBudgetBias < 0
&& Result.ResolvedCaseCount > 1
&& (bMatchesPreferredGuidanceLane
|| DeckLane == EHyperTwistTrainingCoachGuidanceLane::FollowUp
|| bQueuedLaunch))
{
Result.ResolvedCaseCount = FMath::Max(1, Result.ResolvedCaseCount - 1);
BudgetReasons.Add(TEXT("successful tightened-launch history is narrowing the next launch"));
}
Result.ResolvedCaseCount = FMath::Max(1, Result.ResolvedCaseCount);
Result.ReasonLine = BudgetReasons.Num() > 0
? FString::Join(BudgetReasons, TEXT("; "))
@ -1538,12 +1558,22 @@ FHyperTwistTrainingRunState UHyperTwistTrainingSubsystem::StartCoachRecommendedR
const FString UserId = ActiveRunState.Session.UserId.IsEmpty() ? TEXT("local-user") : ActiveRunState.Session.UserId;
const FHyperTwistTrainingCoachSessionQueueState QueueStateBeforeStart = ActiveCoachSessionQueueState;
const HyperTwistTrainingSubsystemInternal::FResolvedCoachCaseBudget LaunchBudget =
HyperTwistTrainingSubsystemInternal::ResolvePreferredCoachCaseBudget(
MaxCases,
EHyperTwistTrainingCoachGuidanceLane::Recommended,
ActiveCoachMemorySnapshot,
false
);
const FHyperTwistTrainingCoachActionPlan DraftActionPlan =
UHyperTwistTrainingRepositoryLibrary::BuildCoachActionPlan(
ActiveCoachBrief,
ActiveCoachMemorySnapshot,
FString::Printf(TEXT("coach_plan_%s"), *SessionId),
FString()
FString(),
LaunchBudget.RequestedCaseCount,
CoachDeck.Cases.Num(),
LaunchBudget.ReasonLine
);
FHyperTwistTrainingRunState RunState = StartTrainingRunFromDeck(
CoachDeck,
@ -1602,12 +1632,22 @@ FHyperTwistTrainingRunState UHyperTwistTrainingSubsystem::StartCoachFollowUpRun(
const FHyperTwistCoachBrief FollowUpBrief = ActiveCoachFollowUpBrief;
const FHyperTwistTrainingCoachSessionQueueState QueueStateBeforeStart = ActiveCoachSessionQueueState;
const HyperTwistTrainingSubsystemInternal::FResolvedCoachCaseBudget LaunchBudget =
HyperTwistTrainingSubsystemInternal::ResolvePreferredCoachCaseBudget(
MaxCases,
EHyperTwistTrainingCoachGuidanceLane::FollowUp,
ActiveCoachMemorySnapshot,
false
);
const FHyperTwistTrainingCoachActionPlan DraftActionPlan =
UHyperTwistTrainingRepositoryLibrary::BuildCoachActionPlan(
FollowUpBrief,
ActiveCoachMemorySnapshot,
FString::Printf(TEXT("coach_follow_up_%s"), *SessionId),
FString()
FString(),
LaunchBudget.RequestedCaseCount,
FollowUpDeck.Cases.Num(),
LaunchBudget.ReasonLine
);
FHyperTwistTrainingRunState RunState = StartTrainingRunFromDeck(
FollowUpDeck,
@ -1694,12 +1734,22 @@ FHyperTwistTrainingRunState UHyperTwistTrainingSubsystem::StartNextQueuedCoachRu
*NextRunnableEntry,
QueueStateBeforeStart.ReferenceUtc
);
const HyperTwistTrainingSubsystemInternal::FResolvedCoachCaseBudget LaunchBudget =
HyperTwistTrainingSubsystemInternal::ResolvePreferredCoachCaseBudget(
MaxCases,
HyperTwistTrainingSubsystemInternal::GuidanceLaneFromQueueSourceLabel(NextRunnableEntry->SourceLabel),
ActiveCoachMemorySnapshot,
true
);
const FHyperTwistTrainingCoachActionPlan DraftActionPlan =
UHyperTwistTrainingRepositoryLibrary::BuildCoachActionPlan(
QueueBrief,
ActiveCoachMemorySnapshot,
FString::Printf(TEXT("coach_queue_%s_%s"), *NextRunnableEntry->EntryId, *SessionId),
FString()
FString(),
LaunchBudget.RequestedCaseCount,
QueueDeck.Cases.Num(),
LaunchBudget.ReasonLine
);
FHyperTwistTrainingRunState RunState = StartTrainingRunFromDeck(
QueueDeck,
@ -1772,6 +1822,7 @@ FHyperTwistTrainingRunState UHyperTwistTrainingSubsystem::StartCoachQueueEntry(
FHyperTwistTrainingDeck QueueDeck;
FHyperTwistCoachBrief QueueBrief;
HyperTwistTrainingSubsystemInternal::FResolvedCoachCaseBudget LaunchBudget;
const bool bHasPrimaryCoachBrief = !ActiveCoachBrief.UserId.IsEmpty() && !ActiveCoachBrief.Headline.IsEmpty();
const bool bHasFollowUpCoachBrief =
!ActiveCoachFollowUpBrief.UserId.IsEmpty() && !ActiveCoachFollowUpBrief.Headline.IsEmpty();
@ -1782,12 +1833,24 @@ FHyperTwistTrainingRunState UHyperTwistTrainingSubsystem::StartCoachQueueEntry(
if (SelectedEntry->SourceLabel == TEXT("primary-brief") && bHasPrimaryCoachBrief)
{
QueueDeck = BuildActiveCoachRecommendedDeck(MaxCases);
LaunchBudget = HyperTwistTrainingSubsystemInternal::ResolvePreferredCoachCaseBudget(
MaxCases,
EHyperTwistTrainingCoachGuidanceLane::Recommended,
ActiveCoachMemorySnapshot,
false
);
QueueBrief = ActiveCoachBrief;
UserId = ActiveCoachBrief.UserId.IsEmpty() ? UserId : ActiveCoachBrief.UserId;
}
else if (SelectedEntry->SourceLabel == TEXT("follow-up-brief") && bHasFollowUpCoachBrief)
{
QueueDeck = BuildActiveCoachFollowUpDeck(MaxCases);
LaunchBudget = HyperTwistTrainingSubsystemInternal::ResolvePreferredCoachCaseBudget(
MaxCases,
EHyperTwistTrainingCoachGuidanceLane::FollowUp,
ActiveCoachMemorySnapshot,
false
);
QueueBrief = ActiveCoachFollowUpBrief;
UserId = ActiveCoachFollowUpBrief.UserId.IsEmpty() ? UserId : ActiveCoachFollowUpBrief.UserId;
}
@ -1799,6 +1862,12 @@ FHyperTwistTrainingRunState UHyperTwistTrainingSubsystem::StartCoachQueueEntry(
ActiveCoachMemorySnapshot,
MaxCases
);
LaunchBudget = HyperTwistTrainingSubsystemInternal::ResolvePreferredCoachCaseBudget(
MaxCases,
HyperTwistTrainingSubsystemInternal::GuidanceLaneFromQueueSourceLabel(SelectedEntry->SourceLabel),
ActiveCoachMemorySnapshot,
true
);
QueueBrief = HyperTwistTrainingSubsystemInternal::BuildCoachBriefFromQueueEntry(
ActiveCoachSessionQueueState,
*SelectedEntry,
@ -1818,7 +1887,10 @@ FHyperTwistTrainingRunState UHyperTwistTrainingSubsystem::StartCoachQueueEntry(
QueueBrief,
ActiveCoachMemorySnapshot,
FString::Printf(TEXT("coach_queue_%s_%s"), *SelectedEntry->EntryId, *SessionId),
FString()
FString(),
LaunchBudget.RequestedCaseCount,
QueueDeck.Cases.Num(),
LaunchBudget.ReasonLine
)
: FHyperTwistTrainingCoachActionPlan();
FHyperTwistTrainingRunState RunState = StartTrainingRunFromDeck(

View file

@ -312,7 +312,10 @@ public:
const FHyperTwistCoachBrief& CoachBrief,
const FHyperTwistTrainingCoachMemorySnapshot& CoachMemorySnapshot,
const FString& PlanId,
const FString& ReferenceUtc
const FString& ReferenceUtc,
int32 RequestedLaunchCaseCount,
int32 PlannedLaunchCaseCount,
const FString& LaunchBudgetReasonLine
);
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Repository|Coach")

View file

@ -1861,6 +1861,12 @@ struct FHyperTwistTrainingCoachMemorySnapshot
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString PreferredCoachHandoffSourceLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 PreferredLaunchBudgetBias = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString PreferredLaunchBudgetSourceLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
EHyperTwistTrainingQueueRecoveryAction PreferredQueueRecoveryAction =
EHyperTwistTrainingQueueRecoveryAction::None;
@ -1892,6 +1898,12 @@ struct FHyperTwistTrainingCoachMemorySnapshot
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 RecoverySuppressedBorderlineFollowUpHistoryCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 BroadenedLaunchBudgetHistoryCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 TightenedLaunchBudgetHistoryCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bNeedsCoachIntervention = false;
@ -2965,6 +2977,21 @@ struct FHyperTwistTrainingCoachActionPlan
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString PreferredCoachHandoffSourceLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 RequestedLaunchCaseCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 PlannedLaunchCaseCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bBroadenedLaunchBudget = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bTightenedLaunchBudget = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString LaunchBudgetReasonLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
TArray<FString> FocusCaseIds;
@ -3506,6 +3533,21 @@ struct FHyperTwistTrainingCoachActionPlanOutcomeSummary
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString PreferredCoachHandoffSourceLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 RequestedLaunchCaseCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 PlannedLaunchCaseCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bBroadenedLaunchBudget = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bTightenedLaunchBudget = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString LaunchBudgetReasonLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 FocusCaseCount = 0;
@ -3855,6 +3897,12 @@ struct FHyperTwistTrainingCoachRecommendationHistorySummary
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 FollowUpLaneContinueBias = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 BroadenedLaunchPlanCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 TightenedLaunchPlanCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 RecurringCaseCount = 0;
@ -3870,6 +3918,15 @@ struct FHyperTwistTrainingCoachRecommendationHistorySummary
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
float AverageFollowUpDepth = 0.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
float AveragePlannedLaunchCaseCount = 0.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
float BroadenedLaunchAverageOutcomeScore = 0.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
float TightenedLaunchAverageOutcomeScore = 0.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
TArray<FString> RecurringCaseIds;