Split template analytics by template-signal support

This commit is contained in:
axiomlogicnexus 2026-05-07 03:22:48 +02:00
parent 67a316e2e2
commit 2f8f392b84
4 changed files with 152 additions and 1 deletions

View file

@ -117,6 +117,10 @@ namespace HyperTwistCoachDashboardWidgetInternal
const FHyperTwistTrainingTemplateLaunchScopedStats* TemplateStats
);
FString BuildTemplateLaunchAnalyticsTieBreakTemplateSignalSupportSplitFragment(
const FHyperTwistTrainingTemplateLaunchScopedStats* TemplateStats
);
FString BuildTemplateLaunchAnalyticsTieBreakTemplateSignalConfidenceSnapshotFragment(
const FHyperTwistTrainingTemplateLaunchScopedStats* TemplateStats
);
@ -192,7 +196,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 | template-signal confidence snapshot %s | peer support split %s | comparable-peer confidence %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 | template-signal support %s | template-signal confidence snapshot %s | peer support split %s | comparable-peer confidence %s | last launch %s | last completed %s"),
TemplateStats->AverageRecommendedCaseCount,
TemplateStats->AverageFocusCaseCount,
TemplateStats->AverageCompletedAttemptCount,
@ -206,6 +210,7 @@ namespace HyperTwistCoachDashboardWidgetInternal
TemplateStats->ShortReviewSetLaunchCount,
*BuildTemplateLaunchSelectionSplitAnalyticsFragment(TemplateStats),
*BuildTemplateLaunchAnalyticsTieBreakSupportSplitFragment(TemplateStats),
*BuildTemplateLaunchAnalyticsTieBreakTemplateSignalSupportSplitFragment(TemplateStats),
*BuildTemplateLaunchAnalyticsTieBreakTemplateSignalConfidenceSnapshotFragment(
TemplateStats),
*BuildTemplateLaunchAnalyticsTieBreakPeerDispositionSplitFragment(TemplateStats),
@ -652,6 +657,51 @@ namespace HyperTwistCoachDashboardWidgetInternal
return Fragment;
}
FString BuildTemplateLaunchAnalyticsTieBreakTemplateSignalSupportSplitFragment(
const FHyperTwistTrainingTemplateLaunchScopedStats* TemplateStats
)
{
if (TemplateStats == nullptr || !TemplateStats->IsStructurallyValid())
{
return TEXT("no template-signal support split is available for this template id yet");
}
const FHyperTwistTrainingTemplateLaunchSelectionScopedStats& BroaderOutcomeOnlyStats =
TemplateStats->DashboardAnalyticsTieBreakTemplateScopedSignalBroaderOutcomeOnlyStats;
const FHyperTwistTrainingTemplateLaunchSelectionScopedStats& ConfidenceLaneBiasStats =
TemplateStats->DashboardAnalyticsTieBreakTemplateScopedSignalConfidenceLaneBiasStats;
if (!BroaderOutcomeOnlyStats.IsStructurallyValid()
&& !ConfidenceLaneBiasStats.IsStructurallyValid())
{
return TEXT("no template-signal support split is available for this template id yet");
}
FString Fragment = FString::Printf(
TEXT("%s | %s"),
*BuildTemplateLaunchSelectionLaneAnalyticsSummary(
BroaderOutcomeOnlyStats,
TEXT("broader-outcome-only")),
*BuildTemplateLaunchSelectionLaneAnalyticsSummary(
ConfidenceLaneBiasStats,
TEXT("confidence-lane-bias"))
);
if (BroaderOutcomeOnlyStats.IsStructurallyValid()
&& ConfidenceLaneBiasStats.IsStructurallyValid()
&& BroaderOutcomeOnlyStats.GetOutcomeRunCount() > 0
&& ConfidenceLaneBiasStats.GetOutcomeRunCount() > 0)
{
Fragment += FString::Printf(
TEXT(" | bias-minus-broader delta success %+.2f | delta mistakes %+.2f"),
ConfidenceLaneBiasStats.OverallSuccessRate
- BroaderOutcomeOnlyStats.OverallSuccessRate,
ConfidenceLaneBiasStats.AverageMistakesPerOutcomeRun
- BroaderOutcomeOnlyStats.AverageMistakesPerOutcomeRun
);
}
return Fragment;
}
FString BuildTemplateLaunchAnalyticsTieBreakPeerDispositionSplitFragment(
const FHyperTwistTrainingTemplateLaunchScopedStats* TemplateStats
)

View file

@ -9162,6 +9162,10 @@ UHyperTwistTrainingRepositoryLibrary::ListTemplateLaunchScopedStatsForUser(
FSelectionScopedAccumulator DashboardPrimarySelectionAccumulator;
FSelectionScopedAccumulator DashboardAnalyticsTieBreakSelectionAccumulator;
FSelectionScopedAccumulator DashboardAnalyticsTieBreakTemplateScopedSignalAccumulator;
FSelectionScopedAccumulator
DashboardAnalyticsTieBreakTemplateScopedSignalBroaderOutcomeOnlyAccumulator;
FSelectionScopedAccumulator
DashboardAnalyticsTieBreakTemplateScopedSignalConfidenceLaneBiasAccumulator;
FSelectionScopedAccumulator
DashboardAnalyticsTieBreakTemplateScopedSignalNoRetainedComparablePeerConfidenceLaneAccumulator;
FSelectionScopedAccumulator
@ -9331,6 +9335,24 @@ UHyperTwistTrainingRepositoryLibrary::ListTemplateLaunchScopedStatsForUser(
Accumulator.DashboardAnalyticsTieBreakTemplateScopedSignalAccumulator,
Provenance.SelectionProvenance
);
if (Provenance.SelectionProvenance.TemplateSignalSupportKind ==
EHyperTwistTrainingTemplateLaunchSelectionTemplateSignalSupportKind::
ConfidenceLaneBias)
{
AccumulateSelectionScopedStats(
Accumulator
.DashboardAnalyticsTieBreakTemplateScopedSignalConfidenceLaneBiasAccumulator,
Provenance.SelectionProvenance
);
}
else
{
AccumulateSelectionScopedStats(
Accumulator
.DashboardAnalyticsTieBreakTemplateScopedSignalBroaderOutcomeOnlyAccumulator,
Provenance.SelectionProvenance
);
}
const EHyperTwistTrainingTemplateLaunchComparablePeerConfidenceSnapshotState
SnapshotState =
Provenance.SelectionProvenance.ComparablePeerConfidenceSnapshot.State;
@ -9498,6 +9520,14 @@ UHyperTwistTrainingRepositoryLibrary::ListTemplateLaunchScopedStatsForUser(
FinalizeSelectionScopedAccumulator(
Accumulator.DashboardAnalyticsTieBreakTemplateScopedSignalAccumulator
);
FinalizeSelectionScopedAccumulator(
Accumulator
.DashboardAnalyticsTieBreakTemplateScopedSignalBroaderOutcomeOnlyAccumulator
);
FinalizeSelectionScopedAccumulator(
Accumulator
.DashboardAnalyticsTieBreakTemplateScopedSignalConfidenceLaneBiasAccumulator
);
FinalizeSelectionScopedAccumulator(
Accumulator
.DashboardAnalyticsTieBreakTemplateScopedSignalNoRetainedComparablePeerConfidenceLaneAccumulator
@ -9536,6 +9566,12 @@ UHyperTwistTrainingRepositoryLibrary::ListTemplateLaunchScopedStatsForUser(
Accumulator.DashboardAnalyticsTieBreakTemplateScopedSignalAccumulator.Stats
.PeerSupportKindDisposition =
EHyperTwistTrainingTemplateLaunchSelectionPeerSupportKindDisposition::None;
Accumulator.DashboardAnalyticsTieBreakTemplateScopedSignalBroaderOutcomeOnlyAccumulator
.Stats.PeerSupportKindDisposition =
EHyperTwistTrainingTemplateLaunchSelectionPeerSupportKindDisposition::None;
Accumulator.DashboardAnalyticsTieBreakTemplateScopedSignalConfidenceLaneBiasAccumulator
.Stats.PeerSupportKindDisposition =
EHyperTwistTrainingTemplateLaunchSelectionPeerSupportKindDisposition::None;
Accumulator
.DashboardAnalyticsTieBreakTemplateScopedSignalNoRetainedComparablePeerConfidenceLaneAccumulator
.Stats.PeerSupportKindDisposition =
@ -9556,6 +9592,14 @@ UHyperTwistTrainingRepositoryLibrary::ListTemplateLaunchScopedStatsForUser(
Accumulator.DashboardAnalyticsTieBreakSelectionAccumulator.Stats;
Accumulator.Stats.DashboardAnalyticsTieBreakTemplateScopedSignalStats =
Accumulator.DashboardAnalyticsTieBreakTemplateScopedSignalAccumulator.Stats;
Accumulator.Stats.DashboardAnalyticsTieBreakTemplateScopedSignalBroaderOutcomeOnlyStats =
Accumulator
.DashboardAnalyticsTieBreakTemplateScopedSignalBroaderOutcomeOnlyAccumulator
.Stats;
Accumulator.Stats.DashboardAnalyticsTieBreakTemplateScopedSignalConfidenceLaneBiasStats =
Accumulator
.DashboardAnalyticsTieBreakTemplateScopedSignalConfidenceLaneBiasAccumulator
.Stats;
Accumulator.Stats
.DashboardAnalyticsTieBreakTemplateScopedSignalNoRetainedComparablePeerConfidenceLaneStats =
Accumulator

View file

@ -2258,6 +2258,14 @@ struct FHyperTwistTrainingTemplateLaunchScopedStats
FHyperTwistTrainingTemplateLaunchSelectionScopedStats
DashboardAnalyticsTieBreakTemplateScopedSignalStats;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FHyperTwistTrainingTemplateLaunchSelectionScopedStats
DashboardAnalyticsTieBreakTemplateScopedSignalBroaderOutcomeOnlyStats;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FHyperTwistTrainingTemplateLaunchSelectionScopedStats
DashboardAnalyticsTieBreakTemplateScopedSignalConfidenceLaneBiasStats;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FHyperTwistTrainingTemplateLaunchSelectionScopedStats
DashboardAnalyticsTieBreakTemplateScopedSignalNoRetainedComparablePeerConfidenceLaneStats;

View file

@ -0,0 +1,49 @@
# HyperTwist Phase 4 template-signal support split analytics packet
## Purpose
This packet pushes the persisted broader `TemplateScopedOutcomeSignal` support kind back into repo-backed template analytics. The dashboard can now separate broader analytics wins that were plain `broader-outcome-only` launches from wins where the `confidence-lane-bias` actually broke the tie, which makes it measurable whether that bias is improving outcomes or just resolving equality.
## Scope
- add repo-backed template analytics buckets for broader template-signal launches split by:
- `broader-outcome-only`
- `confidence-lane-bias`
- treat older broader template-signal launches with no retained support kind as `broader-outcome-only`
- surface the new split through the shared template analytics detail used by live detail, template history, and recap
- show success and mistake deltas when both support buckets have outcome history
## What landed
- `HyperTwistTrainingTypes.h`
- added `DashboardAnalyticsTieBreakTemplateScopedSignalBroaderOutcomeOnlyStats`
- added `DashboardAnalyticsTieBreakTemplateScopedSignalConfidenceLaneBiasStats`
- `HyperTwistTrainingRepositoryLibrary.cpp`
- widened the template launch scoped stats accumulator with matching broader template-signal support buckets
- routes `TemplateScopedOutcomeSignal` launches with:
- `confidence-lane-bias` into the confidence-lane-bias bucket
- `broader-outcome-only` or missing legacy support kind into the broader-outcome-only bucket
- finalizes and persists both new buckets into repo-backed template analytics
- `HyperTwistCoachDashboardWidget.cpp`
- added `BuildTemplateLaunchAnalyticsTieBreakTemplateSignalSupportSplitFragment(...)`
- shared analytics detail now appends a `template-signal support` section showing both support buckets plus `bias-minus-broader` deltas when both lanes have outcome runs
## Product effect
- live `[Template Launch]` detail now shows whether stored broader analytics outcomes are concentrated in plain broader-outcome wins or confidence-lane-bias wins
- template launch history and recap inherit that same repo-backed split automatically through the shared analytics formatter
- operators can now inspect whether the confidence-lane bias is actually outperforming plain broader template-signal tie-breaks
## Acceptance criteria
- repo-backed template analytics persist separate broader template-signal buckets for `broader-outcome-only` and `confidence-lane-bias`
- legacy broader template-signal launches without retained support kind fold into `broader-outcome-only`
- shared analytics detail shows both support buckets
- when both support buckets have outcome history, shared analytics detail reports `bias-minus-broader` success and mistake deltas
## Validation checklist
1. full `Development Editor|Win64` build succeeds
2. confirm repository analytics route `confidence-lane-bias` and `broader-outcome-only` launches into separate buckets
3. confirm legacy runs with no support kind still appear under `broader-outcome-only`
4. confirm live detail, template history, and recap all show the new `template-signal support` split through shared analytics detail