| 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 deptrac reports 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
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 ORM |
Template examples use Doctrine ODM/MongoDB in places; apply the same patterns with Doctrine ORM and MySQL in this service.
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
make deptrac
Track progress: 15 violations → 10 → 5 → 0 ✅
Constraints (Parameters)
NEVER
- Modify
deptrac.yaml to allow violations
- Disable Deptrac checks
- Add suppression comments or ignore directives (
@SuppressWarnings, @psalm-suppress, @phpstan-ignore*, @infection-ignore*, phpcs:ignore)
- Create "wrapper" classes to hide dependencies
- Move entire class to wrong layer just to satisfy Deptrac
- Move classes into unrelated/random directories just to make Deptrac pass (for example, hiding
Generator classes under Factory)
- Brute-force Deptrac by reorganizing code around tool output instead of business responsibility
- Create ad-hoc directory/class types; use only well-known software patterns (e.g., Strategy, Factory, Provider, Resolver, CQRS Command/Handler)
- 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
- Keep "Directory X contains ONLY class type X" semantics
- For new directories/classes, use explicit, well-known pattern names aligned with DDD/CQRS
- Verify fixes with
make deptrac after 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:
Related Skills
Quick Commands
make deptrac
vendor/bin/deptrac analyze --report-uncovered
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 violations
02-domain-doctrine-annotations.php - Removing Doctrine imports
03-domain-api-platform.php - Moving API Platform config
04-infrastructure-handler.php - Using Command Bus pattern
Anti-Patterns to Avoid
❌ DON'T Modify deptrac.yaml
paths:
- { collector: layer_domain, exclude: '.*Annotation.*' }
❌ DON'T Create Wrapper Classes
class MyValidator {
private SymfonyValidator $validator;
}
❌ DON'T Move Classes to 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