Implement Phase S1-A skill registry and manifest contract
This commit is contained in:
parent
740b89e6bd
commit
87676bdb41
15 changed files with 1427 additions and 18 deletions
|
|
@ -1,6 +1,7 @@
|
|||
#include "HyperTwistBootstrap/HyperTwistContractLibrary.h"
|
||||
|
||||
#include "HyperTwistMemory/HyperTwistMemoryCoreLibrary.h"
|
||||
#include "HyperTwistSkills/HyperTwistSkillCoreLibrary.h"
|
||||
#include "HyperTwistRecognition/HyperTwistRecognitionReplayLibrary.h"
|
||||
#include "HyperTwistReplay/HyperTwistReplayReviewLibrary.h"
|
||||
#include "HyperTwistTraining/HyperTwistTrainingCatalogLibrary.h"
|
||||
|
|
@ -3909,6 +3910,11 @@ FHyperTwistMemoryDerivedAdjunctState
|
|||
);
|
||||
}
|
||||
|
||||
FHyperTwistSkillRegistryState UHyperTwistContractLibrary::MakeSampleSkillRegistryState()
|
||||
{
|
||||
return UHyperTwistSkillCoreLibrary::DeriveSkillRegistryState();
|
||||
}
|
||||
|
||||
FHyperTwistTrainingRepositoryIntegrityReport UHyperTwistContractLibrary::MakeSampleTrainingRepositoryIntegrityReport()
|
||||
{
|
||||
FHyperTwistTrainingRepositoryState RepositoryState = MakeSampleTrainingRepositoryState();
|
||||
|
|
@ -5018,6 +5024,15 @@ FString UHyperTwistContractLibrary::SerializeMemoryDerivedAdjunctStateToJson(
|
|||
);
|
||||
}
|
||||
|
||||
FString UHyperTwistContractLibrary::SerializeSkillRegistryStateToJson(
|
||||
const FHyperTwistSkillRegistryState& SkillRegistryState
|
||||
)
|
||||
{
|
||||
return HyperTwistContractLibraryInternal::SerializeStructToJson(
|
||||
SkillRegistryState
|
||||
);
|
||||
}
|
||||
|
||||
FString UHyperTwistContractLibrary::SerializeTrainingTimerExportPacketToJson(
|
||||
const FHyperTwistTrainingTimerExportPacket& TimerExportPacket
|
||||
)
|
||||
|
|
@ -5140,6 +5155,17 @@ bool UHyperTwistContractLibrary::DeserializeMemoryDerivedAdjunctStateFromJson(
|
|||
);
|
||||
}
|
||||
|
||||
bool UHyperTwistContractLibrary::DeserializeSkillRegistryStateFromJson(
|
||||
const FString& Json,
|
||||
FHyperTwistSkillRegistryState& OutSkillRegistryState
|
||||
)
|
||||
{
|
||||
return HyperTwistContractLibraryInternal::DeserializeStructFromJson(
|
||||
Json,
|
||||
OutSkillRegistryState
|
||||
);
|
||||
}
|
||||
|
||||
bool UHyperTwistContractLibrary::DeserializeTrainingTimerExportPacketFromJson(
|
||||
const FString& Json,
|
||||
FHyperTwistTrainingTimerExportPacket& OutTimerExportPacket
|
||||
|
|
|
|||
|
|
@ -0,0 +1,415 @@
|
|||
#include "HyperTwistSkills/HyperTwistSkillCoreLibrary.h"
|
||||
|
||||
namespace HyperTwistSkillCoreLibraryInternal
|
||||
{
|
||||
FHyperTwistSkillCommandBindingDeclaration MakeCommandBinding(
|
||||
const TCHAR* CommandSurfaceId,
|
||||
const TCHAR* ServiceBindingId,
|
||||
const TCHAR* BoundFeatureId,
|
||||
const TCHAR* InvocationPattern,
|
||||
const bool bRequiresImplementedService,
|
||||
const TCHAR* Summary
|
||||
)
|
||||
{
|
||||
FHyperTwistSkillCommandBindingDeclaration Binding;
|
||||
Binding.CommandSurfaceId = CommandSurfaceId;
|
||||
Binding.ServiceBindingId = ServiceBindingId;
|
||||
Binding.BoundFeatureId = BoundFeatureId;
|
||||
Binding.InvocationPattern = InvocationPattern;
|
||||
Binding.bRequiresImplementedService = bRequiresImplementedService;
|
||||
Binding.Summary = Summary;
|
||||
return Binding;
|
||||
}
|
||||
|
||||
FHyperTwistSkillPermissionScopeDeclaration MakePermissionScope(
|
||||
const TCHAR* ScopeId,
|
||||
const TCHAR* DisplayLabel,
|
||||
const bool bReadsTrainingState,
|
||||
const bool bReadsRecognitionState,
|
||||
const bool bReadsReplayState,
|
||||
const bool bReadsMemoryState,
|
||||
const bool bReadsProviderState,
|
||||
const bool bMayToggleOptionalAssistiveState,
|
||||
const bool bMayEmitDerivedAssistiveOutput,
|
||||
const TCHAR* Summary
|
||||
)
|
||||
{
|
||||
FHyperTwistSkillPermissionScopeDeclaration Scope;
|
||||
Scope.ScopeId = ScopeId;
|
||||
Scope.DisplayLabel = DisplayLabel;
|
||||
Scope.bReadsTrainingState = bReadsTrainingState;
|
||||
Scope.bReadsRecognitionState = bReadsRecognitionState;
|
||||
Scope.bReadsReplayState = bReadsReplayState;
|
||||
Scope.bReadsMemoryState = bReadsMemoryState;
|
||||
Scope.bReadsProviderState = bReadsProviderState;
|
||||
Scope.bMayToggleOptionalAssistiveState = bMayToggleOptionalAssistiveState;
|
||||
Scope.bMayEmitDerivedAssistiveOutput = bMayEmitDerivedAssistiveOutput;
|
||||
Scope.Summary = Summary;
|
||||
return Scope;
|
||||
}
|
||||
|
||||
FHyperTwistSkillProvenanceDeclaration MakeProvenanceDeclaration(
|
||||
const EHyperTwistSkillLogPolicy LogPolicy,
|
||||
const TArray<FString>& ProducedArtifactKinds,
|
||||
const bool bRequiresInvocationLoggingWhenEnabled,
|
||||
const TCHAR* Summary
|
||||
)
|
||||
{
|
||||
FHyperTwistSkillProvenanceDeclaration Provenance;
|
||||
Provenance.LogPolicy = LogPolicy;
|
||||
Provenance.ProducedArtifactKinds = ProducedArtifactKinds;
|
||||
Provenance.bRequiresCommandProvenanceDeclaration = true;
|
||||
Provenance.bRequiresInvocationLoggingWhenEnabled = bRequiresInvocationLoggingWhenEnabled;
|
||||
Provenance.Summary = Summary;
|
||||
return Provenance;
|
||||
}
|
||||
|
||||
FHyperTwistSkillManifestEntry MakeSkillEntry(
|
||||
const TCHAR* SkillId,
|
||||
const TCHAR* DisplayLabel,
|
||||
const TCHAR* OwnerLaneId,
|
||||
const TCHAR* OwnerFeatureId,
|
||||
const EHyperTwistSkillFamily Family,
|
||||
const EHyperTwistSkillStatus Status,
|
||||
const bool bEnabledByDefault,
|
||||
const bool bVisibleByDefault,
|
||||
const TArray<FHyperTwistSkillCommandBindingDeclaration>& CommandBindings,
|
||||
const TArray<FHyperTwistSkillPermissionScopeDeclaration>& PermissionScopes,
|
||||
const FHyperTwistSkillProvenanceDeclaration& Provenance,
|
||||
const TCHAR* Summary
|
||||
)
|
||||
{
|
||||
FHyperTwistSkillManifestEntry Entry;
|
||||
Entry.SkillId = SkillId;
|
||||
Entry.Version = TEXT("s1a-v1");
|
||||
Entry.DisplayLabel = DisplayLabel;
|
||||
Entry.OwnerLaneId = OwnerLaneId;
|
||||
Entry.OwnerFeatureId = OwnerFeatureId;
|
||||
Entry.Family = Family;
|
||||
Entry.Status = Status;
|
||||
Entry.bOptionalAssistive = true;
|
||||
Entry.bEnabledByDefault = bEnabledByDefault;
|
||||
Entry.bVisibleByDefault = bVisibleByDefault;
|
||||
Entry.bInstalledWhenDisabled = true;
|
||||
Entry.bInertWhenDisabled = true;
|
||||
Entry.CommandBindings = CommandBindings;
|
||||
Entry.PermissionScopes = PermissionScopes;
|
||||
Entry.Provenance = Provenance;
|
||||
Entry.Summary = Summary;
|
||||
return Entry;
|
||||
}
|
||||
|
||||
FHyperTwistSkillStatusCount MakeStatusCount(
|
||||
const EHyperTwistSkillStatus Status,
|
||||
const int32 Count
|
||||
)
|
||||
{
|
||||
FHyperTwistSkillStatusCount StatusCount;
|
||||
StatusCount.Status = Status;
|
||||
StatusCount.Count = Count;
|
||||
return StatusCount;
|
||||
}
|
||||
|
||||
FHyperTwistSkillFamilyCount MakeFamilyCount(
|
||||
const EHyperTwistSkillFamily Family,
|
||||
const int32 Count
|
||||
)
|
||||
{
|
||||
FHyperTwistSkillFamilyCount FamilyCount;
|
||||
FamilyCount.Family = Family;
|
||||
FamilyCount.Count = Count;
|
||||
return FamilyCount;
|
||||
}
|
||||
}
|
||||
|
||||
FHyperTwistSkillRegistryState UHyperTwistSkillCoreLibrary::DeriveSkillRegistryState()
|
||||
{
|
||||
using namespace HyperTwistSkillCoreLibraryInternal;
|
||||
|
||||
FHyperTwistSkillRegistryState RegistryState;
|
||||
RegistryState.RegistryId = TEXT("skill-registry/first-party");
|
||||
RegistryState.ManifestVersion = TEXT("s1a-v1");
|
||||
RegistryState.ReferenceUtc = TEXT("2026-05-28T19:30:00Z");
|
||||
RegistryState.CommandSurfaceRootId = TEXT("command-surface/skills");
|
||||
RegistryState.Summary =
|
||||
TEXT("First-party skill registry and manifest contract declarations only.");
|
||||
|
||||
RegistryState.Entries = {
|
||||
MakeSkillEntry(
|
||||
TEXT("skill/skillization-governance"),
|
||||
TEXT("Skillization Governance"),
|
||||
TEXT("lane/skillization/substrate"),
|
||||
TEXT("feature/skills/registry-governance"),
|
||||
EHyperTwistSkillFamily::SubstrateGovernance,
|
||||
EHyperTwistSkillStatus::ImplementedNow,
|
||||
true,
|
||||
false,
|
||||
{
|
||||
MakeCommandBinding(
|
||||
TEXT("command/skills/inspect-registry"),
|
||||
TEXT("service/skills/registry-state"),
|
||||
TEXT("feature/skills/registry-governance"),
|
||||
TEXT("command-surface/query"),
|
||||
true,
|
||||
TEXT("Current first-party registry inspection surface.")
|
||||
)
|
||||
},
|
||||
{
|
||||
MakePermissionScope(
|
||||
TEXT("scope/skills/governance"),
|
||||
TEXT("Skill Governance"),
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
TEXT("Allows inspection and bounded optional-assistive governance.")
|
||||
)
|
||||
},
|
||||
MakeProvenanceDeclaration(
|
||||
EHyperTwistSkillLogPolicy::DeclarationOnly,
|
||||
{TEXT("artifact/skill-registry-state")},
|
||||
false,
|
||||
TEXT("Registry inspection currently declares provenance before a later invocation ledger lands.")
|
||||
),
|
||||
TEXT("Landed first-party skill registry and manifest governance substrate.")
|
||||
),
|
||||
MakeSkillEntry(
|
||||
TEXT("skill/review-architecture"),
|
||||
TEXT("Architecture Review"),
|
||||
TEXT("lane/skillization/analysis-review"),
|
||||
TEXT("feature/skills/review-analyzer"),
|
||||
EHyperTwistSkillFamily::AnalysisReview,
|
||||
EHyperTwistSkillStatus::CommandContractPending,
|
||||
false,
|
||||
false,
|
||||
{
|
||||
MakeCommandBinding(
|
||||
TEXT("command/skills/review-architecture"),
|
||||
TEXT("service/deferred/review-architecture"),
|
||||
TEXT("feature/skills/review-analyzer"),
|
||||
TEXT("deferred-wrapper"),
|
||||
false,
|
||||
TEXT("Permissive analyzer wrapper stays deferred until later skillization stages.")
|
||||
)
|
||||
},
|
||||
{
|
||||
MakePermissionScope(
|
||||
TEXT("scope/skills/review-output"),
|
||||
TEXT("Review Output"),
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
TEXT("Allows derived assistive review output only.")
|
||||
)
|
||||
},
|
||||
MakeProvenanceDeclaration(
|
||||
EHyperTwistSkillLogPolicy::InvocationLedgerRequired,
|
||||
{TEXT("artifact/review-report")},
|
||||
true,
|
||||
TEXT("Review wrappers must emit provenance-visible reports once invocation logging lands.")
|
||||
),
|
||||
TEXT("Declared but not yet wrapped analyzer/review family.")
|
||||
),
|
||||
MakeSkillEntry(
|
||||
TEXT("skill/memory-resume-briefing"),
|
||||
TEXT("Memory Resume Briefing"),
|
||||
TEXT("lane/skillization/memory-continuity"),
|
||||
TEXT("feature/skills/memory-resume"),
|
||||
EHyperTwistSkillFamily::MemoryContinuity,
|
||||
EHyperTwistSkillStatus::CommandContractPending,
|
||||
false,
|
||||
false,
|
||||
{
|
||||
MakeCommandBinding(
|
||||
TEXT("command/skills/memory-resume-briefing"),
|
||||
TEXT("service/deferred/memory-resume-briefing"),
|
||||
TEXT("feature/skills/memory-resume"),
|
||||
TEXT("deferred-wrapper"),
|
||||
false,
|
||||
TEXT("Future wrapper over the landed first-party memory seams.")
|
||||
)
|
||||
},
|
||||
{
|
||||
MakePermissionScope(
|
||||
TEXT("scope/skills/memory-resume"),
|
||||
TEXT("Memory Resume"),
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
TEXT("Reads training and memory state to emit bounded resume output.")
|
||||
)
|
||||
},
|
||||
MakeProvenanceDeclaration(
|
||||
EHyperTwistSkillLogPolicy::InvocationLedgerRequired,
|
||||
{TEXT("artifact/resume-pack")},
|
||||
true,
|
||||
TEXT("Shared resume packets must stay provenance-visible once wrappers land.")
|
||||
),
|
||||
TEXT("Declared memory/continuity skill family above the landed memory substrate.")
|
||||
),
|
||||
MakeSkillEntry(
|
||||
TEXT("skill/provider-routing-inspector"),
|
||||
TEXT("Provider Routing Inspector"),
|
||||
TEXT("lane/skillization/provider-ops"),
|
||||
TEXT("feature/skills/provider-routing-inspector"),
|
||||
EHyperTwistSkillFamily::ProviderOperations,
|
||||
EHyperTwistSkillStatus::CommandContractPending,
|
||||
false,
|
||||
false,
|
||||
{
|
||||
MakeCommandBinding(
|
||||
TEXT("command/skills/provider-routing-inspector"),
|
||||
TEXT("service/deferred/provider-routing-inspector"),
|
||||
TEXT("feature/skills/provider-routing-inspector"),
|
||||
TEXT("deferred-wrapper"),
|
||||
false,
|
||||
TEXT("Future wrapper over landed provider-neutral speech/provider contracts.")
|
||||
)
|
||||
},
|
||||
{
|
||||
MakePermissionScope(
|
||||
TEXT("scope/skills/provider-routing"),
|
||||
TEXT("Provider Routing"),
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
TEXT("Reads recognition/provider state to emit bounded operator diagnostics.")
|
||||
)
|
||||
},
|
||||
MakeProvenanceDeclaration(
|
||||
EHyperTwistSkillLogPolicy::InvocationLedgerRequired,
|
||||
{TEXT("artifact/provider-diagnostic-packet")},
|
||||
true,
|
||||
TEXT("Provider inspection output must stay provenance-visible once wrappers land.")
|
||||
),
|
||||
TEXT("Declared provider/ops family above the landed speech/provider seams.")
|
||||
),
|
||||
MakeSkillEntry(
|
||||
TEXT("skill/roux-session-review"),
|
||||
TEXT("Roux Session Review"),
|
||||
TEXT("lane/skillization/training-clean-room"),
|
||||
TEXT("feature/skills/roux-session-review"),
|
||||
EHyperTwistSkillFamily::TrainingCoaching,
|
||||
EHyperTwistSkillStatus::CleanRoomSpecPending,
|
||||
false,
|
||||
false,
|
||||
{
|
||||
MakeCommandBinding(
|
||||
TEXT("command/skills/roux-session-review"),
|
||||
TEXT("service/deferred/roux-session-review"),
|
||||
TEXT("feature/skills/roux-session-review"),
|
||||
TEXT("clean-room-command-spec"),
|
||||
false,
|
||||
TEXT("Restrictive lane remains spec-only until a later clean-room command contract lands.")
|
||||
)
|
||||
},
|
||||
{
|
||||
MakePermissionScope(
|
||||
TEXT("scope/skills/training-review"),
|
||||
TEXT("Training Review"),
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
TEXT("Reads training and replay state to emit derived assistive coaching output.")
|
||||
)
|
||||
},
|
||||
MakeProvenanceDeclaration(
|
||||
EHyperTwistSkillLogPolicy::InvocationLedgerRequired,
|
||||
{TEXT("artifact/training-review-brief")},
|
||||
true,
|
||||
TEXT("Restrictive skill outputs must stay provenance-visible if later clean-roomed.")
|
||||
),
|
||||
TEXT("Declared clean-room-pending training/coaching skill family.")
|
||||
),
|
||||
MakeSkillEntry(
|
||||
TEXT("skill/curriculum-draft-pack"),
|
||||
TEXT("Curriculum Draft Pack"),
|
||||
TEXT("lane/skillization/domain-creative"),
|
||||
TEXT("feature/skills/curriculum-draft-pack"),
|
||||
EHyperTwistSkillFamily::DomainCreative,
|
||||
EHyperTwistSkillStatus::PlaceholderFamily,
|
||||
false,
|
||||
false,
|
||||
{
|
||||
MakeCommandBinding(
|
||||
TEXT("command/skills/curriculum-draft-pack"),
|
||||
TEXT("service/deferred/curriculum-draft-pack"),
|
||||
TEXT("feature/skills/curriculum-draft-pack"),
|
||||
TEXT("placeholder-family"),
|
||||
false,
|
||||
TEXT("Placeholder domain pack stays declared only until source-grounded.")
|
||||
)
|
||||
},
|
||||
{
|
||||
MakePermissionScope(
|
||||
TEXT("scope/skills/domain-creative"),
|
||||
TEXT("Domain Creative"),
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
TEXT("Would emit derived curriculum artifacts only after later source-grounding.")
|
||||
)
|
||||
},
|
||||
MakeProvenanceDeclaration(
|
||||
EHyperTwistSkillLogPolicy::InvocationLedgerRequired,
|
||||
{TEXT("artifact/curriculum-draft-pack")},
|
||||
true,
|
||||
TEXT("Placeholder domain packs must still declare future provenance obligations.")
|
||||
),
|
||||
TEXT("Declared placeholder domain/creative family only.")
|
||||
)
|
||||
};
|
||||
|
||||
RegistryState.SkillCount = RegistryState.Entries.Num();
|
||||
for (const FHyperTwistSkillManifestEntry& Entry : RegistryState.Entries)
|
||||
{
|
||||
RegistryState.EnabledByDefaultCount += Entry.bEnabledByDefault ? 1 : 0;
|
||||
}
|
||||
RegistryState.DisabledByDefaultCount =
|
||||
RegistryState.SkillCount - RegistryState.EnabledByDefaultCount;
|
||||
RegistryState.bAllSkillsOptionalAssistive = true;
|
||||
RegistryState.bDisabledSkillsRemainInstalled = true;
|
||||
RegistryState.bDisabledSkillsAreInert = true;
|
||||
RegistryState.bNoAdHocMetadataRequired = true;
|
||||
|
||||
RegistryState.StatusCounts = {
|
||||
MakeStatusCount(EHyperTwistSkillStatus::ImplementedNow, 1),
|
||||
MakeStatusCount(EHyperTwistSkillStatus::CommandContractPending, 3),
|
||||
MakeStatusCount(EHyperTwistSkillStatus::CleanRoomSpecPending, 1),
|
||||
MakeStatusCount(EHyperTwistSkillStatus::PlaceholderFamily, 1)
|
||||
};
|
||||
|
||||
RegistryState.FamilyCounts = {
|
||||
MakeFamilyCount(EHyperTwistSkillFamily::SubstrateGovernance, 1),
|
||||
MakeFamilyCount(EHyperTwistSkillFamily::AnalysisReview, 1),
|
||||
MakeFamilyCount(EHyperTwistSkillFamily::MemoryContinuity, 1),
|
||||
MakeFamilyCount(EHyperTwistSkillFamily::ProviderOperations, 1),
|
||||
MakeFamilyCount(EHyperTwistSkillFamily::TrainingCoaching, 1),
|
||||
MakeFamilyCount(EHyperTwistSkillFamily::DomainCreative, 1)
|
||||
};
|
||||
|
||||
return RegistryState;
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||
#include "HyperTwistCore/HyperTwistCoreTypes.h"
|
||||
#include "HyperTwistMemory/HyperTwistMemoryTypes.h"
|
||||
#include "HyperTwistSkills/HyperTwistSkillTypes.h"
|
||||
#include "HyperTwistRecognition/HyperTwistRecognitionReplayLibrary.h"
|
||||
#include "HyperTwistReplay/HyperTwistReplayTypes.h"
|
||||
#include "HyperTwistReplay/HyperTwistReplayReviewLibrary.h"
|
||||
|
|
@ -163,6 +164,9 @@ public:
|
|||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Memory")
|
||||
static FHyperTwistMemoryDerivedAdjunctState MakeSampleTrainingMemoryDerivedAdjunctState();
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Skills")
|
||||
static FHyperTwistSkillRegistryState MakeSampleSkillRegistryState();
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training")
|
||||
static FHyperTwistTrainingRepositoryIntegrityReport MakeSampleTrainingRepositoryIntegrityReport();
|
||||
|
||||
|
|
@ -352,6 +356,11 @@ public:
|
|||
const FHyperTwistMemoryDerivedAdjunctState& DerivedAdjunctState
|
||||
);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Serialization")
|
||||
static FString SerializeSkillRegistryStateToJson(
|
||||
const FHyperTwistSkillRegistryState& SkillRegistryState
|
||||
);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Serialization")
|
||||
static FString SerializeTrainingTimerExportPacketToJson(const FHyperTwistTrainingTimerExportPacket& TimerExportPacket);
|
||||
|
||||
|
|
@ -424,6 +433,12 @@ public:
|
|||
FHyperTwistMemoryDerivedAdjunctState& OutDerivedAdjunctState
|
||||
);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Serialization")
|
||||
static bool DeserializeSkillRegistryStateFromJson(
|
||||
const FString& Json,
|
||||
FHyperTwistSkillRegistryState& OutSkillRegistryState
|
||||
);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Serialization")
|
||||
static bool DeserializeTrainingTimerExportPacketFromJson(const FString& Json, FHyperTwistTrainingTimerExportPacket& OutTimerExportPacket);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||
#include "HyperTwistSkills/HyperTwistSkillTypes.h"
|
||||
#include "HyperTwistSkillCoreLibrary.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class UNREALHYPERTWIST_API UHyperTwistSkillCoreLibrary : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintPure, Category = "HyperTwist|Skills")
|
||||
static FHyperTwistSkillRegistryState DeriveSkillRegistryState();
|
||||
};
|
||||
|
|
@ -0,0 +1,425 @@
|
|||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "HyperTwistSkillTypes.generated.h"
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EHyperTwistSkillStatus : uint8
|
||||
{
|
||||
None UMETA(DisplayName = "None"),
|
||||
ImplementedNow UMETA(DisplayName = "Implemented Now"),
|
||||
CommandContractPending UMETA(DisplayName = "Command Contract Pending"),
|
||||
CleanRoomSpecPending UMETA(DisplayName = "Clean-Room Spec Pending"),
|
||||
PlaceholderFamily UMETA(DisplayName = "Placeholder Family")
|
||||
};
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EHyperTwistSkillFamily : uint8
|
||||
{
|
||||
None UMETA(DisplayName = "None"),
|
||||
SubstrateGovernance UMETA(DisplayName = "Substrate Governance"),
|
||||
AnalysisReview UMETA(DisplayName = "Analysis And Review"),
|
||||
MemoryContinuity UMETA(DisplayName = "Memory And Continuity"),
|
||||
ProviderOperations UMETA(DisplayName = "Provider And Operations"),
|
||||
TrainingCoaching UMETA(DisplayName = "Training And Coaching"),
|
||||
DomainCreative UMETA(DisplayName = "Domain And Creative")
|
||||
};
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EHyperTwistSkillLogPolicy : uint8
|
||||
{
|
||||
None UMETA(DisplayName = "None"),
|
||||
DeclarationOnly UMETA(DisplayName = "Declaration Only"),
|
||||
InvocationLedgerRequired UMETA(DisplayName = "Invocation Ledger Required")
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistSkillCommandBindingDeclaration
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
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")
|
||||
bool bRequiresImplementedService = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString Summary;
|
||||
|
||||
bool IsStructurallyValid() const
|
||||
{
|
||||
return !CommandSurfaceId.IsEmpty()
|
||||
&& !ServiceBindingId.IsEmpty()
|
||||
&& !BoundFeatureId.IsEmpty()
|
||||
&& !InvocationPattern.IsEmpty();
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistSkillPermissionScopeDeclaration
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString ScopeId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString DisplayLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bReadsTrainingState = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bReadsRecognitionState = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bReadsReplayState = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bReadsMemoryState = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bReadsProviderState = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bMayToggleOptionalAssistiveState = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bMayEmitDerivedAssistiveOutput = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString Summary;
|
||||
|
||||
bool IsStructurallyValid() const
|
||||
{
|
||||
return !ScopeId.IsEmpty()
|
||||
&& !DisplayLabel.IsEmpty()
|
||||
&& (bReadsTrainingState
|
||||
|| bReadsRecognitionState
|
||||
|| bReadsReplayState
|
||||
|| bReadsMemoryState
|
||||
|| bReadsProviderState
|
||||
|| bMayToggleOptionalAssistiveState
|
||||
|| bMayEmitDerivedAssistiveOutput);
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistSkillProvenanceDeclaration
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
EHyperTwistSkillLogPolicy LogPolicy = EHyperTwistSkillLogPolicy::None;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
TArray<FString> ProducedArtifactKinds;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bRequiresCommandProvenanceDeclaration = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bRequiresInvocationLoggingWhenEnabled = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString Summary;
|
||||
|
||||
bool IsStructurallyValid() const
|
||||
{
|
||||
if (LogPolicy == EHyperTwistSkillLogPolicy::None
|
||||
|| !bRequiresCommandProvenanceDeclaration
|
||||
|| ProducedArtifactKinds.Num() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const FString& ArtifactKind : ProducedArtifactKinds)
|
||||
{
|
||||
if (ArtifactKind.IsEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistSkillManifestEntry
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString SkillId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString Version;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString DisplayLabel;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString OwnerLaneId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString OwnerFeatureId;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
EHyperTwistSkillFamily Family = EHyperTwistSkillFamily::None;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
EHyperTwistSkillStatus Status = EHyperTwistSkillStatus::None;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bOptionalAssistive = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bEnabledByDefault = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bVisibleByDefault = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bInstalledWhenDisabled = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bInertWhenDisabled = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
TArray<FHyperTwistSkillCommandBindingDeclaration> CommandBindings;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
TArray<FHyperTwistSkillPermissionScopeDeclaration> PermissionScopes;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FHyperTwistSkillProvenanceDeclaration Provenance;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString Summary;
|
||||
|
||||
bool IsStructurallyValid() const
|
||||
{
|
||||
if (SkillId.IsEmpty()
|
||||
|| Version.IsEmpty()
|
||||
|| DisplayLabel.IsEmpty()
|
||||
|| OwnerLaneId.IsEmpty()
|
||||
|| OwnerFeatureId.IsEmpty()
|
||||
|| Family == EHyperTwistSkillFamily::None
|
||||
|| Status == EHyperTwistSkillStatus::None
|
||||
|| !bOptionalAssistive
|
||||
|| !bInstalledWhenDisabled
|
||||
|| !bInertWhenDisabled
|
||||
|| CommandBindings.Num() == 0
|
||||
|| PermissionScopes.Num() == 0
|
||||
|| !Provenance.IsStructurallyValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const FHyperTwistSkillCommandBindingDeclaration& Binding : CommandBindings)
|
||||
{
|
||||
if (!Binding.IsStructurallyValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (const FHyperTwistSkillPermissionScopeDeclaration& Scope : PermissionScopes)
|
||||
{
|
||||
if (!Scope.IsStructurallyValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistSkillStatusCount
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
EHyperTwistSkillStatus Status = EHyperTwistSkillStatus::None;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 Count = 0;
|
||||
|
||||
bool IsStructurallyValid() const
|
||||
{
|
||||
return Status != EHyperTwistSkillStatus::None && Count > 0;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistSkillFamilyCount
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
EHyperTwistSkillFamily Family = EHyperTwistSkillFamily::None;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 Count = 0;
|
||||
|
||||
bool IsStructurallyValid() const
|
||||
{
|
||||
return Family != EHyperTwistSkillFamily::None && Count > 0;
|
||||
}
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistSkillRegistryState
|
||||
{
|
||||
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")
|
||||
TArray<FHyperTwistSkillManifestEntry> Entries;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
TArray<FHyperTwistSkillStatusCount> StatusCounts;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
TArray<FHyperTwistSkillFamilyCount> FamilyCounts;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 SkillCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 EnabledByDefaultCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
int32 DisabledByDefaultCount = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bAllSkillsOptionalAssistive = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bDisabledSkillsRemainInstalled = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bDisabledSkillsAreInert = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bNoAdHocMetadataRequired = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
FString Summary;
|
||||
|
||||
bool IsStructurallyValid() const
|
||||
{
|
||||
if (RegistryId.IsEmpty()
|
||||
|| ManifestVersion.IsEmpty()
|
||||
|| ReferenceUtc.IsEmpty()
|
||||
|| CommandSurfaceRootId.IsEmpty()
|
||||
|| Entries.Num() == 0
|
||||
|| SkillCount != Entries.Num()
|
||||
|| !bAllSkillsOptionalAssistive
|
||||
|| !bDisabledSkillsRemainInstalled
|
||||
|| !bDisabledSkillsAreInert
|
||||
|| !bNoAdHocMetadataRequired)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TArray<FString> SeenSkillIds;
|
||||
int32 ComputedEnabledByDefaultCount = 0;
|
||||
bool bComputedAllOptionalAssistive = true;
|
||||
bool bComputedDisabledRemainInstalled = true;
|
||||
bool bComputedDisabledAreInert = true;
|
||||
|
||||
for (const FHyperTwistSkillManifestEntry& Entry : Entries)
|
||||
{
|
||||
if (!Entry.IsStructurallyValid() || SeenSkillIds.Contains(Entry.SkillId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
SeenSkillIds.Add(Entry.SkillId);
|
||||
ComputedEnabledByDefaultCount += Entry.bEnabledByDefault ? 1 : 0;
|
||||
bComputedAllOptionalAssistive &= Entry.bOptionalAssistive;
|
||||
bComputedDisabledRemainInstalled &= Entry.bInstalledWhenDisabled;
|
||||
bComputedDisabledAreInert &= Entry.bInertWhenDisabled;
|
||||
}
|
||||
|
||||
if (EnabledByDefaultCount != ComputedEnabledByDefaultCount
|
||||
|| DisabledByDefaultCount != (Entries.Num() - ComputedEnabledByDefaultCount)
|
||||
|| bAllSkillsOptionalAssistive != bComputedAllOptionalAssistive
|
||||
|| bDisabledSkillsRemainInstalled != bComputedDisabledRemainInstalled
|
||||
|| bDisabledSkillsAreInert != bComputedDisabledAreInert)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TArray<EHyperTwistSkillStatus> SeenStatuses;
|
||||
for (const FHyperTwistSkillStatusCount& StatusCount : StatusCounts)
|
||||
{
|
||||
if (!StatusCount.IsStructurallyValid() || SeenStatuses.Contains(StatusCount.Status))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int32 ComputedCount = 0;
|
||||
for (const FHyperTwistSkillManifestEntry& Entry : Entries)
|
||||
{
|
||||
ComputedCount += Entry.Status == StatusCount.Status ? 1 : 0;
|
||||
}
|
||||
|
||||
if (ComputedCount != StatusCount.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
SeenStatuses.Add(StatusCount.Status);
|
||||
}
|
||||
|
||||
TArray<EHyperTwistSkillFamily> SeenFamilies;
|
||||
for (const FHyperTwistSkillFamilyCount& FamilyCount : FamilyCounts)
|
||||
{
|
||||
if (!FamilyCount.IsStructurallyValid() || SeenFamilies.Contains(FamilyCount.Family))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int32 ComputedCount = 0;
|
||||
for (const FHyperTwistSkillManifestEntry& Entry : Entries)
|
||||
{
|
||||
ComputedCount += Entry.Family == FamilyCount.Family ? 1 : 0;
|
||||
}
|
||||
|
||||
if (ComputedCount != FamilyCount.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
SeenFamilies.Add(FamilyCount.Family);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,262 @@
|
|||
// Copyright HyperTwist, Inc. All Rights Reserved.
|
||||
|
||||
#include "Misc/AutomationTest.h"
|
||||
|
||||
#include "HyperTwistBootstrap/HyperTwistContractLibrary.h"
|
||||
|
||||
#if WITH_AUTOMATION_TESTS
|
||||
|
||||
namespace HyperTwistSkillPhaseS1ATestInternal
|
||||
{
|
||||
const FHyperTwistSkillManifestEntry* FindSkillById(
|
||||
const FHyperTwistSkillRegistryState& RegistryState,
|
||||
const FString& SkillId
|
||||
)
|
||||
{
|
||||
for (const FHyperTwistSkillManifestEntry& Entry : RegistryState.Entries)
|
||||
{
|
||||
if (Entry.SkillId == SkillId)
|
||||
{
|
||||
return &Entry;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int32 FindStatusCount(
|
||||
const FHyperTwistSkillRegistryState& RegistryState,
|
||||
const EHyperTwistSkillStatus Status
|
||||
)
|
||||
{
|
||||
for (const FHyperTwistSkillStatusCount& StatusCount : RegistryState.StatusCounts)
|
||||
{
|
||||
if (StatusCount.Status == Status)
|
||||
{
|
||||
return StatusCount.Count;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32 FindFamilyCount(
|
||||
const FHyperTwistSkillRegistryState& RegistryState,
|
||||
const EHyperTwistSkillFamily Family
|
||||
)
|
||||
{
|
||||
for (const FHyperTwistSkillFamilyCount& FamilyCount : RegistryState.FamilyCounts)
|
||||
{
|
||||
if (FamilyCount.Family == Family)
|
||||
{
|
||||
return FamilyCount.Count;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
|
||||
FHyperTwistSkillPhaseS1ARegistryManifestTest,
|
||||
"HyperTwist.FirstParty.Skill.PhaseS1A.RegistryManifest",
|
||||
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
|
||||
)
|
||||
|
||||
bool FHyperTwistSkillPhaseS1ARegistryManifestTest::RunTest(const FString& Parameters)
|
||||
{
|
||||
const FHyperTwistSkillRegistryState RegistryState =
|
||||
UHyperTwistContractLibrary::MakeSampleSkillRegistryState();
|
||||
|
||||
TestTrue(
|
||||
TEXT("The Phase S1-A skill registry must be structurally valid."),
|
||||
RegistryState.IsStructurallyValid()
|
||||
);
|
||||
TestEqual(
|
||||
TEXT("The sample S1-A registry must expose six declared skills."),
|
||||
RegistryState.SkillCount,
|
||||
6
|
||||
);
|
||||
TestTrue(
|
||||
TEXT("The S1-A registry must avoid ad hoc metadata."),
|
||||
RegistryState.bNoAdHocMetadataRequired
|
||||
);
|
||||
TestTrue(
|
||||
TEXT("The S1-A registry must keep the whole family optional-assistive."),
|
||||
RegistryState.bAllSkillsOptionalAssistive
|
||||
);
|
||||
TestEqual(
|
||||
TEXT("The sample S1-A registry must keep one implemented skill entry."),
|
||||
HyperTwistSkillPhaseS1ATestInternal::FindStatusCount(
|
||||
RegistryState,
|
||||
EHyperTwistSkillStatus::ImplementedNow
|
||||
),
|
||||
1
|
||||
);
|
||||
TestEqual(
|
||||
TEXT("The sample S1-A registry must keep three command-contract-pending entries."),
|
||||
HyperTwistSkillPhaseS1ATestInternal::FindStatusCount(
|
||||
RegistryState,
|
||||
EHyperTwistSkillStatus::CommandContractPending
|
||||
),
|
||||
3
|
||||
);
|
||||
TestEqual(
|
||||
TEXT("The sample S1-A registry must expose one governance-family entry."),
|
||||
HyperTwistSkillPhaseS1ATestInternal::FindFamilyCount(
|
||||
RegistryState,
|
||||
EHyperTwistSkillFamily::SubstrateGovernance
|
||||
),
|
||||
1
|
||||
);
|
||||
|
||||
const FHyperTwistSkillManifestEntry* GovernanceSkill =
|
||||
HyperTwistSkillPhaseS1ATestInternal::FindSkillById(
|
||||
RegistryState,
|
||||
TEXT("skill/skillization-governance")
|
||||
);
|
||||
TestNotNull(
|
||||
TEXT("The governance skill entry must exist."),
|
||||
GovernanceSkill
|
||||
);
|
||||
if (GovernanceSkill != nullptr)
|
||||
{
|
||||
TestEqual(
|
||||
TEXT("The governance skill must be implemented now."),
|
||||
GovernanceSkill->Status,
|
||||
EHyperTwistSkillStatus::ImplementedNow
|
||||
);
|
||||
TestTrue(
|
||||
TEXT("The governance skill must expose a command binding."),
|
||||
GovernanceSkill->CommandBindings.Num() > 0
|
||||
);
|
||||
TestEqual(
|
||||
TEXT("The governance skill must bind to the first-party registry service."),
|
||||
GovernanceSkill->CommandBindings[0].ServiceBindingId,
|
||||
TEXT("service/skills/registry-state")
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
|
||||
FHyperTwistSkillPhaseS1ADisabledSkillsRemainInstalledTest,
|
||||
"HyperTwist.FirstParty.Skill.PhaseS1A.DisabledSkillsRemainInstalled",
|
||||
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
|
||||
)
|
||||
|
||||
bool FHyperTwistSkillPhaseS1ADisabledSkillsRemainInstalledTest::RunTest(
|
||||
const FString& Parameters
|
||||
)
|
||||
{
|
||||
const FHyperTwistSkillRegistryState RegistryState =
|
||||
UHyperTwistContractLibrary::MakeSampleSkillRegistryState();
|
||||
|
||||
TestTrue(
|
||||
TEXT("The S1-A registry must confirm disabled skills remain installed."),
|
||||
RegistryState.bDisabledSkillsRemainInstalled
|
||||
);
|
||||
TestTrue(
|
||||
TEXT("The S1-A registry must confirm disabled skills are inert."),
|
||||
RegistryState.bDisabledSkillsAreInert
|
||||
);
|
||||
TestTrue(
|
||||
TEXT("The sample S1-A registry must keep disabled-by-default entries."),
|
||||
RegistryState.DisabledByDefaultCount > 0
|
||||
);
|
||||
|
||||
const FHyperTwistSkillManifestEntry* DeferredProviderSkill =
|
||||
HyperTwistSkillPhaseS1ATestInternal::FindSkillById(
|
||||
RegistryState,
|
||||
TEXT("skill/provider-routing-inspector")
|
||||
);
|
||||
TestNotNull(
|
||||
TEXT("A disabled provider-routing-inspector skill must exist."),
|
||||
DeferredProviderSkill
|
||||
);
|
||||
if (DeferredProviderSkill != nullptr)
|
||||
{
|
||||
TestFalse(
|
||||
TEXT("The deferred provider skill must start disabled by default."),
|
||||
DeferredProviderSkill->bEnabledByDefault
|
||||
);
|
||||
TestTrue(
|
||||
TEXT("The deferred provider skill must remain installed when disabled."),
|
||||
DeferredProviderSkill->bInstalledWhenDisabled
|
||||
);
|
||||
TestTrue(
|
||||
TEXT("The deferred provider skill must stay inert when disabled."),
|
||||
DeferredProviderSkill->bInertWhenDisabled
|
||||
);
|
||||
TestEqual(
|
||||
TEXT("The deferred provider skill must stay command-contract pending."),
|
||||
DeferredProviderSkill->Status,
|
||||
EHyperTwistSkillStatus::CommandContractPending
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
|
||||
FHyperTwistSkillPhaseS1ASerializationRoundTripTest,
|
||||
"HyperTwist.FirstParty.Skill.PhaseS1A.SerializationRoundTrip",
|
||||
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
|
||||
)
|
||||
|
||||
bool FHyperTwistSkillPhaseS1ASerializationRoundTripTest::RunTest(
|
||||
const FString& Parameters
|
||||
)
|
||||
{
|
||||
const FHyperTwistSkillRegistryState RegistryState =
|
||||
UHyperTwistContractLibrary::MakeSampleSkillRegistryState();
|
||||
TestTrue(
|
||||
TEXT("The Phase S1-A registry must be structurally valid before serialization."),
|
||||
RegistryState.IsStructurallyValid()
|
||||
);
|
||||
|
||||
const FString Json =
|
||||
UHyperTwistContractLibrary::SerializeSkillRegistryStateToJson(RegistryState);
|
||||
TestFalse(TEXT("The serialized S1-A JSON must not be empty."), Json.IsEmpty());
|
||||
TestTrue(
|
||||
TEXT("The serialized S1-A JSON must expose manifest entries."),
|
||||
Json.Contains(TEXT("Entries"))
|
||||
);
|
||||
TestTrue(
|
||||
TEXT("The serialized S1-A JSON must expose the inert-off-state contract."),
|
||||
Json.Contains(TEXT("bDisabledSkillsRemainInstalled"))
|
||||
);
|
||||
|
||||
FHyperTwistSkillRegistryState RoundTrippedState;
|
||||
TestTrue(
|
||||
TEXT("The S1-A JSON must deserialize cleanly."),
|
||||
UHyperTwistContractLibrary::DeserializeSkillRegistryStateFromJson(
|
||||
Json,
|
||||
RoundTrippedState
|
||||
)
|
||||
);
|
||||
TestTrue(
|
||||
TEXT("The round-tripped S1-A registry must remain structurally valid."),
|
||||
RoundTrippedState.IsStructurallyValid()
|
||||
);
|
||||
TestEqual(
|
||||
TEXT("The round-tripped S1-A registry must preserve skill counts."),
|
||||
RoundTrippedState.SkillCount,
|
||||
RegistryState.SkillCount
|
||||
);
|
||||
TestEqual(
|
||||
TEXT("The round-tripped S1-A registry must preserve disabled-by-default counts."),
|
||||
RoundTrippedState.DisabledByDefaultCount,
|
||||
RegistryState.DisabledByDefaultCount
|
||||
);
|
||||
TestEqual(
|
||||
TEXT("The round-tripped S1-A registry must preserve family-count cardinality."),
|
||||
RoundTrippedState.FamilyCounts.Num(),
|
||||
RegistryState.FamilyCounts.Num()
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
# HyperTwist Phase S1-A first-party skill registry and manifest contract implementation packet
|
||||
|
||||
Created on `2026-05-28`
|
||||
|
||||
## Status
|
||||
|
||||
- first-party HyperTwist packet
|
||||
- bounded `Phase S1-A` implementation slice
|
||||
|
||||
## Purpose
|
||||
|
||||
This packet lands the bounded first-party skill registry and manifest contract
|
||||
seam under the canonical `Skillization And Command Surface` doctrine.
|
||||
|
||||
The landed slice is:
|
||||
|
||||
- first-party skill manifest schema
|
||||
- skill id, version, owner lane, and status fields
|
||||
- command/service binding declaration
|
||||
- permission/scope declaration
|
||||
- provenance/log declaration
|
||||
|
||||
It is not:
|
||||
|
||||
- settings/menu/off-state runtime controls
|
||||
- invocation/provenance audit ledger execution
|
||||
- permissive analyzer wrappers
|
||||
- restrictive clean-room command-contract specs
|
||||
|
||||
## 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_A_FIRST_PARTY_SKILL_REGISTRY_AND_MANIFEST_CONTRACT_PREPARATION_PACKET_2026-05-28.md`
|
||||
|
||||
The preserved owners do not change:
|
||||
|
||||
- first-party HyperTwist remains the owner of the product command surface
|
||||
- optional assistive skills remain product-owned adjunct declarations rather
|
||||
than donor command truth
|
||||
- analyzer, memory, provider, and domain skill families remain later bounded
|
||||
wrappers rather than shipped invocation owners
|
||||
|
||||
## Landed scope
|
||||
|
||||
The current code now owns a bounded first-party skill registry seam through:
|
||||
|
||||
- canonical skill status, family, command-binding, permission-scope,
|
||||
provenance-declaration, manifest-entry, and registry-state types in:
|
||||
- `HyperTwistSkillTypes.h`
|
||||
- first-party skill-registry derivation in:
|
||||
- `UHyperTwistSkillCoreLibrary`
|
||||
- current bounded manifest coverage for:
|
||||
- the landed registry-governance substrate
|
||||
- declared analyzer/review family
|
||||
- declared memory/continuity family
|
||||
- declared provider/ops family
|
||||
- declared clean-room-pending training/coaching family
|
||||
- declared placeholder domain/creative family
|
||||
- current bounded disabled-skill installation/inertness truth through:
|
||||
- explicit registry and per-skill fields proving disabled entries remain
|
||||
installed but inert
|
||||
- sample contract helpers in:
|
||||
- `UHyperTwistContractLibrary::MakeSampleSkillRegistryState()`
|
||||
- `UHyperTwistContractLibrary::SerializeSkillRegistryStateToJson(...)`
|
||||
- `UHyperTwistContractLibrary::DeserializeSkillRegistryStateFromJson(...)`
|
||||
- focused automation coverage in:
|
||||
- `HyperTwistSkillPhaseS1ARegistryManifestContractTest.cpp`
|
||||
|
||||
## Why this is still intentionally bounded
|
||||
|
||||
This packet lands declarations only.
|
||||
|
||||
Still deferred:
|
||||
|
||||
- actual settings/menu/off-state runtime controls
|
||||
- invocation/provenance audit ledger execution
|
||||
- permissive analyzer wrappers
|
||||
- restrictive clean-room command-contract specs
|
||||
|
||||
## Validation
|
||||
|
||||
Build validation:
|
||||
|
||||
- `UnrealHyperTwistEditor Win64 Development`
|
||||
|
||||
Focused automation validation:
|
||||
|
||||
- `HyperTwist.FirstParty.Skill.PhaseS1A.RegistryManifest`
|
||||
- `HyperTwist.FirstParty.Skill.PhaseS1A.DisabledSkillsRemainInstalled`
|
||||
- `HyperTwist.FirstParty.Skill.PhaseS1A.SerializationRoundTrip`
|
||||
|
||||
Observed:
|
||||
|
||||
- `3` focused `Phase S1-A` automation tests succeeded
|
||||
|
||||
## Queue effect
|
||||
|
||||
This packet consumes the current `Phase S1-A` implementation slice.
|
||||
|
||||
After this landing:
|
||||
|
||||
- `S1-A` is landed in current code
|
||||
- `S1-B` is the next clean skillization move
|
||||
- do not jump straight from `S1-A` to analyzer wrappers or restrictive command
|
||||
specs
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
# HyperTwist Phase S1-A first-party skill registry and manifest contract preparation packet
|
||||
|
||||
Created on `2026-05-28`
|
||||
|
||||
## Status
|
||||
|
||||
- first-party HyperTwist packet
|
||||
- source-backed `Phase S1-A` preparation/control slice
|
||||
|
||||
## Purpose
|
||||
|
||||
This packet scopes the first bounded product implementation slice under the
|
||||
canonical `Skillization And Command Surface` doctrine.
|
||||
|
||||
The granted slice is:
|
||||
|
||||
- first-party skill manifest schema
|
||||
- skill id, version, owner lane, and status fields
|
||||
- command/service binding declaration
|
||||
- permission/scope declaration
|
||||
- provenance/log declaration
|
||||
|
||||
It is not:
|
||||
|
||||
- menu/settings/off-state controls
|
||||
- invocation/provenance audit ledger execution
|
||||
- permissive analyzer wrappers
|
||||
- restrictive clean-room command-contract specs
|
||||
|
||||
## 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`
|
||||
|
||||
The preserved owners do not change here:
|
||||
|
||||
- first-party HyperTwist remains the owner of the product command surface
|
||||
- optional assistive skills remain product-owned adjuncts rather than donor
|
||||
command truth
|
||||
- analyzer, memory, provider, and domain skill families remain bounded future
|
||||
families rather than shipped wrappers
|
||||
|
||||
## Granted family
|
||||
|
||||
The bounded `Phase S1-A` slice may land:
|
||||
|
||||
1. first-party skill status and family enums
|
||||
2. command/service binding declarations
|
||||
3. permission/scope declarations
|
||||
4. provenance/log declarations
|
||||
5. per-skill manifest entries and registry counts
|
||||
6. sample registry contract and JSON round-trip coverage
|
||||
|
||||
The packet must stay out of:
|
||||
|
||||
- real enable/disable settings behavior
|
||||
- menu visibility controls
|
||||
- actual invocation ledger storage
|
||||
- broad wrapper implementation
|
||||
|
||||
## Proposed implementation shape
|
||||
|
||||
Land the narrower first-party boundary through:
|
||||
|
||||
- new skill types for:
|
||||
- skill status
|
||||
- skill family
|
||||
- command bindings
|
||||
- permission scopes
|
||||
- provenance declarations
|
||||
- manifest entries
|
||||
- registry state
|
||||
- a first-party skill-core library that derives a bounded registry state
|
||||
- sample-contract helpers for:
|
||||
- sample registry derivation
|
||||
- JSON serialization
|
||||
- JSON deserialization
|
||||
- focused automation in:
|
||||
- `HyperTwistSkillPhaseS1ARegistryManifestContractTest.cpp`
|
||||
|
||||
## Validation target
|
||||
|
||||
Validate with:
|
||||
|
||||
- Unreal build for `UnrealHyperTwistEditor Win64 Development`
|
||||
- focused automation:
|
||||
- `HyperTwist.FirstParty.Skill.PhaseS1A.RegistryManifest`
|
||||
- `HyperTwist.FirstParty.Skill.PhaseS1A.DisabledSkillsRemainInstalled`
|
||||
- `HyperTwist.FirstParty.Skill.PhaseS1A.SerializationRoundTrip`
|
||||
|
||||
## Queue effect
|
||||
|
||||
If this packet lands cleanly:
|
||||
|
||||
- `S1-A` is consumed
|
||||
- `S1-B` becomes the next clean move
|
||||
- do not jump straight from `S1-A` to analyzer wrappers or restrictive specs
|
||||
|
|
@ -271,7 +271,8 @@ First follow:
|
|||
|
||||
Specifically:
|
||||
|
||||
- `S1-A` registry and manifest contract
|
||||
- `S1-B` settings/menu/off-state control
|
||||
- `S2-A` permissive analyzer wrappers
|
||||
- `S2-B` clean-room command-contract specs
|
||||
- the bounded first-party `Phase S1-A` skill registry and manifest contract
|
||||
packet is now landed in current code
|
||||
- `S1-B` settings/menu/off-state control is the next clean move
|
||||
- `S2-A` permissive analyzer wrappers stay deferred until `S1-B` lands
|
||||
- `S2-B` clean-room command-contract specs stay deferred until `S2-A`
|
||||
|
|
|
|||
|
|
@ -200,6 +200,13 @@ Acceptance gates:
|
|||
- every skill can be described without ad hoc metadata
|
||||
- disabled skills remain installed but inert
|
||||
|
||||
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`
|
||||
|
||||
#### `S1-B` settings, menu, and visibility controls
|
||||
|
||||
Outputs:
|
||||
|
|
@ -450,10 +457,9 @@ These are target-shape command families, not claims of implemented reality.
|
|||
|
||||
The next correct sequence is:
|
||||
|
||||
1. `S1-A` first-party skill registry and manifest contract
|
||||
2. `S1-B` per-skill settings/menu exposure and off-state behavior
|
||||
3. `S2-A` permissive analyzer wrappers
|
||||
4. `S2-B` clean-room command-contract specs for restrictive lanes
|
||||
1. `S1-B` per-skill settings/menu exposure and off-state behavior
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -234,3 +234,7 @@ Do not let donor commands or optional skills become hidden product truth.
|
|||
Future skill growth must follow:
|
||||
|
||||
- `C:\HyperTwist\docs\ops\HYPERTWIST_SKILLIZATION_AND_COMMAND_SURFACE_DOCTRINE_2026-05-21.md`
|
||||
- the bounded first-party `Phase S1-A` registry/manifest seam is now the live
|
||||
product base for skill status, command binding, permission, and provenance
|
||||
declarations
|
||||
- `S1-B` remains the next clean move before any wrapper widening
|
||||
|
|
|
|||
|
|
@ -304,7 +304,7 @@ repo.
|
|||
|
||||
| Feature | Status | Primary authority | Notes |
|
||||
|---|---|---|---|
|
||||
| First-party skill registry and enable/disable governance | Deep-source grounded retained | skillization doctrine | Required base; not implemented yet. |
|
||||
| First-party skill registry and enable/disable governance | Implemented now | landed first-party `Phase S1-A` packet | Current bounded first-party skill status/family contracts, command/service binding declarations, permission/scope declarations, provenance/log declarations, manifest entries, registry counts, and disabled-but-installed inert-off-state truth are live. Settings/menu controls and invocation ledger execution remain deferred to later bounded skillization stages. |
|
||||
| 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. |
|
||||
|
|
|
|||
|
|
@ -90,6 +90,18 @@ Companion extraction surface:
|
|||
|
||||
- `C:\HyperTwist\docs\v6_5_deep_manual_pack\HyperTwist\FEATURE_REGISTRY.md`
|
||||
|
||||
## Skill-specific consequence
|
||||
|
||||
The skillization doctrine now requires provenance-visible declaration even
|
||||
before wrapper execution lands.
|
||||
|
||||
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
|
||||
|
||||
## Memory-specific consequence
|
||||
|
||||
The memory doctrine defines provenance/trust-ledger memory as a distinct lane
|
||||
|
|
|
|||
|
|
@ -157,6 +157,12 @@ Canonical discovery surfaces for roadmap interpretation:
|
|||
- do not reopen `6R-M1`, `6R-M2`, `6R-M3`, `6R-M4`, `6R-M5`, or `6R-M6` as broad memory
|
||||
packets
|
||||
- the bounded first-party memory packet family is now closed through `6R-M6`
|
||||
- the generic first-party `Phase S1-A` skill registry and manifest contract
|
||||
control pass is now consumed
|
||||
- the bounded first-party `Phase S1-A` skill registry and manifest contract
|
||||
packet is now landed in current code
|
||||
- `S1-B` settings/menu/off-state control is now the next clean skillization
|
||||
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
|
||||
|
|
|
|||
|
|
@ -48,14 +48,19 @@ These are retained doctrine-level families, not live implementation claims.
|
|||
|
||||
Status:
|
||||
|
||||
- Deep-source grounded retained
|
||||
- Implemented now, bounded substrate only
|
||||
|
||||
Includes:
|
||||
|
||||
- skill registry/manifest
|
||||
- enable/disable controls
|
||||
- provenance/invocation ledger
|
||||
- validation harness
|
||||
- landed now:
|
||||
- skill registry/manifest contract
|
||||
- command/service binding declarations
|
||||
- permission/scope declarations
|
||||
- provenance/log declarations
|
||||
- validation harness
|
||||
- still deferred:
|
||||
- enable/disable controls
|
||||
- provenance/invocation ledger execution
|
||||
|
||||
### Analyzer and review skills
|
||||
|
||||
|
|
@ -121,10 +126,9 @@ A coding model working on HyperTwist should still be able to:
|
|||
|
||||
The next correct skillization sequence is:
|
||||
|
||||
1. skill registry/manifest contract
|
||||
2. settings/menu/off-state controls
|
||||
3. permissive analyzer wrappers
|
||||
4. clean-room command-contract specs for restrictive lanes
|
||||
1. settings/menu/off-state controls
|
||||
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.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue