Guard template confidence by comparable peer evidence

This commit is contained in:
axiomlogicnexus 2026-05-07 02:24:31 +02:00
parent f9fbc23216
commit badbd4a082
2 changed files with 180 additions and 1 deletions

View file

@ -121,6 +121,14 @@ namespace HyperTwistCoachDashboardWidgetInternal
const FHyperTwistTrainingTemplateLaunchScopedStats* TemplateStats
);
bool HasTemplateLaunchComparablePeerEvidenceForConfidenceBonus(
const FHyperTwistTrainingTemplateLaunchScopedStats* TemplateStats,
int32* OutComparablePeerOutcomeRuns = nullptr,
int32* OutSplitConfidenceOutcomeRuns = nullptr,
float* OutComparablePeerOutcomeShare = nullptr,
int32* OutPeerNoEvidenceOutcomeRuns = nullptr
);
int32 BuildTemplateLaunchAnalyticsTieBreakConfidenceBonus(
const FHyperTwistTrainingTemplateLaunchScopedStats* TemplateStats
);
@ -930,6 +938,8 @@ namespace HyperTwistCoachDashboardWidgetInternal
constexpr int32 TemplateLaunchSelectionTieBreakConfidenceMinimumScoreDelta = 2;
constexpr float TemplateLaunchSelectionTieBreakConfidenceMinimumSuccessDelta = 0.05f;
constexpr float TemplateLaunchSelectionTieBreakConfidenceMinimumMistakeImprovement = 0.5f;
constexpr int32 TemplateLaunchSelectionTieBreakConfidenceMinimumComparablePeerOutcomeRuns = 2;
constexpr float TemplateLaunchSelectionTieBreakConfidenceMinimumComparablePeerOutcomeShare = 0.40f;
int32 CountTemplateLaunchOutcomeRuns(const FHyperTwistTrainingTemplateLaunchScopedStats* TemplateStats)
{
@ -1007,6 +1017,73 @@ namespace HyperTwistCoachDashboardWidgetInternal
);
}
bool HasTemplateLaunchComparablePeerEvidenceForConfidenceBonus(
const FHyperTwistTrainingTemplateLaunchScopedStats* TemplateStats,
int32* OutComparablePeerOutcomeRuns,
int32* OutSplitConfidenceOutcomeRuns,
float* OutComparablePeerOutcomeShare,
int32* OutPeerNoEvidenceOutcomeRuns
)
{
const FHyperTwistTrainingTemplateLaunchSelectionScopedStats* SplitConfidenceStats = nullptr;
const FHyperTwistTrainingTemplateLaunchSelectionScopedStats* PeerNoEvidenceStats = nullptr;
const FHyperTwistTrainingTemplateLaunchSelectionScopedStats* PeerWeakerStats = nullptr;
const FHyperTwistTrainingTemplateLaunchSelectionScopedStats* PeerMarginalStats = nullptr;
const FHyperTwistTrainingTemplateLaunchSelectionScopedStats* PeerClearedStats = nullptr;
if (TemplateStats != nullptr && TemplateStats->IsStructurallyValid())
{
SplitConfidenceStats =
&TemplateStats->DashboardAnalyticsTieBreakSelectorSplitConfidenceStats;
PeerNoEvidenceStats =
&TemplateStats
->DashboardAnalyticsTieBreakSelectorSplitConfidencePeerLackedComparableEvidenceStats;
PeerWeakerStats =
&TemplateStats
->DashboardAnalyticsTieBreakSelectorSplitConfidencePeerFailedWeakerSupportKindStats;
PeerMarginalStats =
&TemplateStats
->DashboardAnalyticsTieBreakSelectorSplitConfidencePeerFailedMarginalSupportKindStats;
PeerClearedStats =
&TemplateStats
->DashboardAnalyticsTieBreakSelectorSplitConfidencePeerClearedComparableGuardStats;
}
const int32 ComparablePeerOutcomeRuns =
CountTemplateLaunchSelectionOutcomeRuns(PeerWeakerStats)
+ CountTemplateLaunchSelectionOutcomeRuns(PeerMarginalStats)
+ CountTemplateLaunchSelectionOutcomeRuns(PeerClearedStats);
const int32 SplitConfidenceOutcomeRuns =
CountTemplateLaunchSelectionOutcomeRuns(SplitConfidenceStats);
const int32 PeerNoEvidenceOutcomeRuns =
CountTemplateLaunchSelectionOutcomeRuns(PeerNoEvidenceStats);
const float ComparablePeerOutcomeShare = SplitConfidenceOutcomeRuns > 0
? static_cast<float>(ComparablePeerOutcomeRuns)
/ static_cast<float>(SplitConfidenceOutcomeRuns)
: 0.0f;
if (OutComparablePeerOutcomeRuns != nullptr)
{
*OutComparablePeerOutcomeRuns = ComparablePeerOutcomeRuns;
}
if (OutSplitConfidenceOutcomeRuns != nullptr)
{
*OutSplitConfidenceOutcomeRuns = SplitConfidenceOutcomeRuns;
}
if (OutComparablePeerOutcomeShare != nullptr)
{
*OutComparablePeerOutcomeShare = ComparablePeerOutcomeShare;
}
if (OutPeerNoEvidenceOutcomeRuns != nullptr)
{
*OutPeerNoEvidenceOutcomeRuns = PeerNoEvidenceOutcomeRuns;
}
return ComparablePeerOutcomeRuns
>= TemplateLaunchSelectionTieBreakConfidenceMinimumComparablePeerOutcomeRuns
&& ComparablePeerOutcomeShare
>= TemplateLaunchSelectionTieBreakConfidenceMinimumComparablePeerOutcomeShare;
}
int32 BuildTemplateLaunchAnalyticsTieBreakConfidenceBonus(
const FHyperTwistTrainingTemplateLaunchScopedStats* TemplateStats
)
@ -1053,6 +1130,10 @@ namespace HyperTwistCoachDashboardWidgetInternal
{
return 0;
}
if (!HasTemplateLaunchComparablePeerEvidenceForConfidenceBonus(TemplateStats))
{
return 0;
}
return 1;
}
@ -1094,6 +1175,11 @@ namespace HyperTwistCoachDashboardWidgetInternal
return EHyperTwistTrainingTemplateLaunchSelectionPeerSupportKindDisposition::
PeerFailedGuardOnWeakerSupportKindOutcomes;
}
if (!HasTemplateLaunchComparablePeerEvidenceForConfidenceBonus(TemplateStats))
{
return EHyperTwistTrainingTemplateLaunchSelectionPeerSupportKindDisposition::
PeerLackedComparableEvidence;
}
if (BuildTemplateLaunchAnalyticsTieBreakConfidenceBonus(TemplateStats) <= 0)
{
@ -1166,6 +1252,32 @@ namespace HyperTwistCoachDashboardWidgetInternal
const float MistakeImprovement =
TemplateSignalStats.AverageMistakesPerOutcomeRun
- SplitConfidenceStats.AverageMistakesPerOutcomeRun;
int32 ComparablePeerOutcomeRuns = 0;
int32 SplitConfidenceSelectionOutcomeRuns = 0;
int32 PeerNoEvidenceOutcomeRuns = 0;
float ComparablePeerOutcomeShare = 0.0f;
const bool bHasComparablePeerEvidence =
HasTemplateLaunchComparablePeerEvidenceForConfidenceBonus(
TemplateStats,
&ComparablePeerOutcomeRuns,
&SplitConfidenceSelectionOutcomeRuns,
&ComparablePeerOutcomeShare,
&PeerNoEvidenceOutcomeRuns
);
if (!bHasComparablePeerEvidence)
{
return FString::Printf(
TEXT("%s lacked enough selector-split wins against peers with comparable support-kind evidence to clear the selector-split confidence guard: comparable-peer outcomes %d of %d split-confidence outcomes (share %.2f, required at least %d at %.2f) | peer-no-evidence %d | %s"),
ResolvedSubjectLabel,
ComparablePeerOutcomeRuns,
SplitConfidenceSelectionOutcomeRuns,
ComparablePeerOutcomeShare,
TemplateLaunchSelectionTieBreakConfidenceMinimumComparablePeerOutcomeRuns,
TemplateLaunchSelectionTieBreakConfidenceMinimumComparablePeerOutcomeShare,
PeerNoEvidenceOutcomeRuns,
*SignalFragment
);
}
if (BuildTemplateLaunchAnalyticsTieBreakConfidenceBonus(TemplateStats) <= 0)
{
return FString::Printf(
@ -1178,8 +1290,11 @@ namespace HyperTwistCoachDashboardWidgetInternal
}
return FString::Printf(
TEXT("%s split-confidence beat its template-signal bucket on stored support-kind outcomes and cleared the selector-split confidence guard: %s"),
TEXT("%s split-confidence beat its template-signal bucket on stored support-kind outcomes and cleared the selector-split confidence guard with comparable-peer outcomes %d of %d split-confidence outcomes (share %.2f): %s"),
ResolvedSubjectLabel,
ComparablePeerOutcomeRuns,
SplitConfidenceSelectionOutcomeRuns,
ComparablePeerOutcomeShare,
*SignalFragment
);
}

View file

@ -0,0 +1,64 @@
# HyperTwist Phase 4 template launch comparable-peer confidence guard packet
Created on `2026-05-07`
Status:
- first-party HyperTwist packet
- bounded Phase `4` dashboard selector confidence slice
## Purpose
This packet starts consuming the new peer-support disposition analytics in actual selector policy. The selector-split confidence bonus now requires enough wins against peers that had at least some comparable support-kind evidence, so stored confidence does not keep reinforcing itself mainly by beating peer lanes that had no comparable evidence at all.
## Scope
Bounded lane:
- keep the existing support-kind score, success, and mistake delta guard intact
- add a comparable-peer-evidence guard on top of it using the repo-backed peer disposition buckets
- require both:
- a minimum count of selector-split-confidence outcomes against peers with comparable evidence
- a minimum share of the template's selector-split-confidence outcome history coming from those comparable-evidence peers
- align the existing support-kind audit clause with the stricter guard so rationale stays honest
Out of scope:
- changing repo aggregation shape
- widening persisted provenance schema again
- adding a new dashboard panel
- feeding peer disposition directly into primary template scoring outside the selector-split confidence bonus
## What landed
Primary code changes:
- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp`
- added a helper that measures comparable-peer selector-split-confidence evidence from the repo-backed peer disposition buckets
- `BuildTemplateLaunchAnalyticsTieBreakConfidenceBonus(...)` now refuses the bonus unless comparable-peer outcome history is deep enough and large enough as a share of the template's selector-split-confidence history
- peer support-kind disposition resolution now treats insufficient comparable-peer evidence as `PeerLackedComparableEvidence`
- support-kind audit text now explains the comparable-peer evidence requirement and shows counts/share when that guard fails or clears
## Product effect
Template selector confidence is more conservative:
- selector-split confidence reinforcement still requires the template's split-confidence bucket to beat its template-signal bucket
- but that is no longer enough by itself
- the template must also show enough split-confidence wins against peers that brought some comparable evidence, rather than relying mostly on peer-no-evidence lanes
## Acceptance criteria
- selector-split confidence bonus requires minimum comparable-peer outcome count and share
- insufficient comparable-peer evidence suppresses the bonus even when the support-kind split beats the template-signal bucket
- peer disposition and support-kind audit text stay aligned with the stricter guard
- full product build succeeds
## Validation checklist
1. build `UnrealHyperTwist.sln` / `UnrealHyperTwistEditor`
2. confirm selector-split confidence bonus now consults the repo-backed peer disposition buckets
3. confirm insufficient comparable-peer evidence suppresses the bonus
4. confirm support-kind audit text names the comparable-peer count/share requirement when relevant
That is the packet.