From 313aa01cecc18989d3901e4db3c022f6ef98ae2a Mon Sep 17 00:00:00 2001 From: axiomlogicnexus Date: Thu, 7 May 2026 02:28:42 +0200 Subject: [PATCH] Expose comparable peer confidence lanes --- .../HyperTwistCoachDashboardWidget.cpp | 129 +++++++++++++++++- ...PEER_CONFIDENCE_LANES_PACKET_2026-05-07.md | 67 +++++++++ 2 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 docs/arch/HYPERTWIST_PHASE4_TEMPLATE_LAUNCH_COMPARABLE_PEER_CONFIDENCE_LANES_PACKET_2026-05-07.md diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp index 1cfcdef..132f776 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp @@ -121,6 +121,10 @@ namespace HyperTwistCoachDashboardWidgetInternal const FHyperTwistTrainingTemplateLaunchScopedStats* TemplateStats ); + FString BuildTemplateLaunchComparablePeerConfidenceLaneFragment( + const FHyperTwistTrainingTemplateLaunchScopedStats* TemplateStats + ); + bool HasTemplateLaunchComparablePeerEvidenceForConfidenceBonus( const FHyperTwistTrainingTemplateLaunchScopedStats* TemplateStats, int32* OutComparablePeerOutcomeRuns = nullptr, @@ -153,7 +157,7 @@ namespace HyperTwistCoachDashboardWidgetInternal } return FString::Printf( - TEXT("avg recommended %d | avg focus %d | avg completed attempts %d | total success/failure/timeout/dnf %d/%d/%d/%d | avg mistakes %.2f | review-backed %d | coach-review %d | short set %d | selector split %s | tie-break support %s | peer support split %s | last launch %s | last completed %s"), + TEXT("avg recommended %d | avg focus %d | avg completed attempts %d | total success/failure/timeout/dnf %d/%d/%d/%d | avg mistakes %.2f | review-backed %d | coach-review %d | short set %d | selector split %s | tie-break support %s | peer support split %s | comparable-peer confidence %s | last launch %s | last completed %s"), TemplateStats->AverageRecommendedCaseCount, TemplateStats->AverageFocusCaseCount, TemplateStats->AverageCompletedAttemptCount, @@ -168,6 +172,7 @@ namespace HyperTwistCoachDashboardWidgetInternal *BuildTemplateLaunchSelectionSplitAnalyticsFragment(TemplateStats), *BuildTemplateLaunchAnalyticsTieBreakSupportSplitFragment(TemplateStats), *BuildTemplateLaunchAnalyticsTieBreakPeerDispositionSplitFragment(TemplateStats), + *BuildTemplateLaunchComparablePeerConfidenceLaneFragment(TemplateStats), TemplateStats->LastLaunchAtUtc.IsEmpty() ? TEXT("n/a") : *TemplateStats->LastLaunchAtUtc, @@ -536,6 +541,128 @@ namespace HyperTwistCoachDashboardWidgetInternal ); } + FString BuildTemplateLaunchComparablePeerConfidenceLaneFragment( + const FHyperTwistTrainingTemplateLaunchScopedStats* TemplateStats + ) + { + if (TemplateStats == nullptr || !TemplateStats->IsStructurallyValid()) + { + return TEXT("no comparable-peer confidence lane is available for this template id yet"); + } + + const FHyperTwistTrainingTemplateLaunchSelectionScopedStats& SplitConfidenceStats = + TemplateStats->DashboardAnalyticsTieBreakSelectorSplitConfidenceStats; + const FHyperTwistTrainingTemplateLaunchSelectionScopedStats& PeerNoEvidenceStats = + TemplateStats + ->DashboardAnalyticsTieBreakSelectorSplitConfidencePeerLackedComparableEvidenceStats; + const FHyperTwistTrainingTemplateLaunchSelectionScopedStats& PeerWeakerStats = + TemplateStats + ->DashboardAnalyticsTieBreakSelectorSplitConfidencePeerFailedWeakerSupportKindStats; + const FHyperTwistTrainingTemplateLaunchSelectionScopedStats& PeerMarginalStats = + TemplateStats + ->DashboardAnalyticsTieBreakSelectorSplitConfidencePeerFailedMarginalSupportKindStats; + const FHyperTwistTrainingTemplateLaunchSelectionScopedStats& PeerClearedStats = + TemplateStats + ->DashboardAnalyticsTieBreakSelectorSplitConfidencePeerClearedComparableGuardStats; + if (!SplitConfidenceStats.IsStructurallyValid() + && !PeerNoEvidenceStats.IsStructurallyValid() + && !PeerWeakerStats.IsStructurallyValid() + && !PeerMarginalStats.IsStructurallyValid() + && !PeerClearedStats.IsStructurallyValid()) + { + return TEXT("no comparable-peer confidence lane is available for this template id yet"); + } + + auto BuildCombinedLaneSummary = + []( + const TCHAR* LaneLabel, + const FHyperTwistTrainingTemplateLaunchSelectionScopedStats* FirstStats, + const FHyperTwistTrainingTemplateLaunchSelectionScopedStats* SecondStats, + const FHyperTwistTrainingTemplateLaunchSelectionScopedStats* ThirdStats) + { + int32 LaunchCount = 0; + int32 OutcomeRunCount = 0; + int32 TotalCompletedAttemptCount = 0; + int32 TotalSuccessCount = 0; + double MistakeAccumulator = 0.0; + bool bHasAnyStats = false; + auto AccumulateStats = + [&]( + const FHyperTwistTrainingTemplateLaunchSelectionScopedStats* SourceStats) + { + if (SourceStats == nullptr || !SourceStats->IsStructurallyValid()) + { + return; + } + + bHasAnyStats = true; + LaunchCount += SourceStats->LaunchCount; + OutcomeRunCount += SourceStats->GetOutcomeRunCount(); + TotalCompletedAttemptCount += SourceStats->TotalCompletedAttemptCount; + TotalSuccessCount += SourceStats->TotalSuccessCount; + MistakeAccumulator += static_cast( + SourceStats->AverageMistakesPerOutcomeRun) + * static_cast(SourceStats->GetOutcomeRunCount()); + }; + AccumulateStats(FirstStats); + AccumulateStats(SecondStats); + AccumulateStats(ThirdStats); + + if (!bHasAnyStats) + { + return FString::Printf(TEXT("%s none yet"), LaneLabel); + } + + const float SuccessRate = TotalCompletedAttemptCount > 0 + ? static_cast(TotalSuccessCount) + / static_cast(TotalCompletedAttemptCount) + : 0.0f; + const float AverageMistakes = OutcomeRunCount > 0 + ? static_cast( + MistakeAccumulator / static_cast(OutcomeRunCount)) + : 0.0f; + return FString::Printf( + TEXT("%s launches %d | outcomes %d | success %.2f | avg mistakes %.2f"), + LaneLabel, + LaunchCount, + OutcomeRunCount, + SuccessRate, + AverageMistakes + ); + }; + + int32 ComparablePeerOutcomeRuns = 0; + int32 SplitConfidenceOutcomeRuns = 0; + int32 PeerNoEvidenceOutcomeRuns = 0; + float ComparablePeerOutcomeShare = 0.0f; + const bool bGuardEarned = HasTemplateLaunchComparablePeerEvidenceForConfidenceBonus( + TemplateStats, + &ComparablePeerOutcomeRuns, + &SplitConfidenceOutcomeRuns, + &ComparablePeerOutcomeShare, + &PeerNoEvidenceOutcomeRuns + ); + + return FString::Printf( + TEXT("%s | %s | guard %s comparable-peer %d/%d outcomes share %.2f | peer-no-evidence %d"), + *BuildCombinedLaneSummary( + TEXT("comparable-peer-backed"), + &PeerWeakerStats, + &PeerMarginalStats, + &PeerClearedStats), + *BuildCombinedLaneSummary( + TEXT("peer-no-evidence-heavy"), + &PeerNoEvidenceStats, + nullptr, + nullptr), + bGuardEarned ? TEXT("earned") : TEXT("suppressed"), + ComparablePeerOutcomeRuns, + SplitConfidenceOutcomeRuns, + ComparablePeerOutcomeShare, + PeerNoEvidenceOutcomeRuns + ); + } + FString BuildTemplateLaunchSelectionAnalyticsSupportDetailFragment( const FHyperTwistTrainingTemplateLaunchSelectionProvenance* SelectionProvenance ) diff --git a/docs/arch/HYPERTWIST_PHASE4_TEMPLATE_LAUNCH_COMPARABLE_PEER_CONFIDENCE_LANES_PACKET_2026-05-07.md b/docs/arch/HYPERTWIST_PHASE4_TEMPLATE_LAUNCH_COMPARABLE_PEER_CONFIDENCE_LANES_PACKET_2026-05-07.md new file mode 100644 index 0000000..b6ba7ea --- /dev/null +++ b/docs/arch/HYPERTWIST_PHASE4_TEMPLATE_LAUNCH_COMPARABLE_PEER_CONFIDENCE_LANES_PACKET_2026-05-07.md @@ -0,0 +1,67 @@ +# HyperTwist Phase 4 template launch comparable-peer confidence lanes packet + +Created on `2026-05-07` + +Status: + +- first-party HyperTwist packet +- bounded Phase `4` dashboard analytics visibility slice + +## Purpose + +This packet surfaces the comparable-peer confidence guard result directly in shared template analytics detail by collapsing selector-split-confidence history into two operator-facing lanes: + +- `comparable-peer-backed` +- `peer-no-evidence-heavy` + +That makes it obvious whether confidence reinforcement is currently earned on peers with comparable support-kind evidence or suppressed because the template leans too heavily on empty peer lanes. + +## Scope + +Bounded lane: + +- keep the existing raw peer support split +- synthesize two shared analytics lanes from the repo-backed peer disposition buckets +- append guard-earned / guard-suppressed status plus comparable-peer count/share to the shared template analytics detail +- let preferred template launch, template launch history, and template-backed recap inherit that visibility automatically + +Out of scope: + +- changing selector scoring again +- widening repository schema +- adding a dedicated dashboard panel +- changing persisted provenance + +## What landed + +Primary code changes: + +- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp` + - added a shared formatter that combines peer-weaker, peer-marginal, and peer-cleared buckets into a `comparable-peer-backed` lane + - keeps the `peer-no-evidence-heavy` lane separate from the peer-no-evidence bucket + - reports whether the comparable-peer guard is currently earned or suppressed, along with comparable-peer outcome count/share and peer-no-evidence outcome count + - appends that synthesized confidence-lane view to the existing shared template analytics detail + +## Product effect + +Operators now get a quick confidence readout anywhere shared template analytics are shown: + +- live `[Template Launch]` detail shows whether selector-split confidence is currently earned on comparable-peer-backed history +- template launch history shows the same lane split for the selected history row's template +- template-backed recap shows the same lane split for the displayed run's template + +## Acceptance criteria + +- shared template analytics detail shows `comparable-peer-backed` and `peer-no-evidence-heavy` confidence lanes +- shared detail shows guard-earned / guard-suppressed state with comparable-peer count/share +- live launch detail, template history, and recap all inherit the new lane split through the shared analytics fragment +- full product build succeeds + +## Validation checklist + +1. build `UnrealHyperTwist.sln` / `UnrealHyperTwistEditor` +2. confirm shared template analytics detail includes both confidence lanes +3. confirm shared detail shows guard-earned / guard-suppressed state with comparable-peer outcome count/share +4. confirm preferred template launch, template history, and recap all inherit the synthesized confidence lanes + +That is the packet.