Architecture Violation Signal (AVS)¶
Signal ID: AVS
Full name: Architecture Violation Score
Type: Scoring signal (contributes to drift score)
Default weight: 0.16
Scope: cross_file
What AVS detects¶
AVS detects imports that cross layer boundaries — for example, a route handler importing directly from a database module instead of going through a service layer. This is one of the strongest indicators of architectural erosion, especially in projects where AI-generated code bypasses established module hierarchies.
Before — layer violation¶
# routes/user_routes.py
from database.models import User # ← direct DB access from route layer
from database.connection import get_db # ← bypasses service layer
@app.get("/users/{user_id}")
def get_user(user_id: int):
db = get_db()
return db.query(User).get(user_id)
The route handler directly accesses the database layer, skipping the service layer entirely.
After — respecting layer boundaries¶
# routes/user_routes.py
from services.user_service import get_user_by_id # ← proper service call
@app.get("/users/{user_id}")
def get_user(user_id: int):
return get_user_by_id(user_id)
Access goes through the service layer, maintaining separation of concerns.
Why architecture violations matter¶
- Coupling explosion — direct cross-layer imports create hidden dependencies that make refactoring dangerous.
- Testing difficulty — route tests need database fixtures instead of simple service mocks.
- AI generation amplifies violations — LLMs often produce the shortest working path, ignoring project-specific layer conventions.
- Erosion is gradual — each violation makes the next one more likely, as developers copy existing patterns.
How the score is calculated¶
AVS evaluates each import statement against configured layer boundary policies. The score combines:
- Violation count per module — more violations indicate systemic disregard for boundaries.
- Layer distance — imports skipping multiple layers score higher than adjacent-layer violations.
- Hub dampening — modules that serve as intentional "hubs" (many importers) receive dampened scores to avoid false positives.
- Omnilayer recognition — directories configured as
omnilayer_dirs(allowed to be imported everywhere) are excluded.
Severity thresholds:
| Score range | Severity |
|---|---|
| ≥ 0.7 | HIGH |
| ≥ 0.5 | MEDIUM |
| ≥ 0.3 | LOW |
| < 0.3 | INFO |
How to fix AVS findings¶
- Introduce a service layer — if routes directly access the database, create service functions that mediate.
- Respect the import direction — lower layers should not import from higher layers.
- Configure omnilayer directories — for shared utilities that are intentionally available everywhere, add them to
omnilayer_dirs. - Use dependency injection — pass dependencies through function arguments rather than hard-coded imports.
Configuration¶
# drift.yaml
weights:
architecture_violation: 0.16 # default weight (0.0 to 1.0)
policies:
layer_boundaries:
- name: "strict_layers"
from: "routes/**"
deny_import: ["database/**", "infrastructure/**"]
omnilayer_dirs: ["src/common/", "src/shared/"]
Set weight to 0.0 to disable AVS scoring entirely. Use policies.layer_boundaries to define project-specific rules. Use omnilayer_dirs for legitimately shared code.
Detection details¶
AVS uses the following algorithm:
- Parse all imports from AST across the project.
- Resolve import targets to physical file paths.
- Match against configured layer boundary policies (deny rules).
- Apply hub dampening for high-fan-in modules.
- Apply embedding-based layer inference (optional) to infer layer relationships when no explicit policy exists.
AVS is deterministic, AST-based, and works with or without explicit policy configuration. When no policies are configured, it uses heuristic directory-name analysis to infer layer relationships.
Related signals¶
- PFS (Pattern Fragmentation) — detects inconsistent implementations. AVS finds import-level boundary crossings; PFS finds behavioral inconsistency.
- CCC (Co-Change Coupling) — detects hidden coupling through commit history. AVS finds static import violations; CCC finds dynamic coupling.
- CIR (Circular Import) — detects import cycles. AVS finds directional violations; CIR finds circular dependencies.