Implement Phase 6R-S correction resolution closure
This commit is contained in:
parent
dafaf397cc
commit
4ea9e9683d
11 changed files with 1106 additions and 39 deletions
|
|
@ -559,6 +559,22 @@ namespace HyperTwistContractLibraryInternal
|
|||
return Profile;
|
||||
}
|
||||
|
||||
bool HasAppliedResolutionForFace(
|
||||
const TArray<FHyperTwistVisionCorrectionResolution>& ResolutionLedger,
|
||||
const FHyperTwistVisionCommittedFaceState& FaceState
|
||||
)
|
||||
{
|
||||
const FString NormalizedFaceId = NormalizeBrowserFaceHint(FaceState.FaceId);
|
||||
return ResolutionLedger.ContainsByPredicate(
|
||||
[&NormalizedFaceId, &FaceState](const FHyperTwistVisionCorrectionResolution& Resolution)
|
||||
{
|
||||
return NormalizeBrowserFaceHint(Resolution.FaceId) == NormalizedFaceId
|
||||
&& Resolution.ObservationId == FaceState.LatestObservationId
|
||||
&& Resolution.RevisionCount == FaceState.RevisionCount;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void ResolveMockClassicFaceSwatch(
|
||||
const FString& FaceId,
|
||||
FString& OutColorId,
|
||||
|
|
@ -829,7 +845,8 @@ namespace HyperTwistContractLibraryInternal
|
|||
const FHyperTwistVisionSessionConfig& SessionConfig,
|
||||
const FHyperTwistVisionReconstructionSession& ReconstructionSession,
|
||||
const FHyperTwistVisionFaceObservation& ObservedFace,
|
||||
const TArray<FString>& Warnings
|
||||
const TArray<FString>& Warnings,
|
||||
const TArray<FHyperTwistVisionCorrectionResolution>& ResolutionLedger
|
||||
)
|
||||
{
|
||||
static constexpr float LowConfidenceThreshold = 0.85f;
|
||||
|
|
@ -848,6 +865,12 @@ namespace HyperTwistContractLibraryInternal
|
|||
CorrectionState.MissingFaceCount = ReconstructionSession.IsStructurallyValid()
|
||||
? ReconstructionSession.MissingFaces.Num()
|
||||
: 6;
|
||||
CorrectionState.ResolutionLedger = ResolutionLedger;
|
||||
CorrectionState.ResolvedCorrectionCount = ResolutionLedger.Num();
|
||||
if (ResolutionLedger.Num() > 0)
|
||||
{
|
||||
CorrectionState.LastResolution = ResolutionLedger.Last();
|
||||
}
|
||||
CorrectionState.bManualCubeEditVisible =
|
||||
CorrectionProfile.bSupportsManualCubeEdit && ReconstructionSession.bHasCompleteClassicCubeNet;
|
||||
CorrectionState.bStageRestartVisible =
|
||||
|
|
@ -861,6 +884,10 @@ namespace HyperTwistContractLibraryInternal
|
|||
{
|
||||
const FString FaceId = NormalizeBrowserFaceHint(FaceState.FaceId);
|
||||
const bool bHasCompleteNet = ReconstructionSession.bHasCompleteClassicCubeNet;
|
||||
if (HasAppliedResolutionForFace(ResolutionLedger, FaceState))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FaceState.bHasConflicts)
|
||||
{
|
||||
|
|
@ -1494,7 +1521,8 @@ FHyperTwistVisionCommitResult UHyperTwistContractLibrary::MakeMockVisionCommitRe
|
|||
SessionConfig,
|
||||
Result.ReconstructionSession,
|
||||
Result.ObservedFace,
|
||||
Result.Warnings
|
||||
Result.Warnings,
|
||||
TArray<FHyperTwistVisionCorrectionResolution>()
|
||||
);
|
||||
Result.SolveExplanationState = HyperTwistContractLibraryInternal::MakeClassicCubeSolveExplanationState(
|
||||
SessionConfig,
|
||||
|
|
|
|||
|
|
@ -2669,6 +2669,140 @@ namespace HyperTwistTrainingSubsystemInternal
|
|||
return Profile;
|
||||
}
|
||||
|
||||
bool IsCorrectionResolutionCommitKind(const FString& CommitKind)
|
||||
{
|
||||
return CommitKind.Equals(TEXT("correction-resolution"), ESearchCase::IgnoreCase)
|
||||
|| CommitKind.Equals(TEXT("resolve-correction"), ESearchCase::IgnoreCase);
|
||||
}
|
||||
|
||||
const FHyperTwistVisionCorrectionTarget* FindCorrectionTarget(
|
||||
const FHyperTwistVisionCorrectionState& CorrectionState,
|
||||
const FString& FaceId
|
||||
)
|
||||
{
|
||||
const FString NormalizedFaceId = NormalizeRecognitionFaceId(FaceId);
|
||||
return CorrectionState.PendingTargets.FindByPredicate(
|
||||
[&NormalizedFaceId](const FHyperTwistVisionCorrectionTarget& Candidate)
|
||||
{
|
||||
return NormalizeRecognitionFaceId(Candidate.FaceId) == NormalizedFaceId;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
FHyperTwistVisionFaceObservation BuildObservationFromCommittedFaceState(
|
||||
const FHyperTwistVisionCommittedFaceState& FaceState
|
||||
)
|
||||
{
|
||||
FHyperTwistVisionFaceObservation Observation;
|
||||
Observation.ObservationId = FaceState.LatestObservationId;
|
||||
Observation.FaceId = NormalizeRecognitionFaceId(FaceState.FaceId);
|
||||
Observation.OrderingProfile = FaceState.OrderingProfile;
|
||||
Observation.CandidateContourCount = FaceState.LatestOrderedStickers.Num();
|
||||
Observation.AcceptedContourCount = FaceState.LatestOrderedStickers.Num();
|
||||
Observation.bFoundStableThreeByThreeGrid = FaceState.LatestOrderedStickers.Num() == 9;
|
||||
Observation.bOrderingStable = FaceState.LatestOrderedStickers.Num() == 9;
|
||||
Observation.bCommitReady = true;
|
||||
Observation.OrderedStickers = FaceState.LatestOrderedStickers;
|
||||
return Observation;
|
||||
}
|
||||
|
||||
bool HasAppliedResolutionForFace(
|
||||
const TArray<FHyperTwistVisionCorrectionResolution>& ResolutionLedger,
|
||||
const FHyperTwistVisionCommittedFaceState& FaceState
|
||||
)
|
||||
{
|
||||
const FString NormalizedFaceId = NormalizeRecognitionFaceId(FaceState.FaceId);
|
||||
return ResolutionLedger.ContainsByPredicate(
|
||||
[&NormalizedFaceId, &FaceState](const FHyperTwistVisionCorrectionResolution& Resolution)
|
||||
{
|
||||
return NormalizeRecognitionFaceId(Resolution.FaceId) == NormalizedFaceId
|
||||
&& Resolution.ObservationId == FaceState.LatestObservationId
|
||||
&& Resolution.RevisionCount == FaceState.RevisionCount;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void UpsertCorrectionResolution(
|
||||
TArray<FHyperTwistVisionCorrectionResolution>& ResolutionLedger,
|
||||
const FHyperTwistVisionCorrectionResolution& Candidate,
|
||||
bool& bAddedNewResolution
|
||||
)
|
||||
{
|
||||
bAddedNewResolution = false;
|
||||
|
||||
const int32 ExistingIndex = ResolutionLedger.IndexOfByPredicate(
|
||||
[&Candidate](const FHyperTwistVisionCorrectionResolution& Existing)
|
||||
{
|
||||
return NormalizeRecognitionFaceId(Existing.FaceId)
|
||||
== NormalizeRecognitionFaceId(Candidate.FaceId)
|
||||
&& Existing.ObservationId == Candidate.ObservationId
|
||||
&& Existing.RevisionCount == Candidate.RevisionCount;
|
||||
}
|
||||
);
|
||||
if (ExistingIndex == INDEX_NONE)
|
||||
{
|
||||
ResolutionLedger.Add(Candidate);
|
||||
bAddedNewResolution = true;
|
||||
return;
|
||||
}
|
||||
|
||||
ResolutionLedger[ExistingIndex] = Candidate;
|
||||
}
|
||||
|
||||
FHyperTwistVisionCorrectionResolution BuildCorrectionResolution(
|
||||
const FHyperTwistVisionCommitRequest& Request,
|
||||
const FHyperTwistVisionCorrectionState& CorrectionState,
|
||||
const FHyperTwistVisionCommittedFaceState& FaceState
|
||||
)
|
||||
{
|
||||
const FString FaceId = NormalizeRecognitionFaceId(FaceState.FaceId);
|
||||
const FHyperTwistVisionCorrectionTarget* Target = FindCorrectionTarget(CorrectionState, FaceId);
|
||||
|
||||
FHyperTwistVisionCorrectionResolution Resolution;
|
||||
Resolution.FaceId = FaceId;
|
||||
Resolution.ObservationId = FaceState.LatestObservationId;
|
||||
Resolution.RevisionCount = FaceState.RevisionCount;
|
||||
Resolution.RequestedActionId = !Request.RequestedActionId.IsEmpty()
|
||||
? Request.RequestedActionId
|
||||
: (Target != nullptr && !Target->RecommendedActionId.IsEmpty()
|
||||
? Target->RecommendedActionId
|
||||
: TEXT("apply-manual-corrections"));
|
||||
Resolution.ResolutionKind = !Request.ResolutionKind.IsEmpty()
|
||||
? Request.ResolutionKind
|
||||
: (FaceState.RevisionCount > 0
|
||||
? TEXT("manual-review-accepted")
|
||||
: TEXT("correction-review-accepted"));
|
||||
Resolution.ResolutionId = FString::Printf(
|
||||
TEXT("resolution-%s-%d-%s"),
|
||||
*FaceId,
|
||||
FaceState.RevisionCount,
|
||||
*Resolution.ResolutionKind
|
||||
);
|
||||
|
||||
for (const FHyperTwistVisionCorrectionContradiction& Contradiction : CorrectionState.Contradictions)
|
||||
{
|
||||
if (NormalizeRecognitionFaceId(Contradiction.FaceId) == FaceId)
|
||||
{
|
||||
Resolution.ResolvedContradictionIds.Add(Contradiction.ContradictionId);
|
||||
}
|
||||
}
|
||||
|
||||
Resolution.StatusLine = FString::Printf(
|
||||
TEXT("Accepted face %s after manual correction review."),
|
||||
*FaceId
|
||||
);
|
||||
Resolution.DetailLine = Resolution.ResolvedContradictionIds.Num() > 0
|
||||
? FString::Printf(
|
||||
TEXT("The current observation on face %s is now treated as reviewed in the bounded correction shell."),
|
||||
*FaceId
|
||||
)
|
||||
: FString::Printf(
|
||||
TEXT("The current bounded reading on face %s is accepted after manual review."),
|
||||
*FaceId
|
||||
);
|
||||
return Resolution;
|
||||
}
|
||||
|
||||
FHyperTwistVisionShellState BuildClassicCubeWebcamShellState(
|
||||
const FHyperTwistVisionSessionConfig& SessionConfig,
|
||||
const FHyperTwistVisionReconstructionSession& ReconstructionSession,
|
||||
|
|
@ -2780,7 +2914,8 @@ namespace HyperTwistTrainingSubsystemInternal
|
|||
const FHyperTwistVisionSessionConfig& SessionConfig,
|
||||
const FHyperTwistVisionReconstructionSession& ReconstructionSession,
|
||||
const FHyperTwistVisionFaceObservation& ObservedFace,
|
||||
const TArray<FString>& Warnings
|
||||
const TArray<FString>& Warnings,
|
||||
const TArray<FHyperTwistVisionCorrectionResolution>& ResolutionLedger
|
||||
)
|
||||
{
|
||||
static constexpr float LowConfidenceThreshold = 0.85f;
|
||||
|
|
@ -2799,6 +2934,12 @@ namespace HyperTwistTrainingSubsystemInternal
|
|||
CorrectionState.MissingFaceCount = ReconstructionSession.IsStructurallyValid()
|
||||
? ReconstructionSession.MissingFaces.Num()
|
||||
: 6;
|
||||
CorrectionState.ResolutionLedger = ResolutionLedger;
|
||||
CorrectionState.ResolvedCorrectionCount = ResolutionLedger.Num();
|
||||
if (ResolutionLedger.Num() > 0)
|
||||
{
|
||||
CorrectionState.LastResolution = ResolutionLedger.Last();
|
||||
}
|
||||
CorrectionState.bManualCubeEditVisible =
|
||||
CorrectionProfile.bSupportsManualCubeEdit && ReconstructionSession.bHasCompleteClassicCubeNet;
|
||||
CorrectionState.bStageRestartVisible =
|
||||
|
|
@ -2812,6 +2953,10 @@ namespace HyperTwistTrainingSubsystemInternal
|
|||
{
|
||||
const FString FaceId = NormalizeRecognitionFaceId(FaceState.FaceId);
|
||||
const bool bHasCompleteNet = ReconstructionSession.bHasCompleteClassicCubeNet;
|
||||
if (HasAppliedResolutionForFace(ResolutionLedger, FaceState))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FaceState.bHasConflicts)
|
||||
{
|
||||
|
|
@ -4202,13 +4347,14 @@ FHyperTwistTrainingCoachPanelState UHyperTwistTrainingSubsystem::GetActiveCoachP
|
|||
? TEXT("not-ready")
|
||||
: *ActiveRecognitionSessionState.ServiceHealth.LastError);
|
||||
PanelState.RecognitionStatusLine = FString::Printf(
|
||||
TEXT("Recognition: %s | Service: %s | Session: %s | Frames %d | Commits %d | Corrections %d | Finalizations %d"),
|
||||
TEXT("Recognition: %s | Service: %s | Session: %s | Frames %d | Commits %d | Corrections %d | Resolved %d | Finalizations %d"),
|
||||
*RecognitionProviderLabel,
|
||||
*RecognitionTransportState,
|
||||
ActiveRecognitionSessionState.bSessionOpen ? TEXT("open") : TEXT("closed"),
|
||||
ActiveRecognitionSessionState.SubmittedFrameCount,
|
||||
ActiveRecognitionSessionState.CommittedObservationCount,
|
||||
ActiveRecognitionSessionState.CorrectionEventCount,
|
||||
ActiveRecognitionSessionState.ResolvedCorrectionCount,
|
||||
ActiveRecognitionSessionState.FinalizedSessionCount
|
||||
);
|
||||
const bool bCoachPrefersRecognitionReview =
|
||||
|
|
@ -7476,6 +7622,214 @@ FHyperTwistVisionCommitResult UHyperTwistTrainingSubsystem::CommitActiveRecognit
|
|||
NormalizedRequest.CommitKind = TEXT("face");
|
||||
}
|
||||
|
||||
const bool bIsQbrClassicRoute =
|
||||
HyperTwistTrainingSubsystemInternal::IsQbrClassicCubeRoute(ActiveRecognitionSessionState.SessionConfig);
|
||||
if (bIsQbrClassicRoute
|
||||
&& HyperTwistTrainingSubsystemInternal::IsCorrectionResolutionCommitKind(NormalizedRequest.CommitKind))
|
||||
{
|
||||
Result.SessionId = NormalizedRequest.SessionId;
|
||||
Result.CommitKind = NormalizedRequest.CommitKind;
|
||||
Result.Snapshot.State.SourceSessionId = NormalizedRequest.SessionId;
|
||||
Result.ReconstructionSession = ActiveRecognitionSessionState.ActiveReconstructionSession;
|
||||
Result.MissingUnits = Result.ReconstructionSession.MissingFaces;
|
||||
Result.Confidence = Result.ReconstructionSession.ConfidenceRollup;
|
||||
|
||||
const FHyperTwistVisionFaceObservation ReferenceObservation =
|
||||
ActiveRecognitionSessionState.LastCommitResult.ObservedFace.IsStructurallyValid()
|
||||
? ActiveRecognitionSessionState.LastCommitResult.ObservedFace
|
||||
: ActiveRecognitionSessionState.LastPreviewResult.ObservedFace;
|
||||
Result.CorrectionState =
|
||||
HyperTwistTrainingSubsystemInternal::BuildClassicCubeCorrectionState(
|
||||
ActiveRecognitionSessionState.SessionConfig,
|
||||
Result.ReconstructionSession,
|
||||
ReferenceObservation,
|
||||
Result.Warnings,
|
||||
ActiveRecognitionSessionState.CorrectionResolutionLedger
|
||||
);
|
||||
|
||||
const FString RequestedFaceId = !NormalizedRequest.TargetFace.IsEmpty()
|
||||
? HyperTwistTrainingSubsystemInternal::NormalizeRecognitionFaceId(NormalizedRequest.TargetFace)
|
||||
: Result.CorrectionState.ActiveTargetFaceId;
|
||||
const FHyperTwistVisionCorrectionTarget* RequestedTarget =
|
||||
HyperTwistTrainingSubsystemInternal::FindCorrectionTarget(Result.CorrectionState, RequestedFaceId);
|
||||
const FHyperTwistVisionCommittedFaceState* RequestedFaceState =
|
||||
HyperTwistTrainingSubsystemInternal::FindCommittedFaceState(Result.ReconstructionSession, RequestedFaceId);
|
||||
bool bAppliedResolution = false;
|
||||
bool bAddedNewResolution = false;
|
||||
|
||||
if (!Result.ReconstructionSession.IsStructurallyValid())
|
||||
{
|
||||
Result.Warnings.Add(TEXT("correction-resolution-unavailable"));
|
||||
}
|
||||
else if (!Result.ReconstructionSession.bHasCompleteClassicCubeNet)
|
||||
{
|
||||
Result.Warnings.Add(TEXT("correction-resolution-requires-complete-net"));
|
||||
}
|
||||
else if (RequestedFaceId.IsEmpty())
|
||||
{
|
||||
Result.Warnings.Add(TEXT("correction-target-face-required"));
|
||||
}
|
||||
else if (RequestedTarget == nullptr)
|
||||
{
|
||||
Result.Warnings.Add(TEXT("correction-target-unavailable"));
|
||||
}
|
||||
else if (RequestedTarget->RecommendedActionId != TEXT("apply-manual-corrections"))
|
||||
{
|
||||
Result.Warnings.Add(TEXT("correction-target-does-not-support-manual-resolution"));
|
||||
}
|
||||
else if (RequestedFaceState == nullptr)
|
||||
{
|
||||
Result.Warnings.Add(TEXT("correction-face-state-unavailable"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Result.CommittedUnit = RequestedFaceId;
|
||||
Result.ObservedFace =
|
||||
HyperTwistTrainingSubsystemInternal::BuildObservationFromCommittedFaceState(*RequestedFaceState);
|
||||
|
||||
FHyperTwistVisionCorrectionResolution AppliedResolution =
|
||||
HyperTwistTrainingSubsystemInternal::BuildCorrectionResolution(
|
||||
NormalizedRequest,
|
||||
Result.CorrectionState,
|
||||
*RequestedFaceState
|
||||
);
|
||||
HyperTwistTrainingSubsystemInternal::UpsertCorrectionResolution(
|
||||
ActiveRecognitionSessionState.CorrectionResolutionLedger,
|
||||
AppliedResolution,
|
||||
bAddedNewResolution
|
||||
);
|
||||
ActiveRecognitionSessionState.LastCorrectionResolution = AppliedResolution;
|
||||
if (bAddedNewResolution)
|
||||
{
|
||||
++ActiveRecognitionSessionState.ResolvedCorrectionCount;
|
||||
}
|
||||
|
||||
FHyperTwistPuzzleState ReconstructedState;
|
||||
FHyperTwistStateSnapshot ReconstructedSnapshot;
|
||||
if (HyperTwistTrainingSubsystemInternal::TryBuildClassicRecognitionStateSnapshot(
|
||||
ActiveRecognitionSessionState.SessionConfig,
|
||||
Result.ReconstructionSession,
|
||||
ReconstructedState,
|
||||
ReconstructedSnapshot
|
||||
))
|
||||
{
|
||||
Result.Snapshot = ReconstructedSnapshot;
|
||||
}
|
||||
else
|
||||
{
|
||||
Result.Snapshot = FHyperTwistStateSnapshot();
|
||||
Result.Warnings.AddUnique(TEXT("recognition-reconstruction-unavailable"));
|
||||
}
|
||||
|
||||
Result.ShellState = HyperTwistTrainingSubsystemInternal::BuildClassicCubeWebcamShellState(
|
||||
ActiveRecognitionSessionState.SessionConfig,
|
||||
Result.ReconstructionSession,
|
||||
RequestedFaceId,
|
||||
Result.CommittedUnit
|
||||
);
|
||||
Result.BrowserShellState = HyperTwistTrainingSubsystemInternal::BuildClassicCubeBrowserShellState(
|
||||
ActiveRecognitionSessionState.SessionConfig,
|
||||
Result.ReconstructionSession,
|
||||
Result.ObservedFace
|
||||
);
|
||||
Result.CorrectionState =
|
||||
HyperTwistTrainingSubsystemInternal::BuildClassicCubeCorrectionState(
|
||||
ActiveRecognitionSessionState.SessionConfig,
|
||||
Result.ReconstructionSession,
|
||||
Result.ObservedFace,
|
||||
Result.Warnings,
|
||||
ActiveRecognitionSessionState.CorrectionResolutionLedger
|
||||
);
|
||||
AppliedResolution.bClearsSolveExplanationBlock = !Result.CorrectionState.bSolveExplanationBlocked;
|
||||
ActiveRecognitionSessionState.LastCorrectionResolution = AppliedResolution;
|
||||
HyperTwistTrainingSubsystemInternal::UpsertCorrectionResolution(
|
||||
ActiveRecognitionSessionState.CorrectionResolutionLedger,
|
||||
AppliedResolution,
|
||||
bAddedNewResolution
|
||||
);
|
||||
Result.AppliedCorrectionResolution = AppliedResolution;
|
||||
Result.CorrectionState.LastResolution = AppliedResolution;
|
||||
Result.SolveExplanationState =
|
||||
HyperTwistTrainingSubsystemInternal::BuildClassicCubeSolveExplanationState(
|
||||
ActiveRecognitionSessionState.SessionConfig,
|
||||
Result.ReconstructionSession,
|
||||
Result.CorrectionState
|
||||
);
|
||||
bAppliedResolution = true;
|
||||
}
|
||||
|
||||
if (!Result.ObservedFace.IsStructurallyValid() && RequestedFaceState != nullptr)
|
||||
{
|
||||
Result.ObservedFace =
|
||||
HyperTwistTrainingSubsystemInternal::BuildObservationFromCommittedFaceState(*RequestedFaceState);
|
||||
}
|
||||
if (!Result.ShellState.IsStructurallyValid())
|
||||
{
|
||||
Result.ShellState = HyperTwistTrainingSubsystemInternal::BuildClassicCubeWebcamShellState(
|
||||
ActiveRecognitionSessionState.SessionConfig,
|
||||
Result.ReconstructionSession,
|
||||
RequestedFaceId,
|
||||
Result.CommittedUnit
|
||||
);
|
||||
}
|
||||
if (!Result.BrowserShellState.IsStructurallyValid())
|
||||
{
|
||||
Result.BrowserShellState = HyperTwistTrainingSubsystemInternal::BuildClassicCubeBrowserShellState(
|
||||
ActiveRecognitionSessionState.SessionConfig,
|
||||
Result.ReconstructionSession,
|
||||
Result.ObservedFace
|
||||
);
|
||||
}
|
||||
if (!Result.CorrectionState.IsStructurallyValid())
|
||||
{
|
||||
Result.CorrectionState =
|
||||
HyperTwistTrainingSubsystemInternal::BuildClassicCubeCorrectionState(
|
||||
ActiveRecognitionSessionState.SessionConfig,
|
||||
Result.ReconstructionSession,
|
||||
Result.ObservedFace,
|
||||
Result.Warnings,
|
||||
ActiveRecognitionSessionState.CorrectionResolutionLedger
|
||||
);
|
||||
}
|
||||
if (!Result.SolveExplanationState.IsStructurallyValid())
|
||||
{
|
||||
Result.SolveExplanationState =
|
||||
HyperTwistTrainingSubsystemInternal::BuildClassicCubeSolveExplanationState(
|
||||
ActiveRecognitionSessionState.SessionConfig,
|
||||
Result.ReconstructionSession,
|
||||
Result.CorrectionState
|
||||
);
|
||||
}
|
||||
|
||||
if (bAppliedResolution)
|
||||
{
|
||||
FHyperTwistReplayRecognitionPayload CorrectionPayload;
|
||||
CorrectionPayload.Snapshot = Result.Snapshot;
|
||||
CorrectionPayload.Confidence = Result.Confidence;
|
||||
CorrectionPayload.CommittedFaceOrStage = !RequestedFaceId.IsEmpty()
|
||||
? RequestedFaceId
|
||||
: NormalizedRequest.CommitKind;
|
||||
AppendRecognitionReplayEvent(
|
||||
EHyperTwistReplayEventType::RecognitionCorrection,
|
||||
CorrectionPayload,
|
||||
INDEX_NONE
|
||||
);
|
||||
++ActiveRecognitionSessionState.CorrectionEventCount;
|
||||
}
|
||||
|
||||
ActiveRecognitionSessionState.bHasCommitResult = true;
|
||||
ActiveRecognitionSessionState.LastCommitResult = Result;
|
||||
ActiveRecognitionSessionState.LastUpdatedAtUtc = FDateTime::UtcNow().ToIso8601();
|
||||
ActiveRecognitionSessionState.LastError =
|
||||
Result.Warnings.Num() > 0 ? FString::Join(Result.Warnings, TEXT(" | ")) : FString();
|
||||
ActiveRecognitionSessionState.ServiceHealth.LastError = ActiveRecognitionSessionState.LastError;
|
||||
if (bAppliedResolution)
|
||||
{
|
||||
SynchronizeRecognitionReplayMutation();
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
Result = VisionClient->CommitVisionObservation(NormalizedRequest);
|
||||
if (Result.SessionId.IsEmpty())
|
||||
{
|
||||
|
|
@ -7560,7 +7914,8 @@ FHyperTwistVisionCommitResult UHyperTwistTrainingSubsystem::CommitActiveRecognit
|
|||
ActiveRecognitionSessionState.SessionConfig,
|
||||
Result.ReconstructionSession,
|
||||
Result.ObservedFace,
|
||||
Result.Warnings
|
||||
Result.Warnings,
|
||||
ActiveRecognitionSessionState.CorrectionResolutionLedger
|
||||
);
|
||||
Result.SolveExplanationState =
|
||||
HyperTwistTrainingSubsystemInternal::BuildClassicCubeSolveExplanationState(
|
||||
|
|
|
|||
|
|
@ -886,6 +886,51 @@ struct FHyperTwistVisionCorrectionContradiction
|
|||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistVisionCorrectionResolution
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString ResolutionId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString FaceId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString ResolutionKind;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString RequestedActionId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString ObservationId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 RevisionCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
TArray<FString> ResolvedContradictionIds;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString StatusLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString DetailLine;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bClearsSolveExplanationBlock = false;
|
||||
|
||||
bool IsStructurallyValid() const
|
||||
{
|
||||
return !ResolutionId.IsEmpty()
|
||||
&& !FaceId.IsEmpty()
|
||||
&& !ResolutionKind.IsEmpty()
|
||||
&& !RequestedActionId.IsEmpty()
|
||||
&& RevisionCount >= 0;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistVisionCorrectionProfile
|
||||
{
|
||||
|
|
@ -963,6 +1008,9 @@ struct FHyperTwistVisionCorrectionState
|
|||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 ContradictionCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 ResolvedCorrectionCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FHyperTwistVisionCorrectionTarget ActiveTarget;
|
||||
|
||||
|
|
@ -972,6 +1020,12 @@ struct FHyperTwistVisionCorrectionState
|
|||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
TArray<FHyperTwistVisionCorrectionContradiction> Contradictions;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FHyperTwistVisionCorrectionResolution LastResolution;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
TArray<FHyperTwistVisionCorrectionResolution> ResolutionLedger;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bCorrectionRequired = false;
|
||||
|
||||
|
|
@ -998,7 +1052,9 @@ struct FHyperTwistVisionCorrectionState
|
|||
if (CorrectionProfileId.IsEmpty()
|
||||
|| MissingFaceCount < 0
|
||||
|| ContradictionCount < 0
|
||||
|| ContradictionCount != Contradictions.Num())
|
||||
|| ContradictionCount != Contradictions.Num()
|
||||
|| ResolvedCorrectionCount < 0
|
||||
|| ResolvedCorrectionCount != ResolutionLedger.Num())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1029,6 +1085,19 @@ struct FHyperTwistVisionCorrectionState
|
|||
}
|
||||
}
|
||||
|
||||
if (!LastResolution.ResolutionId.IsEmpty() && !LastResolution.IsStructurallyValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const FHyperTwistVisionCorrectionResolution& Resolution : ResolutionLedger)
|
||||
{
|
||||
if (!Resolution.IsStructurallyValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
|
@ -1175,6 +1244,12 @@ struct FHyperTwistVisionCommitRequest
|
|||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString TargetStage;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString RequestedActionId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString ResolutionKind;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
|
|
@ -1215,6 +1290,9 @@ struct FHyperTwistVisionCommitResult
|
|||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FHyperTwistVisionCorrectionState CorrectionState;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FHyperTwistVisionCorrectionResolution AppliedCorrectionResolution;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
TArray<FString> Warnings;
|
||||
|
||||
|
|
|
|||
|
|
@ -1868,6 +1868,9 @@ struct FHyperTwistTrainingRecognitionSessionState
|
|||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 CorrectionEventCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 ResolvedCorrectionCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 FinalizedSessionCount = 0;
|
||||
|
||||
|
|
@ -1886,6 +1889,12 @@ struct FHyperTwistTrainingRecognitionSessionState
|
|||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FHyperTwistVisionFinalizeResult LastFinalizeResult;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FHyperTwistVisionCorrectionResolution LastCorrectionResolution;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
TArray<FHyperTwistVisionCorrectionResolution> CorrectionResolutionLedger;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FHyperTwistVisionReconstructionSession ActiveReconstructionSession;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,235 @@
|
|||
// 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 HyperTwistClassicCubePhase6RSTestInternal
|
||||
{
|
||||
FHyperTwistTrainingDeck MakeRecognitionDeck()
|
||||
{
|
||||
FHyperTwistTrainingDeck Deck;
|
||||
Deck.DeckId = TEXT("phase6r-s/classic-cube-correction-resolution");
|
||||
Deck.Title = TEXT("Phase 6R-S Classic Cube Correction Resolution");
|
||||
Deck.DeliveryModes = {
|
||||
EHyperTwistTrainingDeliveryMode::RecognitionAssisted,
|
||||
EHyperTwistTrainingDeliveryMode::CoachReviewed
|
||||
};
|
||||
|
||||
FHyperTwistTrainingCase TrainingCase;
|
||||
TrainingCase.CaseId = TEXT("phase6r-s-case");
|
||||
TrainingCase.PuzzleId = TEXT("cube/3x3x3");
|
||||
TrainingCase.PromptKind = EHyperTwistTrainingPromptKind::Recognition;
|
||||
TrainingCase.PromptLabel = TEXT("Phase 6R-S 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"));
|
||||
}
|
||||
}
|
||||
|
||||
UHyperTwistTrainingSubsystem* MakeRecognitionSubsystem(const FString& SessionId)
|
||||
{
|
||||
UGameInstance* GameInstance = NewObject<UGameInstance>(GetTransientPackage());
|
||||
if (GameInstance == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UHyperTwistTrainingSubsystem* TrainingSubsystem = NewObject<UHyperTwistTrainingSubsystem>(GameInstance);
|
||||
if (TrainingSubsystem == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ForceMockRecognitionClient(TrainingSubsystem);
|
||||
const FHyperTwistTrainingRunState RunState = TrainingSubsystem->StartTrainingRunFromDeck(
|
||||
MakeRecognitionDeck(),
|
||||
TEXT("phase6r-s-user"),
|
||||
SessionId,
|
||||
EHyperTwistTrainingDeliveryMode::RecognitionAssisted
|
||||
);
|
||||
return RunState.IsStructurallyValid() ? TrainingSubsystem : nullptr;
|
||||
}
|
||||
|
||||
void SubmitPreviewFrame(UHyperTwistTrainingSubsystem* TrainingSubsystem, const FString& FaceId, const int32 FrameOrdinal)
|
||||
{
|
||||
FHyperTwistVisionFrameEnvelope Frame;
|
||||
Frame.FrameOrdinal = FrameOrdinal;
|
||||
Frame.TargetFaceHint = FaceId;
|
||||
TrainingSubsystem->SubmitActiveRecognitionFrame(Frame);
|
||||
}
|
||||
|
||||
FHyperTwistVisionCommitResult CommitFace(
|
||||
UHyperTwistTrainingSubsystem* TrainingSubsystem,
|
||||
const FString& FaceId,
|
||||
const int32 FrameOrdinal
|
||||
)
|
||||
{
|
||||
SubmitPreviewFrame(TrainingSubsystem, FaceId, FrameOrdinal);
|
||||
|
||||
FHyperTwistVisionCommitRequest Request;
|
||||
Request.TargetFace = FaceId;
|
||||
return TrainingSubsystem->CommitActiveRecognitionObservation(Request);
|
||||
}
|
||||
|
||||
FHyperTwistVisionCommitResult ResolveCorrection(
|
||||
UHyperTwistTrainingSubsystem* TrainingSubsystem,
|
||||
const FString& FaceId
|
||||
)
|
||||
{
|
||||
FHyperTwistVisionCommitRequest Request;
|
||||
Request.CommitKind = TEXT("correction-resolution");
|
||||
Request.TargetFace = FaceId;
|
||||
Request.TargetStage = TEXT("cube-edit");
|
||||
Request.RequestedActionId = TEXT("apply-manual-corrections");
|
||||
Request.ResolutionKind = TEXT("manual-review-accepted");
|
||||
return TrainingSubsystem->CommitActiveRecognitionObservation(Request);
|
||||
}
|
||||
|
||||
void CommitClassicCubeNet(UHyperTwistTrainingSubsystem* TrainingSubsystem)
|
||||
{
|
||||
const TArray<FString> FaceOrder = {
|
||||
TEXT("U"),
|
||||
TEXT("R"),
|
||||
TEXT("F"),
|
||||
TEXT("D"),
|
||||
TEXT("L"),
|
||||
TEXT("B")
|
||||
};
|
||||
|
||||
for (int32 FaceOrdinal = 0; FaceOrdinal < FaceOrder.Num(); ++FaceOrdinal)
|
||||
{
|
||||
CommitFace(TrainingSubsystem, FaceOrder[FaceOrdinal], FaceOrdinal + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
|
||||
FHyperTwistClassicCubePhase6RSCorrectionResolutionUnlockTest,
|
||||
"HyperTwist.Permissive.ClassicCube.Phase6R.S.CorrectionResolutionUnlock",
|
||||
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
|
||||
)
|
||||
|
||||
bool FHyperTwistClassicCubePhase6RSCorrectionResolutionUnlockTest::RunTest(const FString& Parameters)
|
||||
{
|
||||
UHyperTwistTrainingSubsystem* TrainingSubsystem =
|
||||
HyperTwistClassicCubePhase6RSTestInternal::MakeRecognitionSubsystem(TEXT("phase6r-s-unlock-session"));
|
||||
TestNotNull(TEXT("The recognition subsystem must be constructed for Phase 6R-S."), TrainingSubsystem);
|
||||
if (TrainingSubsystem == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
HyperTwistClassicCubePhase6RSTestInternal::CommitClassicCubeNet(TrainingSubsystem);
|
||||
HyperTwistClassicCubePhase6RSTestInternal::CommitFace(TrainingSubsystem, TEXT("F"), 7);
|
||||
const FHyperTwistVisionCommitResult Result =
|
||||
HyperTwistClassicCubePhase6RSTestInternal::ResolveCorrection(TrainingSubsystem, TEXT("F"));
|
||||
|
||||
const FHyperTwistTrainingRecognitionSessionState SessionState =
|
||||
TrainingSubsystem->GetActiveRecognitionSessionState();
|
||||
TestTrue(TEXT("The resolution route must surface a structurally valid applied resolution."), Result.AppliedCorrectionResolution.IsStructurallyValid());
|
||||
TestEqual(TEXT("The resolution route must apply the reviewed face explicitly."), Result.AppliedCorrectionResolution.FaceId, TEXT("F"));
|
||||
TestTrue(TEXT("The resolution route must carry a structurally valid correction state."), Result.CorrectionState.IsStructurallyValid());
|
||||
TestFalse(TEXT("The resolution route must close the open correction target after review."), Result.CorrectionState.bCorrectionRequired);
|
||||
TestTrue(TEXT("The resolution route must mark the correction shell complete after review."), Result.CorrectionState.bCorrectionComplete);
|
||||
TestEqual(TEXT("The resolution route must retain one correction resolution in the ledger."), Result.CorrectionState.ResolutionLedger.Num(), 1);
|
||||
TestEqual(TEXT("The resolution route must count one resolved correction event."), Result.CorrectionState.ResolvedCorrectionCount, 1);
|
||||
TestTrue(TEXT("Solve guidance must unlock once the correction review closes."), Result.SolveExplanationState.bReadyForExplanation);
|
||||
TestEqual(TEXT("The solve explanation route must return to the bounded first solve stage."), Result.SolveExplanationState.RecommendedStageId, TEXT("orient-centers"));
|
||||
TestEqual(TEXT("The session must count one resolved correction event."), SessionState.ResolvedCorrectionCount, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
|
||||
FHyperTwistClassicCubePhase6RSCorrectionResolutionPartialClosureTest,
|
||||
"HyperTwist.Permissive.ClassicCube.Phase6R.S.CorrectionResolutionPartialClosure",
|
||||
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
|
||||
)
|
||||
|
||||
bool FHyperTwistClassicCubePhase6RSCorrectionResolutionPartialClosureTest::RunTest(const FString& Parameters)
|
||||
{
|
||||
UHyperTwistTrainingSubsystem* TrainingSubsystem =
|
||||
HyperTwistClassicCubePhase6RSTestInternal::MakeRecognitionSubsystem(TEXT("phase6r-s-partial-session"));
|
||||
TestNotNull(TEXT("The recognition subsystem must be constructed for Phase 6R-S."), TrainingSubsystem);
|
||||
if (TrainingSubsystem == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
HyperTwistClassicCubePhase6RSTestInternal::CommitClassicCubeNet(TrainingSubsystem);
|
||||
HyperTwistClassicCubePhase6RSTestInternal::CommitFace(TrainingSubsystem, TEXT("F"), 7);
|
||||
HyperTwistClassicCubePhase6RSTestInternal::CommitFace(TrainingSubsystem, TEXT("R"), 8);
|
||||
const FHyperTwistVisionCommitResult Result =
|
||||
HyperTwistClassicCubePhase6RSTestInternal::ResolveCorrection(TrainingSubsystem, TEXT("F"));
|
||||
|
||||
const FHyperTwistTrainingRecognitionSessionState SessionState =
|
||||
TrainingSubsystem->GetActiveRecognitionSessionState();
|
||||
TestTrue(TEXT("The partial closure route must still surface an applied resolution."), Result.AppliedCorrectionResolution.IsStructurallyValid());
|
||||
TestTrue(TEXT("The partial closure route must keep correction open while another revised face remains."), Result.CorrectionState.bCorrectionRequired);
|
||||
TestFalse(TEXT("The partial closure route must not mark the shell complete while another face is pending."), Result.CorrectionState.bCorrectionComplete);
|
||||
TestEqual(TEXT("The partial closure route must leave the earlier-ordered revised face active."), Result.CorrectionState.ActiveTargetFaceId, TEXT("R"));
|
||||
TestEqual(TEXT("The partial closure route must classify the remaining active target as a revised face."), Result.CorrectionState.ActiveTarget.ReasonId, TEXT("revised-face"));
|
||||
TestEqual(TEXT("The partial closure route must preserve one ledger entry after the first accepted review."), Result.CorrectionState.ResolutionLedger.Num(), 1);
|
||||
TestFalse(TEXT("Solve guidance must stay blocked while another correction target remains."), Result.SolveExplanationState.bReadyForExplanation);
|
||||
TestEqual(TEXT("The solve explanation route must stay in cube-edit while another review remains."), Result.SolveExplanationState.RecommendedStageId, TEXT("cube-edit"));
|
||||
TestEqual(TEXT("The session must still count only one resolved correction review."), SessionState.ResolvedCorrectionCount, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
|
||||
FHyperTwistClassicCubePhase6RSCorrectionResolutionReopenTest,
|
||||
"HyperTwist.Permissive.ClassicCube.Phase6R.S.CorrectionResolutionReopen",
|
||||
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
|
||||
)
|
||||
|
||||
bool FHyperTwistClassicCubePhase6RSCorrectionResolutionReopenTest::RunTest(const FString& Parameters)
|
||||
{
|
||||
UHyperTwistTrainingSubsystem* TrainingSubsystem =
|
||||
HyperTwistClassicCubePhase6RSTestInternal::MakeRecognitionSubsystem(TEXT("phase6r-s-reopen-session"));
|
||||
TestNotNull(TEXT("The recognition subsystem must be constructed for Phase 6R-S."), TrainingSubsystem);
|
||||
if (TrainingSubsystem == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
HyperTwistClassicCubePhase6RSTestInternal::CommitClassicCubeNet(TrainingSubsystem);
|
||||
HyperTwistClassicCubePhase6RSTestInternal::CommitFace(TrainingSubsystem, TEXT("F"), 7);
|
||||
HyperTwistClassicCubePhase6RSTestInternal::ResolveCorrection(TrainingSubsystem, TEXT("F"));
|
||||
const FHyperTwistVisionCommitResult Result =
|
||||
HyperTwistClassicCubePhase6RSTestInternal::CommitFace(TrainingSubsystem, TEXT("F"), 8);
|
||||
|
||||
const FHyperTwistTrainingRecognitionSessionState SessionState =
|
||||
TrainingSubsystem->GetActiveRecognitionSessionState();
|
||||
TestTrue(TEXT("The reopen route must keep a structurally valid correction state."), Result.CorrectionState.IsStructurallyValid());
|
||||
TestTrue(TEXT("The reopen route must reopen correction after a later recommit on the same face."), Result.CorrectionState.bCorrectionRequired);
|
||||
TestEqual(TEXT("The reopen route must target the recommitted face again."), Result.CorrectionState.ActiveTargetFaceId, TEXT("F"));
|
||||
TestEqual(TEXT("The reopen route must classify the reopened target as a revised face."), Result.CorrectionState.ActiveTarget.ReasonId, TEXT("revised-face"));
|
||||
TestEqual(TEXT("The reopen route must preserve the earlier accepted review in the ledger."), Result.CorrectionState.ResolutionLedger.Num(), 1);
|
||||
TestFalse(TEXT("Solve guidance must block again after a later recommit reopens correction."), Result.SolveExplanationState.bReadyForExplanation);
|
||||
TestEqual(TEXT("The session must not double-count a new resolution when only a recommit occurred."), SessionState.ResolvedCorrectionCount, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -159,8 +159,12 @@ Status update on `2026-05-21`:
|
|||
correction/explanation control pass is now consumed
|
||||
- the bounded permissive `Phase 6R-R` shared classic-cube recognition multi-face
|
||||
correction/explanation shell packet is now landed in current code
|
||||
- the current next bounded move is a source-backed follow-on control pass for the retained
|
||||
classic-cube recognition correction/explanation shell remainder, not a new restrictive packet by
|
||||
- the generic source-backed `Phase 6R-S` shared classic-cube correction-resolution closure
|
||||
control pass is now consumed
|
||||
- the bounded permissive `Phase 6R-S` shared classic-cube correction-resolution closure packet is
|
||||
now landed in current code
|
||||
- the current next bounded move is a source-backed `Phase 6R-T` `roice3/MagicTile`
|
||||
transform-aware macro remapping 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
|
||||
|
|
@ -265,8 +269,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 follow-on control pass for the retained classic-cube
|
||||
recognition correction/explanation shell remainder
|
||||
- the next bounded move is a source-backed `Phase 6R-T` `roice3/MagicTile`
|
||||
transform-aware macro remapping preparation/control pass
|
||||
|
||||
Companion docs:
|
||||
|
||||
|
|
@ -755,7 +759,8 @@ Approved working posture:
|
|||
- classic-cube recognition calibration contract
|
||||
- ordered face-observation contract
|
||||
- classic-cube webcam shell
|
||||
- shared correction-target capture-state and re-scan adjunct via `Phase 6R-R`
|
||||
- shared correction-target capture-state and re-scan adjunct via the landed shared `Phase 6R-R`
|
||||
and `Phase 6R-S` correction shell
|
||||
- keep the following families deferred to later queue decisions:
|
||||
- bundled-font redistribution and multilingual solve shell
|
||||
- direct standalone multilingual or asset-shipping widening beyond the landed shared correction
|
||||
|
|
@ -805,7 +810,7 @@ Approved working posture:
|
|||
- preserve the row as the bounded recognition companion lane after `kkoomen/qbr`
|
||||
- if later implementation ships or copies bundled third-party frontend assets, capture and preserve
|
||||
those assets' own upstream license/provenance rather than flattening them into the repo-level `MIT`
|
||||
- the first two bounded retained slices are now landed in current code:
|
||||
- the bounded retained slices now landed in current code are:
|
||||
- committed-face reconstruction session
|
||||
- face-vote replacement ledger
|
||||
- final classic-net shaping above aggregated committed faces
|
||||
|
|
@ -813,11 +818,13 @@ Approved working posture:
|
|||
- bounded solve explanation/recommendation stage ladder and recommendation state
|
||||
- bounded correction profile, contradiction-aware correction state, and
|
||||
correction-explanation shell routing
|
||||
- correction-resolution ledger, manual-review acceptance, and solve-guidance reopen/unlock
|
||||
semantics
|
||||
- keep the row only partially incorporated by default:
|
||||
- retained correction/explanation shell remainder beyond the landed
|
||||
correction-state slice still requires a separate control decision
|
||||
- any redistribution of `frontend/lib/twistysim.min.js` still requires preserved or replaced
|
||||
upstream provenance/license
|
||||
- generalized solver backend ownership and broad playback-runtime ownership stay separately
|
||||
deferred
|
||||
|
||||
### `tentone/rubix-solver`
|
||||
|
||||
|
|
@ -3147,8 +3154,8 @@ Approved working posture:
|
|||
- keep ordinary third-party notices if code or substantial portions are incorporated
|
||||
- keep the live widening bounded to the landed tiling-topology contract family rather than
|
||||
flattening the row into blanket permission for full host-shell or runtime replacement use
|
||||
- after the landed `Phase 6R-D` slice, move the queue head to the bounded speech-input / voice
|
||||
sidecar set rather than reopening `MagicTile` by default
|
||||
- the next justified widening is now the bounded `Phase 6R-T` transform-aware macro remapping
|
||||
control pass rather than blanket host-shell or runtime replacement use
|
||||
|
||||
### `superliminal.com/andrey/mc7d`
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,173 @@
|
|||
# HyperTwist Phase 6R-S classic-cube correction resolution closure implementation packet
|
||||
|
||||
Created on `2026-05-24`
|
||||
|
||||
## Status
|
||||
|
||||
- first-party HyperTwist packet
|
||||
- bounded permissive `Phase 6R-S` implementation slice
|
||||
|
||||
## Purpose
|
||||
|
||||
This packet lands the current retained shared classic-cube
|
||||
correction-resolution closure family:
|
||||
|
||||
- first-party accepted-resolution ledger state, manual-review acceptance
|
||||
routing, and solve-guidance reopen/unlock semantics above the already landed
|
||||
`qbr` webcam shell, `rubix-cube-solver` reconstruction/browser-shell/solve
|
||||
explanation seams, and the first-party `Phase 6R-R` correction shell
|
||||
|
||||
It is not:
|
||||
|
||||
- a full `qbr` row transplant
|
||||
- a full `rubix-cube-solver` row transplant
|
||||
- a bundled `twistysim.min.js` redistribution packet
|
||||
- a bundled `arial-unicode-ms.ttf` redistribution packet
|
||||
- a multilingual `qbr` shell packet
|
||||
- a generalized solver backend packet
|
||||
- a broad playback-runtime packet
|
||||
|
||||
## Current authority basis
|
||||
|
||||
This implementation packet stands on:
|
||||
|
||||
- `docs/REPO_LICENSE_TRACKING.md`
|
||||
- `docs/ops/HYPERTWIST_CROSS_LANE_AUTHORITY_HIERARCHY_AND_RECONCILIATION_2026-05-20.md`
|
||||
- `docs/arch/HYPERTWIST_PHASE6R_S_CLASSIC_CUBE_CORRECTION_RESOLUTION_CLOSURE_PREPARATION_PACKET_2026-05-24.md`
|
||||
|
||||
The retained owner split stays explicit:
|
||||
|
||||
- `vivaansinghvi07/rubix-cube-solver`
|
||||
- retained primary owner for correction/explanation semantics,
|
||||
correction-resolution closure, and solve-guidance reopen/unlock behavior
|
||||
- `kkoomen/qbr`
|
||||
- retained adjunct owner for capture-state continuity, target-face re-scan
|
||||
anchoring, and revision-aware reopen posture
|
||||
|
||||
The top-level product shell owner does not change here:
|
||||
|
||||
- first-party HyperTwist remains the broader recognition-session and
|
||||
product-shell owner
|
||||
|
||||
## Landed scope
|
||||
|
||||
The current code now owns a bounded first-party correction-resolution closure
|
||||
slice through:
|
||||
|
||||
- first-party `HyperTwistRecognition` contract types for:
|
||||
- correction-resolution record shape
|
||||
- correction-state resolution ledger and last-resolution readout
|
||||
- commit-request manual-review action metadata
|
||||
- commit-result applied-resolution payloads
|
||||
- first-party recognition session-state normalization for:
|
||||
- resolved correction count
|
||||
- last correction resolution
|
||||
- correction-resolution ledger persistence across the active session
|
||||
- active subsystem normalization in:
|
||||
- local correction-resolution commit handling above the landed qbr classic
|
||||
route
|
||||
- correction-target validation before review acceptance
|
||||
- resolution upsert behavior keyed by face id plus observation/revision
|
||||
identity
|
||||
- solve-guidance unlock after full closure
|
||||
- correction reopen after a later recommit changes the reviewed face state
|
||||
- sample contract routing in:
|
||||
- `UHyperTwistContractLibrary`
|
||||
- focused automation coverage in:
|
||||
- `HyperTwistClassicCubePhase6RSCorrectionResolutionContractTest.cpp`
|
||||
|
||||
## Why this is still intentionally bounded
|
||||
|
||||
This packet lands the next bounded correction-resolution closure slice, but it
|
||||
does not widen into neighboring families or broader ownership.
|
||||
|
||||
Still excluded:
|
||||
|
||||
- bundled `twistysim.min.js` redistribution
|
||||
- bundled `arial-unicode-ms.ttf` redistribution
|
||||
- standalone multilingual `qbr` shell ownership
|
||||
- generalized solver backend ownership
|
||||
- broad playback-runtime ownership
|
||||
- donor-shaped frontend transplant
|
||||
|
||||
## Validation
|
||||
|
||||
Build validation:
|
||||
|
||||
- `C:\Program Files\Epic Games\UE_5.7\Engine\Build\BatchFiles\Build.bat UnrealHyperTwistEditor Win64 Development -Project='C:\HyperTwist\UnrealHyperTwist\UnrealHyperTwist.uproject' -WaitMutex -NoHotReloadFromIDE -NoUba`
|
||||
|
||||
Focused automation validation:
|
||||
|
||||
- `C:\Program Files\Epic Games\UE_5.7\Engine\Binaries\Win64\UnrealEditor-Cmd.exe C:\HyperTwist\UnrealHyperTwist\UnrealHyperTwist.uproject -unattended -nop4 -nosplash -NullRHI -log -stdout -FullStdOutLogOutput -AbsLog=C:\HyperTwist\UnrealHyperTwist\Saved\Logs\Phase6R-S-ClassicCube-Verify.log -ReportExportPath=C:\HyperTwist\UnrealHyperTwist\Saved\AutomationReports\Phase6R-S-ClassicCube-Verify -ExecCmds="Automation RunTests HyperTwist.Permissive.ClassicCube.Phase6R.S; Quit" -TestExit="Automation Test Queue Empty"`
|
||||
|
||||
Regression automation validation:
|
||||
|
||||
- `HyperTwist.Permissive.ClassicCube.Phase6R.R`
|
||||
- `HyperTwist.Permissive.RubixCubeSolver.Phase6R.Q`
|
||||
- `HyperTwist.Permissive.RubixCubeSolver.Phase6R.P`
|
||||
- `HyperTwist.Permissive.Qbr.Phase6R.O`
|
||||
- `HyperTwist.Permissive.RubixCubeSolver.Phase6R.C`
|
||||
- `HyperTwist.CleanRoom.CubeDesk`
|
||||
|
||||
Expected covered tests:
|
||||
|
||||
- `CorrectionResolutionUnlock`
|
||||
- `CorrectionResolutionPartialClosure`
|
||||
- `CorrectionResolutionReopen`
|
||||
- existing `Phase 6R-R`, `rubix-cube-solver`, `qbr`, and `CubeDesk`
|
||||
regression suites
|
||||
|
||||
## Queue effect
|
||||
|
||||
This packet consumes the current bounded `Phase 6R-S` implementation slice.
|
||||
|
||||
`kkoomen/qbr` remains partially incorporated:
|
||||
|
||||
- landed now:
|
||||
- classic-cube recognition calibration contract
|
||||
- ordered face-observation contract
|
||||
- classic-cube webcam shell
|
||||
- shared correction-target capture-state and re-scan adjunct
|
||||
- still deferred:
|
||||
- bundled-font redistribution and multilingual solve shell
|
||||
|
||||
`vivaansinghvi07/rubix-cube-solver` remains partially incorporated:
|
||||
|
||||
- landed now:
|
||||
- committed-face reconstruction session
|
||||
- face-vote replacement ledger
|
||||
- final classic-net shaping above aggregated committed faces
|
||||
- browser/webcam shell profile and browser-shell session-state composition
|
||||
- bounded solve explanation/recommendation stage ladder and recommendation
|
||||
state
|
||||
- bounded correction profile, contradiction-aware correction state, and
|
||||
correction-explanation shell routing
|
||||
- correction-resolution ledger, manual-review acceptance, and
|
||||
solve-guidance reopen/unlock semantics
|
||||
- still deferred:
|
||||
- bundled `twistysim.min.js` redistribution
|
||||
- generalized solver backend ownership
|
||||
- broad playback-runtime ownership
|
||||
|
||||
The next clean move is:
|
||||
|
||||
- a source-backed `Phase 6R-T` `roice3/MagicTile` transform-aware macro
|
||||
remapping preparation/control pass
|
||||
|
||||
Keep the future sequencing guards visible:
|
||||
|
||||
- `vivaansinghvi07/rubix-cube-solver`
|
||||
- do not copy or redistribute `frontend/lib/twistysim.min.js` without
|
||||
preserving or replacing its upstream provenance/license in any future
|
||||
widening that would ship that asset
|
||||
- `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
|
||||
- `roice3/MagicTile`
|
||||
- keep the next widening bounded to transform-aware macro remapping rather
|
||||
than broad non-Euclidean interaction or host-shell ownership
|
||||
- first-party HyperTwist
|
||||
- keep the shared classic-cube correction shell closed by default unless a
|
||||
narrower first-party gap is proven above the landed resolution-closure
|
||||
seam
|
||||
|
|
@ -0,0 +1,168 @@
|
|||
# HyperTwist Phase 6R-S classic-cube correction resolution closure preparation packet
|
||||
|
||||
Created on `2026-05-24`
|
||||
|
||||
## Status
|
||||
|
||||
- historical consumed preparation authority
|
||||
- bounded post-`Phase 6R-R` control slice
|
||||
- the first bounded implementation slice now lands in:
|
||||
- `docs/arch/HYPERTWIST_PHASE6R_S_CLASSIC_CUBE_CORRECTION_RESOLUTION_CLOSURE_IMPLEMENTATION_PACKET_2026-05-24.md`
|
||||
|
||||
## Purpose
|
||||
|
||||
This packet freezes the next widening order after the landed `Phase 6R-R`
|
||||
shared classic-cube correction/explanation shell slice.
|
||||
|
||||
The open task was:
|
||||
|
||||
- define the next bounded source-backed widening packet as the shared
|
||||
classic-cube correction-resolution closure layer above the already landed
|
||||
`qbr` webcam shell, `rubix-cube-solver` reconstruction/browser shell/solve
|
||||
explanation seams, and the first-party `Phase 6R-R` correction shell
|
||||
|
||||
It is not:
|
||||
|
||||
- a full `qbr` row transplant
|
||||
- a full `rubix-cube-solver` row transplant
|
||||
- a bundled `twistysim.min.js` redistribution packet
|
||||
- a bundled `arial-unicode-ms.ttf` redistribution packet
|
||||
- a multilingual `qbr` shell packet
|
||||
- a generalized solver backend packet
|
||||
- a broad playback-runtime packet
|
||||
|
||||
## Current authority basis
|
||||
|
||||
This preparation packet stands on already-closed authority:
|
||||
|
||||
- `docs/REPO_LICENSE_TRACKING.md`
|
||||
- `docs/v6_5_deep_manual_pack/HyperTwist/ROADMAP.md`
|
||||
- `docs/arch/HYPERTWIST_PHASE6R_R_CLASSIC_CUBE_MULTI_FACE_CORRECTION_EXPLANATION_IMPLEMENTATION_PACKET_2026-05-24.md`
|
||||
|
||||
The key accepted routing facts are:
|
||||
|
||||
- `kkoomen/qbr` remains the primary classic-cube live-recognition and
|
||||
capture-state donor
|
||||
- `vivaansinghvi07/rubix-cube-solver` remains the stronger correction,
|
||||
reconstruction-companion, and explanation-semantics donor
|
||||
- the already landed `Phase 6R-R` slice owns:
|
||||
- correction targets
|
||||
- contradiction objects
|
||||
- correction-profile defaults
|
||||
- correction shell visibility and solve-guidance blocking
|
||||
- the next donor value strongest for the narrower shared slice is:
|
||||
- accepted manual-review resolution per face/revision
|
||||
- explicit correction-resolution ledger state
|
||||
- reopen-after-recommit behavior
|
||||
- clear-to-solve transition semantics after correction review closure
|
||||
|
||||
Ownership denied here is:
|
||||
|
||||
- do not widen into bundled `twistysim.min.js` redistribution
|
||||
- do not widen into bundled `arial-unicode-ms.ttf` redistribution
|
||||
- do not widen into standalone multilingual `qbr` ownership
|
||||
- do not widen into generalized solver backend ownership
|
||||
- do not widen into broad playback-runtime ownership
|
||||
|
||||
## Cross-lane retained split
|
||||
|
||||
Exact contested slice:
|
||||
|
||||
- classic-cube correction-resolution closure
|
||||
|
||||
Candidate repos considered:
|
||||
|
||||
- `kkoomen/qbr`
|
||||
- `vivaansinghvi07/rubix-cube-solver`
|
||||
|
||||
Authority outcome:
|
||||
|
||||
- `vivaansinghvi07/rubix-cube-solver` - `A1 / R1 / F2`
|
||||
- retained primary owner for correction-resolution semantics, manual-review
|
||||
acceptance flow, and solve-guidance reopen/unlock behavior
|
||||
- `kkoomen/qbr` - `A2 / R1 / F2`
|
||||
- retained adjunct owner for capture-state continuity, target-face re-scan
|
||||
anchoring, and revision-aware reopen posture that keeps the correction
|
||||
shell attached to the recognition substrate
|
||||
|
||||
The top-level product shell owner does not change here:
|
||||
|
||||
- first-party HyperTwist remains the broader recognition-session and
|
||||
product-shell owner
|
||||
|
||||
## Required result
|
||||
|
||||
The source-backed control pass for this packet is now complete.
|
||||
|
||||
The first actual `6R-S` implementation packet should:
|
||||
|
||||
- define one bounded correction-resolution closure slice
|
||||
- keep the slice above the landed `Phase 6R-O`, `Phase 6R-P`, `Phase 6R-Q`,
|
||||
and `Phase 6R-R` seams
|
||||
- land accepted-resolution ledger state, manual-review acceptance routing, and
|
||||
solve-guidance reopen/unlock semantics
|
||||
- preserve `rubix-cube-solver` as the retained correction/explanation-semantic
|
||||
owner while preserving `qbr` as the capture-state adjunct
|
||||
- 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:
|
||||
|
||||
- `C:\visual_studio_solutions\multi_project\GPT 5.4 HyperTwist parse\19-kkoomen-qbr-upstream-dossier.md`
|
||||
- `C:\visual_studio_solutions\multi_project\GPT 5.4 HyperTwist parse\20-vivaansinghvi07-rubix-cube-solver-upstream-dossier.md`
|
||||
|
||||
Inspected first-party receiving basis:
|
||||
|
||||
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistRecognition/HyperTwistRecognitionTypes.h`
|
||||
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistTraining/HyperTwistTrainingTypes.h`
|
||||
- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistBootstrap/HyperTwistContractLibrary.cpp`
|
||||
- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingSubsystem.cpp`
|
||||
- `UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistClassicCubePhase6RRCorrectionContractTest.cpp`
|
||||
|
||||
## Narrowed 6R-S slice decision
|
||||
|
||||
The next widening slice is fixed as:
|
||||
|
||||
1. correction-resolution closure and solve-guidance reopen/unlock semantics
|
||||
|
||||
That narrowed slice covers:
|
||||
|
||||
- first-party accepted-resolution ledger state for:
|
||||
- reviewed face id
|
||||
- observation/revision identity
|
||||
- resolved contradiction ids
|
||||
- clear-to-solve transition visibility
|
||||
- first-party resolution commit behavior for:
|
||||
- manual-review acceptance
|
||||
- correction-target validation
|
||||
- replay mutation and correction-event accounting
|
||||
- first-party reopen behavior for:
|
||||
- later recommits on a previously resolved face
|
||||
- solve-guidance blocking when a later revision reopens correction
|
||||
- focused automation coverage
|
||||
|
||||
## Deferred neighboring families
|
||||
|
||||
The first `6R-S` implementation packet must keep these capability families
|
||||
closed:
|
||||
|
||||
- bundled `twistysim.min.js` shipping or redistribution
|
||||
- bundled `arial-unicode-ms.ttf` shipping or redistribution
|
||||
- standalone multilingual `qbr` shell ownership
|
||||
- generalized solver backend ownership
|
||||
- broad playback-runtime ownership
|
||||
- any donor-shaped frontend transplant
|
||||
|
||||
## Queue effect
|
||||
|
||||
This preparation packet is now consumed by the landed bounded `Phase 6R-S`
|
||||
implementation slice.
|
||||
|
||||
Once that slice lands, the next clean move should return to the retained
|
||||
repo-row queue at:
|
||||
|
||||
- a source-backed `Phase 6R-T` `roice3/MagicTile` transform-aware macro
|
||||
remapping preparation/control pass
|
||||
|
|
@ -108,15 +108,21 @@ The next bounded move is now:
|
|||
correction/explanation control pass is now consumed
|
||||
10. the bounded permissive `Phase 6R-R` shared classic-cube recognition multi-face
|
||||
correction/explanation shell packet is now landed in current code
|
||||
11. the next bounded move is a source-backed follow-on control pass for the retained
|
||||
classic-cube recognition correction/explanation shell remainder shared across `kkoomen/qbr`
|
||||
and `vivaansinghvi07/rubix-cube-solver`
|
||||
12. keep the `rubix-cube-solver` guard visible:
|
||||
11. the generic source-backed `Phase 6R-S` shared classic-cube correction-resolution closure
|
||||
control pass is now consumed
|
||||
12. the bounded permissive `Phase 6R-S` shared classic-cube correction-resolution closure packet
|
||||
is now landed in current code
|
||||
13. the next bounded move is a source-backed `Phase 6R-T` `roice3/MagicTile`
|
||||
transform-aware macro remapping preparation/control pass
|
||||
14. keep the `rubix-cube-solver` guard visible:
|
||||
- do not copy or redistribute `frontend/lib/twistysim.min.js` without preserving or replacing
|
||||
its upstream provenance/license in any future widening that would ship that asset
|
||||
13. keep the `qbr` guard visible:
|
||||
15. keep the `qbr` guard visible:
|
||||
- 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
|
||||
16. keep the `MagicTile` guard visible:
|
||||
- keep the next widening bounded to transform-aware macro remapping rather than broad
|
||||
non-Euclidean interaction or WinForms/OpenTK host-shell ownership
|
||||
|
||||
## Memory-specific sequencing rule
|
||||
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ Do not collapse those three tiers into one undifferentiated "features" voice.
|
|||
| Committed-face reconstruction and final classic-net shaping | Implemented now | landed `rubix-cube-solver` packet | Reconstruction session boundary is live. |
|
||||
| Browser-assisted recognition shell | Implemented now | landed `rubix-cube-solver` `Phase 6R-P` | First-party browser-shell profile, websocket session metadata, stage routing, and manual-edit handoff are live. |
|
||||
| Bounded solve explanation and recommendation shell | Implemented now | landed `rubix-cube-solver` `Phase 6R-Q` | First-party stage-ladder guidance and recommendation-state readout are live after full reconstruction. |
|
||||
| Correction-resolution closure shell | Implemented now | landed shared `Phase 6R-S` packet | First-party accepted-resolution ledger, per-face manual-review acceptance, and solve-guidance reopen/unlock semantics are live above the bounded correction shell. |
|
||||
| Hyper puzzle catalog contract | Implemented now | landed `Hyperspeedcube` `Phase 6R-A` | Narrow retained hyper-puzzle catalog slice is live. |
|
||||
| Hyper notation and replay-log serialization boundary | Implemented now | landed `Hyperspeedcube` `Phase 6R-K` | Narrow retained notation and log-serialization slice is live. |
|
||||
| Hyper replay verification boundary | Implemented now | landed `Hyperspeedcube` `Phase 6R-L` | Narrow retained replay-verification and solve-proof slice is live. |
|
||||
|
|
@ -151,7 +152,7 @@ repo.
|
|||
| Bounded solve explanation/recommendation shell | Implemented now | `rubix-cube-solver` bounded packet | Live stage-ladder recommendation state above the bounded browser recognition shell. |
|
||||
| Provider-backed recognition service contract | Implemented now | first-party recognition client surfaces | First-party normalized recognition session boundary is real. |
|
||||
| Multilingual recognition guidance shell | Deep-source grounded retained | `qbr` retained remainder | Kept deferred until a font-safe and provenance-safe shipping path is explicit. |
|
||||
| Multi-face correction/explanation shell | Implemented now | first-party recognition/training surfaces | Current bounded correction profile, contradiction-aware correction state, and correction-explanation shell are live above the landed `Phase 6R-O`, `Phase 6R-P`, and `Phase 6R-Q` seams. Broader playback/runtime and bundled-asset widening remain deferred. |
|
||||
| Multi-face correction/explanation shell | Implemented now | first-party recognition/training surfaces | Current bounded correction profile, contradiction-aware correction state, accepted-resolution ledger, and correction-explanation / solve-unlock shell are live above the landed `Phase 6R-O`, `Phase 6R-P`, `Phase 6R-Q`, `Phase 6R-R`, and `Phase 6R-S` seams. Bundled-asset, generalized solver-backend, and broad playback/runtime widening remain deferred. |
|
||||
|
||||
### 3. Training, coaching, and progression cockpit
|
||||
|
||||
|
|
@ -187,7 +188,7 @@ repo.
|
|||
| Tiling topology and geometry-family contract | Implemented now | landed `MagicTile` packet | New bounded widening is live. |
|
||||
| Dedicated `120-cell` family runtime profile and persistence boundary | Implemented now | landed `Magic120Cell` packet | Current bounded family-specific widening is live beneath the retained `Hyperspeedcube` runtime anchor. |
|
||||
| Dedicated `5D` family runtime profile and persistence boundary | Implemented now | landed `MagicCube5D` packet | Current bounded family-specific widening is live beneath the retained `Hyperspeedcube` runtime anchor. |
|
||||
| Transform-aware macro remapping and broad non-Euclidean interaction shell | Deep-source grounded retained | `MagicTile` retained remainder | Not yet promoted into live broad interaction ownership. |
|
||||
| Transform-aware macro remapping and broad non-Euclidean interaction shell | Deep-source grounded retained | `MagicTile` retained remainder | Transform-aware macro remapping is the current next bounded retained slice; broad interaction ownership is still deferred. |
|
||||
|
||||
### 7. Speech input and voice sidecars
|
||||
|
||||
|
|
|
|||
|
|
@ -135,9 +135,13 @@ Canonical discovery surfaces for roadmap interpretation:
|
|||
correction/explanation control pass is now consumed
|
||||
- the bounded permissive `Phase 6R-R` shared classic-cube recognition multi-face
|
||||
correction/explanation shell packet is now landed in current code
|
||||
- the current next bounded move is a source-backed follow-on control pass for the retained
|
||||
classic-cube recognition correction/explanation shell remainder, while keeping both the
|
||||
`twistysim.min.js` and `arial-unicode-ms.ttf` redistribution guards explicit
|
||||
- the generic source-backed `Phase 6R-S` shared classic-cube correction-resolution closure
|
||||
control pass is now consumed
|
||||
- the bounded permissive `Phase 6R-S` shared classic-cube correction-resolution closure packet is
|
||||
now landed in current code
|
||||
- the current next bounded move is a source-backed `Phase 6R-T` `roice3/MagicTile`
|
||||
transform-aware macro remapping preparation/control pass, while keeping both classic-cube
|
||||
bundled-asset guards explicit
|
||||
- the repo-row implementation queue is now live from that `Phase 6R-A` entry point rather than
|
||||
waiting on another first-party packet
|
||||
|
||||
|
|
@ -199,15 +203,14 @@ Current routing truth:
|
|||
- active non-live implementation-board rows: `34`
|
||||
- retained benchmark, oracle, or clean-room-later rows outside the active implementation board: `9`
|
||||
|
||||
The next bounded move is a source-backed follow-on control pass for the retained classic-cube
|
||||
recognition correction/explanation shell remainder shared across `kkoomen/qbr` and
|
||||
`vivaansinghvi07/rubix-cube-solver`.
|
||||
The next bounded move is a source-backed `Phase 6R-T` `roice3/MagicTile`
|
||||
transform-aware macro remapping preparation/control pass.
|
||||
|
||||
Queue interpretation after that control pass:
|
||||
|
||||
- then continue with the retained repo-row queue
|
||||
- highest current repo-row queue pressure sits in:
|
||||
- the retained classic-cube recognition shell set
|
||||
- the retained `MagicTile` transform-aware macro remapping remainder
|
||||
- `HactarCE/Hyperspeedcube` is now closed for the currently justified retained row:
|
||||
- landed:
|
||||
- puzzle catalog contract
|
||||
|
|
@ -257,11 +260,13 @@ Queue interpretation after that control pass:
|
|||
- bounded solve explanation/recommendation stage ladder and recommendation state
|
||||
- bounded correction profile, contradiction-aware correction state, and
|
||||
correction-explanation shell routing
|
||||
- correction-resolution ledger, manual-review acceptance, and solve-guidance reopen/unlock
|
||||
semantics
|
||||
- still deferred:
|
||||
- retained correction/explanation shell remainder beyond the landed
|
||||
correction-state slice
|
||||
- bundled `twistysim.min.js` redistribution
|
||||
- after the landed `Phase 6R-R` implementation packet, keep the future legal sequencing guards
|
||||
- generalized solver backend ownership
|
||||
- broad playback-runtime ownership
|
||||
- after the landed `Phase 6R-S` implementation packet, keep the future legal sequencing guards
|
||||
visible:
|
||||
- `vivaansinghvi07/rubix-cube-solver`
|
||||
- do not copy or redistribute `frontend/lib/twistysim.min.js` without preserving or replacing
|
||||
|
|
@ -269,10 +274,12 @@ Queue interpretation after that control pass:
|
|||
- `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
|
||||
- `Phase 6R-R`
|
||||
- `Phase 6R-S`
|
||||
- keep `vivaansinghvi07/rubix-cube-solver` as the retained correction/explanation-semantic
|
||||
owner and preserve `kkoomen/qbr` as the retained capture-state and re-scan adjunct without
|
||||
widening into either bundled asset family or broad playback/runtime ownership
|
||||
reopening the shared correction shell unless a narrower first-party gap is proven above the
|
||||
landed resolution-closure seam or widening into either bundled asset family or broad
|
||||
playback/runtime ownership
|
||||
- `roice3/MagicTile` remains a partially landed row rather than a closed row:
|
||||
- landed:
|
||||
- tiling topology and geometry-family contract
|
||||
|
|
@ -337,11 +344,11 @@ Queue interpretation after that control pass:
|
|||
- viseme / gesture runtime integration
|
||||
- broad assistant-platform scope
|
||||
- the next queue shape is now:
|
||||
- retained classic-cube recognition correction/explanation shell remainder assessment
|
||||
- retained `MagicTile` transform-aware macro remapping assessment
|
||||
- the next bounded move should stay narrow:
|
||||
- a source-backed follow-on control pass before any widening into bundled `twistysim.min.js`
|
||||
redistribution, generalized solver backend ownership, any `qbr` multilingual/font-shipping
|
||||
path, or broad playback-runtime ownership
|
||||
- a source-backed `Phase 6R-T` control pass before any widening into broad non-Euclidean
|
||||
interaction shell, WinForms/OpenTK host ownership, bundled `twistysim.min.js`
|
||||
redistribution, or any `qbr` multilingual/font-shipping path
|
||||
- keep the speech-input / voice sidecar legal sequencing guard visible:
|
||||
- keep code-license judgments separate from model, voice, and payload-license review
|
||||
- keep the provider-neutral speech-lane guard visible:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue