Split template analytics by decision-bias kind

This commit is contained in:
axiomlogicnexus 2026-05-07 04:49:26 +02:00
parent 23ff059aca
commit 2300045f63
4 changed files with 132 additions and 0 deletions

View file

@ -867,6 +867,36 @@ namespace HyperTwistCoachDashboardWidgetInternal
SnapshotGuardOutcomeRuns,
NoSnapshotGuardOutcomeRuns
);
const FHyperTwistTrainingTemplateLaunchSelectionScopedStats& PlainSnapshotGuardStats =
TemplateStats
->DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardNoDecisionBiasStats;
const FHyperTwistTrainingTemplateLaunchSelectionScopedStats& DecisionSplitGuardStats =
TemplateStats
->DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardDecisionSplitGuardStats;
if (PlainSnapshotGuardStats.IsStructurallyValid()
|| DecisionSplitGuardStats.IsStructurallyValid())
{
Fragment += FString::Printf(
TEXT(" | %s | %s"),
*BuildTemplateLaunchSelectionLaneAnalyticsSummary(
PlainSnapshotGuardStats,
TEXT("plain-snapshot-guard")),
*BuildTemplateLaunchSelectionLaneAnalyticsSummary(
DecisionSplitGuardStats,
TEXT("decision-split-guard"))
);
if (PlainSnapshotGuardStats.GetOutcomeRunCount() > 0
&& DecisionSplitGuardStats.GetOutcomeRunCount() > 0)
{
Fragment += FString::Printf(
TEXT(" | decision-split-minus-plain delta success %+.2f | delta mistakes %+.2f"),
DecisionSplitGuardStats.OverallSuccessRate
- PlainSnapshotGuardStats.OverallSuccessRate,
DecisionSplitGuardStats.AverageMistakesPerOutcomeRun
- PlainSnapshotGuardStats.AverageMistakesPerOutcomeRun
);
}
}
return Fragment;
}

View file

@ -9170,6 +9170,10 @@ UHyperTwistTrainingRepositoryLibrary::ListTemplateLaunchScopedStatsForUser(
DashboardAnalyticsTieBreakTemplateScopedSignalNoSupportBiasSnapshotGuardAccumulator;
FSelectionScopedAccumulator
DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardAccumulator;
FSelectionScopedAccumulator
DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardNoDecisionBiasAccumulator;
FSelectionScopedAccumulator
DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardDecisionSplitGuardAccumulator;
FSelectionScopedAccumulator
DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotEarnedAccumulator;
FSelectionScopedAccumulator
@ -9372,6 +9376,24 @@ UHyperTwistTrainingRepositoryLibrary::ListTemplateLaunchScopedStatsForUser(
.DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardAccumulator,
Provenance.SelectionProvenance
);
if (Provenance.SelectionProvenance.TemplateSignalSupportDecisionBiasKind ==
EHyperTwistTrainingTemplateLaunchSelectionTemplateSignalSupportDecisionBiasKind::
DecisionSplitGuard)
{
AccumulateSelectionScopedStats(
Accumulator
.DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardDecisionSplitGuardAccumulator,
Provenance.SelectionProvenance
);
}
else
{
AccumulateSelectionScopedStats(
Accumulator
.DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardNoDecisionBiasAccumulator,
Provenance.SelectionProvenance
);
}
}
else
{
@ -9594,6 +9616,14 @@ UHyperTwistTrainingRepositoryLibrary::ListTemplateLaunchScopedStatsForUser(
Accumulator
.DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardAccumulator
);
FinalizeSelectionScopedAccumulator(
Accumulator
.DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardNoDecisionBiasAccumulator
);
FinalizeSelectionScopedAccumulator(
Accumulator
.DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardDecisionSplitGuardAccumulator
);
FinalizeSelectionScopedAccumulator(
Accumulator
.DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotEarnedAccumulator
@ -9658,6 +9688,14 @@ UHyperTwistTrainingRepositoryLibrary::ListTemplateLaunchScopedStatsForUser(
.DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardAccumulator
.Stats.PeerSupportKindDisposition =
EHyperTwistTrainingTemplateLaunchSelectionPeerSupportKindDisposition::None;
Accumulator
.DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardNoDecisionBiasAccumulator
.Stats.PeerSupportKindDisposition =
EHyperTwistTrainingTemplateLaunchSelectionPeerSupportKindDisposition::None;
Accumulator
.DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardDecisionSplitGuardAccumulator
.Stats.PeerSupportKindDisposition =
EHyperTwistTrainingTemplateLaunchSelectionPeerSupportKindDisposition::None;
Accumulator
.DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotEarnedAccumulator
.Stats.PeerSupportKindDisposition =
@ -9708,6 +9746,16 @@ UHyperTwistTrainingRepositoryLibrary::ListTemplateLaunchScopedStatsForUser(
Accumulator
.DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardAccumulator
.Stats;
Accumulator.Stats
.DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardNoDecisionBiasStats =
Accumulator
.DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardNoDecisionBiasAccumulator
.Stats;
Accumulator.Stats
.DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardDecisionSplitGuardStats =
Accumulator
.DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardDecisionSplitGuardAccumulator
.Stats;
Accumulator.Stats
.DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotEarnedStats =
Accumulator

View file

@ -2332,6 +2332,14 @@ struct FHyperTwistTrainingTemplateLaunchScopedStats
FHyperTwistTrainingTemplateLaunchSelectionScopedStats
DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardStats;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FHyperTwistTrainingTemplateLaunchSelectionScopedStats
DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardNoDecisionBiasStats;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FHyperTwistTrainingTemplateLaunchSelectionScopedStats
DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardDecisionSplitGuardStats;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FHyperTwistTrainingTemplateLaunchSelectionScopedStats
DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotEarnedStats;

View file

@ -0,0 +1,46 @@
# HyperTwist Phase 4 template-signal decision-bias analytics packet
## Purpose
This packet aggregates the newly persisted template-signal decision-bias provenance back into repo-backed template analytics. The dashboard can now compare plain `SupportBiasSnapshotGuard` launches against the stricter `DecisionSplitGuard`-reinforced subset instead of treating every snapshot-guard win as the same lane.
## Scope
- add repo-backed template-scoped stats buckets for `SupportBiasSnapshotGuard` runs with and without the persisted `DecisionSplitGuard` bias marker
- route stored `TemplateSignalSupportDecisionBiasKind` through template launch scoped analytics derivation
- extend the shared `template-signal decision` analytics fragment so live dashboard detail, template history, and recap expose the new nested snapshot-guard split
- report outcome deltas when both plain snapshot-guard and decision-split-guard lanes have outcome history
## What landed
- `HyperTwistTrainingTypes.h`
- added `DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardNoDecisionBiasStats`
- added `DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardDecisionSplitGuardStats`
- `HyperTwistTrainingRepositoryLibrary.cpp`
- added matching scoped accumulators
- `SupportBiasSnapshotGuard` runs with stored `TemplateSignalSupportDecisionBiasKind = DecisionSplitGuard` now flow into the reinforced bucket
- `SupportBiasSnapshotGuard` runs without that retained bias kind, including older records, flow into the plain snapshot-guard bucket
- `HyperTwistCoachDashboardWidget.cpp`
- extended `BuildTemplateLaunchAnalyticsTieBreakTemplateSignalDecisionSplitFragment(...)`
- shared analytics detail now appends plain snapshot-guard vs decision-split-guard lane summaries under the existing decision split
- nested split shows `decision-split-minus-plain` success and mistake deltas when both lanes have outcome history
## Product effect
- operators can now see whether the stricter `DecisionSplitGuard`-reinforced subset of snapshot-guard launches is actually outperforming plain snapshot-guard launches
- template launch history and recap inherit the same nested split automatically because they already reuse the shared analytics detail formatter
- older snapshot-guard runs remain analyzable without migration because missing decision-bias provenance is treated as plain snapshot-guard history
## Acceptance criteria
- repo-backed template launch scoped stats retain separate snapshot-guard buckets for plain wins and `DecisionSplitGuard`-reinforced wins
- shared dashboard analytics detail renders the nested snapshot-guard split anywhere template launch analytics are shown
- nested decision-bias deltas appear only when both snapshot-guard lanes have outcome history
- older snapshot-guard runs without retained `TemplateSignalSupportDecisionBiasKind` continue to participate in analytics through the plain snapshot-guard bucket
## Validation checklist
1. full `Development Editor|Win64` build succeeds
2. confirm scoped analytics route stored `TemplateSignalSupportDecisionBiasKind = DecisionSplitGuard` into the reinforced bucket
3. confirm shared analytics detail shows `plain-snapshot-guard ... | decision-split-guard ...`
4. confirm older snapshot-guard runs without retained decision-bias provenance still surface under `plain-snapshot-guard`