Implement Phase 6R-B calibrated face observation contract

This commit is contained in:
axiomlogicnexus 2026-05-20 23:29:41 +02:00
parent 30b553b792
commit 47670a764a
10 changed files with 980 additions and 33 deletions

View file

@ -97,6 +97,72 @@ namespace HyperTwistContractLibraryInternal
DrillDeck.SourceAttribution = Attribution;
return DrillDeck;
}
FHyperTwistVisionCalibrationProfile MakeDefaultClassicCubeCalibrationProfile(const FString& ProfileId)
{
FHyperTwistVisionCalibrationProfile Profile;
Profile.ProfileId = ProfileId;
Profile.PuzzleId = TEXT("cube/3x3x3");
Profile.DominantColorMethod = TEXT("kmeans-1");
Profile.ColorDistanceMethod = TEXT("ciede2000");
Profile.bPersistsPerUserPalette = true;
auto AddSwatch = [&Profile](
const TCHAR* ColorId,
const TCHAR* Notation,
const FIntVector Bgr,
const FVector Lab
)
{
FHyperTwistVisionCalibrationSwatch Swatch;
Swatch.ColorId = ColorId;
Swatch.Notation = Notation;
Swatch.ReferenceBgr = Bgr;
Swatch.ReferenceLab = Lab;
Profile.PaletteSwatches.Add(Swatch);
};
AddSwatch(TEXT("green"), TEXT("F"), FIntVector(0, 255, 0), FVector(87.737f, -86.185f, 83.181f));
AddSwatch(TEXT("red"), TEXT("R"), FIntVector(0, 0, 255), FVector(53.233f, 80.109f, 67.220f));
AddSwatch(TEXT("blue"), TEXT("B"), FIntVector(255, 0, 0), FVector(32.303f, 79.197f, -107.864f));
AddSwatch(TEXT("orange"), TEXT("L"), FIntVector(0, 165, 255), FVector(74.200f, 23.900f, 78.900f));
AddSwatch(TEXT("white"), TEXT("U"), FIntVector(255, 255, 255), FVector(100.000f, 0.000f, 0.000f));
AddSwatch(TEXT("yellow"), TEXT("D"), FIntVector(0, 255, 255), FVector(97.139f, -21.554f, 94.478f));
return Profile;
}
FHyperTwistVisionFaceObservation MakeMockClassicFaceObservation(
const FString& ObservationId,
const FString& FaceId,
const float StickerConfidence,
const bool bCommitReady
)
{
FHyperTwistVisionFaceObservation Observation;
Observation.ObservationId = ObservationId;
Observation.FaceId = FaceId;
Observation.OrderingProfile = TEXT("3x3-row-major");
Observation.CandidateContourCount = 12;
Observation.AcceptedContourCount = 9;
Observation.bFoundStableThreeByThreeGrid = true;
Observation.bOrderingStable = true;
Observation.bCommitReady = bCommitReady;
for (int32 GridIndex = 0; GridIndex < 9; ++GridIndex)
{
FHyperTwistVisionObservedSticker Sticker;
Sticker.GridIndex = GridIndex;
Sticker.GridRow = GridIndex / 3;
Sticker.GridColumn = GridIndex % 3;
Sticker.ColorId = TEXT("green");
Sticker.Notation = TEXT("F");
Sticker.SampleBgr = FIntVector(0, 255, 0);
Sticker.Confidence = StickerConfidence;
Observation.OrderedStickers.Add(Sticker);
}
return Observation;
}
}
FHyperTwistPuzzleDefinitionRef UHyperTwistContractLibrary::MakeSampleClassicPuzzleDefinition()
@ -321,6 +387,11 @@ FHyperTwistVisionSessionConfig UHyperTwistContractLibrary::MakeSampleVisionSessi
Config.PuzzleId = TEXT("cube/3x3x3");
Config.ExpectedPuzzleFamily = EHyperTwistPuzzleFamily::ClassicCube;
Config.NotationProfile = TEXT("classic-wca");
Config.CalibrationProfile = TEXT("classic-cube-default");
Config.CalibrationProfileDefinition =
HyperTwistContractLibraryInternal::MakeDefaultClassicCubeCalibrationProfile(
Config.CalibrationProfile
);
Config.FrameSize = FIntPoint(1280, 720);
Config.MaxFrameRate = 30;
return Config;
@ -335,6 +406,12 @@ FHyperTwistVisionPreviewResult UHyperTwistContractLibrary::MakeMockVisionPreview
Result.PreviewState.SnapshotId = TEXT("snap_prev_10");
Result.PreviewState.State = MakeSampleClassicRecognitionPreviewState();
Result.PreviewState.DerivedHash = TEXT("preview_hash");
Result.ObservedFace = HyperTwistContractLibraryInternal::MakeMockClassicFaceObservation(
TEXT("observation_preview_10"),
TEXT("F"),
0.84f,
false
);
Result.Guidance = TEXT("capture-ready");
return Result;
}
@ -352,6 +429,12 @@ FHyperTwistVisionCommitResult UHyperTwistContractLibrary::MakeMockVisionCommitRe
Result.Snapshot.DerivedHash = TEXT("commit_hash");
Result.Confidence = 0.96f;
Result.CommittedUnit = TEXT("F");
Result.ObservedFace = HyperTwistContractLibraryInternal::MakeMockClassicFaceObservation(
TEXT("observation_commit"),
TEXT("F"),
0.96f,
true
);
return Result;
}
@ -377,7 +460,12 @@ FHyperTwistVisionServiceHealth UHyperTwistContractLibrary::MakeMockVisionService
Health.ProviderLabel = TEXT("mock");
Health.ServiceVersion = TEXT("mock-vision/v1");
Health.ServiceEndpoint = TEXT("in-process://mock");
Health.Capabilities = {TEXT("liveCamera3x3"), TEXT("faceCommitFlow"), TEXT("calibrationProfiles")};
Health.Capabilities = {
TEXT("liveCamera3x3"),
TEXT("faceCommitFlow"),
TEXT("calibrationProfiles"),
TEXT("orderedFaceObservation")
};
Health.bReady = true;
return Health;
}

View file

@ -373,7 +373,9 @@ FHyperTwistVisionServiceHealth UHyperTwistHttpVisionClient::GetVisionServiceHeal
Health.bReady = false;
Health.Capabilities = {
TEXT("transport:http"),
TEXT("provider-backed-recognition")
TEXT("provider-backed-recognition"),
TEXT("calibrationProfiles"),
TEXT("orderedFaceObservation")
};
HyperTwistHttpVisionClientInternal::FHttpJsonResponse Response;
@ -399,7 +401,9 @@ FHyperTwistVisionServiceHealth UHyperTwistHttpVisionClient::GetVisionServiceHeal
Health.bReady = false;
Health.Capabilities = {
TEXT("transport:http"),
TEXT("provider-backed-recognition")
TEXT("provider-backed-recognition"),
TEXT("calibrationProfiles"),
TEXT("orderedFaceObservation")
};
Health.LastError = LastTransportError;
return Health;
@ -417,6 +421,8 @@ FHyperTwistVisionServiceHealth UHyperTwistHttpVisionClient::GetVisionServiceHeal
Health.Capabilities.AddUnique(TEXT("transport:http"));
Health.Capabilities.AddUnique(TEXT("provider-backed-recognition"));
Health.Capabilities.AddUnique(TEXT("calibrationProfiles"));
Health.Capabilities.AddUnique(TEXT("orderedFaceObservation"));
Health.LastError.Reset();
LastTransportError.Reset();
return Health;

View file

@ -26,7 +26,12 @@ FHyperTwistVisionPreviewResult UHyperTwistMockVisionClient::SubmitVisionFrame(co
const int32 NextFrameCount = SessionFrameCounts.FindRef(Frame.SessionId) + 1;
SessionFrameCounts.Add(Frame.SessionId, NextFrameCount);
Result.Guidance = NextFrameCount >= 3 ? TEXT("commit-ready") : TEXT("keep-scanning");
Result.ObservedFace.FaceId = !Frame.TargetFaceHint.IsEmpty() ? Frame.TargetFaceHint : Result.ObservedFace.FaceId;
Result.ObservedFace.ObservationId = Result.FrameId.IsEmpty()
? TEXT("observation_preview")
: FString::Printf(TEXT("%s/preview"), *Result.FrameId);
Result.ObservedFace.bCommitReady = NextFrameCount >= 3;
Result.Guidance = Result.ObservedFace.bCommitReady ? TEXT("commit-ready") : TEXT("keep-scanning");
return Result;
}
@ -38,6 +43,11 @@ FHyperTwistVisionCommitResult UHyperTwistMockVisionClient::CommitVisionObservati
Result.CommitKind = Request.CommitKind;
Result.CommittedUnit = !Request.TargetFace.IsEmpty() ? Request.TargetFace : Request.TargetStage;
Result.Snapshot.State.SourceSessionId = Request.SessionId;
Result.ObservedFace.FaceId = !Request.TargetFace.IsEmpty() ? Request.TargetFace : Result.ObservedFace.FaceId;
Result.ObservedFace.ObservationId = Request.SessionId.IsEmpty()
? TEXT("observation_commit")
: FString::Printf(TEXT("%s/commit"), *Request.SessionId);
Result.ObservedFace.bCommitReady = true;
if (!SessionConfigs.Contains(Request.SessionId))
{

View file

@ -1866,6 +1866,45 @@ namespace HyperTwistTrainingSubsystemInternal
return FString::Printf(TEXT("%s_frame_%03d"), *SessionId, FMath::Max(1, FrameOrdinal));
}
bool IsQbrClassicCubeRoute(const FHyperTwistVisionSessionConfig& SessionConfig)
{
return SessionConfig.ExpectedPuzzleFamily == EHyperTwistPuzzleFamily::ClassicCube
&& SessionConfig.PuzzleId == TEXT("cube/3x3x3");
}
FHyperTwistVisionCalibrationProfile BuildDefaultClassicCubeCalibrationProfile(const FString& ProfileId)
{
FHyperTwistVisionCalibrationProfile Profile;
Profile.ProfileId = ProfileId;
Profile.PuzzleId = TEXT("cube/3x3x3");
Profile.DominantColorMethod = TEXT("kmeans-1");
Profile.ColorDistanceMethod = TEXT("ciede2000");
Profile.bPersistsPerUserPalette = true;
auto AddSwatch = [&Profile](
const TCHAR* ColorId,
const TCHAR* Notation,
const FIntVector Bgr,
const FVector Lab
)
{
FHyperTwistVisionCalibrationSwatch Swatch;
Swatch.ColorId = ColorId;
Swatch.Notation = Notation;
Swatch.ReferenceBgr = Bgr;
Swatch.ReferenceLab = Lab;
Profile.PaletteSwatches.Add(Swatch);
};
AddSwatch(TEXT("green"), TEXT("F"), FIntVector(0, 255, 0), FVector(87.737f, -86.185f, 83.181f));
AddSwatch(TEXT("red"), TEXT("R"), FIntVector(0, 0, 255), FVector(53.233f, 80.109f, 67.220f));
AddSwatch(TEXT("blue"), TEXT("B"), FIntVector(255, 0, 0), FVector(32.303f, 79.197f, -107.864f));
AddSwatch(TEXT("orange"), TEXT("L"), FIntVector(0, 165, 255), FVector(74.200f, 23.900f, 78.900f));
AddSwatch(TEXT("white"), TEXT("U"), FIntVector(255, 255, 255), FVector(100.000f, 0.000f, 0.000f));
AddSwatch(TEXT("yellow"), TEXT("D"), FIntVector(0, 255, 255), FVector(97.139f, -21.554f, 94.478f));
return Profile;
}
EHyperTwistPuzzleFamily ResolvePuzzleFamilyFromPuzzleId(const FString& PuzzleId)
{
FHyperTwistPuzzleDefinitionRef RetainedHyperDefinition;
@ -6094,6 +6133,11 @@ FHyperTwistVisionPreviewResult UHyperTwistTrainingSubsystem::SubmitActiveRecogni
{
NormalizedFrame.CapturedAtUtc = FDateTime::UtcNow().ToIso8601();
}
if (NormalizedFrame.ObservationProfile.IsEmpty()
&& HyperTwistTrainingSubsystemInternal::IsQbrClassicCubeRoute(ActiveRecognitionSessionState.SessionConfig))
{
NormalizedFrame.ObservationProfile = TEXT("classic-3x3-face-observation-v1");
}
Result = VisionClient->SubmitVisionFrame(NormalizedFrame);
if (Result.SessionId.IsEmpty())
@ -6782,6 +6826,29 @@ FHyperTwistVisionSessionConfig UHyperTwistTrainingSubsystem::BuildActiveRecognit
{
SessionConfig.MaxFrameRate = 30;
}
if (HyperTwistTrainingSubsystemInternal::IsQbrClassicCubeRoute(SessionConfig))
{
if (SessionConfig.CalibrationProfile.IsEmpty()
&& SessionConfig.CalibrationProfileDefinition.IsStructurallyValid())
{
SessionConfig.CalibrationProfile = SessionConfig.CalibrationProfileDefinition.ProfileId;
}
if (SessionConfig.CalibrationProfile.IsEmpty())
{
SessionConfig.CalibrationProfile = TEXT("classic-cube-default");
}
if (!SessionConfig.CalibrationProfileDefinition.IsStructurallyValid())
{
SessionConfig.CalibrationProfileDefinition =
HyperTwistTrainingSubsystemInternal::BuildDefaultClassicCubeCalibrationProfile(
SessionConfig.CalibrationProfile
);
}
if (SessionConfig.CalibrationProfileDefinition.ProfileId.IsEmpty())
{
SessionConfig.CalibrationProfileDefinition.ProfileId = SessionConfig.CalibrationProfile;
}
}
return SessionConfig;
}

View file

@ -11,6 +11,168 @@ enum class EHyperTwistVisionCaptureMode : uint8
BatchVideo UMETA(DisplayName = "Batch Video")
};
USTRUCT(BlueprintType)
struct FHyperTwistVisionCalibrationSwatch
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString ColorId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString Notation;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FIntVector ReferenceBgr = FIntVector::ZeroValue;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FVector ReferenceLab = FVector::ZeroVector;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bUserCalibrated = false;
bool IsStructurallyValid() const
{
return !ColorId.IsEmpty() && !Notation.IsEmpty();
}
};
USTRUCT(BlueprintType)
struct FHyperTwistVisionCalibrationProfile
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString ProfileId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString PuzzleId = TEXT("cube/3x3x3");
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString DominantColorMethod = TEXT("kmeans-1");
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString ColorDistanceMethod = TEXT("ciede2000");
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bPersistsPerUserPalette = true;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
TArray<FHyperTwistVisionCalibrationSwatch> PaletteSwatches;
bool IsStructurallyValid() const
{
if (ProfileId.IsEmpty() || PuzzleId.IsEmpty() || PaletteSwatches.Num() < 6)
{
return false;
}
for (const FHyperTwistVisionCalibrationSwatch& Swatch : PaletteSwatches)
{
if (!Swatch.IsStructurallyValid())
{
return false;
}
}
return true;
}
};
USTRUCT(BlueprintType)
struct FHyperTwistVisionObservedSticker
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 GridIndex = -1;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 GridRow = -1;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 GridColumn = -1;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString ColorId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString Notation;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FIntVector SampleBgr = FIntVector::ZeroValue;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
float Confidence = 0.0f;
bool IsStructurallyValid() const
{
return GridIndex >= 0
&& GridRow >= 0
&& GridColumn >= 0
&& !ColorId.IsEmpty()
&& !Notation.IsEmpty();
}
};
USTRUCT(BlueprintType)
struct FHyperTwistVisionFaceObservation
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString ObservationId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString FaceId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString OrderingProfile = TEXT("3x3-row-major");
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 CandidateContourCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 AcceptedContourCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bFoundStableThreeByThreeGrid = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bOrderingStable = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bCommitReady = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
TArray<FHyperTwistVisionObservedSticker> OrderedStickers;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
TArray<FString> NormalizationWarnings;
bool IsStructurallyValid() const
{
if (ObservationId.IsEmpty()
|| FaceId.IsEmpty()
|| OrderedStickers.Num() != 9
|| !bFoundStableThreeByThreeGrid
|| !bOrderingStable)
{
return false;
}
for (const FHyperTwistVisionObservedSticker& Sticker : OrderedStickers)
{
if (!Sticker.IsStructurallyValid())
{
return false;
}
}
return true;
}
};
USTRUCT(BlueprintType)
struct FHyperTwistVisionSessionConfig
{
@ -37,6 +199,9 @@ struct FHyperTwistVisionSessionConfig
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString CalibrationProfile;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FHyperTwistVisionCalibrationProfile CalibrationProfileDefinition;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FIntPoint FrameSize = FIntPoint(1280, 720);
@ -72,6 +237,12 @@ struct FHyperTwistVisionFrameEnvelope
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 SourceTimestampMs = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString TargetFaceHint;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString ObservationProfile = TEXT("classic-3x3-face-observation-v1");
};
USTRUCT(BlueprintType)
@ -91,6 +262,9 @@ struct FHyperTwistVisionPreviewResult
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FHyperTwistStateSnapshot PreviewState;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FHyperTwistVisionFaceObservation ObservedFace;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString Guidance;
};
@ -133,6 +307,9 @@ struct FHyperTwistVisionCommitResult
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString CommittedUnit;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FHyperTwistVisionFaceObservation ObservedFace;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
TArray<FString> Warnings;

View file

@ -0,0 +1,237 @@
// Copyright HyperTwist, Inc. All Rights Reserved.
#include "Misc/AutomationTest.h"
#include "Engine/GameInstance.h"
#include "HyperTwistTraining/HyperTwistTrainingSubsystem.h"
#include "UObject/UnrealType.h"
#if WITH_AUTOMATION_TESTS
namespace HyperTwistQbrPhase6RBTestInternal
{
FHyperTwistTrainingDeck MakeRecognitionDeck()
{
FHyperTwistTrainingDeck Deck;
Deck.DeckId = TEXT("phase6r-b/qbr-recognition");
Deck.Title = TEXT("Phase 6R-B Qbr Recognition");
Deck.DeliveryModes = {
EHyperTwistTrainingDeliveryMode::RecognitionAssisted,
EHyperTwistTrainingDeliveryMode::CoachReviewed
};
FHyperTwistTrainingCase TrainingCase;
TrainingCase.CaseId = TEXT("phase6r-b-case");
TrainingCase.PuzzleId = TEXT("cube/3x3x3");
TrainingCase.PromptKind = EHyperTwistTrainingPromptKind::Recognition;
TrainingCase.PromptLabel = TEXT("Phase 6R-B Recognition");
TrainingCase.AllowedDeliveryModes = {
EHyperTwistTrainingDeliveryMode::RecognitionAssisted,
EHyperTwistTrainingDeliveryMode::CoachReviewed
};
Deck.Cases = {TrainingCase};
return Deck;
}
void ForceMockRecognitionClient(UHyperTwistTrainingSubsystem* TrainingSubsystem)
{
if (TrainingSubsystem == nullptr)
{
return;
}
if (FStrProperty* RecognitionClientKindProperty = FindFProperty<FStrProperty>(
UHyperTwistTrainingSubsystem::StaticClass(),
TEXT("RecognitionClientKind")
))
{
RecognitionClientKindProperty->SetPropertyValue_InContainer(TrainingSubsystem, TEXT("mock"));
}
}
}
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
FHyperTwistQbrPhase6RBCalibrationSessionConfigTest,
"HyperTwist.Permissive.Qbr.Phase6R.B.CalibrationSessionConfig",
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)
bool FHyperTwistQbrPhase6RBCalibrationSessionConfigTest::RunTest(const FString& Parameters)
{
UGameInstance* GameInstance = NewObject<UGameInstance>(GetTransientPackage());
TestNotNull(TEXT("Game instance outer must exist for subsystem construction."), GameInstance);
if (GameInstance == nullptr)
{
return false;
}
UHyperTwistTrainingSubsystem* TrainingSubsystem = NewObject<UHyperTwistTrainingSubsystem>(GameInstance);
TestNotNull(TEXT("Training subsystem must be constructed."), TrainingSubsystem);
if (TrainingSubsystem == nullptr)
{
return false;
}
HyperTwistQbrPhase6RBTestInternal::ForceMockRecognitionClient(TrainingSubsystem);
const FHyperTwistTrainingRunState RunState = TrainingSubsystem->StartTrainingRunFromDeck(
HyperTwistQbrPhase6RBTestInternal::MakeRecognitionDeck(),
TEXT("phase6r-b-user"),
TEXT("phase6r-b-session"),
EHyperTwistTrainingDeliveryMode::RecognitionAssisted
);
TestTrue(TEXT("The recognition-assisted run must start successfully."), RunState.IsStructurallyValid());
if (!RunState.IsStructurallyValid())
{
return false;
}
FString OpenError;
TestTrue(
TEXT("The recognition session must open for a classic 3x3 run."),
TrainingSubsystem->OpenActiveRecognitionSession(OpenError)
);
TestTrue(TEXT("Opening the recognition session must not report an error."), OpenError.IsEmpty());
const FHyperTwistTrainingRecognitionSessionState SessionState =
TrainingSubsystem->GetActiveRecognitionSessionState();
TestEqual(
TEXT("The qbr-bounded route must default to the classic-cube calibration profile id."),
SessionState.SessionConfig.CalibrationProfile,
TEXT("classic-cube-default")
);
TestTrue(
TEXT("The qbr-bounded route must provide a structurally valid calibration profile definition."),
SessionState.SessionConfig.CalibrationProfileDefinition.IsStructurallyValid()
);
TestEqual(
TEXT("The calibration profile must preserve six retained swatches."),
SessionState.SessionConfig.CalibrationProfileDefinition.PaletteSwatches.Num(),
6
);
if (SessionState.SessionConfig.CalibrationProfileDefinition.PaletteSwatches.Num() > 0)
{
TestEqual(
TEXT("The front swatch must preserve the green/F calibration mapping."),
SessionState.SessionConfig.CalibrationProfileDefinition.PaletteSwatches[0].Notation,
TEXT("F")
);
}
return true;
}
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
FHyperTwistQbrPhase6RBPreviewObservationTest,
"HyperTwist.Permissive.Qbr.Phase6R.B.PreviewObservation",
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)
bool FHyperTwistQbrPhase6RBPreviewObservationTest::RunTest(const FString& Parameters)
{
UGameInstance* GameInstance = NewObject<UGameInstance>(GetTransientPackage());
TestNotNull(TEXT("Game instance outer must exist for subsystem construction."), GameInstance);
if (GameInstance == nullptr)
{
return false;
}
UHyperTwistTrainingSubsystem* TrainingSubsystem = NewObject<UHyperTwistTrainingSubsystem>(GameInstance);
TestNotNull(TEXT("Training subsystem must be constructed."), TrainingSubsystem);
if (TrainingSubsystem == nullptr)
{
return false;
}
HyperTwistQbrPhase6RBTestInternal::ForceMockRecognitionClient(TrainingSubsystem);
const FHyperTwistTrainingRunState RunState = TrainingSubsystem->StartTrainingRunFromDeck(
HyperTwistQbrPhase6RBTestInternal::MakeRecognitionDeck(),
TEXT("phase6r-b-user"),
TEXT("phase6r-b-preview-session"),
EHyperTwistTrainingDeliveryMode::RecognitionAssisted
);
TestTrue(TEXT("The recognition-assisted run must start successfully."), RunState.IsStructurallyValid());
if (!RunState.IsStructurallyValid())
{
return false;
}
FHyperTwistVisionPreviewResult Result;
for (int32 FrameOrdinal = 1; FrameOrdinal <= 3; ++FrameOrdinal)
{
FHyperTwistVisionFrameEnvelope Frame;
Frame.FrameOrdinal = FrameOrdinal;
Frame.TargetFaceHint = TEXT("F");
Result = TrainingSubsystem->SubmitActiveRecognitionFrame(Frame);
}
TestEqual(TEXT("The third preview should move the mock into commit-ready guidance."), Result.Guidance, TEXT("commit-ready"));
TestTrue(
TEXT("The preview must expose a structurally valid ordered face observation."),
Result.ObservedFace.IsStructurallyValid()
);
TestEqual(TEXT("The ordered face observation must resolve the target face."), Result.ObservedFace.FaceId, TEXT("F"));
TestEqual(TEXT("The ordered face observation must contain nine stickers."), Result.ObservedFace.OrderedStickers.Num(), 9);
TestTrue(TEXT("The preview observation must report commit readiness."), Result.ObservedFace.bCommitReady);
TestEqual(
TEXT("The preview observation must preserve row-major ordering."),
Result.ObservedFace.OrderingProfile,
TEXT("3x3-row-major")
);
return true;
}
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
FHyperTwistQbrPhase6RBCommitObservationTest,
"HyperTwist.Permissive.Qbr.Phase6R.B.CommitObservation",
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)
bool FHyperTwistQbrPhase6RBCommitObservationTest::RunTest(const FString& Parameters)
{
UGameInstance* GameInstance = NewObject<UGameInstance>(GetTransientPackage());
TestNotNull(TEXT("Game instance outer must exist for subsystem construction."), GameInstance);
if (GameInstance == nullptr)
{
return false;
}
UHyperTwistTrainingSubsystem* TrainingSubsystem = NewObject<UHyperTwistTrainingSubsystem>(GameInstance);
TestNotNull(TEXT("Training subsystem must be constructed."), TrainingSubsystem);
if (TrainingSubsystem == nullptr)
{
return false;
}
HyperTwistQbrPhase6RBTestInternal::ForceMockRecognitionClient(TrainingSubsystem);
const FHyperTwistTrainingRunState RunState = TrainingSubsystem->StartTrainingRunFromDeck(
HyperTwistQbrPhase6RBTestInternal::MakeRecognitionDeck(),
TEXT("phase6r-b-user"),
TEXT("phase6r-b-commit-session"),
EHyperTwistTrainingDeliveryMode::RecognitionAssisted
);
TestTrue(TEXT("The recognition-assisted run must start successfully."), RunState.IsStructurallyValid());
if (!RunState.IsStructurallyValid())
{
return false;
}
FHyperTwistVisionFrameEnvelope Frame;
Frame.TargetFaceHint = TEXT("F");
TrainingSubsystem->SubmitActiveRecognitionFrame(Frame);
FHyperTwistVisionCommitRequest Request;
Request.TargetFace = TEXT("F");
const FHyperTwistVisionCommitResult Result =
TrainingSubsystem->CommitActiveRecognitionObservation(Request);
TestEqual(TEXT("The commit result must keep the normalized face commit kind."), Result.CommitKind, TEXT("face"));
TestEqual(TEXT("The commit result must report the committed face."), Result.CommittedUnit, TEXT("F"));
TestTrue(
TEXT("The commit result must expose a structurally valid ordered face observation."),
Result.ObservedFace.IsStructurallyValid()
);
TestTrue(TEXT("The commit face observation must be commit-ready."), Result.ObservedFace.bCommitReady);
TestTrue(TEXT("The mock commit path should not report warnings for an open session."), Result.Warnings.IsEmpty());
return true;
}
#endif

View file

@ -94,7 +94,7 @@ Status update on `2026-05-20`:
- the current canonical repo-row portfolio count is `75`
- all `75` current portfolio rows now have explicit root-tracker coverage
- the current implemented-row count is `25`
- the current implemented-row count is `26`
- the four later restrictive clean-room rows now implemented after the original `2026-05-13` truth
block are:
- `cubing/alg.js`
@ -103,30 +103,36 @@ Status update on `2026-05-20`:
- `kash/cubedesk`
- the fifth additional implemented row is the same-day bounded permissive partial row:
- `HactarCE/Hyperspeedcube`
- the sixth additional implemented row is the same-day bounded permissive partial row:
- `kkoomen/qbr`
- the earlier first-party packet block is now confirmed landed in current code through:
- `d4f4ad3` `Add primary coach orchestration entry lane`
- `1860f14` `Add provider-backed recognition sidecar client`
- `2473665` `Overlay imported training catalog packs and finite bundles`
- the bounded permissive `Phase 6R-A` `HactarCE/Hyperspeedcube` puzzle-catalog contract widening
packet is now landed in current code
- `HactarCE/Hyperspeedcube` remains partially incorporated; the current next bounded move is a
source-backed `Phase 6R-B` `kkoomen/qbr` preparation/control pass, not a new restrictive packet
by default
- `HactarCE/Hyperspeedcube` remains partially incorporated
- the bounded permissive `Phase 6R-B` `kkoomen/qbr` classic-cube recognition calibration and
ordered face-observation packet is now landed in current code
- `kkoomen/qbr` remains partially incorporated; the current next bounded move is a source-backed
`Phase 6R-C` `vivaansinghvi07/rubix-cube-solver` preparation/control pass, not a new
restrictive packet by default
- use the repo-row README census, the portfolio standing refresh backfill, and the `2R-A`
ownership contract for the current queue after that correction
This file now also preserves the current truth that future models must not lose:
- current curated HyperTwist shallow-eval set: `75` repos
- currently verified live/implemented in checked `UnrealHyperTwist` surfaces: `25`
- permissive live lanes: `14`
- currently verified live/implemented in checked `UnrealHyperTwist` surfaces: `26`
- permissive live lanes: `15`
- boundary-sensitive live lanes: `6`
- restrictive live lanes: `5`
The fourteen permissive live lanes are:
The fifteen permissive live lanes are:
- `Aarav2709/KubeTimr`
- `HactarCE/Hyperspeedcube`
- `kkoomen/qbr`
- `apache/echarts`
- `abunickabhi/5style-Trainer`
- `google/model-viewer`
@ -170,7 +176,7 @@ Interpretation rule:
Reset rule:
- preserve the twenty landed/live lanes
- preserve the twenty-six landed/live lanes
- do not treat the remaining non-live rows as already absorbed
- route all non-live rows only through the closed `Phase 1R` retained-set contract and the relevant `0R-*` packet
@ -209,7 +215,8 @@ Current practical interpretation:
- the landed `PostHog/posthog` boundary-sensitive widening packet now lives in `docs/HYPERTWIST_PHASE_4R_PACKET_4R_D_POSTHOG_CONTROL_PLANE_IMPLEMENTATION_2026-05-13.md`
- the landed `screenpipe/screenpipe` boundary-sensitive widening packet now lives in `docs/HYPERTWIST_PHASE_4R_PACKET_4R_E_SCREENPIPE_CAPTURE_HISTORY_IMPLEMENTATION_2026-05-13.md`
- the landed `remotion-dev/remotion` boundary-sensitive widening packet now lives in `docs/HYPERTWIST_PHASE_4R_PACKET_4R_F_REMOTION_MEDIA_EXPORT_IMPLEMENTATION_2026-05-13.md`
- the next bounded move is a source-backed `Phase 6R-B` `kkoomen/qbr` preparation/control pass
- the next bounded move is a source-backed `Phase 6R-C`
`vivaansinghvi07/rubix-cube-solver` preparation/control pass
Companion docs:
@ -657,8 +664,8 @@ Current licensing judgment:
- explicit `MIT`
- repo code is usable for HyperTwist under the checked permissive license text
- not a clean-room case
- treat as the retained recognition-substrate donor queued behind the current `Hyperspeedcube`
runtime-anchor packet
- treat as the retained recognition-substrate donor whose first narrower bounded slice is now
landed in current code
Source basis:
@ -675,6 +682,9 @@ Important distinction:
- calibration flow
- color-detection bookkeeping
- multilingual solve guidance shell
- the first landed HyperTwist slice is intentionally narrower than that broader donor value:
- classic-cube recognition calibration contract
- ordered face-observation contract
- permissive posture alone does not let it outrank the already accepted route sequencing or absorb
the whole product recognition shell prematurely
- the checked mirror also contains a bundled font asset:
@ -687,8 +697,15 @@ Approved working posture:
- HyperTwist may use the codebase directly under the checked `MIT` posture
- preserve the upstream `MIT` license text and copyright notice:
- `Copyright (c) 2016 Kim Koomen`
- keep the row queued as the recognition-substrate candidate after `Phase 6R-A`, not as a blanket
promotion to current implementation
- keep the row as a partially incorporated recognition-substrate donor, not as a blanket promotion
to full recognition-shell ownership
- the landed packet is bounded to:
- classic-cube recognition calibration contract
- ordered face-observation contract
- keep the following families deferred to later queue decisions:
- webcam UI shell
- bundled-font redistribution and multilingual solve shell
- multi-face reconstruction / correction / explanation
- if later implementation copies bundled non-code assets, capture and preserve any asset-specific
license or replace the asset with a clearly redistributable alternative
@ -1241,9 +1258,10 @@ Approved working posture:
permission to transplant the whole Rust application shell
- do not let this row absorb non-Euclidean topology ownership that remains queued for
`roice3/MagicTile`
- after the landed puzzle-catalog slice, the next queue head should move to a source-backed
`Phase 6R-B` `kkoomen/qbr` preparation/control pass rather than pretending the entire
`Hyperspeedcube` family is already closed
- after the landed puzzle-catalog slice and the landed bounded `qbr` calibration slice, the next
queue head should move to a source-backed `Phase 6R-C`
`vivaansinghvi07/rubix-cube-solver` preparation/control pass rather than pretending the entire
retained recognition family is already closed
### `coqui-ai/TTS`

View file

@ -0,0 +1,139 @@
# HyperTwist Phase 6R-B qbr calibrated face observation implementation packet
Created on `2026-05-20`
## Status
- first-party HyperTwist packet
- bounded permissive `Phase 6R-B` implementation slice
## Purpose
This packet lands the first narrower bounded slice from the retained `kkoomen/qbr`
recognition-substrate row.
The landed slice is:
- first-party classic-cube recognition calibration plus ordered face-observation contract
It is not:
- a full `qbr` row transplant
- a browser/webcam UI shell packet
- a multilingual solve-shell packet
- a bundled-font redistribution packet
- a multi-face reconstruction or correction packet
- a `rubix-cube-solver` packet
## Current authority basis
This implementation packet stands on:
- `docs/HYPERTWIST_PHASE_0R_PACKET_0R_A_EVALUATION_2026-05-12.md`
- `docs/HYPERTWIST_PHASE_2R_PACKET_2R_A_OWNERSHIP_AND_ACCEPTANCE_CONTRACT_2026-05-13.md`
- `docs/REPO_LICENSE_TRACKING.md`
- `docs/arch/HYPERTWIST_PHASE6R_B_QBR_RECOGNITION_CALIBRATION_PREPARATION_PACKET_2026-05-20.md`
The retained owner remains:
- `kkoomen/qbr`
The granted family remains bounded to:
- recognition calibration flow
- ordered face observation
- color-detection bookkeeping
- bounded capture-session guidance
This packet lands only the first narrower contract slice in that granted set.
## Landed scope
The current code now owns a retained classic-cube recognition contract through:
- retained recognition contract types for:
- calibration swatches
- calibration profiles
- observed stickers
- observed face envelopes
- recognition session config defaults for:
- classic-cube calibration profile id
- calibration-profile definition
- classic ordered face-observation profile
- `UHyperTwistContractLibrary` sample calibration-profile and observed-face routing
- `UHyperTwistTrainingSubsystem` classic `cube/3x3x3` recognition-session normalization
- `UHyperTwistHttpVisionClient` capability exposure for:
- calibration profiles
- ordered face observation
- `UHyperTwistMockVisionClient` preview and commit contract responses for ordered face observation
- focused automation coverage in:
- `HyperTwistQbrPhase6RBCalibrationContractTest.cpp`
## Why this is still intentionally bounded
This packet replaces the thinner recognition sample and session heuristics with a richer first-party
calibration and observed-face contract, but it does not widen into the neighboring retained
families.
Still deferred:
- webcam UI shell
- multilingual solve shell
- bundled-font redistribution
- multi-face reconstruction
- correction or solve-explanation flow
- `rubix-cube-solver` companion-lane ownership
## Validation
Build validation:
- `Build.bat UnrealHyperTwistEditor Win64 Development -Project='C:\HyperTwist\UnrealHyperTwist\UnrealHyperTwist.uproject' -WaitMutex -NoHotReloadFromIDE`
Focused automation validation:
- `Automation RunTests HyperTwist.Permissive.Qbr.Phase6R.B`
Regression automation validation:
- `Automation RunTests HyperTwist.Permissive.Hyperspeedcube.Phase6R.A`
- `Automation RunTests HyperTwist.CleanRoom.CubeDesk`
Expected covered tests:
- `CalibrationSessionConfig`
- `PreviewObservation`
- `CommitObservation`
- `CatalogLookup`
- `SampleDefinition`
- `TrainingRunDefinition`
- existing `CubeDesk` clean-room regression suite
## Queue effect
This packet consumes the current `Phase 6R-B` implementation slice.
`kkoomen/qbr` remains only partially incorporated:
- landed now:
- classic-cube recognition calibration contract
- ordered face-observation contract
- still deferred:
- webcam UI shell
- bundled-font redistribution and multilingual solve shell
- multi-face reconstruction / correction / explanation
The next clean move is not another immediate `qbr` widening by default.
The next queue head should be:
- a source-backed `Phase 6R-C` `vivaansinghvi07/rubix-cube-solver` preparation/control pass
Keep the legal sequencing guards visible there:
- `kkoomen/qbr`
- do not copy or redistribute `src/assets/arial-unicode-ms.ttf` without separate confirmation or
replacement in any future widening that would ship that asset
- `vivaansinghvi07/rubix-cube-solver`
- do not copy or redistribute `frontend/lib/twistysim.min.js` without preserving or replacing
its upstream provenance/license

View file

@ -0,0 +1,189 @@
# HyperTwist Phase 6R-B qbr recognition calibration preparation packet
Created on `2026-05-20`
## Status
- historical same-day preparation authority
- bounded post-Phase-`6R-A` preparation slice
- the first bounded implementation slice now lands separately under:
- `docs/arch/HYPERTWIST_PHASE6R_B_QBR_CALIBRATED_FACE_OBSERVATION_IMPLEMENTATION_PACKET_2026-05-20.md`
## Purpose
This packet freezes the next widening order after the landed `Phase 6R-A`
`HactarCE/Hyperspeedcube` puzzle-catalog contract.
The open task is:
- define the first bounded source-backed widening packet for `kkoomen/qbr` as the retained
`Phase 6R-B` recognition-calibration nucleus
It is not:
- a full `qbr` row transplant
- a `rubix-cube-solver` reconstruction packet
- a `MagicTile` topology packet
- a multi-face reconstruction or correction packet
- a solve-explanation or multilingual-shell packet
- a direct redistribution packet for the bundled `arial-unicode-ms.ttf` asset
## Current authority basis
This preparation packet stands on already-closed authority:
- `docs/HYPERTWIST_PHASE_0R_PACKET_0R_A_EVALUATION_2026-05-12.md`
- `docs/HYPERTWIST_PHASE_2R_PACKET_2R_A_OWNERSHIP_AND_ACCEPTANCE_CONTRACT_2026-05-13.md`
- `docs/REPO_LICENSE_TRACKING.md`
- `docs/arch/HYPERTWIST_PHASE6R_A_HYPERSPEEDCUBE_PUZZLE_CATALOG_IMPLEMENTATION_PACKET_2026-05-20.md`
The key accepted routing facts are:
- `kkoomen/qbr` is the retained recognition-substrate donor immediately after the landed `6R-A`
slice
- earliest widening route is `Phase 6R / Packet 6R-B`
- the retained donor value there is:
- classic-cube recognition calibration flow
- ordered face-observation capture
- color-detection bookkeeping
- bounded capture-session guidance
- ownership denied there is:
- do not let the repo absorb the whole recognition shell
- do not widen into multi-face reconstruction, correction, or solve explanation
- do not widen into browser UI shell or multilingual packaging
- do not copy or redistribute the bundled `arial-unicode-ms.ttf` asset without separate
confirmation or replacement
- do not let the row absorb the queued `rubix-cube-solver` companion lane
## Why this is now the next packet
The earlier `Phase 6R-A` queue head is already landed:
- retained hyper puzzle catalog contract
- runtime family/notation resolution above that catalog seam
That means the live queue advances to:
- `Phase 6R-B` `kkoomen/qbr`
with the adjacent retained rows still ordered behind it:
- `Phase 6R-C` `vivaansinghvi07/rubix-cube-solver`
- `Phase 6R-D` `roice3/MagicTile`
## Required result
The source-backed control pass for this packet is now complete.
The first actual `6R-B` implementation packet should:
- use the retained `0R-A` and `2R-A` authority surfaces plus the inspected `qbr` source basis
- define one bounded retained slice from `qbr`
- keep the slice inside the accepted recognition-substrate ownership
- widen only the first recognition contract family that can stand on its own without dragging in
UI, explanation, or companion-lane scope
- explicitly state which neighboring retained rows stay closed in that packet
## Source-backed retained basis
The queue-head decision is now source-backed rather than README-only.
Inspected retained donor basis:
- `README.md`
- `src/qbr.py`
- `src/colordetection.py`
- `src/video.py`
- `src/config.py`
- `src/helpers.py`
- `src/constants.py`
Inspected first-party receiving basis:
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistRecognition/HyperTwistRecognitionTypes.h`
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistRecognition/HyperTwistVisionClient.h`
- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistRecognition/HyperTwistHttpVisionClient.cpp`
- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistRecognition/HyperTwistMockVisionClient.cpp`
- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSubsystem.cpp`
- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistBootstrap/HyperTwistContractLibrary.cpp`
## Narrowed 6R-B slice decision
The first widening slice is now fixed as:
1. classic-cube recognition calibration plus ordered face-observation contract
not as the broader recognition shell.
That narrowed slice should cover:
- first-party calibration swatches and calibration-profile definition
- classic-cube face observation with:
- ordered stickers
- face id
- observation id
- commit-ready state
- session defaults for calibration profile and observation profile
- client capability exposure and mock/client contract responses
- subsystem normalization for the classic `cube/3x3x3` recognition route
- sample contract outputs and focused automation coverage
## Deferred neighboring families
The first `6R-B` implementation packet must keep these capability families closed:
- webcam UI shell
- multilingual solve shell
- bundled-font redistribution
- multi-face reconstruction
- correction or solve-explanation flow
- downstream solver-or-companion ownership that belongs with `rubix-cube-solver`
- broader provider-backed recognition productionization beyond the retained contract seam
Why this slice is first:
- `qbr` exposes the strongest narrow retained seam at calibration and ordered face observation
- current first-party recognition code already has session, frame, preview, and commit envelopes,
but it still lacks a richer owned contract for calibration profiles and observed-face structure
- multi-face reconstruction and correction would prematurely absorb the next queued companion row
## Out of scope for the first 6R-B packet
- full webcam/browser UI transplant
- multilingual solve shell and bundled font asset redistribution
- multi-face solve-state reconstruction
- correction or explanation ownership
- `rubix-cube-solver` companion-lane widening
- `MagicTile` or broader topology widening
## Queue-adjacent legal sequencing guards
Do not omit the already-recorded legal caveats when the neighboring retained rows later come up:
- `Phase 6R-B` `kkoomen/qbr`
- confirm or replace the bundled `src/assets/arial-unicode-ms.ttf` before direct redistribution
if any packet copies or ships that asset
- `Phase 6R-C` `vivaansinghvi07/rubix-cube-solver`
- preserve or replace the bundled `frontend/lib/twistysim.min.js` with its upstream
provenance/license intact before redistribution if any packet copies or ships that dependency
## Acceptance criteria
- the packet records why the live queue now advances from landed `6R-A` to `6R-B`
- the packet promotes `qbr` as the current queue head without widening the neighboring retained
rows prematurely
- the packet records that the first `6R-B` widening slice is classic-cube recognition calibration
plus ordered face observation only
- the packet states exact out-of-scope families for the first `6R-B` pass
- the packet keeps the `qbr` font and `rubix-cube-solver` bundled dependency caveats visible in
later queue sequencing
## Validation checklist
1. confirm the landed `Phase 6R-A` packet is now the consumed prior queue head
2. confirm the retained recognition-substrate seam in `qbr` narrows cleanly to calibration and
ordered face observation
3. confirm the next packet is framed as bounded source-backed widening rather than README-only
routing
That is the packet.

View file

@ -3,7 +3,7 @@
Status update on `2026-05-20`:
- the canonical HyperTwist repo-row portfolio is now treated as `75` rows, not `71`
- currently implemented rows are now `25`, not `20`
- currently implemented rows are now `26`, not `20`
- four of the additional current implemented rows are the later-landed restrictive clean-room lanes:
- `cubing/alg.js`
- `cubing/twisty.js`
@ -11,6 +11,8 @@ Status update on `2026-05-20`:
- `kash/cubedesk`
- the fifth additional current implemented row is the same-day bounded permissive partial row:
- `HactarCE/Hyperspeedcube`
- the sixth additional current implemented row is the same-day bounded permissive partial row:
- `kkoomen/qbr`
- the current next bounded move is **not** another restrictive packet by default
- the earlier first-party packet block that was still being treated as next is now confirmed landed:
- `d4f4ad3` `Add primary coach orchestration entry lane`
@ -21,8 +23,14 @@ Status update on `2026-05-20`:
packet is now landed in current code
- `HactarCE/Hyperspeedcube` remains partially incorporated; DSL, notation, replay verification,
and stats-shape families stay deferred
- the current next bounded move is a source-backed `Phase 6R-B` `kkoomen/qbr` preparation/control
pass
- the generic source-backed `Phase 6R-B` `kkoomen/qbr` control pass is now consumed
- the bounded permissive `Phase 6R-B` `kkoomen/qbr` classic-cube recognition calibration and
ordered face-observation packet is now landed in current code
- `kkoomen/qbr` remains partially incorporated; webcam UI shell, bundled-font redistribution,
multilingual solve shell, and multi-face reconstruction/correction/explanation families stay
deferred
- the current next bounded move is a source-backed `Phase 6R-C`
`vivaansinghvi07/rubix-cube-solver` preparation/control pass
- the repo-row implementation queue is now live from that `Phase 6R-A` entry point rather than
waiting on another first-party packet
@ -50,8 +58,8 @@ Donor-strength rule:
- route difficulty changes how retained value may enter the product, not whether it may win technically
- current shallow-eval set: `75` repos
- currently verified live/implemented in checked Unreal surfaces: `25`
- permissive live lanes: `14`
- currently verified live/implemented in checked Unreal surfaces: `26`
- permissive live lanes: `15`
- boundary-sensitive live lanes: `6`
- restrictive live lanes: `5`
- the restrictive landed lanes are:
@ -61,7 +69,7 @@ Donor-strength rule:
- `HactarCE/2x2x2x2-Scrambler`
- `kash/cubedesk`
- each restrictive landed lane is to be treated as properly clean-roomed and implemented afterward
- `Phase 0R` is now closed for the remaining `50` non-live rows
- `Phase 0R` is now closed for the remaining `49` non-live rows
- `Phase 1R` is now closed as the retained-set contract and handoff overhaul
- `Phase 2R` is now closed as the retained-set ownership and acceptance packet sequence
- `Phase 3R-A` is now closed as the landed `Aarav2709/KubeTimr` timer subsystem widening packet
@ -81,18 +89,19 @@ Current routing truth:
- retained rows total: `68`
- discarded from the active retained set: `3`
- active non-live implementation-board rows: `38`
- active non-live implementation-board rows: `37`
- retained benchmark, oracle, or clean-room-later rows outside the active implementation board: `9`
The next bounded move is a source-backed `Phase 6R-B` `kkoomen/qbr` preparation/control pass.
The next bounded move is a source-backed `Phase 6R-C`
`vivaansinghvi07/rubix-cube-solver` preparation/control pass.
Queue interpretation after that packet:
- then continue with the retained repo-row queue
- highest current repo-row queue pressure sits in:
- `kkoomen/qbr`
- `vivaansinghvi07/rubix-cube-solver`
- `roice3/MagicTile`
- the bounded speech-input / voice sidecar set
- `HactarCE/Hyperspeedcube` remains a partially landed row rather than a closed row:
- landed:
- puzzle catalog contract
@ -101,14 +110,21 @@ Queue interpretation after that packet:
- notation / serialization
- replay verification
- stats-shape
- after the `Phase 6R-B` control pass, keep the adjacent legal sequencing guards visible:
- `kkoomen/qbr` remains a partially landed row rather than a closed row:
- landed:
- classic-cube recognition calibration contract
- ordered face-observation contract
- still deferred:
- webcam UI shell
- bundled-font redistribution and multilingual solve shell
- multi-face reconstruction / correction / explanation
- after the `Phase 6R-B` implementation packet, keep the adjacent legal sequencing guards visible:
- `kkoomen/qbr`
- do not copy or redistribute `src/assets/arial-unicode-ms.ttf` without separate confirmation
or replacement
- do not copy or redistribute `src/assets/arial-unicode-ms.ttf` without separate
confirmation or replacement in any future widening that would ship that asset
- `vivaansinghvi07/rubix-cube-solver`
- do not copy or redistribute `frontend/lib/twistysim.min.js` without preserving or replacing
its upstream provenance/license
- the bounded speech-input / voice sidecar set
- keep the optional `Phase 3R-G` browser comparison lane deferred unless the landed primary browser
spatial stack exposes a real gap