Expose dashboard verification, recognition, and review-policy status surfaces

This commit is contained in:
axiomlogicnexus 2026-05-10 03:43:11 +02:00
parent 807e712b9b
commit ba7a41775b
5 changed files with 428 additions and 67 deletions

View file

@ -1977,6 +1977,89 @@ namespace HyperTwistCoachDashboardWidgetInternal
return TEXT("Unknown");
}
FString BuildDisplayedGeneratedLaunchRequestDetail(
const FHyperTwistTrainingCoachPanelState& PanelState
)
{
return PanelState.bHasLatestGeneratedModeLaunchRequest
? FString::Printf(
TEXT("Generated request: %s @ %s | mode: %s\nSelectors: %s"),
PanelState.LatestGeneratedModeLaunchRequestId.IsEmpty()
? TEXT("n/a")
: *PanelState.LatestGeneratedModeLaunchRequestId,
PanelState.LatestGeneratedModeLaunchRequestedAtUtc.IsEmpty()
? TEXT("n/a")
: *PanelState.LatestGeneratedModeLaunchRequestedAtUtc,
PanelState.LatestGeneratedModeRuntimeModeId.IsEmpty()
? TEXT("n/a")
: *PanelState.LatestGeneratedModeRuntimeModeId,
PanelState.LatestGeneratedModeSelectorSummaryLine.IsEmpty()
? TEXT("none")
: *PanelState.LatestGeneratedModeSelectorSummaryLine)
: TEXT("Generated request: none for active deck");
}
FString BuildDisplayedGeneratedExecutionDetail(
const FHyperTwistTrainingCoachPanelState& PanelState
)
{
return PanelState.bHasActiveGeneratedModeExecutionTarget
? FString::Printf(
TEXT("Generated execution ready: %s | Request refresh on execute: %s | Blocked: %s"),
PanelState.bCanExecuteActiveGeneratedModeLaunchRequest ? TEXT("yes") : TEXT("no"),
PanelState.bActiveGeneratedModeExecutionWillRefreshLaunchRequest
? TEXT("yes")
: TEXT("no"),
PanelState.ActiveGeneratedModeExecutionBlockedReason.IsEmpty()
? TEXT("none")
: *PanelState.ActiveGeneratedModeExecutionBlockedReason)
: TEXT("");
}
FString BuildDisplayedRepositoryVerificationDetailLine(
const FHyperTwistTrainingRepositoryRoundTripVerification& Verification,
const FString& VerificationNotePreview,
const FHyperTwistTrainingCoachPanelState& PanelState
)
{
const FString GeneratedLaunchRequestDetail =
BuildDisplayedGeneratedLaunchRequestDetail(PanelState);
const FString GeneratedExecutionDetail =
BuildDisplayedGeneratedExecutionDetail(PanelState);
const FString GeneratedExecutionSuffix = GeneratedExecutionDetail.IsEmpty()
? TEXT("")
: FString::Printf(TEXT("\n%s"), *GeneratedExecutionDetail);
return FString::Printf(
TEXT("Path: %s\nRound-trip pass: %s | Save: %s | Load: %s | Count parity: %s | State parity: %s | Integrity parity: %s | Derived parity: %s\nRuns %d/%d | Learners %d/%d | Reviews %d/%d | Plans %d/%d | Queues %d/%d | History %d/%d | Derived users %d | Derived queues %d | Notes: %s\n%s%s"),
Verification.ResolvedPath.IsEmpty()
? TEXT("not yet verified")
: *Verification.ResolvedPath,
Verification.bDidRoundTripPass ? TEXT("yes") : TEXT("no"),
Verification.bSaveSucceeded ? TEXT("yes") : TEXT("no"),
Verification.bLoadSucceeded ? TEXT("yes") : TEXT("no"),
Verification.bRepositoryCountsMatch ? TEXT("yes") : TEXT("no"),
Verification.bSerializedStateMatch ? TEXT("yes") : TEXT("no"),
Verification.bIntegrityReportMatch ? TEXT("yes") : TEXT("no"),
Verification.bDerivedStateMatch ? TEXT("yes") : TEXT("no"),
Verification.LoadedRunRecordCount,
Verification.ExpectedRunRecordCount,
Verification.LoadedLearnerStateCount,
Verification.ExpectedLearnerStateCount,
Verification.LoadedReviewPlanCount,
Verification.ExpectedReviewPlanCount,
Verification.LoadedCoachActionPlanCount,
Verification.ExpectedCoachActionPlanCount,
Verification.LoadedCoachSessionQueueCount,
Verification.ExpectedCoachSessionQueueCount,
Verification.LoadedCoachSessionQueueHistoryCount,
Verification.ExpectedCoachSessionQueueHistoryCount,
Verification.VerifiedDerivedUserCount,
Verification.VerifiedDerivedQueueCount,
*VerificationNotePreview,
*GeneratedLaunchRequestDetail,
*GeneratedExecutionSuffix);
}
bool IsTightCoachPlanPosture(
const EHyperTwistTrainingDeliveryMode SuggestedMode,
const EHyperTwistTrainingSelectionPolicy SuggestedSelectionPolicy)
@ -12269,6 +12352,108 @@ UHyperTwistCoachDashboardWidget::GetDisplayedVerificationActionInspectSurface()
return Surface;
}
FHyperTwistTrainingCoachDashboardRepositoryVerificationStatusInspectSurface
UHyperTwistCoachDashboardWidget::GetDisplayedRepositoryVerificationStatusInspectSurface() const
{
FHyperTwistTrainingCoachDashboardRepositoryVerificationStatusInspectSurface Surface;
Surface.Headline = TEXT("Repository verification status");
const FString VerificationNotePreview = CachedRepositoryRoundTripVerification.VerificationNotes.Num() > 0
? CachedRepositoryRoundTripVerification.VerificationNotes[0]
: TEXT("none");
Surface.RepositoryPath = CachedRepositoryRoundTripVerification.ResolvedPath.IsEmpty()
? TEXT("not yet verified")
: CachedRepositoryRoundTripVerification.ResolvedPath;
Surface.LatestNote = VerificationNotePreview;
Surface.GeneratedLaunchRequestDetail =
HyperTwistCoachDashboardWidgetInternal::BuildDisplayedGeneratedLaunchRequestDetail(
CachedCoachPanelState);
Surface.GeneratedExecutionDetail =
HyperTwistCoachDashboardWidgetInternal::BuildDisplayedGeneratedExecutionDetail(
CachedCoachPanelState);
Surface.StatusLine = !DisplayedVerificationStatusLine.IsEmpty()
? DisplayedVerificationStatusLine
: (CachedCoachPanelState.VerificationStatusLine.IsEmpty()
? TEXT("Repository verification status: not yet populated.")
: CachedCoachPanelState.VerificationStatusLine);
Surface.DetailLine = !DisplayedVerificationDetailLine.IsEmpty()
? DisplayedVerificationDetailLine
: HyperTwistCoachDashboardWidgetInternal::BuildDisplayedRepositoryVerificationDetailLine(
CachedRepositoryRoundTripVerification,
VerificationNotePreview,
CachedCoachPanelState);
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.bHasGeneratedLaunchRequest = CachedCoachPanelState.bHasLatestGeneratedModeLaunchRequest;
Surface.bHasGeneratedExecutionTarget = CachedCoachPanelState.bHasActiveGeneratedModeExecutionTarget;
Surface.bCanExecuteGeneratedLaunchRequest =
CachedCoachPanelState.bCanExecuteActiveGeneratedModeLaunchRequest;
Surface.bGeneratedExecutionWillRefreshRequest =
CachedCoachPanelState.bActiveGeneratedModeExecutionWillRefreshLaunchRequest;
return Surface;
}
FHyperTwistTrainingCoachDashboardRecognitionStatusInspectSurface
UHyperTwistCoachDashboardWidget::GetDisplayedRecognitionStatusInspectSurface() const
{
FHyperTwistTrainingCoachDashboardRecognitionStatusInspectSurface Surface;
Surface.Headline = TEXT("Recognition status");
const bool bHasActiveRun = CachedRunState.Session.IsStructurallyValid()
&& CachedRunState.ActiveDeck.IsStructurallyValid();
Surface.StatusLine = !DisplayedRecognitionStatusLine.IsEmpty()
? DisplayedRecognitionStatusLine
: (CachedCoachPanelState.RecognitionStatusLine.IsEmpty()
? TEXT("Recognition status: not yet populated.")
: CachedCoachPanelState.RecognitionStatusLine);
Surface.DetailLine = !DisplayedRecognitionDetailLine.IsEmpty()
? DisplayedRecognitionDetailLine
: CachedCoachPanelState.RecognitionDetailLine;
Surface.RunModeLabel = bHasActiveRun
? HyperTwistCoachDashboardWidgetInternal::EnumDisplayName(CachedRunState.Session.Mode)
: TEXT("n/a");
Surface.bHasActiveRun = bHasActiveRun;
Surface.bHasLiveAttemptTimer = bHasLiveAttemptTimer;
Surface.bHasRecognitionStatus = !CachedCoachPanelState.RecognitionStatusLine.IsEmpty();
Surface.bHasRecognitionDetail = !CachedCoachPanelState.RecognitionDetailLine.IsEmpty();
return Surface;
}
FHyperTwistTrainingCoachDashboardReviewPolicyStatusInspectSurface
UHyperTwistCoachDashboardWidget::GetDisplayedReviewPolicyStatusInspectSurface() const
{
FHyperTwistTrainingCoachDashboardReviewPolicyStatusInspectSurface Surface;
Surface.Headline = TEXT("Review-policy status");
const bool bHasActiveRun = CachedRunState.Session.IsStructurallyValid()
&& CachedRunState.ActiveDeck.IsStructurallyValid();
const bool bHasRunnableCurrentCase =
bHasActiveRun && CachedRunState.CurrentSelection.TrainingCase.IsStructurallyValid();
Surface.StatusLine = !DisplayedReviewPolicyStatusLine.IsEmpty()
? DisplayedReviewPolicyStatusLine
: (CachedCoachPanelState.ReviewPolicyStatusLine.IsEmpty()
? TEXT("Review-policy status: not yet populated.")
: CachedCoachPanelState.ReviewPolicyStatusLine);
Surface.DetailLine = !DisplayedReviewPolicyDetailLine.IsEmpty()
? DisplayedReviewPolicyDetailLine
: CachedCoachPanelState.ReviewPolicyDetailLine;
Surface.RunModeLabel = bHasActiveRun
? HyperTwistCoachDashboardWidgetInternal::EnumDisplayName(CachedRunState.Session.Mode)
: TEXT("n/a");
Surface.bHasActiveRun = bHasActiveRun;
Surface.bHasLiveAttemptTimer = bHasLiveAttemptTimer;
Surface.bHasRunnableCurrentCase = bHasRunnableCurrentCase;
Surface.bHasReviewPolicyStatus = !CachedCoachPanelState.ReviewPolicyStatusLine.IsEmpty();
Surface.bHasReviewPolicyDetail = !CachedCoachPanelState.ReviewPolicyDetailLine.IsEmpty();
return Surface;
}
FHyperTwistTrainingCoachDashboardSelectedQueueNavigationInspectSurface
UHyperTwistCoachDashboardWidget::GetDisplayedSelectedQueueNavigationInspectSurface() const
{
@ -25629,23 +25814,28 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
}
if (VerificationStatusTextBlock != nullptr)
{
VerificationStatusTextBlock->SetText(FText::FromString(CachedCoachPanelState.VerificationStatusLine));
DisplayedVerificationStatusLine = CachedCoachPanelState.VerificationStatusLine;
VerificationStatusTextBlock->SetText(FText::FromString(DisplayedVerificationStatusLine));
}
if (RecognitionStatusTextBlock != nullptr)
{
RecognitionStatusTextBlock->SetText(FText::FromString(CachedCoachPanelState.RecognitionStatusLine));
DisplayedRecognitionStatusLine = CachedCoachPanelState.RecognitionStatusLine;
RecognitionStatusTextBlock->SetText(FText::FromString(DisplayedRecognitionStatusLine));
}
if (RecognitionDetailTextBlock != nullptr)
{
RecognitionDetailTextBlock->SetText(FText::FromString(CachedCoachPanelState.RecognitionDetailLine));
DisplayedRecognitionDetailLine = CachedCoachPanelState.RecognitionDetailLine;
RecognitionDetailTextBlock->SetText(FText::FromString(DisplayedRecognitionDetailLine));
}
if (ReviewPolicyStatusTextBlock != nullptr)
{
ReviewPolicyStatusTextBlock->SetText(FText::FromString(CachedCoachPanelState.ReviewPolicyStatusLine));
DisplayedReviewPolicyStatusLine = CachedCoachPanelState.ReviewPolicyStatusLine;
ReviewPolicyStatusTextBlock->SetText(FText::FromString(DisplayedReviewPolicyStatusLine));
}
if (ReviewPolicyDetailTextBlock != nullptr)
{
ReviewPolicyDetailTextBlock->SetText(FText::FromString(CachedCoachPanelState.ReviewPolicyDetailLine));
DisplayedReviewPolicyDetailLine = CachedCoachPanelState.ReviewPolicyDetailLine;
ReviewPolicyDetailTextBlock->SetText(FText::FromString(DisplayedReviewPolicyDetailLine));
}
if (VerificationHeaderTextBlock != nullptr)
{
@ -25653,66 +25843,12 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
}
if (VerificationDetailTextBlock != nullptr)
{
const FString GeneratedLaunchRequestDetail = CachedCoachPanelState.bHasLatestGeneratedModeLaunchRequest
? FString::Printf(
TEXT("\nGenerated request: %s @ %s | mode: %s\nSelectors: %s"),
CachedCoachPanelState.LatestGeneratedModeLaunchRequestId.IsEmpty()
? TEXT("n/a")
: *CachedCoachPanelState.LatestGeneratedModeLaunchRequestId,
CachedCoachPanelState.LatestGeneratedModeLaunchRequestedAtUtc.IsEmpty()
? TEXT("n/a")
: *CachedCoachPanelState.LatestGeneratedModeLaunchRequestedAtUtc,
CachedCoachPanelState.LatestGeneratedModeRuntimeModeId.IsEmpty()
? TEXT("n/a")
: *CachedCoachPanelState.LatestGeneratedModeRuntimeModeId,
CachedCoachPanelState.LatestGeneratedModeSelectorSummaryLine.IsEmpty()
? TEXT("none")
: *CachedCoachPanelState.LatestGeneratedModeSelectorSummaryLine
)
: TEXT("\nGenerated request: none for active deck");
const FString GeneratedExecutionDetail =
CachedCoachPanelState.bHasActiveGeneratedModeExecutionTarget
? FString::Printf(
TEXT("\nGenerated execution ready: %s | Request refresh on execute: %s | Blocked: %s"),
CachedCoachPanelState.bCanExecuteActiveGeneratedModeLaunchRequest ? TEXT("yes") : TEXT("no"),
CachedCoachPanelState.bActiveGeneratedModeExecutionWillRefreshLaunchRequest
? TEXT("yes")
: TEXT("no"),
CachedCoachPanelState.ActiveGeneratedModeExecutionBlockedReason.IsEmpty()
? TEXT("none")
: *CachedCoachPanelState.ActiveGeneratedModeExecutionBlockedReason
)
: TEXT("");
VerificationDetailTextBlock->SetText(FText::FromString(FString::Printf(
TEXT("Path: %s\nRound-trip pass: %s | Save: %s | Load: %s | Count parity: %s | State parity: %s | Integrity parity: %s | Derived parity: %s\nRuns %d/%d | Learners %d/%d | Reviews %d/%d | Plans %d/%d | Queues %d/%d | History %d/%d | Derived users %d | Derived queues %d | Notes: %s%s%s"),
CachedRepositoryRoundTripVerification.ResolvedPath.IsEmpty()
? TEXT("not yet verified")
: *CachedRepositoryRoundTripVerification.ResolvedPath,
CachedRepositoryRoundTripVerification.bDidRoundTripPass ? TEXT("yes") : TEXT("no"),
CachedRepositoryRoundTripVerification.bSaveSucceeded ? TEXT("yes") : TEXT("no"),
CachedRepositoryRoundTripVerification.bLoadSucceeded ? TEXT("yes") : TEXT("no"),
CachedRepositoryRoundTripVerification.bRepositoryCountsMatch ? TEXT("yes") : TEXT("no"),
CachedRepositoryRoundTripVerification.bSerializedStateMatch ? TEXT("yes") : TEXT("no"),
CachedRepositoryRoundTripVerification.bIntegrityReportMatch ? TEXT("yes") : TEXT("no"),
CachedRepositoryRoundTripVerification.bDerivedStateMatch ? TEXT("yes") : TEXT("no"),
CachedRepositoryRoundTripVerification.LoadedRunRecordCount,
CachedRepositoryRoundTripVerification.ExpectedRunRecordCount,
CachedRepositoryRoundTripVerification.LoadedLearnerStateCount,
CachedRepositoryRoundTripVerification.ExpectedLearnerStateCount,
CachedRepositoryRoundTripVerification.LoadedReviewPlanCount,
CachedRepositoryRoundTripVerification.ExpectedReviewPlanCount,
CachedRepositoryRoundTripVerification.LoadedCoachActionPlanCount,
CachedRepositoryRoundTripVerification.ExpectedCoachActionPlanCount,
CachedRepositoryRoundTripVerification.LoadedCoachSessionQueueCount,
CachedRepositoryRoundTripVerification.ExpectedCoachSessionQueueCount,
CachedRepositoryRoundTripVerification.LoadedCoachSessionQueueHistoryCount,
CachedRepositoryRoundTripVerification.ExpectedCoachSessionQueueHistoryCount,
CachedRepositoryRoundTripVerification.VerifiedDerivedUserCount,
CachedRepositoryRoundTripVerification.VerifiedDerivedQueueCount,
*VerificationNotePreview,
*GeneratedLaunchRequestDetail,
*GeneratedExecutionDetail
)));
DisplayedVerificationDetailLine =
HyperTwistCoachDashboardWidgetInternal::BuildDisplayedRepositoryVerificationDetailLine(
CachedRepositoryRoundTripVerification,
VerificationNotePreview,
CachedCoachPanelState);
VerificationDetailTextBlock->SetText(FText::FromString(DisplayedVerificationDetailLine));
}
FString PrimaryLabel = CachedCoachPanelState.PrimaryActionLabel;

View file

@ -887,6 +887,18 @@ public:
FHyperTwistTrainingCoachDashboardVerificationActionInspectSurface
GetDisplayedVerificationActionInspectSurface() const;
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
FHyperTwistTrainingCoachDashboardRepositoryVerificationStatusInspectSurface
GetDisplayedRepositoryVerificationStatusInspectSurface() const;
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
FHyperTwistTrainingCoachDashboardRecognitionStatusInspectSurface
GetDisplayedRecognitionStatusInspectSurface() const;
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
FHyperTwistTrainingCoachDashboardReviewPolicyStatusInspectSurface
GetDisplayedReviewPolicyStatusInspectSurface() const;
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
FHyperTwistTrainingCoachDashboardSelectedQueueNavigationInspectSurface
GetDisplayedSelectedQueueNavigationInspectSurface() const;
@ -2001,6 +2013,12 @@ private:
FString DisplayedFollowUpDeckPreviewLine;
FString DisplayedPrimaryActionLabel;
FString DisplayedVerificationActionLabel;
FString DisplayedVerificationStatusLine;
FString DisplayedVerificationDetailLine;
FString DisplayedRecognitionStatusLine;
FString DisplayedRecognitionDetailLine;
FString DisplayedReviewPolicyStatusLine;
FString DisplayedReviewPolicyDetailLine;
FString DisplayedDeferQueueActionLabel;
FString DisplayedPromoteQueueActionLabel;
FString DisplayedQueueRecoveryActionLabel;

View file

@ -11833,6 +11833,156 @@ struct FHyperTwistTrainingCoachDashboardVerificationActionInspectSurface
}
};
USTRUCT(BlueprintType)
struct FHyperTwistTrainingCoachDashboardRepositoryVerificationStatusInspectSurface
{
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 RepositoryPath;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString LatestNote;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString GeneratedLaunchRequestDetail;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString GeneratedExecutionDetail;
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;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasGeneratedLaunchRequest = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasGeneratedExecutionTarget = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bCanExecuteGeneratedLaunchRequest = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bGeneratedExecutionWillRefreshRequest = false;
bool IsStructurallyValid() const
{
return !StatusLine.IsEmpty()
|| !DetailLine.IsEmpty()
|| bDidRoundTripPass
|| bHasGeneratedLaunchRequest;
}
};
USTRUCT(BlueprintType)
struct FHyperTwistTrainingCoachDashboardRecognitionStatusInspectSurface
{
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 RunModeLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasActiveRun = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasLiveAttemptTimer = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasRecognitionStatus = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasRecognitionDetail = false;
bool IsStructurallyValid() const
{
return !StatusLine.IsEmpty()
|| !DetailLine.IsEmpty()
|| bHasRecognitionStatus
|| bHasRecognitionDetail;
}
};
USTRUCT(BlueprintType)
struct FHyperTwistTrainingCoachDashboardReviewPolicyStatusInspectSurface
{
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 RunModeLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasActiveRun = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasLiveAttemptTimer = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasRunnableCurrentCase = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasReviewPolicyStatus = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasReviewPolicyDetail = false;
bool IsStructurallyValid() const
{
return !StatusLine.IsEmpty()
|| !DetailLine.IsEmpty()
|| bHasReviewPolicyStatus
|| bHasReviewPolicyDetail;
}
};
USTRUCT(BlueprintType)
struct FHyperTwistTrainingCoachDashboardSelectedQueueNavigationInspectSurface
{

View file

@ -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 retained-history navigation/control lane and adds the template launch history navigation control inspect surface over already-retained template-backed runs, so gameplay/Blueprint callers can inspect the live prev/next template-launch labels, enablement posture, selected retained launch ordinal, and template/state/analytics/latest-selection context without scraping button text or reopening retained-history derivation
- the retained-history navigation/control lane now appears complete enough to reassess whether to pivot deliberately into the next broader `Phase 4` roadmap lane rather than widening this seam by drift
- the latest landed bounded `Phase 4` packet pivots deliberately into a fresh live dashboard verification/recognition/review-policy status lane and adds displayed repository verification status, displayed recognition status, and displayed review-policy status inspect surfaces over already-derived coach panel and repository verification state, so gameplay/Blueprint callers can inspect the exact displayed verification band, recognition posture, and review-policy lines without scraping widget text or reopening those derivation paths
- the next best clean move is to stay adjacent in that same live dashboard consumer band and expose the main queue-recovery live status/detail inspect pair rather than drifting back into retained-history navigation wrappers or backend continuity
- 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
## Donor portfolio phase taxonomy

View file

@ -0,0 +1,57 @@
# HyperTwist Phase 4 dashboard live verification, recognition, and review-policy status inspect surface packet
- bounded Phase `4` dashboard-consumer slice
- date: `2026-05-10`
## Intent
Pivot deliberately out of the now-complete retained-history navigation/control seam and expose the live verification / recognition / review-policy dashboard band directly to gameplay and Blueprint callers.
## Why this packet exists
`UHyperTwistCoachDashboardWidget` already displayed:
- the repository verification status line
- the repository verification detail block, including generated-mode request / execution context
- the recognition status and detail lines
- the review-policy status and detail lines
But that presentation state still only surfaced through widget text blocks. Callers still had to scrape UI text to understand the live verification band, recognition posture, and review-policy posture.
## What changed
- added `FHyperTwistTrainingCoachDashboardRepositoryVerificationStatusInspectSurface`
- added `FHyperTwistTrainingCoachDashboardRecognitionStatusInspectSurface`
- added `FHyperTwistTrainingCoachDashboardReviewPolicyStatusInspectSurface`
- added `GetDisplayedRepositoryVerificationStatusInspectSurface()`
- added `GetDisplayedRecognitionStatusInspectSurface()`
- added `GetDisplayedReviewPolicyStatusInspectSurface()`
- retained the exact displayed verification / recognition / review-policy lines inside the widget so the new surfaces report the same live strings the dashboard is already presenting
- factored the repository-verification detail assembly into shared widget-local helpers so the displayed verification detail block and the new inspect surface stay aligned
## 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 exact displayed repository verification status line
- the exact displayed repository verification detail block, including generated launch-request and generated execution detail
- the exact displayed recognition status/detail lines
- the exact displayed review-policy status/detail lines
without scraping widget text or reopening those derivation paths.
## Validation
- full `Development Editor | Win64` MSBuild on `UnrealHyperTwist.sln`
- passed with `0 Warning(s), 0 Error(s)`
## Next clean slice
Stay adjacent in the live dashboard consumer band and expose the main queue-recovery live status/detail inspect pair.