skills/validation-rule-generator/SKILL.md
Generate C++ validation rules from JSON definitions. Use when team updates ValidationRules.json or asks to add/modify validation rules.
npx skillsauth add sipherxyz/universal-ue-skills validation-rule-generatorInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Generate or update C++ validation rule classes from JSON definitions.
Plugins/EditorTools/SipherChecklist/Config/ValidationRules.jsonRead: Plugins/EditorTools/SipherChecklist/Config/ValidationRules.json
If user describes a rule in natural language:
Example user request:
"Add a rule that checks all montages have at least one sound notify"
Generated JSON:
{
"id": "sound_notify_required",
"name": "Sound Notify Required",
"description": "All combat montages should have audio feedback",
"category": "audio",
"severity": "warning",
"target": "montage",
"conditions": {
"montage_pattern": "AMT_*",
"check": "has_notify",
"notify_class_contains": ["Sound", "Audio", "PlaySound"],
"minimum_count": 1
},
"error_template": "{count}/{total} montages missing sound notify: {list}"
}
For each rule in JSON, generate a UValidationRule_{RuleId} class.
Output files:
Public/ValidationRules/ValidationRule_{Category}.hPrivate/ValidationRules/ValidationRule_{Category}.cppC++ Template:
// Header
UCLASS(DisplayName = "{name}")
class SIPHERCHECKLIST_API UValidationRule_{PascalId} : public USipherChecklistValidationRule
{
GENERATED_BODY()
public:
// Configurable thresholds from JSON
UPROPERTY(EditDefaultsOnly, Category = "Thresholds")
float {threshold_name} = {default_value};
virtual FSipherAutoValidationResult Validate_Implementation(const FString& EnemyContentPath) const override;
virtual FString GetRuleName_Implementation() const override { return TEXT("{name}"); }
};
// Implementation
FSipherAutoValidationResult UValidationRule_{PascalId}::Validate_Implementation(const FString& EnemyContentPath) const
{
TArray<UAnimMontage*> Montages;
SipherCombatMontageValidation::GetCombatMontagesForEnemy(EnemyContentPath, Montages);
if (Montages.Num() == 0)
{
return FSipherAutoValidationResult::Pass();
}
TArray<FString> FailedMontages;
for (const UAnimMontage* Montage : Montages)
{
// Check condition based on JSON "check" type
bool bPassed = false;
// Generated check logic based on conditions...
for (const FAnimNotifyEvent& NotifyEvent : Montage->Notifies)
{
FString ClassName;
if (NotifyEvent.NotifyStateClass)
{
ClassName = NotifyEvent.NotifyStateClass->GetName();
}
else if (NotifyEvent.Notify)
{
ClassName = NotifyEvent.Notify->GetClass()->GetName();
}
// Check against notify_class_contains
for (const FString& Pattern : {notify_patterns})
{
if (ClassName.Contains(Pattern))
{
bPassed = true;
break;
}
}
if (bPassed) break;
}
if (!bPassed)
{
FailedMontages.Add(Montage->GetName());
}
}
if (FailedMontages.Num() > 0)
{
// Format error using error_template
FString ErrorMsg = FString::Printf(TEXT("{error_template_formatted}"),
FailedMontages.Num(), Montages.Num(),
*FString::Join(FailedMontages, TEXT(", ")));
return FSipherAutoValidationResult::Fail(ErrorMsg);
}
return FSipherAutoValidationResult::Pass();
}
After generating new rules, update ValidateEnemy() in SSipherCombatAuditPanel.cpp to include the new rule.
Run /dev-workflow:ue-cpp-build to compile and verify no errors.
| JSON Field | C++ Element |
|------------|-------------|
| id | Class suffix: UValidationRule_{PascalCase(id)} |
| name | GetRuleName_Implementation() return value |
| description | Class UCLASS DisplayName |
| severity | Affects FSipherAutoValidationResult::Fail() vs ::Warning() |
| conditions.notify_class_contains | String array for Contains() checks |
| conditions.minimum_count | Threshold for pass/fail |
| conditions.duration_* | UPROPERTY threshold values |
| error_template | FString::Printf format string |
User: "Add a rule that warns if attack montages don't have a hit VFX notify"
Steps:
{
"id": "hit_vfx_required",
"name": "Hit VFX Required",
"description": "Attack montages should spawn VFX on hit for visual feedback",
"category": "vfx",
"severity": "warning",
"target": "montage",
"conditions": {
"prerequisite": "has_hitbox_notify",
"check": "has_notify",
"notify_class_contains": ["VFX", "Niagara", "Effect", "Particle"],
"minimum_count": 1
},
"error_template": "{count} attack montages without hit VFX: {list}"
}
Generate C++ class UValidationRule_HitVfxRequired
Add to ValidationRule_CombatMontage.h/cpp
Update SSipherCombatAuditPanel::ValidateEnemy() to run the new rule
Compile
The JSON is the source of truth. When regenerating:
// AUTO-GENERATED - DO NOT EDIT markers for generated sectionsdevelopment
This skill should be used when implementing features in isolation using git worktrees. Triggers on "create worktree", "isolated workspace", "parallel development", or when starting implementation that should not affect main workspace.
testing
Manage VFX team issues on GitHub Projects - timeline scheduling, status updates, member commit checks, bulk assign. Use when managing VFX team project board, adding issues to timeline, checking member progress, or bulk-updating issue fields.
development
Check codebase for Microsoft Xbox XR (Xbox Requirements) compliance issues. Scans for account picker, cloud saves, achievements, Quick Resume, and Xbox certification requirements. Use before console submission or when preparing for Microsoft certification. Triggers on "XR", "Xbox certification", "Microsoft compliance", "Xbox cert", "Xbox requirements", "GDK compliance".
development
Validate weapon DataAssets including damage curves, combo references, VFX links, sound cues, and stat configurations. Use when creating weapons, validating weapon data, or debugging weapon issues. Triggers on "weapon validation", "weapon data", "validate weapon", "weapon check", "damage curves", "weapon asset".