Expose dashboard schedule horizon and policy friction surfaces

This commit is contained in:
axiomlogicnexus 2026-05-09 23:42:50 +02:00
parent 18e1e065fc
commit e09f3c66ee
5 changed files with 413 additions and 6 deletions

View file

@ -11729,6 +11729,157 @@ UHyperTwistCoachDashboardWidget::GetDisplayedSelectedQueueEntryDetailInspectSurf
return Surface;
}
FHyperTwistTrainingCoachDashboardScheduleHorizonStatusInspectSurface
UHyperTwistCoachDashboardWidget::GetDisplayedScheduleHorizonStatusInspectSurface() const
{
FHyperTwistTrainingCoachDashboardScheduleHorizonStatusInspectSurface Surface;
Surface.Headline = TEXT("Schedule horizon status");
Surface.QueueId = CachedCoachScheduleHorizonSummary.QueueId.IsEmpty()
? TEXT("n/a")
: CachedCoachScheduleHorizonSummary.QueueId;
Surface.FocusDeckId = CachedCoachScheduleHorizonSummary.FocusDeckId.IsEmpty()
? TEXT("n/a")
: CachedCoachScheduleHorizonSummary.FocusDeckId;
Surface.FocusMethodSegmentId =
CachedCoachScheduleHorizonSummary.FocusMethodSegmentId.IsEmpty()
? TEXT("n/a")
: CachedCoachScheduleHorizonSummary.FocusMethodSegmentId;
Surface.ActiveEntryId = CachedCoachScheduleHorizonSummary.ActiveEntryId.IsEmpty()
? TEXT("none")
: CachedCoachScheduleHorizonSummary.ActiveEntryId;
Surface.NextReadyEntryId = CachedCoachScheduleHorizonSummary.NextReadyEntryId.IsEmpty()
? TEXT("none")
: CachedCoachScheduleHorizonSummary.NextReadyEntryId;
Surface.NextDeferredEntryId =
CachedCoachScheduleHorizonSummary.NextDeferredEntryId.IsEmpty()
? TEXT("none")
: CachedCoachScheduleHorizonSummary.NextDeferredEntryId;
Surface.NextArchiveEntryId = CachedCoachScheduleHorizonSummary.NextArchiveEntryId.IsEmpty()
? TEXT("none")
: CachedCoachScheduleHorizonSummary.NextArchiveEntryId;
Surface.NextFollowUpEntryId =
CachedCoachScheduleHorizonSummary.NextFollowUpEntryId.IsEmpty()
? TEXT("none")
: CachedCoachScheduleHorizonSummary.NextFollowUpEntryId;
Surface.CurrentHorizonLabel =
CachedCoachScheduleHorizonSummary.CurrentHorizonLabel.IsEmpty()
? TEXT("n/a")
: CachedCoachScheduleHorizonSummary.CurrentHorizonLabel;
Surface.ImmediateEntryCount = CachedCoachScheduleHorizonSummary.ImmediateEntryCount;
Surface.DeferredEntryCount = CachedCoachScheduleHorizonSummary.DeferredEntryCount;
Surface.ArchiveAwareEntryCount = CachedCoachScheduleHorizonSummary.ArchiveAwareEntryCount;
Surface.FollowUpEntryCount = CachedCoachScheduleHorizonSummary.FollowUpEntryCount;
Surface.PinnedEntryCount = CachedCoachScheduleHorizonSummary.PinnedEntryCount;
Surface.bHasImmediateWindow = CachedCoachScheduleHorizonSummary.bHasImmediateWindow;
Surface.bHasDeferredWindow = CachedCoachScheduleHorizonSummary.bHasDeferredWindow;
Surface.bNeedsArchiveWindow = CachedCoachScheduleHorizonSummary.bNeedsArchiveWindow;
Surface.bHasBlockedFollowUp = CachedCoachScheduleHorizonSummary.bHasBlockedFollowUp;
Surface.bHasInProgressEntry = CachedCoachScheduleHorizonSummary.bHasInProgressEntry;
Surface.StatusLine = !DisplayedScheduleStatusLine.IsEmpty()
? DisplayedScheduleStatusLine
: FString::Printf(
TEXT("Horizon: %s | Immediate %d | Deferred %d | Archive-aware %d | Follow-up %d | Pinned %d | Immediate window: %s | Deferred window: %s | Blocked follow-up: %s"),
*Surface.CurrentHorizonLabel,
Surface.ImmediateEntryCount,
Surface.DeferredEntryCount,
Surface.ArchiveAwareEntryCount,
Surface.FollowUpEntryCount,
Surface.PinnedEntryCount,
Surface.bHasImmediateWindow ? TEXT("yes") : TEXT("no"),
Surface.bHasDeferredWindow ? TEXT("yes") : TEXT("no"),
Surface.bHasBlockedFollowUp ? TEXT("yes") : TEXT("no"));
return Surface;
}
FHyperTwistTrainingCoachDashboardSchedulePolicyFrictionInspectSurface
UHyperTwistCoachDashboardWidget::GetDisplayedSchedulePolicyFrictionInspectSurface() const
{
FHyperTwistTrainingCoachDashboardSchedulePolicyFrictionInspectSurface Surface;
Surface.Headline = TEXT("Schedule policy / friction");
Surface.QueueId = CachedCoachSchedulePolicySummary.QueueId.IsEmpty()
? TEXT("n/a")
: CachedCoachSchedulePolicySummary.QueueId;
Surface.FocusDeckId = CachedCoachSchedulePolicySummary.FocusDeckId.IsEmpty()
? TEXT("n/a")
: CachedCoachSchedulePolicySummary.FocusDeckId;
Surface.FocusMethodSegmentId =
CachedCoachSchedulePolicySummary.FocusMethodSegmentId.IsEmpty()
? TEXT("n/a")
: CachedCoachSchedulePolicySummary.FocusMethodSegmentId;
Surface.NextImmediateEntryId =
CachedCoachSchedulePolicySummary.NextImmediateEntryId.IsEmpty()
? TEXT("none")
: CachedCoachSchedulePolicySummary.NextImmediateEntryId;
Surface.NextPendingEntryId = CachedCoachSchedulePolicySummary.NextPendingEntryId.IsEmpty()
? TEXT("none")
: CachedCoachSchedulePolicySummary.NextPendingEntryId;
Surface.NextDeferredEntryId =
CachedCoachSchedulePolicySummary.NextDeferredEntryId.IsEmpty()
? TEXT("none")
: CachedCoachSchedulePolicySummary.NextDeferredEntryId;
Surface.NextManualRescheduleEntryId =
CachedCoachSchedulePolicySummary.NextManualRescheduleEntryId.IsEmpty()
? TEXT("none")
: CachedCoachSchedulePolicySummary.NextManualRescheduleEntryId;
Surface.EarliestDeferredUntilUtc =
CachedCoachSchedulePolicySummary.EarliestDeferredUntilUtc.IsEmpty()
? TEXT("n/a")
: CachedCoachSchedulePolicySummary.EarliestDeferredUntilUtc;
Surface.DominantDeferralReasonLabel =
CachedCoachSchedulePolicySummary.DominantDeferralReasonLabel.IsEmpty()
? TEXT("n/a")
: CachedCoachSchedulePolicySummary.DominantDeferralReasonLabel;
Surface.ClosurePolicyLine = CachedCoachSchedulePolicySummary.ClosurePolicyLine.IsEmpty()
? TEXT("n/a")
: CachedCoachSchedulePolicySummary.ClosurePolicyLine;
Surface.HistoricalFollowUpContinuationCount =
CachedCoachSchedulePolicySummary.HistoricalFollowUpContinuationCount;
Surface.HistoricalBorderlineFollowUpSuppressionCount =
CachedCoachSchedulePolicySummary.HistoricalBorderlineFollowUpSuppressionCount;
Surface.ImmediateEntryCount = CachedCoachSchedulePolicySummary.ImmediateEntryCount;
Surface.PendingEntryCount = CachedCoachSchedulePolicySummary.PendingEntryCount;
Surface.DeferredEntryCount = CachedCoachSchedulePolicySummary.DeferredEntryCount;
Surface.ManualRescheduleEntryCount =
CachedCoachSchedulePolicySummary.ManualRescheduleEntryCount;
Surface.ArchiveAwareDeferredEntryCount =
CachedCoachSchedulePolicySummary.ArchiveAwareDeferredEntryCount;
Surface.BlockedFollowUpDeferredEntryCount =
CachedCoachSchedulePolicySummary.BlockedFollowUpDeferredEntryCount;
Surface.ReschedulePressureScore = CachedCoachSchedulePolicySummary.ReschedulePressureScore;
Surface.bAllowsManualReschedule = CachedCoachSchedulePolicySummary.bAllowsManualReschedule;
Surface.bHasExpiredDeferrals = CachedCoachSchedulePolicySummary.bHasExpiredDeferrals;
Surface.bNeedsManualRescheduleReview =
CachedCoachSchedulePolicySummary.bNeedsManualRescheduleReview;
Surface.bHasArchiveAwareDeferrals =
CachedCoachSchedulePolicySummary.bHasArchiveAwareDeferrals;
Surface.bHasBlockedFollowUpDeferrals =
CachedCoachSchedulePolicySummary.bHasBlockedFollowUpDeferrals;
Surface.bFollowUpContinuationFromRecoveryHistory =
CachedCoachSchedulePolicySummary.bFollowUpContinuationFromRecoveryHistory;
Surface.bBorderlineFollowUpSuppressedByRecoveryHistory =
CachedCoachSchedulePolicySummary.bBorderlineFollowUpSuppressedByRecoveryHistory;
Surface.PolicyLine = !DisplayedSchedulePolicyLine.IsEmpty()
? DisplayedSchedulePolicyLine
: FString::Printf(
TEXT("Policy: immediate %d | pending %d | deferred %d | manual %d | earliest deferred: %s | dominant reason: %s | pressure %.2f | manual allowed: %s | expired deferrals: %s | review needed: %s | archive-aware: %s | blocked follow-up: %s | closure: %s"),
Surface.ImmediateEntryCount,
Surface.PendingEntryCount,
Surface.DeferredEntryCount,
Surface.ManualRescheduleEntryCount,
*Surface.EarliestDeferredUntilUtc,
*Surface.DominantDeferralReasonLabel,
Surface.ReschedulePressureScore,
Surface.bAllowsManualReschedule ? TEXT("yes") : TEXT("no"),
Surface.bHasExpiredDeferrals ? TEXT("yes") : TEXT("no"),
Surface.bNeedsManualRescheduleReview ? TEXT("yes") : TEXT("no"),
Surface.bHasArchiveAwareDeferrals ? TEXT("yes") : TEXT("no"),
Surface.bHasBlockedFollowUpDeferrals ? TEXT("yes") : TEXT("no"),
*Surface.ClosurePolicyLine);
return Surface;
}
FHyperTwistTrainingCoachDashboardLastAttemptReviewSummaryInspectSurface
UHyperTwistCoachDashboardWidget::GetDisplayedLastAttemptReviewSummaryInspectSurface() const
{
@ -24132,7 +24283,7 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
}
if (ScheduleStatusTextBlock != nullptr)
{
ScheduleStatusTextBlock->SetText(FText::FromString(FString::Printf(
DisplayedScheduleStatusLine = FString::Printf(
TEXT("Horizon: %s | Immediate %d | Deferred %d | Archive-aware %d | Follow-up %d | Pinned %d | Immediate window: %s | Deferred window: %s | Blocked follow-up: %s"),
CachedCoachScheduleHorizonSummary.CurrentHorizonLabel.IsEmpty()
? TEXT("n/a")
@ -24145,11 +24296,12 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
CachedCoachScheduleHorizonSummary.bHasImmediateWindow ? TEXT("yes") : TEXT("no"),
CachedCoachScheduleHorizonSummary.bHasDeferredWindow ? TEXT("yes") : TEXT("no"),
CachedCoachScheduleHorizonSummary.bHasBlockedFollowUp ? TEXT("yes") : TEXT("no")
)));
);
ScheduleStatusTextBlock->SetText(FText::FromString(DisplayedScheduleStatusLine));
}
if (SchedulePolicyTextBlock != nullptr)
{
SchedulePolicyTextBlock->SetText(FText::FromString(FString::Printf(
DisplayedSchedulePolicyLine = FString::Printf(
TEXT("Policy: immediate %d | pending %d | deferred %d | manual %d | earliest deferred: %s | dominant reason: %s | pressure %.2f | manual allowed: %s | expired deferrals: %s | review needed: %s | archive-aware: %s | blocked follow-up: %s | closure: %s"),
CachedCoachSchedulePolicySummary.ImmediateEntryCount,
CachedCoachSchedulePolicySummary.PendingEntryCount,
@ -24170,7 +24322,8 @@ void UHyperTwistCoachDashboardWidget::UpdateDashboardPresentation()
CachedCoachSchedulePolicySummary.ClosurePolicyLine.IsEmpty()
? TEXT("n/a")
: *CachedCoachSchedulePolicySummary.ClosurePolicyLine
)));
);
SchedulePolicyTextBlock->SetText(FText::FromString(DisplayedSchedulePolicyLine));
}
const int32 ClosureKeepHistoryCount =
CachedCoachSchedulePolicySummary.HistoricalFollowUpContinuationCount;

View file

@ -875,6 +875,14 @@ public:
FHyperTwistTrainingCoachDashboardSelectedQueueEntryDetailInspectSurface
GetDisplayedSelectedQueueEntryDetailInspectSurface() const;
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
FHyperTwistTrainingCoachDashboardScheduleHorizonStatusInspectSurface
GetDisplayedScheduleHorizonStatusInspectSurface() const;
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
FHyperTwistTrainingCoachDashboardSchedulePolicyFrictionInspectSurface
GetDisplayedSchedulePolicyFrictionInspectSurface() const;
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|Coach|Dashboard")
FHyperTwistTrainingCoachDashboardLastAttemptReviewSummaryInspectSurface
GetDisplayedLastAttemptReviewSummaryInspectSurface() const;
@ -1967,6 +1975,8 @@ private:
FString DisplayedQueueExecutionLine;
FString DisplayedSelectedQueueSummaryLine;
FString DisplayedSelectedQueueEntryDetailLine;
FString DisplayedScheduleStatusLine;
FString DisplayedSchedulePolicyLine;
FString DisplayedPreviousQueueNavigationLabel;
FString DisplayedStartSelectedQueueActionLabel;
FString DisplayedNextQueueNavigationLabel;

View file

@ -11553,6 +11553,184 @@ struct FHyperTwistTrainingCoachDashboardSelectedQueueEntryDetailInspectSurface
}
};
USTRUCT(BlueprintType)
struct FHyperTwistTrainingCoachDashboardScheduleHorizonStatusInspectSurface
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString Headline;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString StatusLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString QueueId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString FocusDeckId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString FocusMethodSegmentId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString ActiveEntryId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString NextReadyEntryId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString NextDeferredEntryId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString NextArchiveEntryId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString NextFollowUpEntryId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString CurrentHorizonLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 ImmediateEntryCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 DeferredEntryCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 ArchiveAwareEntryCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 FollowUpEntryCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 PinnedEntryCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasImmediateWindow = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasDeferredWindow = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bNeedsArchiveWindow = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasBlockedFollowUp = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasInProgressEntry = false;
bool IsStructurallyValid() const
{
return !StatusLine.IsEmpty()
|| !CurrentHorizonLabel.IsEmpty()
|| ImmediateEntryCount > 0
|| DeferredEntryCount > 0
|| bHasInProgressEntry;
}
};
USTRUCT(BlueprintType)
struct FHyperTwistTrainingCoachDashboardSchedulePolicyFrictionInspectSurface
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString Headline;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString PolicyLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString QueueId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString FocusDeckId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString FocusMethodSegmentId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString NextImmediateEntryId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString NextPendingEntryId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString NextDeferredEntryId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString NextManualRescheduleEntryId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString EarliestDeferredUntilUtc;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString DominantDeferralReasonLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString ClosurePolicyLine;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 HistoricalFollowUpContinuationCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 HistoricalBorderlineFollowUpSuppressionCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 ImmediateEntryCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 PendingEntryCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 DeferredEntryCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 ManualRescheduleEntryCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 ArchiveAwareDeferredEntryCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 BlockedFollowUpDeferredEntryCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
float ReschedulePressureScore = 0.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bAllowsManualReschedule = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasExpiredDeferrals = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bNeedsManualRescheduleReview = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasArchiveAwareDeferrals = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasBlockedFollowUpDeferrals = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bFollowUpContinuationFromRecoveryHistory = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bBorderlineFollowUpSuppressedByRecoveryHistory = false;
bool IsStructurallyValid() const
{
return !PolicyLine.IsEmpty()
|| ReschedulePressureScore > 0.0f
|| DeferredEntryCount > 0
|| ManualRescheduleEntryCount > 0
|| bHasArchiveAwareDeferrals
|| bHasBlockedFollowUpDeferrals;
}
};
USTRUCT(BlueprintType)
struct FHyperTwistTrainingCoachDashboardLastAttemptReviewSummaryInspectSurface
{

View file

@ -69,10 +69,24 @@ 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 queue counts/status, selected-queue summary, and selected queue-entry detail inspect surfaces over already-derived live dashboard queue overview and selected-entry presentation state, so gameplay/Blueprint callers can inspect the live queue status line, counts/execution posture, current selected-entry summary, and selected-entry detail without scraping widget text or reopening queue-state derivation
- the next clean move is to stay on that same live dashboard guidance-consumer lane and land the schedule horizon status and schedule policy / friction inspect surface pair 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 schedule horizon status and schedule policy / friction inspect surfaces over already-derived live dashboard schedule presentation state, so gameplay/Blueprint callers can inspect the live horizon posture, queue-window summary, policy/friction line, and reschedule/closure posture without scraping widget text or reopening schedule derivation
- the next clean move is to stay on that same live dashboard guidance-consumer lane and land the closure-recovery live status and closure-recovery detail inspect surface pair 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
## Donor portfolio phase taxonomy
- repo-portfolio intake/classification, mirror custody boundaries, model allowlists, and first-pass donor evaluation belong primarily to Phase `0` and are materially established already
- owned contract extraction from chosen donors belongs primarily to Phase `1` and is already reflected in the first-party notation, replay, training-content, provenance, vision-sidecar, and speech-sidecar contracts
- deep source-level audit of the wider donor corpus is not globally closed; it remains selective ongoing work anchored by the late-Phase-`4` manifest-reconciliation / custody-governance reservation and by later phase-specific donor decisions
- clean-room work belongs first to Phase `0` governance and Phase `1` contract shaping, then executes only for selected restrictive repos when a bounded first-party lane needs it; several restrictive donors already have scrubbed Model A handoff files, but not every restrictive mirror has or needs a full clean-room implementation yet
- implementation of valuable donor ideas is intentionally distributed by domain across later phases rather than treated as one giant repo-import pass:
- Phase `3` / `4`: coaching, runtime, orchestration, recognition continuity, and live consumers
- Phase `5`: speech-sidecar and embodied-coach donors
- Phase `6`: hypercube/simulation donors
- Phase `7`: XR/immersive donors
- Phase `8`: benchmark-oracle, correctness, and release-hardening donors
- do not treat the mirror portfolio as an instruction to deep-audit or reimplement every repo before product work can continue; only the active and justified donor lanes should be pulled forward
## Current execution-reality references
For the current code-reality synthesis and active phase-discipline note, also read:

View file

@ -0,0 +1,52 @@
# HyperTwist Phase 4 dashboard live schedule horizon status and schedule policy / friction 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 schedule horizon and schedule policy / friction presentation state directly to gameplay and Blueprint callers.
## Why this packet exists
The dashboard already derived:
- the live schedule horizon status line
- the live schedule policy / friction line
But that state still only surfaced through widget text blocks. Callers still had to scrape dashboard text to inspect the current queue-window posture, reschedule pressure, deferral reason, and closure policy presentation.
## What changed
- added `FHyperTwistTrainingCoachDashboardScheduleHorizonStatusInspectSurface`
- added `FHyperTwistTrainingCoachDashboardSchedulePolicyFrictionInspectSurface`
- added `GetDisplayedScheduleHorizonStatusInspectSurface()`
- added `GetDisplayedSchedulePolicyFrictionInspectSurface()`
- retained the exact displayed schedule horizon and schedule policy lines inside the widget so the new inspect surfaces report the same live strings the dashboard is already presenting
- refreshed the roadmap docs to record the donor-portfolio phase taxonomy, including where deep donor source audit, selective restrictive clean-room work, and phase-specific donor implementation belong in the live roadmap
- 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 live schedule horizon label, queue-window posture, active/next entry routing, and horizon counts
- the live schedule policy / friction line, reschedule pressure, deferred-window posture, dominant deferral reason, and closure-policy context
without scraping dashboard text blocks or reopening schedule 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 closure-recovery live status and closure-recovery detail inspect surface pair.