| name | deptrac-fixer |
| description | Diagnose and fix Deptrac architectural violations automatically. Use when Deptrac reports dependency violations, layers are incorrectly coupled, or when refactoring code to respect hexagonal architecture boundaries. Never modifies deptrac.yaml - always fixes the code to match the architecture. |
Deptrac Fixer Skill
Context (Input)
make deptracreports violations- Error message contains "must not depend on"
- Domain layer has framework imports (Symfony, Doctrine, API Platform)
- Infrastructure directly calls Application handlers
- Any architectural boundary violation detected
Task (Function)
Diagnose and fix Deptrac violations by refactoring code to respect hexagonal architecture boundaries.
Success Criteria: make deptrac outputs "✅ No violations found"
Core Principle
Fix the code, NEVER modify deptrac.yaml
The architecture is correct. The code must conform to it, not vice versa.
Quick Start: Fix a Violation
Step 1: Run Deptrac
make deptrac
Step 2: Parse Violation Message
Domain must not depend on Symfony
src/Customer/Domain/Entity/Customer.php:8
uses Symfony\Component\Validator\Constraints as Assert
Extract:
- Violating Layer: Domain
- Forbidden Dependency: Symfony
- File & Line:
src/Customer/Domain/Entity/Customer.php:8 - Violation Type:
uses(import statement)
Step 3: Identify Fix Pattern
| Domain Depends On | Fix Pattern | Example File |
|---|---|---|
| Symfony Validator | Move to YAML config | 01-domain-symfony-validation.php |
| Doctrine (ODM/ORM) | Use XML mapping | 02-domain-doctrine-annotations.php |
| API Platform | Move to YAML config | 03-domain-api-platform.php |
| Infrastructure → Handler | Use Command Bus | 04-infrastructure-handler.php |
See: REFERENCE.md for complete fix patterns and advanced scenarios.
Step 4: Apply Fix
Follow the pattern from examples, then verify:
make deptrac
Repeat until: "✅ No violations found"
Layer Dependency Rules
Domain ─────────────────> (NO dependencies)
│
│
Application ──────────> Domain + Infrastructure + Symfony + API Platform
│
│
Infrastructure ───────> Domain + Application + Symfony + Doctrine
Allowed Dependencies:
| Layer | Can Depend On |
|---|---|
| Domain | ❌ Nothing (pure PHP only) |
| Application | ✅ Domain, Infrastructure, Symfony, API Platform |
| Infrastructure | ✅ Domain, Application, Symfony, Doctrine, MongoDB |
See: CODELY-STRUCTURE.md for complete directory hierarchy.
Common Fix Patterns (Quick Reference)
Pattern 1: Domain → Symfony Validator
❌ Problem: Validation annotations in Domain entity
use Symfony\Component\Validator\Constraints as Assert;
class Customer {
#[Assert\NotBlank]
private string $name;
}
✅ Solution: Move validation to config/validator/{Entity}.yaml
Pattern 2: Domain → Doctrine Annotations
❌ Problem: Doctrine attributes in Domain entity
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
#[ODM\Document]
class Customer { }
✅ Solution: Create XML mapping in config/doctrine/{Entity}.mongodb.xml
Pattern 3: Domain → API Platform
❌ Problem: API Platform attributes in Domain entity
use ApiPlatform\Metadata\ApiResource;
#[ApiResource]
class Customer { }
✅ Solution: Create YAML config in config/api_platform/resources/{entity}.yaml
Pattern 4: Infrastructure → Application Handler
❌ Problem: Direct handler call from Infrastructure
class Repository {
public function __construct(
private SomeHandler $handler // ❌ Circular dependency
) {}
}
✅ Solution: Use Command Bus pattern
class Repository {
public function __construct(
private CommandBusInterface $commandBus // ✅ Interface
) {}
public function someMethod() {
$this->commandBus->dispatch(new SomeCommand());
}
}
See: examples/ directory for complete, runnable examples.
Diagnostic Workflow
When facing multiple violations:
Step 1: Get All Violations
make deptrac > violations.txt
Step 2: Categorize by Type
Group violations by layer pair:
- Domain → Symfony
- Domain → Doctrine
- Domain → API Platform
- Infrastructure → Application
- etc.
Step 3: Fix in Priority Order
- Domain violations first (most critical)
- Infrastructure violations (circular dependencies)
- Application violations (least common)
Step 4: Verify Incrementally
# After each fix
make deptrac
Track progress: 15 violations → 10 → 5 → 0 ✅
Constraints
NEVER
- Modify
deptrac.yamlto allow violations - Disable Deptrac checks
- Add suppression comments
- Create "wrapper" classes to hide dependencies
- Move entire class to wrong layer just to satisfy Deptrac
- Use reflection or dynamic loading to bypass checks
ALWAYS
- Fix the code to match the architecture
- Keep Domain layer pure (no framework imports)
- Use interfaces for cross-layer dependencies
- Move configuration to YAML/XML files
- Verify fixes with
make deptracafter each change - Check that tests still pass after refactoring
Format (Output)
Expected Deptrac Output
Deptrac
Checking dependencies...
✅ No violations found
Expected CI Output
✅ CI checks successfully passed!
Verification Checklist
After fixing violations:
-
make deptracshows 0 violations - Domain entities have no framework imports
- Validation moved to
config/validator/ - Doctrine mapping moved to
config/doctrine/ - API Platform config moved to
config/api_platform/ - Infrastructure uses Command Bus, not direct handler calls
- All tests still pass (
make all-tests) -
make cipasses completely
Related Skills
- implementing-ddd-architecture - Understanding DDD patterns and layer responsibilities
- api-platform-crud - YAML-based API Platform configuration
- database-migrations - XML-based Doctrine mappings
- complexity-management - Refactoring without breaking architecture
Quick Commands
# Run Deptrac analysis
make deptrac
# Check specific layer violations (if supported)
vendor/bin/deptrac analyze --report-uncovered
# Verify architecture after fixes
make deptrac && make ci
Reference Documentation
For detailed patterns, examples, and troubleshooting:
- REFERENCE.md - Complete fix patterns for all violation types
- CODELY-STRUCTURE.md - Directory hierarchy and file placement rules
- examples/ - Complete, runnable code examples:
01-domain-symfony-validation.php- Fixing Symfony validation violations02-domain-doctrine-annotations.php- Removing Doctrine imports03-domain-api-platform.php- Moving API Platform config04-infrastructure-handler.php- Using Command Bus pattern
Anti-Patterns to Avoid
❌ DON'T Modify deptrac.yaml
# ❌ NEVER DO THIS
paths:
- { collector: layer_domain, exclude: '.*Annotation.*' } # Hiding violations
❌ DON'T Create Wrapper Classes
// ❌ BAD: Hiding framework dependency
class MyValidator {
private SymfonyValidator $validator; // Still violates!
}
❌ DON'T Move Classes to Wrong Layer
// ❌ BAD: Moving Domain entity to Application to "fix" violation
// src/Application/Entity/Customer.php // WRONG LAYER!
✅ DO Fix the Root Cause
- Extract validation to YAML
- Move configuration to XML
- Use interfaces and dependency inversion
- Respect layer responsibilities
Success Criteria Summary
- ✅ Zero Deptrac violations
- ✅ Domain layer pure (no framework imports)
- ✅ All configuration externalized (YAML/XML)
- ✅ Proper use of Command Bus for cross-layer communication
- ✅ All tests passing
- ✅ CI pipeline green