Expose gameplay generated-mode execution context surface

This commit is contained in:
axiomlogicnexus 2026-05-08 01:11:09 +02:00
parent 146635fbd5
commit 6b418f78b1
9 changed files with 332 additions and 2 deletions

View file

@ -6703,3 +6703,109 @@ UHyperTwistTrainingCoachLibrary::DeriveCoachVerificationRecognitionReviewContext
return Surface;
}
FHyperTwistTrainingCoachGeneratedModeLaunchExecutionContextSurface
UHyperTwistTrainingCoachLibrary::DeriveCoachGeneratedModeLaunchExecutionContextSurface(
const FHyperTwistTrainingCoachPanelState& PanelState,
const FHyperTwistTrainingCoachReadinessEligibilitySurface& ReadinessEligibilitySurface,
const FHyperTwistTrainingCoachVerificationRecognitionReviewContextSurface&
VerificationRecognitionReviewContextSurface
)
{
FHyperTwistTrainingCoachGeneratedModeLaunchExecutionContextSurface Surface;
Surface.Headline = TEXT("Generated Mode");
Surface.bHasLatestLaunchRequest = PanelState.bHasLatestGeneratedModeLaunchRequest;
Surface.bHasExecutionTarget = PanelState.bHasActiveGeneratedModeExecutionTarget;
Surface.bCanExecute = PanelState.bCanExecuteActiveGeneratedModeLaunchRequest;
Surface.bWillRefreshLaunchRequestOnExecute =
PanelState.bActiveGeneratedModeExecutionWillRefreshLaunchRequest;
Surface.LatestLaunchRequestId = PanelState.LatestGeneratedModeLaunchRequestId;
Surface.LatestLaunchRequestedAtUtc = PanelState.LatestGeneratedModeLaunchRequestedAtUtc;
Surface.LatestRuntimeModeId = PanelState.LatestGeneratedModeRuntimeModeId;
Surface.SelectorSummaryLine = PanelState.LatestGeneratedModeSelectorSummaryLine;
Surface.BlockedReasonLine = PanelState.ActiveGeneratedModeExecutionBlockedReason;
if (Surface.bHasExecutionTarget
&& !Surface.bCanExecute
&& Surface.BlockedReasonLine.IsEmpty())
{
Surface.BlockedReasonLine =
TEXT("Finish the active selector choices before executing the owned generated run.");
}
Surface.bHasBlockedExecution = !Surface.BlockedReasonLine.IsEmpty();
const FString RequestIdSummary = Surface.LatestLaunchRequestId.IsEmpty()
? TEXT("n/a")
: Surface.LatestLaunchRequestId;
const FString RequestTimeSummary = Surface.LatestLaunchRequestedAtUtc.IsEmpty()
? TEXT("n/a")
: Surface.LatestLaunchRequestedAtUtc;
const FString RuntimeModeSummary = Surface.LatestRuntimeModeId.IsEmpty()
? TEXT("n/a")
: Surface.LatestRuntimeModeId;
const FString SelectorSummary = Surface.SelectorSummaryLine.IsEmpty()
? TEXT("none")
: Surface.SelectorSummaryLine;
Surface.RequestLine = Surface.bHasLatestLaunchRequest
? FString::Printf(
TEXT("Request: %s @ %s | mode: %s"),
*RequestIdSummary,
*RequestTimeSummary,
*RuntimeModeSummary
)
: TEXT("Request: none persisted for the active deck");
Surface.SelectorLine = FString::Printf(
TEXT("Selectors: %s"),
*SelectorSummary
);
Surface.ExecutionLine = Surface.bHasExecutionTarget
? FString::Printf(
TEXT("Execution: ready %s | request refresh on execute: %s"),
Surface.bCanExecute ? TEXT("yes") : TEXT("no"),
Surface.bWillRefreshLaunchRequestOnExecute ? TEXT("yes") : TEXT("no")
)
: TEXT("Execution: no generated-mode execution target is currently staged");
if (Surface.bHasExecutionTarget && Surface.bCanExecute)
{
Surface.StatusLine = Surface.bWillRefreshLaunchRequestOnExecute
? TEXT("Generated mode: execution is ready and will refresh the stored request on execute.")
: TEXT("Generated mode: execution is ready from the current stored request.");
}
else if (Surface.bHasExecutionTarget)
{
Surface.StatusLine = FString::Printf(
TEXT("Generated mode: execution is blocked. %s"),
*Surface.BlockedReasonLine
);
}
else if (Surface.bHasLatestLaunchRequest)
{
Surface.StatusLine =
TEXT("Generated mode: the latest request is persisted, but no active generated-mode execution target is staged.");
}
else
{
Surface.StatusLine =
TEXT("Generated mode: no persisted request or execution target is currently available.");
}
Surface.DetailLine = FString::Printf(
TEXT("Readiness: %s | Coach context: %s"),
ReadinessEligibilitySurface.StatusLine.IsEmpty()
? TEXT("n/a")
: *ReadinessEligibilitySurface.StatusLine,
VerificationRecognitionReviewContextSurface.StatusLine.IsEmpty()
? TEXT("n/a")
: *VerificationRecognitionReviewContextSurface.StatusLine
);
if (Surface.bHasBlockedExecution)
{
Surface.DetailLine += FString::Printf(
TEXT(" | Blocked: %s"),
*Surface.BlockedReasonLine
);
}
return Surface;
}

View file

@ -662,6 +662,21 @@ UHyperTwistTrainingPanelWidget::GetDisplayedCoachVerificationRecognitionReviewCo
);
}
FHyperTwistTrainingCoachGeneratedModeLaunchExecutionContextSurface
UHyperTwistTrainingPanelWidget::GetDisplayedCoachGeneratedModeLaunchExecutionContextSurface() const
{
const FHyperTwistTrainingCoachReadinessEligibilitySurface ReadinessEligibilitySurface =
GetDisplayedCoachReadinessEligibilitySurface();
const FHyperTwistTrainingCoachVerificationRecognitionReviewContextSurface
VerificationRecognitionReviewContextSurface =
GetDisplayedCoachVerificationRecognitionReviewContextSurface();
return UHyperTwistTrainingCoachLibrary::DeriveCoachGeneratedModeLaunchExecutionContextSurface(
CachedCoachPanelState,
ReadinessEligibilitySurface,
VerificationRecognitionReviewContextSurface
);
}
FHyperTwistTrainingRunState UHyperTwistTrainingPanelWidget::StartCoachRecommendedRun(
const int32 MaxCases,
const FString& StartActionSourceLabel

View file

@ -643,6 +643,21 @@ AHyperTwistTrainingSessionActor::GetDisplayedCoachVerificationRecognitionReviewC
);
}
FHyperTwistTrainingCoachGeneratedModeLaunchExecutionContextSurface
AHyperTwistTrainingSessionActor::GetDisplayedCoachGeneratedModeLaunchExecutionContextSurface() const
{
const FHyperTwistTrainingCoachReadinessEligibilitySurface ReadinessEligibilitySurface =
GetDisplayedCoachReadinessEligibilitySurface();
const FHyperTwistTrainingCoachVerificationRecognitionReviewContextSurface
VerificationRecognitionReviewContextSurface =
GetDisplayedCoachVerificationRecognitionReviewContextSurface();
return UHyperTwistTrainingCoachLibrary::DeriveCoachGeneratedModeLaunchExecutionContextSurface(
CachedCoachPanelState,
ReadinessEligibilitySurface,
VerificationRecognitionReviewContextSurface
);
}
FHyperTwistTrainingRunState AHyperTwistTrainingSessionActor::StartCoachRecommendedTrainingRun(
const int32 MaxCases
)

View file

@ -659,4 +659,13 @@ public:
const FHyperTwistTrainingCoachWorkloadBudgetSurface& WorkloadBudgetSurface,
const FHyperTwistTrainingCoachReadinessEligibilitySurface& ReadinessEligibilitySurface
);
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach")
static FHyperTwistTrainingCoachGeneratedModeLaunchExecutionContextSurface
DeriveCoachGeneratedModeLaunchExecutionContextSurface(
const FHyperTwistTrainingCoachPanelState& PanelState,
const FHyperTwistTrainingCoachReadinessEligibilitySurface& ReadinessEligibilitySurface,
const FHyperTwistTrainingCoachVerificationRecognitionReviewContextSurface&
VerificationRecognitionReviewContextSurface
);
};

View file

@ -244,6 +244,10 @@ public:
FHyperTwistTrainingCoachVerificationRecognitionReviewContextSurface
GetDisplayedCoachVerificationRecognitionReviewContextSurface() const;
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach")
FHyperTwistTrainingCoachGeneratedModeLaunchExecutionContextSurface
GetDisplayedCoachGeneratedModeLaunchExecutionContextSurface() const;
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Coach")
FHyperTwistTrainingRunState StartCoachRecommendedRun(
int32 MaxCases,

View file

@ -225,6 +225,10 @@ public:
FHyperTwistTrainingCoachVerificationRecognitionReviewContextSurface
GetDisplayedCoachVerificationRecognitionReviewContextSurface() const;
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach")
FHyperTwistTrainingCoachGeneratedModeLaunchExecutionContextSurface
GetDisplayedCoachGeneratedModeLaunchExecutionContextSurface() const;
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Coach")
FHyperTwistTrainingRunState StartCoachRecommendedTrainingRun(int32 MaxCases);

View file

@ -8322,3 +8322,68 @@ struct FHyperTwistTrainingCoachVerificationRecognitionReviewContextSurface
|| bHasMaterializedReviewPolicy;
}
};
USTRUCT(BlueprintType)
struct FHyperTwistTrainingCoachGeneratedModeLaunchExecutionContextSurface
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString Headline;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString StatusLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString RequestLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString SelectorLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString ExecutionLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString BlockedReasonLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString DetailLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString LatestLaunchRequestId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString LatestLaunchRequestedAtUtc;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString LatestRuntimeModeId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString SelectorSummaryLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasLatestLaunchRequest = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasExecutionTarget = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bCanExecute = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bWillRefreshLaunchRequestOnExecute = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasBlockedExecution = false;
bool IsStructurallyValid() const
{
return !StatusLine.IsEmpty()
|| !RequestLine.IsEmpty()
|| !ExecutionLine.IsEmpty()
|| bHasLatestLaunchRequest
|| bHasExecutionTarget
|| bCanExecute
|| bHasBlockedExecution;
}
};

View file

@ -68,8 +68,8 @@ Current correction call from the source-exposed audit and current execution refr
- 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 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 latest landed bounded `Phase 4` packet stays on that same gameplay-facing consumer lane and adds one thin coach verification / recognition / review-policy context surface over the already-landed primary CTA, secondary queue-control, queue-recovery posture, handoff-continuation, focus/provenance, workload/budget, and readiness/eligibility surfaces, so gameplay/Blueprint callers can render repository-verification, recognition-provider, and review-policy context without reading raw status/detail lines directly
- the current next bounded packet is to expose one thin generated-mode launch-request / execution context surface on those same two consumer surfaces so gameplay/Blueprint callers can render latest generated-mode request, runtime mode, selector summary, execution readiness, and blocked-reason context without reading raw request/execution fields directly
- the latest landed bounded `Phase 4` packet stays on that same gameplay-facing consumer lane and adds one thin generated-mode launch-request / execution context surface over the already-cached generated-mode request / execution panel state, so gameplay/Blueprint callers can render latest generated-mode request, runtime mode, selector summary, execution readiness, and blocked-reason context without reading raw request/execution fields directly
- the current next bounded packet is to expose one thin generated-mode selector/application context surface on those same two consumer surfaces so gameplay/Blueprint callers can render active selector-state coverage, generator/runtime identity, and request-refresh implications without reading raw imported selection/config payloads directly
- 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,112 @@
# HyperTwist Phase 4 gameplay generated-mode launch / execution context surface packet
Created on `2026-05-08`
Status:
- first-party HyperTwist packet
- bounded Phase `4` gameplay-facing consumer slice
## Purpose
This packet closes the next thin gameplay-facing consumer seam above the panel-widget and session-actor coach helpers by exposing one pure generated-mode launch / execution context surface over the already-cached generated-mode request / execution panel state.
The open tasks were:
- stop forcing gameplay / Blueprint callers to read raw generated-mode launch-request ids, runtime-mode ids, selector summaries, readiness booleans, and blocked-reason strings just to render the current generated-mode posture
- expose one thin first-party context surface that summarizes the latest stored generated-mode request, selector summary, execution readiness, and request-refresh-on-execute posture
- keep that surface derived from already-cached gameplay consumer state instead of widening into dashboard-only generated-mode inspection or backend execution logic
It is not:
- a new generated-mode execution packet
- a selector-application behavior packet
- a launch-request persistence packet
- a broader gameplay HUD composition pass
## Scope
Bounded lane:
- add a first-party generated-mode launch / execution context surface in shared training types
- add a coach-library helper that derives the surface from panel state plus the already-landed readiness and verification context surfaces
- expose that derived context surface on `HyperTwistTrainingPanelWidget` and `HyperTwistTrainingSessionActor`
- keep the derivation presentation-only and rooted in already-cached gameplay consumer state
Out of scope:
- changing generated-mode launch-request persistence
- changing generated-mode execution readiness rules
- changing selector-application behavior
- importing dashboard-only retained analysis into gameplay consumers
## Why this was the right next packet
Before this slice:
- gameplay-facing panel/session consumers already exposed truthful coach action, continuation, provenance, workload, readiness, and operational context surfaces
But one thin consumer seam was still open:
- callers could explain the surrounding coach context
- but they still had to read raw generated-mode request / execution fields to render the current generated-mode posture
That meant:
- coach state explanation was thin and reusable
- but generated-mode execution context still leaked raw panel-state fields into callers
So the next bounded move was:
- keep the already-landed coach context surfaces unchanged
- and expose one narrow generated-mode launch / execution context surface above the cached request / execution state
## What landed
Primary code changes:
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h`
- added `FHyperTwistTrainingCoachGeneratedModeLaunchExecutionContextSurface`
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingCoachLibrary.h`
- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp`
- added `DeriveCoachGeneratedModeLaunchExecutionContextSurface(...)`
- context is derived from existing panel-state, readiness, and verification-context inputs
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingPanelWidget.h`
- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingPanelWidget.cpp`
- added `GetDisplayedCoachGeneratedModeLaunchExecutionContextSurface()`
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingSessionActor.h`
- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSessionActor.cpp`
- added `GetDisplayedCoachGeneratedModeLaunchExecutionContextSurface()`
## Product effect
The gameplay-facing generated-mode consumer layer is now more complete:
- gameplay / Blueprint callers can read one pure surface to render the latest stored generated-mode request, runtime mode, selector summary, execution readiness, request-refresh-on-execute posture, and blocked-reason context
- callers no longer need to inspect raw generated-mode request / execution panel-state fields directly
- the surface stays aligned with the already-landed coach readiness and verification context surfaces without importing dashboard-only behavior
## Acceptance criteria
- shared training types expose a narrow generated-mode launch / execution context surface
- coach-library derivation consumes already-cached gameplay consumer state rather than adding new runtime fetches
- panel-widget callers can fetch the displayed generated-mode context surface directly
- session-actor callers can fetch the displayed generated-mode context surface directly
- full product build succeeds
## Validation checklist
1. build `UnrealHyperTwist.sln` / `UnrealHyperTwistEditor`
2. confirm the new generated-mode context surface compiles in shared types and coach library
3. confirm panel-widget getters compile and return the derived context surface
4. confirm session-actor getters compile and return the derived context surface
5. confirm no backend generated-mode execution behavior was pulled into the packet
## Validation result
- full `Development Editor|Win64` build succeeded on `2026-05-08`
- build completed with `0` warnings and `0` errors
## Next bounded follow-on slice
- stay on the same gameplay-facing consumer lane and expose one thin generated-mode selector/application context surface on `HyperTwistTrainingPanelWidget` and `HyperTwistTrainingSessionActor`, so gameplay callers can render active selector-state coverage, generator/runtime identity, and request-refresh implications without reading raw imported selection/config payloads directly