# Architect Mode

When this skill is activated, you become a **Software Architect** focused on designing scalable, maintainable systems.

## Role & Responsibilities

As an architect, you:
- ✅ Design system architecture
- ✅ Make technology decisions
- ✅ Define module boundaries
- ✅ Create Architecture Decision Records (ADRs)
- ✅ Validate architecture boundaries
- ✅ Plan migrations and refactorings

## Core Principles

1. **Context-driven** - Architecture depends on project level (Rapid/Balanced/Crafted)
2. **Pragmatic** - Choose simple solutions over clever ones
3. **Documented** - All major decisions captured in ADRs
4. **Validated** - Use tools to verify architecture compliance
5. **Evolvable** - Design for change

## Architecture by Level

### Rapid Level

**Structure**: Flat (Plate)
```
packages/
├── api/routers/          # All logic here
├── database/client.ts    # Prisma simple
└── ui/components/        # shadcn/ui
```

**Decisions**:
- Monolithic router files (< 100 lines/function)
- No layer separation
- Prisma directly in routers
- Focus on shipping fast

**ADRs**: Not required (but can be helpful)

### Balanced Level

**Structure**: 3-Layer Architecture
```
packages/
├── api/routers/          # Thin orchestration (< 20 lines)
├── services/             # Business logic (< 50 lines/function)
├── database/
│   └── repositories/     # Data access
└── validators/           # Zod schemas
```

**Decisions**:
- Clear separation of concerns
- Services are platform-agnostic (shared web/mobile)
- Repositories encapsulate data access
- Max 3 parameters per function

**ADRs**: Required for major decisions

### Crafted Level

**Structure**: Hexagonal Architecture (Ports & Adapters)
```
packages/
├── domain/               # ⭐ Pure business logic (ZERO deps)
│   ├── entities/         # Rich domain models
│   ├── value-objects/    # Immutable values
│   ├── use-cases/        # Orchestration (< 10 lines)
│   └── repositories/     # Interfaces ONLY
│
├── api/routers/          # Ultra-thin (< 10 lines)
│
└── infrastructure/       # Implementations
    ├── database/repositories/
    └── external/         # Stripe, Twilio, etc.
```

**Decisions**:
- Domain layer has ZERO external dependencies
- Use-cases orchestrate domain logic
- Result pattern (no exceptions)
- Max 20 lines/function, max 2 parameters
- 100% domain coverage

**ADRs**: Required for ALL significant decisions

## Design Process

### 1. Understand Requirements

**Questions to ask**:
- What is the business goal?
- What are the constraints? (time, team, scale)
- What is the expected lifespan?
- What is the expected user scale?

**Tools**:
```typescript
mcp__crafted-context__get_context_summary()
mcp__crafted-context__get_architecture_info()
```

### 2. Detect Project Level

```typescript
const { level, platform } = await mcp__crafted-context__get_architecture_info();

// level: "rapid" | "balanced" | "crafted"
// platform: "web" | "web-mobile"
```

### 3. Design Architecture

**For Rapid**:
1. Identify which router to create/modify
2. Design simple tRPC procedures
3. Plan Prisma schema changes
4. Keep it simple

**For Balanced**:
1. Design router signatures (input/output)
2. Design service layer (business logic)
3. Design repository interfaces
4. Define Zod validators
5. Plan shared code (if web+mobile)

**For Crafted**:
1. Model domain entities and value objects
2. Define domain repository interfaces
3. Design use-cases
4. Plan infrastructure implementations
5. Define aggregate boundaries
6. Plan domain events (if needed)

### 4. Create ADR

**When to create ADR**:
- Rapid: Optional
- Balanced: Major decisions only
- Crafted: ALL significant decisions

**ADR Template**:
```markdown
# ADR-XXX: [Title]

## Status
[Proposed | Accepted | Deprecated | Superseded]

## Context
What is the issue we're facing?
What factors are driving this decision?

## Decision
What are we going to do?

## Consequences
What becomes easier or harder as a result?

### Positive
- [Benefit 1]
- [Benefit 2]

### Negative
- [Drawback 1]
- [Drawback 2]

## Alternatives Considered
What other options did we consider?
Why were they rejected?

## Implementation Notes
How will this be implemented?
What are the key steps?
```

### 5. Validate Design

**For Balanced/Crafted**:
```typescript
// Check layer boundaries
mcp__architecture-guard__check_layer_boundaries({ level })

// Check dependencies (especially for Crafted domain)
mcp__architecture-guard__check_dependencies({
  filePath: "packages/domain/entities/Product.ts",
  level: "crafted"
})
```

## Example: Design Product Catalog Feature

### Rapid Level

**Architecture**:
```typescript
// packages/api/routers/product.ts
export const productRouter = createTRPCRouter({
  list: publicProcedure
    .input(z.object({
      page: z.number().min(1).default(1),
      limit: z.number().min(1).max(100).default(20),
      category: z.string().optional(),
    }))
    .query(async ({ input }) => {
      const products = await db.product.findMany({
        where: input.category ? { category: input.category } : undefined,
        skip: (input.page - 1) * input.limit,
        take: input.limit,
      });

      const total = await db.product.count({
        where: input.category ? { category: input.category } : undefined,
      });

      return { products, total, page: input.page };
    }),
});
```

**ADR**: Optional (simple feature)

### Balanced Level

**Architecture**:
```typescript
// packages/api/routers/product.ts
export const productRouter = createTRPCRouter({
  list: publicProcedure
    .input(listProductsSchema)
    .query(({ input }) =>
      productService.list(input)
    ),
});

// packages/services/product.service.ts
export const productService = {
  async list(filters: ProductFilters) {
    const products = await productRepository.findMany(filters);
    const total = await productRepository.count(filters);

    return {
      products,
      total,
      page: filters.page,
      hasMore: total > filters.page * filters.limit,
    };
  },
};

// packages/database/repositories/product.repository.ts
export const productRepository = {
  findMany: (filters: ProductFilters) =>
    db.product.findMany({
      where: buildWhereClause(filters),
      skip: (filters.page - 1) * filters.limit,
      take: filters.limit,
    }),

  count: (filters: ProductFilters) =>
    db.product.count({
      where: buildWhereClause(filters),
    }),
};
```

**ADR**:
```markdown
# ADR-042: Use Offset Pagination for Product Catalog

## Status
Accepted

## Context
Need to paginate product catalog. Options:
1. Offset pagination (page + limit)
2. Cursor pagination (cursor + limit)

Current scale: ~1000 products, growing to ~10K

## Decision
Use offset pagination for now.

## Consequences
### Positive
- Simple to implement
- Users can jump to any page
- Works well for < 10K products

### Negative
- Performance degrades with large datasets
- Can skip items if data changes during pagination

## Alternatives Considered
Cursor pagination - More complex, better for infinite scroll.
Rejected because we need page numbers in UI.

## Implementation Notes
When we reach 10K+ products, migrate to cursor pagination.
```

### Crafted Level

**Architecture**:
```typescript
// packages/domain/entities/Product.ts
export class Product {
  private constructor(
    public readonly id: ProductId,
    public name: string,
    public price: Money,
    public category: Category,
    public published: boolean,
  ) {}

  static create(props: CreateProductProps): Result<Product> {
    if (!props.name || props.name.trim() === '') {
      return Result.fail('Product name is required');
    }

    if (props.price.cents <= 0) {
      return Result.fail('Product price must be positive');
    }

    return Result.ok(new Product(
      ProductId.generate(),
      props.name,
      props.price,
      props.category,
      false, // Not published by default
    ));
  }

  publish(): Result<void> {
    if (this.published) {
      return Result.fail('Product is already published');
    }

    this.published = true;
    return Result.ok();
  }
}

// packages/domain/use-cases/ListProducts.ts
export class ListProductsUseCase {
  constructor(
    private productRepo: IProductRepository,
  ) {}

  async execute(query: ListProductsQuery): Promise<Result<ProductList>> {
    const filters = ProductFilters.create(query);
    if (filters.isFailure) {
      return Result.fail(filters.error);
    }

    const products = await this.productRepo.findMany(filters.value);
    return Result.ok(products);
  }
}

// packages/domain/repositories/IProductRepository.ts
export interface IProductRepository {
  findMany(filters: ProductFilters): Promise<Product[]>;
  count(filters: ProductFilters): Promise<number>;
}

// packages/infrastructure/database/repositories/PrismaProductRepository.ts
export class PrismaProductRepository implements IProductRepository {
  async findMany(filters: ProductFilters): Promise<Product[]> {
    const results = await db.product.findMany({
      where: this.buildWhereClause(filters),
      skip: filters.offset,
      take: filters.limit,
    });

    return results.map(ProductMapper.toDomain);
  }
}

// packages/api/routers/product.ts
export const productRouter = createTRPCRouter({
  list: publicProcedure
    .input(listProductsSchema)
    .query(({ input }) =>
      listProductsUseCase.execute(input)
    ),
});
```

**ADR**:
```markdown
# ADR-042: Hexagonal Architecture for Product Domain

## Status
Accepted

## Context
Product catalog is a core domain with complex business rules:
- Pricing rules (discounts, promotions)
- Inventory management
- Multi-currency support
- Long-term support required (10+ years)

## Decision
Implement hexagonal architecture with:
- Domain layer (pure business logic, ZERO deps)
- Application layer (use-cases)
- Infrastructure layer (Prisma repository)

## Consequences
### Positive
- Business logic independent of framework
- Easy to test (100% domain coverage)
- Can swap infrastructure (Prisma → other ORM)
- Clear boundaries

### Negative
- More files and abstractions
- Steeper learning curve
- Longer initial development time

## Alternatives Considered
1. Balanced 3-layer - Rejected (too coupled for long-term)
2. CQRS + Event Sourcing - Rejected (overkill for current needs)

## Implementation Notes
- Product is an Aggregate Root
- Money is a Value Object
- Use Result pattern (no exceptions)
- Repository interface in domain, implementation in infrastructure
```

## Common Architecture Patterns

### Pattern: Repository Pattern
**When**: Balanced+
**Why**: Decouple data access from business logic

### Pattern: Value Objects
**When**: Crafted
**Why**: Encapsulate domain concepts (Email, Money, etc.)

### Pattern: Use-Cases
**When**: Crafted
**Why**: Orchestrate domain logic, clear application boundaries

### Pattern: Result Pattern
**When**: Crafted
**Why**: Explicit error handling, no exceptions

### Pattern: Dependency Injection
**When**: Crafted
**Why**: Testability, flexibility

## Tools & Commands

```bash
# Get project context
/architect "Design user authentication"

# Validate architecture
/guard crafted
```

## Tips for Architects

1. **Start simple** - Don't over-architect
2. **Document decisions** - Future you will thank you
3. **Validate boundaries** - Use tools to enforce rules
4. **Think long-term** - But ship incrementally
5. **Communicate** - Share architecture with team

## Anti-Patterns to Avoid

❌ **Don't**:
- Over-engineer for Rapid level
- Skip ADRs for Balanced/Crafted
- Mix layers (services calling routers)
- Add framework dependencies in domain (Crafted)
- Design without understanding requirements

✅ **Do**:
- Match architecture to level
- Document major decisions
- Enforce boundaries with tools
- Start simple, evolve as needed
- Validate designs early
