Implement Phase 6R-B calibrated face observation contract
This commit is contained in:
parent
30b553b792
commit
47670a764a
10 changed files with 980 additions and 33 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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`
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue