From 10df9596e09d399619d1babdabee5028eb8f98e1 Mon Sep 17 00:00:00 2001 From: axiomlogicnexus Date: Fri, 29 May 2026 08:55:33 +0200 Subject: [PATCH] Implement Phase S4-B browser diagnostics skills --- .../HyperTwistContractLibrary.cpp | 54 ++++ .../HyperTwistSkillCoreLibrary.cpp | 296 +++++++++++++++++- .../HyperTwistContractLibrary.h | 14 + .../HyperTwistSkillCoreLibrary.h | 8 + .../HyperTwistSkills/HyperTwistSkillTypes.h | 295 +++++++++++++++++ ...llPhaseS1ARegistryManifestContractTest.cpp | 35 ++- ...PhaseS1BSettingsVisibilityContractTest.cpp | 30 +- ...seS1CInvocationAuditLedgerContractTest.cpp | 27 +- ...AuthoringValidationHarnessContractTest.cpp | 19 ++ ...PhaseS4BBrowserDiagnosticsContractTest.cpp | 204 ++++++++++++ ...SKILLS_IMPLEMENTATION_PACKET_2026-05-29.md | 35 +++ ...CS_SKILLS_PREPARATION_PACKET_2026-05-29.md | 40 +++ ...PERTWIST_IMPLEMENTATION_PHASE_1_KICKOFF.md | 4 +- ...AND_COMMAND_SURFACE_DOCTRINE_2026-05-21.md | 18 +- .../HyperTwist/ARCHITECTURE.md | 7 +- .../HyperTwist/FEATURE_REGISTRY.md | 5 +- .../HyperTwist/PROVENANCE_AND_TRUST_MODEL.md | 7 +- .../HyperTwist/ROADMAP.md | 4 +- .../HyperTwist/SKILLS.md | 9 +- 19 files changed, 1078 insertions(+), 33 deletions(-) create mode 100644 UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS4BBrowserDiagnosticsContractTest.cpp create mode 100644 docs/arch/HYPERTWIST_PHASES4_B_FIRST_PARTY_BROWSER_DIAGNOSTICS_SKILLS_IMPLEMENTATION_PACKET_2026-05-29.md create mode 100644 docs/arch/HYPERTWIST_PHASES4_B_FIRST_PARTY_BROWSER_DIAGNOSTICS_SKILLS_PREPARATION_PACKET_2026-05-29.md diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistBootstrap/HyperTwistContractLibrary.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistBootstrap/HyperTwistContractLibrary.cpp index 6d57009..be2d0eb 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistBootstrap/HyperTwistContractLibrary.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistBootstrap/HyperTwistContractLibrary.cpp @@ -131,6 +131,22 @@ namespace HyperTwistContractLibraryInternal return OverrideState; }(), []() + { + FHyperTwistSkillControlOverride OverrideState; + OverrideState.SkillId = TEXT("skill/capture-browser-trace"); + OverrideState.bHasEnabledOverride = true; + OverrideState.bEnabled = true; + return OverrideState; + }(), + []() + { + FHyperTwistSkillControlOverride OverrideState; + OverrideState.SkillId = TEXT("skill/discover-browser-api"); + OverrideState.bHasEnabledOverride = true; + OverrideState.bEnabled = true; + return OverrideState; + }(), + []() { FHyperTwistSkillControlOverride OverrideState; OverrideState.SkillId = TEXT("skill/provider-routing-inspector"); @@ -4196,6 +4212,24 @@ UHyperTwistContractLibrary::MakeSampleSkillExtractionState() ); } +FHyperTwistSkillBrowserDiagnosticsState +UHyperTwistContractLibrary::MakeSampleSkillBrowserDiagnosticsState() +{ + const FHyperTwistSkillRegistryState RegistryState = MakeSampleSkillRegistryState(); + const FHyperTwistSkillControlState ControlState = MakeSampleSkillControlState(); + const FHyperTwistSkillAuthoringHarnessState AuthoringHarnessState = + MakeSampleSkillAuthoringHarnessState(); + const FHyperTwistSkillExtractionState ExtractionState = + MakeSampleSkillExtractionState(); + + return UHyperTwistSkillCoreLibrary::DeriveSkillBrowserDiagnosticsState( + RegistryState, + ControlState, + AuthoringHarnessState, + ExtractionState + ); +} + FHyperTwistTrainingRepositoryIntegrityReport UHyperTwistContractLibrary::MakeSampleTrainingRepositoryIntegrityReport() { FHyperTwistTrainingRepositoryState RepositoryState = MakeSampleTrainingRepositoryState(); @@ -5404,6 +5438,15 @@ FString UHyperTwistContractLibrary::SerializeSkillExtractionStateToJson( ); } +FString UHyperTwistContractLibrary::SerializeSkillBrowserDiagnosticsStateToJson( + const FHyperTwistSkillBrowserDiagnosticsState& SkillBrowserDiagnosticsState +) +{ + return HyperTwistContractLibraryInternal::SerializeStructToJson( + SkillBrowserDiagnosticsState + ); +} + FString UHyperTwistContractLibrary::SerializeTrainingTimerExportPacketToJson( const FHyperTwistTrainingTimerExportPacket& TimerExportPacket ) @@ -5647,6 +5690,17 @@ bool UHyperTwistContractLibrary::DeserializeSkillExtractionStateFromJson( ); } +bool UHyperTwistContractLibrary::DeserializeSkillBrowserDiagnosticsStateFromJson( + const FString& Json, + FHyperTwistSkillBrowserDiagnosticsState& OutSkillBrowserDiagnosticsState +) +{ + return HyperTwistContractLibraryInternal::DeserializeStructFromJson( + Json, + OutSkillBrowserDiagnosticsState + ); +} + bool UHyperTwistContractLibrary::DeserializeTrainingTimerExportPacketFromJson( const FString& Json, FHyperTwistTrainingTimerExportPacket& OutTimerExportPacket diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistSkills/HyperTwistSkillCoreLibrary.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistSkills/HyperTwistSkillCoreLibrary.cpp index f539ab9..51dcce1 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistSkills/HyperTwistSkillCoreLibrary.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistSkills/HyperTwistSkillCoreLibrary.cpp @@ -461,6 +461,12 @@ namespace HyperTwistSkillCoreLibraryInternal || SkillId == TEXT("skill/extract-design-spec"); } + bool IsBrowserDiagnosticsSkill(const FString& SkillId) + { + return SkillId == TEXT("skill/capture-browser-trace") + || SkillId == TEXT("skill/discover-browser-api"); + } + bool HasAtLeastCleanRoomCommandContractStatus(const EHyperTwistSkillStatus Status) { return Status == EHyperTwistSkillStatus::CleanRoomCommandContractSpecified @@ -694,6 +700,12 @@ namespace HyperTwistSkillCoreLibraryInternal return EHyperTwistSkillInvocationOutcome::Succeeded; } + if (Entry.SkillId == TEXT("skill/capture-browser-trace") + || Entry.SkillId == TEXT("skill/discover-browser-api")) + { + return EHyperTwistSkillInvocationOutcome::Succeeded; + } + return EHyperTwistSkillInvocationOutcome::Failed; } @@ -1492,6 +1504,88 @@ namespace HyperTwistSkillCoreLibraryInternal ), TEXT("Landed first-party structured design-spec extraction skill over authoritative HyperTwist design and packet surfaces.") ), + MakeSkillEntry( + TEXT("skill/capture-browser-trace"), + TEXT("Capture Browser Trace"), + TEXT("lane/skillization/browser-docs-design"), + TEXT("feature/skills/capture-browser-trace"), + EHyperTwistSkillFamily::BrowserDocsDesign, + EHyperTwistSkillStatus::ImplementedNow, + false, + true, + { + MakeCommandBinding( + TEXT("command/skills/capture-browser-trace"), + TEXT("service/skills/capture-browser-trace"), + TEXT("feature/skills/capture-browser-trace"), + TEXT("browser/trace-capture"), + true, + TEXT("Live first-party bounded browser trace-capture skill above the landed docs/design extraction seam.") + ) + }, + { + MakePermissionScope( + TEXT("scope/skills/browser-diagnostics"), + TEXT("Browser Diagnostics"), + false, + false, + false, + false, + true, + false, + true, + TEXT("Reads first-party browser, service, and packet surfaces to emit bounded browser trace diagnostics.") + ) + }, + MakeProvenanceDeclaration( + EHyperTwistSkillLogPolicy::InvocationLedgerRequired, + {TEXT("artifact/browser-trace-capture-brief")}, + true, + TEXT("Browser trace output must remain provenance-visible, derived-only, and bounded to diagnostics.") + ), + TEXT("Landed first-party bounded browser trace-capture skill above the extraction seam.") + ), + MakeSkillEntry( + TEXT("skill/discover-browser-api"), + TEXT("Discover Browser API"), + TEXT("lane/skillization/browser-docs-design"), + TEXT("feature/skills/discover-browser-api"), + EHyperTwistSkillFamily::BrowserDocsDesign, + EHyperTwistSkillStatus::ImplementedNow, + false, + true, + { + MakeCommandBinding( + TEXT("command/skills/discover-browser-api"), + TEXT("service/skills/discover-browser-api"), + TEXT("feature/skills/discover-browser-api"), + TEXT("browser/api-discovery"), + true, + TEXT("Live first-party bounded browser/API discovery skill above the landed docs/design extraction seam.") + ) + }, + { + MakePermissionScope( + TEXT("scope/skills/browser-diagnostics"), + TEXT("Browser Diagnostics"), + false, + false, + false, + false, + true, + false, + true, + TEXT("Reads first-party browser, service, and packet surfaces to emit bounded browser/API discovery output.") + ) + }, + MakeProvenanceDeclaration( + EHyperTwistSkillLogPolicy::InvocationLedgerRequired, + {TEXT("artifact/browser-api-discovery-brief")}, + true, + TEXT("Browser/API discovery output must remain provenance-visible, derived-only, and separate from design translation.") + ), + TEXT("Landed first-party bounded browser/API discovery skill above the extraction seam.") + ), MakeSkillEntry( TEXT("skill/provider-routing-inspector"), TEXT("Provider Routing Inspector"), @@ -1630,7 +1724,7 @@ namespace HyperTwistSkillCoreLibraryInternal RegistryState.bNoAdHocMetadataRequired = true; RegistryState.StatusCounts = { - MakeStatusCount(EHyperTwistSkillStatus::ImplementedNow, 12), + MakeStatusCount(EHyperTwistSkillStatus::ImplementedNow, 14), MakeStatusCount(EHyperTwistSkillStatus::CommandContractPending, 1), MakeStatusCount(EHyperTwistSkillStatus::CleanRoomSkillSpecSpecified, 1), MakeStatusCount(EHyperTwistSkillStatus::PlaceholderFamily, 1) @@ -1642,7 +1736,7 @@ namespace HyperTwistSkillCoreLibraryInternal MakeFamilyCount(EHyperTwistSkillFamily::MemoryContinuity, 8), MakeFamilyCount(EHyperTwistSkillFamily::ProviderOperations, 1), MakeFamilyCount(EHyperTwistSkillFamily::TrainingCoaching, 1), - MakeFamilyCount(EHyperTwistSkillFamily::BrowserDocsDesign, 2), + MakeFamilyCount(EHyperTwistSkillFamily::BrowserDocsDesign, 4), MakeFamilyCount(EHyperTwistSkillFamily::DomainCreative, 1) }; @@ -3331,3 +3425,201 @@ UHyperTwistSkillCoreLibrary::DeriveSkillExtractionState( return ExtractionState; } + +FHyperTwistSkillBrowserDiagnosticsState +UHyperTwistSkillCoreLibrary::DeriveSkillBrowserDiagnosticsState( + const FHyperTwistSkillRegistryState& RegistryState, + const FHyperTwistSkillControlState& ControlState, + const FHyperTwistSkillAuthoringHarnessState& AuthoringHarnessState, + const FHyperTwistSkillExtractionState& ExtractionState +) +{ + using namespace HyperTwistSkillCoreLibraryInternal; + + if (!RegistryState.IsStructurallyValid() + || !ControlState.IsStructurallyValid() + || !AuthoringHarnessState.IsStructurallyValid() + || !ExtractionState.IsStructurallyValid() + || RegistryState.RegistryId != ControlState.RegistryId + || RegistryState.RegistryId != AuthoringHarnessState.RegistryId + || RegistryState.RegistryId != ExtractionState.RegistryId + || RegistryState.CommandSurfaceRootId != ControlState.CommandSurfaceRootId + || RegistryState.CommandSurfaceRootId != AuthoringHarnessState.CommandSurfaceRootId + || RegistryState.CommandSurfaceRootId != ExtractionState.CommandSurfaceRootId) + { + return FHyperTwistSkillBrowserDiagnosticsState(); + } + + FHyperTwistSkillBrowserDiagnosticsState DiagnosticsState; + DiagnosticsState.RegistryId = RegistryState.RegistryId; + DiagnosticsState.ManifestVersion = TEXT("s4b-v1"); + DiagnosticsState.ReferenceUtc = TEXT("2026-05-29T10:40:00Z"); + DiagnosticsState.CommandSurfaceRootId = RegistryState.CommandSurfaceRootId; + DiagnosticsState.TemplateVersion = TEXT("skill-browser-diagnostics-v1"); + DiagnosticsState.bEveryLiveSkillReadsAuthoritativeBrowserAndDocSurfaces = true; + DiagnosticsState.bEverySkillPreservesOptionalAssistiveOffState = true; + DiagnosticsState.bEveryLiveSkillHasValidationHarnessCoverage = true; + DiagnosticsState.bDiagnosticsRemainBounded = true; + DiagnosticsState.bEverySkillRequiresExtractionSubstrate = true; + DiagnosticsState.bNoDesignTranslationWidening = true; + DiagnosticsState.Summary = + TEXT("First-party browser diagnostics skill layer above the landed docs/design extraction seam."); + + auto AddPreviewHeadline = []( + TArray& PreviewHeadlines, + const FString& Headline + ) + { + if (!Headline.IsEmpty()) + { + PreviewHeadlines.AddUnique(Headline); + } + }; + + auto ExtractionSkillExists = [&ExtractionState](const FString& SkillId) + { + for (const FHyperTwistSkillExtractionSkill& SkillState : ExtractionState.Skills) + { + if (SkillState.SkillId == SkillId && SkillState.IsStructurallyValid()) + { + return true; + } + } + + return false; + }; + + auto BuildBrowserDiagnosticSkill = [&]( + const FString& SkillId + ) -> FHyperTwistSkillBrowserDiagnosticSkill + { + const FHyperTwistSkillManifestEntry* Entry = + FindManifestEntryById(RegistryState, SkillId); + const FHyperTwistSkillControlStateEntry* ControlEntry = + FindControlStateEntryById(ControlState, SkillId); + const FHyperTwistSkillAuthoringExampleState* ExampleState = + FindAuthoringExampleBySkillId(AuthoringHarnessState, SkillId); + if (Entry == nullptr + || !Entry->IsStructurallyValid() + || !IsBrowserDiagnosticsSkill(SkillId) + || ControlEntry == nullptr + || !ControlEntry->IsStructurallyValid() + || !ControlEntry->bInstalled + || !ControlEntry->bOptionalAssistive + || ExampleState == nullptr + || !ExampleState->IsStructurallyValid() + || !HasLiveEvalValidationCase(AuthoringHarnessState, SkillId) + || !ExtractionSkillExists(TEXT("skill/extract-docs")) + || !ExtractionSkillExists(TEXT("skill/extract-design-spec"))) + { + return FHyperTwistSkillBrowserDiagnosticSkill(); + } + + FHyperTwistSkillBrowserDiagnosticSkill SkillState; + SkillState.SkillId = Entry->SkillId; + SkillState.DisplayLabel = Entry->DisplayLabel; + SkillState.CommandSurfaceId = Entry->CommandBindings[0].CommandSurfaceId; + SkillState.ServiceBindingId = Entry->CommandBindings[0].ServiceBindingId; + SkillState.OwnerLaneId = Entry->OwnerLaneId; + SkillState.OwnerFeatureId = Entry->OwnerFeatureId; + SkillState.Status = Entry->Status; + SkillState.PermissionScopeIds = MakePermissionScopeIds(*Entry); + SkillState.RequiredExtractionSkillIds = { + TEXT("skill/extract-docs"), + TEXT("skill/extract-design-spec") + }; + SkillState.OutputArtifactKinds = Entry->Provenance.ProducedArtifactKinds; + SkillState.bLiveSkill = true; + SkillState.bReadsAuthoritativeBrowserAndDocSurfaces = true; + SkillState.bAvailableNow = true; + SkillState.bRequiresOwnerActivation = false; + SkillState.bPreservesOptionalAssistiveOffState = ControlEntry->bInertWhenDisabled; + SkillState.bDerivedAssistiveOnly = Entry->bOptionalAssistive; + SkillState.bHasValidationHarnessCoverage = true; + SkillState.bBoundedToDiagnosticsOnly = true; + SkillState.bRequiresExtractionSubstrate = true; + SkillState.bAvoidsDesignTranslationWidening = true; + + if (SkillId == TEXT("skill/capture-browser-trace")) + { + SkillState.SourceSurfaceIds = { + TEXT("source-surface/browser-diagnostics-packet"), + TEXT("source-surface/architecture-manual"), + TEXT("source-surface/skills-manual"), + TEXT("source-surface/provenance-and-trust-model"), + TEXT("source-surface/extraction-state") + }; + AddPreviewHeadline(SkillState.PreviewHeadlines, TEXT("Browser trace readiness")); + AddPreviewHeadline(SkillState.PreviewHeadlines, TEXT("Trace-capture prerequisites")); + AddPreviewHeadline(SkillState.PreviewHeadlines, TEXT("Bounded diagnostics trace output")); + SkillState.bCapturesBrowserTrace = true; + SkillState.bPerformsBrowserApiDiscovery = false; + SkillState.Summary = + TEXT("Live first-party bounded browser trace-capture skill above the landed extraction seam."); + } + else if (SkillId == TEXT("skill/discover-browser-api")) + { + SkillState.SourceSurfaceIds = { + TEXT("source-surface/browser-api-contracts"), + TEXT("source-surface/browser-diagnostics-packet"), + TEXT("source-surface/skills-manual"), + TEXT("source-surface/provenance-and-trust-model"), + TEXT("source-surface/extraction-state") + }; + AddPreviewHeadline(SkillState.PreviewHeadlines, TEXT("Browser/API discovery readiness")); + AddPreviewHeadline(SkillState.PreviewHeadlines, TEXT("Diagnostic API surface extraction")); + AddPreviewHeadline(SkillState.PreviewHeadlines, TEXT("Bounded browser/API discovery output")); + SkillState.bCapturesBrowserTrace = false; + SkillState.bPerformsBrowserApiDiscovery = true; + SkillState.Summary = + TEXT("Live first-party bounded browser/API discovery skill above the landed extraction seam."); + } + + SkillState.SourceSurfaceCount = SkillState.SourceSurfaceIds.Num(); + SkillState.RequiredExtractionSkillCount = SkillState.RequiredExtractionSkillIds.Num(); + return SkillState; + }; + + for (const FString& SkillId : { + FString(TEXT("skill/capture-browser-trace")), + FString(TEXT("skill/discover-browser-api")) + }) + { + const FHyperTwistSkillBrowserDiagnosticSkill SkillState = + BuildBrowserDiagnosticSkill(SkillId); + if (!SkillState.IsStructurallyValid()) + { + return FHyperTwistSkillBrowserDiagnosticsState(); + } + + DiagnosticsState.Skills.Add(SkillState); + } + + for (const FHyperTwistSkillBrowserDiagnosticSkill& SkillState : DiagnosticsState.Skills) + { + DiagnosticsState.LiveSkillCount += SkillState.bLiveSkill ? 1 : 0; + DiagnosticsState.AvailableNowCount += SkillState.bAvailableNow ? 1 : 0; + DiagnosticsState.BrowserTraceCaptureSkillCount += SkillState.bCapturesBrowserTrace ? 1 : 0; + DiagnosticsState.BrowserApiDiscoverySkillCount += + SkillState.bPerformsBrowserApiDiscovery ? 1 : 0; + DiagnosticsState.bEverySkillPreservesOptionalAssistiveOffState &= + SkillState.bPreservesOptionalAssistiveOffState; + DiagnosticsState.bDiagnosticsRemainBounded &= SkillState.bBoundedToDiagnosticsOnly; + DiagnosticsState.bEverySkillRequiresExtractionSubstrate &= + SkillState.bRequiresExtractionSubstrate; + DiagnosticsState.bNoDesignTranslationWidening &= + SkillState.bAvoidsDesignTranslationWidening; + + if (SkillState.bLiveSkill) + { + DiagnosticsState.bEveryLiveSkillReadsAuthoritativeBrowserAndDocSurfaces &= + SkillState.bReadsAuthoritativeBrowserAndDocSurfaces; + DiagnosticsState.bEveryLiveSkillHasValidationHarnessCoverage &= + SkillState.bHasValidationHarnessCoverage; + } + } + + DiagnosticsState.SkillCount = DiagnosticsState.Skills.Num(); + + return DiagnosticsState; +} diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistBootstrap/HyperTwistContractLibrary.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistBootstrap/HyperTwistContractLibrary.h index c945123..3248244 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistBootstrap/HyperTwistContractLibrary.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistBootstrap/HyperTwistContractLibrary.h @@ -202,6 +202,9 @@ public: UFUNCTION(BlueprintPure, Category = "HyperTwist|Skills") static FHyperTwistSkillExtractionState MakeSampleSkillExtractionState(); + UFUNCTION(BlueprintPure, Category = "HyperTwist|Skills") + static FHyperTwistSkillBrowserDiagnosticsState MakeSampleSkillBrowserDiagnosticsState(); + UFUNCTION(BlueprintPure, Category = "HyperTwist|Training") static FHyperTwistTrainingRepositoryIntegrityReport MakeSampleTrainingRepositoryIntegrityReport(); @@ -446,6 +449,11 @@ public: const FHyperTwistSkillExtractionState& SkillExtractionState ); + UFUNCTION(BlueprintCallable, Category = "HyperTwist|Serialization") + static FString SerializeSkillBrowserDiagnosticsStateToJson( + const FHyperTwistSkillBrowserDiagnosticsState& SkillBrowserDiagnosticsState + ); + UFUNCTION(BlueprintPure, Category = "HyperTwist|Serialization") static FString SerializeTrainingTimerExportPacketToJson(const FHyperTwistTrainingTimerExportPacket& TimerExportPacket); @@ -584,6 +592,12 @@ public: FHyperTwistSkillExtractionState& OutSkillExtractionState ); + UFUNCTION(BlueprintCallable, Category = "HyperTwist|Serialization") + static bool DeserializeSkillBrowserDiagnosticsStateFromJson( + const FString& Json, + FHyperTwistSkillBrowserDiagnosticsState& OutSkillBrowserDiagnosticsState + ); + UFUNCTION(BlueprintCallable, Category = "HyperTwist|Serialization") static bool DeserializeTrainingTimerExportPacketFromJson(const FString& Json, FHyperTwistTrainingTimerExportPacket& OutTimerExportPacket); }; diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistSkills/HyperTwistSkillCoreLibrary.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistSkills/HyperTwistSkillCoreLibrary.h index 728936d..bfc607e 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistSkills/HyperTwistSkillCoreLibrary.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistSkills/HyperTwistSkillCoreLibrary.h @@ -90,4 +90,12 @@ public: const FHyperTwistSkillControlState& ControlState, const FHyperTwistSkillAuthoringHarnessState& AuthoringHarnessState ); + + UFUNCTION(BlueprintPure, Category = "HyperTwist|Skills") + static FHyperTwistSkillBrowserDiagnosticsState DeriveSkillBrowserDiagnosticsState( + const FHyperTwistSkillRegistryState& RegistryState, + const FHyperTwistSkillControlState& ControlState, + const FHyperTwistSkillAuthoringHarnessState& AuthoringHarnessState, + const FHyperTwistSkillExtractionState& ExtractionState + ); }; diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistSkills/HyperTwistSkillTypes.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistSkills/HyperTwistSkillTypes.h index 042384c..b3d4e81 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistSkills/HyperTwistSkillTypes.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistSkills/HyperTwistSkillTypes.h @@ -3540,3 +3540,298 @@ struct FHyperTwistSkillExtractionState == bComputedNoDesignTranslationWidening; } }; + +USTRUCT(BlueprintType) +struct FHyperTwistSkillBrowserDiagnosticSkill +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SkillId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString DisplayLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString CommandSurfaceId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString ServiceBindingId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString OwnerLaneId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString OwnerFeatureId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + EHyperTwistSkillStatus Status = EHyperTwistSkillStatus::None; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + TArray PermissionScopeIds; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + TArray SourceSurfaceIds; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + TArray RequiredExtractionSkillIds; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + TArray OutputArtifactKinds; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + TArray PreviewHeadlines; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 SourceSurfaceCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 RequiredExtractionSkillCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bLiveSkill = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bReadsAuthoritativeBrowserAndDocSurfaces = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bAvailableNow = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bRequiresOwnerActivation = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bPreservesOptionalAssistiveOffState = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bDerivedAssistiveOnly = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bHasValidationHarnessCoverage = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bBoundedToDiagnosticsOnly = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bRequiresExtractionSubstrate = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bAvoidsDesignTranslationWidening = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bCapturesBrowserTrace = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bPerformsBrowserApiDiscovery = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString Summary; + + bool IsStructurallyValid() const + { + if (SkillId.IsEmpty() + || DisplayLabel.IsEmpty() + || CommandSurfaceId.IsEmpty() + || ServiceBindingId.IsEmpty() + || OwnerLaneId.IsEmpty() + || OwnerFeatureId.IsEmpty() + || Status == EHyperTwistSkillStatus::None + || PermissionScopeIds.Num() == 0 + || SourceSurfaceIds.Num() == 0 + || RequiredExtractionSkillIds.Num() == 0 + || OutputArtifactKinds.Num() == 0 + || PreviewHeadlines.Num() == 0 + || SourceSurfaceCount != SourceSurfaceIds.Num() + || RequiredExtractionSkillCount != RequiredExtractionSkillIds.Num() + || !bReadsAuthoritativeBrowserAndDocSurfaces + || !bPreservesOptionalAssistiveOffState + || !bDerivedAssistiveOnly + || !bHasValidationHarnessCoverage + || !bBoundedToDiagnosticsOnly + || !bRequiresExtractionSubstrate + || !bAvoidsDesignTranslationWidening + || bCapturesBrowserTrace == bPerformsBrowserApiDiscovery) + { + return false; + } + + for (const FString& Value : PermissionScopeIds) + { + if (Value.IsEmpty()) + { + return false; + } + } + + for (const FString& Value : SourceSurfaceIds) + { + if (Value.IsEmpty()) + { + return false; + } + } + + for (const FString& Value : RequiredExtractionSkillIds) + { + if (Value.IsEmpty()) + { + return false; + } + } + + for (const FString& Value : OutputArtifactKinds) + { + if (Value.IsEmpty()) + { + return false; + } + } + + for (const FString& Value : PreviewHeadlines) + { + if (Value.IsEmpty()) + { + return false; + } + } + + return Status == EHyperTwistSkillStatus::ImplementedNow + && bLiveSkill + && bAvailableNow + && !bRequiresOwnerActivation; + } +}; + +USTRUCT(BlueprintType) +struct FHyperTwistSkillBrowserDiagnosticsState +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString RegistryId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString ManifestVersion; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString ReferenceUtc; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString CommandSurfaceRootId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString TemplateVersion; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + TArray Skills; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 SkillCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 LiveSkillCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 AvailableNowCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 BrowserTraceCaptureSkillCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 BrowserApiDiscoverySkillCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bEveryLiveSkillReadsAuthoritativeBrowserAndDocSurfaces = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bEverySkillPreservesOptionalAssistiveOffState = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bEveryLiveSkillHasValidationHarnessCoverage = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bDiagnosticsRemainBounded = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bEverySkillRequiresExtractionSubstrate = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bNoDesignTranslationWidening = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString Summary; + + bool IsStructurallyValid() const + { + if (RegistryId.IsEmpty() + || ManifestVersion.IsEmpty() + || ReferenceUtc.IsEmpty() + || CommandSurfaceRootId.IsEmpty() + || TemplateVersion.IsEmpty() + || Skills.Num() == 0 + || SkillCount != Skills.Num() + || !bEveryLiveSkillReadsAuthoritativeBrowserAndDocSurfaces + || !bEverySkillPreservesOptionalAssistiveOffState + || !bEveryLiveSkillHasValidationHarnessCoverage + || !bDiagnosticsRemainBounded + || !bEverySkillRequiresExtractionSubstrate + || !bNoDesignTranslationWidening) + { + return false; + } + + TArray SeenSkillIds; + int32 ComputedLiveSkillCount = 0; + int32 ComputedAvailableNowCount = 0; + int32 ComputedBrowserTraceCaptureSkillCount = 0; + int32 ComputedBrowserApiDiscoverySkillCount = 0; + bool bComputedEveryLiveSkillReadsAuthoritativeBrowserAndDocSurfaces = true; + bool bComputedEverySkillPreservesOptionalAssistiveOffState = true; + bool bComputedEveryLiveSkillHasValidationHarnessCoverage = true; + bool bComputedDiagnosticsRemainBounded = true; + bool bComputedEverySkillRequiresExtractionSubstrate = true; + bool bComputedNoDesignTranslationWidening = true; + + for (const FHyperTwistSkillBrowserDiagnosticSkill& Skill : Skills) + { + if (!Skill.IsStructurallyValid() || SeenSkillIds.Contains(Skill.SkillId)) + { + return false; + } + + SeenSkillIds.Add(Skill.SkillId); + ComputedLiveSkillCount += Skill.bLiveSkill ? 1 : 0; + ComputedAvailableNowCount += Skill.bAvailableNow ? 1 : 0; + ComputedBrowserTraceCaptureSkillCount += Skill.bCapturesBrowserTrace ? 1 : 0; + ComputedBrowserApiDiscoverySkillCount += Skill.bPerformsBrowserApiDiscovery ? 1 : 0; + bComputedEverySkillPreservesOptionalAssistiveOffState &= + Skill.bPreservesOptionalAssistiveOffState; + bComputedDiagnosticsRemainBounded &= Skill.bBoundedToDiagnosticsOnly; + bComputedEverySkillRequiresExtractionSubstrate &= Skill.bRequiresExtractionSubstrate; + bComputedNoDesignTranslationWidening &= Skill.bAvoidsDesignTranslationWidening; + + if (Skill.bLiveSkill) + { + bComputedEveryLiveSkillReadsAuthoritativeBrowserAndDocSurfaces &= + Skill.bReadsAuthoritativeBrowserAndDocSurfaces; + bComputedEveryLiveSkillHasValidationHarnessCoverage &= + Skill.bHasValidationHarnessCoverage; + } + } + + return LiveSkillCount == ComputedLiveSkillCount + && AvailableNowCount == ComputedAvailableNowCount + && BrowserTraceCaptureSkillCount == ComputedBrowserTraceCaptureSkillCount + && BrowserApiDiscoverySkillCount == ComputedBrowserApiDiscoverySkillCount + && bEveryLiveSkillReadsAuthoritativeBrowserAndDocSurfaces + == bComputedEveryLiveSkillReadsAuthoritativeBrowserAndDocSurfaces + && bEverySkillPreservesOptionalAssistiveOffState + == bComputedEverySkillPreservesOptionalAssistiveOffState + && bEveryLiveSkillHasValidationHarnessCoverage + == bComputedEveryLiveSkillHasValidationHarnessCoverage + && bDiagnosticsRemainBounded == bComputedDiagnosticsRemainBounded + && bEverySkillRequiresExtractionSubstrate + == bComputedEverySkillRequiresExtractionSubstrate + && bNoDesignTranslationWidening == bComputedNoDesignTranslationWidening; + } +}; diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS1ARegistryManifestContractTest.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS1ARegistryManifestContractTest.cpp index 8d75771..33e94c1 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS1ARegistryManifestContractTest.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS1ARegistryManifestContractTest.cpp @@ -73,9 +73,9 @@ bool FHyperTwistSkillPhaseS1ARegistryManifestTest::RunTest(const FString& Parame RegistryState.IsStructurallyValid() ); TestEqual( - TEXT("The sample S1-A registry must expose fifteen declared skills after S4-A lands."), + TEXT("The sample S1-A registry must expose seventeen declared skills after S4-B lands."), RegistryState.SkillCount, - 15 + 17 ); TestTrue( TEXT("The S1-A registry must avoid ad hoc metadata."), @@ -86,12 +86,12 @@ bool FHyperTwistSkillPhaseS1ARegistryManifestTest::RunTest(const FString& Parame RegistryState.bAllSkillsOptionalAssistive ); TestEqual( - TEXT("The sample S1-A registry must keep twelve implemented skill entries after S4-A lands."), + TEXT("The sample S1-A registry must keep fourteen implemented skill entries after S4-B lands."), HyperTwistSkillPhaseS1ATestInternal::FindStatusCount( RegistryState, EHyperTwistSkillStatus::ImplementedNow ), - 12 + 14 ); TestEqual( TEXT("The sample S1-A registry must keep one command-contract-pending entry for note capture."), @@ -126,12 +126,12 @@ bool FHyperTwistSkillPhaseS1ARegistryManifestTest::RunTest(const FString& Parame 8 ); TestEqual( - TEXT("The sample S1-A registry must expose two browser/docs/design-family entries after S4-A lands."), + TEXT("The sample S1-A registry must expose four browser/docs/design-family entries after S4-B lands."), HyperTwistSkillPhaseS1ATestInternal::FindFamilyCount( RegistryState, EHyperTwistSkillFamily::BrowserDocsDesign ), - 2 + 4 ); const FHyperTwistSkillManifestEntry* GovernanceSkill = @@ -230,6 +230,29 @@ bool FHyperTwistSkillPhaseS1ARegistryManifestTest::RunTest(const FString& Parame ); } + const FHyperTwistSkillManifestEntry* BrowserTraceSkill = + HyperTwistSkillPhaseS1ATestInternal::FindSkillById( + RegistryState, + TEXT("skill/capture-browser-trace") + ); + TestNotNull( + TEXT("The capture-browser-trace skill entry must exist."), + BrowserTraceSkill + ); + if (BrowserTraceSkill != nullptr) + { + TestEqual( + TEXT("The capture-browser-trace skill must be implemented now."), + BrowserTraceSkill->Status, + EHyperTwistSkillStatus::ImplementedNow + ); + TestEqual( + TEXT("The capture-browser-trace skill must bind to the first-party browser-trace service."), + BrowserTraceSkill->CommandBindings[0].ServiceBindingId, + FString(TEXT("service/skills/capture-browser-trace")) + ); + } + return true; } diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS1BSettingsVisibilityContractTest.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS1BSettingsVisibilityContractTest.cpp index 8992df2..676aabe 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS1BSettingsVisibilityContractTest.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS1BSettingsVisibilityContractTest.cpp @@ -71,9 +71,9 @@ bool FHyperTwistSkillPhaseS1BSettingsVisibilityTest::RunTest( ControlState.MasterSwitch.bImmediateMenuControlExposed ); TestEqual( - TEXT("The sample S1-B control state must preserve all fifteen installed skills after S4-A lands."), + TEXT("The sample S1-B control state must preserve all seventeen installed skills after S4-B lands."), ControlState.SkillCount, - 15 + 17 ); TestEqual( TEXT("The default S1-B control state must keep one effective enabled skill."), @@ -160,6 +160,32 @@ bool FHyperTwistSkillPhaseS1BSettingsVisibilityTest::RunTest( ); } + const FHyperTwistSkillControlStateEntry* BrowserTraceState = + HyperTwistSkillPhaseS1BTestInternal::FindSkillStateById( + ControlState, + TEXT("skill/capture-browser-trace") + ); + TestNotNull( + TEXT("The capture-browser-trace skill state must exist."), + BrowserTraceState + ); + if (BrowserTraceState != nullptr) + { + TestFalse( + TEXT("The capture-browser-trace skill must remain opt-in by default."), + BrowserTraceState->bEffectiveEnabled + ); + TestTrue( + TEXT("The capture-browser-trace skill must remain visible by default."), + BrowserTraceState->bEffectiveVisible + ); + TestEqual( + TEXT("The capture-browser-trace skill must use the browser/docs/design visibility group."), + BrowserTraceState->VisibilityGroupId, + TEXT("skill-group/browser-docs-design") + ); + } + return true; } diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS1CInvocationAuditLedgerContractTest.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS1CInvocationAuditLedgerContractTest.cpp index f430457..33c0afd 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS1CInvocationAuditLedgerContractTest.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS1CInvocationAuditLedgerContractTest.cpp @@ -39,7 +39,7 @@ bool FHyperTwistSkillPhaseS1CInvocationProvenanceTest::RunTest(const FString& Pa TestEqual( TEXT("Sample skill audit ledger should record one invocation per enabled sample skill."), AuditLedgerState.InvocationCount, - 12 + 14 ); TestEqual( TEXT("All sample invocations should remain traceable."), @@ -111,7 +111,7 @@ bool FHyperTwistSkillPhaseS1CFailureCancelRecordingTest::RunTest(const FString& TestEqual( TEXT("The sample audit ledger should contain the expected successful invocation count."), AuditLedgerState.SuccessfulInvocationCount, - 10 + 12 ); TestEqual( TEXT("The sample audit ledger should contain the expected failed invocation count."), @@ -241,6 +241,29 @@ bool FHyperTwistSkillPhaseS1CFailureCancelRecordingTest::RunTest(const FString& ); } + const FHyperTwistSkillInvocationRecord* BrowserTraceRecord = + HyperTwistSkillPhaseS1CTestInternal::FindInvocationRecordBySkillId( + AuditLedgerState, + TEXT("skill/capture-browser-trace") + ); + TestNotNull( + TEXT("The browser-trace skill invocation should be present in the sample audit ledger."), + BrowserTraceRecord + ); + if (BrowserTraceRecord != nullptr) + { + TestEqual( + TEXT("The browser-trace skill should record a success outcome."), + BrowserTraceRecord->Outcome, + EHyperTwistSkillInvocationOutcome::Succeeded + ); + TestEqual( + TEXT("The browser-trace skill should emit the bounded browser trace artifact."), + BrowserTraceRecord->ProducedArtifacts[0].ArtifactKind, + FString(TEXT("artifact/browser-trace-capture-brief")) + ); + } + return true; } diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS1DAuthoringValidationHarnessContractTest.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS1DAuthoringValidationHarnessContractTest.cpp index deaee33..bc57e54 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS1DAuthoringValidationHarnessContractTest.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS1DAuthoringValidationHarnessContractTest.cpp @@ -287,6 +287,25 @@ bool FHyperTwistSkillPhaseS1DValidationHarnessCoverageTest::RunTest(const FStrin ); } + const FHyperTwistSkillValidationContractCase* BrowserTraceEval = + HyperTwistSkillPhaseS1DTestInternal::FindValidationCase( + HarnessState, + TEXT("skill/capture-browser-trace"), + EHyperTwistSkillValidationContractKind::Eval + ); + TestNotNull( + TEXT("The capture-browser-trace skill should have an eval validation contract."), + BrowserTraceEval + ); + if (BrowserTraceEval != nullptr) + { + TestEqual( + TEXT("The capture-browser-trace skill eval contract should run live after S4-B lands."), + BrowserTraceEval->ExecutionMode, + EHyperTwistSkillValidationExecutionMode::LiveContract + ); + } + const FHyperTwistSkillValidationContractCase* RouxEval = HyperTwistSkillPhaseS1DTestInternal::FindValidationCase( HarnessState, diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS4BBrowserDiagnosticsContractTest.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS4BBrowserDiagnosticsContractTest.cpp new file mode 100644 index 0000000..a4e692d --- /dev/null +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS4BBrowserDiagnosticsContractTest.cpp @@ -0,0 +1,204 @@ +// Copyright HyperTwist, Inc. All Rights Reserved. + +#include "Misc/AutomationTest.h" + +#include "HyperTwistBootstrap/HyperTwistContractLibrary.h" + +#if WITH_AUTOMATION_TESTS + +namespace HyperTwistSkillPhaseS4BTestInternal +{ + const FHyperTwistSkillBrowserDiagnosticSkill* FindSkillById( + const FHyperTwistSkillBrowserDiagnosticsState& DiagnosticsState, + const FString& SkillId + ) + { + for (const FHyperTwistSkillBrowserDiagnosticSkill& Skill : DiagnosticsState.Skills) + { + if (Skill.SkillId == SkillId) + { + return &Skill; + } + } + + return nullptr; + } +} + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FHyperTwistSkillPhaseS4BBrowserDiagnosticsCoverageTest, + "HyperTwist.FirstParty.Skill.PhaseS4B.BrowserDiagnosticsCoverage", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter +) + +bool FHyperTwistSkillPhaseS4BBrowserDiagnosticsCoverageTest::RunTest(const FString& Parameters) +{ + const FHyperTwistSkillBrowserDiagnosticsState DiagnosticsState = + UHyperTwistContractLibrary::MakeSampleSkillBrowserDiagnosticsState(); + + TestTrue( + TEXT("The sample S4-B browser-diagnostics state should be structurally valid."), + DiagnosticsState.IsStructurallyValid() + ); + TestEqual( + TEXT("S4-B should expose two browser-diagnostics skills."), + DiagnosticsState.SkillCount, + 2 + ); + TestEqual( + TEXT("S4-B should expose two live browser-diagnostics skills."), + DiagnosticsState.LiveSkillCount, + 2 + ); + TestEqual( + TEXT("S4-B should expose one browser-trace-capture skill."), + DiagnosticsState.BrowserTraceCaptureSkillCount, + 1 + ); + TestEqual( + TEXT("S4-B should expose one browser/API discovery skill."), + DiagnosticsState.BrowserApiDiscoverySkillCount, + 1 + ); + + const FHyperTwistSkillBrowserDiagnosticSkill* BrowserTraceSkill = + HyperTwistSkillPhaseS4BTestInternal::FindSkillById( + DiagnosticsState, + TEXT("skill/capture-browser-trace") + ); + TestNotNull( + TEXT("The capture-browser-trace skill should exist."), + BrowserTraceSkill + ); + if (BrowserTraceSkill != nullptr) + { + TestEqual( + TEXT("The capture-browser-trace skill should bind to the bounded browser-trace artifact."), + BrowserTraceSkill->OutputArtifactKinds[0], + FString(TEXT("artifact/browser-trace-capture-brief")) + ); + TestTrue( + TEXT("The capture-browser-trace skill should declare browser trace capture."), + BrowserTraceSkill->bCapturesBrowserTrace + ); + } + + return true; +} + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FHyperTwistSkillPhaseS4BBoundedBrowserDiagnosticsTest, + "HyperTwist.FirstParty.Skill.PhaseS4B.BoundedBrowserDiagnostics", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter +) + +bool FHyperTwistSkillPhaseS4BBoundedBrowserDiagnosticsTest::RunTest(const FString& Parameters) +{ + const FHyperTwistSkillBrowserDiagnosticsState DiagnosticsState = + UHyperTwistContractLibrary::MakeSampleSkillBrowserDiagnosticsState(); + + TestTrue( + TEXT("The sample S4-B browser-diagnostics state should be structurally valid."), + DiagnosticsState.IsStructurallyValid() + ); + TestTrue( + TEXT("Every live S4-B skill should read authoritative browser and docs surfaces."), + DiagnosticsState.bEveryLiveSkillReadsAuthoritativeBrowserAndDocSurfaces + ); + TestTrue( + TEXT("Every live S4-B skill should keep validation-harness coverage."), + DiagnosticsState.bEveryLiveSkillHasValidationHarnessCoverage + ); + TestTrue( + TEXT("S4-B browser diagnostics should remain structurally bounded."), + DiagnosticsState.bDiagnosticsRemainBounded + ); + TestTrue( + TEXT("S4-B browser diagnostics should require the landed extraction substrate."), + DiagnosticsState.bEverySkillRequiresExtractionSubstrate + ); + TestTrue( + TEXT("S4-B browser diagnostics should not widen into design translation."), + DiagnosticsState.bNoDesignTranslationWidening + ); + + const FHyperTwistSkillBrowserDiagnosticSkill* BrowserApiSkill = + HyperTwistSkillPhaseS4BTestInternal::FindSkillById( + DiagnosticsState, + TEXT("skill/discover-browser-api") + ); + TestNotNull( + TEXT("The discover-browser-api skill should exist."), + BrowserApiSkill + ); + if (BrowserApiSkill != nullptr) + { + TestTrue( + TEXT("The discover-browser-api skill should declare browser/API discovery."), + BrowserApiSkill->bPerformsBrowserApiDiscovery + ); + TestTrue( + TEXT("The discover-browser-api skill should depend on the extraction substrate."), + BrowserApiSkill->bRequiresExtractionSubstrate + ); + TestTrue( + TEXT("The discover-browser-api skill should explicitly avoid design translation widening."), + BrowserApiSkill->bAvoidsDesignTranslationWidening + ); + } + + return true; +} + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FHyperTwistSkillPhaseS4BSerializationRoundTripTest, + "HyperTwist.FirstParty.Skill.PhaseS4B.SerializationRoundTrip", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter +) + +bool FHyperTwistSkillPhaseS4BSerializationRoundTripTest::RunTest(const FString& Parameters) +{ + const FHyperTwistSkillBrowserDiagnosticsState DiagnosticsState = + UHyperTwistContractLibrary::MakeSampleSkillBrowserDiagnosticsState(); + + TestTrue( + TEXT("The sample S4-B browser-diagnostics state should be structurally valid before serialization."), + DiagnosticsState.IsStructurallyValid() + ); + + const FString Json = + UHyperTwistContractLibrary::SerializeSkillBrowserDiagnosticsStateToJson( + DiagnosticsState + ); + TestTrue( + TEXT("Serialized S4-B JSON should include the extraction-substrate guard field."), + Json.Contains(TEXT("bEverySkillRequiresExtractionSubstrate")) + ); + + FHyperTwistSkillBrowserDiagnosticsState RoundTrippedState; + TestTrue( + TEXT("Deserializing the S4-B browser-diagnostics JSON should succeed."), + UHyperTwistContractLibrary::DeserializeSkillBrowserDiagnosticsStateFromJson( + Json, + RoundTrippedState + ) + ); + TestTrue( + TEXT("Round-tripped S4-B browser-diagnostics state should remain structurally valid."), + RoundTrippedState.IsStructurallyValid() + ); + TestEqual( + TEXT("Round-tripped S4-B skill count should match the original sample."), + RoundTrippedState.SkillCount, + DiagnosticsState.SkillCount + ); + TestEqual( + TEXT("Round-tripped S4-B live-skill count should match the original sample."), + RoundTrippedState.LiveSkillCount, + DiagnosticsState.LiveSkillCount + ); + + return true; +} + +#endif diff --git a/docs/arch/HYPERTWIST_PHASES4_B_FIRST_PARTY_BROWSER_DIAGNOSTICS_SKILLS_IMPLEMENTATION_PACKET_2026-05-29.md b/docs/arch/HYPERTWIST_PHASES4_B_FIRST_PARTY_BROWSER_DIAGNOSTICS_SKILLS_IMPLEMENTATION_PACKET_2026-05-29.md new file mode 100644 index 0000000..5886ea6 --- /dev/null +++ b/docs/arch/HYPERTWIST_PHASES4_B_FIRST_PARTY_BROWSER_DIAGNOSTICS_SKILLS_IMPLEMENTATION_PACKET_2026-05-29.md @@ -0,0 +1,35 @@ +# HyperTwist Phase S4-B Implementation Packet + +Date: `2026-05-29` + +Packet: `Phase S4-B` + +Title: `first-party browser diagnostics skills` + +## Outcome + +Implemented now. + +## Landed scope + +- live `skill/capture-browser-trace` +- live `skill/discover-browser-api` +- bounded first-party browser diagnostics state over authoritative first-party + browser/service source surfaces +- registry, control-state, audit-ledger, authoring-harness, sample-contract, + and JSON round-trip support + +## Preserved boundaries + +- browser diagnostics remain provenance-visible and bounded +- extraction remains a separate prerequisite seam +- no design translation widening in this packet +- no broad browser-shell orchestration widening in this packet + +## Validation + +- build target: `UnrealHyperTwistEditor Win64 Development` +- focused `S4-B` automation passed for browser diagnostics coverage, bounded + browser diagnostics, and serialization round-trip +- `S4-A` regression passed after the new family landed +- full `Phase S1` skill substrate regression passed after the new family landed diff --git a/docs/arch/HYPERTWIST_PHASES4_B_FIRST_PARTY_BROWSER_DIAGNOSTICS_SKILLS_PREPARATION_PACKET_2026-05-29.md b/docs/arch/HYPERTWIST_PHASES4_B_FIRST_PARTY_BROWSER_DIAGNOSTICS_SKILLS_PREPARATION_PACKET_2026-05-29.md new file mode 100644 index 0000000..7169be2 --- /dev/null +++ b/docs/arch/HYPERTWIST_PHASES4_B_FIRST_PARTY_BROWSER_DIAGNOSTICS_SKILLS_PREPARATION_PACKET_2026-05-29.md @@ -0,0 +1,40 @@ +# HyperTwist Phase S4-B Preparation Packet + +Date: `2026-05-29` + +Packet: `Phase S4-B` + +Title: `first-party browser diagnostics skills` + +## Goal + +Land the next bounded browser/docs/design skill seam by exposing first-party +browser diagnostics skills over authoritative HyperTwist browser, service, and +artifact source surfaces. + +## Scope + +- `skill/capture-browser-trace` +- `skill/discover-browser-api` +- first-party browser diagnostics state over authoritative first-party + browser/service source surfaces +- registry, control-state, audit-ledger, authoring-harness, sample-contract, + and JSON support + +## Required boundaries + +- do not widen into design-to-native translation +- do not widen into broad browser-shell orchestration +- keep browser diagnostics provenance-visible, bounded, derived-assistive, and + first-party owned + +## Inputs + +- landed `S1-A` through `S4-A` skill substrate +- landed first-party architecture, roadmap, feature-registry, and provenance + authority surfaces + +## Acceptance gate + +- browser diagnostics remain bounded to trace capture and browser/API + discovery and do not claim design translation ownership diff --git a/docs/ops/HYPERTWIST_IMPLEMENTATION_PHASE_1_KICKOFF.md b/docs/ops/HYPERTWIST_IMPLEMENTATION_PHASE_1_KICKOFF.md index 3f41b5a..393a31f 100644 --- a/docs/ops/HYPERTWIST_IMPLEMENTATION_PHASE_1_KICKOFF.md +++ b/docs/ops/HYPERTWIST_IMPLEMENTATION_PHASE_1_KICKOFF.md @@ -293,4 +293,6 @@ Specifically: now landed in current code - the bounded first-party `Phase S4-A` extraction skill packet is now landed in current code -- `S4-B` browser diagnostics skills are now the next clean move +- the bounded first-party `Phase S4-B` browser diagnostics skill packet is now + landed in current code +- `S4-C` design shell skills are now the next clean move diff --git a/docs/ops/HYPERTWIST_SKILLIZATION_AND_COMMAND_SURFACE_DOCTRINE_2026-05-21.md b/docs/ops/HYPERTWIST_SKILLIZATION_AND_COMMAND_SURFACE_DOCTRINE_2026-05-21.md index 552b21a..8974fb7 100644 --- a/docs/ops/HYPERTWIST_SKILLIZATION_AND_COMMAND_SURFACE_DOCTRINE_2026-05-21.md +++ b/docs/ops/HYPERTWIST_SKILLIZATION_AND_COMMAND_SURFACE_DOCTRINE_2026-05-21.md @@ -407,8 +407,11 @@ Current landed posture: collapse into opaque summaries - bounded first-party `Phase S4-A` extraction skills are live for `extract-docs` and `extract-design-spec` over authoritative first-party - docs/design source surfaces while remaining separate from browser - diagnostics and design translation + docs/design source surfaces +- bounded first-party `Phase S4-B` browser diagnostics skills are live for + `capture-browser-trace` and `discover-browser-api` over authoritative + first-party browser/service source surfaces while remaining separate from + design translation ### S4 - browser/docs/design skills @@ -544,13 +547,12 @@ These are target-shape command families, not claims of implemented reality. The next correct sequence is: -1. `S4-B` browser diagnostics skills -2. `S4-C` translation/design-to-native skills -3. broader workflow, provider, and domain skill widening +1. `S4-C` translation/design-to-native skills +2. broader workflow, provider, and domain skill widening -The browser/docs/design extraction base now exists. Broader memory, browser, -workflow, provider, and domain skill widening should wait until browser -diagnostics and design translation follow-through settles. +The browser/docs/design extraction base and browser diagnostics seam now +exist. Broader memory, browser, workflow, provider, and domain skill widening +should wait until design translation follow-through settles. ## Product messaging rule diff --git a/docs/v6_5_deep_manual_pack/HyperTwist/ARCHITECTURE.md b/docs/v6_5_deep_manual_pack/HyperTwist/ARCHITECTURE.md index 48b8d90..33d591f 100644 --- a/docs/v6_5_deep_manual_pack/HyperTwist/ARCHITECTURE.md +++ b/docs/v6_5_deep_manual_pack/HyperTwist/ARCHITECTURE.md @@ -267,5 +267,8 @@ Future skill growth must follow: user-authored note capture and opaque summary collapse - the bounded first-party `Phase S4-A` extraction seam is now the live product base for `extract-docs` and `extract-design-spec` over authoritative - first-party docs/design source surfaces, while remaining separate from - browser diagnostics and design translation + first-party docs/design source surfaces +- the bounded first-party `Phase S4-B` browser diagnostics seam is now the + live product base for `capture-browser-trace` and `discover-browser-api` + over authoritative first-party browser/service source surfaces, while + remaining separate from design translation 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 24afa64..a5972ac 100644 --- a/docs/v6_5_deep_manual_pack/HyperTwist/FEATURE_REGISTRY.md +++ b/docs/v6_5_deep_manual_pack/HyperTwist/FEATURE_REGISTRY.md @@ -304,10 +304,11 @@ repo. | Feature | Status | Primary authority | Notes | |---|---|---|---| -| First-party skill registry and enable/disable governance | Implemented now | landed first-party `Phase S1-A`, `Phase S1-B`, `Phase S1-C`, `Phase S1-D`, `Phase S2-A`, `Phase S2-B`, `Phase S2-C`, `Phase S3-A`, `Phase S3-B`, `Phase S3-C`, and `Phase S4-A` packets | Current bounded first-party skill status/family contracts, command/service binding declarations, permission/scope declarations, provenance/log declarations, manifest entries, registry counts, durable master-switch/per-skill control-state, family visibility groups, disabled-but-installed inert-off-state truth, invocation-record format, command/service provenance, failure/cancel audit-ledger storage, authoring-template sections, registry-grounded examples, per-skill smoke/eval validation-harness contracts, structured permissive wrapper-output contracts, first-party clean-room command-contract specs, first-party clean-room-ready skill specs, bounded first-party continuity/resume skill state, bounded recall/compact-view skill state, bounded workflow-memory capture skill state, and bounded docs/design extraction skill state are live as bounded substrate. `S4-B` is now the next bounded skillization seam. | +| First-party skill registry and enable/disable governance | Implemented now | landed first-party `Phase S1-A`, `Phase S1-B`, `Phase S1-C`, `Phase S1-D`, `Phase S2-A`, `Phase S2-B`, `Phase S2-C`, `Phase S3-A`, `Phase S3-B`, `Phase S3-C`, `Phase S4-A`, and `Phase S4-B` packets | Current bounded first-party skill status/family contracts, command/service binding declarations, permission/scope declarations, provenance/log declarations, manifest entries, registry counts, durable master-switch/per-skill control-state, family visibility groups, disabled-but-installed inert-off-state truth, invocation-record format, command/service provenance, failure/cancel audit-ledger storage, authoring-template sections, registry-grounded examples, per-skill smoke/eval validation-harness contracts, structured permissive wrapper-output contracts, first-party clean-room command-contract specs, first-party clean-room-ready skill specs, bounded first-party continuity/resume skill state, bounded recall/compact-view skill state, bounded workflow-memory capture skill state, bounded docs/design extraction skill state, and bounded browser diagnostics skill state are live as bounded substrate. `S4-C` is now the next bounded skillization seam. | | Review/analyzer skill family | Implemented now | landed first-party `Phase S2-A` packet | Current bounded first-party review/analyzer wrappers are live for architecture scan and policy scan output over permissive product evidence. Broader review/diff/plan helper widening still remains future work. | -| Memory/continuity skill family | Implemented now | landed first-party `Phase S3-A`, `Phase S3-B`, and `Phase S3-C` packets + skillization + memory doctrine | Current bounded `resume-session`, `search-history`, `recall-memory`, `generate-compact-view`, `capture-session-template`, and `capture-follow-up-routine` skills are live above the landed first-party `6R-M1`, `6R-M2`, `6R-M3`, and `6R-M6` memory seams, while `capture-note` remains explicit but non-live under separate owner activation because active user-authored note capture is still not landed beyond the bounded `6R-M5` seam. Compact views remain optional and linked to authoritative sources, workflow capture remains separate from user-authored notes, and the browser/docs/design extraction base is now live ahead of browser diagnostics and design-shell follow-through. | +| Memory/continuity skill family | Implemented now | landed first-party `Phase S3-A`, `Phase S3-B`, and `Phase S3-C` packets + skillization + memory doctrine | Current bounded `resume-session`, `search-history`, `recall-memory`, `generate-compact-view`, `capture-session-template`, and `capture-follow-up-routine` skills are live above the landed first-party `6R-M1`, `6R-M2`, `6R-M3`, and `6R-M6` memory seams, while `capture-note` remains explicit but non-live under separate owner activation because active user-authored note capture is still not landed beyond the bounded `6R-M5` seam. Compact views remain optional and linked to authoritative sources, workflow capture remains separate from user-authored notes, and the browser/docs/design extraction base plus browser diagnostics seam are now live ahead of design-shell follow-through. | | Browser/docs/design extraction skill family | Implemented now | landed first-party `Phase S4-A` packet | Current bounded `extract-docs` and `extract-design-spec` skills are live over authoritative first-party docs/design source surfaces. Structured extraction remains provenance-visible and derived-only, while browser diagnostics and design translation remain separate later seams. | +| Browser/docs/design browser diagnostics skill family | Implemented now | landed first-party `Phase S4-B` packet | Current bounded `capture-browser-trace` and `discover-browser-api` skills are live over authoritative first-party browser/service source surfaces. Browser diagnostics remain provenance-visible, extraction-dependent, and separate from design translation. | | Provider/ops skill family | Deep-source grounded retained + bounded live wrapper | landed first-party `Phase S2-A` packet + skillization + provider doctrine | Current bounded route-inspection wrapper output is live above the landed provider-neutral speech/provider seams, while broader provider/ops skill widening still remains retained. | | Restrictive training/coaching clean-room skill-spec family | Implemented now, spec-only bounded seam | landed first-party `Phase S2-B` and `Phase S2-C` packets + skillization doctrine | Current restrictive training/coaching skillization seam is now clean-room-ready in first-party terms for bounded Roux session review output. HyperTwist owns the first-party command contract, safety model, and clean-room-ready skill spec, while live clean-room skill behavior still remains separately deferred unless later reopened. | | Domain/creative skill packs | Shallow placeholder | skillization doctrine only | Keep internal until source-grounded. | diff --git a/docs/v6_5_deep_manual_pack/HyperTwist/PROVENANCE_AND_TRUST_MODEL.md b/docs/v6_5_deep_manual_pack/HyperTwist/PROVENANCE_AND_TRUST_MODEL.md index 0f8c858..ec8ced6 100644 --- a/docs/v6_5_deep_manual_pack/HyperTwist/PROVENANCE_AND_TRUST_MODEL.md +++ b/docs/v6_5_deep_manual_pack/HyperTwist/PROVENANCE_AND_TRUST_MODEL.md @@ -130,8 +130,11 @@ The landed bounded first-party `Phase S1-A` packet keeps: notes, and free of opaque summary collapse - the landed bounded first-party `Phase S4-A` packet now keeps docs extraction and design-spec extraction provenance-visible while requiring structured - extraction to remain bounded, separate from browser diagnostics, and unable - to widen into design translation + extraction to remain bounded and unable to widen into design translation +- the landed bounded first-party `Phase S4-B` packet now keeps browser trace + capture and browser/API discovery provenance-visible while requiring + browser diagnostics to remain bounded and unable to widen into design + translation ## Memory-specific consequence diff --git a/docs/v6_5_deep_manual_pack/HyperTwist/ROADMAP.md b/docs/v6_5_deep_manual_pack/HyperTwist/ROADMAP.md index d9279dc..5d426c6 100644 --- a/docs/v6_5_deep_manual_pack/HyperTwist/ROADMAP.md +++ b/docs/v6_5_deep_manual_pack/HyperTwist/ROADMAP.md @@ -189,7 +189,9 @@ Canonical discovery surfaces for roadmap interpretation: now landed in current code - the bounded first-party `Phase S4-A` extraction skill packet is now landed in current code -- `S4-B` browser diagnostics skills are now the next clean move +- the bounded first-party `Phase S4-B` browser diagnostics skill packet is now + landed in current code +- `S4-C` design shell skills are now the next clean move - the generic source-backed `Phase 6R-R` shared classic-cube recognition multi-face correction/explanation control pass is now consumed - the bounded permissive `Phase 6R-R` shared classic-cube recognition multi-face diff --git a/docs/v6_5_deep_manual_pack/HyperTwist/SKILLS.md b/docs/v6_5_deep_manual_pack/HyperTwist/SKILLS.md index 2fa7bc0..8ef0ecc 100644 --- a/docs/v6_5_deep_manual_pack/HyperTwist/SKILLS.md +++ b/docs/v6_5_deep_manual_pack/HyperTwist/SKILLS.md @@ -130,9 +130,8 @@ A coding model working on HyperTwist should still be able to: The next correct skillization sequence is: -1. browser diagnostics skills -2. design shell skills +1. design shell skills -The browser/docs/design extraction base now exists. Broader memory, provider, -and domain skill widening should wait until browser diagnostics and design -shell follow-through settles. +The browser/docs/design extraction base and browser diagnostics seam now +exist. Broader memory, provider, and domain skill widening should wait until +design shell follow-through settles.