BlockRun lib Architecture Refactor Plan
For Claude: REQUIRED SUB-SKILL: Use superpowers
to implement this plan task-by-task.
Goal: Reorganize the 126-file flat lib/ structure into 7 domain-based subdirectories, split oversized files (ai-providers 4.8K LOC, gcs-logger 823 LOC), and consolidate type definitions for improved maintainability and discoverability.
Architecture: Move from a flat, monolithic lib/ directory to a domain-driven organization where related functionality (providers, payment, logging, blockchain, etc.) lives together. Each domain has its own index.ts barrel export and types.ts file. This preserves all functionality while dramatically improving cognitive load and file discovery.
Tech Stack: Next.js 16, TypeScript, vitest, Node.js
Current State
- 126 files in
lib/(flat structure) - ai-providers.ts at 4,885 LOC (dispatcher + provider adapters mixed)
- gcs-logger.ts at 823 LOC (logging + metrics combined)
- Scattered domains: Payment files (x402, treasury, allowlists) spread across root
- No type consolidation: Types buried in implementation files
- Import complexity: Routes import from multiple files per concern
Target State
lib/
├── providers/ # LLM routing + adapters (split from ai-providers)
├── payment/ # x402 settlement (consolidated)
├── optimization/ # Context compression
├── observability/ # Logging, health, analytics
├── blockchain/ # Chains, RPC, wallets
├── common/ # Cross-cutting utils
├── middleware/ # Rate-limiting, identity injection
└── [~20 single-purpose files] # Focused utilities (stay in root)
Phase 1: Directory Setup & Type Consolidation
Task 1.1: Create Domain Directories
Files:
- Create:
lib/providers/ - Create:
lib/payment/ - Create:
lib/optimization/ - Create:
lib/observability/ - Create:
lib/blockchain/ - Create:
lib/common/ - Create:
lib/middleware/
Step 1: Create directories
cd /Users/vickyfu/Documents/blockrun-web/blockrun
mkdir -p lib/{providers,payment,optimization,observability,blockchain,common,middleware}
Step 2: Verify directories exist
ls -la lib/ | grep "^d"
Expected output:
drwxr-xr-x ... common
drwxr-xr-x ... middleware
drwxr-xr-x ... observability
drwxr-xr-x ... optimization
drwxr-xr-x ... payment
drwxr-xr-x ... blockchain
drwxr-xr-x ... providers
Step 3: Commit
git add -A
git commit -m "refactor(lib): create domain-based directory structure"
Task 1.2: Create Provider Domain Types
Files:
- Create:
lib/providers/types.ts - Reference: Current
lib/models.ts(extract types)
Step 1: Extract type definitions from models.ts
Read the current lib/models.ts to identify types:
ModelinterfaceImageModel,AudioModel,VideoModel, etc.BillingModetypeNetworkTypetype- Pricing-related types
Step 2: Create lib/providers/types.ts
// lib/providers/types.ts
export interface Model {
id: string
name: string
provider: string
type: 'chat' | 'image' | 'audio' | 'video'
pricing: {
input: number
output: number
}
hidden?: boolean
fallbackModel?: string
capabilities: string[]
}
export interface ImageModel {
id: string
name: string
provider: string
pricing: {
per_image: number
}
maxResolution: string
}
export interface AudioModel {
id: string
name: string
provider: string
type: 'speech' | 'music' | 'soundfx'
pricing: {
per_request: number
}
}
export interface VideoModel {
id: string
name: string
provider: string
pricing: {
per_second: number
}
maxDuration: number
}
export type BillingMode = 'free' | 'paid' | 'flat'
export type NetworkType = 'mainnet' | 'testnet'
export interface ModelHealth {
isHealthy: boolean
lastChecked: Date
successRate: number
}
export interface ProviderConfig {
name: string
apiKey?: string
baseUrl?: string
timeout?: number
}
Step 3: Verify file exists
cat lib/providers/types.ts | head -20
Step 4: Run type check
npm run type-check 2>&1 | head -30
Expected: May have errors at this point (imports not updated yet).
Step 5: Commit
git add lib/providers/types.ts
git commit -m "feat(providers): create domain types file"
Task 1.3: Create Payment Domain Types
Files:
- Create:
lib/payment/types.ts - Reference: Current
lib/x402.ts,lib/onchain-settle.ts
Step 1: Extract payment types
From lib/x402.ts, identify:
PaymentRequirementinterfaceVerifyPaymentResulttypeSettlementResulttype
Step 2: Create lib/payment/types.ts
// lib/payment/types.ts
export interface PaymentRequirement {
resource: string
amount: bigint
currency: 'USDC' | 'SOL' | 'ETH'
chainId: number
payTo: string
expires: number
nonce: string
}
export interface VerifyPaymentResult {
valid: boolean
payer: string
signature: string
timestamp: number
message?: string
}
export interface SettlementResult {
success: boolean
txHash?: string
error?: string
retryable: boolean
}
export interface EnterpriseAllowlist {
wallet: string
provider: string
asyncSettle?: boolean
}
export interface PayerDenylist {
wallet: string
reason: string
blockedAt: Date
}
export interface TreasuryConfig {
baseWallet: string
solanaWallet: string
supportedChains: number[]
}
Step 3: Verify file exists and check structure
cat lib/payment/types.ts | wc -l
Step 4: Commit
git add lib/payment/types.ts
git commit -m "feat(payment): create domain types file"
Task 1.4: Create Observability Domain Types
Files:
- Create:
lib/observability/types.ts - Reference:
lib/types/health.ts,lib/gcs-logger.ts
Step 1: Create lib/observability/types.ts
// lib/observability/types.ts
export type HealthStatus = 'healthy' | 'degraded' | 'unhealthy'
export interface ModelHealth {
modelId: string
provider: string
status: HealthStatus
lastChecked: Date
successCount: number
failureCount: number
successRate: number
}
export interface ProviderHealth {
provider: string
status: HealthStatus
lastChecked: Date
models: ModelHealth[]
}
export interface SystemHealth {
status: HealthStatus
providers: ProviderHealth[]
timestamp: Date
}
export interface LogEntry {
timestamp: Date
modelId: string
provider: string
inputTokens: number
outputTokens: number
cost: number
wallet: string
txHash?: string
}
export interface MetricSnapshot {
recentCalls: LogEntry[]
successCount: number
errorCount: number
totalCost: number
}
Step 2: Verify file exists
cat lib/observability/types.ts | head -15
Step 3: Commit
git add lib/observability/types.ts
git commit -m "feat(observability): create domain types file"
Task 1.5: Create Blockchain Domain Types
Files:
- Create:
lib/blockchain/types.ts - Reference:
lib/network-config.ts,lib/wallet-recon.ts
Step 1: Create lib/blockchain/types.ts
// lib/blockchain/types.ts
export interface NetworkConfig {
name: string
chainId: number
rpcUrl: string
explorerUrl: string
nativeCurrency: string
}
export interface WalletActivity {
wallet: string
timestamp: Date
txHash: string
amount: string
type: 'send' | 'receive'
token: string
}
export interface WalletReconRecord {
wallet: string
totalSpent: number
totalReceived: number
balance: number
lastUpdated: Date
}
export interface ChainPrice {
symbol: string
price: number
timestamp: Date
source: string
}
export interface PythPriceData {
symbol: string
price: number
confidence: number
exponent: number
}
Step 2: Verify file exists
cat lib/blockchain/types.ts | head -10
Step 3: Commit
git add lib/blockchain/types.ts
git commit -m "feat(blockchain): create domain types file"
Task 1.6: Create Common & Middleware Types
Files:
- Create:
lib/common/types.ts - Create:
lib/middleware/types.ts
Step 1: Create lib/common/types.ts
// lib/common/types.ts
export interface RequestContext {
ip: string
userAgent: string
clientId?: string
wallet?: string
}
export interface CacheEntry<T> {
value: T
timestamp: Date
ttl: number
}
export type ConfigValue = string | number | boolean | string[]
export interface Config {
[key: string]: ConfigValue
}
Step 2: Create lib/middleware/types.ts
// lib/middleware/types.ts
export interface RateLimitBucket {
ip: string
requests: number
resetAt: Date
}
export interface IdentityContext {
wallet: string
isEnterprise: boolean
isDenied: boolean
}
export interface DiscoveryEntry {
service: string
url: string
cached: boolean
lastFetch: Date
}
Step 3: Verify both files
ls -lh lib/{common,middleware}/types.ts
Step 4: Commit
git add lib/common/types.ts lib/middleware/types.ts
git commit -m "feat(common,middleware): create domain types files"
Task 1.7: Create Domain Index Files (Barrel Exports)
Files:
- Create:
lib/providers/index.ts - Create:
lib/payment/index.ts - Create:
lib/optimization/index.ts - Create:
lib/observability/index.ts - Create:
lib/blockchain/index.ts - Create:
lib/common/index.ts - Create:
lib/middleware/index.ts
Step 1: Create minimal index files with re-exports (we'll populate later)
cat > lib/providers/index.ts << 'EOF'
// lib/providers/index.ts
// Re-exports will be added as we move provider adapters
export * from './types'
// export { callAIProvider, streamAIProvider } from './index' // TODO
EOF
cat > lib/payment/index.ts << 'EOF'
// lib/payment/index.ts
// Re-exports will be added as we move payment logic
export * from './types'
// export { verifyPayment, settlePayment } from './index' // TODO
EOF
cat > lib/optimization/index.ts << 'EOF'
// lib/optimization/index.ts
export * from './types'
// export { compressContext } from './index' // TODO
EOF
cat > lib/observability/index.ts << 'EOF'
// lib/observability/index.ts
export * from './types'
// export { recordCall, recordHealth } from './index' // TODO
EOF
cat > lib/blockchain/index.ts << 'EOF'
// lib/blockchain/index.ts
export * from './types'
// export { getNetworkConfig, reconcileWallet } from './index' // TODO
EOF
cat > lib/common/index.ts << 'EOF'
// lib/common/index.ts
export * from './types'
// export { formatAddress, parseConfig } from './index' // TODO
EOF
cat > lib/middleware/index.ts << 'EOF'
// lib/middleware/index.ts
export * from './types'
// export { checkRateLimit, injectIdentity } from './index' // TODO
EOF
Step 2: Verify all index files exist
ls -lh lib/*/index.ts
Expected:
-rw-r--r-- ... lib/blockchain/index.ts
-rw-r--r-- ... lib/common/index.ts
-rw-r--r-- ... lib/middleware/index.ts
-rw-r--r-- ... lib/observability/index.ts
-rw-r--r-- ... lib/optimization/index.ts
-rw-r--r-- ... lib/payment/index.ts
-rw-r--r-- ... lib/providers/index.ts
Step 3: Commit
git add lib/*/index.ts
git commit -m "feat(lib): create domain index files with type re-exports"
Task 1.8: Verify No Breakage Yet
Files:
- All API routes should still work (imports unchanged)
- Tests should pass (no moved code yet)
Step 1: Run type check
npm run type-check 2>&1 | grep -i error | head -20
Expected: Some "Cannot find module" errors for moved files (expected, we'll fix in phases 2-6).
Step 2: Run tests (should still pass)
npm run test 2>&1 | tail -20
Expected: Tests pass, no regressions (we haven't moved code yet).
Step 3: Commit progress
git add -A
git commit -m "refactor(lib): phase 1 complete - domain structure ready"
Phase 2: Split Provider Domain (ai-providers.ts)
This is the largest single file (4.8K LOC) — split into focused adapters
Task 2.1: Create Anthropic Adapter
Files:
- Create:
lib/providers/adapters/anthropic.ts - Reference: Extract from
lib/ai-providers.ts(provider === 'anthropic')
Step 1: Identify all anthropic-related code in ai-providers.ts
grep -n "provider === 'anthropic'" lib/ai-providers.ts | head -5
Step 2: Create lib/providers/adapters/anthropic.ts
// lib/providers/adapters/anthropic.ts
import { Anthropic } from '@anthropic-ai/sdk'
import { Message, MessageParam } from '@anthropic-ai/sdk/resources'
interface CallAnthropicOptions {
model: string
messages: MessageParam[]
maxTokens?: number
temperature?: number
tools?: any[]
systemPrompt?: string
}
export async function callAnthropic(
options: CallAnthropicOptions
): Promise<Message> {
const client = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
})
const response = await client.messages.create({
model: options.model,
max_tokens: options.maxTokens || 2048,
temperature: options.temperature,
system: options.systemPrompt,
messages: options.messages,
tools: options.tools,
})
return response
}
export async function* streamAnthropic(
options: CallAnthropicOptions
): AsyncGenerator<any> {
const client = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
})
const stream = client.messages.stream({
model: options.model,
max_tokens: options.maxTokens || 2048,
temperature: options.temperature,
system: options.systemPrompt,
messages: options.messages,
tools: options.tools,
})
for await (const chunk of stream) {
yield chunk
}
}
Step 3: Verify file exists and has correct structure
head -30 lib/providers/adapters/anthropic.ts
Step 4: Commit
git add lib/providers/adapters/anthropic.ts
git commit -m "feat(providers): extract anthropic adapter from ai-providers"
Task 2.2-2.6: Create Other Provider Adapters
Repeat the pattern for OpenAI, Azure, Bedrock, Gemini adapters (similar to Task 2.1)
For brevity, here's the command to create all stub adapters:
for adapter in openai azure bedrock gemini partners; do
cat > lib/providers/adapters/${adapter}.ts << 'EOF'
// lib/providers/adapters/${adapter}.ts
// TODO: Extract ${adapter}-specific logic from ai-providers.ts
export async function call${adapter^}(options: any) {
throw new Error('Not yet implemented')
}
export async function* stream${adapter^}(options: any): AsyncGenerator<any> {
throw new Error('Not yet implemented')
}
EOF
done
Then fill each file with extracted logic from current lib/ai-providers.ts.
Step 1: Create stub files
mkdir -p lib/providers/adapters
for adapter in openai azure bedrock gemini partners; do
touch lib/providers/adapters/${adapter}.ts
done
ls -lh lib/providers/adapters/
Step 2: Commit stubs
git add lib/providers/adapters/
git commit -m "feat(providers): create adapter stubs (openai, azure, bedrock, gemini, partners)"
Task 2.3: Move Streaming Logic to lib/providers/streaming.ts
Files:
- Create:
lib/providers/streaming.ts - Reference: Extract from
lib/ai-stream.ts
Step 1: Copy ai-stream.ts to streaming.ts
cp lib/ai-stream.ts lib/providers/streaming.ts
Step 2: Update imports in streaming.ts (fix relative paths)
sed -i "s|from '\./|from '../|g" lib/providers/streaming.ts
Step 3: Verify file exists
head -20 lib/providers/streaming.ts
Step 4: Commit
git add lib/providers/streaming.ts
git commit -m "refactor(providers): move ai-stream to providers/streaming.ts"
Task 2.4: Move Models to lib/providers/models.ts
Files:
- Create:
lib/providers/models.ts - Source: Copy from
lib/models.ts
Step 1: Copy models.ts
cp lib/models.ts lib/providers/models.ts
Step 2: Update imports in providers/models.ts
sed -i "s|from '\./|from '../|g" lib/providers/models.ts
sed -i "s|from '\./types|from './types|g" lib/providers/models.ts
Step 3: Verify
head -30 lib/providers/models.ts
Step 4: Commit
git add lib/providers/models.ts
git commit -m "refactor(providers): move models to providers/models.ts"
Task 2.5: Create lib/providers/index.ts Dispatcher
Files:
- Create:
lib/providers/index.ts(main dispatcher)
Step 1: Create dispatcher that routes to adapters
// lib/providers/index.ts
export * from './types'
export * from './models'
export * from './streaming'
import { callAnthropic } from './adapters/anthropic'
// import { callOpenAI } from './adapters/openai' // TODO
// ... (other adapters)
export async function callAIProvider(model: string, messages: any[], options?: any) {
const provider = getProviderForModel(model)
switch (provider) {
case 'anthropic':
return callAnthropic({ model, messages, ...options })
// case 'openai':
// return callOpenAI({ model, messages, ...options })
// ... (other providers)
default:
throw new Error(`Unknown provider: ${provider}`)
}
}
export async function* streamAIProvider(
model: string,
messages: any[],
options?: any
): AsyncGenerator<any> {
const provider = getProviderForModel(model)
switch (provider) {
case 'anthropic':
yield* streamAnthropic({ model, messages, ...options })
break
// case 'openai':
// yield* streamOpenAI({ model, messages, ...options })
// break
// ... (other providers)
default:
throw new Error(`Unknown provider: ${provider}`)
}
}
function getProviderForModel(model: string): string {
// TODO: Extract from current ai-providers.ts MODEL_MAP
if (model.startsWith('claude')) return 'anthropic'
if (model.startsWith('gpt')) return 'openai'
// ... (etc)
return 'unknown'
}
Step 2: Verify file
head -50 lib/providers/index.ts
Step 3: Commit
git add lib/providers/index.ts
git commit -m "feat(providers): create main dispatcher in index.ts"
Task 2.6: Update Routes to Use New Provider Structure
Files:
- Modify:
src/app/api/v1/chat/completions/route.ts - Modify:
src/app/api/v1/images/generations/route.ts - Modify:
src/app/api/v1/videos/generations/route.ts - (any other routes importing from ai-providers)
Step 1: Find all routes using ai-providers
grep -r "from '@/lib/ai-providers" src/app/api --include="*.ts"
Step 2: Update first route (chat/completions)
Replace:
import { callAIProvider, streamAIProvider } from '@/lib/ai-providers'
With:
import { callAIProvider, streamAIProvider } from '@/lib/providers'
Step 3: Update all routes with same import
find src/app/api -name "route.ts" -type f -exec sed -i "s|from '@/lib/ai-providers|from '@/lib/providers|g" {} \;
Step 4: Run tests
npm run test -- src/app/api/v1/chat/completions/route.test.ts 2>&1 | tail -30
Expected: Tests should pass with new import structure.
Step 5: Commit
git add src/app/api
git commit -m "refactor: update routes to import from lib/providers"
Task 2.7: Verify Phase 2 Complete
Step 1: Type check
npm run type-check 2>&1 | grep -c error
Expected: Should have fewer errors than before (provider imports work).
Step 2: Run affected tests
npm run test -- route.test.ts 2>&1 | tail -20
Expected: All tests pass.
Step 3: Live-test chat endpoint
# Start dev server in background
npm run dev &
sleep 3
# Test chat endpoint
curl -X POST http://localhost:3000/api/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"gpt-4o","messages":[{"role":"user","content":"hi"}]}'
# Kill dev server
kill %1
Expected: Returns valid response (may fail auth, but endpoint works).
Step 4: Commit
git add -A
git commit -m "refactor(lib): phase 2 complete - provider domain organized"
Phase 3: Consolidate Payment Domain
Follow similar pattern to Phase 2 (extract functions into domain)
Task 3.1-3.5: Move Payment Files
Summary:
- Extract x402 verification →
lib/payment/verification.ts - Extract settlement logic →
lib/payment/settlement.ts - Move treasury →
lib/payment/treasury.ts - Consolidate allowlists →
lib/payment/allowlists.ts - Create dispatcher →
lib/payment/index.ts
Process (same as Phase 2):
- Copy files to payment/
- Update imports
- Create domain/index.ts dispatcher
- Update all routes to use new imports
- Test
- Commit
Phase 4-6: Organize Remaining Domains
Follow same pattern as Phases 2-3 for:
- Phase 4: Observability (logging, health, analytics)
- Phase 5: Blockchain (networks, RPC, wallets, data)
- Phase 6: Optimization, Common, Middleware
Each phase: extract functions → create domain files → dispatcher index → update imports → test → commit
Phase 7-9: Bulk Import Updates & Cleanup
Task 7.1: Generate Import Update Script
# Find all files importing from old lib files
grep -r "from '@/lib/" src --include="*.ts" --include="*.tsx" | \
grep -v "from '@/lib/providers" | \
grep -v "from '@/lib/payment" | \
cut -d: -f1 | sort -u > /tmp/files-to-update.txt
wc -l /tmp/files-to-update.txt # Should be ~71 routes + 52 components = ~120 files
Task 7.2: Batch Update Imports
# Replace old import paths with new ones
sed -i "s|from '@/lib/ai-providers|from '@/lib/providers|g" $(cat /tmp/files-to-update.txt)
sed -i "s|from '@/lib/x402|from '@/lib/payment|g" $(cat /tmp/files-to-update.txt)
sed -i "s|from '@/lib/gcs-logger|from '@/lib/observability/logging|g" $(cat /tmp/files-to-update.txt)
# ... (repeat for all moved files)
Task 7.3: Delete Old Files
# Verify all files have been moved before deleting
diff <(ls lib/*.ts | sort) <(find lib -maxdepth 1 -name "*.ts" | sort)
# Delete old flat structure
rm lib/ai-providers.ts lib/x402.ts lib/gcs-logger.ts lib/ai-stream.ts lib/models.ts
# ... (etc for all moved files)
Phase 10: Code Review & Documentation
Task 10.1: Create ARCHITECTURE.md
# BlockRun lib Architecture
## Structure
lib/ is organized into 7 domain-based modules:
### 1. providers/
LLM provider routing and adapters.
- `index.ts` - Main dispatcher (callAIProvider, streamAIProvider)
- `adapters/` - Provider-specific implementations
- `models.ts` - Model catalog and pricing
- `streaming.ts` - Streaming response handling
### 2. payment/
x402 payment protocol and settlement.
- `index.ts` - Main entry point
- `verification.ts` - Payment verification
- `settlement.ts` - On-chain settlement
- `allowlists.ts` - Enterprise/denylist management
- `treasury.ts` - Treasury wallet management
### 3. observability/
Logging, analytics, and health monitoring.
- `logging.ts` - GCS logging
- `analytics.ts` - BigQuery analytics
- `health.ts` - Health aggregation and circuit breakers
- `metrics.ts` - In-memory metrics
### 4. blockchain/
Blockchain RPC, wallets, and on-chain data.
- `networks.ts` - Network configuration
- `rpc.ts` - Multi-chain RPC routing
- `wallets.ts` - Wallet reconciliation
- `data.ts` - Price feeds, DeFi data
### 5. optimization/
Context compression and cost optimization.
- `index.ts` - Compression orchestrator
- `layers.ts` - 7-layer compression pipeline
- `codebook.ts` - Encoding dictionaries
### 6. common/
Cross-cutting utilities and helpers.
- `utils.ts` - General utilities
- `config.ts` - Runtime configuration
- `storage.ts` - Storage helpers
### 7. middleware/
Request processing and middleware.
- `rate-limit.ts` - Rate limiting
- `identity.ts` - Request identity enrichment
- `discovery.ts` - Service discovery
## Import Example
```typescript
// Before refactor
import { callAIProvider } from '@/lib/ai-providers'
import { verifyPayment } from '@/lib/x402'
import { recordCall } from '@/lib/gcs-logger'
// After refactor
import { callAIProvider } from '@/lib/providers'
import { verifyPayment } from '@/lib/payment'
import { recordCall } from '@/lib/observability/logging'
Benefits
- Clear separation of concerns - Each domain has a single responsibility
- Easier navigation - Related files grouped together
- Better type organization - Types.ts file per domain
- Reduced cognitive load - Fewer files to understand per task
- Scalability - Easy to add new sub-domains as needed
---
## Testing Strategy
**After Each Phase:**
1. **Type Check**
```bash
npm run type-check
-
Unit Tests
npm run test -- "phase-X" 2>&1 | tail -30 -
Live Test (after imports updated)
npm run dev & sleep 3 # Test key endpoints curl http://localhost:3000/api/v1/chat/completions curl http://localhost:3000/api/v1/images/generations curl http://localhost:3000/api/health kill %1 -
Code Review
/code-review medium
Success Criteria
✅ After complete refactor:
- All 126 lib files organized into 7 domain subdirectories
- ai-providers.ts (4.8K LOC) split into <1000 LOC per adapter
- gcs-logger.ts (823 LOC) split into logging.ts + metrics.ts
- All types consolidated into domain/types.ts files
- No cyclic imports
- All 71 routes pass tests
- All 52 components render without errors
- Zero runtime regressions
- ARCHITECTURE.md documenting new structure
- Code review approval (no maintainability issues)
Rollback Plan
If issues arise at any phase:
- Use
git revertto undo commits from that phase - Keep old lib/ structure in a backup branch
- Tests will catch most issues immediately
Estimated Timeline
- Phase 1 (Setup & Types): 1-2 days
- Phase 2 (Provider split): 2-3 days
- Phase 3 (Payment): 1-2 days
- Phase 4 (Observability): 1-2 days
- Phase 5 (Blockchain): 1 day
- Phase 6 (Remaining): 1 day
- Phase 7 (Import updates): 1 day
- Phase 8 (Component imports): 1 day
- Phase 9 (Cleanup): 1 day
- Phase 10 (Docs & review): 1 day
Total: 12-18 days (can be accelerated with parallel execution)