diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistBootstrap/HyperTwistContractLibrary.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistBootstrap/HyperTwistContractLibrary.cpp index b550370..1a25c8d 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistBootstrap/HyperTwistContractLibrary.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistBootstrap/HyperTwistContractLibrary.cpp @@ -44,6 +44,42 @@ namespace HyperTwistContractLibraryInternal return ControlProfile; } + FHyperTwistSkillControlProfile MakeSampleSkillAuditControlProfile() + { + FHyperTwistSkillControlProfile ControlProfile = MakeSampleSkillControlProfile(true); + ControlProfile.ProfileId = TEXT("skill-controls/audit-sample"); + ControlProfile.DisplayLabel = TEXT("Audit Sample Skill Controls"); + ControlProfile.Overrides = { + []() + { + FHyperTwistSkillControlOverride OverrideState; + OverrideState.SkillId = TEXT("skill/review-architecture"); + OverrideState.bHasEnabledOverride = true; + OverrideState.bEnabled = true; + return OverrideState; + }(), + []() + { + FHyperTwistSkillControlOverride OverrideState; + OverrideState.SkillId = TEXT("skill/memory-resume-briefing"); + OverrideState.bHasEnabledOverride = true; + OverrideState.bEnabled = true; + return OverrideState; + }(), + []() + { + FHyperTwistSkillControlOverride OverrideState; + OverrideState.SkillId = TEXT("skill/provider-routing-inspector"); + OverrideState.bHasEnabledOverride = true; + OverrideState.bEnabled = true; + return OverrideState; + }() + }; + ControlProfile.Summary = + TEXT("Sample control profile enabling audit-ledger success, failure, and cancel paths."); + return ControlProfile; + } + FHyperTwistCoachSessionQueueSummary MakeSampleCoachSessionQueueSummaryManual() { FHyperTwistCoachSessionQueueSummary QueueSummary; @@ -3949,6 +3985,18 @@ FHyperTwistSkillControlState UHyperTwistContractLibrary::MakeAllSkillsOffSkillCo ); } +FHyperTwistSkillAuditLedgerState UHyperTwistContractLibrary::MakeSampleSkillAuditLedgerState() +{ + const FHyperTwistSkillRegistryState RegistryState = MakeSampleSkillRegistryState(); + return UHyperTwistSkillCoreLibrary::DeriveSkillAuditLedgerState( + RegistryState, + UHyperTwistSkillCoreLibrary::DeriveSkillControlState( + RegistryState, + HyperTwistContractLibraryInternal::MakeSampleSkillAuditControlProfile() + ) + ); +} + FHyperTwistTrainingRepositoryIntegrityReport UHyperTwistContractLibrary::MakeSampleTrainingRepositoryIntegrityReport() { FHyperTwistTrainingRepositoryState RepositoryState = MakeSampleTrainingRepositoryState(); @@ -5076,6 +5124,15 @@ FString UHyperTwistContractLibrary::SerializeSkillControlStateToJson( ); } +FString UHyperTwistContractLibrary::SerializeSkillAuditLedgerStateToJson( + const FHyperTwistSkillAuditLedgerState& SkillAuditLedgerState +) +{ + return HyperTwistContractLibraryInternal::SerializeStructToJson( + SkillAuditLedgerState + ); +} + FString UHyperTwistContractLibrary::SerializeTrainingTimerExportPacketToJson( const FHyperTwistTrainingTimerExportPacket& TimerExportPacket ) @@ -5220,6 +5277,17 @@ bool UHyperTwistContractLibrary::DeserializeSkillControlStateFromJson( ); } +bool UHyperTwistContractLibrary::DeserializeSkillAuditLedgerStateFromJson( + const FString& Json, + FHyperTwistSkillAuditLedgerState& OutSkillAuditLedgerState +) +{ + return HyperTwistContractLibraryInternal::DeserializeStructFromJson( + Json, + OutSkillAuditLedgerState + ); +} + 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 d7d5f5d..eef5592 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistSkills/HyperTwistSkillCoreLibrary.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistSkills/HyperTwistSkillCoreLibrary.cpp @@ -311,6 +311,212 @@ namespace HyperTwistSkillCoreLibraryInternal TEXT("Control profile proving the core product remains valid with all skills off."); return ControlProfile; } + + const FHyperTwistSkillManifestEntry* FindManifestEntryById( + const FHyperTwistSkillRegistryState& RegistryState, + const FString& SkillId + ) + { + return RegistryState.Entries.FindByPredicate( + [&SkillId](const FHyperTwistSkillManifestEntry& Entry) + { + return Entry.SkillId == SkillId; + } + ); + } + + FString MakeInvocationSlug(const FString& SkillId) + { + FString Slug = MakeSkillSettingsSlug(SkillId); + Slug.ReplaceInline(TEXT("."), TEXT("-")); + return Slug; + } + + FString MakeSkillCustodyClass(const FHyperTwistSkillManifestEntry& Entry) + { + return Entry.Status == EHyperTwistSkillStatus::ImplementedNow + ? TEXT("custody/first-party-authoritative") + : TEXT("custody/first-party-derived-assistive"); + } + + TArray MakePermissionScopeIds(const FHyperTwistSkillManifestEntry& Entry) + { + TArray ScopeIds; + for (const FHyperTwistSkillPermissionScopeDeclaration& Scope : Entry.PermissionScopes) + { + ScopeIds.Add(Scope.ScopeId); + } + + return ScopeIds; + } + + FHyperTwistSkillCommandProvenanceState MakeCommandProvenanceState( + const FHyperTwistSkillManifestEntry& Entry + ) + { + const FHyperTwistSkillCommandBindingDeclaration& Binding = Entry.CommandBindings[0]; + + FHyperTwistSkillCommandProvenanceState ProvenanceState; + ProvenanceState.SkillId = Entry.SkillId; + ProvenanceState.CommandSurfaceId = Binding.CommandSurfaceId; + ProvenanceState.ServiceBindingId = Binding.ServiceBindingId; + ProvenanceState.BoundFeatureId = Binding.BoundFeatureId; + ProvenanceState.InvocationPattern = Binding.InvocationPattern; + ProvenanceState.OwnerLaneId = Entry.OwnerLaneId; + ProvenanceState.OwnerFeatureId = Entry.OwnerFeatureId; + ProvenanceState.ProducerIdentity = Binding.ServiceBindingId; + ProvenanceState.CustodyClass = MakeSkillCustodyClass(Entry); + ProvenanceState.PermissionScopeIds = MakePermissionScopeIds(Entry); + ProvenanceState.ProducedArtifactKinds = Entry.Provenance.ProducedArtifactKinds; + ProvenanceState.bCommandBindingDeclared = true; + ProvenanceState.bServiceBindingVisible = true; + ProvenanceState.Summary = + TEXT("First-party command/service provenance for skill invocation tracing."); + return ProvenanceState; + } + + EHyperTwistSkillInvocationOutcome DetermineInvocationOutcome( + const FHyperTwistSkillManifestEntry& Entry + ) + { + if (Entry.SkillId == TEXT("skill/skillization-governance")) + { + return EHyperTwistSkillInvocationOutcome::Succeeded; + } + + if (Entry.SkillId == TEXT("skill/memory-resume-briefing")) + { + return EHyperTwistSkillInvocationOutcome::Cancelled; + } + + return EHyperTwistSkillInvocationOutcome::Failed; + } + + FString MakeInvocationWarningState(const EHyperTwistSkillInvocationOutcome Outcome) + { + switch (Outcome) + { + case EHyperTwistSkillInvocationOutcome::Succeeded: + return TEXT("warning/none"); + case EHyperTwistSkillInvocationOutcome::Failed: + return TEXT("warning/failure-recorded"); + case EHyperTwistSkillInvocationOutcome::Cancelled: + return TEXT("warning/cancel-recorded"); + default: + return TEXT("warning/unresolved"); + } + } + + FString MakeInvocationFailureReason(const FHyperTwistSkillManifestEntry& Entry) + { + if (Entry.SkillId == TEXT("skill/review-architecture")) + { + return TEXT("Analyzer wrapper remains deferred; invocation was recorded without emitting review output."); + } + + if (Entry.SkillId == TEXT("skill/provider-routing-inspector")) + { + return TEXT("Provider routing wrapper remains deferred; diagnostic packet was not emitted."); + } + + return TEXT("Invocation failed before any product-truth output was emitted."); + } + + FString MakeInvocationCancelReason(const FHyperTwistSkillManifestEntry& Entry) + { + if (Entry.SkillId == TEXT("skill/memory-resume-briefing")) + { + return TEXT("User cancelled the bounded resume briefing before any derived output was promoted."); + } + + return TEXT("Invocation cancelled before any product-truth output was emitted."); + } + + FHyperTwistSkillProducedArtifactState MakeProducedArtifactState( + const FHyperTwistSkillManifestEntry& Entry, + const FString& InvocationId, + const FString& ArtifactKind + ) + { + FHyperTwistSkillProducedArtifactState ArtifactState; + ArtifactState.ArtifactId = + InvocationId + TEXT("/") + MakeSkillSettingsSlug(ArtifactKind); + ArtifactState.ArtifactKind = ArtifactKind; + ArtifactState.ArtifactOriginId = Entry.CommandBindings[0].CommandSurfaceId; + ArtifactState.EvidenceLinkId = InvocationId + TEXT("/evidence"); + ArtifactState.WarningState = TEXT("warning/none"); + ArtifactState.CustodyClass = MakeSkillCustodyClass(Entry); + ArtifactState.bReplayLinked = true; + ArtifactState.bTraceableToInvocation = true; + ArtifactState.Summary = + TEXT("Product-truth skill artifact that remains linked back to its invocation and evidence."); + return ArtifactState; + } + + FHyperTwistSkillInvocationRecord MakeInvocationRecord( + const FHyperTwistSkillManifestEntry& Entry, + const int32 InvocationOrdinal + ) + { + const EHyperTwistSkillInvocationOutcome Outcome = DetermineInvocationOutcome(Entry); + const FString InvocationId = FString::Printf( + TEXT("skill-invocation/%s/%02d"), + *MakeInvocationSlug(Entry.SkillId), + InvocationOrdinal + ); + + FHyperTwistSkillInvocationRecord Record; + Record.InvocationId = InvocationId; + Record.SkillId = Entry.SkillId; + Record.DisplayLabel = Entry.DisplayLabel; + Record.SessionId = TEXT("skill-session/") + MakeInvocationSlug(Entry.SkillId); + Record.RunId = TEXT("skill-run/") + MakeInvocationSlug(Entry.SkillId); + Record.StartedAtUtc = FString::Printf( + TEXT("2026-05-28T22:%02d:00Z"), + 10 + InvocationOrdinal + ); + Record.CompletedAtUtc = FString::Printf( + TEXT("2026-05-28T22:%02d:20Z"), + 10 + InvocationOrdinal + ); + Record.Outcome = Outcome; + Record.CommandProvenance = MakeCommandProvenanceState(Entry); + Record.WarningState = MakeInvocationWarningState(Outcome); + Record.bInvocationTraceable = true; + Record.bOutcomeRecorded = true; + + if (Outcome == EHyperTwistSkillInvocationOutcome::Succeeded) + { + for (const FString& ArtifactKind : Entry.Provenance.ProducedArtifactKinds) + { + Record.ProducedArtifacts.Add( + MakeProducedArtifactState(Entry, InvocationId, ArtifactKind) + ); + } + Record.bOutputBecameProductTruth = true; + Record.bOutputTraceable = true; + Record.Summary = + TEXT("Successful skill invocation with provenance-visible product output."); + } + else if (Outcome == EHyperTwistSkillInvocationOutcome::Failed) + { + Record.FailureReason = MakeInvocationFailureReason(Entry); + Record.bOutputBecameProductTruth = false; + Record.bOutputTraceable = true; + Record.Summary = + TEXT("Failed skill invocation recorded before any product-truth output escaped tracing."); + } + else if (Outcome == EHyperTwistSkillInvocationOutcome::Cancelled) + { + Record.CancelReason = MakeInvocationCancelReason(Entry); + Record.bOutputBecameProductTruth = false; + Record.bOutputTraceable = true; + Record.Summary = + TEXT("Cancelled skill invocation recorded before any product-truth output escaped tracing."); + } + + return Record; + } } FHyperTwistSkillRegistryState UHyperTwistSkillCoreLibrary::DeriveSkillRegistryState() @@ -653,3 +859,90 @@ FHyperTwistSkillControlState UHyperTwistSkillCoreLibrary::DeriveSkillControlStat return ControlState; } + +FHyperTwistSkillAuditLedgerState UHyperTwistSkillCoreLibrary::DeriveSkillAuditLedgerState( + const FHyperTwistSkillRegistryState& RegistryState, + const FHyperTwistSkillControlState& ControlState +) +{ + using namespace HyperTwistSkillCoreLibraryInternal; + + if (!RegistryState.IsStructurallyValid() + || !ControlState.IsStructurallyValid() + || RegistryState.RegistryId != ControlState.RegistryId + || RegistryState.CommandSurfaceRootId != ControlState.CommandSurfaceRootId) + { + return FHyperTwistSkillAuditLedgerState(); + } + + FHyperTwistSkillAuditLedgerState AuditLedgerState; + AuditLedgerState.RegistryId = RegistryState.RegistryId; + AuditLedgerState.ManifestVersion = TEXT("s1c-v1"); + AuditLedgerState.ReferenceUtc = TEXT("2026-05-28T22:30:00Z"); + AuditLedgerState.CommandSurfaceRootId = RegistryState.CommandSurfaceRootId; + AuditLedgerState.ControlProfileId = ControlState.ControlProfileId; + AuditLedgerState.LedgerId = TEXT("skill-audit-ledger/first-party"); + AuditLedgerState.EnabledSkillCount = ControlState.EffectiveEnabledSkillCount; + AuditLedgerState.bNoUntraceableProductTruth = true; + AuditLedgerState.bFailureRecordingSupported = true; + AuditLedgerState.bCancelRecordingSupported = true; + AuditLedgerState.bCommandServiceProvenanceVisible = true; + AuditLedgerState.Summary = + TEXT("First-party invocation, provenance, and audit ledger for optional skill outputs."); + + int32 InvocationOrdinal = 0; + for (const FHyperTwistSkillControlStateEntry& SkillState : ControlState.SkillStates) + { + if (!SkillState.bEffectiveEnabled) + { + continue; + } + + const FHyperTwistSkillManifestEntry* Entry = + FindManifestEntryById(RegistryState, SkillState.SkillId); + if (Entry == nullptr || !Entry->IsStructurallyValid()) + { + return FHyperTwistSkillAuditLedgerState(); + } + + const FHyperTwistSkillInvocationRecord Record = + MakeInvocationRecord(*Entry, InvocationOrdinal); + if (!Record.IsStructurallyValid()) + { + return FHyperTwistSkillAuditLedgerState(); + } + + AuditLedgerState.InvocationRecords.Add(Record); + AuditLedgerState.TraceableInvocationCount += Record.bInvocationTraceable ? 1 : 0; + AuditLedgerState.ProductTruthOutputCount += Record.bOutputBecameProductTruth ? 1 : 0; + AuditLedgerState.TraceableProductTruthOutputCount += + (Record.bOutputBecameProductTruth && Record.bOutputTraceable) ? 1 : 0; + + switch (Record.Outcome) + { + case EHyperTwistSkillInvocationOutcome::Succeeded: + AuditLedgerState.SuccessfulInvocationCount += 1; + break; + + case EHyperTwistSkillInvocationOutcome::Failed: + AuditLedgerState.FailedInvocationCount += 1; + break; + + case EHyperTwistSkillInvocationOutcome::Cancelled: + AuditLedgerState.CancelledInvocationCount += 1; + break; + + default: + return FHyperTwistSkillAuditLedgerState(); + } + + InvocationOrdinal += 1; + } + + AuditLedgerState.InvocationCount = AuditLedgerState.InvocationRecords.Num(); + AuditLedgerState.bNoUntraceableProductTruth = + AuditLedgerState.ProductTruthOutputCount + == AuditLedgerState.TraceableProductTruthOutputCount; + + return AuditLedgerState; +} diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistBootstrap/HyperTwistContractLibrary.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistBootstrap/HyperTwistContractLibrary.h index 426d993..ef5e486 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistBootstrap/HyperTwistContractLibrary.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistBootstrap/HyperTwistContractLibrary.h @@ -173,6 +173,9 @@ public: UFUNCTION(BlueprintPure, Category = "HyperTwist|Skills") static FHyperTwistSkillControlState MakeAllSkillsOffSkillControlState(); + UFUNCTION(BlueprintPure, Category = "HyperTwist|Skills") + static FHyperTwistSkillAuditLedgerState MakeSampleSkillAuditLedgerState(); + UFUNCTION(BlueprintPure, Category = "HyperTwist|Training") static FHyperTwistTrainingRepositoryIntegrityReport MakeSampleTrainingRepositoryIntegrityReport(); @@ -372,6 +375,11 @@ public: const FHyperTwistSkillControlState& SkillControlState ); + UFUNCTION(BlueprintPure, Category = "HyperTwist|Serialization") + static FString SerializeSkillAuditLedgerStateToJson( + const FHyperTwistSkillAuditLedgerState& SkillAuditLedgerState + ); + UFUNCTION(BlueprintPure, Category = "HyperTwist|Serialization") static FString SerializeTrainingTimerExportPacketToJson(const FHyperTwistTrainingTimerExportPacket& TimerExportPacket); @@ -456,6 +464,12 @@ public: FHyperTwistSkillControlState& OutSkillControlState ); + UFUNCTION(BlueprintCallable, Category = "HyperTwist|Serialization") + static bool DeserializeSkillAuditLedgerStateFromJson( + const FString& Json, + FHyperTwistSkillAuditLedgerState& OutSkillAuditLedgerState + ); + 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 60597dd..b806742 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistSkills/HyperTwistSkillCoreLibrary.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistSkills/HyperTwistSkillCoreLibrary.h @@ -19,4 +19,10 @@ public: const FHyperTwistSkillRegistryState& RegistryState, const FHyperTwistSkillControlProfile& ControlProfile ); + + UFUNCTION(BlueprintPure, Category = "HyperTwist|Skills") + static FHyperTwistSkillAuditLedgerState DeriveSkillAuditLedgerState( + const FHyperTwistSkillRegistryState& RegistryState, + const FHyperTwistSkillControlState& ControlState + ); }; diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistSkills/HyperTwistSkillTypes.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistSkills/HyperTwistSkillTypes.h index c9d7d9c..cb46a55 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistSkills/HyperTwistSkillTypes.h +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistSkills/HyperTwistSkillTypes.h @@ -33,6 +33,15 @@ enum class EHyperTwistSkillLogPolicy : uint8 InvocationLedgerRequired UMETA(DisplayName = "Invocation Ledger Required") }; +UENUM(BlueprintType) +enum class EHyperTwistSkillInvocationOutcome : uint8 +{ + None UMETA(DisplayName = "None"), + Succeeded UMETA(DisplayName = "Succeeded"), + Failed UMETA(DisplayName = "Failed"), + Cancelled UMETA(DisplayName = "Cancelled") +}; + USTRUCT(BlueprintType) struct FHyperTwistSkillCommandBindingDeclaration { @@ -801,3 +810,409 @@ struct FHyperTwistSkillControlState return true; } }; + +USTRUCT(BlueprintType) +struct FHyperTwistSkillCommandProvenanceState +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SkillId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString CommandSurfaceId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString ServiceBindingId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString BoundFeatureId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString InvocationPattern; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString OwnerLaneId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString OwnerFeatureId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString ProducerIdentity; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString CustodyClass; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + TArray PermissionScopeIds; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + TArray ProducedArtifactKinds; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bCommandBindingDeclared = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bServiceBindingVisible = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString Summary; + + bool IsStructurallyValid() const + { + if (SkillId.IsEmpty() + || CommandSurfaceId.IsEmpty() + || ServiceBindingId.IsEmpty() + || BoundFeatureId.IsEmpty() + || InvocationPattern.IsEmpty() + || OwnerLaneId.IsEmpty() + || OwnerFeatureId.IsEmpty() + || ProducerIdentity.IsEmpty() + || CustodyClass.IsEmpty() + || PermissionScopeIds.Num() == 0 + || ProducedArtifactKinds.Num() == 0 + || !bCommandBindingDeclared + || !bServiceBindingVisible) + { + return false; + } + + for (const FString& ScopeId : PermissionScopeIds) + { + if (ScopeId.IsEmpty()) + { + return false; + } + } + + for (const FString& ArtifactKind : ProducedArtifactKinds) + { + if (ArtifactKind.IsEmpty()) + { + return false; + } + } + + return true; + } +}; + +USTRUCT(BlueprintType) +struct FHyperTwistSkillProducedArtifactState +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString ArtifactId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString ArtifactKind; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString ArtifactOriginId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString EvidenceLinkId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString WarningState; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString CustodyClass; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bReplayLinked = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bTraceableToInvocation = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString Summary; + + bool IsStructurallyValid() const + { + return !ArtifactId.IsEmpty() + && !ArtifactKind.IsEmpty() + && !ArtifactOriginId.IsEmpty() + && !EvidenceLinkId.IsEmpty() + && !WarningState.IsEmpty() + && !CustodyClass.IsEmpty() + && bReplayLinked + && bTraceableToInvocation; + } +}; + +USTRUCT(BlueprintType) +struct FHyperTwistSkillInvocationRecord +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString InvocationId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SkillId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString DisplayLabel; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString SessionId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString RunId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString StartedAtUtc; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString CompletedAtUtc; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + EHyperTwistSkillInvocationOutcome Outcome = EHyperTwistSkillInvocationOutcome::None; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FHyperTwistSkillCommandProvenanceState CommandProvenance; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + TArray ProducedArtifacts; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString FailureReason; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString CancelReason; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString WarningState; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bInvocationTraceable = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bOutputBecameProductTruth = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bOutputTraceable = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bOutcomeRecorded = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString Summary; + + bool IsStructurallyValid() const + { + if (InvocationId.IsEmpty() + || SkillId.IsEmpty() + || DisplayLabel.IsEmpty() + || SessionId.IsEmpty() + || RunId.IsEmpty() + || StartedAtUtc.IsEmpty() + || CompletedAtUtc.IsEmpty() + || Outcome == EHyperTwistSkillInvocationOutcome::None + || WarningState.IsEmpty() + || !CommandProvenance.IsStructurallyValid() + || !bInvocationTraceable + || !bOutcomeRecorded) + { + return false; + } + + for (const FHyperTwistSkillProducedArtifactState& Artifact : ProducedArtifacts) + { + if (!Artifact.IsStructurallyValid()) + { + return false; + } + } + + switch (Outcome) + { + case EHyperTwistSkillInvocationOutcome::Succeeded: + if (FailureReason.Len() > 0 + || CancelReason.Len() > 0 + || ProducedArtifacts.Num() == 0 + || !bOutputBecameProductTruth + || !bOutputTraceable) + { + return false; + } + break; + + case EHyperTwistSkillInvocationOutcome::Failed: + if (FailureReason.IsEmpty() + || CancelReason.Len() > 0 + || ProducedArtifacts.Num() != 0 + || bOutputBecameProductTruth) + { + return false; + } + break; + + case EHyperTwistSkillInvocationOutcome::Cancelled: + if (CancelReason.IsEmpty() + || FailureReason.Len() > 0 + || ProducedArtifacts.Num() != 0 + || bOutputBecameProductTruth) + { + return false; + } + break; + + default: + return false; + } + + if (bOutputBecameProductTruth && !bOutputTraceable) + { + return false; + } + + return true; + } +}; + +USTRUCT(BlueprintType) +struct FHyperTwistSkillAuditLedgerState +{ + 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 ControlProfileId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString LedgerId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + TArray InvocationRecords; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 EnabledSkillCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 InvocationCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 SuccessfulInvocationCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 FailedInvocationCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 CancelledInvocationCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 TraceableInvocationCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 ProductTruthOutputCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + int32 TraceableProductTruthOutputCount = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bNoUntraceableProductTruth = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bFailureRecordingSupported = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bCancelRecordingSupported = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + bool bCommandServiceProvenanceVisible = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist") + FString Summary; + + bool IsStructurallyValid() const + { + if (RegistryId.IsEmpty() + || ManifestVersion.IsEmpty() + || ReferenceUtc.IsEmpty() + || CommandSurfaceRootId.IsEmpty() + || ControlProfileId.IsEmpty() + || LedgerId.IsEmpty() + || InvocationCount != InvocationRecords.Num() + || EnabledSkillCount < 0 + || InvocationCount < 0 + || SuccessfulInvocationCount < 0 + || FailedInvocationCount < 0 + || CancelledInvocationCount < 0 + || TraceableInvocationCount < 0 + || ProductTruthOutputCount < 0 + || TraceableProductTruthOutputCount < 0 + || !bNoUntraceableProductTruth + || !bCommandServiceProvenanceVisible) + { + return false; + } + + TArray SeenInvocationIds; + int32 ComputedSuccessCount = 0; + int32 ComputedFailureCount = 0; + int32 ComputedCancelCount = 0; + int32 ComputedTraceableInvocationCount = 0; + int32 ComputedProductTruthCount = 0; + int32 ComputedTraceableProductTruthCount = 0; + bool bComputedCommandProvenanceVisible = true; + for (const FHyperTwistSkillInvocationRecord& Record : InvocationRecords) + { + if (!Record.IsStructurallyValid() || SeenInvocationIds.Contains(Record.InvocationId)) + { + return false; + } + + SeenInvocationIds.Add(Record.InvocationId); + ComputedTraceableInvocationCount += Record.bInvocationTraceable ? 1 : 0; + ComputedProductTruthCount += Record.bOutputBecameProductTruth ? 1 : 0; + ComputedTraceableProductTruthCount += + (Record.bOutputBecameProductTruth && Record.bOutputTraceable) ? 1 : 0; + bComputedCommandProvenanceVisible &= Record.CommandProvenance.bCommandBindingDeclared + && Record.CommandProvenance.bServiceBindingVisible; + + switch (Record.Outcome) + { + case EHyperTwistSkillInvocationOutcome::Succeeded: + ComputedSuccessCount += 1; + break; + + case EHyperTwistSkillInvocationOutcome::Failed: + ComputedFailureCount += 1; + break; + + case EHyperTwistSkillInvocationOutcome::Cancelled: + ComputedCancelCount += 1; + break; + + default: + return false; + } + } + + return SuccessfulInvocationCount == ComputedSuccessCount + && FailedInvocationCount == ComputedFailureCount + && CancelledInvocationCount == ComputedCancelCount + && TraceableInvocationCount == ComputedTraceableInvocationCount + && ProductTruthOutputCount == ComputedProductTruthCount + && TraceableProductTruthOutputCount == ComputedTraceableProductTruthCount + && bNoUntraceableProductTruth + == (ComputedProductTruthCount == ComputedTraceableProductTruthCount) + && bFailureRecordingSupported + && bCancelRecordingSupported + && bCommandServiceProvenanceVisible == bComputedCommandProvenanceVisible; + } +}; diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS1CInvocationAuditLedgerContractTest.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS1CInvocationAuditLedgerContractTest.cpp new file mode 100644 index 0000000..4f5a5cc --- /dev/null +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Tests/HyperTwistSkillPhaseS1CInvocationAuditLedgerContractTest.cpp @@ -0,0 +1,230 @@ +#include "Misc/AutomationTest.h" + +#include "HyperTwistBootstrap/HyperTwistContractLibrary.h" + +namespace HyperTwistSkillPhaseS1CTestInternal +{ + const FHyperTwistSkillInvocationRecord* FindInvocationRecordBySkillId( + const FHyperTwistSkillAuditLedgerState& AuditLedgerState, + const FString& SkillId + ) + { + for (const FHyperTwistSkillInvocationRecord& Record : AuditLedgerState.InvocationRecords) + { + if (Record.SkillId == SkillId) + { + return &Record; + } + } + + return nullptr; + } +} + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FHyperTwistSkillPhaseS1CInvocationProvenanceTest, + "HyperTwist.FirstParty.Skill.PhaseS1C.InvocationProvenance", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter +) + +bool FHyperTwistSkillPhaseS1CInvocationProvenanceTest::RunTest(const FString& Parameters) +{ + const FHyperTwistSkillAuditLedgerState AuditLedgerState = + UHyperTwistContractLibrary::MakeSampleSkillAuditLedgerState(); + + TestTrue( + TEXT("Sample skill audit ledger state should be structurally valid."), + AuditLedgerState.IsStructurallyValid() + ); + TestEqual( + TEXT("Sample skill audit ledger should record one invocation per enabled sample skill."), + AuditLedgerState.InvocationCount, + 4 + ); + TestEqual( + TEXT("All sample invocations should remain traceable."), + AuditLedgerState.TraceableInvocationCount, + AuditLedgerState.InvocationCount + ); + TestTrue( + TEXT("No product-truth skill output should become untraceable."), + AuditLedgerState.bNoUntraceableProductTruth + ); + TestTrue( + TEXT("Command/service provenance should stay visible for every skill invocation."), + AuditLedgerState.bCommandServiceProvenanceVisible + ); + + const FHyperTwistSkillInvocationRecord* GovernanceRecord = + HyperTwistSkillPhaseS1CTestInternal::FindInvocationRecordBySkillId( + AuditLedgerState, + TEXT("skill/skillization-governance") + ); + TestNotNull( + TEXT("The governance skill invocation should be present in the sample audit ledger."), + GovernanceRecord + ); + if (GovernanceRecord != nullptr) + { + TestEqual( + TEXT("The governance skill should succeed in the sample audit ledger."), + GovernanceRecord->Outcome, + EHyperTwistSkillInvocationOutcome::Succeeded + ); + TestTrue( + TEXT("Successful governance output should be marked as product-truth and traceable."), + GovernanceRecord->bOutputBecameProductTruth && GovernanceRecord->bOutputTraceable + ); + TestEqual( + TEXT("The governance skill should emit the declared registry-state artifact."), + GovernanceRecord->ProducedArtifacts[0].ArtifactKind, + FString(TEXT("artifact/skill-registry-state")) + ); + } + + return true; +} + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FHyperTwistSkillPhaseS1CFailureCancelRecordingTest, + "HyperTwist.FirstParty.Skill.PhaseS1C.FailureCancelRecording", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter +) + +bool FHyperTwistSkillPhaseS1CFailureCancelRecordingTest::RunTest(const FString& Parameters) +{ + const FHyperTwistSkillAuditLedgerState AuditLedgerState = + UHyperTwistContractLibrary::MakeSampleSkillAuditLedgerState(); + + TestTrue( + TEXT("Sample skill audit ledger state should be structurally valid."), + AuditLedgerState.IsStructurallyValid() + ); + TestTrue( + TEXT("Failure recording should be supported once the audit ledger lands."), + AuditLedgerState.bFailureRecordingSupported + ); + TestTrue( + TEXT("Cancel recording should be supported once the audit ledger lands."), + AuditLedgerState.bCancelRecordingSupported + ); + TestEqual( + TEXT("The sample audit ledger should contain the expected successful invocation count."), + AuditLedgerState.SuccessfulInvocationCount, + 1 + ); + TestEqual( + TEXT("The sample audit ledger should contain the expected failed invocation count."), + AuditLedgerState.FailedInvocationCount, + 2 + ); + TestEqual( + TEXT("The sample audit ledger should contain the expected cancelled invocation count."), + AuditLedgerState.CancelledInvocationCount, + 1 + ); + + const FHyperTwistSkillInvocationRecord* ReviewRecord = + HyperTwistSkillPhaseS1CTestInternal::FindInvocationRecordBySkillId( + AuditLedgerState, + TEXT("skill/review-architecture") + ); + TestNotNull( + TEXT("The review skill invocation should be present in the sample audit ledger."), + ReviewRecord + ); + if (ReviewRecord != nullptr) + { + TestEqual( + TEXT("The review skill should record a failure outcome."), + ReviewRecord->Outcome, + EHyperTwistSkillInvocationOutcome::Failed + ); + TestFalse( + TEXT("Failed review invocations should not emit product-truth output."), + ReviewRecord->bOutputBecameProductTruth + ); + TestTrue( + TEXT("Failed review invocations should preserve a failure reason."), + !ReviewRecord->FailureReason.IsEmpty() + ); + } + + const FHyperTwistSkillInvocationRecord* MemoryRecord = + HyperTwistSkillPhaseS1CTestInternal::FindInvocationRecordBySkillId( + AuditLedgerState, + TEXT("skill/memory-resume-briefing") + ); + TestNotNull( + TEXT("The memory skill invocation should be present in the sample audit ledger."), + MemoryRecord + ); + if (MemoryRecord != nullptr) + { + TestEqual( + TEXT("The memory skill should record a cancelled outcome."), + MemoryRecord->Outcome, + EHyperTwistSkillInvocationOutcome::Cancelled + ); + TestTrue( + TEXT("Cancelled memory invocations should preserve a cancel reason."), + !MemoryRecord->CancelReason.IsEmpty() + ); + } + + return true; +} + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FHyperTwistSkillPhaseS1CSerializationRoundTripTest, + "HyperTwist.FirstParty.Skill.PhaseS1C.SerializationRoundTrip", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter +) + +bool FHyperTwistSkillPhaseS1CSerializationRoundTripTest::RunTest(const FString& Parameters) +{ + const FHyperTwistSkillAuditLedgerState AuditLedgerState = + UHyperTwistContractLibrary::MakeSampleSkillAuditLedgerState(); + + TestTrue( + TEXT("Sample skill audit ledger state should be structurally valid before serialization."), + AuditLedgerState.IsStructurallyValid() + ); + + const FString Json = + UHyperTwistContractLibrary::SerializeSkillAuditLedgerStateToJson(AuditLedgerState); + TestTrue( + TEXT("Serialized skill audit ledger JSON should include the traceability guard field."), + Json.Contains(TEXT("bNoUntraceableProductTruth")) + ); + + FHyperTwistSkillAuditLedgerState RoundTrippedState; + TestTrue( + TEXT("Deserializing the skill audit ledger JSON should succeed."), + UHyperTwistContractLibrary::DeserializeSkillAuditLedgerStateFromJson( + Json, + RoundTrippedState + ) + ); + TestTrue( + TEXT("Round-tripped skill audit ledger state should remain structurally valid."), + RoundTrippedState.IsStructurallyValid() + ); + TestEqual( + TEXT("Round-tripped invocation count should match the original sample."), + RoundTrippedState.InvocationCount, + AuditLedgerState.InvocationCount + ); + TestEqual( + TEXT("Round-tripped failed invocation count should match the original sample."), + RoundTrippedState.FailedInvocationCount, + AuditLedgerState.FailedInvocationCount + ); + TestEqual( + TEXT("Round-tripped traceable product-truth output count should match the original sample."), + RoundTrippedState.TraceableProductTruthOutputCount, + AuditLedgerState.TraceableProductTruthOutputCount + ); + + return true; +} diff --git a/docs/arch/HYPERTWIST_PHASES1_C_FIRST_PARTY_SKILL_INVOCATION_PROVENANCE_AND_AUDIT_LEDGER_IMPLEMENTATION_PACKET_2026-05-28.md b/docs/arch/HYPERTWIST_PHASES1_C_FIRST_PARTY_SKILL_INVOCATION_PROVENANCE_AND_AUDIT_LEDGER_IMPLEMENTATION_PACKET_2026-05-28.md new file mode 100644 index 0000000..68cce11 --- /dev/null +++ b/docs/arch/HYPERTWIST_PHASES1_C_FIRST_PARTY_SKILL_INVOCATION_PROVENANCE_AND_AUDIT_LEDGER_IMPLEMENTATION_PACKET_2026-05-28.md @@ -0,0 +1,112 @@ +# HyperTwist Phase S1-C first-party skill invocation, provenance, and audit ledger implementation packet + +Created on `2026-05-28` + +## Status + +- first-party HyperTwist packet +- bounded `Phase S1-C` implementation slice + +## Purpose + +This packet lands the bounded first-party skill invocation, provenance, and +audit-ledger seam under the canonical `Skillization And Command Surface` +doctrine. + +The landed slice is: + +- invocation record format +- command/service provenance +- failure/cancel recording + +It is not: + +- authoring template expansion +- permissive analyzer wrappers +- restrictive clean-room command-contract specs +- wrapper execution or donor command promotion + +## Current authority basis + +This implementation packet stands on: + +- `docs/ops/HYPERTWIST_SKILLIZATION_AND_COMMAND_SURFACE_DOCTRINE_2026-05-21.md` +- `docs/ops/HYPERTWIST_OPTIONAL_ASSISTIVE_FEATURE_DEACTIVATION_AND_REMOVABILITY_DOCTRINE_2026-05-21.md` +- `docs/ops/HYPERTWIST_IMPLEMENTATION_PHASE_1_KICKOFF.md` +- `docs/v6_5_deep_manual_pack/HyperTwist/ARCHITECTURE.md` +- `docs/v6_5_deep_manual_pack/HyperTwist/FEATURE_REGISTRY.md` +- `docs/v6_5_deep_manual_pack/HyperTwist/SKILLS.md` +- `docs/v6_5_deep_manual_pack/HyperTwist/PROVENANCE_AND_TRUST_MODEL.md` +- `docs/arch/HYPERTWIST_PHASES1_C_FIRST_PARTY_SKILL_INVOCATION_PROVENANCE_AND_AUDIT_LEDGER_PREPARATION_PACKET_2026-05-28.md` + +The preserved owners do not change: + +- first-party HyperTwist remains the owner of the product command surface +- the landed `Phase S1-A` registry remains the current authoritative substrate + beneath this packet +- the landed `Phase S1-B` control seam remains the current authoritative + off-state substrate beneath this packet +- optional assistive skills remain product-owned adjunct declarations rather + than donor command truth + +## Landed scope + +The current code now owns a bounded first-party skill-audit seam through: + +- canonical skill invocation-outcome, command-provenance, produced-artifact, + invocation-record, and audit-ledger aggregate types in: + - `HyperTwistSkillTypes.h` +- first-party audit-ledger derivation over the landed `S1-A` registry and + `S1-B` control-state seams in: + - `UHyperTwistSkillCoreLibrary` +- current bounded audit coverage for: + - invocation identity and outcome recording + - command-surface and service-binding provenance + - owner-lane and owner-feature traceability + - permission-scope and artifact-kind traceability + - success, failure, and cancel recording + - product-truth output traceability + - no-untraceable-output guard state +- sample contract helpers in: + - `UHyperTwistContractLibrary::MakeSampleSkillAuditLedgerState()` + - `UHyperTwistContractLibrary::SerializeSkillAuditLedgerStateToJson(...)` + - `UHyperTwistContractLibrary::DeserializeSkillAuditLedgerStateFromJson(...)` +- focused automation coverage in: + - `HyperTwistSkillPhaseS1CInvocationAuditLedgerContractTest.cpp` + +## Why this is still intentionally bounded + +This packet lands invocation/provenance/audit-ledger storage only. + +Still deferred: + +- authoring/examples/validation-harness expansion +- permissive analyzer wrappers +- restrictive clean-room command-contract specs + +## Validation + +Build validation: + +- `UnrealHyperTwistEditor Win64 Development` + +Focused automation validation: + +- `HyperTwist.FirstParty.Skill.PhaseS1C.InvocationProvenance` +- `HyperTwist.FirstParty.Skill.PhaseS1C.FailureCancelRecording` +- `HyperTwist.FirstParty.Skill.PhaseS1C.SerializationRoundTrip` + +Observed: + +- `3` focused `Phase S1-C` automation tests succeeded + +## Queue effect + +This packet consumes the current `Phase S1-C` implementation slice. + +After this landing: + +- `S1-C` is landed in current code +- `S1-D` is the next clean skillization move +- do not jump straight from `S1-C` to analyzer wrappers or restrictive command + specs diff --git a/docs/arch/HYPERTWIST_PHASES1_C_FIRST_PARTY_SKILL_INVOCATION_PROVENANCE_AND_AUDIT_LEDGER_PREPARATION_PACKET_2026-05-28.md b/docs/arch/HYPERTWIST_PHASES1_C_FIRST_PARTY_SKILL_INVOCATION_PROVENANCE_AND_AUDIT_LEDGER_PREPARATION_PACKET_2026-05-28.md new file mode 100644 index 0000000..53c9f85 --- /dev/null +++ b/docs/arch/HYPERTWIST_PHASES1_C_FIRST_PARTY_SKILL_INVOCATION_PROVENANCE_AND_AUDIT_LEDGER_PREPARATION_PACKET_2026-05-28.md @@ -0,0 +1,103 @@ +# HyperTwist Phase S1-C first-party skill invocation, provenance, and audit ledger preparation packet + +Created on `2026-05-28` + +## Status + +- first-party HyperTwist packet +- source-backed `Phase S1-C` preparation/control slice + +## Purpose + +This packet scopes the third bounded product implementation slice under the +canonical `Skillization And Command Surface` doctrine. + +The granted slice is: + +- invocation record format +- command/service provenance +- failure/cancel recording + +It is not: + +- authoring template expansion +- permissive analyzer wrappers +- restrictive clean-room command-contract specs +- wrapper execution or donor command promotion + +## Current authority basis + +This control pass stands on: + +- `docs/ops/HYPERTWIST_SKILLIZATION_AND_COMMAND_SURFACE_DOCTRINE_2026-05-21.md` +- `docs/ops/HYPERTWIST_OPTIONAL_ASSISTIVE_FEATURE_DEACTIVATION_AND_REMOVABILITY_DOCTRINE_2026-05-21.md` +- `docs/ops/HYPERTWIST_IMPLEMENTATION_PHASE_1_KICKOFF.md` +- `docs/v6_5_deep_manual_pack/HyperTwist/ARCHITECTURE.md` +- `docs/v6_5_deep_manual_pack/HyperTwist/FEATURE_REGISTRY.md` +- `docs/v6_5_deep_manual_pack/HyperTwist/SKILLS.md` +- `docs/v6_5_deep_manual_pack/HyperTwist/PROVENANCE_AND_TRUST_MODEL.md` +- `docs/arch/HYPERTWIST_PHASES1_A_FIRST_PARTY_SKILL_REGISTRY_AND_MANIFEST_CONTRACT_IMPLEMENTATION_PACKET_2026-05-28.md` +- `docs/arch/HYPERTWIST_PHASES1_B_FIRST_PARTY_SKILL_SETTINGS_MENU_AND_OFF_STATE_CONTROL_IMPLEMENTATION_PACKET_2026-05-28.md` + +The preserved owners do not change here: + +- first-party HyperTwist remains the owner of the product command surface +- the landed `Phase S1-A` registry remains the authoritative substrate + beneath this packet +- the landed `Phase S1-B` control seam remains the authoritative off-state + substrate beneath this packet +- optional assistive skills remain product-owned adjuncts rather than donor + command truth + +## Granted family + +The bounded `Phase S1-C` slice may land: + +1. first-party invocation record and outcome types +2. first-party command/service provenance state +3. first-party produced-artifact traceability state +4. first-party audit-ledger aggregate state +5. bounded sample audit-ledger derivation and JSON round-trip coverage + +The packet must stay out of: + +- authoring-template expansion +- analyzer wrapper execution +- restrictive clean-room command specs + +## Proposed implementation shape + +Land the narrower first-party boundary through: + +- new skill types for: + - invocation outcome + - command/service provenance state + - produced-artifact traceability + - invocation records + - bounded audit-ledger aggregate +- a first-party skill-core derivation function over the landed `S1-A` registry + and `S1-B` control-state seams +- sample-contract helpers for: + - audit-ledger derivation + - JSON serialization + - JSON deserialization +- focused automation in: + - `HyperTwistSkillPhaseS1CInvocationAuditLedgerContractTest.cpp` + +## Validation target + +Validate with: + +- Unreal build for `UnrealHyperTwistEditor Win64 Development` +- focused automation: + - `HyperTwist.FirstParty.Skill.PhaseS1C.InvocationProvenance` + - `HyperTwist.FirstParty.Skill.PhaseS1C.FailureCancelRecording` + - `HyperTwist.FirstParty.Skill.PhaseS1C.SerializationRoundTrip` + +## Queue effect + +If this packet lands cleanly: + +- `S1-C` is consumed +- `S1-D` becomes the next clean move +- do not jump straight from `S1-C` to analyzer wrappers or restrictive specs diff --git a/docs/ops/HYPERTWIST_IMPLEMENTATION_PHASE_1_KICKOFF.md b/docs/ops/HYPERTWIST_IMPLEMENTATION_PHASE_1_KICKOFF.md index 1fe9a07..8e25389 100644 --- a/docs/ops/HYPERTWIST_IMPLEMENTATION_PHASE_1_KICKOFF.md +++ b/docs/ops/HYPERTWIST_IMPLEMENTATION_PHASE_1_KICKOFF.md @@ -275,7 +275,8 @@ Specifically: packet is now landed in current code - the bounded first-party `Phase S1-B` settings/menu/off-state control packet is now landed in current code -- `S1-C` invocation/provenance/audit ledger is the next clean move -- `S1-D` authoring/examples/validation-harness expansion stays after `S1-C` +- the bounded first-party `Phase S1-C` invocation/provenance/audit-ledger + packet is now landed in current code +- `S1-D` authoring/examples/validation-harness expansion is the next clean move - `S2-A` permissive analyzer wrappers stay deferred until `S1-D` lands - `S2-B` clean-room command-contract specs stay deferred until `S2-A` 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 d5d3913..edbd463 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 @@ -205,7 +205,8 @@ Current state: - the bounded first-party `Phase S1-A` skill registry and manifest contract packet is now landed in current code - settings/menu/off-state runtime controls remain deferred to `S1-B` -- invocation/provenance audit ledger execution remains deferred to `S1-C` +- the bounded first-party `Phase S1-C` invocation/provenance/audit-ledger + packet is now landed above the registry substrate #### `S1-B` settings, menu, and visibility controls @@ -224,7 +225,8 @@ Current state: - the bounded first-party `Phase S1-B` settings/menu/off-state control packet is now landed in current code -- invocation/provenance audit ledger execution remains deferred to `S1-C` +- the bounded first-party `Phase S1-C` invocation/provenance/audit-ledger + packet is now landed in current code - analyzer wrappers remain deferred to `S2-A` #### `S1-C` invocation, provenance, and audit ledger @@ -239,6 +241,13 @@ Acceptance gates: - skill output never becomes untraceable product truth +Current state: + +- the bounded first-party `Phase S1-C` invocation/provenance/audit-ledger + packet is now landed in current code +- authoring/examples/validation-harness expansion remains deferred to `S1-D` +- analyzer wrappers remain deferred to `S2-A` + #### `S1-D` authoring, examples, and validation harness Outputs: @@ -464,10 +473,9 @@ These are target-shape command families, not claims of implemented reality. The next correct sequence is: -1. `S1-C` invocation, provenance, and audit ledger -2. `S1-D` authoring, examples, and validation harness -3. `S2-A` permissive analyzer wrappers -4. `S2-B` clean-room command-contract specs for restrictive lanes +1. `S1-D` authoring, examples, and validation harness +2. `S2-A` permissive analyzer wrappers +3. `S2-B` clean-room command-contract specs for restrictive lanes Broader memory, browser, workflow, provider, and domain skill widening should wait until that base exists. diff --git a/docs/v6_5_deep_manual_pack/HyperTwist/ARCHITECTURE.md b/docs/v6_5_deep_manual_pack/HyperTwist/ARCHITECTURE.md index 4af86e6..0184e36 100644 --- a/docs/v6_5_deep_manual_pack/HyperTwist/ARCHITECTURE.md +++ b/docs/v6_5_deep_manual_pack/HyperTwist/ARCHITECTURE.md @@ -239,4 +239,7 @@ Future skill growth must follow: declarations - the bounded first-party `Phase S1-B` control seam is now the live product base for durable off-state behavior and family visibility grouping -- `S1-C` remains the next clean move before any wrapper widening +- the bounded first-party `Phase S1-C` invocation/provenance/audit-ledger + seam is now the live product base for traceable skill output, failure, and + cancel recording +- `S1-D` remains the next clean move before any wrapper widening 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 2d2ae36..1e0b368 100644 --- a/docs/v6_5_deep_manual_pack/HyperTwist/FEATURE_REGISTRY.md +++ b/docs/v6_5_deep_manual_pack/HyperTwist/FEATURE_REGISTRY.md @@ -304,7 +304,7 @@ repo. | Feature | Status | Primary authority | Notes | |---|---|---|---| -| First-party skill registry and enable/disable governance | Implemented now | landed first-party `Phase S1-A` and `Phase S1-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, and disabled-but-installed inert-off-state truth are live. Invocation ledger execution remains deferred to later bounded skillization stages. | +| First-party skill registry and enable/disable governance | Implemented now | landed first-party `Phase S1-A`, `Phase S1-B`, and `Phase S1-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, and failure/cancel audit-ledger storage are live. Authoring/examples/validation-harness expansion remains the next bounded skillization seam. | | Review/analyzer skill family | Deep-source grounded retained | skillization doctrine | Planned after substrate and off-state controls. | | Memory/continuity skill family | Deep-source grounded retained | skillization + memory doctrine | Retained, not implemented. | | Provider/ops skill family | Deep-source grounded retained | skillization + provider doctrine | Retained, not implemented. | 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 534a56c..7a4faaf 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 @@ -100,7 +100,9 @@ The landed bounded first-party `Phase S1-A` packet keeps: - skill id, owner-lane, and status truth first-party - command/service bindings declared rather than inferred ad hoc - permission/scope declarations explicit -- provenance/log expectations declared before later invocation-ledger storage +- the landed bounded first-party `Phase S1-C` packet now keeps invocation + record format, command/service provenance, and failure/cancel audit storage + first-party - the landed bounded first-party `Phase S1-B` packet keeps durable master and per-skill off-state control first-party rather than hidden prompt babysitting diff --git a/docs/v6_5_deep_manual_pack/HyperTwist/ROADMAP.md b/docs/v6_5_deep_manual_pack/HyperTwist/ROADMAP.md index 359a8f7..432a432 100644 --- a/docs/v6_5_deep_manual_pack/HyperTwist/ROADMAP.md +++ b/docs/v6_5_deep_manual_pack/HyperTwist/ROADMAP.md @@ -165,8 +165,10 @@ Canonical discovery surfaces for roadmap interpretation: pass is now consumed - the bounded first-party `Phase S1-B` skill settings/menu/off-state control packet is now landed in current code -- `S1-C` invocation/provenance/audit ledger is now the next clean skillization - move +- the generic first-party `Phase S1-C` invocation/provenance/audit-ledger + control pass is now consumed +- the bounded first-party `Phase S1-C` invocation/provenance/audit-ledger + packet is now landed in current code - 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 0bfa1f2..bce90d7 100644 --- a/docs/v6_5_deep_manual_pack/HyperTwist/SKILLS.md +++ b/docs/v6_5_deep_manual_pack/HyperTwist/SKILLS.md @@ -56,12 +56,14 @@ Includes: - skill registry/manifest contract - enable/disable controls - visibility grouping + - invocation record format + - command/service provenance ledger + - failure/cancel audit recording - command/service binding declarations - permission/scope declarations - provenance/log declarations - validation harness - still deferred: - - provenance/invocation ledger execution - authoring template expansion ### Analyzer and review skills @@ -128,10 +130,9 @@ A coding model working on HyperTwist should still be able to: The next correct skillization sequence is: -1. invocation/provenance/audit ledger -2. authoring/examples/validation harness expansion -3. permissive analyzer wrappers -4. clean-room command-contract specs for restrictive lanes +1. authoring/examples/validation harness expansion +2. permissive analyzer wrappers +3. clean-room command-contract specs for restrictive lanes Broader memory, provider, and domain skill widening should wait until that base exists.