# Crafted Mode - Software Craftsmanship

**Context**: 10-200+ developers, 5-10+ years lifespan, 10K-1M+ users, $100K+ MRR

When this skill is activated, you operate in **CRAFTED mode** - enterprise-grade architecture for long-term sustainability.

## Architecture Rules

### Structure: Hexagonal Architecture (Ports & Adapters)

**Domain Layer** - Pure business logic
- ZERO external dependencies
- Entities, Value Objects, Aggregates
- 100% test coverage (Spec-First TDD)
- Result pattern for errors (no throws)
- Max 20 lines per function
- Max 2 parameters

**Application Layer** - Use-cases
- Orchestration of domain logic
- Ultra-thin (< 10 lines)
- 100% test coverage
- Dependency injection

**Infrastructure Layer** - Implementations
- Database repositories
- External services (Stripe, Twilio, etc.)
- 80% test coverage

### Code Quality Rules

| Aspect | Rule |
|--------|------|
| Max lines/function | 20 lines |
| Parameters | Max 2 |
| Duplication | 0 duplication (❌ CI FAILS) |
| Cyclomatic complexity | < 5 |
| SOLID | Full + auditable |
| Comments | WHY + ADR reference |

### Testing Strategy

**Coverage**: Domain 100%, Use-cases 100%, Infrastructure 80%

**Test approach**: Spec-First (TDD-inspired)

For domain entities and use-cases:
1. **UNDERSTAND** business rules first
2. **Generate tests FIRST** (they specify behavior)
3. **Then generate implementation** that satisfies tests
4. Tests ARE the specification

**What to test**:
- ✅ Domain entities (100% coverage)
- ✅ Value objects (100% coverage)
- ✅ Use-cases (100% coverage)
- ✅ Infrastructure (80% coverage)
- ✅ E2E (complete flows)
- ✅ Integration tests
- ✅ Contract tests (API boundaries)

### Typical Structure

```
packages/
├── domain/                    # ⭐ Pure business logic (ZERO deps)
│   ├── entities/
│   │   ├── Product.ts         # Rich domain entity
│   │   └── Product.test.ts    # 100% coverage
│   ├── value-objects/
│   │   ├── Money.ts
│   │   ├── Money.test.ts
│   │   ├── Email.ts
│   │   └── Email.test.ts
│   ├── use-cases/
│   │   ├── CreateProduct.ts   # Orchestration
│   │   └── CreateProduct.test.ts
│   └── repositories/          # Interfaces ONLY
│       └── IProductRepository.ts
│
├── api/                       # Application layer
│   └── routers/
│       └── product.ts         # Ultra-thin (< 10 lines)
│
└── infrastructure/            # Implementations
    ├── database/
    │   └── repositories/
    │       └── PrismaProductRepository.ts
    └── payments/
        └── StripeClient.ts
```

## MCP Tools to Use

### Context
```typescript
mcp__crafted-context__get_context_summary()
mcp__crafted-context__get_architecture_info() // Confirm level = crafted
```

### Validation (Strict)
```typescript
mcp__rules-validator__validate_code({
  code: "...",
  level: "crafted" // Will enforce 20 lines, 2 params, 0 duplication
})

mcp__rules-validator__check_test_coverage({
  testPath: "packages/domain",
  level: "crafted" // Will require 100% for domain
})
```

### Architecture Guard (Critical)
```typescript
mcp__architecture-guard__check_dependencies({
  filePath: "packages/domain/entities/Product.ts",
  level: "crafted" // Will FAIL if external deps
})

mcp__architecture-guard__check_layer_boundaries({
  level: "crafted" // Validates hexagonal architecture
})
```

### Development (TDD)
```typescript
mcp__vitest__run_specific_test({
  testFile: "packages/domain/entities/Product.test.ts"
})

mcp__vitest__check_coverage({ threshold: 100 }) // For domain
mcp__typescript__check_types()
```

## Philosophy

> "Build it right. Architecture-first, sustainable for 10+ years."

## Active Craft Principles (16/16 - ALL)

All from Balanced +
- ✅ Hexagonal Architecture
- ✅ Domain-Driven Design
- ✅ TDD-inspired (Spec-First)
- ✅ SOLID strict (architecture tests)
- ✅ ADR for ALL major decisions
- ✅ E2E complete
- ✅ Security hardened (OWASP Top 10)
- ✅ Performance optimized

## When to Use This Skill

Invoke this skill when:
- Building enterprise-grade software
- 10+ year product vision
- Large team (10+ developers)
- Critical business logic
- High stakes (healthcare, fintech, etc.)

## Spec-First TDD Workflow

### Example: Creating a Product Entity

**Step 1: Write tests FIRST (specification)**

```typescript
// Product.test.ts
describe('Product Entity', () => {
  describe('creation', () => {
    it('should create valid product with positive price', () => {
      const result = Product.create({
        name: 'MacBook Pro',
        price: Money.fromDollars(2999),
        description: '16-inch M3 Max',
      });

      expect(result.isSuccess).toBe(true);
      expect(result.value.name).toBe('MacBook Pro');
    });

    it('should reject product with empty name', () => {
      const result = Product.create({
        name: '',
        price: Money.fromDollars(2999),
      });

      expect(result.isFailure).toBe(true);
      expect(result.error).toBe('Product name cannot be empty');
    });

    it('should reject product with negative price', () => {
      const result = Product.create({
        name: 'MacBook Pro',
        price: Money.fromDollars(-100),
      });

      expect(result.isFailure).toBe(true);
      expect(result.error).toBe('Product price must be positive');
    });
  });

  describe('price update', () => {
    it('should allow price increase', () => {
      const product = Product.create({
        name: 'MacBook Pro',
        price: Money.fromDollars(2999),
      }).value;

      const result = product.updatePrice(Money.fromDollars(3299));

      expect(result.isSuccess).toBe(true);
      expect(product.price.dollars).toBe(3299);
    });

    it('should reject price decrease of more than 20%', () => {
      const product = Product.create({
        name: 'MacBook Pro',
        price: Money.fromDollars(2999),
      }).value;

      // 30% decrease (not allowed)
      const result = product.updatePrice(Money.fromDollars(2099));

      expect(result.isFailure).toBe(true);
      expect(result.error).toContain('Price decrease exceeds 20%');
    });
  });
});
```

**Step 2: Implement to satisfy tests**

```typescript
// Product.ts
export class Product {
  private constructor(
    public readonly id: string,
    public name: string,
    public price: Money,
    public description?: string,
  ) {}

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

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

    return Result.ok(new Product(
      generateId(),
      props.name,
      props.price,
      props.description,
    ));
  }

  updatePrice(newPrice: Money): Result<void> {
    const decreasePercent = this.calculatePriceDecreasePercent(newPrice);

    if (decreasePercent > 0.20) {
      return Result.fail(`Price decrease exceeds 20% (${decreasePercent * 100}%)`);
    }

    this.price = newPrice;
    return Result.ok();
  }

  private calculatePriceDecreasePercent(newPrice: Money): number {
    if (newPrice.cents >= this.price.cents) {
      return 0;
    }

    return (this.price.cents - newPrice.cents) / this.price.cents;
  }
}
```

## Result Pattern (No Exceptions)

```typescript
// Result.ts
export class Result<T> {
  private constructor(
    public readonly isSuccess: boolean,
    public readonly value?: T,
    public readonly error?: string,
  ) {}

  static ok<T>(value?: T): Result<T> {
    return new Result(true, value);
  }

  static fail<T>(error: string): Result<T> {
    return new Result(false, undefined, error);
  }

  get isFailure(): boolean {
    return !this.isSuccess;
  }
}
```

## ADR (Required for ALL Decisions)

```markdown
# ADR-042: Use Result Pattern Instead of Exceptions

## Status
Accepted

## Context
Domain layer should have ZERO external dependencies and be pure.
Exceptions create implicit control flow.

## Decision
Use Result<T> pattern for all domain operations.

## Consequences
- Positive: Explicit error handling, pure functions
- Positive: Better testability
- Negative: More verbose code
- Negative: Learning curve for team

## Alternatives Considered
1. Exceptions - Rejected (impure, implicit)
2. Either monad - Rejected (FP overkill for team)
```

## Commands You Can Run

```bash
# Generate feature with Crafted rules (Spec-First)
/feature "Add product pricing rules"

# Validate architecture (strict)
/guard crafted

# Check domain coverage (must be 100%)
/coverage crafted packages/domain

# Run domain tests (TDD)
pnpm test packages/domain --watch

# Architecture tests
pnpm test:architecture
```

## Architecture Tests

```typescript
// architecture.test.ts
describe('Architecture Boundaries', () => {
  it('domain layer should have ZERO external dependencies', () => {
    const domainFiles = getDomainFiles();

    domainFiles.forEach(file => {
      const imports = extractImports(file);
      const externalImports = imports.filter(isExternalDependency);

      expect(externalImports).toHaveLength(0);
    });
  });

  it('services should not import from API layer', () => {
    const serviceFiles = getServiceFiles();

    serviceFiles.forEach(file => {
      const imports = extractImports(file);
      const apiImports = imports.filter(imp => imp.includes('/api/'));

      expect(apiImports).toHaveLength(0);
    });
  });
});
```

## Domain-Driven Design Patterns

### Entity
```typescript
export class User {
  // Identity + behavior
  private constructor(
    public readonly id: UserId,
    public email: Email,
    public name: string,
  ) {}
}
```

### Value Object
```typescript
export class Email {
  // No identity, immutable
  private constructor(private readonly value: string) {}

  static create(email: string): Result<Email> {
    if (!Email.isValid(email)) {
      return Result.fail('Invalid email format');
    }
    return Result.ok(new Email(email));
  }

  equals(other: Email): boolean {
    return this.value === other.value;
  }
}
```

### Aggregate
```typescript
export class Order {
  // Aggregate root
  private items: OrderItem[] = [];

  addItem(item: OrderItem): Result<void> {
    // Business rule: max 10 items per order
    if (this.items.length >= 10) {
      return Result.fail('Order cannot have more than 10 items');
    }
    this.items.push(item);
    return Result.ok();
  }
}
```

## Dependency Injection

```typescript
// Use-case with DI
export class CreateProductUseCase {
  constructor(
    private productRepo: IProductRepository,
    private paymentService: IPaymentService,
  ) {}

  async execute(input: CreateProductInput): Promise<Result<Product>> {
    const product = Product.create(input);
    if (product.isFailure) {
      return product;
    }

    await this.productRepo.save(product.value);
    await this.paymentService.createProduct(product.value);

    return product;
  }
}
```

## When NOT to Use Crafted

Crafted is overkill for:
- MVPs and prototypes
- Small teams (< 5 developers)
- Short-lived projects (< 1 year)
- Simple CRUD apps

Use `/rapid` or `/balanced` instead.
