skills/n2c-validator/SKILL.md
Validate generated C++ code and auto-fix common issues. Sub-agent of n2c-orchestrator.
npx skillsauth add sipherxyz/universal-ue-skills n2c-validatorInstall 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.
This skill reads project-specific values from skills.config.json at the repository root.
If not found, auto-detect using ue-detect-engine skill or prompt the user.
Validates generated C++ code against project context and auto-fixes known issues.
{
"header": "// Generated .h content",
"implementation": "// Generated .cpp content",
"context": {
"includeMap": { ... },
"baseClassContext": { ... },
"apiPatterns": { ... },
"potentialConflicts": [ ... ]
},
"outputPaths": {
"header": "Source/S2/Public/Core/GAS/GA_Jump.h",
"implementation": "Source/S2/Private/Core/GAS/GA_Jump.cpp"
}
}
Success (valid):
{
"valid": true,
"header": "// Validated .h content",
"implementation": "// Validated .cpp content",
"appliedFixes": [],
"warnings": [],
"requiresManualReview": false
}
Success (fixed):
{
"valid": true,
"header": "// Fixed .h content",
"implementation": "// Fixed .cpp content",
"appliedFixes": [
{"line": 15, "issue": "Wrong include path", "fix": "Changed to correct path"},
{"line": 42, "issue": "OnMoveFinished is protected", "fix": "Changed to OnMoveTaskFinished"}
],
"warnings": [
{"line": 78, "issue": "Unknown function", "suggestion": "Verify this function exists"}
],
"requiresManualReview": false
}
Failure (unfixable):
{
"valid": false,
"header": "// Partially fixed .h content",
"implementation": "// Partially fixed .cpp content",
"appliedFixes": [ ... ],
"unresolvedIssues": [
{"line": 95, "issue": "Cannot determine correct signature", "context": "..."}
],
"requiresManualReview": true
}
Header Structure:
1. Copyright/pragma once
2. CoreMinimal.h
3. Base class include
4. Other includes
5. .generated.h (MUST BE LAST)
6. Forward declarations
7. Class definition
Implementation Structure:
1. Own header (MUST BE FIRST)
2. Other includes
3. Implementations (no code before includes)
Detection:
# Check .generated.h is last include in header
grep -n "#include" {header} | tail -1 | grep ".generated.h"
# Check own header is first include in cpp
grep -n "#include" {implementation} | head -1 | grep "{ClassName}.h"
# Check no code before includes in cpp
first_include_line=$(grep -n "#include" {implementation} | head -1 | cut -d: -f1)
first_code_line=$(grep -n "^\w" {implementation} | grep -v "^//" | head -1 | cut -d: -f1)
if [ $first_code_line -lt $first_include_line ]; then
# ERROR: Code before includes
fi
Fix:
For each #include "..." in header and implementation:
# Extract include path
INCLUDE_PATH=$(echo "$line" | grep -oP '#include\s+"\K[^"]+')
# Check if file exists
FOUND=false
for BASE in "Source/S2/Public" "Plugins/Sipher*/Source/*/Public" "Plugins/Frameworks/*/Source/*/Public"; do
if [ -f "$BASE/$INCLUDE_PATH" ]; then
FOUND=true
break
fi
done
if [ "$FOUND" = false ]; then
# ERROR: Include not found
fi
Fix:
grepFor each virtual method in header:
# Extract method name and signature
method_match = re.search(r'virtual\s+(\w+)\s+(\w+)\s*\(([^)]*)\)', line)
method_name = method_match.group(2)
generated_signature = method_match.group(0)
# Find in base class context
for base_method in base_class_context.virtualMethods:
if base_method.name == method_name:
expected_signature = base_method.signature
if generated_signature != expected_signature:
# ERROR: Signature mismatch
# Fix: Replace with expected signature
Fix:
| Pattern | Detection Regex | Fix |
|---------|----------------|-----|
| OnMoveFinished.AddDynamic | OnMoveFinished\s*\.\s*AddDynamic | → OnMoveTaskFinished.AddUObject |
| UGameplayTask_WaitDelay | UGameplayTask_WaitDelay | → UAbilityTask_WaitDelay |
| K2_SetActorLocation | K2_SetActorLocation | → SetActorLocation |
| K2_GetActorLocation | K2_GetActorLocation | → GetActorLocation |
| K2_DestroyActor | K2_DestroyActor | → Destroy |
| TSoftObjectPtr without Load | TSoftObjectPtr<\w+>\([^)]+\)[^.]*; | Add .LoadSynchronous() |
Detection and Fix:
patterns = [
{
"pattern": r"OnMoveFinished\s*\.\s*AddDynamic",
"replacement": "OnMoveTaskFinished.AddUObject",
"issue": "OnMoveFinished is protected in UE5.7"
},
{
"pattern": r"UGameplayTask_WaitDelay",
"replacement": "UAbilityTask_WaitDelay",
"issue": "Wrong WaitDelay class for abilities"
},
{
"pattern": r"K2_(\w+)",
"replacement": lambda m: m.group(1), # Remove K2_ prefix
"issue": "K2_ functions are Blueprint wrappers"
}
]
for p in patterns:
if re.search(p["pattern"], code):
code = re.sub(p["pattern"], p["replacement"], code)
applied_fixes.append({"issue": p["issue"], "fix": "Applied pattern replacement"})
Check if any local variables shadow base class members:
# Extract local variable declarations from implementation
local_vars = re.findall(r'(\w+)\s+(\w+)\s*[;=]', implementation)
for var_type, var_name in local_vars:
if var_name in context.potentialConflicts:
# ERROR: Variable shadows base class member
# Fix: Rename to Local{VarName} or {VarName}Local
Fix:
# Rename pattern: AnimationData -> LocalAnimData
new_name = f"Local{var_name}"
implementation = implementation.replace(var_name, new_name)
If orchestrator requests compile verification:
# Single-module build
"{EnginePath}/Engine/Build/BatchFiles/Build.bat" S2Editor Win64 Development \
-Project="{project.root}/{project.uproject}" \
-Module=S2 \
-WaitMutex \
2>&1 | tee build_output.txt
# Check for errors
if grep -q "error C" build_output.txt; then
# Extract error details
ERRORS=$(grep "error C" build_output.txt)
# Return compile errors for manual review
fi
MAX_ATTEMPTS = 3
for attempt in range(MAX_ATTEMPTS):
issues = run_all_checks(header, implementation, context)
if not issues:
return {
"valid": True,
"header": header,
"implementation": implementation,
"appliedFixes": all_fixes,
"requiresManualReview": False
}
fixable = [i for i in issues if i.fixable]
unfixable = [i for i in issues if not i.fixable]
if not fixable:
# No more auto-fixes possible
break
# Apply fixes
for issue in fixable:
header, implementation = apply_fix(header, implementation, issue)
all_fixes.append(issue.to_dict())
# After max attempts
return {
"valid": len(unfixable) == 0,
"header": header,
"implementation": implementation,
"appliedFixes": all_fixes,
"unresolvedIssues": [i.to_dict() for i in unfixable],
"requiresManualReview": len(unfixable) > 0
}
After validation passes (or with warnings):
def write_files(header, implementation, output_paths):
header_path = output_paths["header"]
impl_path = output_paths["implementation"]
# Ensure directories exist
os.makedirs(os.path.dirname(header_path), exist_ok=True)
os.makedirs(os.path.dirname(impl_path), exist_ok=True)
# Backup existing files
if os.path.exists(header_path):
shutil.copy(header_path, f"{header_path}.bak")
if os.path.exists(impl_path):
shutil.copy(impl_path, f"{impl_path}.bak")
# Write new files
with open(header_path, 'w') as f:
f.write(header)
with open(impl_path, 'w') as f:
f.write(implementation)
return {
"headerPath": header_path,
"implementationPath": impl_path,
"backedUp": True
}
If write fails or subsequent build fails:
def rollback(output_paths):
header_path = output_paths["header"]
impl_path = output_paths["implementation"]
# Restore from backup
if os.path.exists(f"{header_path}.bak"):
shutil.move(f"{header_path}.bak", header_path)
else:
os.remove(header_path) # New file, just delete
if os.path.exists(f"{impl_path}.bak"):
shutil.move(f"{impl_path}.bak", impl_path)
else:
os.remove(impl_path)
return {"rolledBack": True}
development
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.
tools
Generate C++ validation rules from JSON definitions. Use when team updates ValidationRules.json or asks to add/modify validation rules.
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".