Implement Phase S1-B skill settings menu and off-state control

This commit is contained in:
axiomlogicnexus 2026-05-28 22:24:39 +02:00
parent 87676bdb41
commit f01fa43af6
15 changed files with 1219 additions and 16 deletions

View file

@ -26,6 +26,24 @@ namespace HyperTwistContractLibraryInternal
return FJsonObjectConverter::JsonObjectStringToUStruct(Json, &OutValue, 0, 0);
}
FHyperTwistSkillControlProfile MakeSampleSkillControlProfile(const bool bMasterEnabled)
{
FHyperTwistSkillControlProfile ControlProfile;
ControlProfile.ProfileId = bMasterEnabled
? TEXT("skill-controls/default")
: TEXT("skill-controls/all-skills-off");
ControlProfile.DisplayLabel = bMasterEnabled
? TEXT("Default Skill Controls")
: TEXT("All Skills Off");
ControlProfile.bMasterEnabled = bMasterEnabled;
ControlProfile.bDurableSettingsExposed = true;
ControlProfile.bImmediateMenuControlExposed = true;
ControlProfile.Summary = bMasterEnabled
? TEXT("Default first-party skill control profile.")
: TEXT("Control profile proving the core product remains valid with all skills off.");
return ControlProfile;
}
FHyperTwistCoachSessionQueueSummary MakeSampleCoachSessionQueueSummaryManual()
{
FHyperTwistCoachSessionQueueSummary QueueSummary;
@ -3915,6 +3933,22 @@ FHyperTwistSkillRegistryState UHyperTwistContractLibrary::MakeSampleSkillRegistr
return UHyperTwistSkillCoreLibrary::DeriveSkillRegistryState();
}
FHyperTwistSkillControlState UHyperTwistContractLibrary::MakeSampleSkillControlState()
{
return UHyperTwistSkillCoreLibrary::DeriveSkillControlState(
MakeSampleSkillRegistryState(),
HyperTwistContractLibraryInternal::MakeSampleSkillControlProfile(true)
);
}
FHyperTwistSkillControlState UHyperTwistContractLibrary::MakeAllSkillsOffSkillControlState()
{
return UHyperTwistSkillCoreLibrary::DeriveSkillControlState(
MakeSampleSkillRegistryState(),
HyperTwistContractLibraryInternal::MakeSampleSkillControlProfile(false)
);
}
FHyperTwistTrainingRepositoryIntegrityReport UHyperTwistContractLibrary::MakeSampleTrainingRepositoryIntegrityReport()
{
FHyperTwistTrainingRepositoryState RepositoryState = MakeSampleTrainingRepositoryState();
@ -5033,6 +5067,15 @@ FString UHyperTwistContractLibrary::SerializeSkillRegistryStateToJson(
);
}
FString UHyperTwistContractLibrary::SerializeSkillControlStateToJson(
const FHyperTwistSkillControlState& SkillControlState
)
{
return HyperTwistContractLibraryInternal::SerializeStructToJson(
SkillControlState
);
}
FString UHyperTwistContractLibrary::SerializeTrainingTimerExportPacketToJson(
const FHyperTwistTrainingTimerExportPacket& TimerExportPacket
)
@ -5166,6 +5209,17 @@ bool UHyperTwistContractLibrary::DeserializeSkillRegistryStateFromJson(
);
}
bool UHyperTwistContractLibrary::DeserializeSkillControlStateFromJson(
const FString& Json,
FHyperTwistSkillControlState& OutSkillControlState
)
{
return HyperTwistContractLibraryInternal::DeserializeStructFromJson(
Json,
OutSkillControlState
);
}
bool UHyperTwistContractLibrary::DeserializeTrainingTimerExportPacketFromJson(
const FString& Json,
FHyperTwistTrainingTimerExportPacket& OutTimerExportPacket

View file

@ -120,6 +120,197 @@ namespace HyperTwistSkillCoreLibraryInternal
FamilyCount.Count = Count;
return FamilyCount;
}
FString MakeSkillSettingsSlug(const FString& SkillId)
{
FString Slug = SkillId;
Slug.ReplaceInline(TEXT("/"), TEXT("."));
Slug.ReplaceInline(TEXT("-"), TEXT("."));
return Slug;
}
FString MakeEnableSettingsKey(const FString& SkillId)
{
return TEXT("skills.enabled.") + MakeSkillSettingsSlug(SkillId);
}
FString MakeVisibilitySettingsKey(const FString& SkillId)
{
return TEXT("skills.visible.") + MakeSkillSettingsSlug(SkillId);
}
FString MakeVisibilityGroupId(const EHyperTwistSkillFamily Family)
{
switch (Family)
{
case EHyperTwistSkillFamily::SubstrateGovernance:
return TEXT("skill-group/substrate-governance");
case EHyperTwistSkillFamily::AnalysisReview:
return TEXT("skill-group/analysis-review");
case EHyperTwistSkillFamily::MemoryContinuity:
return TEXT("skill-group/memory-continuity");
case EHyperTwistSkillFamily::ProviderOperations:
return TEXT("skill-group/provider-operations");
case EHyperTwistSkillFamily::TrainingCoaching:
return TEXT("skill-group/training-coaching");
case EHyperTwistSkillFamily::DomainCreative:
return TEXT("skill-group/domain-creative");
default:
return FString();
}
}
FString MakeVisibilityGroupLabel(const EHyperTwistSkillFamily Family)
{
switch (Family)
{
case EHyperTwistSkillFamily::SubstrateGovernance:
return TEXT("Substrate Governance");
case EHyperTwistSkillFamily::AnalysisReview:
return TEXT("Analysis And Review");
case EHyperTwistSkillFamily::MemoryContinuity:
return TEXT("Memory And Continuity");
case EHyperTwistSkillFamily::ProviderOperations:
return TEXT("Provider And Operations");
case EHyperTwistSkillFamily::TrainingCoaching:
return TEXT("Training And Coaching");
case EHyperTwistSkillFamily::DomainCreative:
return TEXT("Domain And Creative");
default:
return FString();
}
}
FString MakeVisibilityGroupSettingsKey(const EHyperTwistSkillFamily Family)
{
return TEXT("skills.group.visible.")
+ MakeSkillSettingsSlug(MakeVisibilityGroupId(Family));
}
const FHyperTwistSkillControlOverride* FindControlOverride(
const FHyperTwistSkillControlProfile& ControlProfile,
const FString& SkillId
)
{
for (const FHyperTwistSkillControlOverride& Override : ControlProfile.Overrides)
{
if (Override.SkillId == SkillId)
{
return &Override;
}
}
return nullptr;
}
FHyperTwistSkillMasterSwitchState MakeMasterSwitchState(
const FHyperTwistSkillControlProfile& ControlProfile
)
{
FHyperTwistSkillMasterSwitchState MasterSwitch;
MasterSwitch.SettingsKey = TEXT("skills.master.enabled");
MasterSwitch.DisplayLabel = TEXT("Enable Skills");
MasterSwitch.bEnabled = ControlProfile.bMasterEnabled;
MasterSwitch.bDurableSettingExposed = ControlProfile.bDurableSettingsExposed;
MasterSwitch.bImmediateMenuControlExposed = ControlProfile.bImmediateMenuControlExposed;
MasterSwitch.bAllSkillsOffSafe = true;
MasterSwitch.Summary =
TEXT("Global master gate for optional assistive skills.");
return MasterSwitch;
}
FHyperTwistSkillControlStateEntry MakeControlStateEntry(
const FHyperTwistSkillManifestEntry& Entry,
const FHyperTwistSkillControlProfile& ControlProfile
)
{
const FHyperTwistSkillControlOverride* Override =
FindControlOverride(ControlProfile, Entry.SkillId);
const bool bRequestedEnabled =
(Override != nullptr && Override->bHasEnabledOverride)
? Override->bEnabled
: Entry.bEnabledByDefault;
const bool bRequestedVisible =
(Override != nullptr && Override->bHasVisibilityOverride)
? Override->bVisible
: Entry.bVisibleByDefault;
FHyperTwistSkillControlStateEntry SkillState;
SkillState.SkillId = Entry.SkillId;
SkillState.DisplayLabel = Entry.DisplayLabel;
SkillState.EnableSettingsKey = MakeEnableSettingsKey(Entry.SkillId);
SkillState.VisibilitySettingsKey = MakeVisibilitySettingsKey(Entry.SkillId);
SkillState.VisibilityGroupId = MakeVisibilityGroupId(Entry.Family);
SkillState.Family = Entry.Family;
SkillState.Status = Entry.Status;
SkillState.bInstalled = Entry.bInstalledWhenDisabled;
SkillState.bOptionalAssistive = Entry.bOptionalAssistive;
SkillState.bRequestedEnabled = bRequestedEnabled;
SkillState.bEffectiveEnabled = ControlProfile.bMasterEnabled && bRequestedEnabled;
SkillState.bRequestedVisible = bRequestedVisible;
SkillState.bEffectiveVisible = bRequestedVisible;
SkillState.bInertWhenDisabled = Entry.bInertWhenDisabled;
SkillState.bDurableSettingExposed = ControlProfile.bDurableSettingsExposed;
SkillState.bImmediateMenuControlExposed = ControlProfile.bImmediateMenuControlExposed;
SkillState.Summary = Entry.Summary;
return SkillState;
}
void AddOrUpdateVisibilityGroup(
FHyperTwistSkillControlState& ControlState,
const FHyperTwistSkillControlStateEntry& SkillState
)
{
FHyperTwistSkillVisibilityGroupState* Group = ControlState.VisibilityGroups.FindByPredicate(
[&SkillState](const FHyperTwistSkillVisibilityGroupState& ExistingGroup)
{
return ExistingGroup.GroupId == SkillState.VisibilityGroupId;
}
);
if (Group == nullptr)
{
FHyperTwistSkillVisibilityGroupState NewGroup;
NewGroup.GroupId = SkillState.VisibilityGroupId;
NewGroup.DisplayLabel = MakeVisibilityGroupLabel(SkillState.Family);
NewGroup.VisibilitySettingsKey = MakeVisibilityGroupSettingsKey(SkillState.Family);
NewGroup.Family = SkillState.Family;
NewGroup.bGroupVisibleByDefault = SkillState.bRequestedVisible;
NewGroup.bDurableVisibilityControlExposed = SkillState.bDurableSettingExposed;
NewGroup.Summary = TEXT("Family-based visibility grouping for optional skills.");
ControlState.VisibilityGroups.Add(NewGroup);
Group = &ControlState.VisibilityGroups.Last();
}
Group->SkillIds.Add(SkillState.SkillId);
Group->VisibleSkillCount += SkillState.bEffectiveVisible ? 1 : 0;
Group->HiddenSkillCount += SkillState.bEffectiveVisible ? 0 : 1;
Group->bGroupVisibleByDefault |= SkillState.bRequestedVisible;
}
FHyperTwistSkillControlProfile MakeDefaultControlProfile()
{
FHyperTwistSkillControlProfile ControlProfile;
ControlProfile.ProfileId = TEXT("skill-controls/default");
ControlProfile.DisplayLabel = TEXT("Default Skill Controls");
ControlProfile.bMasterEnabled = true;
ControlProfile.bDurableSettingsExposed = true;
ControlProfile.bImmediateMenuControlExposed = true;
ControlProfile.Summary =
TEXT("Default first-party skill control profile.");
return ControlProfile;
}
FHyperTwistSkillControlProfile MakeAllSkillsOffControlProfile()
{
FHyperTwistSkillControlProfile ControlProfile = MakeDefaultControlProfile();
ControlProfile.ProfileId = TEXT("skill-controls/all-skills-off");
ControlProfile.DisplayLabel = TEXT("All Skills Off");
ControlProfile.bMasterEnabled = false;
ControlProfile.Summary =
TEXT("Control profile proving the core product remains valid with all skills off.");
return ControlProfile;
}
}
FHyperTwistSkillRegistryState UHyperTwistSkillCoreLibrary::DeriveSkillRegistryState()
@ -143,7 +334,7 @@ FHyperTwistSkillRegistryState UHyperTwistSkillCoreLibrary::DeriveSkillRegistrySt
EHyperTwistSkillFamily::SubstrateGovernance,
EHyperTwistSkillStatus::ImplementedNow,
true,
false,
true,
{
MakeCommandBinding(
TEXT("command/skills/inspect-registry"),
@ -184,7 +375,7 @@ FHyperTwistSkillRegistryState UHyperTwistSkillCoreLibrary::DeriveSkillRegistrySt
EHyperTwistSkillFamily::AnalysisReview,
EHyperTwistSkillStatus::CommandContractPending,
false,
false,
true,
{
MakeCommandBinding(
TEXT("command/skills/review-architecture"),
@ -225,7 +416,7 @@ FHyperTwistSkillRegistryState UHyperTwistSkillCoreLibrary::DeriveSkillRegistrySt
EHyperTwistSkillFamily::MemoryContinuity,
EHyperTwistSkillStatus::CommandContractPending,
false,
false,
true,
{
MakeCommandBinding(
TEXT("command/skills/memory-resume-briefing"),
@ -266,7 +457,7 @@ FHyperTwistSkillRegistryState UHyperTwistSkillCoreLibrary::DeriveSkillRegistrySt
EHyperTwistSkillFamily::ProviderOperations,
EHyperTwistSkillStatus::CommandContractPending,
false,
false,
true,
{
MakeCommandBinding(
TEXT("command/skills/provider-routing-inspector"),
@ -413,3 +604,52 @@ FHyperTwistSkillRegistryState UHyperTwistSkillCoreLibrary::DeriveSkillRegistrySt
return RegistryState;
}
FHyperTwistSkillControlState UHyperTwistSkillCoreLibrary::DeriveSkillControlState(
const FHyperTwistSkillRegistryState& RegistryState,
const FHyperTwistSkillControlProfile& ControlProfile
)
{
using namespace HyperTwistSkillCoreLibraryInternal;
if (!RegistryState.IsStructurallyValid() || !ControlProfile.IsStructurallyValid())
{
return FHyperTwistSkillControlState();
}
FHyperTwistSkillControlState ControlState;
ControlState.RegistryId = RegistryState.RegistryId;
ControlState.ManifestVersion = TEXT("s1b-v1");
ControlState.ReferenceUtc = TEXT("2026-05-28T21:15:00Z");
ControlState.CommandSurfaceRootId = RegistryState.CommandSurfaceRootId;
ControlState.ControlProfileId = ControlProfile.ProfileId;
ControlState.MasterSwitch = MakeMasterSwitchState(ControlProfile);
ControlState.Summary =
TEXT("First-party skill settings, menu, and off-state control contract.");
for (const FHyperTwistSkillManifestEntry& Entry : RegistryState.Entries)
{
const FHyperTwistSkillControlStateEntry SkillState =
MakeControlStateEntry(Entry, ControlProfile);
if (!SkillState.IsStructurallyValid())
{
return FHyperTwistSkillControlState();
}
ControlState.SkillStates.Add(SkillState);
ControlState.EffectiveEnabledSkillCount += SkillState.bEffectiveEnabled ? 1 : 0;
ControlState.VisibleSkillCount += SkillState.bEffectiveVisible ? 1 : 0;
AddOrUpdateVisibilityGroup(ControlState, SkillState);
}
ControlState.SkillCount = ControlState.SkillStates.Num();
ControlState.EffectiveDisabledSkillCount =
ControlState.SkillCount - ControlState.EffectiveEnabledSkillCount;
ControlState.HiddenSkillCount =
ControlState.SkillCount - ControlState.VisibleSkillCount;
ControlState.bCoreProductWorksWithAllSkillsOff = true;
ControlState.bNoPromptBabysittingToDisable = true;
ControlState.bAllInstalledSkillsRemainReenableable = true;
return ControlState;
}

View file

@ -167,6 +167,12 @@ public:
UFUNCTION(BlueprintPure, Category = "HyperTwist|Skills")
static FHyperTwistSkillRegistryState MakeSampleSkillRegistryState();
UFUNCTION(BlueprintPure, Category = "HyperTwist|Skills")
static FHyperTwistSkillControlState MakeSampleSkillControlState();
UFUNCTION(BlueprintPure, Category = "HyperTwist|Skills")
static FHyperTwistSkillControlState MakeAllSkillsOffSkillControlState();
UFUNCTION(BlueprintPure, Category = "HyperTwist|Training")
static FHyperTwistTrainingRepositoryIntegrityReport MakeSampleTrainingRepositoryIntegrityReport();
@ -361,6 +367,11 @@ public:
const FHyperTwistSkillRegistryState& SkillRegistryState
);
UFUNCTION(BlueprintPure, Category = "HyperTwist|Serialization")
static FString SerializeSkillControlStateToJson(
const FHyperTwistSkillControlState& SkillControlState
);
UFUNCTION(BlueprintPure, Category = "HyperTwist|Serialization")
static FString SerializeTrainingTimerExportPacketToJson(const FHyperTwistTrainingTimerExportPacket& TimerExportPacket);
@ -439,6 +450,12 @@ public:
FHyperTwistSkillRegistryState& OutSkillRegistryState
);
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Serialization")
static bool DeserializeSkillControlStateFromJson(
const FString& Json,
FHyperTwistSkillControlState& OutSkillControlState
);
UFUNCTION(BlueprintCallable, Category = "HyperTwist|Serialization")
static bool DeserializeTrainingTimerExportPacketFromJson(const FString& Json, FHyperTwistTrainingTimerExportPacket& OutTimerExportPacket);
};

View file

@ -13,4 +13,10 @@ class UNREALHYPERTWIST_API UHyperTwistSkillCoreLibrary : public UBlueprintFuncti
public:
UFUNCTION(BlueprintPure, Category = "HyperTwist|Skills")
static FHyperTwistSkillRegistryState DeriveSkillRegistryState();
UFUNCTION(BlueprintPure, Category = "HyperTwist|Skills")
static FHyperTwistSkillControlState DeriveSkillControlState(
const FHyperTwistSkillRegistryState& RegistryState,
const FHyperTwistSkillControlProfile& ControlProfile
);
};

View file

@ -423,3 +423,381 @@ struct FHyperTwistSkillRegistryState
return true;
}
};
USTRUCT(BlueprintType)
struct FHyperTwistSkillControlOverride
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString SkillId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasEnabledOverride = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bEnabled = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bHasVisibilityOverride = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bVisible = false;
bool IsStructurallyValid() const
{
return !SkillId.IsEmpty()
&& (bHasEnabledOverride || bHasVisibilityOverride);
}
};
USTRUCT(BlueprintType)
struct FHyperTwistSkillControlProfile
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString ProfileId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString DisplayLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bMasterEnabled = true;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bDurableSettingsExposed = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bImmediateMenuControlExposed = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
TArray<FHyperTwistSkillControlOverride> Overrides;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString Summary;
bool IsStructurallyValid() const
{
if (ProfileId.IsEmpty()
|| DisplayLabel.IsEmpty()
|| !bDurableSettingsExposed)
{
return false;
}
TArray<FString> SeenSkillIds;
for (const FHyperTwistSkillControlOverride& Override : Overrides)
{
if (!Override.IsStructurallyValid() || SeenSkillIds.Contains(Override.SkillId))
{
return false;
}
SeenSkillIds.Add(Override.SkillId);
}
return true;
}
};
USTRUCT(BlueprintType)
struct FHyperTwistSkillMasterSwitchState
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString SettingsKey;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString DisplayLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bEnabled = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bDurableSettingExposed = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bImmediateMenuControlExposed = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bAllSkillsOffSafe = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString Summary;
bool IsStructurallyValid() const
{
return !SettingsKey.IsEmpty()
&& !DisplayLabel.IsEmpty()
&& bDurableSettingExposed
&& bAllSkillsOffSafe;
}
};
USTRUCT(BlueprintType)
struct FHyperTwistSkillControlStateEntry
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString SkillId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString DisplayLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString EnableSettingsKey;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString VisibilitySettingsKey;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString VisibilityGroupId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
EHyperTwistSkillFamily Family = EHyperTwistSkillFamily::None;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
EHyperTwistSkillStatus Status = EHyperTwistSkillStatus::None;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bInstalled = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bOptionalAssistive = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bRequestedEnabled = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bEffectiveEnabled = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bRequestedVisible = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bEffectiveVisible = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bInertWhenDisabled = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bDurableSettingExposed = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bImmediateMenuControlExposed = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString Summary;
bool IsStructurallyValid() const
{
return !SkillId.IsEmpty()
&& !DisplayLabel.IsEmpty()
&& !EnableSettingsKey.IsEmpty()
&& !VisibilitySettingsKey.IsEmpty()
&& !VisibilityGroupId.IsEmpty()
&& Family != EHyperTwistSkillFamily::None
&& Status != EHyperTwistSkillStatus::None
&& bInstalled
&& bOptionalAssistive
&& bInertWhenDisabled
&& bDurableSettingExposed
&& (!bEffectiveEnabled || bRequestedEnabled);
}
};
USTRUCT(BlueprintType)
struct FHyperTwistSkillVisibilityGroupState
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString GroupId;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString DisplayLabel;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString VisibilitySettingsKey;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
EHyperTwistSkillFamily Family = EHyperTwistSkillFamily::None;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
TArray<FString> SkillIds;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 VisibleSkillCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 HiddenSkillCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bGroupVisibleByDefault = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bDurableVisibilityControlExposed = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString Summary;
bool IsStructurallyValid() const
{
return !GroupId.IsEmpty()
&& !DisplayLabel.IsEmpty()
&& !VisibilitySettingsKey.IsEmpty()
&& Family != EHyperTwistSkillFamily::None
&& SkillIds.Num() > 0
&& VisibleSkillCount >= 0
&& HiddenSkillCount >= 0
&& (VisibleSkillCount + HiddenSkillCount) == SkillIds.Num()
&& bDurableVisibilityControlExposed;
}
};
USTRUCT(BlueprintType)
struct FHyperTwistSkillControlState
{
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")
FHyperTwistSkillMasterSwitchState MasterSwitch;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
TArray<FHyperTwistSkillControlStateEntry> SkillStates;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
TArray<FHyperTwistSkillVisibilityGroupState> VisibilityGroups;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 SkillCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 EffectiveEnabledSkillCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 EffectiveDisabledSkillCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 VisibleSkillCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
int32 HiddenSkillCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bCoreProductWorksWithAllSkillsOff = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bNoPromptBabysittingToDisable = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
bool bAllInstalledSkillsRemainReenableable = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
FString Summary;
bool IsStructurallyValid() const
{
if (RegistryId.IsEmpty()
|| ManifestVersion.IsEmpty()
|| ReferenceUtc.IsEmpty()
|| CommandSurfaceRootId.IsEmpty()
|| ControlProfileId.IsEmpty()
|| !MasterSwitch.IsStructurallyValid()
|| SkillStates.Num() == 0
|| SkillCount != SkillStates.Num()
|| EffectiveDisabledSkillCount != (SkillCount - EffectiveEnabledSkillCount)
|| HiddenSkillCount != (SkillCount - VisibleSkillCount)
|| !bCoreProductWorksWithAllSkillsOff
|| !bNoPromptBabysittingToDisable
|| !bAllInstalledSkillsRemainReenableable)
{
return false;
}
TArray<FString> SeenSkillIds;
int32 ComputedEnabledCount = 0;
int32 ComputedVisibleCount = 0;
bool bComputedNoBabysitting = true;
bool bComputedReenableable = true;
for (const FHyperTwistSkillControlStateEntry& SkillState : SkillStates)
{
if (!SkillState.IsStructurallyValid() || SeenSkillIds.Contains(SkillState.SkillId))
{
return false;
}
SeenSkillIds.Add(SkillState.SkillId);
ComputedEnabledCount += SkillState.bEffectiveEnabled ? 1 : 0;
ComputedVisibleCount += SkillState.bEffectiveVisible ? 1 : 0;
bComputedNoBabysitting &= SkillState.bDurableSettingExposed;
bComputedReenableable &= SkillState.bInstalled && SkillState.bInertWhenDisabled;
}
if (ComputedEnabledCount != EffectiveEnabledSkillCount
|| ComputedVisibleCount != VisibleSkillCount
|| bComputedNoBabysitting != bNoPromptBabysittingToDisable
|| bComputedReenableable != bAllInstalledSkillsRemainReenableable)
{
return false;
}
TArray<FString> SeenGroupIds;
for (const FHyperTwistSkillVisibilityGroupState& Group : VisibilityGroups)
{
if (!Group.IsStructurallyValid() || SeenGroupIds.Contains(Group.GroupId))
{
return false;
}
int32 ComputedGroupVisibleCount = 0;
int32 ComputedGroupHiddenCount = 0;
for (const FString& SkillId : Group.SkillIds)
{
const FHyperTwistSkillControlStateEntry* SkillState = SkillStates.FindByPredicate(
[&SkillId](const FHyperTwistSkillControlStateEntry& Entry)
{
return Entry.SkillId == SkillId;
}
);
if (SkillState == nullptr
|| SkillState->Family != Group.Family
|| SkillState->VisibilityGroupId != Group.GroupId)
{
return false;
}
ComputedGroupVisibleCount += SkillState->bEffectiveVisible ? 1 : 0;
ComputedGroupHiddenCount += SkillState->bEffectiveVisible ? 0 : 1;
}
if (ComputedGroupVisibleCount != Group.VisibleSkillCount
|| ComputedGroupHiddenCount != Group.HiddenSkillCount)
{
return false;
}
SeenGroupIds.Add(Group.GroupId);
}
return true;
}
};

View file

@ -0,0 +1,276 @@
// Copyright HyperTwist, Inc. All Rights Reserved.
#include "Misc/AutomationTest.h"
#include "HyperTwistBootstrap/HyperTwistContractLibrary.h"
#if WITH_AUTOMATION_TESTS
namespace HyperTwistSkillPhaseS1BTestInternal
{
const FHyperTwistSkillControlStateEntry* FindSkillStateById(
const FHyperTwistSkillControlState& ControlState,
const FString& SkillId
)
{
for (const FHyperTwistSkillControlStateEntry& SkillState : ControlState.SkillStates)
{
if (SkillState.SkillId == SkillId)
{
return &SkillState;
}
}
return nullptr;
}
const FHyperTwistSkillVisibilityGroupState* FindVisibilityGroupById(
const FHyperTwistSkillControlState& ControlState,
const FString& GroupId
)
{
for (const FHyperTwistSkillVisibilityGroupState& Group : ControlState.VisibilityGroups)
{
if (Group.GroupId == GroupId)
{
return &Group;
}
}
return nullptr;
}
}
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
FHyperTwistSkillPhaseS1BSettingsVisibilityTest,
"HyperTwist.FirstParty.Skill.PhaseS1B.SettingsVisibility",
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)
bool FHyperTwistSkillPhaseS1BSettingsVisibilityTest::RunTest(
const FString& Parameters
)
{
const FHyperTwistSkillControlState ControlState =
UHyperTwistContractLibrary::MakeSampleSkillControlState();
TestTrue(
TEXT("The Phase S1-B skill-control state must be structurally valid."),
ControlState.IsStructurallyValid()
);
TestTrue(
TEXT("The master switch must be enabled in the default control profile."),
ControlState.MasterSwitch.bEnabled
);
TestTrue(
TEXT("The S1-B control state must expose durable settings."),
ControlState.MasterSwitch.bDurableSettingExposed
);
TestTrue(
TEXT("The S1-B control state must expose immediate menu control."),
ControlState.MasterSwitch.bImmediateMenuControlExposed
);
TestEqual(
TEXT("The sample S1-B control state must preserve all six installed skills."),
ControlState.SkillCount,
6
);
TestEqual(
TEXT("The default S1-B control state must keep one effective enabled skill."),
ControlState.EffectiveEnabledSkillCount,
1
);
TestTrue(
TEXT("The S1-B control state must keep visible family groupings."),
ControlState.VisibilityGroups.Num() > 0
);
const FHyperTwistSkillControlStateEntry* GovernanceState =
HyperTwistSkillPhaseS1BTestInternal::FindSkillStateById(
ControlState,
TEXT("skill/skillization-governance")
);
TestNotNull(
TEXT("The governance skill state must exist."),
GovernanceState
);
if (GovernanceState != nullptr)
{
TestTrue(
TEXT("The governance skill must remain effectively enabled by default."),
GovernanceState->bEffectiveEnabled
);
TestTrue(
TEXT("The governance skill must remain visible by default."),
GovernanceState->bEffectiveVisible
);
TestEqual(
TEXT("The governance skill must use the substrate visibility group."),
GovernanceState->VisibilityGroupId,
TEXT("skill-group/substrate-governance")
);
}
const FHyperTwistSkillVisibilityGroupState* GovernanceGroup =
HyperTwistSkillPhaseS1BTestInternal::FindVisibilityGroupById(
ControlState,
TEXT("skill-group/substrate-governance")
);
TestNotNull(
TEXT("The substrate-governance visibility group must exist."),
GovernanceGroup
);
if (GovernanceGroup != nullptr)
{
TestEqual(
TEXT("The governance visibility group must contain one skill."),
GovernanceGroup->SkillIds.Num(),
1
);
TestEqual(
TEXT("The governance visibility group must expose one visible skill."),
GovernanceGroup->VisibleSkillCount,
1
);
}
return true;
}
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
FHyperTwistSkillPhaseS1BAllSkillsOffCorrectnessTest,
"HyperTwist.FirstParty.Skill.PhaseS1B.AllSkillsOffCorrectness",
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)
bool FHyperTwistSkillPhaseS1BAllSkillsOffCorrectnessTest::RunTest(
const FString& Parameters
)
{
const FHyperTwistSkillControlState ControlState =
UHyperTwistContractLibrary::MakeAllSkillsOffSkillControlState();
TestTrue(
TEXT("The all-skills-off S1-B control state must remain structurally valid."),
ControlState.IsStructurallyValid()
);
TestFalse(
TEXT("The master switch must be disabled in the all-skills-off profile."),
ControlState.MasterSwitch.bEnabled
);
TestTrue(
TEXT("The all-skills-off control state must confirm off-state safety."),
ControlState.MasterSwitch.bAllSkillsOffSafe
);
TestEqual(
TEXT("The all-skills-off control state must expose zero effective enabled skills."),
ControlState.EffectiveEnabledSkillCount,
0
);
TestEqual(
TEXT("The all-skills-off control state must preserve all installed skills as disabled."),
ControlState.EffectiveDisabledSkillCount,
ControlState.SkillCount
);
TestTrue(
TEXT("The core product must still work with all skills off."),
ControlState.bCoreProductWorksWithAllSkillsOff
);
TestTrue(
TEXT("Disabled skills must remain reenableable."),
ControlState.bAllInstalledSkillsRemainReenableable
);
const FHyperTwistSkillControlStateEntry* GovernanceState =
HyperTwistSkillPhaseS1BTestInternal::FindSkillStateById(
ControlState,
TEXT("skill/skillization-governance")
);
TestNotNull(
TEXT("The governance skill state must still exist with all skills off."),
GovernanceState
);
if (GovernanceState != nullptr)
{
TestTrue(
TEXT("The governance skill must stay requested-enabled by default."),
GovernanceState->bRequestedEnabled
);
TestFalse(
TEXT("The governance skill must become effectively disabled when the master switch is off."),
GovernanceState->bEffectiveEnabled
);
TestTrue(
TEXT("The governance skill must remain installed when disabled."),
GovernanceState->bInstalled
);
TestTrue(
TEXT("The governance skill must remain inert when disabled."),
GovernanceState->bInertWhenDisabled
);
}
return true;
}
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
FHyperTwistSkillPhaseS1BSerializationRoundTripTest,
"HyperTwist.FirstParty.Skill.PhaseS1B.SerializationRoundTrip",
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
)
bool FHyperTwistSkillPhaseS1BSerializationRoundTripTest::RunTest(
const FString& Parameters
)
{
const FHyperTwistSkillControlState ControlState =
UHyperTwistContractLibrary::MakeSampleSkillControlState();
TestTrue(
TEXT("The Phase S1-B skill-control state must be structurally valid before serialization."),
ControlState.IsStructurallyValid()
);
const FString Json =
UHyperTwistContractLibrary::SerializeSkillControlStateToJson(ControlState);
TestFalse(TEXT("The serialized S1-B JSON must not be empty."), Json.IsEmpty());
TestTrue(
TEXT("The serialized S1-B JSON must expose the master-switch contract."),
Json.Contains(TEXT("MasterSwitch"))
);
TestTrue(
TEXT("The serialized S1-B JSON must expose visibility groups."),
Json.Contains(TEXT("VisibilityGroups"))
);
FHyperTwistSkillControlState RoundTrippedState;
TestTrue(
TEXT("The S1-B JSON must deserialize cleanly."),
UHyperTwistContractLibrary::DeserializeSkillControlStateFromJson(
Json,
RoundTrippedState
)
);
TestTrue(
TEXT("The round-tripped S1-B control state must remain structurally valid."),
RoundTrippedState.IsStructurallyValid()
);
TestEqual(
TEXT("The round-tripped S1-B control state must preserve skill counts."),
RoundTrippedState.SkillCount,
ControlState.SkillCount
);
TestEqual(
TEXT("The round-tripped S1-B control state must preserve effective enabled counts."),
RoundTrippedState.EffectiveEnabledSkillCount,
ControlState.EffectiveEnabledSkillCount
);
TestEqual(
TEXT("The round-tripped S1-B control state must preserve visibility-group counts."),
RoundTrippedState.VisibilityGroups.Num(),
ControlState.VisibilityGroups.Num()
);
return true;
}
#endif

View file

@ -0,0 +1,109 @@
# HyperTwist Phase S1-B first-party skill settings, menu, and off-state control implementation packet
Created on `2026-05-28`
## Status
- first-party HyperTwist packet
- bounded `Phase S1-B` implementation slice
## Purpose
This packet lands the bounded first-party skill settings, menu, and off-state
control seam under the canonical `Skillization And Command Surface` doctrine.
The landed slice is:
- global skill enable/disable master switch
- per-skill enable/disable state
- visibility grouping
It is not:
- invocation/provenance audit ledger execution
- 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_B_FIRST_PARTY_SKILL_SETTINGS_MENU_AND_OFF_STATE_CONTROL_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
- 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-control seam through:
- canonical skill control-profile, master-switch, per-skill control-state,
visibility-group, and aggregate control-state types in:
- `HyperTwistSkillTypes.h`
- first-party control-state derivation over the landed `S1-A` registry in:
- `UHyperTwistSkillCoreLibrary`
- current bounded control coverage for:
- durable global skill master-switch declaration
- per-skill durable enable/disable settings keys
- per-skill requested/effective enable state
- per-skill requested/effective visibility state
- family-based visibility groups
- immediate menu-control exposure declarations
- all-skills-off correctness
- sample contract helpers in:
- `UHyperTwistContractLibrary::MakeSampleSkillControlState()`
- `UHyperTwistContractLibrary::MakeAllSkillsOffSkillControlState()`
- `UHyperTwistContractLibrary::SerializeSkillControlStateToJson(...)`
- `UHyperTwistContractLibrary::DeserializeSkillControlStateFromJson(...)`
- focused automation coverage in:
- `HyperTwistSkillPhaseS1BSettingsVisibilityContractTest.cpp`
## Why this is still intentionally bounded
This packet lands control-state and visibility-group contracts only.
Still deferred:
- 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.PhaseS1B.SettingsVisibility`
- `HyperTwist.FirstParty.Skill.PhaseS1B.AllSkillsOffCorrectness`
- `HyperTwist.FirstParty.Skill.PhaseS1B.SerializationRoundTrip`
Observed:
- `3` focused `Phase S1-B` automation tests succeeded
## Queue effect
This packet consumes the current `Phase S1-B` implementation slice.
After this landing:
- `S1-B` is landed in current code
- `S1-C` is the next clean skillization move
- do not jump straight from `S1-B` to analyzer wrappers or restrictive command
specs

View file

@ -0,0 +1,101 @@
# HyperTwist Phase S1-B first-party skill settings, menu, and off-state control preparation packet
Created on `2026-05-28`
## Status
- first-party HyperTwist packet
- source-backed `Phase S1-B` preparation/control slice
## Purpose
This packet scopes the second bounded product implementation slice under the
canonical `Skillization And Command Surface` doctrine.
The granted slice is:
- global skill enable/disable master switch
- per-skill enable/disable state
- visibility grouping
It is not:
- invocation/provenance audit ledger execution
- 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`
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
- optional assistive skills remain product-owned adjuncts rather than donor
command truth
## Granted family
The bounded `Phase S1-B` slice may land:
1. first-party skill control profile and master-switch state
2. first-party per-skill requested/effective enable state
3. first-party per-skill requested/effective visibility state
4. family-based visibility grouping
5. explicit all-skills-off correctness
6. sample control-state and JSON round-trip coverage
The packet must stay out of:
- invocation record storage
- service/wrapper execution
- restrictive clean-room command specs
## Proposed implementation shape
Land the narrower first-party boundary through:
- new skill types for:
- control profile
- master switch
- per-skill control-state entries
- visibility groups
- bounded control-state aggregate
- a first-party skill-core derivation function over the landed `S1-A` registry
- sample-contract helpers for:
- default control-state derivation
- all-skills-off derivation
- JSON serialization
- JSON deserialization
- focused automation in:
- `HyperTwistSkillPhaseS1BSettingsVisibilityContractTest.cpp`
## Validation target
Validate with:
- Unreal build for `UnrealHyperTwistEditor Win64 Development`
- focused automation:
- `HyperTwist.FirstParty.Skill.PhaseS1B.SettingsVisibility`
- `HyperTwist.FirstParty.Skill.PhaseS1B.AllSkillsOffCorrectness`
- `HyperTwist.FirstParty.Skill.PhaseS1B.SerializationRoundTrip`
## Queue effect
If this packet lands cleanly:
- `S1-B` is consumed
- `S1-C` becomes the next clean move
- do not jump straight from `S1-B` to analyzer wrappers or restrictive specs

View file

@ -273,6 +273,9 @@ Specifically:
- 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
- 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`
- `S2-A` permissive analyzer wrappers stay deferred until `S1-D` lands
- `S2-B` clean-room command-contract specs stay deferred until `S2-A`

View file

@ -220,6 +220,13 @@ Acceptance gates:
- core product still works with all skills off
- no skill requires prompt babysitting to disable
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`
- analyzer wrappers remain deferred to `S2-A`
#### `S1-C` invocation, provenance, and audit ledger
Outputs:
@ -457,9 +464,10 @@ These are target-shape command families, not claims of implemented reality.
The next correct sequence is:
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
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
Broader memory, browser, workflow, provider, and domain skill widening should
wait until that base exists.

View file

@ -237,4 +237,6 @@ Future skill growth must follow:
- 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
- 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

View file

@ -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` 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. |
| 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. |
| 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. |

View file

@ -101,6 +101,8 @@ The landed bounded first-party `Phase S1-A` packet keeps:
- 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-B` packet keeps durable master and
per-skill off-state control first-party rather than hidden prompt babysitting
## Memory-specific consequence

View file

@ -161,7 +161,11 @@ Canonical discovery surfaces for roadmap interpretation:
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
- the generic first-party `Phase S1-B` skill settings/menu/off-state control
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 source-backed `Phase 6R-R` shared classic-cube recognition multi-face
correction/explanation control pass is now consumed

View file

@ -54,13 +54,15 @@ Includes:
- landed now:
- skill registry/manifest contract
- enable/disable controls
- visibility grouping
- command/service binding declarations
- permission/scope declarations
- provenance/log declarations
- validation harness
- still deferred:
- enable/disable controls
- provenance/invocation ledger execution
- authoring template expansion
### Analyzer and review skills
@ -126,9 +128,10 @@ A coding model working on HyperTwist should still be able to:
The next correct skillization sequence is:
1. settings/menu/off-state controls
2. permissive analyzer wrappers
3. clean-room command-contract specs for restrictive lanes
1. invocation/provenance/audit ledger
2. authoring/examples/validation harness expansion
3. permissive analyzer wrappers
4. clean-room command-contract specs for restrictive lanes
Broader memory, provider, and domain skill widening should wait until that
base exists.