Expose first-party template launch consumers

This commit is contained in:
axiomlogicnexus 2026-05-06 22:50:12 +02:00
parent 89a37bce08
commit 84b426443a
5 changed files with 247 additions and 0 deletions

View file

@ -53,6 +53,21 @@ void UHyperTwistTrainingPanelWidget::RefreshTrainingState()
UHyperTwistTrainingRuntimeLibrary::GetActiveTrainingMethodDrillFollowUpTemplate(this);
CachedMethodDrillFollowUpDeck =
UHyperTwistTrainingRuntimeLibrary::BuildActiveMethodDrillFollowUpDeck(this);
CachedActiveTrainingSessionTemplates =
UHyperTwistTrainingRuntimeLibrary::GetActiveTrainingSessionTemplates(this);
if (DefaultUserId.IsEmpty())
{
CachedDefaultUserTrainingSessionTemplates.Reset();
}
else
{
CachedDefaultUserTrainingSessionTemplates =
UHyperTwistTrainingRuntimeLibrary::GetTrainingSessionTemplatesForUser(
this,
DefaultUserId,
FString()
);
}
CachedCoachSignals = UHyperTwistTrainingRuntimeLibrary::GetActiveTrainingCoachSignals(this);
CachedCoachBrief = UHyperTwistTrainingRuntimeLibrary::GetActiveTrainingCoachBrief(this);
CachedCoachFollowUpBrief = UHyperTwistTrainingRuntimeLibrary::GetActiveTrainingCoachFollowUpBrief(this);
@ -71,6 +86,25 @@ void UHyperTwistTrainingPanelWidget::RefreshTrainingState()
UHyperTwistTrainingRuntimeLibrary::GetActiveTrainingRepositoryRoundTripVerification(this);
}
TArray<FHyperTwistTrainingSessionTemplate> UHyperTwistTrainingPanelWidget::GetTrainingSessionTemplatesForUser(
const FString& UserId,
const FString& ReferenceUtc
)
{
const TArray<FHyperTwistTrainingSessionTemplate> SessionTemplates =
UHyperTwistTrainingRuntimeLibrary::GetTrainingSessionTemplatesForUser(
this,
UserId,
ReferenceUtc
);
if (UserId == DefaultUserId)
{
CachedDefaultUserTrainingSessionTemplates = SessionTemplates;
}
return SessionTemplates;
}
FHyperTwistTrainingRunState UHyperTwistTrainingPanelWidget::StartSampleClassicTrainingRun()
{
LastStepResult = FHyperTwistTrainingRunStepResult();
@ -103,6 +137,23 @@ FHyperTwistTrainingRunState UHyperTwistTrainingPanelWidget::StartTrainingRunFrom
return CachedRunState;
}
FHyperTwistTrainingRunState UHyperTwistTrainingPanelWidget::StartTrainingRunFromTemplate(
const FString& TemplateId,
const FString& UserId,
const FString& SessionId
)
{
LastStepResult = FHyperTwistTrainingRunStepResult();
CachedRunState = UHyperTwistTrainingRuntimeLibrary::StartTrainingRunFromTemplate(
this,
TemplateId,
UserId,
SessionId
);
RefreshTrainingState();
return CachedRunState;
}
FHyperTwistTrainingRunStepResult UHyperTwistTrainingPanelWidget::SubmitTrainingAttempt(
const FHyperTwistTrainingAttempt& Attempt,
int32 TimeMs

View file

@ -145,6 +145,21 @@ void AHyperTwistTrainingSessionActor::RefreshCachedTrainingState()
this,
CachedLatestGeneratedModeLaunchRequestForActiveDeck
);
CachedActiveTrainingSessionTemplates =
UHyperTwistTrainingRuntimeLibrary::GetActiveTrainingSessionTemplates(this);
if (AutoStartUserId.IsEmpty())
{
CachedAutoStartUserTrainingSessionTemplates.Reset();
}
else
{
CachedAutoStartUserTrainingSessionTemplates =
UHyperTwistTrainingRuntimeLibrary::GetTrainingSessionTemplatesForUser(
this,
AutoStartUserId,
FString()
);
}
CachedCoachSignals = UHyperTwistTrainingRuntimeLibrary::GetActiveTrainingCoachSignals(this);
CachedCoachBrief = UHyperTwistTrainingRuntimeLibrary::GetActiveTrainingCoachBrief(this);
CachedCoachFollowUpBrief = UHyperTwistTrainingRuntimeLibrary::GetActiveTrainingCoachFollowUpBrief(this);
@ -163,6 +178,25 @@ void AHyperTwistTrainingSessionActor::RefreshCachedTrainingState()
UHyperTwistTrainingRuntimeLibrary::GetActiveTrainingRepositoryRoundTripVerification(this);
}
TArray<FHyperTwistTrainingSessionTemplate> AHyperTwistTrainingSessionActor::GetTrainingSessionTemplatesForUser(
const FString& UserId,
const FString& ReferenceUtc
)
{
const TArray<FHyperTwistTrainingSessionTemplate> SessionTemplates =
UHyperTwistTrainingRuntimeLibrary::GetTrainingSessionTemplatesForUser(
this,
UserId,
ReferenceUtc
);
if (UserId == AutoStartUserId)
{
CachedAutoStartUserTrainingSessionTemplates = SessionTemplates;
}
return SessionTemplates;
}
FHyperTwistTrainingRunState AHyperTwistTrainingSessionActor::ApplyActiveImportedRuntimeSelectorOption(
const FString& SelectorId,
const FString& OptionId
@ -246,6 +280,22 @@ FHyperTwistTrainingDeck AHyperTwistTrainingSessionActor::BuildCoachFollowUpDeck(
return CachedCoachFollowUpDeck;
}
FHyperTwistTrainingRunState AHyperTwistTrainingSessionActor::StartRunFromTemplate(
const FString& TemplateId,
const FString& UserId,
const FString& SessionId
)
{
CachedRunState = UHyperTwistTrainingRuntimeLibrary::StartTrainingRunFromTemplate(
this,
TemplateId,
UserId,
SessionId
);
RefreshCachedTrainingState();
return CachedRunState;
}
FHyperTwistTrainingRunState AHyperTwistTrainingSessionActor::StartCoachRecommendedTrainingRun(
const int32 MaxCases
)

View file

@ -50,6 +50,12 @@ public:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "HyperTwist|Training|Drill")
FHyperTwistTrainingDeck CachedMethodDrillFollowUpDeck;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "HyperTwist|Training|Templates")
TArray<FHyperTwistTrainingSessionTemplate> CachedActiveTrainingSessionTemplates;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "HyperTwist|Training|Templates")
TArray<FHyperTwistTrainingSessionTemplate> CachedDefaultUserTrainingSessionTemplates;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "HyperTwist|Training")
FHyperTwistTrainingRunStepResult LastStepResult;
@ -116,6 +122,12 @@ public:
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training")
void RefreshTrainingState();
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Templates")
TArray<FHyperTwistTrainingSessionTemplate> GetTrainingSessionTemplatesForUser(
const FString& UserId,
const FString& ReferenceUtc
);
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training")
FHyperTwistTrainingRunState StartSampleClassicTrainingRun();
@ -127,6 +139,13 @@ public:
EHyperTwistTrainingDeliveryMode Mode
);
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Templates")
FHyperTwistTrainingRunState StartTrainingRunFromTemplate(
const FString& TemplateId,
const FString& UserId,
const FString& SessionId
);
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training")
FHyperTwistTrainingRunStepResult SubmitTrainingAttempt(
const FHyperTwistTrainingAttempt& Attempt,

View file

@ -76,6 +76,12 @@ public:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "HyperTwist|Training|Coach")
FHyperTwistTrainingDeck CachedCoachFollowUpDeck;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "HyperTwist|Training|Templates")
TArray<FHyperTwistTrainingSessionTemplate> CachedActiveTrainingSessionTemplates;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "HyperTwist|Training|Templates")
TArray<FHyperTwistTrainingSessionTemplate> CachedAutoStartUserTrainingSessionTemplates;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "HyperTwist|Training|Imported")
FHyperTwistTrainingImportedRuntimeSelectionState CachedImportedRuntimeSelectionState;
@ -138,6 +144,12 @@ public:
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training")
void RefreshCachedTrainingState();
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Templates")
TArray<FHyperTwistTrainingSessionTemplate> GetTrainingSessionTemplatesForUser(
const FString& UserId,
const FString& ReferenceUtc
);
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Imported")
FHyperTwistTrainingRunState ApplyActiveImportedRuntimeSelectorOption(
const FString& SelectorId,
@ -168,6 +180,13 @@ public:
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Coach")
FHyperTwistTrainingDeck BuildCoachFollowUpDeck(int32 MaxCases);
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Templates")
FHyperTwistTrainingRunState StartRunFromTemplate(
const FString& TemplateId,
const FString& UserId,
const FString& SessionId
);
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|Coach")
FHyperTwistTrainingRunState StartCoachRecommendedTrainingRun(int32 MaxCases);

View file

@ -0,0 +1,108 @@
# HyperTwist Phase 4 template consumer parity packet
Created on `2026-05-06`
Status:
- first-party HyperTwist packet
- bounded Phase `4` template consumer parity slice
## Purpose
This packet exposes session-template launch and query access through first-party panel and actor consumers.
The open tasks are:
- surface active session templates in built-in Blueprint-facing consumers
- surface user-scoped session-template queries without dropping to the raw runtime library
- surface template-backed training launches through the same first-party consumer layer
It is not:
- a dashboard UI redesign packet
- a new template derivation packet
- a review-plan subsystem packet
- a coach orchestration packet
## Scope
Bounded lane:
- keep runtime-library and subsystem template logic unchanged
- cache active session templates on `UHyperTwistTrainingPanelWidget`
- cache active session templates on `AHyperTwistTrainingSessionActor`
- cache the current default / auto-start user template set on those first-party consumers
- add panel and actor wrappers for `GetTrainingSessionTemplatesForUser(...)`
- add panel and actor wrappers for `StartTrainingRunFromTemplate(...)`
Out of scope:
- adding new UMG controls or dashboard buttons
- changing review-template resume semantics
- widening into template editing or repository mutation flows
- changing coach or method-drill recommendation logic
## Why this was the right next packet
The last two packets fixed review-template behavior in the subsystem:
- generic review-preferring templates now launch with review-plan semantics
- method-drill follow-up templates that prefer review execution now persist review-plan state too
But first-party consumer parity still lagged behind:
- the runtime library already exposed active template lists, user-scoped template queries, and template-backed launches
- while the built-in panel and session actor still only surfaced deck-backed and coach/drill launch paths
That left the corrected review-template lane reachable only through the raw runtime library or custom caller code.
So the next honest move was:
- lift session-template state into the default panel and actor caches
- add matching query and launch wrappers there
- keep the packet narrow by avoiding UI redesign work
## What landed
Primary code changes:
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingPanelWidget.h`
- added cached active/default-user session-template arrays
- added first-party template query and launch wrappers
- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingPanelWidget.cpp`
- refresh now caches active session templates and default-user templates
- added `GetTrainingSessionTemplatesForUser(...)`
- added `StartTrainingRunFromTemplate(...)`
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingSessionActor.h`
- added cached active/auto-start-user session-template arrays
- added first-party template query and launch wrappers
- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSessionActor.cpp`
- refresh now caches active session templates and auto-start-user templates
- added `GetTrainingSessionTemplatesForUser(...)`
- added `StartRunFromTemplate(...)`
## Product effect
The corrected template lane is now reachable through the maintained first-party consumer layer:
- panel and dashboard consumers can inspect active session templates after refresh
- panel and dashboard consumers can inspect the default users effective session templates without raw runtime calls
- actor consumers can do the same for their configured auto-start user
- template-backed launches, including review-preferring templates, now have built-in panel/actor entry points
## Acceptance criteria
- panel refresh caches active session templates and default-user templates
- session actor refresh caches active session templates and auto-start-user templates
- panel exposes template query and template launch wrappers
- session actor exposes template query and template launch wrappers
- full product build succeeds
## Validation checklist
1. build `UnrealHyperTwist.sln` / `UnrealHyperTwistEditor`
2. confirm panel refresh populates active and default-user template caches
3. confirm session actor refresh populates active and auto-start-user template caches
4. confirm template-backed launch calls route through the new first-party panel/actor wrappers
That is the packet.