| name | hammer-dependency-analyzer |
| description | Verify dependency structure and architecture health for SDL3 HammerEngine. Detects circular dependencies, excessive coupling, layer violations, header bloat, and provides dependency graph visualization. Ensures adherence to layered architecture (Core→Managers→States→Entities). Use monthly, after major refactors, or when investigating compile time issues. |
| allowed-tools | ["Bash","Read","Write","Grep","Glob"] |
HammerEngine Dependency Analyzer
Comprehensive dependency structure analysis for SDL3 HammerEngine. Verifies architectural integrity, detects circular dependencies, identifies coupling issues, and maintains clean layered design.
Purpose
HammerEngine follows a layered architecture pattern:
Core (ThreadSystem, Logger, GameLoop)
↓
Managers (AIManager, CollisionManager, etc.)
↓
States (GameState, MenuState, etc.)
↓
Entities (Entity classes, Components)
↓
Utils (Vector2D, Math helpers)
This Skill ensures:
- Circular Dependency Detection - Prevent include cycles that break compilation
- Coupling Analysis - Maintain loose coupling between managers
- Layer Violation Detection - Enforce one-way dependencies (no upward dependencies)
- Header Bloat Identification - Find unnecessary includes slowing compilation
- Forward Declaration Opportunities - Reduce compilation dependencies
- Dependency Graph Visualization - Understand system relationships
- Compile Time Impact Analysis - Estimate compilation cost per component
- Architecture Health Scoring - Quantify overall design quality
Architecture Rules (from CLAUDE.md)
Layer Rules
1. Core Layer (src/core/, include/core/)
- Can depend on: Nothing (foundation layer)
- Used by: Everything
- Components: ThreadSystem, Logger, GameLoop, GameEngine
2. Managers Layer (src/managers/, include/managers/)
- Can depend on: Core, Utils
- Cannot depend on: States, Entities (except via interfaces)
- Coupling: Managers should be loosely coupled, communicate via GameEngine
- Components: AIManager, CollisionManager, PathfinderManager, EventManager, etc.
3. States Layer (src/gameStates/, include/gameStates/)
- Can depend on: Core, Managers, Utils
- Cannot depend on: Other States (no cross-state dependencies)
- Components: GameState, MainMenuState, PlayingState, PauseState, etc.
4. Entities Layer (src/entities/, include/entities/)
- Can depend on: Core, Utils
- Should avoid: Direct manager dependencies (use interfaces/callbacks)
- Components: Entity, Component classes
5. Utils Layer (src/utils/, include/utils/)
- Can depend on: Nothing (pure utility functions)
- Used by: Everything
- Components: Vector2D, Math, JsonReader
Coupling Rules
Important: Game Engine Functional Coupling
Game engines have necessary functional dependencies between managers. The following patterns are CORRECT and expected:
✅ Functional Game System Dependencies (GOOD):
- AIManager → CollisionManager (AI needs collision queries for obstacle avoidance, LOS)
- AIManager → PathfinderManager (AI needs pathfinding for navigation)
- CollisionManager → WorldManager (collision needs world geometry/tile data)
- Managers → EventManager (event-driven notifications are good architecture)
- UIManager → FontManager (UI needs fonts to render text)
- WorldManager → ResourceManager (world needs tile/sprite resources)
- ResourceFactory → ResourceTemplateManager (factory pattern requires templates)
Manager-to-Manager Rules:
- ✅ GOOD: Functional dependencies for game systems
- ✅ GOOD: Event-based communication between managers
- 🔴 FORBIDDEN: Circular Manager dependencies (breaks compilation)
- 🔴 FORBIDDEN: Managers depending on States (violates layer boundaries)
What Actually Matters:
- Circular dependencies: 🔴 ALWAYS BAD (breaks compilation)
- Layer violations: 🔴 ALWAYS BAD (breaks architecture)
- Tight coupling: ✅ OFTEN NECESSARY for game systems to work together
- High reference counts: ✅ EXPECTED when systems interact functionally
State-to-Manager:
- ✅ GOOD: PlayingState → AIManager (states use managers)
- 🔴 FORBIDDEN: AIManager → PlayingState (managers don't know about states)
Header Inclusion:
- ✅ GOOD: Forward declarations in headers, include in .cpp
- ⚠️ WARNING: Including heavy headers in .hpp (ripple effect)
- 🔴 FORBIDDEN: Circular includes (breaks compilation)
Analysis Modes
Mode 1: Quick Dependency Check (2-3 minutes)
- Scan for circular dependencies only
- Quick validation before commits
- Use when: Daily development, pre-commit
Mode 2: Coupling Analysis (5-10 minutes)
- Analyze manager-to-manager coupling
- Identify high fan-out components
- Measure coupling strength
- Use when: Adding new managers, refactoring
Mode 3: Full Architecture Audit (15-20 minutes)
- Complete dependency graph
- Layer violation detection
- Header bloat analysis
- Forward declaration opportunities
- Compile time impact estimation
- Use when: Monthly audits, major refactors, release prep
Mode 4: Specific Component Analysis (3-5 minutes)
- Analyze single component's dependencies
- Show what it depends on and what depends on it
- Use when: Investigating specific coupling issues
Step 1: Gather User Input
Use AskUserQuestion to determine analysis scope:
Question 1: Analysis Mode
- Header: "Mode"
- Question: "What type of dependency analysis do you want?"
- Options:
- "Quick Circular Check" (2-3 min, daily use)
- "Coupling Analysis" (5-10 min, manager refactoring)
- "Full Architecture Audit" (15-20 min, comprehensive)
- "Specific Component" (3-5 min, targeted analysis)
- multiSelect: false
Question 2: Scope (if Mode = Specific Component)
- Header: "Component"
- Question: "Which component should be analyzed?"
- Options:
- "AIManager"
- "CollisionManager"
- "PathfinderManager"
- "EventManager"
- "Custom (specify)"
- multiSelect: false
- Only show if Mode = "Specific Component"
Question 3: Output Format
- Header: "Format"
- Question: "Preferred output format?"
- Options:
- "Markdown Report" (default, saved to docs/)
- "ASCII Tree" (console visualization)
- "Both" (report + console tree)
- multiSelect: false
Step 2: Scan Include Dependencies
2a. Find All Header Files
echo "=== Scanning Include Dependencies ==="
INCLUDE_HEADERS=$(find include/ -name "*.hpp" -type f)
SRC_HEADERS=$(find src/ -name "*.hpp" -type f)
ALL_HEADERS=$(echo "$INCLUDE_HEADERS $SRC_HEADERS" | tr ' ' '\n' | sort -u)
HEADER_COUNT=$(echo "$ALL_HEADERS" | wc -l)
echo "Total headers found: $HEADER_COUNT"
2b. Extract Include Directives
OUTPUT_DIR="test_results/dependency_analysis"
mkdir -p "$OUTPUT_DIR"
DEPENDENCY_FILE="$OUTPUT_DIR/dependencies_raw.txt"
> "$DEPENDENCY_FILE"
echo "Extracting #include directives..."
for HEADER in $ALL_HEADERS; do
LOCAL_INCLUDES=$(grep '^#include "' "$HEADER" | sed 's/#include "\(.*\)"/\1/' | tr -d '\r')
if [ ! -z "$LOCAL_INCLUDES" ]; then
echo "=== $HEADER ===" >> "$DEPENDENCY_FILE"
echo "$LOCAL_INCLUDES" >> "$DEPENDENCY_FILE"
echo "" >> "$DEPENDENCY_FILE"
fi
done
echo "Dependencies extracted to: $DEPENDENCY_FILE"
2c. Build Dependency Graph
Graph Structure (Adjacency List):
GRAPH_FILE="$OUTPUT_DIR/dependency_graph.txt"
> "$GRAPH_FILE"
echo "Building dependency graph..."
for HEADER in $ALL_HEADERS; do
HEADER_NAME=$(basename "$HEADER")
INCLUDES=$(grep '^#include "' "$HEADER" | sed 's/#include "\(.*\)"/\1/' | xargs -n1 basename 2>/dev/null)
if [ ! -z "$INCLUDES" ]; then
for INCLUDE in $INCLUDES; do
echo "$HEADER_NAME -> $INCLUDE" >> "$GRAPH_FILE"
done
fi
done
echo "Dependency graph built: $GRAPH_FILE"
Step 3: Analyze Dependencies by Mode
Mode 1: Quick Circular Check
3a. Detect Circular Dependencies (DFS)
echo "=== Circular Dependency Detection ==="
cat > "$OUTPUT_DIR/detect_cycles.py" <<'PYTHON_SCRIPT'
import sys
from collections import defaultdict
def read_graph(graph_file):
"""Read dependency graph from file."""
graph = defaultdict(list)
with open(graph_file, 'r') as f:
for line in f:
if '->' in line:
source, target = line.strip().split(' -> ')
graph[source].append(target)
return graph
def find_cycles_dfs(graph):
"""Find all cycles using DFS with recursion stack."""
visited = set()
rec_stack = set()
cycles = []
def dfs(node, path):
visited.add(node)
rec_stack.add(node)
path.append(node)
for neighbor in graph.get(node, []):
if neighbor not in visited:
dfs(neighbor, path.copy())
elif neighbor in rec_stack:
cycle_start = path.index(neighbor)
cycle = path[cycle_start:] + [neighbor]
cycles.append(cycle)
rec_stack.remove(node)
for node in graph:
if node not in visited:
dfs(node, [])
return cycles
def main():
len(sys.argv) != 2:
()
sys.exit(1)
graph_file = sys.argv[1]
graph = read_graph(graph_file)
(f)
cycles = find_cycles_dfs(graph)
not cycles:
()
sys.exit(0)
:
(f)
()
i, cycle enumerate(cycles, 1):
(f)
( + .(cycle))
()
sys.exit(1)
__name__ == :
main()
PYTHON_SCRIPT
+x
python3
CYCLE_STATUS=$?
[ -ne 0 ];
3b. Suggest Fixes for Circular Dependencies
If cycles detected:
echo ""
echo "=== Circular Dependency Fix Suggestions ==="
cat <<EOF
Cycle: AIManager.hpp -> PathfinderManager.hpp -> AIManager.hpp
Suggested Fixes:
1. Forward Declaration (RECOMMENDED):
In AIManager.hpp:
Remove: #include "PathfinderManager.hpp"
Add: class PathfinderManager; // Forward declaration
In AIManager.cpp:
Add: #include "PathfinderManager.hpp"
2. Interface Extraction:
Create IPathfinder.hpp with pure virtual interface
AIManager depends on IPathfinder (no circular dependency)
PathfinderManager implements IPathfinder
3. Dependency Inversion:
Both managers depend on abstract interface
GameEngine wires concrete implementations
EOF
Mode 2: Coupling Analysis
3a. Calculate Coupling Metrics
Fan-Out (Efferent Coupling):
echo "=== Coupling Analysis ==="
echo "Fan-Out (Efferent Coupling - what this component depends on):"
echo ""
while IFS= read -r HEADER; do
HEADER_NAME=$(basename "$HEADER")
FAN_OUT=$(grep "^$HEADER_NAME ->" "$GRAPH_FILE" | wc -l)
if [ "$FAN_OUT" -gt 0 ]; then
if [ "$FAN_OUT" -gt 15 ]; then
STATUS="🔴 HIGH"
elif [ "$FAN_OUT" -gt 10 ]; then
STATUS="⚠️ MEDIUM"
elif [ "$FAN_OUT" -gt 5 ]; then
STATUS="🟡 MODERATE"
else
STATUS="✅ LOW"
fi
echo " $HEADER_NAME: $FAN_OUT dependencies - $STATUS"
fi
done <<< "$ALL_HEADERS" | sort -t: -k2 -rn | -20
Fan-In (Afferent Coupling):
echo "Fan-In (Afferent Coupling - what depends on this component):"
echo ""
while IFS= read -r HEADER; do
HEADER_NAME=$(basename "$HEADER")
FAN_IN=$(grep " -> $HEADER_NAME$" "$GRAPH_FILE" | wc -l)
if [ "$FAN_IN" -gt 0 ]; then
if [ "$FAN_IN" -gt 20 ]; then
STATUS="⭐ CORE"
elif [ "$FAN_IN" -gt 10 ]; then
STATUS="📦 STABLE"
elif [ "$FAN_IN" -gt 5 ]; then
STATUS="🔧 UTILITY"
else
STATUS="📄 LEAF"
fi
echo " $HEADER_NAME: $FAN_IN dependents - $STATUS"
fi
done <<< "$ALL_HEADERS" | sort -t: -k2 -rn | head -20
echo ""
Instability Metric (I = Fan-Out / (Fan-In + Fan-Out)):
echo "Instability Metric (I = Efferent / (Afferent + Efferent)):"
echo " 0.0 = Maximally Stable (hard to change)"
echo " 1.0 = Maximally Unstable (easy to change)"
echo ""
while IFS= read -r HEADER; do
HEADER_NAME=$(basename "$HEADER")
FAN_OUT=$(grep "^$HEADER_NAME ->" "$GRAPH_FILE" | wc -l)
FAN_IN=$(grep " -> $HEADER_NAME$" "$GRAPH_FILE" | wc -l)
TOTAL=$((FAN_OUT + FAN_IN))
if [ "$TOTAL" -gt 0 ]; then
INSTABILITY=$(echo "scale=2; $FAN_OUT / $TOTAL" | bc)
echo " $HEADER_NAME: I=$INSTABILITY (out=$FAN_OUT, in=$FAN_IN)"
fi
done <<< "$ALL_HEADERS" | head -20
3b. Manager-to-Manager Coupling
echo ""
echo "=== Manager-to-Manager Coupling ==="
MANAGERS=$(find include/managers -name "*.hpp" -type f 2>/dev/null)
if [ -z "$MANAGERS" ]; then
echo "No managers found in include/managers/"
else
echo "Manager Coupling Matrix:"
echo ""
printf "%-25s" "Manager"
for MGR in $MANAGERS; do
MGR_NAME=$(basename "$MGR" .hpp)
printf "%-8s" "${MGR_NAME:0:7}"
done
echo ""
for MGR1 in $MANAGERS; do
MGR1_NAME=$(basename "$MGR1" .hpp)
printf "%-25s" "$MGR1_NAME"
for MGR2 in $MANAGERS; do
MGR2_NAME=$( .hpp)
INCLUDES=$(grep -c 2>/dev/null || )
[ = ];
[ -gt 0 ];
3c. Coupling Strength Analysis
echo ""
echo "=== Coupling Strength Analysis ==="
FUNCTIONAL_DEPS=(
"AIManager->CollisionManager"
"AIManager->PathfinderManager"
"CollisionManager->WorldManager"
"CollisionManager->EventManager"
"WorldManager->EventManager"
"WorldManager->WorldResourceManager"
"WorldManager->TextureManager"
"UIManager->FontManager"
"UIManager->UIConstants"
"InputManager->UIManager"
"InputManager->FontManager"
"PathfinderManager->EventManager"
"ParticleManager->EventManager"
"ResourceFactory->ResourceTemplateManager"
"ResourceTemplateManager->ResourceFactory"
"WorldResourceManager->EventManager"
)
FUNCTIONAL_PATTERN=$(printf "|%s" "${FUNCTIONAL_DEPS[@]}")
FUNCTIONAL_PATTERN="${FUNCTIONAL_PATTERN:1}"
TIGHT_COUPLING_COUNT=0
FUNCTIONAL_COUPLING_COUNT=0
for MGR1 in $MANAGERS; do
MGR1_NAME=$(basename "$MGR1" .hpp)
MGR1_CPP="src/managers/${MGR1_NAME}.cpp"
if [ -f "" ];
MGR2 ;
MGR2_NAME=$( .hpp)
[ != ];
REF_COUNT=$(grep -c 2>/dev/null || )
[ -gt 10 ];
COUPLING_PAIR=
| grep -qE ;
FUNCTIONAL_COUPLING_COUNT=$((FUNCTIONAL_COUPLING_COUNT + ))
TIGHT_COUPLING_COUNT=$((TIGHT_COUPLING_COUNT + ))
[ -gt 5 ];
Mode 3: Full Architecture Audit
3a. Layer Violation Detection
echo "=== Layer Violation Detection ==="
CORE_HEADERS=$(find include/core src/core -name "*.hpp" 2>/dev/null)
MANAGER_HEADERS=$(find include/managers src/managers -name "*.hpp" 2>/dev/null)
STATE_HEADERS=$(find include/gameStates src/gameStates -name "*.hpp" 2>/dev/null)
ENTITY_HEADERS=$(find include/entities src/entities -name "*.hpp" 2>/dev/null)
UTIL_HEADERS=$(find include/utils src/utils -name "*.hpp" 2>/dev/null)
echo "1. Core Layer (should be dependency-free):"
for CORE in $CORE_HEADERS; do
VIOLATIONS=$(grep '#include "' "$CORE" | grep -v 'core/' | grep -v 'utils/' | wc -l)
if [ "$VIOLATIONS" -gt 0 ]; then
echo " 🔴 $(basename "$CORE"): includes non-Core/Utils headers"
grep '#include "' "$CORE" | grep -v 'core/' | grep -v 'utils/'
fi
done
echo ""
echo "2. Manager Layer (should not depend on States/Entities):"
for MGR in $MANAGER_HEADERS;
STATE_DEPS=$(grep | grep -c 2>/dev/null || )
ENTITY_DEPS=$(grep | grep -c 2>/dev/null || )
[ -gt 0 ] || [ -gt 0 ];
[ -gt 0 ] &&
[ -gt 0 ] &&
STATE1 ;
STATE1_NAME=$( )
STATE2 ;
STATE2_NAME=$( )
[ != ];
grep -q 2>/dev/null;
UTIL ;
NON_UTIL_DEPS=$(grep | grep -v | -l)
[ -gt 0 ];
grep | grep -v
CORE_VIOLATIONS=$(find include/core src/core -name - grep {} \; | grep -v | grep -v | -l)
MANAGER_VIOLATIONS=$(find include/managers src/managers -name - grep {} \; | grep | -l)
STATE_VIOLATIONS=0
UTIL_VIOLATIONS=$(find include/utils src/utils -name - grep {} \; | grep -v | -l)
TOTAL_VIOLATIONS=$((CORE_VIOLATIONS + MANAGER_VIOLATIONS + STATE_VIOLATIONS + UTIL_VIOLATIONS))
[ -eq 0 ];
3b. Header Bloat Analysis
echo ""
echo "=== Header Bloat Analysis ==="
echo "Headers with High Include Count (potential bloat):"
echo ""
for HEADER in $ALL_HEADERS; do
INCLUDE_COUNT=$(grep -c '^#include "' "$HEADER")
if [ "$INCLUDE_COUNT" -gt 15 ]; then
echo " 🔴 $(basename "$HEADER"): $INCLUDE_COUNT includes (HIGH - review for bloat)"
elif [ "$INCLUDE_COUNT" -gt 10 ]; then
echo " ⚠️ $(basename "$HEADER"): $INCLUDE_COUNT includes (MODERATE)"
fi
done
echo ""
echo "Frequently Included Headers (ripple effect on compile times):"
echo ""
while IFS= read -r HEADER; do
HEADER_NAME=$(basename "")
INCLUDE_COUNT=$(grep -r include/ src/ 2>/dev/null | -l)
[ -gt 10 ];
HEADER_INCLUDES=$(grep -c 2>/dev/null || )
[ -gt 10 ];
<<< | -t: -k2 -rn | -15
3c. Forward Declaration Opportunities
echo ""
echo "=== Forward Declaration Opportunities ==="
echo "Analyzing headers for forward declaration opportunities..."
echo ""
for HEADER in $ALL_HEADERS; do
INCLUDES=$(grep '^#include "' "$HEADER" | sed 's/#include "\(.*\.hpp\)"/\1/')
for INCLUDE in $INCLUDES; do
INCLUDE_BASE=$(basename "$INCLUDE" .hpp)
PTR_REF_ONLY=$(grep -c "${INCLUDE_BASE}[*&]" "$HEADER" 2>/dev/null || echo "0")
DIRECT_USE=$(grep -c "${INCLUDE_BASE}[^*&];.*;" "$HEADER" 2>/dev/null || echo "0")
if [ "$PTR_REF_ONLY" -gt 0 ] && [ "$DIRECT_USE" -eq 0 ]; then
echo " ✨ : Can forward-declare "
| -30
3d. Compile Time Impact Estimation
echo ""
echo "=== Compile Time Impact Estimation ==="
echo "Dependency Depth (higher = more recompilation ripple):"
echo ""
cat > "$OUTPUT_DIR/calc_depth.py" <<'PYTHON_SCRIPT'
import sys
from collections import defaultdict, deque
def read_graph(graph_file):
graph = defaultdict(list)
with open(graph_file, 'r') as f:
for line in f:
if '->' in line:
source, target = line.strip().split(' -> ')
graph[source].append(target)
return graph
def calculate_depth(graph, node, memo=None):
"""Calculate max dependency depth using DFS with memoization."""
if memo is None:
memo = {}
if node in memo:
return memo[node]
if node not in graph or not graph[node]:
memo[node] = 0
return 0
max_depth = 0
for neighbor in graph[node]:
depth = calculate_depth(graph, neighbor, memo)
max_depth = max(max_depth, depth + 1)
memo[node] = max_depth
return max_depth
def main():
len(sys.argv) != 2:
()
sys.exit(1)
graph = read_graph(sys.argv[1])
depths = {}
node graph:
depths[node] = calculate_depth(graph, node)
sorted_depths = sorted(depths.items(), key=lambda x: x[1], reverse=True)
()
()
node, depth sorted_depths[:20]:
depth > 10:
status =
depth > 7:
status =
depth > 4:
status =
:
status =
(f)
()
()
__name__ == :
main()
PYTHON_SCRIPT
+x
python3
TOTAL_DEPTH=$(python3 2>/dev/null | grep | awk -F | awk | -sd+ | bc)
Mode 4: Specific Component Analysis
4a. Single Component Dependency Analysis
COMPONENT="$USER_COMPONENT"
COMPONENT_HEADER=$(find include/ src/ -name "${COMPONENT}.hpp" | head -1)
if [ -z "$COMPONENT_HEADER" ]; then
echo "❌ Component not found: $COMPONENT"
exit 1
fi
echo "=== Dependency Analysis: $COMPONENT ==="
echo ""
echo "1. What $COMPONENT depends on (Efferent Dependencies):"
echo ""
grep '^#include "' "$COMPONENT_HEADER" | sed 's/#include "\(.*\)"/ - \1/'
EFFERENT_COUNT=$(grep -c '^#include "' "$COMPONENT_HEADER")
echo ""
echo " Total: $EFFERENT_COUNT direct dependencies"
echo ""
echo "2. What depends on $COMPONENT (Afferent Dependencies):"
echo ""
COMPONENT_NAME=$(basename "$COMPONENT_HEADER")
DEPENDENTS=$(grep -r "#include \"\"" include/ src/ 2>/dev/null | -d: -f1 | -u)
[ -z ];
| DEP;
AFFERENT_COUNT=$( | -l)
TOTAL=$((EFFERENT_COUNT + AFFERENT_COUNT))
[ -gt 0 ];
INSTABILITY=$( | bc)
(( $(echo " > " | bc -l) ));
(( $(echo " < " | bc -l) ));
| grep -q ;
| grep -q ;
| grep -q ;
| grep -q ;
| grep -q ;
VIOLATIONS=0
| grep -q ;
STATE_DEPS=$(grep | grep -c || )
[ -gt 0 ];
VIOLATIONS=$((VIOLATIONS + ))
[ -gt 15 ];
VIOLATIONS=$((VIOLATIONS + ))
COMPONENT_BASE=$( )
CYCLES=$(python3 2>&1 | grep || )
[ ! -z ];
| sed
VIOLATIONS=$((VIOLATIONS + ))
[ -eq 0 ];
Step 4: Generate Dependency Visualizations
4a. ASCII Dependency Tree
echo ""
echo "=== Dependency Tree (ASCII) ==="
cat > "$OUTPUT_DIR/make_tree.sh" <<'TREE_SCRIPT'
print_tree() {
local node=$1
local prefix=$2
local visited=$3
local max_depth=$4
local current_depth=$5
if echo "$visited" | grep -q "|$node|"; then
echo "${prefix}└── $node (circular)"
return
fi
if [ "$current_depth" -ge "$max_depth" ]; then
echo "${prefix}└── $node (...)"
return
fi
echo "${prefix}└── $node"
deps=$(grep | -d -f2 | -d )
[ ! -z ];
new_visited=
new_depth=$((current_depth + ))
| dep;
print_tree
}
GRAPH_FILE=
ROOT_NODE=
MAX_DEPTH=
print_tree 0
TREE_SCRIPT
+x
3
3
4b. Dependency Matrix (for report)
echo ""
echo "Generating dependency matrix for report..."
cat > "$OUTPUT_DIR/dependency_matrix.txt" <<EOF
# Dependency Matrix
Rows depend on Columns (✓ = direct dependency)
EOF
TOP_HEADERS=$(cat "$GRAPH_FILE" | grep -o '[^ ]*\.hpp' | sort | uniq -c | sort -rn | head -20 | awk '{print $2}')
printf "%-25s" "Component"
echo "$TOP_HEADERS" | while read HEADER; do
HEADER_SHORT=$(echo "$HEADER" | cut -d'.' -f1 | cut -c1-7)
printf "%-8s" "$HEADER_SHORT"
done
echo ""
echo "$TOP_HEADERS" | while read ROW_HEADER; do
printf "%-25s" ""
| COL_HEADER;
[ = ];
HAS_DEP=$(grep )
[ ! -z ];
>>
Step 5: Generate Architecture Health Report
Report Structure:
# HammerEngine Dependency Analysis Report
**Generated:** YYYY-MM-DD HH:MM:SS
**Branch:** <branch>
**Commit:** <hash>
**Analysis Mode:** <mode>
---
## Executive Summary
**Architecture Health Score:** [85/100] (GOOD)
**Status:** ✅ HEALTHY / ⚠️ NEEDS ATTENTION / 🔴 CRITICAL ISSUES
**Key Findings:**
- [Finding 1]
- [Finding 2]
- [Finding 3]
**Overall Assessment:** [2-3 sentence summary]
---
## Dependency Statistics
**Codebase Size:**
- Total headers analyzed: [N]
- Core layer: [N] files
- Managers layer: [N] files
- States layer: [N] files
- Entities layer: [N] files
- Utils layer: [N] files
**Dependency Metrics:**
- Total dependencies: [N]
- Average dependencies per file: [X.X]
- Max dependencies (single file): [N]
- Circular dependencies: [N] 🔴/✅
---
## Circular Dependencies (CRITICAL)
[If none:]
✅ **NO CIRCULAR DEPENDENCIES DETECTED**
All include hierarchies are acyclic. Compilation order is deterministic.
[If found:]
🔴 **FOUND [N] CIRCULAR DEPENDENCIES**
### Cycle 1: [Component A] ↔ [Component B]
**Cycle Path:**
ComponentA.hpp -> ComponentB.hpp -> ComponentA.hpp
**Impact:** Breaks compilation or requires workarounds
**Suggested Fix:**
1. **Forward Declaration** (RECOMMENDED)
- In ComponentA.hpp, replace `#include "ComponentB.hpp"` with `class ComponentB;`
- Move include to ComponentA.cpp
2. **Interface Extraction**
- Create IComponentB.hpp with pure virtual interface
- ComponentA depends on interface (breaks cycle)
[Repeat for each cycle]
---
## Coupling Analysis
### High-Coupling Components (Top 10)
| Component | Fan-Out | Fan-In | Instability | Status |
|-----------|---------|--------|-------------|--------|
| [Component1] | 18 | 5 | 0.78 | 🔴 HIGH |
| [Component2] | 15 | 12 | 0.55 | ⚠️ MODERATE |
| [Component3] | 8 | 20 | 0.29 | ✅ STABLE |
**Legend:**
- **Fan-Out:** Number of dependencies (efferent coupling)
- **Fan-In:** Number of dependents (afferent coupling)
- **Instability:** Fan-Out / (Fan-In + Fan-Out)
- 0.0 = Maximally stable (hard to change)
- 1.0 = Maximally unstable (easy to change)
### Manager-to-Manager Coupling
**Coupling Matrix:**
[Include dependency matrix from Step 4b]
**Manager Coupling Analysis:**
**Important Context:** Game engines have **necessary functional dependencies**. Tight coupling between game systems is often **CORRECT and required** for the engine to function.
**Functional Coupling (✅ Expected & Correct):**
[List coupling pairs that serve game functionality]
- AIManager → CollisionManager (AI obstacle avoidance, LOS checks)
- CollisionManager → WorldManager (world geometry queries)
- Managers → EventManager (event-driven notifications)
- UIManager → FontManager (text rendering)
- etc.
**Status:** ✅ These dependencies are functionally necessary and represent correct game engine architecture.
**Problematic Coupling (🔴 Review Required):**
[If any non-functional tight coupling exists]
1. **[Manager1] → [Manager2]** (N references)
- Status: 🔴 REVIEW
- Reason: Unclear functional necessity
- Recommendation: Verify this coupling serves game functionality
[If none:]
✅ **NO PROBLEMATIC COUPLING**
All tight coupling serves clear game system functionality.
---
## Layer Violations
### Layer Integrity Check
**Core Layer** (should depend on nothing):
[✅ CLEAN / 🔴 [N] violations]
**Managers Layer** (should depend on Core, Utils only):
[✅ CLEAN / 🔴 [N] violations]
**States Layer** (no cross-state dependencies):
[✅ CLEAN / 🔴 [N] violations]
**Utils Layer** (should be dependency-free):
[✅ CLEAN / 🔴 [N] violations]
### Violation Details
[If violations found:]
**Violation 1: AIManager includes PlayingState.hpp**
- **File:** include/managers/AIManager.hpp:15
- **Issue:** Manager layer depending on State layer
- **Impact:** Violates layered architecture, creates tight coupling
- **Fix:** Remove include, use interface or event system
[Repeat for each violation]
[If none:]
✅ **NO LAYER VIOLATIONS**
All components respect layered architecture boundaries.
---
## Header Bloat Analysis
### High-Include Headers
| Header | #Includes | Status | Dependents |
|--------|-----------|--------|-----------|
| [Header1] | 22 | 🔴 HIGH | 15 files |
| [Header2] | 18 | ⚠️ MODERATE | 8 files |
**Bloat Amplification:**
Headers with many includes that are widely used cause compilation ripple effects.
**Worst Offenders:**
1. **GameEngine.hpp** - 22 includes, used by 15 files
- Ripple effect: ~330 transitive includes
- Recommendation: Split into GameEngine_fwd.hpp with forward declarations
### Forward Declaration Opportunities
[Top 10 opportunities from Step 3c]
**Estimated Compile Time Savings:** ~15-25% reduction
---
## Dependency Depth Analysis
### Compile Time Impact
| Header | Depth | Impact | Recommendation |
|--------|-------|--------|----------------|
| [Header1] | 14 | 🔴 VERY HIGH | Reduce dependencies |
| [Header2] | 9 | ⚠️ HIGH | Consider splitting |
| [Header3] | 6 | 🟡 MODERATE | Monitor |
**Total Dependency Depth:** [N]
**Average Depth:** [X.X]
**High-Depth Components:**
Changing these headers causes cascading recompilation:
- [List top 5 highest depth headers]
**Recommendation:** Use forward declarations and split large headers
---
## Architecture Health Scorecard
| Category | Score | Weight | Weighted | Status |
|----------|-------|--------|----------|--------|
| Circular Dependencies | [X/10] | 30% | [X.X] | 🔴/⚠️/✅ |
| Layer Compliance | [X/10] | 25% | [X.X] | 🔴/⚠️/✅ |
| Coupling Strength | [X/10] | 20% | [X.X] | 🔴/⚠️/✅ |
| Header Bloat | [X/10] | 15% | [X.X] | 🔴/⚠️/✅ |
| Dependency Depth | [X/10] | 10% | [X.X] | 🔴/⚠️/✅ |
| **TOTAL** | | **100%** | **[XX/100]** | **[GRADE]** |
**Grading Scale:**
- 90-100: A+ (Excellent architecture)
- 80-89: A (Good architecture, minor issues)
- 70-79: B (Fair architecture, needs improvement)
- 60-69: C (Poor architecture, refactoring required)
- Below 60: F (Critical issues, major refactoring needed)
---
## Recommendations
### Critical (Fix Immediately)
1. **Break Circular Dependencies** ([N] found)
- Use forward declarations
- Extract interfaces
- Priority: HIGH, Effort: 2-4 hours
2. **Fix Layer Violations** ([N] found)
- Remove inappropriate includes
- Use event system for cross-layer communication
- Priority: HIGH, Effort: 1-2 hours
### Important (Address Soon)
3. **Review Non-Functional Coupling (if any)**
- [Only list coupling that doesn't serve clear game functionality]
- Verify: Does this coupling serve a game system requirement?
- If yes: Document the functional reason, no change needed
- If no: Consider refactoring or event-based communication
- Priority: MEDIUM (only if problematic coupling exists)
4. **Optimize High-Include Headers**
- Split [Header] into interface and implementation
- Add forward declaration headers
- Priority: MEDIUM, Effort: 2-3 hours
**Note:** Do NOT refactor functional game system dependencies. Coupling between managers is often necessary and correct for game engines.
### Optional (Consider)
5. **Improve Compile Times**
- Apply forward declaration opportunities
- Split large headers
- Expected improvement: 15-25% faster compilation
- Priority: LOW, Effort: 3-5 hours
---
## Dependency Visualizations
### GameEngine Dependency Tree
[ASCII tree from Step 4a]
### AIManager Dependency Tree
[ASCII tree from Step 4a]
### Full Dependency Matrix
[Link to or include dependency_matrix.txt]
---
## Comparison with Previous Analysis (if baseline exists)
| Metric | Previous | Current | Change | Trend |
|--------|----------|---------|--------|-------|
| Total Dependencies | [N] | [N] | [+/-N] | 📈/📉/➡️ |
| Circular Dependencies | [N] | [N] | [+/-N] | 📈/📉/➡️ |
| Layer Violations | [N] | [N] | [+/-N] | 📈/📉/➡️ |
| Average Coupling | [X.X] | [X.X] | [+/-X.X] | 📈/📉/➡️ |
| Health Score | [XX] | [XX] | [+/-XX] | 📈/📉/➡️ |
**Overall Trend:** [Improving/Stable/Degrading]
---
## Action Plan
### Immediate (This Week)
- [ ] Break circular dependency: [Cycle description]
- [ ] Fix layer violation: [Specific violation]
### Short-term (This Month)
- [ ] Reduce coupling between [Component1] and [Component2]
- [ ] Split high-include headers: [Header list]
- [ ] Apply top 5 forward declaration opportunities
### Long-term (This Quarter)
- [ ] Comprehensive header cleanup
- [ ] Establish pre-commit dependency checks
- [ ] Document architecture patterns
---
## Files Requiring Attention
Based on analysis, these files need modification:
**High Priority:**
- [File1] - Circular dependency
- [File2] - Layer violation
**Medium Priority:**
- [File3] - High coupling
- [File4] - Header bloat
**Low Priority:**
- [File5] - Forward declaration opportunity
---
## Next Steps
1. **Review this report** with team/architect
2. **Prioritize fixes** based on impact and effort
3. **Create tickets** for identified issues
4. **Re-run analysis** after fixes to verify improvements
5. **Schedule regular audits** (monthly recommended)
**Re-run Analysis:**
```bash
# After fixes, verify improvements
[Command to re-invoke skill]
Report Generated By: hammer-dependency-analyzer Skill
Report Saved To: docs/architecture/dependency_analysis_YYYY-MM-DD.md
**Save report:**
```bash
REPORT_FILE="docs/architecture/dependency_analysis_$(date +%Y-%m-%d).md"
mkdir -p "docs/architecture"
cat > "$REPORT_FILE" <<'EOF'
[Generated markdown report]
EOF
echo "✅ Dependency analysis report saved to: $REPORT_FILE"
Step 6: Console Summary
=== HammerEngine Dependency Analysis ===
Mode: [Mode Name]
Files Analyzed: [N] headers
Architecture Health: [Score]/100 ([GRADE])
Circular Dependencies: [N] 🔴/✅
Layer Violations: [N] 🔴/✅
High Coupling: [N] components ⚠️
Header Bloat: [N] headers 🔴/⚠️
[If issues:]
Status: 🔴 CRITICAL ISSUES / ⚠️ NEEDS ATTENTION
Critical Issues:
- [Issue 1]
- [Issue 2]
Recommendations:
1. [Top recommendation]
2. [Second recommendation]
[If clean:]
Status: ✅ ARCHITECTURE HEALTHY
All checks passed:
✅ No circular dependencies
✅ No layer violations
✅ Coupling within acceptable limits
✅ No excessive header bloat
Full Report: docs/architecture/dependency_analysis_YYYY-MM-DD.md
Next: [Suggested action based on results]
Usage Examples
When the user says:
- "analyze dependencies"
- "check architecture health"
- "find circular dependencies"
- "check manager coupling"
- "analyze AIManager dependencies"
- "audit header dependencies"
Activate this Skill automatically.
Integration with Development Workflow
Use this Skill:
Regular Maintenance
- Monthly audits - Catch architectural drift early
- After major refactors - Verify improvements
- Before releases - Ensure architecture quality
Development Checkpoints
- Adding new manager - Verify coupling is appropriate
- Refactoring existing code - Check impact on dependencies
- Investigating compile times - Identify bloat and depth issues
Problem Investigation
- Circular dependency errors - Find and break cycles
- Slow compilation - Identify high-depth headers
- Tight coupling concerns - Analyze manager interactions
Common Dependency Issues in HammerEngine
Issue 1: Manager Circular Dependencies
Symptom: Compilation errors with forward declaration issues
Cause: Two managers including each other's headers
Solution: One-way dependency with interface or event system
Issue 2: State-to-State Dependencies
Symptom: States including other state headers
Cause: Sharing data/logic between states
Solution: Move shared logic to Manager or GameEngine
Issue 3: GameEngine.hpp Bloat
Symptom: Long compile times for any GameEngine change
Cause: GameEngine includes all managers in header
Solution: Forward declarations + includes in .cpp
Issue 4: Layer Violations
Symptom: Manager includes State header
Cause: Manager needs state-specific logic
Solution: Dependency inversion - state registers callback with manager
Issue 5: Utils Dependencies
Symptom: Utils including Core or Manager headers
Cause: Utils trying to use engine-specific types
Solution: Make Utils pure (STL only), or move to appropriate layer
Performance Expectations
- Quick Circular Check: 2-3 minutes (scan + cycle detection)
- Coupling Analysis: 5-10 minutes (metrics + matrix)
- Full Architecture Audit: 15-20 minutes (all checks + visualization)
- Specific Component: 3-5 minutes (single component deep dive)
Manual Equivalent: 60-120 minutes per full audit
Exit Codes
- 0: No architectural issues detected
- 1: Circular dependencies found (BLOCKING)
- 2: Layer violations detected (CRITICAL)
- 3: High coupling detected (WARNING)
- 4: Multiple issues detected
Important Notes
- Run regularly - Architecture degrades over time without monitoring
- Fix issues promptly - Small issues compound into major refactors
- Document patterns - Share good architectural examples with team
- Automate checks - Consider pre-commit hooks for critical violations
- Track trends - Monitor health score over time
- Game Engine Context - Remember that tight manager coupling is often functionally necessary
Scoring Guidance for Game Engines
Coupling Strength Score Calculation:
When scoring coupling (20% of health score), distinguish between:
-
Functional Coupling (✅ Good, score: 8-10/10)
- Game systems that must interact to work
- Examples: AI→Collision, Collision→World, Managers→Events
- These are correct design and should NOT reduce the score significantly
-
Problematic Coupling (🔴 Bad, score: 0-4/10)
- Circular dependencies (breaks compilation)
- Layer violations (Manager→State)
- Unclear/unnecessary dependencies
Scoring Formula:
Coupling Score = 10 - (problematic_coupling_count * 1.5)
Where problematic_coupling_count =
- Circular dependencies found
- Layer-violating dependencies
- Non-functional tight coupling (unclear purpose)
Functional coupling does NOT reduce score.
Example:
- 0 problematic, 9 functional: Score = 10/10 ✅ Excellent
- 1-2 problematic, 9 functional: Score = 7-8.5/10 ✅ Good
- 3-5 problematic, 9 functional: Score = 4-6/10 ⚠️ Needs work
- 6+ problematic: Score = 0-2/10 🔴 Critical
This scoring recognizes that game engines NEED manager coupling to function.
Ready to analyze HammerEngine architecture. Ask user for analysis mode.