Godot Refactor Orchestrator
This orchestrator runs 5 code quality mini-skills in sequence. For individual operations, invoke mini-skills directly.
Core Principle: Scene-First, Signal-Based, Component Composition
Iron Law: NO functional or visual changes during refactoring. Period.
This skill automatically refactors Godot projects to cleaner, more modular architecture while preserving exact behavior. Every operation creates a git commit. Rollback is always available.
UPON INVOCATION - START HERE
When this skill is invoked, IMMEDIATELY execute the following sequence:
1. Verify Godot Project (5 seconds)
# Check if this is a Godot project ls project.godot 2>/dev/null && echo "✓ Godot project detected" || echo "✗ Not a Godot project"
If NOT a Godot project:
- •Inform user this skill only works on Godot projects
- •Ask if they want to navigate to the correct directory
- •STOP here
If IS a Godot project:
- •Proceed to step 2
2. Begin Phase 1: Analysis & Baseline (AUTOMATIC)
Do NOT ask "What would you like me to do?" - Start analyzing immediately.
Execute these commands in parallel:
# Detect code-created objects
grep -rn "\.new()" --include="*.gd" . | grep -E "(Node|Timer|Area|Sprite|Control|Collision)" | wc -l
# Detect monolithic scripts
find . -name "*.gd" -exec wc -l {} + | awk '$1 > 150' | wc -l
# Detect tight coupling
grep -rn "get_node\|has_method" --include="*.gd" . | wc -l
# Detect inline data
grep -rn "^[[:space:]]*const.*\[" --include="*.gd" . | wc -l
3. Present Findings (30 seconds)
Show the user:
=== Godot Refactoring Analysis === Project: [project name from project.godot] Anti-patterns detected: - Code-created objects: X - Monolithic scripts: X - Tight coupling: X - Inline data: X - Conflicting operations: (will be detected after refactoring) Total: X anti-patterns found Refactoring includes: ✓ Automatic testing after each operation ✓ Auto-rollback on test failure ✓ Git commit per operation ✓ Push to remote on demand Would you like me to: 1. Proceed with automatic refactoring (recommended) 2. Show detailed breakdown first 3. Cancel
4. Wait for User Choice
- •If 1 (Proceed): Start Phase 2 immediately
- •If 2 (Details): Show detailed file-by-file breakdown, then offer to proceed
- •If 3 (Cancel): Exit skill
CRITICAL: Do NOT stop after loading the skill. Do NOT ask "What would you like me to do?" Start with step 1 immediately.
When to Use This Skill
Use this skill when you detect ANY of these symptoms:
Code-Created Objects:
- •
.new()calls in_ready(),_process(), or other lifecycle methods - •
add_child()with programmatically created nodes - •Timers, Areas, Sprites created in code
Monolithic Scripts:
- •Scripts >150 lines
- •Multiple unrelated responsibilities in one file
- •God objects that do everything
Tight Coupling:
- •
get_node()chains to access other nodes - •
has_method()checks before calling - •Direct property access across nodes
- •Parent-child dependencies for behavior
Inline Data:
- •
constarrays with game data - •Hardcoded configuration in scripts
- •Data that should be resources
Deep Inheritance:
- •More than 2 levels of script inheritance
- •Inheritance used for code reuse instead of composition
Decision Flowchart
User mentions Godot project
↓
Does it have ANY of the above symptoms?
↓ YES ↓ NO
Use this skill Regular development
↓
Run Phase 1: Analysis
↓
Anti-patterns found?
↓ YES ↓ NO
Run Phases 2-4 Document clean state
The Four Phases
Phase 1: Analysis & Baseline (Automatic)
Purpose: Detect all anti-patterns and create safety baseline.
Steps:
- •Scan Project Files
# Find all Godot script files find . -name "*.gd" -type f # Find all scene files find . -name "*.tscn" -type f
- •Detect Anti-Patterns
Use detection patterns from anti-patterns-detection.md:
# Code-created objects
grep -rn "\.new()" --include="*.gd" .
# Monolithic scripts (>150 lines)
find . -name "*.gd" -exec wc -l {} + | awk '$1 > 150 {print $2 " (" $1 " lines)"}'
# Tight coupling
grep -rn "get_node\|get_parent\|has_method" --include="*.gd" .
# Inline data
grep -rn "^[[:space:]]*const.*\[" --include="*.gd" .
- •Create Git Baseline
# Save current branch current_branch=$(git branch --show-current) # Create baseline tag git tag baseline-$(date +%Y%m%d-%H%M%S) # Initial commit if there are uncommitted changes git add . git commit -m "Baseline: Pre-refactoring state (on $current_branch)"
- •Generate Refactoring Manifest
Create a priority-ordered list:
| Priority | Anti-Pattern | File | Lines | Operation |
|---|---|---|---|---|
| 1 | Inline data | enemy_data.gd | 45-78 | Extract to .tres |
| 2 | Code-created Timer | laser_beam.gd | 38-45 | Extract to .tscn |
| 3 | Tight coupling | base_station.gd | 92 | Signal decoupling |
| 4 | Monolithic script | player_movement.gd | 287 lines | Split script |
Phase 1 Output:
- •✓ Baseline git commit/tag created
- •✓ Anti-patterns detected and prioritized
- •✓ Manifest table generated
- •✓ Ready for automatic refactoring
Phase 2: Automatic Refactoring (Five Operations)
Process anti-patterns in priority order: Data → Scenes → Signals → Scripts → Conflicts
CRITICAL - After Each Operation:
- •Git commit the changes
- •Run automatic validation test
- •If test fails: Auto-revert and report error
- •If test passes: Continue automatically to next operation
- •No user prompt unless test fails or user confirmation needed
Automatic Testing Procedure:
# Quick validation test (runs after each git commit)
echo "Running validation test..."
godot --headless --quit-after 5 project.godot 2>&1 | tee test_output.log
# Check for errors
if grep -q "ERROR\|SCRIPT ERROR\|Parse Error" test_output.log; then
echo "⚠️ Tests failed - reverting operation"
git reset --hard HEAD~1
echo "❌ Operation reverted. Error details:"
grep "ERROR\|SCRIPT ERROR\|Parse Error" test_output.log
# STOP and report to user
else
echo "✓ Tests passed - continuing"
rm test_output.log
# CONTINUE to next operation automatically
fi
Note: If test fails, STOP workflow and report to user. Otherwise, continue automatically through all operations.
Operation A: Extract Code-Created Objects to Modular Components
Target: Any .new() calls that create nodes
Enhanced Process:
- •
Detect and Analyze
- •Find
.new()calls for node types - •Extract 30 lines of context (properties, methods, signals)
- •Analyze variable names, properties, methods
- •Consult
node-selection-guide.mddecision trees - •Calculate confidence score for node type
- •Select optimal node from
godot-node-reference.md
- •Find
- •
Check Component Library
- •Does
components/{category}/exist? (e.g.,components/timers/) - •If YES: Reuse base component, skip to Step 4
- •If NO: Generate full component structure (Steps 2-3)
- •Does
- •
Generate Component (First Time Only)
- •Create
{type}_config.gd(Resource class with @export properties) - •Create
configurable_{type}.gd(Script that extends node, applies config) - •Create
configurable_{type}.tscn(Base scene with script) - •Creates modular, reusable foundation
- •Create
- •
Generate Preset Resource
- •Extract properties from analyzed code
- •Create
presets/{preset_name}.tres(specific configuration) - •Each detected instance gets unique preset
- •Presets reference the base component
- •
Update Parent Scene
- •Add ext_resource entries for base scene and preset
- •Instance base component with preset resource
- •Same scene reused, different presets = ZERO duplication
- •
Update Parent Script
- •Add @onready reference to component instance
- •Keep signal connections
- •Remove .new(), add_child(), static property assignments
- •Configuration now comes from preset resource
- •
Git Commit & Validate
- •Commit all component files and parent changes
- •Run validation test
- •Ensure behavior unchanged
Example Transformation:
Before (Code-Created):
func _ready():
_damage_timer = Timer.new()
_damage_timer.wait_time = 0.5
_damage_timer.one_shot = false
add_child(_damage_timer)
_damage_timer.timeout.connect(_on_damage)
_cooldown_timer = Timer.new()
_cooldown_timer.wait_time = 2.0
_cooldown_timer.one_shot = true
add_child(_cooldown_timer)
_cooldown_timer.timeout.connect(_on_cooldown)
After (First Timer - Full Component Created):
Files created:
✓ components/timers/timer_config.gd (resource class)
✓ components/timers/configurable_timer.gd (reusable script)
✓ components/timers/configurable_timer.tscn (reusable base scene)
✓ components/timers/presets/damage_timer.tres (configuration preset)
parent.gd:
@onready var _damage_timer: ConfigurableTimer = $DamageTimer
func _ready():
_damage_timer.timeout.connect(_on_damage)
After (Second Timer - Reuses Base):
Files created:
✓ components/timers/presets/cooldown_timer.tres (NEW preset only!)
parent.gd:
@onready var _damage_timer: ConfigurableTimer = $DamageTimer
@onready var _cooldown_timer: ConfigurableTimer = $CooldownTimer
func _ready():
_damage_timer.timeout.connect(_on_damage)
_cooldown_timer.timeout.connect(_on_cooldown)
Key Benefits:
- •✅ Intelligent node selection (no arbitrary choices)
- •✅ Modular components (reusable across project)
- •✅ Zero duplication (same base, different presets)
- •✅ Inspector-configurable (edit presets in editor)
- •✅ Automatic library building (grows organically)
- •✅ Signal connections preserved
- •✅ Behavior unchanged (Iron Law maintained)
Success Criteria:
- •Component structure created (if first of type)
- •Preset resource created with extracted values
- •Parent scene instances component with preset
- •Parent script has @onready reference
- •Signal connections work
- •Old code removed
- •Behavior unchanged
Operation B: Split Monolithic Scripts
Target: Scripts >150 lines with multiple responsibilities
Detection:
find . -name "*.gd" -exec wc -l {} + | awk '$1 > 150'
For each detected script:
- •
Analyze script structure
- •Identify logical sections (look for comment headers, function groups)
- •Find responsibilities (input, physics, abilities, UI, etc.)
- •Determine dependencies between sections
- •
Plan split
- •Main script keeps core responsibility
- •Extract secondary responsibilities to components
- •Define signal interface between components
- •
Create component scripts
Example: Split
player_movement.gd(287 lines)Extract to
player_abilities.gd:gdscriptextends Node class_name PlayerAbilities signal ability_used(ability_name: String) signal cooldown_started(duration: float) # Ability-related functions moved here
- •
Update main script
gdscript@onready var abilities: PlayerAbilities = $Abilities func _ready(): abilities.ability_used.connect(_on_ability_used) - •
Implement signal communication
- •Replace direct function calls with signals
- •Connect signals in _ready()
- •Remove tight coupling
- •
Git commit
bashgit add player_movement.gd player_abilities.gd git commit -m "Refactor: Split abilities from player_movement.gd"
- •
Run automatic test (see Phase 2 header for test procedure)
Success criteria:
- •Main script <150 lines
- •Component scripts focused (80-120 lines optimal)
- •Signal-based communication
- •No direct dependencies
- •Behavior unchanged
Operation C: Implement Signal-Based Decoupling
Target: Direct coupling via get_node(), has_method(), direct calls
Detection:
grep -rn "get_node\|has_method" --include="*.gd" .
For each detected coupling:
- •
Identify the relationship
- •What is being accessed?
- •What information is being exchanged?
- •Is this event-based or state query?
- •
Create/use Events autoload
If not exists, create
events.gd:gdscriptextends Node # Global event bus signal player_entered_safe_zone(zone: Node2D) signal enemy_spawned(enemy: Node2D) signal score_changed(new_score: int)
Add to project settings: Project → Project Settings → Autoload
- •
Replace direct coupling with signals
Before:
gdscriptfunc _on_body_entered(body): if body.has_method("set_beam_enabled"): body.set_beam_enabled(false)After (emitter):
gdscriptfunc _on_body_entered(body): if body.is_in_group("player"): Events.player_entered_safe_zone.emit(self)After (receiver):
gdscriptfunc _ready(): Events.player_entered_safe_zone.connect(_on_safe_zone) func _on_safe_zone(zone): set_beam_enabled(false) - •
Remove coupling code
- •Delete get_node() calls
- •Delete has_method() checks
- •Delete direct property access
- •
Git commit
bashgit add events.gd base_station.gd player_movement.gd git commit -m "Refactor: Decouple base_station from player via signals"
- •
Run automatic test (see Phase 2 header for test procedure)
Success criteria:
- •No get_node() for behavior access
- •No has_method() checks
- •Events.gd exists and is used
- •Signal connections established
- •Behavior unchanged
Operation D: Extract Data to .tres Resources
Target: const declarations with game data
Detection:
grep -rn "^[[:space:]]*const.*\[" --include="*.gd" .
For each detected data constant:
- •
Analyze data structure
gdscriptconst ENEMY_TYPES = [ {"type": "basic", "health": 100, "speed": 200}, {"type": "fast", "health": 50, "speed": 400} ] - •
Create Resource class
Create
enemy_type_data.gd:gdscriptextends Resource class_name EnemyTypeData @export var type_name: String @export var health: int @export var speed: float
- •
Generate .tres files
Create
enemy_types/basic.tres:ini[gd_resource type="EnemyTypeData" load_steps=2 format=3] [ext_resource type="Script" path="res://enemy_type_data.gd" id="1"] [resource] script = ExtResource("1") type_name = "basic" health = 100 speed = 200.0 - •
Update script to use resources
gdscript@export var enemy_types: Array[EnemyTypeData] # In scene, assign resources via inspector
- •
Remove const declaration
- •
Git commit
bashgit add enemy_type_data.gd enemy_types/*.tres enemy_spawner.gd git commit -m "Refactor: Extract enemy data to .tres resources"
- •
Run automatic test (see Phase 2 header for test procedure)
Success criteria:
- •Resource class created
- •.tres files generated with correct data
- •Script updated to use resources
- •Const declaration removed
- •Behavior unchanged
Operation E: Clean Conflicting/Ineffective Operations
Target: Code that runs without errors but has no effect or conflicts with other code
IMPORTANT: This operation runs after Operations A-D are complete, as refactoring may introduce or remove conflicts.
Detection:
# Run comprehensive conflict detection
bash << 'EOF'
echo "=== Detecting Conflicting Operations ==="
# Self-assignments
echo "Self-assignments:"
grep -rn "position\s*=\s*position\|scale\s*=\s*scale\|rotation\s*=\s*rotation" --include="*.gd" .
# Redundant defaults
echo "Redundant defaults:"
grep -rn "modulate\s*=\s*Color\.WHITE\|scale\s*=\s*Vector2\.ONE" --include="*.gd" .
# Duplicate property assignments (common properties)
echo "Checking for duplicate assignments..."
for prop in "scale" "position" "rotation" "modulate" "visible"; do
grep -rn "\.$prop\s*=" --include="*.gd" . | \
awk -F: -v prop="$prop" '{
file=$1; line=$2;
if (file==prev_file && line-prev_line<20) {
print file":"prev_line" and "line" - Duplicate "prop
}
prev_file=file; prev_line=line
}'
done
# Conflicting tweens
echo "Conflicting tweens:"
grep -n "tween_property" --include="*.gd" -r . | \
awk -F: '{
file=$1; line=$2;
if (match($0, /tween_property.*"([^"]+)"/, arr)) {
prop=arr[1];
key=file":"prop;
if (key in seen && line-seen[key]<15) {
print file":"seen[key]" and "line" - Conflicting tweens on "prop
}
seen[key]=line
}
}'
# Code after queue_free
echo "Code after queue_free:"
grep -A2 "queue_free()" --include="*.gd" . | grep -v "^--$"
EOF
For each detected conflict:
- •
Auto-fix (no user input):
- •Self-assignments: Remove entirely
- •Code after
queue_free(): Move code before queue_free - •Obvious redundant defaults: Remove
- •
User confirmation (ask user):
- •Duplicate assignments: Which value to keep?
- •Conflicting tweens: Which to keep or chain?
- •Multiple process calls: Final intended state?
- •
Example fixes:
Self-assignment:
gdscript# Before position = position # After (remove line)
Duplicate assignment:
gdscript# Before sprite.scale = Vector2(2, 2) # Line 45 sprite.scale = Vector2(1, 1) # Line 52 # After (keep last) sprite.scale = Vector2(1, 1) # Line 52
Conflicting tweens (user chose "chain"):
gdscript# Before var tween1 = create_tween() tween1.tween_property(self, "scale", Vector2(2,2), 1.0) var tween2 = create_tween() tween2.tween_property(self, "scale", Vector2(0.5,0.5), 1.0) # After var tween = create_tween() tween.tween_property(self, "scale", Vector2(2,2), 1.0) tween.tween_property(self, "scale", Vector2(0.5,0.5), 1.0)
- •
Git commit
bashgit add <modified files> git commit -m "Refactor: Clean conflicting/ineffective operations - Removed self-assignments - Fixed duplicate property assignments - Resolved conflicting tweens - Cleaned up redundant operations No functional changes - code cleanup only"
- •
Run automatic test (see Phase 2 header for test procedure)
Success criteria:
- •No self-assignments remain
- •No obvious duplicate assignments
- •Conflicting tweens resolved
- •Code after queue_free() moved
- •Behavior unchanged
Note: See conflicting-operations-detection.md for comprehensive detection patterns and refactoring-operations.md Operation E for detailed procedures.
Phase 3: Git Commits (Automatic)
After each operation, commit with clear message:
# Template git add <files> git commit -m "Refactor: <Operation> in <file> - <specific change>" # Examples git commit -m "Refactor: Extract Timer to scene in laser_beam.gd" git commit -m "Refactor: Split abilities from player_movement.gd (287→142 lines)" git commit -m "Refactor: Decouple base_station from player via signals" git commit -m "Refactor: Extract enemy data to .tres resources" git commit -m "Refactor: Clean conflicting/ineffective operations"
After all operations:
git tag refactor-complete-$(date +%Y%m%d)
Commit history should show:
- •Baseline commit
- •One commit per refactoring operation (A, B, C, D, E)
- •Clear, descriptive messages
- •Easy to review
- •Easy to rollback individual changes
Push on Demand:
After all operations complete, ask user:
=== Refactoring Complete === All operations completed successfully! 5 operations performed, X commits created on current branch. Would you like to push to remote? 1. Yes, push now 2. No, I'll push manually later 3. Show me the commit log first Choice [1-3]:
If user chooses 1 (push now):
# Push to current branch's remote git push origin $(git branch --show-current)
If user chooses 3 (show log first):
git log --oneline --graph baseline-*..HEAD # Then ask again: Push now? [y/n]
If user says "push" or "push et" at ANY time during the workflow:
# Immediately push current branch git push origin $(git branch --show-current) echo "✓ Pushed to remote"
Phase 4: Final Verification (Minimal, Automatic)
Purpose: Ensure no functional or visual regressions.
Steps:
- •
Open project in Godot
bashgodot --editor path/to/project.godot
- •
Check for errors
- •No red errors in console
- •No yellow warnings about missing nodes
- •All scenes load successfully
- •
Visual verification
- •Run main scene
- •Quick visual check (30 seconds)
- •Compare against expected behavior
- •
Play test checklist (from
verification-checklist.md):- • Player movement works
- • Abilities trigger correctly
- • Enemies spawn and behave normally
- • UI updates properly
- • No crashes or errors
- •
Performance baseline (optional):
bash# Compare FPS before/after # Should be identical ±2 FPS
If verification fails:
# Rollback procedure git reset --hard baseline-YYYYMMDD-HHMMSS git tag refactor-failed-$(date +%Y%m%d-%H%M%S) # Report what broke # Debug with systematic-debugging skill
If verification succeeds:
Report summary:
✓ Refactoring complete ✓ 8 operations performed ✓ 287 lines reduced to 142 across 3 files ✓ 4 .tscn scenes created ✓ 2 .tres resources created ✓ Signal-based architecture established ✓ No functional changes ✓ All tests passing
Supporting Files
This skill uses modular reference files:
- •anti-patterns-detection.md: All grep/find patterns for detection
- •refactoring-operations.md: Detailed step-by-step procedures
- •godot-best-practices.md: Clean patterns reference
- •tscn-generation-guide.md: .tscn file format templates
- •verification-checklist.md: Testing procedures
Read these files for detailed implementation guidance.
Red Flags - STOP
These thoughts mean you're rationalizing away discipline:
| Rationalization | Reality | Fix |
|---|---|---|
| "While I'm here, let me add this feature" | Feature creep breaks Iron Law | Refactor only, no features |
| "This behavior is wrong, I'll fix it now" | Bug fixes are separate work | Note bug, refactor only |
| "I don't need to test this change" | Untested = broken | Always verify |
| "I'll commit after a few more changes" | Loses granularity | Commit per operation |
| "This .tscn format looks close enough" | Invalid scenes crash | Use exact format |
| "The user won't notice this visual change" | Iron Law has no exceptions | Revert and fix |
| "Signals are overkill for this" | Coupling creeps back | Use signals anyway |
| "I'll manually test later" | Later never comes | Test now |
| "This script is fine at 160 lines" | Arbitrary exceptions grow | Split at 150 |
| "I understand the pattern, no need to read" | Assumptions create bugs | Read the guide |
Quick Reference: Anti-Pattern → Clean Pattern
| Anti-Pattern | Clean Pattern | Tool |
|---|---|---|
Timer.new() in code | .tscn scene with Timer | Operation A |
get_node("../Player") | Signal via Events | Operation C |
if has_method("take_damage"): | Signal listener | Operation C |
| 287-line script | Split to 3 focused scripts | Operation B |
const WEAPONS = [...] | .tres resources | Operation D |
add_child(sprite) | Scene composition | Operation A |
| Direct method calls | Signal emit/connect | Operation C |
| Deep inheritance | Component composition | Operations A+B |
File Operation Flow
1. Data Extraction .gd with const → Resource class .gd + .tres files 2. Scene Extraction .gd with .new() → .gd with @onready + new .tscn 3. Signal Decoupling .gd with get_node() → events.gd + updated .gd files 4. Script Splitting Large .gd → Multiple focused .gd files with signals
Godot Naming Conventions
Scenes (.tscn):
- •PascalCase for node names:
DamageTimer,AbilitySystem - •snake_case for file names:
damage_timer.tscn,ability_system.tscn
Scripts (.gd):
- •snake_case for files:
player_movement.gd,enemy_spawner.gd - •PascalCase for class_name:
class_name PlayerMovement
Resources (.tres):
- •snake_case for files:
enemy_types/basic.tres - •PascalCase for Resource class:
class_name EnemyTypeData
Signals:
- •snake_case:
signal ability_used,signal player_entered_safe_zone - •Past tense for events:
signal enemy_spawned(notenemy_spawn)
@onready variables:
- •snake_case with type hint:
@onready var _damage_timer: Timer = $DamageTimer - •Private with underscore:
_damage_timer,_ability_system
Common Mistakes
| Mistake | Consequence | Fix |
|---|---|---|
| Invalid .tscn format | Scene won't load in Godot | Use exact template format |
| Missing node type in .tscn | Godot can't parse scene | Always specify type="Timer" |
| Forgetting @onready | Null reference at runtime | Add @onready for all node refs |
| Wrong signal signature | Connection fails silently | Match parameter types exactly |
| Removing necessary .new() | Some objects SHOULD be created | Only refactor scene nodes |
| Not testing after each op | Compounding errors | Test after every commit |
| Coupling through globals | Different coupling, same problem | Use Events for decoupling only |
| Over-splitting scripts | Too many tiny files | 80-120 lines is optimal |
| Async signals without checks | Race conditions | Verify node existence |
| Changing behavior "slightly" | Iron Law violation | Revert immediately |
Signal Architecture Patterns
Event Bus (Events.gd):
# Use for global events signal player_died signal level_completed(level_num: int) signal score_changed(new_score: int)
Direct Node Signals:
# Use for parent-child communication signal health_depleted signal ability_activated(ability_name: String)
When to use which:
- •Events.gd: Cross-tree communication, global state changes
- •Node signals: Parent-child, local behavior
Real-World Impact
Expected improvements after refactoring:
Code Quality:
- •30-50% reduction in total lines of code
- •Scripts average 80-120 lines (down from 150-300)
- •Zero direct node dependencies
- •Signal-based architecture throughout
Maintainability:
- •Changes isolated to single files
- •Components reusable across scenes
- •Testing individual components possible
- •New developers onboard faster
Performance:
- •Identical to baseline (±2 FPS)
- •Scene loading slightly faster
- •Memory usage unchanged
Execution Strategy
This skill runs fully automatically:
- •User invokes skill on Godot project
- •Phase 1: Scan and report findings
- •User approves refactoring
- •Phases 2-3: Execute all operations with commits on current branch
- •Phase 4: Verify and report results
User input required:
- •Initial invocation
- •Approval after Phase 1 analysis
- •Final verification check (30 seconds)
Everything else is automatic:
- •Anti-pattern detection
- •.tscn file generation
- •Script modifications
- •Git commits on current branch
- •Testing
Success Criteria
Refactoring is complete when:
- •✓ Zero
.new()calls for scene nodes - •✓ All scripts <150 lines
- •✓ Signal-based architecture established
- •✓ No
get_node()for behavior access - •✓ Data in .tres resources
- •✓ Clean git history with descriptive commits on current branch
- •✓ All scenes load without errors
- •✓ Behavior identical to baseline
- •✓ Visual appearance unchanged
- •✓ Performance within ±2 FPS
Post-Refactoring
After successful refactoring:
- •
Continue development
- •Changes are already on current branch
- •Push to remote if not already pushed
- •Continue normal development workflow
- •
Document architecture
- •Create architecture diagram
- •Document signal flows
- •List component responsibilities
- •
Establish standards
- •Use this clean architecture as template
- •Apply patterns to new code
- •Prevent anti-pattern regression
- •
Consider further improvements (separate tasks):
- •Add unit tests (use TDD skill)
- •Optimize performance (profile first)
- •Add new features (use brainstorming skill)
Remember: Refactoring changes HOW code works internally, not WHAT it does externally. The Iron Law is absolute.