From b08442c335f731ae3714006e07eea8382e893b38 Mon Sep 17 00:00:00 2001 From: axiomlogicnexus Date: Wed, 6 May 2026 18:08:19 +0200 Subject: [PATCH] Preserve queue backed coach brief continuity --- .../HyperTwistTrainingCoachLibrary.cpp | 13 ++ .../HyperTwistTrainingRepositoryLibrary.cpp | 54 +++++++-- .../HyperTwistTrainingSubsystem.cpp | 42 ++++++- .../HyperTwistTrainingCoachLibrary.h | 39 ++++++ .../HyperTwistTrainingTypes.h | 39 ++++++ ...UEUE_BRIEF_CONTINUITY_PACKET_2026-05-06.md | 112 ++++++++++++++++++ 6 files changed, 285 insertions(+), 14 deletions(-) create mode 100644 docs/arch/HYPERTWIST_PHASE4_QUEUE_BRIEF_CONTINUITY_PACKET_2026-05-06.md diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp index a175a2e..0249ed7 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp @@ -3773,16 +3773,29 @@ FHyperTwistCoachSessionQueueSummary UHyperTwistTrainingCoachLibrary::DeriveCoach FHyperTwistCoachSessionQueueEntry Entry; Entry.EntryId = EntryId; Entry.SourceLabel = SourceLabel; + Entry.SourceBriefTrainingSessionId = Brief.TrainingSessionId; + Entry.SourceReviewPlanId = Brief.SourceReviewPlanId; + Entry.CarryForwardPlanId = Brief.CarryForwardPlanId; + Entry.RootPlanId = Brief.RootPlanId; + Entry.FollowUpDepth = FMath::Max(0, Brief.FollowUpDepth); Entry.Priority = Brief.Priority; Entry.PriorityScore = Brief.PriorityScore; + Entry.FocusLane = Brief.FocusLane; Entry.Headline = Brief.Headline; + Entry.PrimaryActionLabel = Brief.PrimaryActionLabel; Entry.SuggestedMode = Brief.SuggestedMode; Entry.SuggestedSelectionPolicy = Brief.SuggestedSelectionPolicy; Entry.FocusDeckId = Brief.FocusDeckId; Entry.FocusMethodSegmentId = Brief.FocusMethodSegmentId; Entry.FocusCaseIds = Brief.FocusCaseIds; + Entry.DeferredLaunchCaseCount = FMath::Max(0, Brief.DeferredLaunchCaseCount); + Entry.bNeedsDeferredLaunchRecovery = Brief.bNeedsDeferredLaunchRecovery; + Entry.bHasTightenedLaunchOverflow = Brief.bHasTightenedLaunchOverflow; Entry.bRequiresFollowUp = bRequiresFollowUp; Entry.bRequiresArchiveRetentionTuning = bRequiresArchiveRetentionTuning; + Entry.bNeedsCoachReview = Brief.bNeedsCoachReview; + Entry.bNeedsCadenceRecovery = Brief.bNeedsCadenceRecovery; + Entry.bNeedsVarietyRotation = Brief.bNeedsVarietyRotation; Entry.bPreferRecognitionReplayReview = Brief.bPreferRecognitionReplayReview; const bool bNarrowedContinuationPreferred = HyperTwistTrainingCoachLibraryInternal::IsDeferredOverflowDashboardHandoffSource( diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.cpp index 66a4152..ced97a2 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.cpp @@ -4828,17 +4828,32 @@ namespace HyperTwistTrainingRepositoryLibraryInternal ) { const FString CaseFingerprint = FString::Join(Entry.FocusCaseIds, TEXT("|")); - return FString::Printf( - TEXT("%s|%s|%s|%s|%d|%d|%s|%d"), - *Entry.SourceLabel, - *Entry.FocusDeckId, - *Entry.FocusMethodSegmentId, - *Entry.Headline, - static_cast(Entry.SuggestedMode), - static_cast(Entry.SuggestedSelectionPolicy), - *CaseFingerprint, - Entry.bPreferRecognitionReplayReview ? 1 : 0 - ); + TArray FingerprintParts; + FingerprintParts.Reserve(22); + FingerprintParts.Add(Entry.SourceLabel); + FingerprintParts.Add(Entry.SourceBriefTrainingSessionId); + FingerprintParts.Add(Entry.SourceReviewPlanId); + FingerprintParts.Add(Entry.CarryForwardPlanId); + FingerprintParts.Add(Entry.RootPlanId); + FingerprintParts.Add(FString::FromInt(Entry.FollowUpDepth)); + FingerprintParts.Add(Entry.FocusLaneLabel); + FingerprintParts.Add(Entry.Headline); + FingerprintParts.Add(Entry.PrimaryActionLabel); + FingerprintParts.Add(Entry.FocusDeckId); + FingerprintParts.Add(Entry.FocusMethodSegmentId); + FingerprintParts.Add(FString::FromInt(static_cast(Entry.SuggestedMode))); + FingerprintParts.Add(FString::FromInt(static_cast(Entry.SuggestedSelectionPolicy))); + FingerprintParts.Add(CaseFingerprint); + FingerprintParts.Add(FString::FromInt(Entry.DeferredLaunchCaseCount)); + FingerprintParts.Add(Entry.bNeedsDeferredLaunchRecovery ? TEXT("1") : TEXT("0")); + FingerprintParts.Add(Entry.bHasTightenedLaunchOverflow ? TEXT("1") : TEXT("0")); + FingerprintParts.Add(Entry.bRequiresFollowUp ? TEXT("1") : TEXT("0")); + FingerprintParts.Add(Entry.bRequiresArchiveRetentionTuning ? TEXT("1") : TEXT("0")); + FingerprintParts.Add(Entry.bNeedsCoachReview ? TEXT("1") : TEXT("0")); + FingerprintParts.Add(Entry.bNeedsCadenceRecovery ? TEXT("1") : TEXT("0")); + FingerprintParts.Add(Entry.bNeedsVarietyRotation ? TEXT("1") : TEXT("0")); + FingerprintParts.Add(Entry.bPreferRecognitionReplayReview ? TEXT("1") : TEXT("0")); + return FString::Join(FingerprintParts, TEXT("|")); } FHyperTwistTrainingCoachSessionQueueState NormalizeCoachSessionQueueState( @@ -4864,6 +4879,8 @@ namespace HyperTwistTrainingRepositoryLibraryInternal { FHyperTwistTrainingCoachSessionQueueStateEntry NormalizedEntry = Entry; NormalizedEntry.FocusCaseIds = DeduplicateCaseIds(Entry.FocusCaseIds); + NormalizedEntry.FollowUpDepth = FMath::Max(0, NormalizedEntry.FollowUpDepth); + NormalizedEntry.DeferredLaunchCaseCount = FMath::Max(0, NormalizedEntry.DeferredLaunchCaseCount); if (NormalizedEntry.WorkFingerprint.IsEmpty()) { NormalizedEntry.WorkFingerprint = MakeCoachSessionQueueEntryFingerprint(NormalizedEntry); @@ -20664,19 +20681,34 @@ FHyperTwistTrainingCoachSessionQueueState UHyperTwistTrainingRepositoryLibrary:: FHyperTwistTrainingCoachSessionQueueStateEntry QueueEntry; QueueEntry.EntryId = SummaryEntry.EntryId; QueueEntry.SourceLabel = SummaryEntry.SourceLabel; + QueueEntry.SourceBriefTrainingSessionId = SummaryEntry.SourceBriefTrainingSessionId; + QueueEntry.SourceReviewPlanId = SummaryEntry.SourceReviewPlanId; + QueueEntry.CarryForwardPlanId = SummaryEntry.CarryForwardPlanId; + QueueEntry.RootPlanId = SummaryEntry.RootPlanId; + QueueEntry.FollowUpDepth = FMath::Max(0, SummaryEntry.FollowUpDepth); QueueEntry.SlotIndex = SummaryEntry.SlotIndex; QueueEntry.PriorityLabel = StaticEnum()->GetNameStringByValue( static_cast(SummaryEntry.Priority) ); QueueEntry.PriorityScore = SummaryEntry.PriorityScore; + QueueEntry.FocusLaneLabel = StaticEnum()->GetNameStringByValue( + static_cast(SummaryEntry.FocusLane) + ); QueueEntry.Headline = SummaryEntry.Headline; + QueueEntry.PrimaryActionLabel = SummaryEntry.PrimaryActionLabel; QueueEntry.SuggestedMode = SummaryEntry.SuggestedMode; QueueEntry.SuggestedSelectionPolicy = SummaryEntry.SuggestedSelectionPolicy; QueueEntry.FocusDeckId = SummaryEntry.FocusDeckId; QueueEntry.FocusMethodSegmentId = SummaryEntry.FocusMethodSegmentId; QueueEntry.FocusCaseIds = SummaryEntry.FocusCaseIds; + QueueEntry.DeferredLaunchCaseCount = FMath::Max(0, SummaryEntry.DeferredLaunchCaseCount); + QueueEntry.bNeedsDeferredLaunchRecovery = SummaryEntry.bNeedsDeferredLaunchRecovery; + QueueEntry.bHasTightenedLaunchOverflow = SummaryEntry.bHasTightenedLaunchOverflow; QueueEntry.bRequiresFollowUp = SummaryEntry.bRequiresFollowUp; QueueEntry.bRequiresArchiveRetentionTuning = SummaryEntry.bRequiresArchiveRetentionTuning; + QueueEntry.bNeedsCoachReview = SummaryEntry.bNeedsCoachReview; + QueueEntry.bNeedsCadenceRecovery = SummaryEntry.bNeedsCadenceRecovery; + QueueEntry.bNeedsVarietyRotation = SummaryEntry.bNeedsVarietyRotation; QueueEntry.bPreferRecognitionReplayReview = SummaryEntry.bPreferRecognitionReplayReview; QueueEntry.bPinned = QueueEntry.bRequiresFollowUp || QueueEntry.bRequiresArchiveRetentionTuning; QueueEntry.EntryState = EHyperTwistTrainingCoachSessionQueueEntryState::Pending; diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSubsystem.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSubsystem.cpp index 7eb1694..bbe774f 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSubsystem.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSubsystem.cpp @@ -81,6 +81,25 @@ namespace HyperTwistTrainingSubsystemInternal return TEXT("Unknown"); } + template + TEnum EnumValueFromName(const FString& Value, const TEnum Fallback) + { + if (Value.IsEmpty()) + { + return Fallback; + } + if (const UEnum* Enum = StaticEnum()) + { + const int64 RawValue = Enum->GetValueByNameString(Value); + if (RawValue != INDEX_NONE) + { + return static_cast(RawValue); + } + } + + return Fallback; + } + bool ShouldPreferRecognitionReplayReviewForActiveRun( const FHyperTwistTrainingRunState& RunState, const FHyperTwistTrainingCoachActionPlan& ActionPlan @@ -1188,19 +1207,36 @@ namespace HyperTwistTrainingSubsystemInternal FHyperTwistCoachBrief Brief; Brief.UserId = QueueState.UserId; Brief.ReferenceUtc = ReferenceUtc; + Brief.TrainingSessionId = QueueEntry.SourceBriefTrainingSessionId; + Brief.SourceReviewPlanId = QueueEntry.SourceReviewPlanId; + Brief.CarryForwardPlanId = QueueEntry.CarryForwardPlanId; + Brief.RootPlanId = !QueueEntry.RootPlanId.IsEmpty() + ? QueueEntry.RootPlanId + : QueueEntry.CarryForwardPlanId; + Brief.FollowUpDepth = FMath::Max(0, QueueEntry.FollowUpDepth); Brief.PriorityScore = QueueEntry.PriorityScore; Brief.Priority = CoachPriorityFromScore(QueueEntry.PriorityScore); Brief.FocusLane = QueueEntry.SourceLabel == TEXT("archive-policy") ? EHyperTwistCoachFocusLane::Stability - : EHyperTwistCoachFocusLane::ReviewBacklog; + : EnumValueFromName( + QueueEntry.FocusLaneLabel, + EHyperTwistCoachFocusLane::ReviewBacklog + ); Brief.Headline = QueueEntry.Headline; - Brief.PrimaryActionLabel = ResolveQueueActionLabel(QueueEntry.SourceLabel); + Brief.PrimaryActionLabel = !QueueEntry.PrimaryActionLabel.IsEmpty() + ? QueueEntry.PrimaryActionLabel + : ResolveQueueActionLabel(QueueEntry.SourceLabel); Brief.SuggestedMode = QueueEntry.SuggestedMode; Brief.SuggestedSelectionPolicy = QueueEntry.SuggestedSelectionPolicy; Brief.FocusDeckId = QueueEntry.FocusDeckId; Brief.FocusMethodSegmentId = QueueEntry.FocusMethodSegmentId; Brief.FocusCaseIds = QueueEntry.FocusCaseIds; - Brief.bNeedsCoachReview = QueueEntry.SuggestedMode == EHyperTwistTrainingDeliveryMode::CoachReviewed; + Brief.DeferredLaunchCaseCount = FMath::Max(0, QueueEntry.DeferredLaunchCaseCount); + Brief.bNeedsDeferredLaunchRecovery = QueueEntry.bNeedsDeferredLaunchRecovery; + Brief.bHasTightenedLaunchOverflow = QueueEntry.bHasTightenedLaunchOverflow; + Brief.bNeedsCoachReview = QueueEntry.bNeedsCoachReview; + Brief.bNeedsCadenceRecovery = QueueEntry.bNeedsCadenceRecovery; + Brief.bNeedsVarietyRotation = QueueEntry.bNeedsVarietyRotation; Brief.bPreferRecognitionReplayReview = QueueEntry.bPreferRecognitionReplayReview; return Brief; } diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingCoachLibrary.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingCoachLibrary.h index ef22ea4..12bb77d 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingCoachLibrary.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingCoachLibrary.h @@ -162,6 +162,21 @@ struct FHyperTwistCoachSessionQueueEntry UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") FString SourceLabel; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SourceBriefTrainingSessionId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SourceReviewPlanId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString CarryForwardPlanId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString RootPlanId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 FollowUpDepth = 0; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") int32 SlotIndex = 0; @@ -171,9 +186,15 @@ struct FHyperTwistCoachSessionQueueEntry UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") float PriorityScore = 0.0f; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + EHyperTwistCoachFocusLane FocusLane = EHyperTwistCoachFocusLane::ReviewBacklog; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") FString Headline; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString PrimaryActionLabel; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") EHyperTwistTrainingDeliveryMode SuggestedMode = EHyperTwistTrainingDeliveryMode::Timer; @@ -189,12 +210,30 @@ struct FHyperTwistCoachSessionQueueEntry UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") TArray FocusCaseIds; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 DeferredLaunchCaseCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bNeedsDeferredLaunchRecovery = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasTightenedLaunchOverflow = false; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") bool bRequiresFollowUp = false; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") bool bRequiresArchiveRetentionTuning = false; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bNeedsCoachReview = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bNeedsCadenceRecovery = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bNeedsVarietyRotation = false; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") bool bPreferRecognitionReplayReview = false; }; diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h index 2288ec8..b0d660b 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h @@ -4190,9 +4190,24 @@ struct FHyperTwistTrainingCoachSessionQueueStateEntry UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") FString SourceTrainingSessionId; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SourceBriefTrainingSessionId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SourceReviewPlanId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString CarryForwardPlanId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString RootPlanId; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") FString StartActionSourceLabel; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 FollowUpDepth = 0; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") int32 SlotIndex = 0; @@ -4206,9 +4221,15 @@ struct FHyperTwistTrainingCoachSessionQueueStateEntry UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") float PriorityScore = 0.0f; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString FocusLaneLabel; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") FString Headline; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString PrimaryActionLabel; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") EHyperTwistTrainingDeliveryMode SuggestedMode = EHyperTwistTrainingDeliveryMode::Timer; @@ -4224,6 +4245,15 @@ struct FHyperTwistTrainingCoachSessionQueueStateEntry UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") TArray FocusCaseIds; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 DeferredLaunchCaseCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bNeedsDeferredLaunchRecovery = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasTightenedLaunchOverflow = false; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") FString ScheduledAtUtc; @@ -4251,6 +4281,15 @@ struct FHyperTwistTrainingCoachSessionQueueStateEntry UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") bool bRequiresArchiveRetentionTuning = false; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bNeedsCoachReview = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bNeedsCadenceRecovery = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bNeedsVarietyRotation = false; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") bool bPreferRecognitionReplayReview = false; diff --git a/docs/arch/HYPERTWIST_PHASE4_QUEUE_BRIEF_CONTINUITY_PACKET_2026-05-06.md b/docs/arch/HYPERTWIST_PHASE4_QUEUE_BRIEF_CONTINUITY_PACKET_2026-05-06.md new file mode 100644 index 0000000..6a68b49 --- /dev/null +++ b/docs/arch/HYPERTWIST_PHASE4_QUEUE_BRIEF_CONTINUITY_PACKET_2026-05-06.md @@ -0,0 +1,112 @@ +# HyperTwist Phase 4 queue brief continuity packet + +Created on `2026-05-06` + +Status: + +- first-party HyperTwist packet +- bounded Phase `4` coach-to-review validation slice + +## Purpose + +This packet closes the next end-to-end continuity gap in the live recognition-assisted coach-to-review loop. + +The open task is: + +- preserve full queue-backed coach-brief semantics when coach guidance is materialized into queue entries and later reconstructed back into action-plan starts + +It is not: + +- a new recognition transport packet +- a new review-policy heuristic packet +- a new dashboard packet +- a broad queue-system rewrite + +## Scope + +Bounded lane: + +- persist the coach-brief fields that materially shape downstream coach action plans through queue summary and queue state +- reconstruct queue-backed coach briefs from those persisted fields instead of inferring them from delivery mode or source label alone +- keep queue fingerprints aligned with the widened preserved semantics so queue-state continuity remains honest + +Specifically preserved through the queue lane: + +- source brief training session id +- source review-plan id +- carry-forward/root plan lineage and follow-up depth +- focus lane and primary action label +- deferred-launch recovery state +- coach-review, cadence-recovery, and variety-rotation flags +- recognition-review preference + +Out of scope: + +- new queue prioritization rules +- new coach-signal derivation +- new replay scoring +- new UI layout work + +## Why this was the right next packet + +Before this slice: + +- recognition replay pressure already flowed into coach guidance +- queue entries already preserved recognition-review preference explicitly +- review-policy continuity and review-policy inspection were already landed +- recognition-biased repeat pressure already escalated correctly into coach intervention + +But the queue reconstruction lane still dropped critical coach-brief semantics: + +- coach-review intent could collapse to `false` unless suggested mode was explicit `CoachReviewed` +- queued follow-up entries lost carry-forward lineage +- queue-started action plans could lose source review-plan linkage, focus lane, primary action label, and cadence/variety/deferred-launch state + +That meant the broad Phase `4` validation lane was still not end-to-end coherent once guidance crossed the queue materialization boundary. + +So the next honest move was: + +- preserve queue-backed coach brief continuity directly rather than layering more downstream fixes on top of lossy queue reconstruction + +## What landed + +Primary code changes: + +- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingCoachLibrary.h` + - widened queue-summary entry structure to carry the coach-brief state needed for downstream continuity +- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h` + - widened queue-state entry structure to persist the same continuity fields through repository state +- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp` + - queue summary creation now copies the relevant coach-brief semantics into queue entries +- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingRepositoryLibrary.cpp` + - queue-state construction now preserves those fields and queue fingerprints now include them +- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSubsystem.cpp` + - queue-backed brief reconstruction now restores coach-review intent, review-plan linkage, follow-up lineage, focus lane, action label, deferred-launch state, cadence/variety flags, and recognition-review preference from queue state + +## Product effect + +Queue-backed coach execution is now materially more coherent: + +- recognition-assisted queue entries no longer lose coach-review intent just because they run in `RecognitionAssisted` mode +- queued follow-up guidance now preserves carry-forward/root-plan lineage into action-plan starts +- queue-started action plans now retain the same focus lane and primary action label that shaped the original brief +- deferred-launch, cadence, and variety state now survive the queue materialization boundary instead of resetting during reconstruction +- dashboard queue-preview and action-plan inspection now stay closer to the original coach guidance because they read the reconstructed brief path + +## Acceptance criteria + +- queue-backed brief reconstruction no longer infers coach-review intent from delivery mode alone +- queue entries preserve follow-up lineage and review-plan linkage needed by downstream action-plan creation +- queue-started action plans retain primary action label, focus lane, deferred-launch state, cadence/variety flags, and recognition-review preference +- queue fingerprinting reflects the widened preserved semantics +- full product build succeeds + +## Validation checklist + +1. build `UnrealHyperTwist.sln` / `UnrealHyperTwistEditor` +2. confirm queue summary entries preserve the coach-brief fields that materially affect action-plan creation +3. confirm queue-state construction and fingerprinting preserve those widened semantics +4. confirm queue-backed brief reconstruction restores coach-review intent, follow-up lineage, and review-plan linkage without reopening a broader packet +5. confirm dashboard/preview surfaces continue reading the reconstructed queue-backed brief path without compile or runtime-surface regressions + +That is the packet.