Enforce clean architecture patterns in any project. Activates when the user says "architecture review", "check my patterns", "enforce architecture", "review structure", "observer pattern", "repository pattern", "dependency injection", "DI pattern", "event-driven", "composition over inheritance", "code quality check", "pattern review", "architecture audit", "clean architecture", "SOLID principles", or invokes /vault-architecture. Reads project.config.json for project-specific enforcement. Ensures Observer, Repository, DI, and Composition patterns are followed consistently.
// vault-architecture SKILL.md / Developer: Marcus Daley / 2026-02-27 // Architecture enforcement skill for Claude Code // Enforces Observer, Repository, DI, and Composition patterns across projects // Reads project.config.json for project-specific customization (95/5 rule)
Audit and enforce clean architecture patterns in any project. This skill reads
project.config.json to customize enforcement per project while applying universal
patterns across all codebases.
/vault-architecture # Audit entire project
/vault-architecture server/ # Audit server directory only
/vault-architecture server/routes.ts # Audit a single file
/vault-architecture --fix # Audit + suggest fixes
Read project.config.json from the project root. This file tells you:
If project.config.json does not exist, apply all patterns universally and note
that the project should create one.
Check the codebase against these four core patterns. Every project must follow all four.
// WHY: Polling wastes resources and creates race conditions. // The Observer pattern ensures consumers react to state changes immediately. // This matches UE5 DECLARE_DYNAMIC_MULTICAST_DELEGATE conventions.
Violations to detect:
| Anti-Pattern | What To Flag |
|---|---|
setInterval with fetch/query | Timer-based state polling |
refetchInterval in React Query | Polling disguised as "smart" refetch |
setTimeout + recursive fetch | Manual polling loop |
| Repeated GET requests on a timer | Network polling |
| Busy-wait loops | CPU-wasting state checks |
Correct patterns:
| Context | Pattern |
|---|---|
| Server → Client real-time | EventEmitter → SSE endpoint → EventSource |
| Cross-service communication | EventBus singleton with typed events |
| React state from server | SSE event → React Query cache invalidation |
| Component-to-component | React context, callback props, or custom hooks |
| UE5 equivalent | DECLARE_DYNAMIC_MULTICAST_DELEGATE |
Audit checklist:
setInterval, refetchInterval, setTimeout used for data fetching// WHY: Raw SQL or ORM calls scattered through route handlers create // maintenance nightmares and make it impossible to audit data access. // All database operations go through a single storage interface.
Violations to detect:
| Anti-Pattern | What To Flag |
|---|---|
db.select() in route handler | Direct ORM in business logic |
db.insert() outside storage | Scattered write operations |
| Raw SQL strings in routes | SQL outside repository layer |
| Inline query construction | Missing abstraction |
Correct pattern:
// All database access through a typed interface
// Route handlers call storage methods, never touch the database directly
interface IStorage {
getDocuments(): Promise<Document[]>;
createDocument(doc: InsertDocument): Promise<Document>;
// ... all database operations centralized here
}
// Route handler (correct)
app.get("/api/documents", async (req, res) => {
const docs = await storage.getDocuments(); // Repository call
res.json(docs);
});
// Route handler (VIOLATION)
app.get("/api/documents", async (req, res) => {
const docs = await db.select().from(documents); // Direct ORM call
res.json(docs);
});
Audit checklist:
// WHY: Hidden dependencies (global imports, singletons without interfaces) // make code untestable and tightly coupled. DI makes dependencies visible. // Manual DI via constructor injection is preferred at small-to-medium scale.
Violations to detect:
| Anti-Pattern | What To Flag |
|---|---|
import { db } from "../db" in 10 files | Hardcoded singleton dependency |
new Service() inside another service | Hidden construction |
| Global mutable state | Shared state without injection |
| Circular imports for shared state | Dependency cycle smell |
Correct pattern (manual DI):
// Dependencies injected through constructor or factory function
class ExtractionManager {
constructor(
private storage: IStorage,
private eventBus: ExtractionEventBus,
private downloadQueue: DownloadQueue
) {}
}
// Wiring happens at composition root (server/index.ts)
const storage = new DatabaseStorage(db);
const eventBus = ExtractionEventBus.getInstance();
const queue = new DownloadQueue();
const manager = new ExtractionManager(storage, eventBus, queue);
Audit checklist:
// WHY: Deep inheritance hierarchies create brittle, hard-to-modify code. // Prefer composing behaviors via interfaces, mixins, or strategy pattern. // Exception: React components extending base is fine (framework convention).
Violations to detect:
| Anti-Pattern | What To Flag |
|---|---|
class A extends B extends C | Deep inheritance chain |
super.method() called 3+ levels deep | Fragile base class |
| Abstract class with 10+ methods | God class via inheritance |
instanceof checks for branching | Type-switch smell |
Correct patterns:
| Instead Of | Use |
|---|---|
| Deep class hierarchy | Interface + composition |
| Abstract base with many methods | Small focused interfaces |
instanceof branching | Strategy pattern or polymorphism |
Mixins via extends | Functional composition |
Audit checklist:
extends and check inheritance depthsuper. calls — more than 2 levels is a smellinstanceof used for control flowBased on project.config.json, apply additional checks:
architecture.patterns includes "sse-push":transport.heartbeatInterval configarchitecture.patterns includes "event-bus":any)architecture.database is "sqlite":architecture.orm is "drizzle")security.localFirst is true:security.csp is trueGenerate a structured report:
## Architecture Audit Report
### Summary
- Files scanned: N
- Violations found: N
- Patterns checked: Observer, Repository, DI, Composition
### Violations
#### [PATTERN] Violation in file:line
**What**: Description of the violation
**Why it matters**: Impact on maintainability/security/performance
**Fix**: Specific code change to resolve
### Passing Checks
- [x] Observer pattern — no polling detected
- [x] Repository pattern — all DB access through storage
- [ ] DI pattern — 2 violations found
- [x] Composition — no deep inheritance
### Recommendations
1. Priority fixes (violations)
2. Improvement suggestions (not violations, but could be better)
In addition to architecture patterns, enforce these coding standards:
// Marcus Daley's coding standards — applies to ALL projects
| Rule | Check |
|---|---|
| Line comments only | Flag any /* */ or /** */ block comments |
| File headers | Every source file needs: // FileName / Developer: Marcus Daley / Date / Description |
| Function documentation | Every function needs // comment block: purpose, params, returns, usage |
| WHY not WHAT | Comments should explain design decisions, not restate code |
| No hardcoded gameplay types | Flag hardcoded enums that should be config-driven (UE5 rule, applies broadly) |
For detailed pattern guides: