diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistBootstrap/HyperTwistContractLibrary.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistBootstrap/HyperTwistContractLibrary.cpp index 041b4bf..6d57009 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistBootstrap/HyperTwistContractLibrary.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistBootstrap/HyperTwistContractLibrary.cpp @@ -115,6 +115,22 @@ namespace HyperTwistContractLibraryInternal return OverrideState; }(), []() + { + FHyperTwistSkillControlOverride OverrideState; + OverrideState.SkillId = TEXT("skill/extract-docs"); + OverrideState.bHasEnabledOverride = true; + OverrideState.bEnabled = true; + return OverrideState; + }(), + []() + { + FHyperTwistSkillControlOverride OverrideState; + OverrideState.SkillId = TEXT("skill/extract-design-spec"); + OverrideState.bHasEnabledOverride = true; + OverrideState.bEnabled = true; + return OverrideState; + }(), + []() { FHyperTwistSkillControlOverride OverrideState; OverrideState.SkillId = TEXT("skill/provider-routing-inspector"); @@ -4165,6 +4181,21 @@ UHyperTwistContractLibrary::MakeSampleSkillWorkflowMemoryCaptureState() ); } +FHyperTwistSkillExtractionState +UHyperTwistContractLibrary::MakeSampleSkillExtractionState() +{ + const FHyperTwistSkillRegistryState RegistryState = MakeSampleSkillRegistryState(); + const FHyperTwistSkillControlState ControlState = MakeSampleSkillControlState(); + const FHyperTwistSkillAuthoringHarnessState AuthoringHarnessState = + MakeSampleSkillAuthoringHarnessState(); + + return UHyperTwistSkillCoreLibrary::DeriveSkillExtractionState( + RegistryState, + ControlState, + AuthoringHarnessState + ); +} + FHyperTwistTrainingRepositoryIntegrityReport UHyperTwistContractLibrary::MakeSampleTrainingRepositoryIntegrityReport() { FHyperTwistTrainingRepositoryState RepositoryState = MakeSampleTrainingRepositoryState(); @@ -5364,6 +5395,15 @@ FString UHyperTwistContractLibrary::SerializeSkillWorkflowMemoryCaptureStateToJs ); } +FString UHyperTwistContractLibrary::SerializeSkillExtractionStateToJson( + const FHyperTwistSkillExtractionState& SkillExtractionState +) +{ + return HyperTwistContractLibraryInternal::SerializeStructToJson( + SkillExtractionState + ); +} + FString UHyperTwistContractLibrary::SerializeTrainingTimerExportPacketToJson( const FHyperTwistTrainingTimerExportPacket& TimerExportPacket ) @@ -5596,6 +5636,17 @@ bool UHyperTwistContractLibrary::DeserializeSkillWorkflowMemoryCaptureStateFromJ ); } +bool UHyperTwistContractLibrary::DeserializeSkillExtractionStateFromJson( + const FString& Json, + FHyperTwistSkillExtractionState& OutSkillExtractionState +) +{ + return HyperTwistContractLibraryInternal::DeserializeStructFromJson( + Json, + OutSkillExtractionState + ); +} + 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 9f64cf6..f539ab9 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistSkills/HyperTwistSkillCoreLibrary.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistSkills/HyperTwistSkillCoreLibrary.cpp @@ -153,6 +153,8 @@ namespace HyperTwistSkillCoreLibraryInternal return TEXT("skill-group/provider-operations"); case EHyperTwistSkillFamily::TrainingCoaching: return TEXT("skill-group/training-coaching"); + case EHyperTwistSkillFamily::BrowserDocsDesign: + return TEXT("skill-group/browser-docs-design"); case EHyperTwistSkillFamily::DomainCreative: return TEXT("skill-group/domain-creative"); default: @@ -174,6 +176,8 @@ namespace HyperTwistSkillCoreLibraryInternal return TEXT("Provider And Operations"); case EHyperTwistSkillFamily::TrainingCoaching: return TEXT("Training And Coaching"); + case EHyperTwistSkillFamily::BrowserDocsDesign: + return TEXT("Browser, Docs, And Design"); case EHyperTwistSkillFamily::DomainCreative: return TEXT("Domain And Creative"); default: @@ -451,6 +455,12 @@ namespace HyperTwistSkillCoreLibraryInternal || SkillId == TEXT("skill/capture-follow-up-routine"); } + bool IsExtractionSkill(const FString& SkillId) + { + return SkillId == TEXT("skill/extract-docs") + || SkillId == TEXT("skill/extract-design-spec"); + } + bool HasAtLeastCleanRoomCommandContractStatus(const EHyperTwistSkillStatus Status) { return Status == EHyperTwistSkillStatus::CleanRoomCommandContractSpecified @@ -678,6 +688,12 @@ namespace HyperTwistSkillCoreLibraryInternal return EHyperTwistSkillInvocationOutcome::Succeeded; } + if (Entry.SkillId == TEXT("skill/extract-docs") + || Entry.SkillId == TEXT("skill/extract-design-spec")) + { + return EHyperTwistSkillInvocationOutcome::Succeeded; + } + return EHyperTwistSkillInvocationOutcome::Failed; } @@ -974,11 +990,11 @@ namespace HyperTwistSkillCoreLibraryInternal FHyperTwistSkillRegistryState RegistryState; RegistryState.RegistryId = TEXT("skill-registry/first-party"); - RegistryState.ManifestVersion = TEXT("s3c-v1"); - RegistryState.ReferenceUtc = TEXT("2026-05-29T07:10:00Z"); + RegistryState.ManifestVersion = TEXT("s4a-v1"); + RegistryState.ReferenceUtc = TEXT("2026-05-29T09:20:00Z"); RegistryState.CommandSurfaceRootId = TEXT("command-surface/skills"); RegistryState.Summary = - TEXT("First-party skill registry and manifest contract with landed permissive analyzer wrappers, landed clean-room command contracts, landed clean-room skill specs, landed continuity/resume skills, landed recall/compact-view skills, and landed workflow-memory capture skills."); + TEXT("First-party skill registry and manifest contract with landed permissive analyzer wrappers, landed clean-room command contracts, landed clean-room skill specs, landed continuity/resume skills, landed recall/compact-view skills, landed workflow-memory capture skills, and landed browser/docs/design extraction skills."); RegistryState.Entries = { MakeSkillEntry( @@ -1394,6 +1410,88 @@ namespace HyperTwistSkillCoreLibraryInternal ), TEXT("Landed first-party workflow capture skill over authoritative review-plan and follow-up routine entities.") ), + MakeSkillEntry( + TEXT("skill/extract-docs"), + TEXT("Extract Docs"), + TEXT("lane/skillization/browser-docs-design"), + TEXT("feature/skills/extract-docs"), + EHyperTwistSkillFamily::BrowserDocsDesign, + EHyperTwistSkillStatus::ImplementedNow, + false, + true, + { + MakeCommandBinding( + TEXT("command/skills/extract-docs"), + TEXT("service/skills/extract-docs"), + TEXT("feature/skills/extract-docs"), + TEXT("docs/structured-extraction"), + true, + TEXT("Live first-party structured docs-extraction skill over authoritative HyperTwist canon surfaces.") + ) + }, + { + MakePermissionScope( + TEXT("scope/skills/extract-docs"), + TEXT("Extract Docs"), + false, + false, + false, + false, + false, + false, + true, + TEXT("Reads first-party documentation source surfaces and emits bounded structured extraction output.") + ) + }, + MakeProvenanceDeclaration( + EHyperTwistSkillLogPolicy::InvocationLedgerRequired, + {TEXT("artifact/docs-extraction-brief")}, + true, + TEXT("Docs-extraction output must remain provenance-visible, derived-only, and bounded to structured extraction.") + ), + TEXT("Landed first-party structured docs-extraction skill over authoritative HyperTwist canon surfaces.") + ), + MakeSkillEntry( + TEXT("skill/extract-design-spec"), + TEXT("Extract Design Spec"), + TEXT("lane/skillization/browser-docs-design"), + TEXT("feature/skills/extract-design-spec"), + EHyperTwistSkillFamily::BrowserDocsDesign, + EHyperTwistSkillStatus::ImplementedNow, + false, + true, + { + MakeCommandBinding( + TEXT("command/skills/extract-design-spec"), + TEXT("service/skills/extract-design-spec"), + TEXT("feature/skills/extract-design-spec"), + TEXT("design/structured-spec-extraction"), + true, + TEXT("Live first-party structured design-spec extraction skill over authoritative HyperTwist design and packet surfaces.") + ) + }, + { + MakePermissionScope( + TEXT("scope/skills/extract-design-spec"), + TEXT("Extract Design Spec"), + false, + false, + false, + false, + false, + false, + true, + TEXT("Reads first-party design and packet source surfaces to emit bounded structured design-spec extraction output.") + ) + }, + MakeProvenanceDeclaration( + EHyperTwistSkillLogPolicy::InvocationLedgerRequired, + {TEXT("artifact/design-spec-extraction-brief")}, + true, + TEXT("Design-spec extraction output must remain provenance-visible, derived-only, and must not widen into design translation.") + ), + TEXT("Landed first-party structured design-spec extraction skill over authoritative HyperTwist design and packet surfaces.") + ), MakeSkillEntry( TEXT("skill/provider-routing-inspector"), TEXT("Provider Routing Inspector"), @@ -1532,7 +1630,7 @@ namespace HyperTwistSkillCoreLibraryInternal RegistryState.bNoAdHocMetadataRequired = true; RegistryState.StatusCounts = { - MakeStatusCount(EHyperTwistSkillStatus::ImplementedNow, 8), + MakeStatusCount(EHyperTwistSkillStatus::ImplementedNow, 12), MakeStatusCount(EHyperTwistSkillStatus::CommandContractPending, 1), MakeStatusCount(EHyperTwistSkillStatus::CleanRoomSkillSpecSpecified, 1), MakeStatusCount(EHyperTwistSkillStatus::PlaceholderFamily, 1) @@ -1544,6 +1642,7 @@ namespace HyperTwistSkillCoreLibraryInternal MakeFamilyCount(EHyperTwistSkillFamily::MemoryContinuity, 8), MakeFamilyCount(EHyperTwistSkillFamily::ProviderOperations, 1), MakeFamilyCount(EHyperTwistSkillFamily::TrainingCoaching, 1), + MakeFamilyCount(EHyperTwistSkillFamily::BrowserDocsDesign, 2), MakeFamilyCount(EHyperTwistSkillFamily::DomainCreative, 1) }; @@ -3020,3 +3119,215 @@ UHyperTwistSkillCoreLibrary::DeriveSkillWorkflowMemoryCaptureState( return WorkflowCaptureState; } + +FHyperTwistSkillExtractionState +UHyperTwistSkillCoreLibrary::DeriveSkillExtractionState( + const FHyperTwistSkillRegistryState& RegistryState, + const FHyperTwistSkillControlState& ControlState, + const FHyperTwistSkillAuthoringHarnessState& AuthoringHarnessState +) +{ + using namespace HyperTwistSkillCoreLibraryInternal; + + if (!RegistryState.IsStructurallyValid() + || !ControlState.IsStructurallyValid() + || !AuthoringHarnessState.IsStructurallyValid() + || RegistryState.RegistryId != ControlState.RegistryId + || RegistryState.RegistryId != AuthoringHarnessState.RegistryId + || RegistryState.CommandSurfaceRootId != ControlState.CommandSurfaceRootId + || RegistryState.CommandSurfaceRootId != AuthoringHarnessState.CommandSurfaceRootId) + { + return FHyperTwistSkillExtractionState(); + } + + FHyperTwistSkillExtractionState ExtractionState; + ExtractionState.RegistryId = RegistryState.RegistryId; + ExtractionState.ManifestVersion = TEXT("s4a-v1"); + ExtractionState.ReferenceUtc = TEXT("2026-05-29T09:55:00Z"); + ExtractionState.CommandSurfaceRootId = RegistryState.CommandSurfaceRootId; + ExtractionState.TemplateVersion = TEXT("skill-extraction-v1"); + ExtractionState.bEveryLiveSkillReadsAuthoritativeSourceSurfaces = true; + ExtractionState.bEverySkillPreservesOptionalAssistiveOffState = true; + ExtractionState.bEveryLiveSkillHasValidationHarnessCoverage = true; + ExtractionState.bStructuredExtractionRemainsBounded = true; + ExtractionState.bNoBrowserDiagnosticsWidening = true; + ExtractionState.bNoDesignTranslationWidening = true; + ExtractionState.Summary = + TEXT("First-party extraction skill layer over authoritative docs and design-spec source surfaces."); + + auto AddPreviewHeadline = []( + TArray& PreviewHeadlines, + const FString& Headline + ) + { + if (!Headline.IsEmpty()) + { + PreviewHeadlines.AddUnique(Headline); + } + }; + + auto BuildExtractionSkill = [&]( + const FString& SkillId + ) -> FHyperTwistSkillExtractionSkill + { + const FHyperTwistSkillManifestEntry* Entry = + FindManifestEntryById(RegistryState, SkillId); + const FHyperTwistSkillControlStateEntry* ControlEntry = + FindControlStateEntryById(ControlState, SkillId); + const FHyperTwistSkillAuthoringExampleState* ExampleState = + FindAuthoringExampleBySkillId(AuthoringHarnessState, SkillId); + if (Entry == nullptr + || !Entry->IsStructurallyValid() + || !IsExtractionSkill(SkillId) + || ControlEntry == nullptr + || !ControlEntry->IsStructurallyValid() + || !ControlEntry->bInstalled + || !ControlEntry->bOptionalAssistive + || ExampleState == nullptr + || !ExampleState->IsStructurallyValid() + || !HasLiveEvalValidationCase(AuthoringHarnessState, SkillId)) + { + return FHyperTwistSkillExtractionSkill(); + } + + FHyperTwistSkillExtractionSkill 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.OutputArtifactKinds = Entry->Provenance.ProducedArtifactKinds; + SkillState.bLiveSkill = true; + SkillState.bReadsAuthoritativeSourceSurfaces = true; + SkillState.bAvailableNow = true; + SkillState.bRequiresOwnerActivation = false; + SkillState.bPreservesOptionalAssistiveOffState = ControlEntry->bInertWhenDisabled; + SkillState.bDerivedAssistiveOnly = Entry->bOptionalAssistive; + SkillState.bHasValidationHarnessCoverage = true; + SkillState.bStructuredExtractionOnly = true; + SkillState.bAvoidsBrowserDiagnosticsWidening = true; + SkillState.bAvoidsDesignTranslationWidening = true; + + if (SkillId == TEXT("skill/extract-docs")) + { + SkillState.SourceSurfaceIds = { + TEXT("source-surface/feature-registry"), + TEXT("source-surface/architecture-manual"), + TEXT("source-surface/roadmap"), + TEXT("source-surface/skills-manual"), + TEXT("source-surface/provenance-and-trust-model"), + TEXT("source-surface/implementation-phase-kickoff") + }; + SkillState.StructuredFieldIds = { + TEXT("field/docs-source-title"), + TEXT("field/docs-owner-lane"), + TEXT("field/docs-owner-feature"), + TEXT("field/docs-bounded-status"), + TEXT("field/docs-provenance-note"), + TEXT("field/docs-next-clean-step") + }; + AddPreviewHeadline( + SkillState.PreviewHeadlines, + TEXT("Feature registry extraction") + ); + AddPreviewHeadline( + SkillState.PreviewHeadlines, + TEXT("Architecture manual extraction") + ); + AddPreviewHeadline( + SkillState.PreviewHeadlines, + TEXT("Roadmap and provenance extraction") + ); + SkillState.bExtractsDocumentation = true; + SkillState.bExtractsDesignSpecs = false; + SkillState.Summary = + TEXT("Live first-party structured docs-extraction skill over authoritative HyperTwist canon surfaces."); + } + else if (SkillId == TEXT("skill/extract-design-spec")) + { + SkillState.SourceSurfaceIds = { + TEXT("source-surface/skillization-doctrine"), + TEXT("source-surface/architecture-manual"), + TEXT("source-surface/implementation-packets"), + TEXT("source-surface/feature-registry"), + TEXT("source-surface/roadmap") + }; + SkillState.StructuredFieldIds = { + TEXT("field/design-target-feature"), + TEXT("field/design-owner-lane"), + TEXT("field/design-command-surface"), + TEXT("field/design-output-artifact"), + TEXT("field/design-bounded-non-goals"), + TEXT("field/design-provenance-guard") + }; + AddPreviewHeadline( + SkillState.PreviewHeadlines, + TEXT("Skill packet boundary extraction") + ); + AddPreviewHeadline( + SkillState.PreviewHeadlines, + TEXT("Architecture seam extraction") + ); + AddPreviewHeadline( + SkillState.PreviewHeadlines, + TEXT("Bounded design-spec extraction") + ); + SkillState.bExtractsDocumentation = false; + SkillState.bExtractsDesignSpecs = true; + SkillState.Summary = + TEXT("Live first-party structured design-spec extraction skill over authoritative HyperTwist design and packet surfaces."); + } + + SkillState.SourceSurfaceCount = SkillState.SourceSurfaceIds.Num(); + SkillState.StructuredFieldCount = SkillState.StructuredFieldIds.Num(); + return SkillState; + }; + + for (const FString& SkillId : { + FString(TEXT("skill/extract-docs")), + FString(TEXT("skill/extract-design-spec")) + }) + { + const FHyperTwistSkillExtractionSkill SkillState = + BuildExtractionSkill(SkillId); + if (!SkillState.IsStructurallyValid()) + { + return FHyperTwistSkillExtractionState(); + } + + ExtractionState.Skills.Add(SkillState); + } + + for (const FHyperTwistSkillExtractionSkill& SkillState : ExtractionState.Skills) + { + ExtractionState.LiveSkillCount += SkillState.bLiveSkill ? 1 : 0; + ExtractionState.AvailableNowCount += SkillState.bAvailableNow ? 1 : 0; + ExtractionState.DocsExtractionSkillCount += + SkillState.bExtractsDocumentation ? 1 : 0; + ExtractionState.DesignSpecExtractionSkillCount += + SkillState.bExtractsDesignSpecs ? 1 : 0; + ExtractionState.bEverySkillPreservesOptionalAssistiveOffState &= + SkillState.bPreservesOptionalAssistiveOffState; + ExtractionState.bStructuredExtractionRemainsBounded &= + SkillState.bStructuredExtractionOnly; + ExtractionState.bNoBrowserDiagnosticsWidening &= + SkillState.bAvoidsBrowserDiagnosticsWidening; + ExtractionState.bNoDesignTranslationWidening &= + SkillState.bAvoidsDesignTranslationWidening; + + if (SkillState.bLiveSkill) + { + ExtractionState.bEveryLiveSkillReadsAuthoritativeSourceSurfaces &= + SkillState.bReadsAuthoritativeSourceSurfaces; + ExtractionState.bEveryLiveSkillHasValidationHarnessCoverage &= + SkillState.bHasValidationHarnessCoverage; + } + } + + ExtractionState.SkillCount = ExtractionState.Skills.Num(); + + return ExtractionState; +} diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistBootstrap/HyperTwistContractLibrary.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistBootstrap/HyperTwistContractLibrary.h index ac1f250..c945123 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistBootstrap/HyperTwistContractLibrary.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistBootstrap/HyperTwistContractLibrary.h @@ -199,6 +199,9 @@ public: static FHyperTwistSkillWorkflowMemoryCaptureState MakeSampleSkillWorkflowMemoryCaptureState(); + UFUNCTION(BlueprintPure, Category = "HyperTwist|Skills") + static FHyperTwistSkillExtractionState MakeSampleSkillExtractionState(); + UFUNCTION(BlueprintPure, Category = "HyperTwist|Training") static FHyperTwistTrainingRepositoryIntegrityReport MakeSampleTrainingRepositoryIntegrityReport(); @@ -438,6 +441,11 @@ public: const FHyperTwistSkillWorkflowMemoryCaptureState& SkillWorkflowMemoryCaptureState ); + UFUNCTION(BlueprintCallable, Category = "HyperTwist|Serialization") + static FString SerializeSkillExtractionStateToJson( + const FHyperTwistSkillExtractionState& SkillExtractionState + ); + UFUNCTION(BlueprintPure, Category = "HyperTwist|Serialization") static FString SerializeTrainingTimerExportPacketToJson(const FHyperTwistTrainingTimerExportPacket& TimerExportPacket); @@ -570,6 +578,12 @@ public: FHyperTwistSkillWorkflowMemoryCaptureState& OutSkillWorkflowMemoryCaptureState ); + UFUNCTION(BlueprintCallable, Category = "HyperTwist|Serialization") + static bool DeserializeSkillExtractionStateFromJson( + const FString& Json, + FHyperTwistSkillExtractionState& OutSkillExtractionState + ); + 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 ff46ae5..728936d 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistSkills/HyperTwistSkillCoreLibrary.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistSkills/HyperTwistSkillCoreLibrary.h @@ -83,4 +83,11 @@ public: const FHyperTwistMemoryLedgerState& LedgerState, const FHyperTwistMemoryChronicleContinuityState& ChronicleContinuityState ); + + UFUNCTION(BlueprintPure, Category = "HyperTwist|Skills") + static FHyperTwistSkillExtractionState DeriveSkillExtractionState( + const FHyperTwistSkillRegistryState& RegistryState, + const FHyperTwistSkillControlState& ControlState, + const FHyperTwistSkillAuthoringHarnessState& AuthoringHarnessState + ); }; diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistSkills/HyperTwistSkillTypes.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistSkills/HyperTwistSkillTypes.h index 22cf2cc..042384c 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistSkills/HyperTwistSkillTypes.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistSkills/HyperTwistSkillTypes.h @@ -24,6 +24,7 @@ enum class EHyperTwistSkillFamily : uint8 MemoryContinuity UMETA(DisplayName = "Memory And Continuity"), ProviderOperations UMETA(DisplayName = "Provider And Operations"), TrainingCoaching UMETA(DisplayName = "Training And Coaching"), + BrowserDocsDesign UMETA(DisplayName = "Browser Docs And Design"), DomainCreative UMETA(DisplayName = "Domain And Creative") }; @@ -3240,3 +3241,302 @@ struct FHyperTwistSkillWorkflowMemoryCaptureState == bComputedOpaqueSummaryGuard; } }; + +USTRUCT(BlueprintType) +struct FHyperTwistSkillExtractionSkill +{ + 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 StructuredFieldIds; + + 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 StructuredFieldCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bLiveSkill = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bReadsAuthoritativeSourceSurfaces = 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 bStructuredExtractionOnly = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bAvoidsBrowserDiagnosticsWidening = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bAvoidsDesignTranslationWidening = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bExtractsDocumentation = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bExtractsDesignSpecs = 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 + || StructuredFieldIds.Num() == 0 + || OutputArtifactKinds.Num() == 0 + || PreviewHeadlines.Num() == 0 + || SourceSurfaceCount != SourceSurfaceIds.Num() + || StructuredFieldCount != StructuredFieldIds.Num() + || !bReadsAuthoritativeSourceSurfaces + || !bPreservesOptionalAssistiveOffState + || !bDerivedAssistiveOnly + || !bHasValidationHarnessCoverage + || !bStructuredExtractionOnly + || !bAvoidsBrowserDiagnosticsWidening + || !bAvoidsDesignTranslationWidening + || bExtractsDocumentation == bExtractsDesignSpecs) + { + 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 : StructuredFieldIds) + { + 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 FHyperTwistSkillExtractionState +{ + 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 DocsExtractionSkillCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 DesignSpecExtractionSkillCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bEveryLiveSkillReadsAuthoritativeSourceSurfaces = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bEverySkillPreservesOptionalAssistiveOffState = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bEveryLiveSkillHasValidationHarnessCoverage = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bStructuredExtractionRemainsBounded = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bNoBrowserDiagnosticsWidening = 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() + || !bEveryLiveSkillReadsAuthoritativeSourceSurfaces + || !bEverySkillPreservesOptionalAssistiveOffState + || !bEveryLiveSkillHasValidationHarnessCoverage + || !bStructuredExtractionRemainsBounded + || !bNoBrowserDiagnosticsWidening + || !bNoDesignTranslationWidening) + { + return false; + } + + TArray SeenSkillIds; + int32 ComputedLiveSkillCount = 0; + int32 ComputedAvailableNowCount = 0; + int32 ComputedDocsExtractionSkillCount = 0; + int32 ComputedDesignSpecExtractionSkillCount = 0; + bool bComputedEveryLiveSkillReadsAuthoritativeSourceSurfaces = true; + bool bComputedEverySkillPreservesOptionalAssistiveOffState = true; + bool bComputedEveryLiveSkillHasValidationHarnessCoverage = true; + bool bComputedStructuredExtractionBounded = true; + bool bComputedNoBrowserDiagnosticsWidening = true; + bool bComputedNoDesignTranslationWidening = true; + + for (const FHyperTwistSkillExtractionSkill& 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; + ComputedDocsExtractionSkillCount += Skill.bExtractsDocumentation ? 1 : 0; + ComputedDesignSpecExtractionSkillCount += Skill.bExtractsDesignSpecs ? 1 : 0; + bComputedEverySkillPreservesOptionalAssistiveOffState &= + Skill.bPreservesOptionalAssistiveOffState; + bComputedStructuredExtractionBounded &= Skill.bStructuredExtractionOnly; + bComputedNoBrowserDiagnosticsWidening &= + Skill.bAvoidsBrowserDiagnosticsWidening; + bComputedNoDesignTranslationWidening &= + Skill.bAvoidsDesignTranslationWidening; + + if (Skill.bLiveSkill) + { + bComputedEveryLiveSkillReadsAuthoritativeSourceSurfaces &= + Skill.bReadsAuthoritativeSourceSurfaces; + bComputedEveryLiveSkillHasValidationHarnessCoverage &= + Skill.bHasValidationHarnessCoverage; + } + } + + return LiveSkillCount == ComputedLiveSkillCount + && AvailableNowCount == ComputedAvailableNowCount + && DocsExtractionSkillCount == ComputedDocsExtractionSkillCount + && DesignSpecExtractionSkillCount == ComputedDesignSpecExtractionSkillCount + && bEveryLiveSkillReadsAuthoritativeSourceSurfaces + == bComputedEveryLiveSkillReadsAuthoritativeSourceSurfaces + && bEverySkillPreservesOptionalAssistiveOffState + == bComputedEverySkillPreservesOptionalAssistiveOffState + && bEveryLiveSkillHasValidationHarnessCoverage + == bComputedEveryLiveSkillHasValidationHarnessCoverage + && bStructuredExtractionRemainsBounded + == bComputedStructuredExtractionBounded + && bNoBrowserDiagnosticsWidening + == bComputedNoBrowserDiagnosticsWidening + && bNoDesignTranslationWidening + == bComputedNoDesignTranslationWidening; + } +}; diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS1ARegistryManifestContractTest.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS1ARegistryManifestContractTest.cpp index 394135a..8d75771 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 thirteen declared skills after S3-C lands."), + TEXT("The sample S1-A registry must expose fifteen declared skills after S4-A lands."), RegistryState.SkillCount, - 13 + 15 ); 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 ten implemented skill entries after S3-C lands."), + TEXT("The sample S1-A registry must keep twelve implemented skill entries after S4-A lands."), HyperTwistSkillPhaseS1ATestInternal::FindStatusCount( RegistryState, EHyperTwistSkillStatus::ImplementedNow ), - 10 + 12 ); TestEqual( TEXT("The sample S1-A registry must keep one command-contract-pending entry for note capture."), @@ -125,6 +125,14 @@ 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."), + HyperTwistSkillPhaseS1ATestInternal::FindFamilyCount( + RegistryState, + EHyperTwistSkillFamily::BrowserDocsDesign + ), + 2 + ); const FHyperTwistSkillManifestEntry* GovernanceSkill = HyperTwistSkillPhaseS1ATestInternal::FindSkillById( @@ -199,6 +207,29 @@ bool FHyperTwistSkillPhaseS1ARegistryManifestTest::RunTest(const FString& Parame ); } + const FHyperTwistSkillManifestEntry* DocsExtractionSkill = + HyperTwistSkillPhaseS1ATestInternal::FindSkillById( + RegistryState, + TEXT("skill/extract-docs") + ); + TestNotNull( + TEXT("The extract-docs skill entry must exist."), + DocsExtractionSkill + ); + if (DocsExtractionSkill != nullptr) + { + TestEqual( + TEXT("The extract-docs skill must be implemented now."), + DocsExtractionSkill->Status, + EHyperTwistSkillStatus::ImplementedNow + ); + TestEqual( + TEXT("The extract-docs skill must bind to the first-party docs extraction service."), + DocsExtractionSkill->CommandBindings[0].ServiceBindingId, + FString(TEXT("service/skills/extract-docs")) + ); + } + return true; } diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS1BSettingsVisibilityContractTest.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS1BSettingsVisibilityContractTest.cpp index b02afb3..8992df2 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 six installed skills."), + TEXT("The sample S1-B control state must preserve all fifteen installed skills after S4-A lands."), ControlState.SkillCount, - 6 + 15 ); TestEqual( TEXT("The default S1-B control state must keep one effective enabled skill."), @@ -134,6 +134,32 @@ bool FHyperTwistSkillPhaseS1BSettingsVisibilityTest::RunTest( ); } + const FHyperTwistSkillControlStateEntry* DocsExtractionState = + HyperTwistSkillPhaseS1BTestInternal::FindSkillStateById( + ControlState, + TEXT("skill/extract-docs") + ); + TestNotNull( + TEXT("The extract-docs skill state must exist."), + DocsExtractionState + ); + if (DocsExtractionState != nullptr) + { + TestFalse( + TEXT("The extract-docs skill must remain opt-in by default."), + DocsExtractionState->bEffectiveEnabled + ); + TestTrue( + TEXT("The extract-docs skill must remain visible by default."), + DocsExtractionState->bEffectiveVisible + ); + TestEqual( + TEXT("The extract-docs skill must use the browser/docs/design visibility group."), + DocsExtractionState->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 0356ff9..f430457 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, - 6 + 12 ); 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, - 4 + 10 ); TestEqual( TEXT("The sample audit ledger should contain the expected failed invocation count."), @@ -218,6 +218,29 @@ bool FHyperTwistSkillPhaseS1CFailureCancelRecordingTest::RunTest(const FString& ); } + const FHyperTwistSkillInvocationRecord* DocsExtractionRecord = + HyperTwistSkillPhaseS1CTestInternal::FindInvocationRecordBySkillId( + AuditLedgerState, + TEXT("skill/extract-docs") + ); + TestNotNull( + TEXT("The docs-extraction skill invocation should be present in the sample audit ledger."), + DocsExtractionRecord + ); + if (DocsExtractionRecord != nullptr) + { + TestEqual( + TEXT("The docs-extraction skill should record a success outcome."), + DocsExtractionRecord->Outcome, + EHyperTwistSkillInvocationOutcome::Succeeded + ); + TestEqual( + TEXT("The docs-extraction skill should emit the bounded docs extraction artifact."), + DocsExtractionRecord->ProducedArtifacts[0].ArtifactKind, + FString(TEXT("artifact/docs-extraction-brief")) + ); + } + return true; } diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS1DAuthoringValidationHarnessContractTest.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS1DAuthoringValidationHarnessContractTest.cpp index 6d8c14b..deaee33 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS1DAuthoringValidationHarnessContractTest.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS1DAuthoringValidationHarnessContractTest.cpp @@ -249,6 +249,44 @@ bool FHyperTwistSkillPhaseS1DValidationHarnessCoverageTest::RunTest(const FStrin ); } + const FHyperTwistSkillValidationContractCase* DocsExtractionEval = + HyperTwistSkillPhaseS1DTestInternal::FindValidationCase( + HarnessState, + TEXT("skill/extract-docs"), + EHyperTwistSkillValidationContractKind::Eval + ); + TestNotNull( + TEXT("The extract-docs skill should have an eval validation contract."), + DocsExtractionEval + ); + if (DocsExtractionEval != nullptr) + { + TestEqual( + TEXT("The extract-docs skill eval contract should run live after S4-A lands."), + DocsExtractionEval->ExecutionMode, + EHyperTwistSkillValidationExecutionMode::LiveContract + ); + } + + const FHyperTwistSkillValidationContractCase* DesignSpecExtractionEval = + HyperTwistSkillPhaseS1DTestInternal::FindValidationCase( + HarnessState, + TEXT("skill/extract-design-spec"), + EHyperTwistSkillValidationContractKind::Eval + ); + TestNotNull( + TEXT("The extract-design-spec skill should have an eval validation contract."), + DesignSpecExtractionEval + ); + if (DesignSpecExtractionEval != nullptr) + { + TestEqual( + TEXT("The extract-design-spec skill eval contract should run live after S4-A lands."), + DesignSpecExtractionEval->ExecutionMode, + EHyperTwistSkillValidationExecutionMode::LiveContract + ); + } + const FHyperTwistSkillValidationContractCase* RouxEval = HyperTwistSkillPhaseS1DTestInternal::FindValidationCase( HarnessState, diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS4AExtractionContractTest.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS4AExtractionContractTest.cpp new file mode 100644 index 0000000..e87c876 --- /dev/null +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS4AExtractionContractTest.cpp @@ -0,0 +1,204 @@ +// Copyright HyperTwist, Inc. All Rights Reserved. + +#include "Misc/AutomationTest.h" + +#include "HyperTwistBootstrap/HyperTwistContractLibrary.h" + +#if WITH_AUTOMATION_TESTS + +namespace HyperTwistSkillPhaseS4ATestInternal +{ + const FHyperTwistSkillExtractionSkill* FindSkillById( + const FHyperTwistSkillExtractionState& ExtractionState, + const FString& SkillId + ) + { + for (const FHyperTwistSkillExtractionSkill& Skill : ExtractionState.Skills) + { + if (Skill.SkillId == SkillId) + { + return &Skill; + } + } + + return nullptr; + } +} + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FHyperTwistSkillPhaseS4AExtractionCoverageTest, + "HyperTwist.FirstParty.Skill.PhaseS4A.ExtractionCoverage", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter +) + +bool FHyperTwistSkillPhaseS4AExtractionCoverageTest::RunTest(const FString& Parameters) +{ + const FHyperTwistSkillExtractionState ExtractionState = + UHyperTwistContractLibrary::MakeSampleSkillExtractionState(); + + TestTrue( + TEXT("The sample S4-A extraction skill state should be structurally valid."), + ExtractionState.IsStructurallyValid() + ); + TestEqual( + TEXT("S4-A should expose two extraction skills."), + ExtractionState.SkillCount, + 2 + ); + TestEqual( + TEXT("S4-A should expose two live extraction skills."), + ExtractionState.LiveSkillCount, + 2 + ); + TestEqual( + TEXT("S4-A should expose one docs-extraction skill."), + ExtractionState.DocsExtractionSkillCount, + 1 + ); + TestEqual( + TEXT("S4-A should expose one design-spec-extraction skill."), + ExtractionState.DesignSpecExtractionSkillCount, + 1 + ); + + const FHyperTwistSkillExtractionSkill* DocsSkill = + HyperTwistSkillPhaseS4ATestInternal::FindSkillById( + ExtractionState, + TEXT("skill/extract-docs") + ); + TestNotNull( + TEXT("The extract-docs skill should exist."), + DocsSkill + ); + if (DocsSkill != nullptr) + { + TestEqual( + TEXT("The extract-docs skill should bind to the bounded docs extraction artifact."), + DocsSkill->OutputArtifactKinds[0], + FString(TEXT("artifact/docs-extraction-brief")) + ); + TestTrue( + TEXT("The extract-docs skill should declare documentation extraction."), + DocsSkill->bExtractsDocumentation + ); + } + + return true; +} + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FHyperTwistSkillPhaseS4ABoundedExtractionTest, + "HyperTwist.FirstParty.Skill.PhaseS4A.BoundedExtraction", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter +) + +bool FHyperTwistSkillPhaseS4ABoundedExtractionTest::RunTest(const FString& Parameters) +{ + const FHyperTwistSkillExtractionState ExtractionState = + UHyperTwistContractLibrary::MakeSampleSkillExtractionState(); + + TestTrue( + TEXT("The sample S4-A extraction skill state should be structurally valid."), + ExtractionState.IsStructurallyValid() + ); + TestTrue( + TEXT("Every live S4-A skill should read authoritative source surfaces."), + ExtractionState.bEveryLiveSkillReadsAuthoritativeSourceSurfaces + ); + TestTrue( + TEXT("Every live S4-A skill should keep validation-harness coverage."), + ExtractionState.bEveryLiveSkillHasValidationHarnessCoverage + ); + TestTrue( + TEXT("S4-A extraction should remain structurally bounded."), + ExtractionState.bStructuredExtractionRemainsBounded + ); + TestTrue( + TEXT("S4-A extraction should not widen into browser diagnostics."), + ExtractionState.bNoBrowserDiagnosticsWidening + ); + TestTrue( + TEXT("S4-A extraction should not widen into design translation."), + ExtractionState.bNoDesignTranslationWidening + ); + + const FHyperTwistSkillExtractionSkill* DesignSpecSkill = + HyperTwistSkillPhaseS4ATestInternal::FindSkillById( + ExtractionState, + TEXT("skill/extract-design-spec") + ); + TestNotNull( + TEXT("The extract-design-spec skill should exist."), + DesignSpecSkill + ); + if (DesignSpecSkill != nullptr) + { + TestTrue( + TEXT("The extract-design-spec skill should declare design-spec extraction."), + DesignSpecSkill->bExtractsDesignSpecs + ); + TestTrue( + TEXT("The extract-design-spec skill should explicitly avoid design translation widening."), + DesignSpecSkill->bAvoidsDesignTranslationWidening + ); + TestTrue( + TEXT("The extract-design-spec skill should explicitly avoid browser diagnostics widening."), + DesignSpecSkill->bAvoidsBrowserDiagnosticsWidening + ); + } + + return true; +} + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FHyperTwistSkillPhaseS4ASerializationRoundTripTest, + "HyperTwist.FirstParty.Skill.PhaseS4A.SerializationRoundTrip", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter +) + +bool FHyperTwistSkillPhaseS4ASerializationRoundTripTest::RunTest(const FString& Parameters) +{ + const FHyperTwistSkillExtractionState ExtractionState = + UHyperTwistContractLibrary::MakeSampleSkillExtractionState(); + + TestTrue( + TEXT("The sample S4-A extraction skill state should be structurally valid before serialization."), + ExtractionState.IsStructurallyValid() + ); + + const FString Json = + UHyperTwistContractLibrary::SerializeSkillExtractionStateToJson( + ExtractionState + ); + TestTrue( + TEXT("Serialized S4-A JSON should include the browser-diagnostics widening guard field."), + Json.Contains(TEXT("bNoBrowserDiagnosticsWidening")) + ); + + FHyperTwistSkillExtractionState RoundTrippedState; + TestTrue( + TEXT("Deserializing the S4-A extraction JSON should succeed."), + UHyperTwistContractLibrary::DeserializeSkillExtractionStateFromJson( + Json, + RoundTrippedState + ) + ); + TestTrue( + TEXT("Round-tripped S4-A extraction state should remain structurally valid."), + RoundTrippedState.IsStructurallyValid() + ); + TestEqual( + TEXT("Round-tripped S4-A skill count should match the original sample."), + RoundTrippedState.SkillCount, + ExtractionState.SkillCount + ); + TestEqual( + TEXT("Round-tripped S4-A live-skill count should match the original sample."), + RoundTrippedState.LiveSkillCount, + ExtractionState.LiveSkillCount + ); + + return true; +} + +#endif diff --git a/docs/arch/HYPERTWIST_PHASES4_A_FIRST_PARTY_EXTRACTION_SKILLS_IMPLEMENTATION_PACKET_2026-05-29.md b/docs/arch/HYPERTWIST_PHASES4_A_FIRST_PARTY_EXTRACTION_SKILLS_IMPLEMENTATION_PACKET_2026-05-29.md new file mode 100644 index 0000000..fe3022a --- /dev/null +++ b/docs/arch/HYPERTWIST_PHASES4_A_FIRST_PARTY_EXTRACTION_SKILLS_IMPLEMENTATION_PACKET_2026-05-29.md @@ -0,0 +1,34 @@ +# HyperTwist Phase S4-A Implementation Packet + +Date: `2026-05-29` + +Packet: `Phase S4-A` + +Title: `first-party extraction skills` + +## Outcome + +Implemented now. + +## Landed scope + +- live `skill/extract-docs` +- live `skill/extract-design-spec` +- bounded first-party extraction state over authoritative first-party + docs/design source surfaces +- registry, control-state, audit-ledger, authoring-harness, sample-contract, + and JSON round-trip support + +## Preserved boundaries + +- extraction remains structured and provenance-visible +- no browser diagnostics widening in this packet +- no design translation widening in this packet +- the placeholder domain/creative family remains separate and non-source-grounded + +## Validation + +- build target: `UnrealHyperTwistEditor Win64 Development` +- focused `S4-A` automation passed for extraction coverage, bounded extraction, + and serialization round-trip +- full `Phase S1` skill substrate regression passed after the new family landed diff --git a/docs/arch/HYPERTWIST_PHASES4_A_FIRST_PARTY_EXTRACTION_SKILLS_PREPARATION_PACKET_2026-05-29.md b/docs/arch/HYPERTWIST_PHASES4_A_FIRST_PARTY_EXTRACTION_SKILLS_PREPARATION_PACKET_2026-05-29.md new file mode 100644 index 0000000..a95a619 --- /dev/null +++ b/docs/arch/HYPERTWIST_PHASES4_A_FIRST_PARTY_EXTRACTION_SKILLS_PREPARATION_PACKET_2026-05-29.md @@ -0,0 +1,40 @@ +# HyperTwist Phase S4-A Preparation Packet + +Date: `2026-05-29` + +Packet: `Phase S4-A` + +Title: `first-party extraction skills` + +## Goal + +Land the next bounded browser/docs/design skill seam by exposing first-party +structured extraction skills over authoritative HyperTwist docs and design-spec +source surfaces. + +## Scope + +- `skill/extract-docs` +- `skill/extract-design-spec` +- first-party extraction state over authoritative first-party docs/design + source surfaces +- registry, control-state, audit-ledger, authoring-harness, sample-contract, + and JSON support + +## Required boundaries + +- do not widen into browser diagnostics +- do not widen into design-to-native translation +- keep extraction structured, provenance-visible, derived-assistive, and + first-party owned + +## Inputs + +- landed `S1-A` through `S3-C` skill substrate +- landed first-party architecture, roadmap, feature-registry, and provenance + authority surfaces + +## Acceptance gate + +- extraction remains bounded to structured docs/design-spec output and does not + claim browser tracing, API discovery, or design translation ownership diff --git a/docs/ops/HYPERTWIST_IMPLEMENTATION_PHASE_1_KICKOFF.md b/docs/ops/HYPERTWIST_IMPLEMENTATION_PHASE_1_KICKOFF.md index 49baac4..3f41b5a 100644 --- a/docs/ops/HYPERTWIST_IMPLEMENTATION_PHASE_1_KICKOFF.md +++ b/docs/ops/HYPERTWIST_IMPLEMENTATION_PHASE_1_KICKOFF.md @@ -291,4 +291,6 @@ Specifically: now landed in current code - the bounded first-party `Phase S3-C` workflow-memory capture skill packet is now landed in current code -- `S4-A` extraction skills are now the next clean move +- 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 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 6a9b469..552b21a 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 @@ -405,6 +405,10 @@ Current landed posture: and queue follow-up entities - workflow capture remains separate from user-authored notes and does not 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 ### S4 - browser/docs/design skills @@ -540,11 +544,13 @@ These are target-shape command families, not claims of implemented reality. The next correct sequence is: -1. `S4-A` extraction skills -2. broader browser, workflow, provider, and domain skill widening +1. `S4-B` browser diagnostics skills +2. `S4-C` translation/design-to-native skills +3. broader workflow, provider, and domain skill widening -Broader memory, browser, workflow, provider, and domain skill widening should -wait until that base exists. +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. ## 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 02e23ad..48b8d90 100644 --- a/docs/v6_5_deep_manual_pack/HyperTwist/ARCHITECTURE.md +++ b/docs/v6_5_deep_manual_pack/HyperTwist/ARCHITECTURE.md @@ -265,3 +265,7 @@ Future skill growth must follow: `capture-follow-up-routine` over authoritative procedural workflow ledger entities plus review/queue continuity evidence, while remaining separate from 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 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 2cb72af..24afa64 100644 --- a/docs/v6_5_deep_manual_pack/HyperTwist/FEATURE_REGISTRY.md +++ b/docs/v6_5_deep_manual_pack/HyperTwist/FEATURE_REGISTRY.md @@ -304,9 +304,10 @@ 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`, and `Phase S3-C` 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, and bounded workflow-memory capture skill state are live as bounded substrate. `S4-A` 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`, 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. | | 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 broader browser/docs/design skill widening is now the next family step. | +| 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. | +| 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. | | 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 c07acdb..0f8c858 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 @@ -128,6 +128,10 @@ The landed bounded first-party `Phase S1-A` packet keeps: capture output provenance-visible while requiring capture state to remain anchored to authoritative workflow entities, separate from user-authored 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 ## 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 db7a72c..d9279dc 100644 --- a/docs/v6_5_deep_manual_pack/HyperTwist/ROADMAP.md +++ b/docs/v6_5_deep_manual_pack/HyperTwist/ROADMAP.md @@ -187,7 +187,9 @@ Canonical discovery surfaces for roadmap interpretation: now landed in current code - the bounded first-party `Phase S3-C` workflow-memory capture skill packet is now landed in current code -- `S4-A` extraction skills are now the next clean move +- 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 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 6bf07b4..2fa7bc0 100644 --- a/docs/v6_5_deep_manual_pack/HyperTwist/SKILLS.md +++ b/docs/v6_5_deep_manual_pack/HyperTwist/SKILLS.md @@ -130,9 +130,9 @@ A coding model working on HyperTwist should still be able to: The next correct skillization sequence is: -1. extraction skills -2. browser diagnostics skills -3. design shell skills +1. browser diagnostics skills +2. design shell skills -Broader memory, provider, and domain skill widening should wait until that -browser/docs/design base exists. +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.