Restore retained idle preview/history closure

This commit is contained in:
axiomlogicnexus 2026-05-07 21:38:09 +02:00
parent 4a9f5fd0ca
commit 06a78c4fd8
4 changed files with 250 additions and 99 deletions

View file

@ -9797,9 +9797,15 @@ const FHyperTwistTrainingDeck* UHyperTwistCoachDashboardWidget::GetActiveGuidanc
switch (ActiveGuidancePreviewLane)
{
case EHyperTwistCoachDashboardGuidancePreviewLane::Recommended:
return CachedCoachRecommendedDeck.IsStructurallyValid() ? &CachedCoachRecommendedDeck : nullptr;
return CachedCoachPanelState.bCanStartCoachRecommendedRun
&& CachedCoachRecommendedDeck.IsStructurallyValid()
? &CachedCoachRecommendedDeck
: nullptr;
case EHyperTwistCoachDashboardGuidancePreviewLane::FollowUp:
return CachedCoachFollowUpDeck.IsStructurallyValid() ? &CachedCoachFollowUpDeck : nullptr;
return CachedCoachPanelState.bCanStartCoachFollowUpRun
&& CachedCoachFollowUpDeck.IsStructurallyValid()
? &CachedCoachFollowUpDeck
: nullptr;
default:
return nullptr;
}
@ -9810,11 +9816,16 @@ const FHyperTwistCoachBrief* UHyperTwistCoachDashboardWidget::GetActiveGuidanceP
switch (ActiveGuidancePreviewLane)
{
case EHyperTwistCoachDashboardGuidancePreviewLane::Recommended:
return CachedCoachBrief.Headline.IsEmpty() && CachedCoachBrief.PrimaryActionLabel.IsEmpty()
return !CachedCoachPanelState.bCanStartCoachRecommendedRun
|| (CachedCoachBrief.Headline.IsEmpty()
&& CachedCoachBrief.PrimaryActionLabel.IsEmpty())
? nullptr
: &CachedCoachBrief;
case EHyperTwistCoachDashboardGuidancePreviewLane::FollowUp:
return CachedCoachFollowUpBrief.Headline.IsEmpty() && CachedCoachFollowUpBrief.PrimaryActionLabel.IsEmpty()
return !CachedCoachPanelState.bCanStartCoachFollowUpRun
|| !CachedCoachPanelState.bHasFollowUpGuidance
|| (CachedCoachFollowUpBrief.Headline.IsEmpty()
&& CachedCoachFollowUpBrief.PrimaryActionLabel.IsEmpty())
? nullptr
: &CachedCoachFollowUpBrief;
default:
@ -10671,8 +10682,10 @@ FHyperTwistCoachDashboardDecisionWeighting UHyperTwistCoachDashboardWidget::Buil
FHyperTwistCoachDashboardGuidanceLanePreference UHyperTwistCoachDashboardWidget::BuildGuidanceLanePreference() const
{
FHyperTwistCoachDashboardGuidanceLanePreference Preference;
const bool bHasRecommendedDeck = CachedCoachRecommendedDeck.IsStructurallyValid();
const bool bHasFollowUpDeck = CachedCoachFollowUpDeck.IsStructurallyValid();
const bool bHasRecommendedDeck = CachedCoachPanelState.bCanStartCoachRecommendedRun
&& CachedCoachRecommendedDeck.IsStructurallyValid();
const bool bHasFollowUpDeck = CachedCoachPanelState.bCanStartCoachFollowUpRun
&& CachedCoachFollowUpDeck.IsStructurallyValid();
if (!bHasRecommendedDeck && !bHasFollowUpDeck)
{
return Preference;
@ -13054,7 +13067,8 @@ void UHyperTwistCoachDashboardWidget::RecordMethodDrillRecoveryMemoryHistorySnap
const FString& QueueRecoveryStatusLine,
const FString& HandoffRecommendationKindLabel,
const FString& HandoffRecommendationStatusLine,
const bool bUsedMethodDrillRecoveryMemoryForHandoff
const bool bUsedMethodDrillRecoveryMemoryForHandoff,
const bool bSuppressGeneratedGuidancePacketSurface
)
{
const bool bHasMethodDrillRecoveryHistory =
@ -13323,63 +13337,31 @@ void UHyperTwistCoachDashboardWidget::RecordMethodDrillRecoveryMemoryHistorySnap
Entry.bGeneratedPacketUsedStrongRetainedMethodDrillRecoveryPosture = bStrongPacketPosture;
Entry.bGeneratedPacketUsedWeakRetainedMethodDrillRecoveryPosture = bWeakPacketPosture;
Entry.bGeneratedPacketUsedGenericMethodDrillRecoveryMemory = bGenericRecoveryPacket;
if (Entry.RecommendedHandoffKindLabel.Equals(TEXT("queue"), ESearchCase::IgnoreCase))
if (!bSuppressGeneratedGuidancePacketSurface)
{
if (const FHyperTwistTrainingCoachSessionQueueStateEntry* SelectedQueueEntry =
FindSelectedQueueEntry())
if (Entry.RecommendedHandoffKindLabel.Equals(TEXT("queue"), ESearchCase::IgnoreCase))
{
Entry.GeneratedGuidancePacketKindLabel = TEXT("queue-entry");
Entry.GeneratedGuidancePacketSourceLabel = SelectedQueueEntry->SourceLabel;
Entry.GeneratedGuidancePacketHeadline = SelectedQueueEntry->Headline;
Entry.GeneratedGuidancePacketActionLabel =
SelectedQueueEntry->Headline.IsEmpty()
? SelectedQueueEntry->SourceLabel
: SelectedQueueEntry->Headline;
Entry.GeneratedGuidancePacketFocusCaseCount = SelectedQueueEntry->FocusCaseIds.Num();
ApplyGeneratedPlanSnapshot(
bReliableAlignedTrustedTightPlanSource,
bReliableAlignedTrustedBroadPlanSource,
bReliableTrustedTightPlanSource,
bReliableTrustedBroadPlanSource,
SelectedQueueEntry->SuggestedMode,
SelectedQueueEntry->SuggestedSelectionPolicy);
if (const FHyperTwistTrainingCoachSessionQueueStateEntry* SelectedQueueEntry =
FindSelectedQueueEntry())
{
Entry.GeneratedGuidancePacketKindLabel = TEXT("queue-entry");
Entry.GeneratedGuidancePacketSourceLabel = SelectedQueueEntry->SourceLabel;
Entry.GeneratedGuidancePacketHeadline = SelectedQueueEntry->Headline;
Entry.GeneratedGuidancePacketActionLabel =
SelectedQueueEntry->Headline.IsEmpty()
? SelectedQueueEntry->SourceLabel
: SelectedQueueEntry->Headline;
Entry.GeneratedGuidancePacketFocusCaseCount = SelectedQueueEntry->FocusCaseIds.Num();
ApplyGeneratedPlanSnapshot(
bReliableAlignedTrustedTightPlanSource,
bReliableAlignedTrustedBroadPlanSource,
bReliableTrustedTightPlanSource,
bReliableTrustedBroadPlanSource,
SelectedQueueEntry->SuggestedMode,
SelectedQueueEntry->SuggestedSelectionPolicy);
}
}
}
else if (Entry.RecommendedHandoffKindLabel.Equals(TEXT("follow-up"), ESearchCase::IgnoreCase))
{
Entry.GeneratedGuidancePacketKindLabel = TEXT("follow-up-packet");
Entry.GeneratedGuidancePacketSourceLabel = GuidanceSourceLabel;
Entry.GeneratedGuidancePacketHeadline = CachedCoachFollowUpBrief.Headline;
Entry.GeneratedGuidancePacketActionLabel = CachedCoachFollowUpBrief.PrimaryActionLabel;
Entry.GeneratedGuidancePacketFocusCaseCount = CachedCoachFollowUpBrief.FocusCaseIds.Num();
ApplyGeneratedPlanSnapshot(
bReliableAlignedTrustedTightPlanSource,
bReliableAlignedTrustedBroadPlanSource,
bReliableTrustedTightPlanSource,
bReliableTrustedBroadPlanSource,
CachedCoachFollowUpBrief.SuggestedMode,
CachedCoachFollowUpBrief.SuggestedSelectionPolicy);
}
else if (Entry.RecommendedHandoffKindLabel.Equals(TEXT("recommended"), ESearchCase::IgnoreCase))
{
Entry.GeneratedGuidancePacketKindLabel = TEXT("recommended-brief");
Entry.GeneratedGuidancePacketSourceLabel = GuidanceSourceLabel;
Entry.GeneratedGuidancePacketHeadline = CachedCoachBrief.Headline;
Entry.GeneratedGuidancePacketActionLabel = CachedCoachBrief.PrimaryActionLabel;
Entry.GeneratedGuidancePacketFocusCaseCount = CachedCoachBrief.FocusCaseIds.Num();
ApplyGeneratedPlanSnapshot(
bReliableAlignedTrustedTightPlanSource,
bReliableAlignedTrustedBroadPlanSource,
bReliableTrustedTightPlanSource,
bReliableTrustedBroadPlanSource,
CachedCoachBrief.SuggestedMode,
CachedCoachBrief.SuggestedSelectionPolicy);
}
if (Entry.GeneratedGuidancePacketKindLabel.IsEmpty())
{
if (!CachedCoachFollowUpBrief.Headline.IsEmpty()
|| !CachedCoachFollowUpBrief.PrimaryActionLabel.IsEmpty()
|| CachedCoachFollowUpBrief.FocusCaseIds.Num() > 0)
else if (Entry.RecommendedHandoffKindLabel.Equals(TEXT("follow-up"), ESearchCase::IgnoreCase))
{
Entry.GeneratedGuidancePacketKindLabel = TEXT("follow-up-packet");
Entry.GeneratedGuidancePacketSourceLabel = GuidanceSourceLabel;
@ -13394,28 +13376,7 @@ void UHyperTwistCoachDashboardWidget::RecordMethodDrillRecoveryMemoryHistorySnap
CachedCoachFollowUpBrief.SuggestedMode,
CachedCoachFollowUpBrief.SuggestedSelectionPolicy);
}
else if (const FHyperTwistTrainingCoachSessionQueueStateEntry* SelectedQueueEntry =
FindSelectedQueueEntry())
{
Entry.GeneratedGuidancePacketKindLabel = TEXT("queue-entry");
Entry.GeneratedGuidancePacketSourceLabel = SelectedQueueEntry->SourceLabel;
Entry.GeneratedGuidancePacketHeadline = SelectedQueueEntry->Headline;
Entry.GeneratedGuidancePacketActionLabel =
SelectedQueueEntry->Headline.IsEmpty()
? SelectedQueueEntry->SourceLabel
: SelectedQueueEntry->Headline;
Entry.GeneratedGuidancePacketFocusCaseCount = SelectedQueueEntry->FocusCaseIds.Num();
ApplyGeneratedPlanSnapshot(
bReliableAlignedTrustedTightPlanSource,
bReliableAlignedTrustedBroadPlanSource,
bReliableTrustedTightPlanSource,
bReliableTrustedBroadPlanSource,
SelectedQueueEntry->SuggestedMode,
SelectedQueueEntry->SuggestedSelectionPolicy);
}
else if (!CachedCoachBrief.Headline.IsEmpty()
|| !CachedCoachBrief.PrimaryActionLabel.IsEmpty()
|| CachedCoachBrief.FocusCaseIds.Num() > 0)
else if (Entry.RecommendedHandoffKindLabel.Equals(TEXT("recommended"), ESearchCase::IgnoreCase))
{
Entry.GeneratedGuidancePacketKindLabel = TEXT("recommended-brief");
Entry.GeneratedGuidancePacketSourceLabel = GuidanceSourceLabel;
@ -13430,6 +13391,62 @@ void UHyperTwistCoachDashboardWidget::RecordMethodDrillRecoveryMemoryHistorySnap
CachedCoachBrief.SuggestedMode,
CachedCoachBrief.SuggestedSelectionPolicy);
}
if (Entry.GeneratedGuidancePacketKindLabel.IsEmpty())
{
if (!CachedCoachFollowUpBrief.Headline.IsEmpty()
|| !CachedCoachFollowUpBrief.PrimaryActionLabel.IsEmpty()
|| CachedCoachFollowUpBrief.FocusCaseIds.Num() > 0)
{
Entry.GeneratedGuidancePacketKindLabel = TEXT("follow-up-packet");
Entry.GeneratedGuidancePacketSourceLabel = GuidanceSourceLabel;
Entry.GeneratedGuidancePacketHeadline = CachedCoachFollowUpBrief.Headline;
Entry.GeneratedGuidancePacketActionLabel = CachedCoachFollowUpBrief.PrimaryActionLabel;
Entry.GeneratedGuidancePacketFocusCaseCount = CachedCoachFollowUpBrief.FocusCaseIds.Num();
ApplyGeneratedPlanSnapshot(
bReliableAlignedTrustedTightPlanSource,
bReliableAlignedTrustedBroadPlanSource,
bReliableTrustedTightPlanSource,
bReliableTrustedBroadPlanSource,
CachedCoachFollowUpBrief.SuggestedMode,
CachedCoachFollowUpBrief.SuggestedSelectionPolicy);
}
else if (const FHyperTwistTrainingCoachSessionQueueStateEntry* SelectedQueueEntry =
FindSelectedQueueEntry())
{
Entry.GeneratedGuidancePacketKindLabel = TEXT("queue-entry");
Entry.GeneratedGuidancePacketSourceLabel = SelectedQueueEntry->SourceLabel;
Entry.GeneratedGuidancePacketHeadline = SelectedQueueEntry->Headline;
Entry.GeneratedGuidancePacketActionLabel =
SelectedQueueEntry->Headline.IsEmpty()
? SelectedQueueEntry->SourceLabel
: SelectedQueueEntry->Headline;
Entry.GeneratedGuidancePacketFocusCaseCount = SelectedQueueEntry->FocusCaseIds.Num();
ApplyGeneratedPlanSnapshot(
bReliableAlignedTrustedTightPlanSource,
bReliableAlignedTrustedBroadPlanSource,
bReliableTrustedTightPlanSource,
bReliableTrustedBroadPlanSource,
SelectedQueueEntry->SuggestedMode,
SelectedQueueEntry->SuggestedSelectionPolicy);
}
else if (!CachedCoachBrief.Headline.IsEmpty()
|| !CachedCoachBrief.PrimaryActionLabel.IsEmpty()
|| CachedCoachBrief.FocusCaseIds.Num() > 0)
{
Entry.GeneratedGuidancePacketKindLabel = TEXT("recommended-brief");
Entry.GeneratedGuidancePacketSourceLabel = GuidanceSourceLabel;
Entry.GeneratedGuidancePacketHeadline = CachedCoachBrief.Headline;
Entry.GeneratedGuidancePacketActionLabel = CachedCoachBrief.PrimaryActionLabel;
Entry.GeneratedGuidancePacketFocusCaseCount = CachedCoachBrief.FocusCaseIds.Num();
ApplyGeneratedPlanSnapshot(
bReliableAlignedTrustedTightPlanSource,
bReliableAlignedTrustedBroadPlanSource,
bReliableTrustedTightPlanSource,
bReliableTrustedBroadPlanSource,
CachedCoachBrief.SuggestedMode,
CachedCoachBrief.SuggestedSelectionPolicy);
}
}
}
if (!Entry.IsStructurallyValid())
{
@ -16782,14 +16799,22 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
return FString::Printf(TEXT("%s: no guidance available"), EmptyPrefix);
};
const FString RecommendedDeckPreviewLine = BuildDeckPreviewLine(
CachedCoachRecommendedDeck,
CachedCoachBrief,
FString RecommendedDeckPreviewLine = BuildDeckPreviewLine(
CachedCoachPanelState.bCanStartCoachRecommendedRun
? CachedCoachRecommendedDeck
: FHyperTwistTrainingDeck(),
CachedCoachPanelState.bCanStartCoachRecommendedRun
? CachedCoachBrief
: FHyperTwistCoachBrief(),
TEXT("Recommended guidance")
);
const FString FollowUpDeckPreviewLine = BuildDeckPreviewLine(
CachedCoachFollowUpDeck,
CachedCoachFollowUpBrief,
FString FollowUpDeckPreviewLine = BuildDeckPreviewLine(
(CachedCoachPanelState.bCanStartCoachFollowUpRun && CachedCoachPanelState.bHasFollowUpGuidance)
? CachedCoachFollowUpDeck
: FHyperTwistTrainingDeck(),
(CachedCoachPanelState.bCanStartCoachFollowUpRun && CachedCoachPanelState.bHasFollowUpGuidance)
? CachedCoachFollowUpBrief
: FHyperTwistCoachBrief(),
TEXT("Follow-up guidance")
);
const FHyperTwistTrainingDeck* ActivePreviewDeck = GetActiveGuidancePreviewDeck();
@ -16841,7 +16866,7 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
: HyperTwistCoachDashboardWidgetInternal::DescribeCoachMemorySourceLabel(
CachedCoachPanelState.PreferredGuidanceSourceLabel);
}();
const FString GuidancePreferenceStatusLine =
FString GuidancePreferenceStatusLine =
GuidanceLanePreference.IsStructurallyValid()
? FString::Printf(
TEXT("Preference: next surfaced lane %s | Active preview: %s | Source: %s"),
@ -17361,6 +17386,14 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
}
if (bShouldPresentClosedLoopIdleDashboard)
{
RecommendedDeckPreviewLine =
TEXT("Recommended guidance: no active recommended guidance; the coach-to-review loop is closed and idle.");
FollowUpDeckPreviewLine =
TEXT("Follow-up guidance: no active follow-up guidance; the coach-to-review loop is closed and idle.");
GuidancePreferenceStatusLine =
TEXT("Preference: the coach-to-review loop is closed and idle; no coach preview lane is active.");
GuidancePreferenceDetailLine =
TEXT("Preference detail: retained lane history remains inspectable, but no recommended or follow-up preview is currently active.");
TransitionStatusLine =
TEXT("Transition: the coach-to-review loop is closed and idle. No queued, follow-up, or recommended continuation remains.");
ContinueRunLabel = TEXT("Loop Idle");
@ -17441,7 +17474,8 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
HyperTwistCoachDashboardWidgetInternal::DescribeHandoffRecommendationKind(
HandoffRecommendationKind),
CoachHandoffRecommendationStatusLine,
bHandoffRecommendationUsedMethodDrillRecoveryMemory
bHandoffRecommendationUsedMethodDrillRecoveryMemory,
bShouldPresentClosedLoopIdleDashboard
);
const bool bHasPrimaryQueueSuppression =
CachedCoachSessionQueueSummary.bSuppressedPrimaryQueueCreation
@ -17929,7 +17963,7 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
: (CachedCoachPanelState.bCanStartQueuedRun
? TEXT("Launch Queue Recovery")
: TEXT("Apply Recovery")))));
const FString GuidancePreviewSelectionLine =
FString GuidancePreviewSelectionLine =
SelectedGuidancePreviewCase != nullptr && ActivePreviewDeck != nullptr
? FString::Printf(
TEXT("Active preview: %s | case %d/%d | deck %s"),
@ -17939,7 +17973,7 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
ActivePreviewDeck->Title.IsEmpty() ? *ActivePreviewDeck->DeckId : *ActivePreviewDeck->Title
)
: FString::Printf(TEXT("Active preview: %s | build a coach deck preview to inspect specific cases"), *ActivePreviewLaneLabel);
const FString GuidancePreviewCaseDetailLine =
FString GuidancePreviewCaseDetailLine =
SelectedGuidancePreviewCase != nullptr
? FString::Printf(
TEXT("Preview case: %s | Prompt: %s | Kind: %s | Subset: %s | Target: %d ms | Scramble: %s | Canonical: %s"),
@ -17997,7 +18031,7 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
SignalSummaryLine = FString::Join(SignalSummaryParts, TEXT(" | "));
}
}
const FString GuidanceRationaleStatusLine =
FString GuidanceRationaleStatusLine =
ActivePreviewBrief != nullptr
? FString::Printf(
TEXT("Rationale: %s lane | Priority: %s (%.2f) | Focus: %s | Mode: %s | Selection: %s"),
@ -18012,7 +18046,7 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
TEXT("Rationale: %s lane | build a recommended or follow-up preview to inspect the coach rationale"),
*ActivePreviewLaneLabel
);
const FString GuidanceRationaleDetailLine =
FString GuidanceRationaleDetailLine =
ActivePreviewBrief != nullptr
? FString::Printf(
TEXT("Brief: %s | Action: %s | Deck: %s | Method: %s | Focus cases: %d | Review: %s | Cadence: %s | Variety: %s | Guidance source: %s | Launch bias: %s from %s | broadened/tightened history %d/%d | deferred tightened launches %d | deferred launch cases %d%s | Selected focus: %s | Matching signals: %d | Case signal: %s | Top signals: %s"),
@ -18044,6 +18078,17 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
*SignalSummaryLine
)
: TEXT("Rationale detail: unavailable until a guidance preview lane is active.");
if (bShouldPresentClosedLoopIdleDashboard)
{
GuidancePreviewSelectionLine =
TEXT("Active preview: none | the coach-to-review loop is closed and idle.");
GuidancePreviewCaseDetailLine =
TEXT("Preview case: no active guidance preview remains in the closed-loop idle state.");
GuidanceRationaleStatusLine =
TEXT("Rationale: closed-loop idle state | no active guidance preview remains.");
GuidanceRationaleDetailLine =
TEXT("Rationale detail: retained coach memory and history remain available for inspection, but no live preview packet is active.");
}
const FString GuidanceComparisonLaneLabel =
DisplayedGuidanceComparisonLane == EHyperTwistCoachDashboardGuidancePreviewLane::Recommended
? TEXT("recommended")

View file

@ -1663,7 +1663,8 @@ private:
const FString& QueueRecoveryStatusLine,
const FString& HandoffRecommendationKindLabel,
const FString& HandoffRecommendationStatusLine,
bool bUsedMethodDrillRecoveryMemoryForHandoff
bool bUsedMethodDrillRecoveryMemoryForHandoff,
bool bSuppressGeneratedGuidancePacketSurface
);
void RecordGuidanceOutcomeDecision(
EHyperTwistCoachDashboardOutcomeAction RecommendedAction,

View file

@ -66,9 +66,9 @@ Current correction call from the source-exposed audit and current execution refr
- retained benchmark-oracle and mirror-intake reservations
- current code reality in which training/coaching/catalog integration is materially ahead of recognition and hypercube runtime implementation
- the imported generated-mode gap is closed; request/config/selection plumbing and the bounded clean-room executor are already landed in first-party code
- the latest landed bounded `Phase 4` packet closes the retained-idle dashboard presentation gap at the end of the already-live recognition-assisted coach-to-review continuity lane
- the retained idle widget surface now collapses next-step, handoff, and retained handoff-history presentation to the truthful closed-loop idle state instead of carrying pre-collapse queue/follow-up/recommended narration forward
- the current next bounded packet is to run one final retained-surface sweep across preview/history panes and land only if stale launch labels, generated packet headlines, or handoff narration still survive after the closed-loop idle collapse
- the latest landed bounded `Phase 4` packet closes the retained-idle preview/history gap at the end of the already-live recognition-assisted coach-to-review continuity lane
- the retained idle widget surface now suppresses stale coach preview availability, preview narration, and generated-packet history restamping once the coach-to-review loop has already collapsed to truthful closed-loop idle
- the current next bounded packet is to run one final lane-completion verification across retained comparison/history surfaces and, only if anything still leaks through, land the last narrow continuity fix before marking this closure lane complete
- the current execution-discipline rule that broad refactor / monolith-splitting work should not interrupt the active bounded roadmap packet unless structure is actually blocking it
## Current execution-reality references

View file

@ -0,0 +1,105 @@
# HyperTwist Phase 4 retained idle preview/history closure packet
Created on `2026-05-07`
Status:
- first-party HyperTwist packet
- bounded Phase `4` coach-to-review validation slice
## Purpose
This packet closes the last retained preview/history seam after the retained idle next-step and handoff surface already collapsed to truthful closed-loop idle.
The open tasks were:
- stop stale cached recommended/follow-up coach previews from still surfacing as an active preview lane after the panel state has already collapsed to idle
- stop retained method-drill recovery memory history from restamping a fresh generated guidance packet headline/action from those stale cached briefs during the same idle refresh
It is not:
- a new subsystem closure packet
- a new queue recovery policy packet
- a new coach-memory scoring packet
- a broader dashboard rewrite
## Scope
Bounded lane:
- make active guidance preview deck/brief selection respect current coach actionability instead of only cached deck structure
- make preferred guidance lane selection treat recommended/follow-up availability as actionability-aware
- collapse retained idle preview narration so the current preview and rationale panes explicitly report that no active guidance preview remains
- suppress generated guidance packet surface restamping in retained method-drill recovery history when the dashboard is already presenting the closed-loop idle boundary
Out of scope:
- changing review carryover continuity
- changing queue ordering or queue execution policy
- reopening retained idle next-step or handoff closure work
- widening into unrelated analytics or recognition packets
## Why this was the right next packet
Before this slice:
- retained idle subsystem refresh already stopped rebuilding queue and follow-up actionability
- retained idle dashboard presentation already collapsed next-step and handoff narration to truthful closed-loop idle
But one retained surface seam still remained:
- cached recommended/follow-up decks and briefs could still keep a preview lane structurally alive even when the panel state no longer allowed those launches
- retained method-drill recovery memory history could still snapshot a fresh generated guidance packet from those cached briefs during that same idle-closed refresh
That meant:
- the live dashboard action surface could already be truthful and idle
- while the retained preview/history surfaces could still imply that a coach packet was actively previewable or newly generated
So the next honest move was:
- gate preview availability on live actionability instead of cache structure alone
- and suppress generated-packet history restamping once the retained loop is already closed and idle
## What landed
Primary code changes:
- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp`
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h`
- `GetActiveGuidancePreviewDeck()` and `GetActiveGuidancePreviewBrief()` now require the matching recommended/follow-up lane to still be actionable before they surface a live preview
- `BuildGuidanceLanePreference()` now treats recommended/follow-up deck availability as actionability-aware instead of only structurally cached
- `UpdateDashboardPresentation()` now collapses retained idle preview/rationale narration to explicit no-active-preview wording and avoids building preview deck summary lines from inactive cached coach guidance
- `RecordMethodDrillRecoveryMemoryHistorySnapshot(...)` now accepts an idle-suppression flag so retained closed-loop idle refresh does not stamp a fresh generated guidance packet surface from stale cached queue/recommended/follow-up briefs
## Product effect
The retained idle preview/history surface is now more truthful:
- recommended/follow-up preview lanes no longer remain live just because cached decks and briefs still exist
- retained idle preview and rationale panes no longer narrate a live coach packet after the coach-to-review loop is already closed and idle
- retained method-drill recovery memory history no longer restamps a fresh generated guidance packet from stale cached guidance at that same boundary
## Acceptance criteria
- when the retained coach-to-review loop is closed and idle, active guidance preview selection returns no live recommended or follow-up preview
- retained idle preview/rationale panes explicitly report that no active guidance preview remains
- retained method-drill recovery memory history does not stamp a fresh generated guidance packet surface from stale cached guidance in that state
- full product build succeeds
## Validation checklist
1. build `UnrealHyperTwist.sln` / `UnrealHyperTwistEditor`
2. confirm retained idle preview selection respects current recommended/follow-up actionability instead of stale cached deck structure
3. confirm retained idle preview and rationale panes collapse to no-active-preview narration
4. confirm retained method-drill recovery memory history does not record a fresh generated guidance packet surface at the same idle boundary
5. confirm no broader queue, carryover, or analytics behavior was reopened
## Validation result
- full `Development Editor|Win64` build succeeded on `2026-05-07`
- the preexisting `UnrealMCP` / `PythonScriptPlugin` dependency warning remained unchanged
## Next bounded follow-on slice
- run one final lane-completion verification across retained comparison/history surfaces and, only if anything still leaks through, land the last narrow continuity fix before marking the recognition-assisted coach-to-review closure lane complete