From 9c8c16997640626dd7f7cd61e82b29b21ae6ac1b Mon Sep 17 00:00:00 2001 From: axiomlogicnexus Date: Wed, 6 May 2026 02:51:21 +0200 Subject: [PATCH] Resync coach queue state after brief refinements --- .../HyperTwistTrainingSubsystem.cpp | 167 +++++++++--------- ..._DERIVED_STATE_RESYNC_PACKET_2026-05-06.md | 89 ++++++++++ 2 files changed, 176 insertions(+), 80 deletions(-) create mode 100644 docs/arch/HYPERTWIST_PHASE3_COACH_DERIVED_STATE_RESYNC_PACKET_2026-05-06.md diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSubsystem.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSubsystem.cpp index 2a364f9..5f84650 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSubsystem.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSubsystem.cpp @@ -4058,7 +4058,7 @@ void UHyperTwistTrainingSubsystem::RefreshRepositoryViews() ); ActiveCoachSignals = ActiveCoachBrief.Signals; } - ActiveCoachFollowUpBrief = ActiveCoachActionPlanOutcomeSummary.IsStructurallyValid() + const bool bShouldDeriveCoachFollowUpBrief = ActiveCoachActionPlanOutcomeSummary.IsStructurallyValid() && ( ActiveCoachActionClosureSummary.bShouldSpawnFollowUp || ( @@ -4067,20 +4067,80 @@ void UHyperTwistTrainingSubsystem::RefreshRepositoryViews() && !ActiveCoachActionSequenceSummary.bHasOpenPlan && !ActiveCoachActionClosureSummary.bNeedsEscalation ) - ) - ? UHyperTwistTrainingCoachLibrary::DeriveCoachFollowUpBrief( + ); + const auto RebuildActiveCoachQueueDerivedState = [&]() + { + ActiveCoachFollowUpBrief = bShouldDeriveCoachFollowUpBrief + ? UHyperTwistTrainingCoachLibrary::DeriveCoachFollowUpBrief( + ActiveCoachBrief, + ActiveCoachActionPlan, + ActiveCoachActionPlanOutcomeSummary + ) + : FHyperTwistCoachBrief(); + ActiveCoachSessionQueueSummary = UHyperTwistTrainingCoachLibrary::DeriveCoachSessionQueueSummary( ActiveCoachBrief, - ActiveCoachActionPlan, - ActiveCoachActionPlanOutcomeSummary - ) - : FHyperTwistCoachBrief(); - ActiveCoachSessionQueueSummary = UHyperTwistTrainingCoachLibrary::DeriveCoachSessionQueueSummary( - ActiveCoachBrief, - ActiveCoachFollowUpBrief, - ActiveCoachMemorySnapshot, - ActiveCoachArchivePolicySummary, - ActiveReviewProgramSummary - ); + ActiveCoachFollowUpBrief, + ActiveCoachMemorySnapshot, + ActiveCoachArchivePolicySummary, + ActiveReviewProgramSummary + ); + if (ActiveCoachSessionQueueSummary.IsStructurallyValid()) + { + FHyperTwistTrainingCoachSessionQueueState StoredQueueState; + const bool bHasStoredQueueState = UHyperTwistTrainingRepositoryLibrary::TryGetCoachSessionQueueState( + TrainingRepositoryState, + ActiveCoachSessionQueueSummary.UserId, + HyperTwistTrainingSubsystemInternal::ActiveCoachSessionQueueId, + StoredQueueState + ); + ActiveCoachSessionQueueState = bHasStoredQueueState + ? UHyperTwistTrainingRepositoryLibrary::ResolveCoachSessionQueueState( + StoredQueueState, + ActiveCoachSessionQueueSummary, + ActiveLearnerDeckStateSummary.ReferenceUtc + ) + : UHyperTwistTrainingRepositoryLibrary::BuildCoachSessionQueueState( + ActiveCoachSessionQueueSummary, + HyperTwistTrainingSubsystemInternal::ActiveCoachSessionQueueId, + ActiveLearnerDeckStateSummary.ReferenceUtc + ); + if (ActiveCoachSessionQueueState.IsStructurallyValid()) + { + TrainingRepositoryState = UHyperTwistTrainingRepositoryLibrary::UpsertCoachSessionQueueState( + TrainingRepositoryState, + ActiveCoachSessionQueueState + ); + } + ActiveCoachScheduleHorizonSummary = UHyperTwistTrainingCoachLibrary::DeriveCoachScheduleHorizonSummary( + ActiveCoachSessionQueueState, + ActiveCoachArchivePolicySummary, + ActiveLearnerDeckStateSummary.ReferenceUtc + ); + ActiveCoachSchedulePolicySummary = UHyperTwistTrainingCoachLibrary::DeriveCoachSchedulePolicySummary( + ActiveCoachSessionQueueState, + ActiveCoachScheduleHorizonSummary, + ActiveCoachActionClosureSummary, + ActiveCoachMemorySnapshot, + ActiveCoachArchivePolicySummary, + ActiveLearnerDeckStateSummary.ReferenceUtc + ); + ActiveCoachSessionQueueExecutionSummary = + UHyperTwistTrainingRepositoryLibrary::DeriveCoachSessionQueueExecutionSummary( + TrainingRepositoryState, + ActiveCoachSessionQueueState.UserId, + ActiveCoachSessionQueueState.QueueId, + ActiveLearnerDeckStateSummary.ReferenceUtc + ); + } + else + { + ActiveCoachSessionQueueState = FHyperTwistTrainingCoachSessionQueueState(); + ActiveCoachScheduleHorizonSummary = FHyperTwistCoachScheduleHorizonSummary(); + ActiveCoachSchedulePolicySummary = FHyperTwistCoachSchedulePolicySummary(); + ActiveCoachSessionQueueExecutionSummary = FHyperTwistTrainingCoachSessionQueueExecutionSummary(); + } + }; + RebuildActiveCoachQueueDerivedState(); const FHyperTwistCoachSignal QueueSuppressionSignal = UHyperTwistTrainingCoachLibrary::DeriveQueueSuppressionSignal( ActiveCoachSessionQueueSummary, @@ -4095,76 +4155,23 @@ void UHyperTwistTrainingSubsystem::RefreshRepositoryViews() QueueSuppressionSignal ); ActiveCoachSignals = ActiveCoachBrief.Signals; + RebuildActiveCoachQueueDerivedState(); } - if (ActiveCoachSessionQueueSummary.IsStructurallyValid()) - { - FHyperTwistTrainingCoachSessionQueueState StoredQueueState; - const bool bHasStoredQueueState = UHyperTwistTrainingRepositoryLibrary::TryGetCoachSessionQueueState( - TrainingRepositoryState, - ActiveCoachSessionQueueSummary.UserId, - HyperTwistTrainingSubsystemInternal::ActiveCoachSessionQueueId, - StoredQueueState - ); - ActiveCoachSessionQueueState = bHasStoredQueueState - ? UHyperTwistTrainingRepositoryLibrary::ResolveCoachSessionQueueState( - StoredQueueState, - ActiveCoachSessionQueueSummary, - ActiveLearnerDeckStateSummary.ReferenceUtc - ) - : UHyperTwistTrainingRepositoryLibrary::BuildCoachSessionQueueState( - ActiveCoachSessionQueueSummary, - HyperTwistTrainingSubsystemInternal::ActiveCoachSessionQueueId, - ActiveLearnerDeckStateSummary.ReferenceUtc - ); - if (ActiveCoachSessionQueueState.IsStructurallyValid()) - { - TrainingRepositoryState = UHyperTwistTrainingRepositoryLibrary::UpsertCoachSessionQueueState( - TrainingRepositoryState, - ActiveCoachSessionQueueState - ); - } - ActiveCoachScheduleHorizonSummary = UHyperTwistTrainingCoachLibrary::DeriveCoachScheduleHorizonSummary( - ActiveCoachSessionQueueState, - ActiveCoachArchivePolicySummary, - ActiveLearnerDeckStateSummary.ReferenceUtc - ); - ActiveCoachSchedulePolicySummary = UHyperTwistTrainingCoachLibrary::DeriveCoachSchedulePolicySummary( - ActiveCoachSessionQueueState, - ActiveCoachScheduleHorizonSummary, - ActiveCoachActionClosureSummary, + const FHyperTwistCoachSignal SchedulePolicyFeedbackSignal = + UHyperTwistTrainingCoachLibrary::DeriveSchedulePolicyFeedbackSignal( + ActiveCoachSchedulePolicySummary, + ActiveCoachSessionQueueExecutionSummary, ActiveCoachMemorySnapshot, - ActiveCoachArchivePolicySummary, - ActiveLearnerDeckStateSummary.ReferenceUtc + ActiveCoachBrief ); - ActiveCoachSessionQueueExecutionSummary = - UHyperTwistTrainingRepositoryLibrary::DeriveCoachSessionQueueExecutionSummary( - TrainingRepositoryState, - ActiveCoachSessionQueueState.UserId, - ActiveCoachSessionQueueState.QueueId, - ActiveLearnerDeckStateSummary.ReferenceUtc - ); - const FHyperTwistCoachSignal SchedulePolicyFeedbackSignal = - UHyperTwistTrainingCoachLibrary::DeriveSchedulePolicyFeedbackSignal( - ActiveCoachSchedulePolicySummary, - ActiveCoachSessionQueueExecutionSummary, - ActiveCoachMemorySnapshot, - ActiveCoachBrief - ); - if (!SchedulePolicyFeedbackSignal.SignalId.IsEmpty()) - { - ActiveCoachBrief = UHyperTwistTrainingCoachLibrary::RefineCoachBriefWithSchedulePolicyFeedbackSignal( - ActiveCoachBrief, - SchedulePolicyFeedbackSignal - ); - ActiveCoachSignals = ActiveCoachBrief.Signals; - } - } - else + if (!SchedulePolicyFeedbackSignal.SignalId.IsEmpty()) { - ActiveCoachSessionQueueState = FHyperTwistTrainingCoachSessionQueueState(); - ActiveCoachScheduleHorizonSummary = FHyperTwistCoachScheduleHorizonSummary(); - ActiveCoachSchedulePolicySummary = FHyperTwistCoachSchedulePolicySummary(); - ActiveCoachSessionQueueExecutionSummary = FHyperTwistTrainingCoachSessionQueueExecutionSummary(); + ActiveCoachBrief = UHyperTwistTrainingCoachLibrary::RefineCoachBriefWithSchedulePolicyFeedbackSignal( + ActiveCoachBrief, + SchedulePolicyFeedbackSignal + ); + ActiveCoachSignals = ActiveCoachBrief.Signals; + RebuildActiveCoachQueueDerivedState(); } } diff --git a/docs/arch/HYPERTWIST_PHASE3_COACH_DERIVED_STATE_RESYNC_PACKET_2026-05-06.md b/docs/arch/HYPERTWIST_PHASE3_COACH_DERIVED_STATE_RESYNC_PACKET_2026-05-06.md new file mode 100644 index 0000000..6863b7a --- /dev/null +++ b/docs/arch/HYPERTWIST_PHASE3_COACH_DERIVED_STATE_RESYNC_PACKET_2026-05-06.md @@ -0,0 +1,89 @@ +# HyperTwist Phase 3 coach derived-state resync packet + +Created on `2026-05-06` + +Status: + +- first-party HyperTwist packet +- bounded coaching-stack closure slice + +## Purpose + +This packet defines the next logical Phase 3 closure task after the live schedule-policy feedback loop landed. + +The open task is: + +- keep the final active coach brief synchronized with the downstream follow-up brief, queue summary, queue state, and queue policy/execution summaries when late same-pass brief refinements fire + +It is not: + +- a new queue heuristic pass +- an iterative multi-pass coaching solver +- a dashboard redesign +- a donor widening task + +## Scope + +Bounded lane: + +- same-pass resynchronization of downstream coach derived state after late brief refinements + +Required result: + +- `RefreshRepositoryViews()` rebuilds downstream coach queue-derived surfaces after queue-suppression and schedule-policy feedback refinements +- the final `ActiveCoachBrief`, `ActiveCoachFollowUpBrief`, `ActiveCoachSessionQueueSummary`, and `ActiveCoachSessionQueueState` all describe the same refresh-pass result + +Out of scope: + +- changing the scoring heuristics of the existing signals +- introducing unbounded re-derivation loops +- changing generated-mode execution behavior +- changing external plugin copies + +## Current owned product truth + +These pieces are already live in first-party code: + +- late brief refinements for closure history, launch-budget history, queue suppression, and live schedule-policy feedback +- queue summary, queue state, queue horizon, schedule policy, and queue execution derivation +- dashboard consumers that read both coach briefs and queue-derived summaries + +What was still missing: + +- same-pass rebuild of downstream coach queue-derived state after late brief refinements changed the current brief +- protection against drift where the final active coach brief and the launchable follow-up/queue surfaces no longer matched each other + +## Implementation target + +The slice should do the following: + +1. centralize same-pass rebuild of: + - `ActiveCoachFollowUpBrief` + - `ActiveCoachSessionQueueSummary` + - `ActiveCoachSessionQueueState` + - `ActiveCoachScheduleHorizonSummary` + - `ActiveCoachSchedulePolicySummary` + - `ActiveCoachSessionQueueExecutionSummary` +2. run that rebuild once after the initial coach-brief history refinements +3. run it again after queue-suppression refinement if that refinement fires +4. run it again after schedule-policy feedback refinement if that refinement fires + +## Suggested file ownership + +Primary edit surface: + +- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSubsystem.cpp` + +## Acceptance criteria + +- final active brief and downstream follow-up/queue surfaces are same-pass aligned +- follow-up deck, queue entry launch, and panel state now consume queue-derived state that matches the final refined brief +- full UE build still succeeds + +## Validation checklist + +1. build `UnrealHyperTwist.sln` +2. confirm the subsystem rebuilds queue-derived surfaces after late brief refinements +3. confirm the final refresh-pass state no longer leaves `ActiveCoachFollowUpBrief` / `ActiveCoachSessionQueueSummary` stale relative to `ActiveCoachBrief` + +That is the packet.