一键导入
architecture-review
Use after implementing features to verify architecture compliance. Checks for layer violations, missing interfaces, and tight coupling.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Use after implementing features to verify architecture compliance. Checks for layer violations, missing interfaces, and tight coupling.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
识别业务能力并分类子域(Core/Supporting/Generic),产出核心域声明与所有权建议。
从不变量出发设计聚合边界:聚合根、实体、值对象、事务边界与跨聚合一致性策略。
映射限界上下文间的关系与集成策略:模式选择、契约所有权、失败模式与版本策略。
设计限界上下文及其通用语言:边界、职责、词汇表、团队所有权与边界 ADR。
协作式领域发现:通过事件风暴或领域故事讲述,产出事件流、命令/事件候选、热点与歧义清单。
设计构造块间的协作机制:领域事件、领域服务、仓储接口与工厂。
| name | architecture-review |
| description | Use after implementing features to verify architecture compliance. Checks for layer violations, missing interfaces, and tight coupling. |
Verify that implemented code follows the three-layer architecture with proper dependency injection. This skill catches violations before they become entrenched.
Run this after every feature implementation. Catching violations early prevents technical debt accumulation.
Use this skill when:
lib/domain/) MUST NOT import from lib/infra/ or lib/db/lib/container.ts, never directly from infraapp/ → Can import: lib/container.ts, lib/domain/**/types
lib/domain/ → Can import: lib/infra/interfaces/* (types only)
lib/infra/interfaces/ → Can import: lib/domain/**/entity types
lib/infra/db/ → Can import: lib/infra/interfaces/*, lib/domain/**/types
lib/infra/storage/ → Can import: lib/infra/interfaces/*
lib/container.ts → Can import: Everything (wires it all together)
Run these commands to detect violations:
# Domain importing from infra (VIOLATION)
grep -r "from.*infra" lib/domain/ 2>/dev/null
# Domain importing db directly (VIOLATION)
grep -r "from.*lib/db" lib/domain/ 2>/dev/null
grep -r "from.*\/db" lib/domain/ 2>/dev/null
# Domain importing drizzle (VIOLATION)
grep -r "drizzle-orm" lib/domain/ 2>/dev/null
# Domain importing external storage (VIOLATION)
grep -r "@vercel/blob" lib/domain/ 2>/dev/null
# UI importing infra directly (VIOLATION)
grep -r "from.*lib/infra" app/ 2>/dev/null
grep -r "from.*infra/db" app/ 2>/dev/null
# UI importing db directly (VIOLATION)
grep -r "from.*lib/db" app/ 2>/dev/null
Expected result: No matches. Any match is a violation that must be fixed.
Verify services use constructor injection:
# Find all service files
find lib/domain -name "*.service.ts" -type f
# For each service, verify:
# - Has constructor with interface parameters
# - Does NOT instantiate dependencies with 'new'
# - Does NOT import concrete implementations
Check each service for:
// ✅ GOOD: Constructor injection
export class SiteService {
constructor(
private repo: ISiteRepository, // Interface type
private storage: IStorageAdapter, // Interface type
) {}
}
// ❌ BAD: Direct instantiation
export class SiteService {
private repo = new DrizzleSiteRepository(); // VIOLATION
}
// ❌ BAD: Importing concrete class
import { DrizzleSiteRepository } from '../infra/db/site.repository'; // VIOLATION
Verify entity files have no side effects:
# Find all entity files
find lib/domain -name "*.entity.ts" -type f
# Check for violations in entity files:
grep -l "async" lib/domain/**/*.entity.ts 2>/dev/null # Should be empty
grep -l "await" lib/domain/**/*.entity.ts 2>/dev/null # Should be empty
grep -l "fetch" lib/domain/**/*.entity.ts 2>/dev/null # Should be empty
grep -l "import.*db" lib/domain/**/*.entity.ts 2>/dev/null # Should be empty
Entity files should contain ONLY:
Verify interfaces exist for all external dependencies:
# List interface files
ls lib/infra/interfaces/
# Expected: One interface per external dependency type
# - site.repository.ts (or combined {entity}.repository.ts)
# - storage.adapter.ts
# - email.adapter.ts
# - etc.
For each repository/adapter:
lib/infra/interfaces/lib/infra/{type}/Verify container properly wires dependencies:
# Check container file
cat lib/container.ts
Verify:
getSiteService(), etc.)createSiteService(mockRepo, mockStorage))Verify UI layer imports correctly:
# Find all imports from lib/ in app/
grep -rh "from.*@/lib" app/ | sort | uniq
# Should see:
# - from '@/lib/container' ✅ OK
# - from '@/lib/domain/.../types' ✅ OK (if just types)
# - from '@/lib/infra/...' ❌ VIOLATION
# - from '@/lib/db/...' ❌ VIOLATION
// ❌ In lib/domain/site/site.service.ts
import { db } from '../../db';
import { sites } from '../../db/schema';
// ✅ Fixed
import type { ISiteRepository } from '../../infra/interfaces/site.repository';
constructor(private repo: ISiteRepository) {}
// ❌ In lib/domain/site/site.entity.ts
export async function isSubdomainAvailable(subdomain: string): Promise<boolean> {
const existing = await db.select()... // VIOLATION: I/O in entity
}
// ✅ Fixed: Move to service
// In site.entity.ts - pure validation only
export function validateSubdomainFormat(subdomain: string): ValidationResult { }
// In site.service.ts - async checks
async createSite(input: CreateSiteInput) {
const formatResult = validateSubdomainFormat(input.subdomain);
if (!formatResult.valid) throw new SiteError(...);
const existing = await this.repo.findBySubdomain(input.subdomain);
if (existing) throw new SiteError('SUBDOMAIN_TAKEN', ...);
}
// ❌ In lib/domain/site/site.service.ts
export class SiteService {
private repo = new DrizzleSiteRepository(); // VIOLATION
private storage = new VercelBlobAdapter(); // VIOLATION
}
// ✅ Fixed: Constructor injection
export class SiteService {
constructor(
private repo: ISiteRepository,
private storage: IStorageAdapter,
) {}
}
// ❌ In app/(dashboard)/sites/new/actions.ts
import { createSite } from '@/lib/infra/db/site.repository';
// ✅ Fixed: Import from container
import { getSiteService } from '@/lib/container';
const service = getSiteService();
await service.createSite(...);
// ❌ Service depends on concrete class
import { DrizzleSiteRepository } from '../../infra/db/site.repository';
export class SiteService {
constructor(private repo: DrizzleSiteRepository) {} // Concrete type!
}
// ✅ Fixed: Depend on interface
import type { ISiteRepository } from '../../infra/interfaces/site.repository';
export class SiteService {
constructor(private repo: ISiteRepository) {} // Interface type
}
After running the review, document findings:
## Architecture Review - [Feature/Date]
### Layer Violations
- [ ] Domain → Infra imports: None / [List violations]
- [ ] Domain → DB imports: None / [List violations]
- [ ] UI → Infra imports: None / [List violations]
### Dependency Injection
- [ ] All services use constructor injection: Yes / [List violations]
- [ ] No direct instantiation in services: Yes / [List violations]
### Entity Purity
- [ ] No async in entity files: Yes / [List violations]
- [ ] No I/O in entity files: Yes / [List violations]
### Interface Coverage
- [ ] All repositories have interfaces: Yes / [List missing]
- [ ] All adapters have interfaces: Yes / [List missing]
### Container
- [ ] All services wired in container: Yes / [List missing]
- [ ] Test factories available: Yes / No
### Actions Required
1. [Action item 1]
2. [Action item 2]
Create this script for quick reviews:
#!/bin/bash
# save as: scripts/architecture-review.sh
echo "=== Architecture Review ==="
echo ""
echo "1. Checking domain → infra imports..."
DOMAIN_INFRA=$(grep -r "from.*infra" lib/domain/ 2>/dev/null | grep -v ".test.ts")
if [ -n "$DOMAIN_INFRA" ]; then
echo "❌ VIOLATION: Domain imports from infra"
echo "$DOMAIN_INFRA"
else
echo "✅ No domain → infra imports"
fi
echo ""
echo "2. Checking domain → db imports..."
DOMAIN_DB=$(grep -r "from.*\/db" lib/domain/ 2>/dev/null | grep -v ".test.ts")
if [ -n "$DOMAIN_DB" ]; then
echo "❌ VIOLATION: Domain imports from db"
echo "$DOMAIN_DB"
else
echo "✅ No domain → db imports"
fi
echo ""
echo "3. Checking UI → infra imports..."
UI_INFRA=$(grep -r "from.*lib/infra" app/ 2>/dev/null)
if [ -n "$UI_INFRA" ]; then
echo "❌ VIOLATION: UI imports from infra"
echo "$UI_INFRA"
else
echo "✅ No UI → infra imports"
fi
echo ""
echo "4. Checking for async in entity files..."
ASYNC_ENTITY=$(grep -l "async\|await" lib/domain/**/*.entity.ts 2>/dev/null)
if [ -n "$ASYNC_ENTITY" ]; then
echo "❌ VIOLATION: Async found in entity files"
echo "$ASYNC_ENTITY"
else
echo "✅ No async in entity files"
fi
echo ""
echo "5. Checking for direct instantiation in services..."
DIRECT_NEW=$(grep -r "new.*Repository\|new.*Adapter" lib/domain/ 2>/dev/null | grep -v ".test.ts")
if [ -n "$DIRECT_NEW" ]; then
echo "❌ VIOLATION: Direct instantiation in services"
echo "$DIRECT_NEW"
else
echo "✅ No direct instantiation in services"
fi
echo ""
echo "=== Review Complete ==="
Without architecture reviews:
With regular reviews: