From 06b88284e9efba7b5f2b1afa700220938c98c3fa Mon Sep 17 00:00:00 2001 From: axiomlogicnexus Date: Thu, 7 May 2026 15:20:57 +0200 Subject: [PATCH] Guard template decision bias by selection split --- .../HyperTwistCoachDashboardWidget.cpp | 96 ++++++++++--------- ...SELECTION_SPLIT_GUARD_PACKET_2026-05-07.md | 41 ++++++++ 2 files changed, 91 insertions(+), 46 deletions(-) create mode 100644 docs/arch/HYPERTWIST_PHASE4_TEMPLATE_SIGNAL_DECISION_BIAS_SELECTION_SPLIT_GUARD_PACKET_2026-05-07.md diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp index 7572fdb..4f97fe1 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp @@ -203,8 +203,8 @@ namespace HyperTwistCoachDashboardWidgetInternal bool HasTemplateLaunchTemplateSignalSupportDecisionBias( const FHyperTwistTrainingTemplateLaunchScopedStats* TemplateStats, - int32* OutSnapshotGuardOutcomeRuns = nullptr, - int32* OutNoSnapshotGuardOutcomeRuns = nullptr + int32* OutDecisionSplitGuardOutcomeRuns = nullptr, + int32* OutPlainSnapshotGuardOutcomeRuns = nullptr ); int32 BuildTemplateLaunchAnalyticsTieBreakConfidenceBonus( @@ -854,18 +854,18 @@ namespace HyperTwistCoachDashboardWidgetInternal - NoSnapshotGuardStats.AverageMistakesPerOutcomeRun ); } - int32 SnapshotGuardOutcomeRuns = 0; - int32 NoSnapshotGuardOutcomeRuns = 0; + int32 DecisionSplitGuardOutcomeRuns = 0; + int32 PlainSnapshotGuardOutcomeRuns = 0; const bool bDecisionBiasEarned = HasTemplateLaunchTemplateSignalSupportDecisionBias( TemplateStats, - &SnapshotGuardOutcomeRuns, - &NoSnapshotGuardOutcomeRuns + &DecisionSplitGuardOutcomeRuns, + &PlainSnapshotGuardOutcomeRuns ); Fragment += FString::Printf( - TEXT(" | decision-bias %s guard outcomes %d | no-guard outcomes %d"), + TEXT(" | decision-bias %s reinforced outcomes %d | plain outcomes %d"), bDecisionBiasEarned ? TEXT("earned") : TEXT("suppressed"), - SnapshotGuardOutcomeRuns, - NoSnapshotGuardOutcomeRuns + DecisionSplitGuardOutcomeRuns, + PlainSnapshotGuardOutcomeRuns ); const FHyperTwistTrainingTemplateLaunchSelectionScopedStats& PlainSnapshotGuardStats = TemplateStats @@ -1877,10 +1877,10 @@ namespace HyperTwistCoachDashboardWidgetInternal constexpr float TemplateLaunchTemplateSignalSupportBiasSnapshotMinimumSuccessDelta = 0.05f; constexpr float TemplateLaunchTemplateSignalSupportBiasSnapshotMinimumMistakeImprovement = 0.5f; - constexpr int32 TemplateLaunchTemplateSignalSupportDecisionMinimumSnapshotGuardOutcomeRuns = - 2; - constexpr int32 TemplateLaunchTemplateSignalSupportDecisionMinimumNoSnapshotGuardOutcomeRuns = - 2; + constexpr int32 + TemplateLaunchTemplateSignalSupportDecisionMinimumDecisionSplitGuardOutcomeRuns = 2; + constexpr int32 + TemplateLaunchTemplateSignalSupportDecisionMinimumPlainSnapshotGuardOutcomeRuns = 2; constexpr int32 TemplateLaunchTemplateSignalSupportDecisionMinimumScoreDelta = 1; constexpr float TemplateLaunchTemplateSignalSupportDecisionMinimumSuccessDelta = 0.05f; constexpr float TemplateLaunchTemplateSignalSupportDecisionMinimumMistakeImprovement = 0.5f; @@ -2289,63 +2289,67 @@ namespace HyperTwistCoachDashboardWidgetInternal bool HasTemplateLaunchTemplateSignalSupportDecisionBias( const FHyperTwistTrainingTemplateLaunchScopedStats* TemplateStats, - int32* OutSnapshotGuardOutcomeRuns, - int32* OutNoSnapshotGuardOutcomeRuns + int32* OutDecisionSplitGuardOutcomeRuns, + int32* OutPlainSnapshotGuardOutcomeRuns ) { - const FHyperTwistTrainingTemplateLaunchSelectionScopedStats* SnapshotGuardStats = nullptr; - const FHyperTwistTrainingTemplateLaunchSelectionScopedStats* NoSnapshotGuardStats = + const FHyperTwistTrainingTemplateLaunchSelectionScopedStats* DecisionSplitGuardStats = + nullptr; + const FHyperTwistTrainingTemplateLaunchSelectionScopedStats* PlainSnapshotGuardStats = nullptr; if (TemplateStats != nullptr && TemplateStats->IsStructurallyValid()) { - SnapshotGuardStats = + DecisionSplitGuardStats = &TemplateStats - ->DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardStats; - NoSnapshotGuardStats = + ->DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardDecisionSplitGuardStats; + PlainSnapshotGuardStats = &TemplateStats - ->DashboardAnalyticsTieBreakTemplateScopedSignalNoSupportBiasSnapshotGuardStats; + ->DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardNoDecisionBiasStats; } - const int32 SnapshotGuardOutcomeRuns = - CountTemplateLaunchSelectionOutcomeRuns(SnapshotGuardStats); - const int32 NoSnapshotGuardOutcomeRuns = - CountTemplateLaunchSelectionOutcomeRuns(NoSnapshotGuardStats); - if (OutSnapshotGuardOutcomeRuns != nullptr) + const int32 DecisionSplitGuardOutcomeRuns = + CountTemplateLaunchSelectionOutcomeRuns(DecisionSplitGuardStats); + const int32 PlainSnapshotGuardOutcomeRuns = + CountTemplateLaunchSelectionOutcomeRuns(PlainSnapshotGuardStats); + if (OutDecisionSplitGuardOutcomeRuns != nullptr) { - *OutSnapshotGuardOutcomeRuns = SnapshotGuardOutcomeRuns; + *OutDecisionSplitGuardOutcomeRuns = DecisionSplitGuardOutcomeRuns; } - if (OutNoSnapshotGuardOutcomeRuns != nullptr) + if (OutPlainSnapshotGuardOutcomeRuns != nullptr) { - *OutNoSnapshotGuardOutcomeRuns = NoSnapshotGuardOutcomeRuns; + *OutPlainSnapshotGuardOutcomeRuns = PlainSnapshotGuardOutcomeRuns; } if (!HasTemplateLaunchTemplateSignalSupportBiasSnapshotBias(TemplateStats) - || SnapshotGuardOutcomeRuns - < TemplateLaunchTemplateSignalSupportDecisionMinimumSnapshotGuardOutcomeRuns - || NoSnapshotGuardOutcomeRuns - < TemplateLaunchTemplateSignalSupportDecisionMinimumNoSnapshotGuardOutcomeRuns) + || DecisionSplitGuardOutcomeRuns + < TemplateLaunchTemplateSignalSupportDecisionMinimumDecisionSplitGuardOutcomeRuns + || PlainSnapshotGuardOutcomeRuns + < TemplateLaunchTemplateSignalSupportDecisionMinimumPlainSnapshotGuardOutcomeRuns) { return false; } - const int32 SnapshotGuardScore = - BuildTemplateLaunchSelectionLaneAnalyticsScore(SnapshotGuardStats); - const int32 NoSnapshotGuardScore = - BuildTemplateLaunchSelectionLaneAnalyticsScore(NoSnapshotGuardStats); - const int32 ScoreDelta = SnapshotGuardScore - NoSnapshotGuardScore; + const int32 DecisionSplitGuardScore = + BuildTemplateLaunchSelectionLaneAnalyticsScore(DecisionSplitGuardStats); + const int32 PlainSnapshotGuardScore = + BuildTemplateLaunchSelectionLaneAnalyticsScore(PlainSnapshotGuardStats); + const int32 ScoreDelta = DecisionSplitGuardScore - PlainSnapshotGuardScore; const float SuccessDelta = - (SnapshotGuardStats != nullptr && SnapshotGuardStats->IsStructurallyValid() - ? SnapshotGuardStats->OverallSuccessRate + (DecisionSplitGuardStats != nullptr && DecisionSplitGuardStats->IsStructurallyValid() + ? DecisionSplitGuardStats->OverallSuccessRate : 0.0f) - - (NoSnapshotGuardStats != nullptr && NoSnapshotGuardStats->IsStructurallyValid() - ? NoSnapshotGuardStats->OverallSuccessRate + - (PlainSnapshotGuardStats != nullptr + && PlainSnapshotGuardStats->IsStructurallyValid() + ? PlainSnapshotGuardStats->OverallSuccessRate : 0.0f); const float MistakeImprovement = - (NoSnapshotGuardStats != nullptr && NoSnapshotGuardStats->IsStructurallyValid() - ? NoSnapshotGuardStats->AverageMistakesPerOutcomeRun + (PlainSnapshotGuardStats != nullptr + && PlainSnapshotGuardStats->IsStructurallyValid() + ? PlainSnapshotGuardStats->AverageMistakesPerOutcomeRun : 0.0f) - - (SnapshotGuardStats != nullptr && SnapshotGuardStats->IsStructurallyValid() - ? SnapshotGuardStats->AverageMistakesPerOutcomeRun + - (DecisionSplitGuardStats != nullptr + && DecisionSplitGuardStats->IsStructurallyValid() + ? DecisionSplitGuardStats->AverageMistakesPerOutcomeRun : 0.0f); return ScoreDelta >= TemplateLaunchTemplateSignalSupportDecisionMinimumScoreDelta || SuccessDelta >= TemplateLaunchTemplateSignalSupportDecisionMinimumSuccessDelta diff --git a/docs/arch/HYPERTWIST_PHASE4_TEMPLATE_SIGNAL_DECISION_BIAS_SELECTION_SPLIT_GUARD_PACKET_2026-05-07.md b/docs/arch/HYPERTWIST_PHASE4_TEMPLATE_SIGNAL_DECISION_BIAS_SELECTION_SPLIT_GUARD_PACKET_2026-05-07.md new file mode 100644 index 0000000..46927aa --- /dev/null +++ b/docs/arch/HYPERTWIST_PHASE4_TEMPLATE_SIGNAL_DECISION_BIAS_SELECTION_SPLIT_GUARD_PACKET_2026-05-07.md @@ -0,0 +1,41 @@ +# HyperTwist Phase 4 template-signal decision-bias selection split guard packet + +## Purpose + +This packet tightens the stricter `DecisionSplitGuard` reinforcement rule so tied broader template-signal selection no longer compares that reinforced lane against all non-snapshot-guard history. It now compares reinforced `decision-split-guard` outcomes against plain snapshot-guard history, which is the actual lane the stricter guard is supposed to outperform before it gets extra preference. + +## Scope + +- retarget the existing template-signal decision-bias helper to compare: + - `decision-split-guard` + - vs `plain-snapshot-guard` +- keep the existing minimum-sample and score/success/mistake thresholds, but apply them to the new nested snapshot-guard split +- update shared analytics wording so the current decision-bias state reports reinforced and plain snapshot-guard outcome counts instead of broader guard vs no-guard counts + +## What landed + +- `HyperTwistCoachDashboardWidget.cpp` + - `HasTemplateLaunchTemplateSignalSupportDecisionBias(...)` now uses: + - `DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardDecisionSplitGuardStats` + - `DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardNoDecisionBiasStats` + - tied broader analytics selection still gates the stricter reinforcement through the same helper, but the helper now only earns when reinforced outcomes are actually beating plain snapshot-guard history + - shared `template-signal decision` analytics detail now reports: + - `decision-bias earned/suppressed reinforced outcomes ... | plain outcomes ...` + +## Product effect + +- the stricter `DecisionSplitGuard` lane now has to outperform plain snapshot-guard history, not merely broader no-snapshot-guard history, before it can reinforce future tied broader selections +- operators see the current gate in the same terms the selector now uses, which makes the analytics readout match the actual decision policy + +## Acceptance criteria + +- `HasTemplateLaunchTemplateSignalSupportDecisionBias(...)` compares reinforced `decision-split-guard` history against plain snapshot-guard history +- tied broader `TemplateScopedOutcomeSignal` selection only gets the stricter reinforcement when that reinforced-vs-plain comparison clears the existing thresholds +- shared analytics detail reports reinforced and plain snapshot-guard outcome counts for the current decision-bias state + +## Validation checklist + +1. full `Development Editor|Win64` build succeeds +2. confirm the decision-bias helper reads the nested snapshot-guard split instead of the older snapshot-guard vs no-snapshot-guard split +3. confirm shared analytics detail shows `decision-bias earned/suppressed reinforced outcomes ... | plain outcomes ...` +4. confirm tied broader analytics selection still flows through the same decision-bias helper after the comparison target change