diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp index 2d220c1..9a68b28 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp @@ -130,6 +130,11 @@ namespace HyperTwistCoachDashboardWidgetInternal const TCHAR* SubjectLabel ); + FString BuildTemplateLaunchComparablePeerConfidenceStatusClause( + const FHyperTwistTrainingTemplateLaunchSelectionProvenance* SelectionProvenance, + const FHyperTwistTrainingTemplateLaunchScopedStats* TemplateStats + ); + bool HasTemplateLaunchComparablePeerEvidenceForConfidenceBonus( const FHyperTwistTrainingTemplateLaunchScopedStats* TemplateStats, int32* OutComparablePeerOutcomeRuns = nullptr, @@ -710,6 +715,56 @@ namespace HyperTwistCoachDashboardWidgetInternal ); } + FString BuildTemplateLaunchComparablePeerConfidenceStatusClause( + const FHyperTwistTrainingTemplateLaunchSelectionProvenance* SelectionProvenance, + const FHyperTwistTrainingTemplateLaunchScopedStats* TemplateStats + ) + { + if (SelectionProvenance == nullptr + || SelectionProvenance->ReasonClass + != EHyperTwistTrainingTemplateLaunchSelectionReasonClass::AnalyticsTieBreak + || SelectionProvenance->AnalyticsSupportKind + != EHyperTwistTrainingTemplateLaunchSelectionAnalyticsSupportKind:: + TemplateScopedOutcomeSignal) + { + return FString(); + } + + if (TemplateStats == nullptr || !TemplateStats->IsStructurallyValid()) + { + return TEXT("Broader analytics pick; split-confidence lane has no retained comparable-peer confidence lane yet."); + } + + int32 ComparablePeerOutcomeRuns = 0; + int32 SplitConfidenceOutcomeRuns = 0; + int32 PeerNoEvidenceOutcomeRuns = 0; + float ComparablePeerOutcomeShare = 0.0f; + const bool bGuardEarned = HasTemplateLaunchComparablePeerEvidenceForConfidenceBonus( + TemplateStats, + &ComparablePeerOutcomeRuns, + &SplitConfidenceOutcomeRuns, + &ComparablePeerOutcomeShare, + &PeerNoEvidenceOutcomeRuns + ); + if (bGuardEarned) + { + return FString::Printf( + TEXT("Broader analytics pick; split-confidence lane is already confidence-eligible for future reinforcement on comparable-peer-backed history (%d/%d outcomes, share %.2f)."), + ComparablePeerOutcomeRuns, + SplitConfidenceOutcomeRuns, + ComparablePeerOutcomeShare + ); + } + + return FString::Printf( + TEXT("Broader analytics pick; split-confidence lane is still suppressed by peer-no-evidence-heavy history (%d/%d comparable-peer outcomes, share %.2f; peer-no-evidence %d)."), + ComparablePeerOutcomeRuns, + SplitConfidenceOutcomeRuns, + ComparablePeerOutcomeShare, + PeerNoEvidenceOutcomeRuns + ); + } + FString BuildTemplateLaunchSelectionAnalyticsSupportDetailFragment( const FHyperTwistTrainingTemplateLaunchSelectionProvenance* SelectionProvenance ) @@ -12626,6 +12681,13 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation() ? &PreferredTemplateLaunchSelectionProvenance : nullptr ); + const FString PreferredTemplateLaunchComparablePeerConfidenceStatusClause = + HyperTwistCoachDashboardWidgetInternal::BuildTemplateLaunchComparablePeerConfidenceStatusClause( + PreferredTemplateLaunchSelectionProvenance.IsStructurallyValid() + ? &PreferredTemplateLaunchSelectionProvenance + : nullptr, + PreferredTemplateLaunchStats + ); const bool bCanLaunchPreferredTemplate = !bHasLiveAttemptTimer && !bHasActiveRun && bHasPreferredTemplateLaunch; FString TemplateLaunchStatusLine; @@ -12669,6 +12731,11 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation() PreferredTemplateLaunchStats) ); } + if (!PreferredTemplateLaunchComparablePeerConfidenceStatusClause.IsEmpty()) + { + TemplateLaunchStatusLine += TEXT(" "); + TemplateLaunchStatusLine += PreferredTemplateLaunchComparablePeerConfidenceStatusClause; + } FString TemplateLaunchDetailLine; if (!bHasPreferredTemplateLaunch) { diff --git a/docs/arch/HYPERTWIST_PHASE4_TEMPLATE_LAUNCH_STATUS_CONFIDENCE_LANE_PACKET_2026-05-07.md b/docs/arch/HYPERTWIST_PHASE4_TEMPLATE_LAUNCH_STATUS_CONFIDENCE_LANE_PACKET_2026-05-07.md new file mode 100644 index 0000000..e235af0 --- /dev/null +++ b/docs/arch/HYPERTWIST_PHASE4_TEMPLATE_LAUNCH_STATUS_CONFIDENCE_LANE_PACKET_2026-05-07.md @@ -0,0 +1,61 @@ +# HyperTwist Phase 4 template launch status confidence-lane packet + +Created on `2026-05-07` + +Status: + +- first-party HyperTwist packet +- bounded Phase `4` dashboard status-line slice + +## Purpose + +This packet moves the comparable-peer confidence-lane result up into the live `[Template Launch]` status sentence itself. Before launch, an operator can now see in one line whether the preferred template is winning on broader analytics while its split-confidence lane is already eligible for future reinforcement or is still being suppressed by peer-no-evidence-heavy history. + +## Scope + +Bounded lane: + +- add a concise status-clause formatter for comparable-peer confidence state +- only emit that clause when the preferred template was chosen by the broader `TemplateScopedOutcomeSignal` analytics tie-break path +- append the clause to the existing live template-launch status sentence without widening persisted provenance or dashboard layout + +Out of scope: + +- changing selector policy or thresholds +- changing the long-form detail/recap/history analytics fragments +- widening repo aggregation +- adding another dashboard section + +## What landed + +Primary code changes: + +- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp` + - added a short comparable-peer confidence status formatter + - when the preferred template is an analytics tie-break winner on broader outcome signal, the live status sentence now says whether the template's split-confidence lane is: + - already `confidence-eligible` for future reinforcement on comparable-peer-backed history + - or still `suppressed` by peer-no-evidence-heavy history + - the status clause includes comparable-peer outcome count/share and peer-no-evidence count + +## Product effect + +The operator no longer has to open detail text to understand the preferred template's confidence posture: + +- the live `[Template Launch]` status line itself now explains the current confidence-lane state for broader-analytics winners +- the status sentence stays unchanged for primary-priority picks and `SelectorSplitConfidence` picks + +## Acceptance criteria + +- live template-launch status sentence includes comparable-peer confidence posture for broader outcome-signal analytics winners +- status sentence distinguishes `confidence-eligible` from `suppressed` +- status sentence includes comparable-peer count/share and peer-no-evidence count +- full product build succeeds + +## Validation checklist + +1. build `UnrealHyperTwist.sln` / `UnrealHyperTwistEditor` +2. confirm broader outcome-signal preferred-template status includes the confidence-lane clause +3. confirm primary-priority and `SelectorSplitConfidence` status sentences remain unchanged +4. confirm the clause distinguishes confidence-eligible vs suppressed with counts + +That is the packet.