Split template analytics by support decision kind
This commit is contained in:
parent
2f4b0afcc4
commit
3cee1031ea
4 changed files with 155 additions and 1 deletions
|
|
@ -121,6 +121,10 @@ namespace HyperTwistCoachDashboardWidgetInternal
|
|||
const FHyperTwistTrainingTemplateLaunchScopedStats* TemplateStats
|
||||
);
|
||||
|
||||
FString BuildTemplateLaunchAnalyticsTieBreakTemplateSignalDecisionSplitFragment(
|
||||
const FHyperTwistTrainingTemplateLaunchScopedStats* TemplateStats
|
||||
);
|
||||
|
||||
FString BuildTemplateLaunchAnalyticsTieBreakTemplateSignalSupportBiasSnapshotFragment(
|
||||
const FHyperTwistTrainingTemplateLaunchScopedStats* TemplateStats
|
||||
);
|
||||
|
|
@ -221,7 +225,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 support %s | template-signal support-bias snapshot %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 decision %s | template-signal support-bias snapshot %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,
|
||||
|
|
@ -236,6 +240,8 @@ namespace HyperTwistCoachDashboardWidgetInternal
|
|||
*BuildTemplateLaunchSelectionSplitAnalyticsFragment(TemplateStats),
|
||||
*BuildTemplateLaunchAnalyticsTieBreakSupportSplitFragment(TemplateStats),
|
||||
*BuildTemplateLaunchAnalyticsTieBreakTemplateSignalSupportSplitFragment(TemplateStats),
|
||||
*BuildTemplateLaunchAnalyticsTieBreakTemplateSignalDecisionSplitFragment(
|
||||
TemplateStats),
|
||||
*BuildTemplateLaunchAnalyticsTieBreakTemplateSignalSupportBiasSnapshotFragment(
|
||||
TemplateStats),
|
||||
*BuildTemplateLaunchAnalyticsTieBreakTemplateSignalConfidenceSnapshotFragment(
|
||||
|
|
@ -766,6 +772,52 @@ namespace HyperTwistCoachDashboardWidgetInternal
|
|||
return Fragment;
|
||||
}
|
||||
|
||||
FString BuildTemplateLaunchAnalyticsTieBreakTemplateSignalDecisionSplitFragment(
|
||||
const FHyperTwistTrainingTemplateLaunchScopedStats* TemplateStats
|
||||
)
|
||||
{
|
||||
if (TemplateStats == nullptr || !TemplateStats->IsStructurallyValid())
|
||||
{
|
||||
return TEXT("no template-signal decision split is available for this template id yet");
|
||||
}
|
||||
|
||||
const FHyperTwistTrainingTemplateLaunchSelectionScopedStats& NoSnapshotGuardStats =
|
||||
TemplateStats
|
||||
->DashboardAnalyticsTieBreakTemplateScopedSignalNoSupportBiasSnapshotGuardStats;
|
||||
const FHyperTwistTrainingTemplateLaunchSelectionScopedStats& SnapshotGuardStats =
|
||||
TemplateStats
|
||||
->DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardStats;
|
||||
if (!NoSnapshotGuardStats.IsStructurallyValid()
|
||||
&& !SnapshotGuardStats.IsStructurallyValid())
|
||||
{
|
||||
return TEXT("no template-signal decision split is available for this template id yet");
|
||||
}
|
||||
|
||||
FString Fragment = FString::Printf(
|
||||
TEXT("%s | %s"),
|
||||
*BuildTemplateLaunchSelectionLaneAnalyticsSummary(
|
||||
NoSnapshotGuardStats,
|
||||
TEXT("no-snapshot-guard")),
|
||||
*BuildTemplateLaunchSelectionLaneAnalyticsSummary(
|
||||
SnapshotGuardStats,
|
||||
TEXT("support-bias-snapshot-guard"))
|
||||
);
|
||||
if (NoSnapshotGuardStats.IsStructurallyValid()
|
||||
&& SnapshotGuardStats.IsStructurallyValid()
|
||||
&& NoSnapshotGuardStats.GetOutcomeRunCount() > 0
|
||||
&& SnapshotGuardStats.GetOutcomeRunCount() > 0)
|
||||
{
|
||||
Fragment += FString::Printf(
|
||||
TEXT(" | snapshot-guard-minus-no-guard delta success %+.2f | delta mistakes %+.2f"),
|
||||
SnapshotGuardStats.OverallSuccessRate - NoSnapshotGuardStats.OverallSuccessRate,
|
||||
SnapshotGuardStats.AverageMistakesPerOutcomeRun
|
||||
- NoSnapshotGuardStats.AverageMistakesPerOutcomeRun
|
||||
);
|
||||
}
|
||||
|
||||
return Fragment;
|
||||
}
|
||||
|
||||
FString BuildTemplateLaunchAnalyticsTieBreakTemplateSignalSupportBiasSnapshotFragment(
|
||||
const FHyperTwistTrainingTemplateLaunchScopedStats* TemplateStats
|
||||
)
|
||||
|
|
|
|||
|
|
@ -9166,6 +9166,10 @@ UHyperTwistTrainingRepositoryLibrary::ListTemplateLaunchScopedStatsForUser(
|
|||
DashboardAnalyticsTieBreakTemplateScopedSignalBroaderOutcomeOnlyAccumulator;
|
||||
FSelectionScopedAccumulator
|
||||
DashboardAnalyticsTieBreakTemplateScopedSignalConfidenceLaneBiasAccumulator;
|
||||
FSelectionScopedAccumulator
|
||||
DashboardAnalyticsTieBreakTemplateScopedSignalNoSupportBiasSnapshotGuardAccumulator;
|
||||
FSelectionScopedAccumulator
|
||||
DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardAccumulator;
|
||||
FSelectionScopedAccumulator
|
||||
DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotEarnedAccumulator;
|
||||
FSelectionScopedAccumulator
|
||||
|
|
@ -9359,6 +9363,24 @@ UHyperTwistTrainingRepositoryLibrary::ListTemplateLaunchScopedStatsForUser(
|
|||
Provenance.SelectionProvenance
|
||||
);
|
||||
}
|
||||
if (Provenance.SelectionProvenance.TemplateSignalSupportDecisionKind ==
|
||||
EHyperTwistTrainingTemplateLaunchSelectionTemplateSignalSupportDecisionKind::
|
||||
SupportBiasSnapshotGuard)
|
||||
{
|
||||
AccumulateSelectionScopedStats(
|
||||
Accumulator
|
||||
.DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardAccumulator,
|
||||
Provenance.SelectionProvenance
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
AccumulateSelectionScopedStats(
|
||||
Accumulator
|
||||
.DashboardAnalyticsTieBreakTemplateScopedSignalNoSupportBiasSnapshotGuardAccumulator,
|
||||
Provenance.SelectionProvenance
|
||||
);
|
||||
}
|
||||
const EHyperTwistTrainingTemplateLaunchTemplateSignalSupportBiasSnapshotState
|
||||
SupportBiasSnapshotState =
|
||||
Provenance.SelectionProvenance.TemplateSignalSupportBiasSnapshot.State;
|
||||
|
|
@ -9564,6 +9586,14 @@ UHyperTwistTrainingRepositoryLibrary::ListTemplateLaunchScopedStatsForUser(
|
|||
Accumulator
|
||||
.DashboardAnalyticsTieBreakTemplateScopedSignalConfidenceLaneBiasAccumulator
|
||||
);
|
||||
FinalizeSelectionScopedAccumulator(
|
||||
Accumulator
|
||||
.DashboardAnalyticsTieBreakTemplateScopedSignalNoSupportBiasSnapshotGuardAccumulator
|
||||
);
|
||||
FinalizeSelectionScopedAccumulator(
|
||||
Accumulator
|
||||
.DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardAccumulator
|
||||
);
|
||||
FinalizeSelectionScopedAccumulator(
|
||||
Accumulator
|
||||
.DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotEarnedAccumulator
|
||||
|
|
@ -9620,6 +9650,14 @@ UHyperTwistTrainingRepositoryLibrary::ListTemplateLaunchScopedStatsForUser(
|
|||
Accumulator.DashboardAnalyticsTieBreakTemplateScopedSignalConfidenceLaneBiasAccumulator
|
||||
.Stats.PeerSupportKindDisposition =
|
||||
EHyperTwistTrainingTemplateLaunchSelectionPeerSupportKindDisposition::None;
|
||||
Accumulator
|
||||
.DashboardAnalyticsTieBreakTemplateScopedSignalNoSupportBiasSnapshotGuardAccumulator
|
||||
.Stats.PeerSupportKindDisposition =
|
||||
EHyperTwistTrainingTemplateLaunchSelectionPeerSupportKindDisposition::None;
|
||||
Accumulator
|
||||
.DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardAccumulator
|
||||
.Stats.PeerSupportKindDisposition =
|
||||
EHyperTwistTrainingTemplateLaunchSelectionPeerSupportKindDisposition::None;
|
||||
Accumulator
|
||||
.DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotEarnedAccumulator
|
||||
.Stats.PeerSupportKindDisposition =
|
||||
|
|
@ -9660,6 +9698,16 @@ UHyperTwistTrainingRepositoryLibrary::ListTemplateLaunchScopedStatsForUser(
|
|||
Accumulator
|
||||
.DashboardAnalyticsTieBreakTemplateScopedSignalConfidenceLaneBiasAccumulator
|
||||
.Stats;
|
||||
Accumulator.Stats
|
||||
.DashboardAnalyticsTieBreakTemplateScopedSignalNoSupportBiasSnapshotGuardStats =
|
||||
Accumulator
|
||||
.DashboardAnalyticsTieBreakTemplateScopedSignalNoSupportBiasSnapshotGuardAccumulator
|
||||
.Stats;
|
||||
Accumulator.Stats
|
||||
.DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardStats =
|
||||
Accumulator
|
||||
.DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardAccumulator
|
||||
.Stats;
|
||||
Accumulator.Stats
|
||||
.DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotEarnedStats =
|
||||
Accumulator
|
||||
|
|
|
|||
|
|
@ -2311,6 +2311,14 @@ struct FHyperTwistTrainingTemplateLaunchScopedStats
|
|||
FHyperTwistTrainingTemplateLaunchSelectionScopedStats
|
||||
DashboardAnalyticsTieBreakTemplateScopedSignalConfidenceLaneBiasStats;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FHyperTwistTrainingTemplateLaunchSelectionScopedStats
|
||||
DashboardAnalyticsTieBreakTemplateScopedSignalNoSupportBiasSnapshotGuardStats;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FHyperTwistTrainingTemplateLaunchSelectionScopedStats
|
||||
DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardStats;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FHyperTwistTrainingTemplateLaunchSelectionScopedStats
|
||||
DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotEarnedStats;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
# HyperTwist Phase 4 template-signal decision split analytics packet
|
||||
|
||||
## Purpose
|
||||
|
||||
This packet aggregates the newly persisted template-signal support decision kind back into repo-backed template analytics. The dashboard can now compare broader template-signal launches that did not need the historical support-bias snapshot guard against launches where that guard explicitly decided the winner.
|
||||
|
||||
## Scope
|
||||
|
||||
- add repo-backed template-scoped stats buckets for broader template-signal launches with and without the `SupportBiasSnapshotGuard` decision
|
||||
- route stored `TemplateSignalSupportDecisionKind` through template launch scoped analytics derivation
|
||||
- append a shared `template-signal decision` analytics fragment so the live dashboard launch row, template history, and recap all expose the new split
|
||||
- report outcome deltas when both decision lanes have meaningful outcome history
|
||||
|
||||
## What landed
|
||||
|
||||
- `HyperTwistTrainingTypes.h`
|
||||
- added `DashboardAnalyticsTieBreakTemplateScopedSignalNoSupportBiasSnapshotGuardStats`
|
||||
- added `DashboardAnalyticsTieBreakTemplateScopedSignalSupportBiasSnapshotGuardStats`
|
||||
- `HyperTwistTrainingRepositoryLibrary.cpp`
|
||||
- added matching scoped accumulators
|
||||
- broader `TemplateScopedOutcomeSignal` runs with `TemplateSignalSupportDecisionKind = SupportBiasSnapshotGuard` now flow into the guard bucket
|
||||
- all other broader template-signal runs, including older records with no retained decision kind, flow into the `no-support-bias-snapshot-guard` bucket
|
||||
- `HyperTwistCoachDashboardWidget.cpp`
|
||||
- added `BuildTemplateLaunchAnalyticsTieBreakTemplateSignalDecisionSplitFragment(...)`
|
||||
- shared analytics detail now appends `template-signal decision ...`
|
||||
- decision split shows both lanes plus `snapshot-guard-minus-no-guard` success and mistake deltas when both lanes have outcome history
|
||||
|
||||
## Product effect
|
||||
|
||||
- operators can now see whether broader template-signal launches that were explicitly decided by the historical support-bias snapshot guard are outperforming the broader template-signal launches that were selected without that guard
|
||||
- template launch history and recap inherit the same decision split automatically because they already reuse the shared analytics detail formatter
|
||||
- older runs remain analyzable without migration because missing decision-kind provenance is treated as `no-snapshot-guard`
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- repo-backed template launch scoped stats retain separate broader template-signal buckets for `SupportBiasSnapshotGuard` and `no-snapshot-guard`
|
||||
- shared dashboard analytics detail renders the new `template-signal decision` fragment anywhere template launch analytics are shown
|
||||
- decision split deltas appear only when both decision lanes have outcome history
|
||||
- older runs without retained `TemplateSignalSupportDecisionKind` continue to participate in analytics through the `no-snapshot-guard` bucket
|
||||
|
||||
## Validation checklist
|
||||
|
||||
1. full `Development Editor|Win64` build succeeds
|
||||
2. confirm template launch scoped analytics route stored `TemplateSignalSupportDecisionKind = SupportBiasSnapshotGuard` into the new guard bucket
|
||||
3. confirm shared analytics detail shows `template-signal decision no-snapshot-guard ... | support-bias-snapshot-guard ...`
|
||||
4. confirm older broader template-signal runs without retained decision kind still surface under `no-snapshot-guard`
|
||||
Loading…
Add table
Reference in a new issue