From dc93432f7663683269e6d47010dbe93ef557674c Mon Sep 17 00:00:00 2001 From: axiomlogicnexus Date: Thu, 7 May 2026 15:31:45 +0200 Subject: [PATCH] Persist template decision-bias snapshot provenance --- .../HyperTwistCoachDashboardWidget.cpp | 77 +++++++++++++++++++ .../HyperTwistTrainingTypes.h | 36 +++++++++ ...S_SNAPSHOT_PROVENANCE_PACKET_2026-05-07.md | 42 ++++++++++ 3 files changed, 155 insertions(+) create mode 100644 docs/arch/HYPERTWIST_PHASE4_TEMPLATE_SIGNAL_DECISION_BIAS_SNAPSHOT_PROVENANCE_PACKET_2026-05-07.md diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp index 4f97fe1..ffc0cb4 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp @@ -151,6 +151,11 @@ namespace HyperTwistCoachDashboardWidgetInternal const FHyperTwistTrainingTemplateLaunchScopedStats* TemplateStats ); + FHyperTwistTrainingTemplateLaunchTemplateSignalSupportDecisionBiasSnapshot + BuildTemplateLaunchTemplateSignalSupportDecisionBiasSnapshot( + const FHyperTwistTrainingTemplateLaunchScopedStats* TemplateStats + ); + FString BuildTemplateLaunchComparablePeerConfidenceAuditClause( const FHyperTwistTrainingTemplateLaunchScopedStats* TemplateStats, const TCHAR* SubjectLabel @@ -173,6 +178,10 @@ namespace HyperTwistCoachDashboardWidgetInternal const FHyperTwistTrainingTemplateLaunchSelectionProvenance* SelectionProvenance ); + FString BuildTemplateLaunchSelectionTemplateSignalSupportDecisionBiasSnapshotDetailFragment( + const FHyperTwistTrainingTemplateLaunchSelectionProvenance* SelectionProvenance + ); + bool HasTemplateLaunchComparablePeerEvidenceForConfidenceBonus( const FHyperTwistTrainingTemplateLaunchScopedStats* TemplateStats, int32* OutComparablePeerOutcomeRuns = nullptr, @@ -502,6 +511,8 @@ namespace HyperTwistCoachDashboardWidgetInternal None; Provenance.TemplateSignalSupportBiasSnapshot = BuildTemplateLaunchTemplateSignalSupportBiasSnapshot(SelectedStats); + Provenance.TemplateSignalSupportDecisionBiasSnapshot = + BuildTemplateLaunchTemplateSignalSupportDecisionBiasSnapshot(SelectedStats); Provenance.ComparablePeerConfidenceSnapshot = BuildTemplateLaunchComparablePeerConfidenceSnapshot(SelectedStats); const FString SelectedComparablePeerConfidenceAuditClause = @@ -1217,6 +1228,25 @@ namespace HyperTwistCoachDashboardWidgetInternal return Snapshot; } + FHyperTwistTrainingTemplateLaunchTemplateSignalSupportDecisionBiasSnapshot + BuildTemplateLaunchTemplateSignalSupportDecisionBiasSnapshot( + const FHyperTwistTrainingTemplateLaunchScopedStats* TemplateStats + ) + { + FHyperTwistTrainingTemplateLaunchTemplateSignalSupportDecisionBiasSnapshot Snapshot; + const bool bBiasEarned = HasTemplateLaunchTemplateSignalSupportDecisionBias( + TemplateStats, + &Snapshot.DecisionSplitGuardOutcomeRuns, + &Snapshot.PlainSnapshotGuardOutcomeRuns + ); + Snapshot.State = bBiasEarned + ? EHyperTwistTrainingTemplateLaunchTemplateSignalSupportDecisionBiasSnapshotState:: + Earned + : EHyperTwistTrainingTemplateLaunchTemplateSignalSupportDecisionBiasSnapshotState:: + Suppressed; + return Snapshot; + } + FString BuildTemplateLaunchComparablePeerConfidenceStatusClauseFromSnapshot( const FHyperTwistTrainingTemplateLaunchComparablePeerConfidenceSnapshot& Snapshot ) @@ -1425,6 +1455,49 @@ namespace HyperTwistCoachDashboardWidgetInternal } } + FString BuildTemplateLaunchSelectionTemplateSignalSupportDecisionBiasSnapshotDetailFragment( + const FHyperTwistTrainingTemplateLaunchSelectionProvenance* SelectionProvenance + ) + { + if (SelectionProvenance == nullptr + || SelectionProvenance->ReasonClass + != EHyperTwistTrainingTemplateLaunchSelectionReasonClass::AnalyticsTieBreak + || SelectionProvenance->AnalyticsSupportKind + != EHyperTwistTrainingTemplateLaunchSelectionAnalyticsSupportKind:: + TemplateScopedOutcomeSignal + || !SelectionProvenance->TemplateSignalSupportDecisionBiasSnapshot + .IsStructurallyValid()) + { + return FString(); + } + + const FHyperTwistTrainingTemplateLaunchTemplateSignalSupportDecisionBiasSnapshot& + Snapshot = SelectionProvenance->TemplateSignalSupportDecisionBiasSnapshot; + switch (Snapshot.State) + { + case EHyperTwistTrainingTemplateLaunchTemplateSignalSupportDecisionBiasSnapshotState:: + Earned: + return FString::Printf( + TEXT( + " | at-launch decision-bias earned on reinforced snapshot-guard history (%d reinforced outcomes vs %d plain outcomes)"), + Snapshot.DecisionSplitGuardOutcomeRuns, + Snapshot.PlainSnapshotGuardOutcomeRuns + ); + case EHyperTwistTrainingTemplateLaunchTemplateSignalSupportDecisionBiasSnapshotState:: + Suppressed: + return FString::Printf( + TEXT( + " | at-launch decision-bias suppressed (%d reinforced outcomes vs %d plain outcomes)"), + Snapshot.DecisionSplitGuardOutcomeRuns, + Snapshot.PlainSnapshotGuardOutcomeRuns + ); + case EHyperTwistTrainingTemplateLaunchTemplateSignalSupportDecisionBiasSnapshotState:: + None: + default: + return FString(); + } + } + FString BuildTemplateLaunchSelectionComparablePeerConfidenceDetailFragment( const FHyperTwistTrainingTemplateLaunchSelectionProvenance* SelectionProvenance ) @@ -1497,6 +1570,9 @@ namespace HyperTwistCoachDashboardWidgetInternal const FString TemplateSignalSupportDecisionBiasDetailFragment = BuildTemplateLaunchSelectionTemplateSignalSupportDecisionBiasDetailFragment( SelectionProvenance); + const FString TemplateSignalSupportDecisionBiasSnapshotDetailFragment = + BuildTemplateLaunchSelectionTemplateSignalSupportDecisionBiasSnapshotDetailFragment( + SelectionProvenance); const FString TemplateSignalSupportBiasDetailFragment = BuildTemplateLaunchSelectionTemplateSignalSupportBiasDetailFragment( SelectionProvenance); @@ -1509,6 +1585,7 @@ namespace HyperTwistCoachDashboardWidgetInternal AnalyticsSupportDetailFragment + TemplateSignalSupportDetailFragment + TemplateSignalSupportDecisionDetailFragment + TemplateSignalSupportDecisionBiasDetailFragment + + TemplateSignalSupportDecisionBiasSnapshotDetailFragment + TemplateSignalSupportBiasDetailFragment + PeerSupportDispositionDetailFragment + ComparablePeerConfidenceDetailFragment; diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h index 4625add..0ed66b0 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h @@ -1105,6 +1105,15 @@ enum class EHyperTwistTrainingTemplateLaunchSelectionTemplateSignalSupportDecisi DecisionSplitGuard UMETA(DisplayName = "Decision Split Guard") }; +UENUM(BlueprintType) +enum class EHyperTwistTrainingTemplateLaunchTemplateSignalSupportDecisionBiasSnapshotState : + uint8 +{ + None UMETA(DisplayName = "None"), + Earned UMETA(DisplayName = "Earned"), + Suppressed UMETA(DisplayName = "Suppressed") +}; + UENUM(BlueprintType) enum class EHyperTwistTrainingTemplateLaunchComparablePeerConfidenceSnapshotState : uint8 { @@ -1163,6 +1172,29 @@ struct FHyperTwistTrainingTemplateLaunchComparablePeerConfidenceSnapshot } }; +USTRUCT(BlueprintType) +struct FHyperTwistTrainingTemplateLaunchTemplateSignalSupportDecisionBiasSnapshot +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + EHyperTwistTrainingTemplateLaunchTemplateSignalSupportDecisionBiasSnapshotState State = + EHyperTwistTrainingTemplateLaunchTemplateSignalSupportDecisionBiasSnapshotState::None; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 DecisionSplitGuardOutcomeRuns = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 PlainSnapshotGuardOutcomeRuns = 0; + + bool IsStructurallyValid() const + { + return State + != EHyperTwistTrainingTemplateLaunchTemplateSignalSupportDecisionBiasSnapshotState:: + None; + } +}; + USTRUCT(BlueprintType) struct FHyperTwistTrainingTemplateLaunchSelectionProvenance { @@ -1203,6 +1235,10 @@ struct FHyperTwistTrainingTemplateLaunchSelectionProvenance FHyperTwistTrainingTemplateLaunchTemplateSignalSupportBiasSnapshot TemplateSignalSupportBiasSnapshot; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FHyperTwistTrainingTemplateLaunchTemplateSignalSupportDecisionBiasSnapshot + TemplateSignalSupportDecisionBiasSnapshot; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") FHyperTwistTrainingTemplateLaunchComparablePeerConfidenceSnapshot ComparablePeerConfidenceSnapshot; diff --git a/docs/arch/HYPERTWIST_PHASE4_TEMPLATE_SIGNAL_DECISION_BIAS_SNAPSHOT_PROVENANCE_PACKET_2026-05-07.md b/docs/arch/HYPERTWIST_PHASE4_TEMPLATE_SIGNAL_DECISION_BIAS_SNAPSHOT_PROVENANCE_PACKET_2026-05-07.md new file mode 100644 index 0000000..265574d --- /dev/null +++ b/docs/arch/HYPERTWIST_PHASE4_TEMPLATE_SIGNAL_DECISION_BIAS_SNAPSHOT_PROVENANCE_PACKET_2026-05-07.md @@ -0,0 +1,42 @@ +# HyperTwist Phase 4 template-signal decision-bias snapshot provenance packet + +## Purpose + +This packet stops template launch history and recap from recomputing the stricter template-signal decision-bias guard from whatever reinforced-vs-plain snapshot-guard analytics happen to exist later. It stores the dashboard's at-launch `decision-bias earned/suppressed` state directly in template selection provenance and reuses that retained snapshot when rendering selector detail. + +## Scope + +- add a persisted template-signal decision-bias snapshot to launch selection provenance +- stamp that snapshot whenever a broader `TemplateScopedOutcomeSignal` analytics tie-break builds selection provenance +- append the stored at-launch decision-bias snapshot to the shared selector-detail path used by dashboard template history and template-backed recap + +## What landed + +- `HyperTwistTrainingTypes.h` + - added `EHyperTwistTrainingTemplateLaunchTemplateSignalSupportDecisionBiasSnapshotState` + - added `FHyperTwistTrainingTemplateLaunchTemplateSignalSupportDecisionBiasSnapshot` + - added `TemplateSignalSupportDecisionBiasSnapshot` to `FHyperTwistTrainingTemplateLaunchSelectionProvenance` +- `HyperTwistCoachDashboardWidget.cpp` + - added `BuildTemplateLaunchTemplateSignalSupportDecisionBiasSnapshot(...)` + - broader analytics selection provenance now stamps the current `decision-bias earned/suppressed` state with reinforced and plain snapshot-guard outcome counts + - shared selector detail now renders: + - `at-launch decision-bias earned ...` + - or `at-launch decision-bias suppressed ...` + +## Product effect + +- template launch history and recap now preserve the dashboard's at-launch decision-bias posture instead of drifting with later reinforced-vs-plain snapshot-guard analytics +- selector audits can distinguish the persisted at-launch decision-bias state from the separately persisted `DecisionSplitGuard` winner-reason flag + +## Acceptance criteria + +- broader `TemplateScopedOutcomeSignal` selection provenance stores an at-launch decision-bias snapshot +- template launch history and recap read that stored snapshot back through shared selector detail +- the new selector detail uses retained reinforced vs plain snapshot-guard counts instead of recomputing them from current analytics + +## Validation checklist + +1. full `Development Editor|Win64` build succeeds +2. confirm `FHyperTwistTrainingTemplateLaunchSelectionProvenance` persists `TemplateSignalSupportDecisionBiasSnapshot` +3. confirm broader analytics provenance stamping calls `BuildTemplateLaunchTemplateSignalSupportDecisionBiasSnapshot(...)` +4. confirm shared selector detail shows `at-launch decision-bias earned ...` or `at-launch decision-bias suppressed ...`