diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp index ff6e6b0..583ec08 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp @@ -11376,6 +11376,178 @@ UHyperTwistCoachDashboardWidget::GetDisplayedQueueActionEnablementInspectSurface return Surface; } +FHyperTwistTrainingCoachDashboardVerificationActionInspectSurface +UHyperTwistCoachDashboardWidget::GetDisplayedVerificationActionInspectSurface() const +{ + FHyperTwistTrainingCoachDashboardVerificationActionInspectSurface Surface; + Surface.Headline = TEXT("Verification action"); + + Surface.VerifyLabel = !DisplayedVerificationActionLabel.IsEmpty() + ? DisplayedVerificationActionLabel + : TEXT("Verify"); + Surface.RepositoryPath = CachedRepositoryRoundTripVerification.ResolvedPath.IsEmpty() + ? TEXT("not yet verified") + : CachedRepositoryRoundTripVerification.ResolvedPath; + Surface.LatestNote = CachedRepositoryRoundTripVerification.VerificationNotes.Num() > 0 + ? CachedRepositoryRoundTripVerification.VerificationNotes[0] + : TEXT("none"); + Surface.bVerifyEnabled = true; + Surface.bHasResolvedPath = !CachedRepositoryRoundTripVerification.ResolvedPath.IsEmpty(); + Surface.bDidRoundTripPass = CachedRepositoryRoundTripVerification.bDidRoundTripPass; + Surface.bSaveSucceeded = CachedRepositoryRoundTripVerification.bSaveSucceeded; + Surface.bLoadSucceeded = CachedRepositoryRoundTripVerification.bLoadSucceeded; + Surface.bCountsMatched = CachedRepositoryRoundTripVerification.bRepositoryCountsMatch; + Surface.bStateMatched = CachedRepositoryRoundTripVerification.bSerializedStateMatch; + Surface.bIntegrityMatched = CachedRepositoryRoundTripVerification.bIntegrityReportMatch; + Surface.bDerivedMatched = CachedRepositoryRoundTripVerification.bDerivedStateMatch; + Surface.StatusLine = CachedCoachPanelState.VerificationStatusLine.IsEmpty() + ? FString::Printf( + TEXT("%s: %s"), + *Surface.VerifyLabel, + Surface.bDidRoundTripPass ? TEXT("last round-trip passed") : TEXT("ready to run repository round-trip verification")) + : CachedCoachPanelState.VerificationStatusLine; + Surface.DetailLine = FString::Printf( + TEXT("Verification detail: label %s | enabled %s | path %s | save %s | load %s | counts %s | state %s | integrity %s | derived %s | note %s"), + *Surface.VerifyLabel, + Surface.bVerifyEnabled ? TEXT("yes") : TEXT("no"), + *Surface.RepositoryPath, + Surface.bSaveSucceeded ? TEXT("yes") : TEXT("no"), + Surface.bLoadSucceeded ? TEXT("yes") : TEXT("no"), + Surface.bCountsMatched ? TEXT("yes") : TEXT("no"), + Surface.bStateMatched ? TEXT("yes") : TEXT("no"), + Surface.bIntegrityMatched ? TEXT("yes") : TEXT("no"), + Surface.bDerivedMatched ? TEXT("yes") : TEXT("no"), + *Surface.LatestNote); + return Surface; +} + +FHyperTwistTrainingCoachDashboardSelectedQueueNavigationInspectSurface +UHyperTwistCoachDashboardWidget::GetDisplayedSelectedQueueNavigationInspectSurface() const +{ + FHyperTwistTrainingCoachDashboardSelectedQueueNavigationInspectSurface Surface; + Surface.Headline = TEXT("Selected-queue navigation"); + + const FHyperTwistTrainingCoachSessionQueueStateEntry* SelectedEntry = FindSelectedQueueEntry(); + const bool bNavigationEnabled = + !bHasLiveAttemptTimer && CachedCoachSessionQueueState.Entries.Num() > 1; + + Surface.PreviousLabel = !DisplayedPreviousQueueNavigationLabel.IsEmpty() + ? DisplayedPreviousQueueNavigationLabel + : TEXT("Prev Queue"); + Surface.NextLabel = !DisplayedNextQueueNavigationLabel.IsEmpty() + ? DisplayedNextQueueNavigationLabel + : TEXT("Next Queue"); + Surface.SelectedQueueEntryId = + SelectedEntry != nullptr && !SelectedEntry->EntryId.IsEmpty() + ? SelectedEntry->EntryId + : TEXT("none"); + Surface.SelectedQueueSourceLabel = + SelectedEntry != nullptr && !SelectedEntry->SourceLabel.IsEmpty() + ? SelectedEntry->SourceLabel + : TEXT("n/a"); + Surface.SelectedQueueStateLabel = + SelectedEntry != nullptr + ? HyperTwistCoachDashboardWidgetInternal::EnumDisplayName(SelectedEntry->EntryState) + : TEXT("n/a"); + Surface.SelectedQueueOrdinal = + SelectedEntry != nullptr + ? FString::Printf( + TEXT("%d/%d"), + SelectedQueueEntryIndex + 1, + CachedCoachSessionQueueState.Entries.Num()) + : TEXT("none"); + Surface.SelectedQueueEntryIndex = SelectedQueueEntryIndex; + Surface.TotalQueueEntries = CachedCoachSessionQueueState.Entries.Num(); + Surface.bHasSelectedQueueEntry = SelectedEntry != nullptr; + Surface.bHasLiveAttemptTimer = bHasLiveAttemptTimer; + Surface.bSelectedEntryMatchesActiveQueue = + SelectedEntry != nullptr + && SelectedEntry->EntryId == CachedCoachPanelState.ActiveQueueEntryId; + Surface.bPreviousEnabled = bNavigationEnabled; + Surface.bNextEnabled = bNavigationEnabled; + Surface.StatusLine = + SelectedEntry != nullptr + ? FString::Printf( + TEXT("Selected queue item %d/%d | Source: %s | State: %s | Priority: %s (%.1f)"), + SelectedQueueEntryIndex + 1, + CachedCoachSessionQueueState.Entries.Num(), + *Surface.SelectedQueueSourceLabel, + *Surface.SelectedQueueStateLabel, + SelectedEntry->PriorityLabel.IsEmpty() ? TEXT("n/a") : *SelectedEntry->PriorityLabel, + SelectedEntry->PriorityScore) + : TEXT("Selected queue item: none"); + Surface.DetailLine = FString::Printf( + TEXT("%s: %s | %s: %s | active selection: %s | live timer: %s"), + *Surface.PreviousLabel, + Surface.bPreviousEnabled ? TEXT("enabled") : TEXT("disabled"), + *Surface.NextLabel, + Surface.bNextEnabled ? TEXT("enabled") : TEXT("disabled"), + Surface.bSelectedEntryMatchesActiveQueue ? TEXT("yes") : TEXT("no"), + Surface.bHasLiveAttemptTimer ? TEXT("yes") : TEXT("no")); + return Surface; +} + +FHyperTwistTrainingCoachDashboardStartSelectedQueueActionInspectSurface +UHyperTwistCoachDashboardWidget::GetDisplayedStartSelectedQueueActionInspectSurface() const +{ + FHyperTwistTrainingCoachDashboardStartSelectedQueueActionInspectSurface Surface; + Surface.Headline = TEXT("Start-selected queue action"); + + const FHyperTwistTrainingCoachSessionQueueStateEntry* SelectedEntry = FindSelectedQueueEntry(); + const bool bSelectedEntryReady = + SelectedEntry != nullptr + && SelectedEntry->EntryState == EHyperTwistTrainingCoachSessionQueueEntryState::Ready; + const bool bSelectedEntryPendingImmediate = + SelectedEntry != nullptr + && SelectedEntry->EntryState == EHyperTwistTrainingCoachSessionQueueEntryState::Pending + && SelectedEntry->bCanStartImmediately; + + Surface.StartSelectedLabel = !DisplayedStartSelectedQueueActionLabel.IsEmpty() + ? DisplayedStartSelectedQueueActionLabel + : TEXT("Start Selected"); + Surface.SelectedQueueEntryId = + SelectedEntry != nullptr && !SelectedEntry->EntryId.IsEmpty() + ? SelectedEntry->EntryId + : TEXT("none"); + Surface.SelectedQueueStateLabel = + SelectedEntry != nullptr + ? HyperTwistCoachDashboardWidgetInternal::EnumDisplayName(SelectedEntry->EntryState) + : TEXT("n/a"); + Surface.SelectedQueueSourceLabel = + SelectedEntry != nullptr && !SelectedEntry->SourceLabel.IsEmpty() + ? SelectedEntry->SourceLabel + : TEXT("n/a"); + Surface.SelectedQueuePrimaryActionLabel = + SelectedEntry != nullptr && !SelectedEntry->PrimaryActionLabel.IsEmpty() + ? SelectedEntry->PrimaryActionLabel + : TEXT("n/a"); + Surface.bHasSelectedQueueEntry = SelectedEntry != nullptr; + Surface.bHasLiveAttemptTimer = bHasLiveAttemptTimer; + Surface.bSelectedEntryReady = bSelectedEntryReady; + Surface.bSelectedEntryPendingStartImmediate = bSelectedEntryPendingImmediate; + Surface.bStartSelectedEnabled = + !bHasLiveAttemptTimer && (bSelectedEntryReady || bSelectedEntryPendingImmediate); + Surface.StatusLine = + SelectedEntry != nullptr + ? FString::Printf( + TEXT("%s: %s | entry %s | state %s"), + *Surface.StartSelectedLabel, + Surface.bStartSelectedEnabled ? TEXT("enabled") : TEXT("disabled"), + *Surface.SelectedQueueEntryId, + *Surface.SelectedQueueStateLabel) + : FString::Printf( + TEXT("%s: disabled | no queue entry selected"), + *Surface.StartSelectedLabel); + Surface.DetailLine = FString::Printf( + TEXT("Start-selected detail: source %s | action %s | ready %s | pending-immediate %s | live timer %s"), + *Surface.SelectedQueueSourceLabel, + *Surface.SelectedQueuePrimaryActionLabel, + Surface.bSelectedEntryReady ? TEXT("yes") : TEXT("no"), + Surface.bSelectedEntryPendingStartImmediate ? TEXT("yes") : TEXT("no"), + Surface.bHasLiveAttemptTimer ? TEXT("yes") : TEXT("no")); + return Surface; +} + FHyperTwistTrainingCoachDashboardLastAttemptReviewSummaryInspectSurface UHyperTwistCoachDashboardWidget::GetDisplayedLastAttemptReviewSummaryInspectSurface() const { @@ -24216,7 +24388,8 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation() if (VerifyButtonLabel != nullptr) { - VerifyButtonLabel->SetText(FText::FromString(TEXT("Verify"))); + DisplayedVerificationActionLabel = TEXT("Verify"); + VerifyButtonLabel->SetText(FText::FromString(DisplayedVerificationActionLabel)); } if (DeferButtonLabel != nullptr) { @@ -24401,7 +24574,8 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation() } if (PreviousQueueButtonLabel != nullptr) { - PreviousQueueButtonLabel->SetText(FText::FromString(TEXT("Prev Queue"))); + DisplayedPreviousQueueNavigationLabel = TEXT("Prev Queue"); + PreviousQueueButtonLabel->SetText(FText::FromString(DisplayedPreviousQueueNavigationLabel)); } if (PreviousQueueButton != nullptr) { @@ -24409,7 +24583,8 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation() } if (StartSelectedButtonLabel != nullptr) { - StartSelectedButtonLabel->SetText(FText::FromString(TEXT("Start Selected"))); + DisplayedStartSelectedQueueActionLabel = TEXT("Start Selected"); + StartSelectedButtonLabel->SetText(FText::FromString(DisplayedStartSelectedQueueActionLabel)); } if (StartSelectedButton != nullptr) { @@ -24422,7 +24597,8 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation() } if (NextQueueButtonLabel != nullptr) { - NextQueueButtonLabel->SetText(FText::FromString(TEXT("Next Queue"))); + DisplayedNextQueueNavigationLabel = TEXT("Next Queue"); + NextQueueButtonLabel->SetText(FText::FromString(DisplayedNextQueueNavigationLabel)); } if (NextQueueButton != nullptr) { diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h index ad6256f..af7e0dd 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistCoachDashboardWidget.h @@ -851,6 +851,18 @@ public: FHyperTwistTrainingCoachDashboardQueueActionEnablementInspectSurface GetDisplayedQueueActionEnablementInspectSurface() const; + UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard") + FHyperTwistTrainingCoachDashboardVerificationActionInspectSurface + GetDisplayedVerificationActionInspectSurface() const; + + UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard") + FHyperTwistTrainingCoachDashboardSelectedQueueNavigationInspectSurface + GetDisplayedSelectedQueueNavigationInspectSurface() const; + + UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard") + FHyperTwistTrainingCoachDashboardStartSelectedQueueActionInspectSurface + GetDisplayedStartSelectedQueueActionInspectSurface() const; + UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard") FHyperTwistTrainingCoachDashboardLastAttemptReviewSummaryInspectSurface GetDisplayedLastAttemptReviewSummaryInspectSurface() const; @@ -1928,6 +1940,7 @@ private: FString DisplayedRecommendedDeckPreviewLine; FString DisplayedFollowUpDeckPreviewLine; FString DisplayedPrimaryActionLabel; + FString DisplayedVerificationActionLabel; FString DisplayedDeferQueueActionLabel; FString DisplayedPromoteQueueActionLabel; FString DisplayedQueueRecoveryActionLabel; @@ -1937,6 +1950,9 @@ private: FString DisplayedQueuedRunLabel; FString DisplayedFollowUpRunLabel; FString DisplayedRecommendedRunLabel; + FString DisplayedPreviousQueueNavigationLabel; + FString DisplayedStartSelectedQueueActionLabel; + FString DisplayedNextQueueNavigationLabel; FString DisplayedPreviousAttemptNavigationLabel; FString DisplayedNextAttemptNavigationLabel; EHyperTwistCoachDashboardGuidancePreviewLane ActiveGuidancePreviewLane = diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h index ded0cf7..2208d08 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h @@ -11183,6 +11183,181 @@ struct FHyperTwistTrainingCoachDashboardQueueActionEnablementInspectSurface } }; +USTRUCT(BlueprintType) +struct FHyperTwistTrainingCoachDashboardVerificationActionInspectSurface +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString Headline; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString StatusLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString DetailLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString VerifyLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString RepositoryPath; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString LatestNote; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bVerifyEnabled = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasResolvedPath = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bDidRoundTripPass = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bSaveSucceeded = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bLoadSucceeded = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bCountsMatched = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bStateMatched = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bIntegrityMatched = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bDerivedMatched = false; + + bool IsStructurallyValid() const + { + return !StatusLine.IsEmpty() + || !DetailLine.IsEmpty() + || bVerifyEnabled + || bDidRoundTripPass; + } +}; + +USTRUCT(BlueprintType) +struct FHyperTwistTrainingCoachDashboardSelectedQueueNavigationInspectSurface +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString Headline; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString StatusLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString DetailLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString PreviousLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString NextLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SelectedQueueEntryId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SelectedQueueSourceLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SelectedQueueStateLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SelectedQueueOrdinal; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 SelectedQueueEntryIndex = INDEX_NONE; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 TotalQueueEntries = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasSelectedQueueEntry = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasLiveAttemptTimer = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bSelectedEntryMatchesActiveQueue = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bPreviousEnabled = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bNextEnabled = false; + + bool IsStructurallyValid() const + { + return !StatusLine.IsEmpty() + || !DetailLine.IsEmpty() + || bHasSelectedQueueEntry + || bPreviousEnabled + || bNextEnabled; + } +}; + +USTRUCT(BlueprintType) +struct FHyperTwistTrainingCoachDashboardStartSelectedQueueActionInspectSurface +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString Headline; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString StatusLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString DetailLine; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString StartSelectedLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SelectedQueueEntryId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SelectedQueueStateLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SelectedQueueSourceLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SelectedQueuePrimaryActionLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasSelectedQueueEntry = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasLiveAttemptTimer = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bSelectedEntryReady = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bSelectedEntryPendingStartImmediate = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bStartSelectedEnabled = false; + + bool IsStructurallyValid() const + { + return !StatusLine.IsEmpty() + || !DetailLine.IsEmpty() + || bStartSelectedEnabled + || bHasSelectedQueueEntry; + } +}; + USTRUCT(BlueprintType) struct FHyperTwistTrainingCoachDashboardLastAttemptReviewSummaryInspectSurface { diff --git a/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md b/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md index 6581b41..e12104e 100644 --- a/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md +++ b/docs/HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md @@ -69,8 +69,8 @@ Current correction call from the source-exposed audit and current execution refr - the latest landed bounded `Phase 4` packet closes the retained-idle comparison/outcome actionability gap at the end of the recognition-assisted coach-to-review continuity lane, and the final retained-surface confirmation pass now leaves that closure lane functionally complete - the retained idle widget surface now keeps retained comparison and decision history inspectable without continuing to advertise live launch or guidance-outcome actions once the coach-to-review loop has already collapsed to truthful closed-loop idle - the now-complete deliberate `UHyperTwistTrainingRuntimeLibrary` world-context consumer lane reaches through active generated-mode selector option owned-execution split-phase current-selection merged ordered roster phase-id lookup, normalized-order lookup, and evaluation-order lookup inspect surfaces, so gameplay/Blueprint callers can inspect one retained merged-roster row directly by phase id, normalized order, or evaluation order without scanning the merged roster array or re-running inspect derivation details directly - - the latest landed bounded `Phase 4` packet stays on that same live `UHyperTwistCoachDashboardWidget` guidance-consumer lane and adds attempt-review navigation, primary / continue / clear / complete run-control enablement, and queue defer / promote / recovery action enablement inspect surfaces over already-derived live dashboard review-navigation and execution-control presentation state, so gameplay/Blueprint callers can inspect retained attempt-review cycling plus the current run / queue-control labels and enablement without scraping widget buttons or reopening execution-control derivation - - the next clean move is to stay on that same live dashboard guidance-consumer lane and land the verification action, selected-queue navigation, and start-selected action enablement inspect surface group rather than drifting back into backend continuity or reopening the already-complete retained-history seam + - the latest landed bounded `Phase 4` packet stays on that same live `UHyperTwistCoachDashboardWidget` guidance-consumer lane and adds verification action, selected-queue navigation, and start-selected action enablement inspect surfaces over already-derived live dashboard verification and queue-control presentation state, so gameplay/Blueprint callers can inspect the verify action plus the current queue-navigation and selected-entry launch labels and enablement without scraping widget buttons or reopening queue-control derivation + - the next clean move is to stay on that same live dashboard guidance-consumer lane and land the queue counts/status, selected-queue summary, and selected queue-entry detail inspect surface group rather than drifting back into backend continuity or reopening the already-complete retained-history seam - 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 diff --git a/docs/arch/HYPERTWIST_PHASE4_DASHBOARD_LIVE_VERIFICATION_QUEUE_NAVIGATION_START_SELECTED_ACTION_ENABLEMENT_INSPECT_SURFACE_PACKET_2026-05-09.md b/docs/arch/HYPERTWIST_PHASE4_DASHBOARD_LIVE_VERIFICATION_QUEUE_NAVIGATION_START_SELECTED_ACTION_ENABLEMENT_INSPECT_SURFACE_PACKET_2026-05-09.md new file mode 100644 index 0000000..cd9340d --- /dev/null +++ b/docs/arch/HYPERTWIST_PHASE4_DASHBOARD_LIVE_VERIFICATION_QUEUE_NAVIGATION_START_SELECTED_ACTION_ENABLEMENT_INSPECT_SURFACE_PACKET_2026-05-09.md @@ -0,0 +1,55 @@ +# HyperTwist Phase 4 dashboard live verification, queue navigation, and start-selected action enablement inspect surface packet + +- bounded Phase `4` dashboard-consumer slice +- date: `2026-05-09` + +## Intent + +Stay on the deliberate live `UHyperTwistCoachDashboardWidget` guidance-consumer lane and expose the remaining verification and selected-queue execution controls directly to gameplay and Blueprint callers. + +## Why this packet exists + +The dashboard already derived: + +- the displayed `Verify` action label and the retained repository-verification posture behind it +- the displayed previous/next selected-queue navigation labels and their enablement posture +- the displayed `Start Selected` queue-action label and its selected-entry actionability posture + +But that live state still only surfaced through widget buttons. Callers still had to scrape button labels or enabled state to inspect what the dashboard was currently presenting. + +## What changed + +- added `FHyperTwistTrainingCoachDashboardVerificationActionInspectSurface` +- added `FHyperTwistTrainingCoachDashboardSelectedQueueNavigationInspectSurface` +- added `FHyperTwistTrainingCoachDashboardStartSelectedQueueActionInspectSurface` +- added `GetDisplayedVerificationActionInspectSurface()` +- added `GetDisplayedSelectedQueueNavigationInspectSurface()` +- added `GetDisplayedStartSelectedQueueActionInspectSurface()` +- retained the exact displayed verify, previous-queue, next-queue, and start-selected labels inside the widget so the new inspect surfaces report the same live strings the dashboard is already presenting +- kept the packet bounded to `UHyperTwistCoachDashboardWidget` plus shared surface types, with no dashboard redesign and no backend continuity changes + +## Files + +- `C:\HyperTwist\UnrealHyperTwist\Source\UnrealHyperTwist\Public\HyperTwistTraining\HyperTwistTrainingTypes.h` +- `C:\HyperTwist\UnrealHyperTwist\Source\UnrealHyperTwist\Public\HyperTwistTraining\HyperTwistCoachDashboardWidget.h` +- `C:\HyperTwist\UnrealHyperTwist\Source\UnrealHyperTwist\Private\HyperTwistTraining\HyperTwistCoachDashboardWidget.cpp` +- `C:\HyperTwist\docs\HYPERTWIST_ROADMAP_OVERHAUL_EXPANSION_GUIDE.md` + +## Outcome + +Gameplay and Blueprint callers can now inspect: + +- the verify action label, latest round-trip posture, and button availability +- the current selected-queue navigation labels, selection summary, and navigation enablement posture +- the start-selected action label plus the selected-entry runnable posture + +without scraping widget buttons or reopening queue-control derivation. + +## Validation + +- full `Development Editor | Win64` MSBuild on `UnrealHyperTwist.sln` + - passed with `0 Warning(s), 0 Error(s)` + +## Next clean slice + +Stay on the same live dashboard guidance-consumer lane and land the queue counts/status, selected-queue summary, and selected queue-entry detail inspect surface group.