From d28366348ff77ef5a46b9e42b58fa7b638581fd1 Mon Sep 17 00:00:00 2001 From: axiomlogicnexus Date: Wed, 27 May 2026 02:33:48 +0200 Subject: [PATCH] Audit Phase 6R-AG AH and sharpen scramble successor authority --- ...NativeCaptureRouteWorkflowContractTest.cpp | 76 ++++++++ ...RAHNativeCaptureRouteShellContractTest.cpp | 72 ++++++++ ...FACES_DEEP_SOURCE_EVALUATION_2026-05-27.md | 162 ++++++++++++++++++ docs/REPO_LICENSE_TRACKING.md | 28 ++- .../HyperTwist/FEATURE_REGISTRY.md | 1 + 5 files changed, 331 insertions(+), 8 deletions(-) create mode 100644 docs/HYPERTWIST_CUBING_SCRAMBLE_SUCCESSOR_SURFACES_DEEP_SOURCE_EVALUATION_2026-05-27.md diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistWhisperCppPhase6RAGNativeCaptureRouteWorkflowContractTest.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistWhisperCppPhase6RAGNativeCaptureRouteWorkflowContractTest.cpp index 57ee844..c6f49c2 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistWhisperCppPhase6RAGNativeCaptureRouteWorkflowContractTest.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistWhisperCppPhase6RAGNativeCaptureRouteWorkflowContractTest.cpp @@ -145,6 +145,27 @@ namespace HyperTwistWhisperCppPhase6RAGTestInternal SessionState->LastError = TEXT("service-base-url-missing"); } } + + void ForceRetryState( + UHyperTwistTrainingSubsystem* TrainingSubsystem, + const FString& SessionId, + const FString& ErrorText + ) + { + if (FHyperTwistTrainingCompanionSpeechSessionState* SessionState = + ResolveActiveSpeechSessionState(TrainingSubsystem)) + { + SessionState->bSessionOpen = true; + SessionState->ActiveSessionId = SessionId; + SessionState->OpenedAtUtc = FDateTime::UtcNow().ToIso8601(); + SessionState->LastUpdatedAtUtc = SessionState->OpenedAtUtc; + SessionState->SessionConfig = UHyperTwistContractLibrary::MakeSampleSpeechSessionConfig(); + SessionState->SessionConfig.SessionId = SessionId; + SessionState->LastError = ErrorText; + SessionState->ServiceHealth.LastError = ErrorText; + SessionState->ServiceHealth.bReady = false; + } + } } IMPLEMENT_SIMPLE_AUTOMATION_TEST( @@ -345,4 +366,59 @@ bool FHyperTwistWhisperCppPhase6RAGNativeCaptureRouteWorkflowPreparationStateTes return true; } +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FHyperTwistWhisperCppPhase6RAGNativeCaptureRouteWorkflowRetryStateTest, + "HyperTwist.Permissive.WhisperCpp.Phase6R.AG.NativeCaptureRouteWorkflowRetryState", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter +) + +bool FHyperTwistWhisperCppPhase6RAGNativeCaptureRouteWorkflowRetryStateTest::RunTest( + const FString& Parameters +) +{ + UHyperTwistTrainingSubsystem* TrainingSubsystem = + HyperTwistWhisperCppPhase6RAGTestInternal::MakeSpeechSubsystem( + TEXT("phase6r-ag-retry-session"), + TEXT("http-sidecar") + ); + TestNotNull(TEXT("The speech subsystem must be constructed for the retry workflow test."), TrainingSubsystem); + if (TrainingSubsystem == nullptr) + { + return false; + } + + UHyperTwistHttpSpeechClient* HttpSpeechClient = + HyperTwistWhisperCppPhase6RAGTestInternal::ResolveHttpSpeechClient(TrainingSubsystem); + TestNotNull(TEXT("The provider-backed speech client must be available for the retry workflow test."), HttpSpeechClient); + if (HttpSpeechClient == nullptr) + { + return false; + } + + HttpSpeechClient->RequestTimeoutSeconds = 0.25f; + HyperTwistWhisperCppPhase6RAGTestInternal::ForceRetryState( + TrainingSubsystem, + TEXT("phase6r-ag-retry-session"), + TEXT("request-failed") + ); + TrainingSubsystem->RefreshCompanionSpeechServiceHealthForAutomation(); + + const FHyperTwistSpeechNativeCaptureRouteWorkflowState& WorkflowState = + TrainingSubsystem->GetActiveCompanionSpeechSessionState().NativeCaptureRouteWorkflowState; + + TestTrue(TEXT("The retry-required native capture-route workflow state must remain structurally valid."), WorkflowState.IsStructurallyValid()); + TestEqual(TEXT("The retry-required workflow must preserve the retry workflow state id."), WorkflowState.WorkflowStateId, TEXT("capture-route-retry-required")); + TestEqual(TEXT("The retry-required workflow must preserve the retry capture-route posture."), WorkflowState.CaptureRouteStateId, TEXT("route-retry-required")); + TestEqual(TEXT("The retry-required workflow must preserve the retry source kind."), WorkflowState.LatestSourceKind, TEXT("capture-route-retry-required")); + TestFalse(TEXT("The retry-required workflow must clear ownership confirmation."), WorkflowState.bRouteOwnershipConfirmed); + TestFalse(TEXT("The retry-required workflow must block workflow-ready posture."), WorkflowState.bWorkflowReady); + TestTrue(TEXT("The retry-required workflow must surface the retry action."), WorkflowState.bPreparationRetryVisible); + TestEqual(TEXT("The retry-required workflow must retain one workflow entry."), WorkflowState.WorkflowEntryCount, 1); + TestEqual(TEXT("The retry-required workflow must retain one retry entry."), WorkflowState.RouteRetryEntryCount, 1); + TestEqual(TEXT("The retry-required workflow must classify the active issue correctly."), WorkflowState.ActiveIssue.IssueKind, TEXT("capture-route-retry-required")); + TestEqual(TEXT("The retry-required workflow must recommend the bounded retry action."), WorkflowState.ActiveIssue.RecommendedActionId, TEXT("retry-capture-route")); + TestEqual(TEXT("The retry-required workflow must preserve the provider-backed transport failure."), WorkflowState.LastRouteError, TEXT("request-failed")); + return true; +} + #endif diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistWhisperCppPhase6RAHNativeCaptureRouteShellContractTest.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistWhisperCppPhase6RAHNativeCaptureRouteShellContractTest.cpp index 539aee7..831d799 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistWhisperCppPhase6RAHNativeCaptureRouteShellContractTest.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistWhisperCppPhase6RAHNativeCaptureRouteShellContractTest.cpp @@ -146,6 +146,27 @@ namespace HyperTwistWhisperCppPhase6RAHTestInternal } } + void ForceRetryState( + UHyperTwistTrainingSubsystem* TrainingSubsystem, + const FString& SessionId, + const FString& ErrorText + ) + { + if (FHyperTwistTrainingCompanionSpeechSessionState* SessionState = + ResolveActiveSpeechSessionState(TrainingSubsystem)) + { + SessionState->bSessionOpen = true; + SessionState->ActiveSessionId = SessionId; + SessionState->OpenedAtUtc = FDateTime::UtcNow().ToIso8601(); + SessionState->LastUpdatedAtUtc = SessionState->OpenedAtUtc; + SessionState->SessionConfig = UHyperTwistContractLibrary::MakeSampleSpeechSessionConfig(); + SessionState->SessionConfig.SessionId = SessionId; + SessionState->LastError = ErrorText; + SessionState->ServiceHealth.LastError = ErrorText; + SessionState->ServiceHealth.bReady = false; + } + } + bool ContainsPanelId( const TArray& Panels, const FString& ExpectedPanelId @@ -361,4 +382,55 @@ bool FHyperTwistWhisperCppPhase6RAHNativeCaptureRouteShellPreparationStateTest:: return true; } +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FHyperTwistWhisperCppPhase6RAHNativeCaptureRouteShellRetryStateTest, + "HyperTwist.Permissive.WhisperCpp.Phase6R.AH.NativeCaptureRouteShellRetryState", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter +) + +bool FHyperTwistWhisperCppPhase6RAHNativeCaptureRouteShellRetryStateTest::RunTest( + const FString& Parameters +) +{ + UHyperTwistTrainingSubsystem* TrainingSubsystem = + HyperTwistWhisperCppPhase6RAHTestInternal::MakeSpeechSubsystem( + TEXT("phase6r-ah-retry-session"), + TEXT("http-sidecar") + ); + TestNotNull(TEXT("The speech subsystem must be constructed for the retry shell test."), TrainingSubsystem); + if (TrainingSubsystem == nullptr) + { + return false; + } + + UHyperTwistHttpSpeechClient* HttpSpeechClient = + HyperTwistWhisperCppPhase6RAHTestInternal::ResolveHttpSpeechClient(TrainingSubsystem); + TestNotNull(TEXT("The provider-backed speech client must be available for the retry shell test."), HttpSpeechClient); + if (HttpSpeechClient == nullptr) + { + return false; + } + + HttpSpeechClient->RequestTimeoutSeconds = 0.25f; + HyperTwistWhisperCppPhase6RAHTestInternal::ForceRetryState( + TrainingSubsystem, + TEXT("phase6r-ah-retry-session"), + TEXT("request-failed") + ); + TrainingSubsystem->RefreshCompanionSpeechServiceHealthForAutomation(); + + const FHyperTwistSpeechNativeCaptureRouteShellState& ShellState = + TrainingSubsystem->GetActiveCompanionSpeechSessionState().NativeCaptureRouteShellState; + + TestTrue(TEXT("The retry-required native capture-route shell state must remain structurally valid."), ShellState.IsStructurallyValid()); + TestEqual(TEXT("The shell must preserve the retry workflow state id."), ShellState.WorkflowStateId, TEXT("capture-route-retry-required")); + TestEqual(TEXT("The shell must preserve the retry capture-route posture."), ShellState.CaptureRouteStateId, TEXT("route-retry-required")); + TestTrue(TEXT("The shell must surface the preparation card for route retry."), ShellState.bPreparationCardVisible); + TestTrue(TEXT("The shell must surface the retry action."), ShellState.bPreparationRetryVisible); + TestEqual(TEXT("The shell must classify the active issue correctly."), ShellState.ActiveIssue.IssueKind, TEXT("capture-route-retry-required")); + TestTrue(TEXT("The shell must preserve the bounded retry action."), ShellState.AvailableActionIds.Contains(TEXT("retry-capture-route"))); + TestEqual(TEXT("The shell must preserve the provider-backed transport failure."), ShellState.LastRouteError, TEXT("request-failed")); + return true; +} + #endif diff --git a/docs/HYPERTWIST_CUBING_SCRAMBLE_SUCCESSOR_SURFACES_DEEP_SOURCE_EVALUATION_2026-05-27.md b/docs/HYPERTWIST_CUBING_SCRAMBLE_SUCCESSOR_SURFACES_DEEP_SOURCE_EVALUATION_2026-05-27.md new file mode 100644 index 0000000..adeca58 --- /dev/null +++ b/docs/HYPERTWIST_CUBING_SCRAMBLE_SUCCESSOR_SURFACES_DEEP_SOURCE_EVALUATION_2026-05-27.md @@ -0,0 +1,162 @@ +# HyperTwist Cubing Scramble Successor Surfaces Deep-Source Evaluation - 2026-05-27 + +## Status + +This document is the source-backed evaluation note for the retained cubing +scramble successor surfaces: + +- `cubing/mark3` +- `cubing/scramble.cubing.net` +- `cubing/scramble-display` + +It answers one narrow question: + +- do these successor repos displace the already retained `cubing/cubing.js` + and `cubing/twisty.js` ownership lanes for scramble generation or + scramble-operator shells + +They do not. + +## Source basis + +- `C:\Workspaces\HyperTwist\mirrors\permissive\cubing\cubing.js\src\cubing\scramble\index.ts` +- `C:\Workspaces\HyperTwist\mirrors\permissive\cubing\cubing.js\src\cubing\search\cubing-private.ts` +- `C:\Workspaces\HyperTwist\mirrors\permissive\cubing\cubing.js\src\cubing\search\outside.ts` +- `C:\Workspaces\HyperTwist\mirrors\restrictive\cubing\mark3\README.md` +- `C:\Workspaces\HyperTwist\mirrors\restrictive\cubing\mark3\package.json` +- `C:\Workspaces\HyperTwist\mirrors\restrictive\cubing\mark3\src\scramble-generation\index.ts` +- `C:\Workspaces\HyperTwist\mirrors\restrictive\cubing\mark3\src\fixtures\testCompetitionScramblesSpec.ts` +- `C:\Workspaces\HyperTwist\mirrors\restrictive\cubing\scramble.cubing.net\README.md` +- `C:\Workspaces\HyperTwist\mirrors\restrictive\cubing\scramble.cubing.net\package.json` +- `C:\Workspaces\HyperTwist\mirrors\restrictive\cubing\scramble.cubing.net\src\scramble.ts` +- `C:\Workspaces\HyperTwist\mirrors\restrictive\cubing\scramble-display\README.md` +- `C:\Workspaces\HyperTwist\mirrors\restrictive\cubing\scramble-display\src\scramble-display\ScrambleDisplay.ts` + +## Slice-local verdict + +| Slice | Primary authority | Secondary value kept | Route | Width | Result | +|---|---|---|---|---|---| +| Random-state scramble engine and event scramble API | `cubing/cubing.js` | `cubing/mark3`, `cubing/scramble.cubing.net` | existing retained route | existing retained width | unchanged | +| Seeded competition, round, set, and attempt scramble workflow expectations | `cubing/cubing.js` for the engine contract | `cubing/mark3` as fixture/workflow adjunct | `R3` for `mark3` | `F2` | keep `mark3` as bounded adjunct only | +| Public scramble operator shell behavior | `cubing/cubing.js` + `cubing/twisty.js` for engine and visualization seams | `cubing/scramble.cubing.net` as operator-shell adjunct | `R3` for `scramble.cubing.net` | `F2` | keep as bounded shell reference only | +| Lightweight scramble display wrapper behavior | `cubing/twisty.js` | `cubing/scramble-display` as comparison/reference wrapper | `R3` for `scramble-display` | `F2` | keep as comparison surface only | + +## Why the ownership does not flip + +### `cubing/mark3` + +`mark3` does not replace `cubing/cubing.js` for scramble generation. + +The current source imports `randomScrambleForEvent` from `cubing/scramble` and +uses it directly inside the round/set/attempt loop. The `README.md` also marks +seed derivation as future work, and `src/scramble-generation/index.ts` still +contains a `TODO` comment for that derivation path. + +Retained value that survives: + +- competition/WCIF-shaped scramble generation workflow +- round/set/attempt traversal shape +- seeded derivation intent and fixture framing + +Value that does not survive as owner displacement: + +- the actual scramble engine +- event scramble correctness ownership +- scramble API ownership + +Working classification: + +- `A2` adjunct donor for competition scramble workflow expectations +- `R3` clean-room route because the row remains restrictive custody +- `F2` only; no broad scramble-engine promotion + +### `cubing/scramble.cubing.net` + +`scramble.cubing.net` does not replace `cubing/cubing.js` or `cubing/twisty.js` +for the underlying scramble or visualization seams. + +The current source imports `randomScrambleForEvent` from `cubing/scramble`, +imports `cubing/twisty`, binds event selection and URL parameters in the shell, +and uses those existing seams to present a public scramble operator surface. + +Retained value that survives: + +- event-selection behavior +- refresh/rescramble workflow +- URL-state and view-option behavior +- copy-to-clipboard and lightweight operator-shell posture + +Value that does not survive as owner displacement: + +- scramble engine ownership +- puzzle visualization ownership +- general command-surface ownership for HyperTwist + +Working classification: + +- `A2` adjunct donor for public scramble operator-shell behavior +- `R3` clean-room route because the row remains restrictive custody +- `F2` only; no shell-family widening by default + +### `cubing/scramble-display` + +`scramble-display` is a convenience wrapper above `cubing/twisty`, not a new +display owner lane. + +The current custom element maps `event` to a `TwistyPlayer`, applies +visualization and background convenience properties, and forwards scramble text +into the already retained visualization seam. + +Working classification: + +- `A3` reference authority for wrapper convenience only +- `R3` clean-room route because the row remains restrictive custody +- `F2` only; comparison surface, not owner displacement + +## Propagation result + +### Feature registry + +Updated. + +The registry now keeps a narrow retained row for seeded competition scramble +workflow and lightweight scramble-operator-shell adjuncts while preserving +`cubing/cubing.js` and `cubing/twisty.js` as the deeper owners. + +### Cross-lane doctrine + +No doctrine wording change was needed. + +The current doctrine already covers this outcome: + +- later repos only displace the exact stronger slice +- partial successors stay bounded adjuncts or references + +### Retroactive backfill + +No selective reopening of earlier packet authority was required. + +Reason: + +- no earlier `A1` winner was displaced +- this pass only sharpened successor-row interpretation and retained adjunct + value + +### Skillization + +No doctrine or `SKILLS.md` change was required. + +Reason: + +- these repos do not create a first-party HyperTwist command surface +- they do not justify a live skill family by themselves +- any future scramble helper remains command-contract pending until a + first-party scramble command exists + +### Legal evidence + +No custody or license-status change occurred in this pass. + +The legal tracker and manifest rows were sharpened to reflect the source-backed +upper-surface split, and the generated legal-evidence bundle remained a +verification surface rather than a changed policy surface. diff --git a/docs/REPO_LICENSE_TRACKING.md b/docs/REPO_LICENSE_TRACKING.md index ce2705d..810bf18 100644 --- a/docs/REPO_LICENSE_TRACKING.md +++ b/docs/REPO_LICENSE_TRACKING.md @@ -750,7 +750,7 @@ Current licensing judgment: - the checked `package.json` does not declare a repo license - treat the row as restrictive custody and `license-missing` - direct donor use is not cleared -- retain as a scramble-generation clean-room candidate only +- retain as a restrictive upper-surface adjunct only Source basis: @@ -769,10 +769,13 @@ Practical obligations: Approved working posture: -- retain as a scramble-generation architecture reference and clean-room - candidate only -- use it for source inspection, seeded workflow reference, and independently - owned reimplementation planning +- retain as a seeded competition / round / attempt workflow adjunct above the + already retained `cubing/cubing.js` scramble engine +- use it for source inspection, WCIF-shaped fixture comparison, and + independently owned reimplementation planning +- do not treat it as scramble-engine ownership, because the current source + delegates actual scramble generation to `cubing/scramble` and still leaves + seed derivation as `TODO` - do not widen from the mirror as a normal permissive donor lane ### `cubing/scramble.cubing.net` @@ -810,9 +813,14 @@ Practical obligations: Approved working posture: -- retain as a scramble-webapp behavior reference and clean-room candidate only +- retain as a public scramble operator-shell adjunct above the already retained + `cubing/cubing.js` and `cubing/twisty.js` seams - use it for source inspection, event-selection UX reference, refresh-workflow - comparison, and independently owned reimplementation planning + comparison, URL-state behavior, and independently owned reimplementation + planning +- do not treat it as scramble-engine or visualization ownership, because the + current source imports `randomScrambleForEvent` from `cubing/scramble` and + uses `cubing/twisty` for the player shell - do not widen from the mirror as a normal permissive or direct-integration lane @@ -848,7 +856,11 @@ Practical obligations: Approved working posture: -- retain as a scramble-visualization comparison surface only +- retain as a scramble-display comparison surface only +- use it as a wrapper-convenience reference above the already retained + `cubing/twisty.js` visualization seam +- do not treat it as a new visualization owner lane, because the current + custom element is a thin `TwistyPlayer` wrapper - use it for source inspection, display-shell behavior reference, and bounded clean-room planning if a first-party equivalent is ever needed - do not widen from the mirror as a normal permissive donor lane diff --git a/docs/v6_5_deep_manual_pack/HyperTwist/FEATURE_REGISTRY.md b/docs/v6_5_deep_manual_pack/HyperTwist/FEATURE_REGISTRY.md index a99e648..d6d0401 100644 --- a/docs/v6_5_deep_manual_pack/HyperTwist/FEATURE_REGISTRY.md +++ b/docs/v6_5_deep_manual_pack/HyperTwist/FEATURE_REGISTRY.md @@ -150,6 +150,7 @@ repo. |---|---|---|---| | Native puzzle-state runtime | Implemented now | first-party runtime + landed donor packets | Core product identity. | | Classic-cubing semantic/runtime adapter | Implemented now | landed `cubing/cubing.js` packet | Live adapter family. | +| Seeded competition scramble workflow and lightweight scramble-operator shell adjuncts | Deep-source grounded retained | `cubing/cubing.js` retained lane + `cubing/mark3` / `cubing/scramble.cubing.net` successor evaluation | Source-backed successor surfaces sharpen competition-spec workflow and operator-shell expectations above the retained scramble and visualization seams, but they do not displace `cubing/cubing.js` or `cubing/twisty.js`; `scramble-display` remains comparison-only. | | Replay shell and timeline | Implemented now | landed `cubing/twisty.js` bounded packets | Replay/runtime viewer family is real. | | Algorithm/training semantic lane | Implemented now | landed `cubing/alg.js` bounded packets | Semantic/training contract is real. | | Hyper puzzle catalog | Implemented now | `Hyperspeedcube` bounded packet | Current realized hyper-puzzle entry slice. |