# HyperTwist Phase 4 gameplay queue-control surface packet

Created on `2026-05-07`

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 secondary queue-control descriptor / availability surface for defer and promote flows.

The open tasks were:

- stop forcing gameplay / Blueprint callers to reconstruct defer-vs-promote readiness from raw panel-state and queue-state booleans just to bind the common non-primary queue controls
- expose the actual displayed defer target, the preferred deferred promote target, and promote provenance through a narrow pure surface instead of through caller-side queue inspection
- align `PromoteDisplayedCoachQueueEntry()` on the panel-widget and session-actor with the same deferred-entry recovery ranking already used by the dashboard, instead of assuming the active queue entry is the promote target

It is not:

- a new queue-policy packet
- a broader gameplay UI composition pass
- a new default deferral-window flow
- a backend continuity or template-analytics packet

## Scope

Bounded lane:

- add a first-party secondary queue-control surface type in shared training types
- add a coach-library helper that derives defer/promote availability from the retained queue state plus coach panel state
- expose that derived surface on `HyperTwistTrainingPanelWidget` and `HyperTwistTrainingSessionActor`
- keep the derived promote target aligned with the existing dashboard deferred-entry recovery ranking
- route the panel/session displayed defer and displayed promote helpers through that same derived surface

Out of scope:

- changing queue recovery policy
- adding dashboard-only selection state to the gameplay consumers
- introducing new queue UI widgets
- widening into broader passive status composition in the same packet

## Why this was the right next packet

Before this slice:

- gameplay-facing panel/session consumers already had displayed queue execution helpers
- those surfaces already had a primary coach CTA surface and execution provenance
- callers could launch the current primary action without dashboard code

But one thin consumer seam was still open:

- callers still had to inspect raw queue-state and panel-state booleans to decide whether defer or promote should be shown
- the panel-widget and session-actor still promoted `ActiveQueueEntryId`, even though the dashboard already promotes the best deferred recovery candidate instead

That meant:

- primary coach action rendering was thin
- but truthful secondary queue-control rendering and promotion targeting still drifted across consumers

So the next bounded move was:

- keep queue policy unchanged
- expose one narrow pure queue-control surface
- and route the displayed promote path through the same deferred-entry recovery target selection already used on the dashboard

## What landed

Primary code changes:

- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h`
  - added `FHyperTwistTrainingCoachQueueControlSurface`
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingCoachLibrary.h`
- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingCoachLibrary.cpp`
  - added `DeriveCoachQueueControlSurface(...)`
  - centralized deferred-entry promotion scoring and preferred deferred-target resolution for shared consumers
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingPanelWidget.h`
- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingPanelWidget.cpp`
  - added `GetDisplayedCoachQueueControlSurface()`
  - `DeferDisplayedCoachQueueEntry(...)` and `PromoteDisplayedCoachQueueEntry()` now route through the derived surface instead of directly trusting `ActiveQueueEntryId`
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingSessionActor.h`
- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSessionActor.cpp`
  - added `GetDisplayedCoachQueueControlSurface()`
  - the actor-side displayed defer/promote helpers now route through the same derived surface
- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistCoachDashboardWidget.cpp`
  - `FindFirstDeferredQueueEntryId()` now reuses the shared queue-control derivation instead of holding a duplicate deferred-ranking implementation

## Product effect

The gameplay-facing coach consumer layer is now more complete:

- gameplay / Blueprint callers can bind defer and promote controls from a pure descriptor instead of replaying queue-state branching
- panel-widget and session-actor promote behavior no longer assumes the active queue entry is the correct promote target
- the dashboard and the gameplay-facing consumers now resolve deferred recovery targets through one shared ranking path

## Acceptance criteria

- shared training types expose a narrow queue-control surface
- coach-library derivation resolves the displayed defer target and the preferred deferred promote target
- panel-widget callers can fetch the displayed queue-control surface directly
- session-actor callers can fetch the displayed queue-control surface directly
- displayed promote no longer depends on `ActiveQueueEntryId`
- full product build succeeds

## Validation checklist

1. build `UnrealHyperTwist.sln` / `UnrealHyperTwistEditor`
2. confirm the new queue-control surface compiles in shared types and coach library
3. confirm panel-widget getters compile and the displayed defer/promote helpers route through the derived surface
4. confirm session-actor getters compile and the displayed defer/promote helpers route through the derived surface
5. confirm the dashboard still resolves the same deferred promote target through the shared helper

## Validation result

- full `Development Editor|Win64` build succeeded on `2026-05-07`
- build completed with the same preexisting `UnrealMCP` / `PythonScriptPlugin` dependency warning and `0` errors

## Next bounded follow-on slice

- stay on the same gameplay-facing consumer lane and expose one thin queue-recovery posture / status surface on `HyperTwistTrainingPanelWidget` and `HyperTwistTrainingSessionActor`, so gameplay callers can explain why continue, defer, or promote is preferred without reading raw suppression/status strings or recovery enums directly
