Expose dashboard handoff, transition, and action-label surfaces
This commit is contained in:
parent
5ab380abfe
commit
67ec0915cb
5 changed files with 638 additions and 2 deletions
|
|
@ -10385,6 +10385,346 @@ UHyperTwistCoachDashboardWidget::GetDisplayedCoachHandoffRecommendationInspectSu
|
|||
return Surface;
|
||||
}
|
||||
|
||||
FHyperTwistTrainingCoachDashboardHandoffStatusInspectSurface
|
||||
UHyperTwistCoachDashboardWidget::GetDisplayedCoachHandoffStatusInspectSurface() const
|
||||
{
|
||||
FHyperTwistTrainingCoachDashboardHandoffStatusInspectSurface Surface;
|
||||
Surface.Headline = TEXT("Coach handoff status");
|
||||
|
||||
const bool bHasActiveRun = CachedRunState.Session.IsStructurallyValid()
|
||||
&& CachedRunState.ActiveDeck.IsStructurallyValid();
|
||||
Surface.bHasLiveAttemptTimer = bHasLiveAttemptTimer;
|
||||
Surface.bHasActiveRun = bHasActiveRun;
|
||||
Surface.bQueueReady = CachedCoachPanelState.bCanStartQueuedRun;
|
||||
Surface.bFollowUpReady =
|
||||
CachedCoachPanelState.bCanStartCoachFollowUpRun
|
||||
&& CachedCoachPanelState.bHasFollowUpGuidance;
|
||||
Surface.bRecommendedReady = CachedCoachPanelState.bCanStartCoachRecommendedRun;
|
||||
Surface.QueueSourceLabel =
|
||||
CachedCoachPanelState.NextQueueSourceLabel.IsEmpty()
|
||||
? TEXT("n/a")
|
||||
: CachedCoachPanelState.NextQueueSourceLabel;
|
||||
Surface.FollowUpBriefHeadline =
|
||||
CachedCoachFollowUpBrief.Headline.IsEmpty() ? TEXT("n/a") : CachedCoachFollowUpBrief.Headline;
|
||||
Surface.RecommendedBriefHeadline =
|
||||
CachedCoachBrief.Headline.IsEmpty() ? TEXT("n/a") : CachedCoachBrief.Headline;
|
||||
Surface.FollowUpFocusCaseCount = CachedCoachFollowUpBrief.FocusCaseIds.Num();
|
||||
Surface.RecommendedFocusCaseCount = CachedCoachBrief.FocusCaseIds.Num();
|
||||
Surface.QueueStatusLabel = Surface.bQueueReady
|
||||
? FString::Printf(TEXT("queue ready from %s"), *Surface.QueueSourceLabel)
|
||||
: TEXT("queue not ready");
|
||||
Surface.FollowUpStatusLabel = Surface.bFollowUpReady
|
||||
? FString::Printf(
|
||||
TEXT("follow-up %s (%d cases)"),
|
||||
CachedCoachFollowUpBrief.Headline.IsEmpty() ? TEXT("ready") : *CachedCoachFollowUpBrief.Headline,
|
||||
Surface.FollowUpFocusCaseCount)
|
||||
: TEXT("follow-up not ready");
|
||||
Surface.RecommendedStatusLabel = Surface.bRecommendedReady
|
||||
? FString::Printf(
|
||||
TEXT("recommended %s (%d cases)"),
|
||||
CachedCoachBrief.Headline.IsEmpty() ? TEXT("ready") : *CachedCoachBrief.Headline,
|
||||
Surface.RecommendedFocusCaseCount)
|
||||
: TEXT("recommended not ready");
|
||||
|
||||
const bool bQueueRecoveryMemorySource =
|
||||
HyperTwistCoachDashboardWidgetInternal::IsQueueRecoveryMemorySource(
|
||||
CachedCoachPanelState.PreferredGuidanceSourceLabel);
|
||||
Surface.bClosedLoopIdleDashboard =
|
||||
IsCoachLoopActionabilityClosed()
|
||||
&& (
|
||||
bQueueRecoveryMemorySource
|
||||
|| !CachedCoachPanelState.PreferredGuidanceSourceLabel.IsEmpty()
|
||||
|| DisplayedCoachHandoffRecommendationKind != EHyperTwistTrainingCoachHandoffKind::None);
|
||||
|
||||
Surface.StatusLine = !DisplayedCoachHandoffStatusLine.IsEmpty()
|
||||
? DisplayedCoachHandoffStatusLine
|
||||
: FString::Printf(
|
||||
TEXT("Coach handoff: %s | %s | %s"),
|
||||
*Surface.QueueStatusLabel,
|
||||
*Surface.FollowUpStatusLabel,
|
||||
*Surface.RecommendedStatusLabel);
|
||||
if (Surface.bClosedLoopIdleDashboard)
|
||||
{
|
||||
Surface.DetailLine =
|
||||
TEXT("Coach handoff detail: retained readiness posture remains inspectable, but no queued, follow-up, or recommended continuation is active in the closed-loop idle state.");
|
||||
}
|
||||
else if (Surface.bHasLiveAttemptTimer)
|
||||
{
|
||||
Surface.DetailLine =
|
||||
TEXT("Coach handoff detail: live attempt or inspection is active, so coach-directed handoff launch surfaces are intentionally paused.");
|
||||
}
|
||||
else if (Surface.bHasActiveRun)
|
||||
{
|
||||
Surface.DetailLine =
|
||||
TEXT("Coach handoff detail: an active run is still owned by the dashboard; finish, clear, or complete it before launching another coach-directed run.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Surface.DetailLine = FString::Printf(
|
||||
TEXT("Coach handoff detail: %s | %s | %s"),
|
||||
*Surface.QueueStatusLabel,
|
||||
*Surface.FollowUpStatusLabel,
|
||||
*Surface.RecommendedStatusLabel);
|
||||
}
|
||||
return Surface;
|
||||
}
|
||||
|
||||
FHyperTwistTrainingCoachDashboardTransitionStatusInspectSurface
|
||||
UHyperTwistCoachDashboardWidget::GetDisplayedTransitionStatusInspectSurface() const
|
||||
{
|
||||
FHyperTwistTrainingCoachDashboardTransitionStatusInspectSurface Surface;
|
||||
Surface.Headline = TEXT("Transition");
|
||||
|
||||
const bool bHasActiveRun = CachedRunState.Session.IsStructurallyValid()
|
||||
&& CachedRunState.ActiveDeck.IsStructurallyValid();
|
||||
const FString ActiveCaseId = CachedRunState.CurrentSelection.TrainingCase.CaseId.IsEmpty()
|
||||
? TEXT("n/a")
|
||||
: CachedRunState.CurrentSelection.TrainingCase.CaseId;
|
||||
const FString ActivePromptLabel =
|
||||
CachedRunState.CurrentSelection.TrainingCase.PromptLabel.IsEmpty()
|
||||
? ActiveCaseId
|
||||
: CachedRunState.CurrentSelection.TrainingCase.PromptLabel;
|
||||
const bool bLiveInspectionPhase = IsLiveAttemptInspectionPhase();
|
||||
const bool bLiveSolvePhase = bHasLiveAttemptTimer
|
||||
&& LiveAttemptPhase == EHyperTwistCoachDashboardAttemptPhase::Solving;
|
||||
const bool bHasSessionScopedLastStep = !LastStepResult.SessionSummary.TrainingSessionId.IsEmpty()
|
||||
&& LastStepResult.SessionSummary.TrainingSessionId == CachedRunState.Session.TrainingSessionId;
|
||||
const bool bLastStepCompletedRun = bHasSessionScopedLastStep
|
||||
&& (LastStepResult.AttemptResolution.UpdatedSession.SessionState
|
||||
== EHyperTwistTrainingSessionState::Completed
|
||||
|| LastStepResult.AttemptResolution.UpdatedSession.SessionState
|
||||
== EHyperTwistTrainingSessionState::Aborted);
|
||||
const bool bHasNextCaseFromLastStep = bHasSessionScopedLastStep
|
||||
&& LastStepResult.AttemptResolution.NextCaseSelection.IsStructurallyValid();
|
||||
const bool bGeneratedModeLaunchDeck =
|
||||
HyperTwistCoachDashboardWidgetInternal::IsGeneratedModeLaunchDeck(CachedRunState);
|
||||
const bool bCanExecuteGeneratedModeLaunch =
|
||||
bGeneratedModeLaunchDeck
|
||||
&& CachedCoachPanelState.bCanExecuteActiveGeneratedModeLaunchRequest;
|
||||
const bool bRecognitionAssistedCurrentRun =
|
||||
CachedRunState.Session.Mode == EHyperTwistTrainingDeliveryMode::RecognitionAssisted;
|
||||
const bool bRecognitionSessionOpenForCurrentRun =
|
||||
!bRecognitionAssistedCurrentRun || CachedRecognitionSessionState.bSessionOpen;
|
||||
const bool bRecognitionServiceReadyForCurrentRun =
|
||||
!bRecognitionAssistedCurrentRun || CachedRecognitionSessionState.ServiceHealth.bReady;
|
||||
const FString RecognitionRunBlockedReason =
|
||||
!CachedRecognitionSessionState.LastError.IsEmpty()
|
||||
? CachedRecognitionSessionState.LastError
|
||||
: (!CachedRecognitionSessionState.ServiceHealth.LastError.IsEmpty()
|
||||
? CachedRecognitionSessionState.ServiceHealth.LastError
|
||||
: TEXT("recognition-session-not-open"));
|
||||
const bool bHasRunnableCurrentCase =
|
||||
bHasActiveRun && CachedRunState.CurrentSelection.TrainingCase.IsStructurallyValid();
|
||||
const bool bCanContinueCurrentRun = !bHasLiveAttemptTimer
|
||||
&& bHasRunnableCurrentCase
|
||||
&& !bLastStepCompletedRun
|
||||
&& (!bRecognitionAssistedCurrentRun
|
||||
|| bRecognitionSessionOpenForCurrentRun
|
||||
|| bRecognitionServiceReadyForCurrentRun)
|
||||
&& (!bGeneratedModeLaunchDeck || bCanExecuteGeneratedModeLaunch);
|
||||
const bool bCanLaunchCoachRun = !bHasLiveAttemptTimer
|
||||
&& (
|
||||
CachedCoachPanelState.bCanStartQueuedRun
|
||||
|| CachedCoachPanelState.bCanStartCoachFollowUpRun
|
||||
|| CachedCoachPanelState.bCanStartCoachRecommendedRun);
|
||||
FString TransitionLaunchLabel = CachedCoachPanelState.PrimaryActionLabel;
|
||||
if (TransitionLaunchLabel.IsEmpty())
|
||||
{
|
||||
TransitionLaunchLabel = TEXT("Launch Coach Run");
|
||||
}
|
||||
|
||||
Surface.TransitionLaunchLabel = TransitionLaunchLabel;
|
||||
Surface.ActiveCaseId = ActiveCaseId;
|
||||
Surface.ActivePromptLabel = ActivePromptLabel;
|
||||
Surface.RecognitionBlockedReason = RecognitionRunBlockedReason;
|
||||
Surface.AttemptCount = CachedRunSummary.AttemptCount;
|
||||
Surface.bHasLiveAttemptTimer = bHasLiveAttemptTimer;
|
||||
Surface.bLiveInspectionPhase = bLiveInspectionPhase;
|
||||
Surface.bLiveSolvePhase = bLiveSolvePhase;
|
||||
Surface.bHasActiveRun = bHasActiveRun;
|
||||
Surface.bLastStepCompletedRun = bLastStepCompletedRun;
|
||||
Surface.bHasNextCaseFromLastStep = bHasNextCaseFromLastStep;
|
||||
Surface.bGeneratedModeLaunchDeck = bGeneratedModeLaunchDeck;
|
||||
Surface.bCanExecuteGeneratedModeLaunch = bCanExecuteGeneratedModeLaunch;
|
||||
Surface.bRecognitionAssistedCurrentRun = bRecognitionAssistedCurrentRun;
|
||||
Surface.bRecognitionSessionOpenForCurrentRun = bRecognitionSessionOpenForCurrentRun;
|
||||
Surface.bRecognitionServiceReadyForCurrentRun = bRecognitionServiceReadyForCurrentRun;
|
||||
Surface.bCanContinueCurrentRun = bCanContinueCurrentRun;
|
||||
Surface.bCanLaunchCoachRun = bCanLaunchCoachRun;
|
||||
|
||||
const bool bQueueRecoveryMemorySource =
|
||||
HyperTwistCoachDashboardWidgetInternal::IsQueueRecoveryMemorySource(
|
||||
CachedCoachPanelState.PreferredGuidanceSourceLabel);
|
||||
Surface.bClosedLoopIdleDashboard =
|
||||
IsCoachLoopActionabilityClosed()
|
||||
&& (
|
||||
bQueueRecoveryMemorySource
|
||||
|| !CachedCoachPanelState.PreferredGuidanceSourceLabel.IsEmpty()
|
||||
|| DisplayedCoachHandoffRecommendationKind != EHyperTwistTrainingCoachHandoffKind::None);
|
||||
|
||||
Surface.StatusLine = !DisplayedTransitionStatusLine.IsEmpty()
|
||||
? DisplayedTransitionStatusLine
|
||||
: FString::Printf(TEXT("Transition: no run is active. Use the next-step action to %s."), *TransitionLaunchLabel);
|
||||
if (Surface.bClosedLoopIdleDashboard)
|
||||
{
|
||||
Surface.DetailLine =
|
||||
TEXT("Transition detail: the coach-to-review loop is closed and idle, so no runnable continuation or coach-directed launch remains active.");
|
||||
}
|
||||
else if (Surface.bLiveInspectionPhase)
|
||||
{
|
||||
Surface.DetailLine = FString::Printf(
|
||||
TEXT("Transition detail: inspection is live on %s."),
|
||||
*Surface.ActivePromptLabel);
|
||||
}
|
||||
else if (Surface.bLiveSolvePhase)
|
||||
{
|
||||
Surface.DetailLine = FString::Printf(
|
||||
TEXT("Transition detail: solve is live on %s."),
|
||||
*Surface.ActivePromptLabel);
|
||||
}
|
||||
else if (Surface.bLastStepCompletedRun)
|
||||
{
|
||||
Surface.DetailLine = FString::Printf(
|
||||
TEXT("Transition detail: last step completed the run after case %s | coach launch available: %s"),
|
||||
LastStepResult.SessionSummary.LastCaseId.IsEmpty()
|
||||
? TEXT("n/a")
|
||||
: *LastStepResult.SessionSummary.LastCaseId,
|
||||
Surface.bCanLaunchCoachRun ? TEXT("yes") : TEXT("no"));
|
||||
}
|
||||
else if (Surface.bGeneratedModeLaunchDeck)
|
||||
{
|
||||
Surface.DetailLine = FString::Printf(
|
||||
TEXT("Transition detail: generated-mode launch deck is active on %s | execute ready: %s"),
|
||||
*Surface.ActivePromptLabel,
|
||||
Surface.bCanExecuteGeneratedModeLaunch ? TEXT("yes") : TEXT("no"));
|
||||
}
|
||||
else if (Surface.bRecognitionAssistedCurrentRun)
|
||||
{
|
||||
Surface.DetailLine = FString::Printf(
|
||||
TEXT("Transition detail: recognition-assisted run on %s | session open: %s | service ready: %s | blocked reason: %s"),
|
||||
*Surface.ActivePromptLabel,
|
||||
Surface.bRecognitionSessionOpenForCurrentRun ? TEXT("yes") : TEXT("no"),
|
||||
Surface.bRecognitionServiceReadyForCurrentRun ? TEXT("yes") : TEXT("no"),
|
||||
*Surface.RecognitionBlockedReason);
|
||||
}
|
||||
else if (Surface.bCanContinueCurrentRun)
|
||||
{
|
||||
Surface.DetailLine = FString::Printf(
|
||||
TEXT("Transition detail: runnable case %s | attempts %d | next-case-from-last-step: %s"),
|
||||
*Surface.ActivePromptLabel,
|
||||
Surface.AttemptCount,
|
||||
Surface.bHasNextCaseFromLastStep ? TEXT("yes") : TEXT("no"));
|
||||
}
|
||||
else if (Surface.bHasActiveRun)
|
||||
{
|
||||
Surface.DetailLine =
|
||||
TEXT("Transition detail: an active run exists but no runnable current case remains.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Surface.DetailLine = FString::Printf(
|
||||
TEXT("Transition detail: no run is active | coach launch available: %s | launch label: %s"),
|
||||
Surface.bCanLaunchCoachRun ? TEXT("yes") : TEXT("no"),
|
||||
*Surface.TransitionLaunchLabel);
|
||||
}
|
||||
return Surface;
|
||||
}
|
||||
|
||||
FHyperTwistTrainingCoachDashboardRunActionLabelsInspectSurface
|
||||
UHyperTwistCoachDashboardWidget::GetDisplayedRunActionLabelsInspectSurface() const
|
||||
{
|
||||
FHyperTwistTrainingCoachDashboardRunActionLabelsInspectSurface Surface;
|
||||
Surface.Headline = TEXT("Run action labels");
|
||||
|
||||
const auto DescribeDisplayedHandoffKind = [](const EHyperTwistTrainingCoachHandoffKind Kind) -> FString
|
||||
{
|
||||
switch (Kind)
|
||||
{
|
||||
case EHyperTwistTrainingCoachHandoffKind::Queue:
|
||||
return TEXT("queue");
|
||||
case EHyperTwistTrainingCoachHandoffKind::FollowUp:
|
||||
return TEXT("follow-up");
|
||||
case EHyperTwistTrainingCoachHandoffKind::Recommended:
|
||||
return TEXT("recommended");
|
||||
default:
|
||||
return TEXT("none");
|
||||
}
|
||||
};
|
||||
|
||||
FString TransitionLaunchLabel = CachedCoachPanelState.PrimaryActionLabel;
|
||||
if (TransitionLaunchLabel.IsEmpty())
|
||||
{
|
||||
TransitionLaunchLabel = TEXT("Launch Coach Run");
|
||||
}
|
||||
|
||||
Surface.ContinueRunLabel =
|
||||
DisplayedContinueRunLabel.IsEmpty() ? TransitionLaunchLabel : DisplayedContinueRunLabel;
|
||||
Surface.QueuedRunLabel =
|
||||
DisplayedQueuedRunLabel.IsEmpty() ? TEXT("Start Queue") : DisplayedQueuedRunLabel;
|
||||
Surface.FollowUpRunLabel =
|
||||
DisplayedFollowUpRunLabel.IsEmpty() ? TEXT("Start Follow-Up") : DisplayedFollowUpRunLabel;
|
||||
Surface.RecommendedRunLabel =
|
||||
DisplayedRecommendedRunLabel.IsEmpty() ? TEXT("Start Recommended") : DisplayedRecommendedRunLabel;
|
||||
Surface.RecommendedHandoffKindLabel =
|
||||
DescribeDisplayedHandoffKind(DisplayedCoachHandoffRecommendationKind);
|
||||
Surface.TransitionLaunchLabel = TransitionLaunchLabel;
|
||||
Surface.bContinueUsesRecognitionPrimeLabel =
|
||||
Surface.ContinueRunLabel == TEXT("Prime Recognition")
|
||||
|| Surface.ContinueRunLabel == TEXT("Recognition Blocked");
|
||||
Surface.bContinueUsesGeneratedModeExecuteLabel =
|
||||
Surface.ContinueRunLabel == TEXT("Execute Generated Run");
|
||||
Surface.bContinueUsesGeneratedModeResolveLabel =
|
||||
Surface.ContinueRunLabel == TEXT("Resolve Selectors");
|
||||
Surface.bContinueUsesAttemptActiveLabel =
|
||||
Surface.ContinueRunLabel == TEXT("Start Solve")
|
||||
|| Surface.ContinueRunLabel == TEXT("Attempt Active");
|
||||
Surface.bQueueActionRecommended =
|
||||
Surface.QueuedRunLabel.StartsWith(TEXT("Recommended: "));
|
||||
Surface.bFollowUpActionRecommended =
|
||||
Surface.FollowUpRunLabel.StartsWith(TEXT("Recommended: "));
|
||||
Surface.bRecommendedActionRecommended =
|
||||
Surface.RecommendedRunLabel.StartsWith(TEXT("Recommended: "));
|
||||
|
||||
const bool bQueueRecoveryMemorySource =
|
||||
HyperTwistCoachDashboardWidgetInternal::IsQueueRecoveryMemorySource(
|
||||
CachedCoachPanelState.PreferredGuidanceSourceLabel);
|
||||
Surface.bClosedLoopIdleDashboard =
|
||||
IsCoachLoopActionabilityClosed()
|
||||
&& (
|
||||
bQueueRecoveryMemorySource
|
||||
|| !CachedCoachPanelState.PreferredGuidanceSourceLabel.IsEmpty()
|
||||
|| DisplayedCoachHandoffRecommendationKind != EHyperTwistTrainingCoachHandoffKind::None);
|
||||
|
||||
Surface.StatusLine = FString::Printf(
|
||||
TEXT("Continue: %s | Queue: %s | Follow-up: %s | Recommended: %s"),
|
||||
*Surface.ContinueRunLabel,
|
||||
*Surface.QueuedRunLabel,
|
||||
*Surface.FollowUpRunLabel,
|
||||
*Surface.RecommendedRunLabel);
|
||||
Surface.DetailLine = FString::Printf(
|
||||
TEXT("Action-label detail: recommended handoff branch %s | transition launch label %s"),
|
||||
*Surface.RecommendedHandoffKindLabel,
|
||||
*Surface.TransitionLaunchLabel);
|
||||
Surface.DetailLine += Surface.bContinueUsesGeneratedModeExecuteLabel
|
||||
? TEXT(" | continue is currently an execute-generated-run action")
|
||||
: TEXT("");
|
||||
Surface.DetailLine += Surface.bContinueUsesGeneratedModeResolveLabel
|
||||
? TEXT(" | continue is currently a selector-resolution action")
|
||||
: TEXT("");
|
||||
Surface.DetailLine += Surface.bContinueUsesRecognitionPrimeLabel
|
||||
? TEXT(" | continue is currently a recognition priming gate")
|
||||
: TEXT("");
|
||||
Surface.DetailLine += Surface.bContinueUsesAttemptActiveLabel
|
||||
? TEXT(" | continue is currently carrying the live-attempt control label")
|
||||
: TEXT("");
|
||||
if (Surface.bClosedLoopIdleDashboard)
|
||||
{
|
||||
Surface.DetailLine =
|
||||
TEXT("Action-label detail: closed-loop idle keeps the labels inspectable, but no runnable continuation or coach-directed launch remains active.");
|
||||
}
|
||||
return Surface;
|
||||
}
|
||||
|
||||
bool UHyperTwistCoachDashboardWidget::SelectPreviousMethodDrillFollowUpHistoryEntry()
|
||||
{
|
||||
if (MethodDrillFollowUpHistoryEntries.Num() <= 0)
|
||||
|
|
@ -20733,6 +21073,12 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
|
|||
DisplayedFollowUpDeckPreviewLine = FollowUpDeckPreviewLine;
|
||||
DisplayedCoachHandoffRecommendationStatusLine = CoachHandoffRecommendationStatusLine;
|
||||
DisplayedCoachHandoffRecommendationDetailLine = CoachHandoffRecommendationDetailLine;
|
||||
DisplayedCoachHandoffStatusLine = CoachHandoffStatusLine;
|
||||
DisplayedTransitionStatusLine = TransitionStatusLine;
|
||||
DisplayedContinueRunLabel = ContinueRunLabel;
|
||||
DisplayedQueuedRunLabel = QueuedRunLabel;
|
||||
DisplayedFollowUpRunLabel = FollowUpRunLabel;
|
||||
DisplayedRecommendedRunLabel = RecommendedRunLabel;
|
||||
RecordCoachHandoffHistorySnapshot(
|
||||
HyperTwistCoachDashboardWidgetInternal::DescribeHandoffRecommendationKind(
|
||||
HandoffRecommendationKind),
|
||||
|
|
|
|||
|
|
@ -803,6 +803,18 @@ public:
|
|||
FHyperTwistTrainingCoachDashboardHandoffRecommendationInspectSurface
|
||||
GetDisplayedCoachHandoffRecommendationInspectSurface() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
|
||||
FHyperTwistTrainingCoachDashboardHandoffStatusInspectSurface
|
||||
GetDisplayedCoachHandoffStatusInspectSurface() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
|
||||
FHyperTwistTrainingCoachDashboardTransitionStatusInspectSurface
|
||||
GetDisplayedTransitionStatusInspectSurface() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
|
||||
FHyperTwistTrainingCoachDashboardRunActionLabelsInspectSurface
|
||||
GetDisplayedRunActionLabelsInspectSurface() const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Coach|Dashboard")
|
||||
bool SelectPreviousMethodDrillFollowUpHistoryEntry();
|
||||
|
||||
|
|
@ -1842,8 +1854,14 @@ private:
|
|||
FString DisplayedCoachHandoffMethodDrillRecoveryMemoryStartActionSourceLabel;
|
||||
FString DisplayedCoachHandoffRecommendationStatusLine;
|
||||
FString DisplayedCoachHandoffRecommendationDetailLine;
|
||||
FString DisplayedCoachHandoffStatusLine;
|
||||
FString DisplayedTransitionStatusLine;
|
||||
FString DisplayedRecommendedDeckPreviewLine;
|
||||
FString DisplayedFollowUpDeckPreviewLine;
|
||||
FString DisplayedContinueRunLabel;
|
||||
FString DisplayedQueuedRunLabel;
|
||||
FString DisplayedFollowUpRunLabel;
|
||||
FString DisplayedRecommendedRunLabel;
|
||||
EHyperTwistCoachDashboardGuidancePreviewLane ActiveGuidancePreviewLane =
|
||||
EHyperTwistCoachDashboardGuidancePreviewLane::None;
|
||||
int32 SelectedGuidancePreviewCaseIndex = INDEX_NONE;
|
||||
|
|
|
|||
|
|
@ -10821,6 +10821,223 @@ struct FHyperTwistTrainingCoachDashboardHandoffRecommendationInspectSurface
|
|||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistTrainingCoachDashboardHandoffStatusInspectSurface
|
||||
{
|
||||
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 QueueStatusLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString FollowUpStatusLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString RecommendedStatusLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString QueueSourceLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString FollowUpBriefHeadline;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString RecommendedBriefHeadline;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 FollowUpFocusCaseCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 RecommendedFocusCaseCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasLiveAttemptTimer = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasActiveRun = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bQueueReady = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bFollowUpReady = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bRecommendedReady = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bClosedLoopIdleDashboard = false;
|
||||
|
||||
bool IsStructurallyValid() const
|
||||
{
|
||||
return !StatusLine.IsEmpty()
|
||||
|| !DetailLine.IsEmpty()
|
||||
|| bQueueReady
|
||||
|| bFollowUpReady
|
||||
|| bRecommendedReady
|
||||
|| bHasLiveAttemptTimer
|
||||
|| bHasActiveRun;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistTrainingCoachDashboardTransitionStatusInspectSurface
|
||||
{
|
||||
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 TransitionLaunchLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString ActiveCaseId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString ActivePromptLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString RecognitionBlockedReason;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 AttemptCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasLiveAttemptTimer = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bLiveInspectionPhase = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bLiveSolvePhase = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasActiveRun = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bLastStepCompletedRun = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bHasNextCaseFromLastStep = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bGeneratedModeLaunchDeck = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bCanExecuteGeneratedModeLaunch = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bRecognitionAssistedCurrentRun = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bRecognitionSessionOpenForCurrentRun = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bRecognitionServiceReadyForCurrentRun = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bCanContinueCurrentRun = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bCanLaunchCoachRun = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bClosedLoopIdleDashboard = false;
|
||||
|
||||
bool IsStructurallyValid() const
|
||||
{
|
||||
return !StatusLine.IsEmpty()
|
||||
|| !DetailLine.IsEmpty()
|
||||
|| bHasLiveAttemptTimer
|
||||
|| bHasActiveRun
|
||||
|| bCanContinueCurrentRun
|
||||
|| bCanLaunchCoachRun;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistTrainingCoachDashboardRunActionLabelsInspectSurface
|
||||
{
|
||||
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 ContinueRunLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString QueuedRunLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString FollowUpRunLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString RecommendedRunLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString RecommendedHandoffKindLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString TransitionLaunchLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bContinueUsesRecognitionPrimeLabel = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bContinueUsesGeneratedModeExecuteLabel = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bContinueUsesGeneratedModeResolveLabel = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bContinueUsesAttemptActiveLabel = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bQueueActionRecommended = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bFollowUpActionRecommended = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bRecommendedActionRecommended = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bClosedLoopIdleDashboard = false;
|
||||
|
||||
bool IsStructurallyValid() const
|
||||
{
|
||||
return !StatusLine.IsEmpty()
|
||||
|| !DetailLine.IsEmpty()
|
||||
|| !ContinueRunLabel.IsEmpty()
|
||||
|| !QueuedRunLabel.IsEmpty()
|
||||
|| !FollowUpRunLabel.IsEmpty()
|
||||
|| !RecommendedRunLabel.IsEmpty();
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistTrainingCoachGeneratedModeLaunchExecutionContextSurface
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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 displayed recommended guidance deck preview, displayed follow-up guidance deck preview, and displayed coach handoff recommendation inspect surfaces over already-cached deck/brief state and the live retained handoff recommendation posture, so gameplay/Blueprint callers can inspect the surfaced deck previews and current handoff recommendation without scraping dashboard text blocks or reopening preview/handoff derivation
|
||||
- the next clean move is to stay on that same live dashboard guidance-consumer lane and land the displayed coach handoff status, displayed transition status, and displayed continuation / queued / follow-up / recommended run action-label 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 displayed coach handoff status, displayed transition status, and displayed continuation / queued / follow-up / recommended run action-label inspect surfaces over already-derived live dashboard transition and action-label state, so gameplay/Blueprint callers can inspect the current transition posture, coach handoff availability line, and surfaced launch/control labels without scraping dashboard text blocks or reopening transition/handoff derivation
|
||||
- the next clean move is to stay on that same live dashboard guidance-consumer lane and land the displayed active-run status, active-attempt/timer status, and current-case / current-deck status 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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
# HyperTwist Phase 4 dashboard live handoff status, transition status, and run action-label 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 live handoff-status, transition-status, and surfaced run action-label state directly to gameplay and Blueprint callers.
|
||||
|
||||
## Why this packet exists
|
||||
|
||||
The dashboard already derived:
|
||||
|
||||
- the displayed coach handoff availability/status line
|
||||
- the displayed transition-status line
|
||||
- the displayed continue / queue / follow-up / recommended run button labels
|
||||
|
||||
But that live state still only surfaced through dashboard text blocks and button labels. Callers still had to scrape widget presentation or reopen transition / handoff derivation to inspect what the dashboard was currently showing.
|
||||
|
||||
## What changed
|
||||
|
||||
- added `FHyperTwistTrainingCoachDashboardHandoffStatusInspectSurface`
|
||||
- added `FHyperTwistTrainingCoachDashboardTransitionStatusInspectSurface`
|
||||
- added `FHyperTwistTrainingCoachDashboardRunActionLabelsInspectSurface`
|
||||
- added `GetDisplayedCoachHandoffStatusInspectSurface()`
|
||||
- added `GetDisplayedTransitionStatusInspectSurface()`
|
||||
- added `GetDisplayedRunActionLabelsInspectSurface()`
|
||||
- retained the exact displayed handoff-status line, transition-status line, and surfaced run action 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 displayed coach handoff status line and current queue / follow-up / recommended readiness posture
|
||||
- the displayed transition status line and current live transition posture
|
||||
- the surfaced continue / queue / follow-up / recommended run action labels, including which branch is currently marked as recommended
|
||||
|
||||
without scraping dashboard text blocks or button labels or reopening transition / handoff 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 displayed active-run status, active-attempt/timer status, and current-case / current-deck status inspect surface group.
|
||||
Loading…
Add table
Reference in a new issue