UNPKG

prprompts-flutter-generator

Version:

AI-powered Flutter development with full automation + official extension support - Generate 32 security-audited guides & auto-implement in 2-3 hours. NEW v5.1: Official Claude Code plugin with hooks, Gemini TOML commands, Qwen MCP settings. Features: Comp

2,662 lines 69.3 kB
# Feature Implementation Automation - Complete Guide

> **Automatically implement Flutter features from specifications in 3-8 minutes**
>
> Transforms feature specifications into production-ready code following Clean Architecture patterns with comprehensive testing and security validation.

---

## Table of Contents

- [Quick Start](#quick-start)
- [For Junior Developers - ELI5](#for-junior-developers---eli5)
- [For Intermediate Developers](#for-intermediate-developers)
- [For Senior Developers](#for-senior-developers)
- [Usage Examples](#usage-examples)
- [Troubleshooting](#troubleshooting)
- [FAQ](#faq)

---

## Quick Start

### Prerequisites

1. **Flutter Bootstrapper** completed:
   ```bash
   @claude use skill automation/flutter-bootstrapper
   ```

2. **IMPLEMENTATION_PLAN.md** exists:
   ```bash
   test -f docs/IMPLEMENTATION_PLAN.md
   ```

3. **PRPROMPTS files** generated:
   ```bash
   ls PRPROMPTS/*.md | wc -l  # Should show 32
   ```

### Basic Usage

```bash
# Implement a feature from IMPLEMENTATION_PLAN.md
@claude use skill automation/feature-implementer

# When prompted, provide:
# - Feature name: "authentication"
# - Test coverage target: 75 (default: 70%)
```

### What Gets Created

For a feature named "authentication", this skill creates:

```
lib/features/auth/
├── domain/
│   ├── entities/
│   │   ├── user.dart
│   │   └── auth_tokens.dart
│   ├── repositories/
│   │   └── auth_repository.dart
│   └── usecases/
│       ├── login_with_email.dart
│       ├── register_with_email.dart
│       ├── logout.dart
│       ├── get_current_user.dart
│       └── refresh_token.dart
├── data/
│   ├── models/
│   │   ├── user_model.dart
│   │   └── auth_tokens_model.dart
│   ├── datasources/
│   │   ├── auth_remote_data_source.dart
│   │   └── auth_local_data_source.dart
│   └── repositories/
│       └── auth_repository_impl.dart
└── presentation/
    ├── bloc/
    │   ├── auth_bloc.dart
    │   ├── auth_event.dart
    │   └── auth_state.dart
    ├── pages/
    │   ├── login_screen.dart
    │   ├── register_screen.dart
    │   └── forgot_password_screen.dart
    └── widgets/
        ├── custom_text_field.dart
        └── primary_button.dart

test/features/auth/
├── domain/usecases/
│   └── login_with_email_test.dart
├── data/
│   ├── models/user_model_test.dart
│   └── repositories/auth_repository_impl_test.dart
└── presentation/
    └── pages/login_screen_test.dart

integration_test/
└── auth_test.dart
```

**Total:** 20-30 files per feature

---

## For Junior Developers - ELI5

### What Does This Skill Do?

Think of this skill like a **robot construction worker** that builds your Flutter app feature by feature.

**Real-World Analogy:**

Imagine you're building a house (your Flutter app):

1. **IMPLEMENTATION_PLAN.md** = Blueprint
   - Shows what rooms you need (features)
   - Describes what goes in each room (requirements)
   - Lists materials needed (dependencies)

2. **feature-implementer skill** = Construction Crew
   - Reads the blueprint
   - Builds each room (feature) automatically
   - Follows building codes (Clean Architecture patterns)
   - Inspects the work (runs tests)
   - Ensures safety (validates security)

3. **Result** = Finished Room
   - All walls, floors, electrical, plumbing done (all code layers)
   - Passes inspection (tests pass, security validated)
   - Ready to use (production-ready code)

### How Long Does It Take?

**Manual Implementation:**
- Junior developer: 1-2 days per feature
- Writing tests: +4-6 hours
- **Total:** 2-3 days

**With feature-implementer:**
- Complete implementation: 3-8 minutes
- **Speedup:** 300-600x faster!

### What You Need to Know

#### 1. **IMPLEMENTATION_PLAN.md Structure**

Your feature specification should look like this:

```markdown
### Feature 1: User Profile

**Priority:** HIGH
**Estimated Time:** 4-6 hours

**Requirements:**
- View user profile with photo, name, bio
- Edit profile information
- Upload profile photo
- Change password

**User Stories:**
- As a user, I can view my profile
- As a user, I can edit my name and bio
- As a user, I can upload a profile photo
- As a user, I can change my password

**Data Models:**
```dart
class UserProfile {
  final String id;
  final String name;
  final String email;
  final String? bio;
  final String? photoUrl;
}
```

**API Endpoints:**
- GET /api/users/me
- PUT /api/users/me
- POST /api/users/me/photo
- PUT /api/users/me/password

**UI Screens:**
- ProfileScreen (view)
- EditProfileScreen (edit)
- ChangePasswordScreen
```

#### 2. **Clean Architecture Explained (Simple)**

Clean Architecture is like organizing your code into **3 floors** of a building:

**Floor 1: Domain Layer (Top Floor - Business Logic)**
- **What it is:** The "brain" of your feature
- **Contains:**
  - **Entities:** Core data objects (like User, Product)
  - **Use Cases:** Actions users can do (Login, AddToCart)
  - **Repository Contracts:** Promises about how to get data
- **Rule:** This floor NEVER knows about UI or databases
- **Why:** Business rules stay the same even if UI changes

**Floor 2: Data Layer (Middle Floor - Data Management)**
- **What it is:** The "warehouse" that stores and fetches data
- **Contains:**
  - **Models:** Data from API (converts JSON to objects)
  - **Data Sources:** API calls, database queries
  - **Repository Implementations:** Actually gets the data
- **Rule:** Talks to APIs and databases, converts to domain objects
- **Why:** Switching from Firebase to custom backend? Just change this floor!

**Floor 3: Presentation Layer (Ground Floor - User Interface)**
- **What it is:** Everything users see and interact with
- **Contains:**
  - **BLoC:** Manages UI state (loading, success, error)
  - **Screens:** Full pages users navigate to
  - **Widgets:** Reusable UI components (buttons, cards)
- **Rule:** Only knows about UI, gets data from domain layer
- **Why:** Can redesign UI without touching business logic

**Example Flow: User Logs In**

1. **Presentation:** User taps "Log In" button
   - `LoginScreen` shows loading spinner
   - Calls `AuthBloc` with `LoginEvent`

2. **Domain:** BLoC processes the event
   - Calls `LoginWithEmail` use case
   - Use case validates email/password
   - Calls `AuthRepository` (interface)

3. **Data:** Repository fetches data
   - `AuthRepositoryImpl` calls `AuthRemoteDataSource`
   - Sends HTTP request to `/api/auth/login`
   - Converts JSON response to `User` entity
   - Stores JWT token in secure storage

4. **Back to Presentation:** Success!
   - BLoC emits `Authenticated` state
   - UI shows home screen

**Key Insight:** Each layer only talks to the one above it. This makes code:
- **Testable:** Mock each layer independently
- **Maintainable:** Change one layer without breaking others
- **Scalable:** Add features without spaghetti code

#### 3. **BLoC Pattern Explained (Simple)**

**BLoC** = Business Logic Component

Think of BLoC like a **traffic controller** for your UI:

- **Events:** Things that happen (user taps button, data loads)
- **States:** What the UI shows (loading, success, error)
- **BLoC:** Converts events into states

**Example: Login Screen**

```dart
// States (what UI shows)
AuthInitial      → Show login form
AuthLoading      → Show loading spinner
Authenticated    → Navigate to home
AuthError        → Show error message

// Events (what user does)
LoginEvent       → User taps "Log In"
LogoutEvent      → User taps "Log Out"

// BLoC (traffic controller)
- Receives LoginEvent
- Emits AuthLoading
- Calls LoginUseCase
- If success: emits Authenticated
- If failure: emits AuthError
```

**Why BLoC?**
- **Separation:** UI and logic are separate
- **Testability:** Test BLoC without building UI
- **Reusability:** Same BLoC for iOS/Android/Web

#### 4. **Testing Explained (Simple)**

This skill writes **3 types of tests** automatically:

**Unit Tests (Test individual pieces)**
- **Example:** Does `LoginUseCase` validate email correctly?
- **Speed:** Very fast (milliseconds)
- **Coverage:** Business logic, data conversion

**Widget Tests (Test UI components)**
- **Example:** Does login button show loading spinner?
- **Speed:** Fast (seconds)
- **Coverage:** Screens, widgets, user interactions

**Integration Tests (Test complete flows)**
- **Example:** Can user actually log in end-to-end?
- **Speed:** Slow (minutes)
- **Coverage:** Full feature workflows

**Why 70%+ Coverage?**
- Industry standard for production code
- Catches 90% of bugs before users see them
- Required for CI/CD pipelines

#### 5. **Security Validation**

This skill automatically checks that your code follows **security best practices**:

**What Gets Checked:**

- ✅ **JWT Tokens:** Stored in encrypted storage (FlutterSecureStorage)
- ✅ **Passwords:** NEVER stored locally, only sent over HTTPS
- ✅ **API Calls:** Always use HTTPS, not HTTP
- ✅ **Error Messages:** Don't reveal if email exists (prevents enumeration)
- ✅ **Input Validation:** Email format, password strength, no SQL injection

**Example: Bad vs Good**

```dart
// ❌ BAD - Storing password locally
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString('password', userPassword); // NEVER DO THIS!

// ✅ GOOD - Only storing JWT token (encrypted)
FlutterSecureStorage storage = FlutterSecureStorage();
await storage.write(key: 'access_token', value: jwtToken);
```

```dart
// ❌ BAD - Revealing if email exists
if (emailExists) {
  return 'Email already registered';
} else {
  return 'Invalid credentials';
}

// ✅ GOOD - Generic message
return 'Invalid email or password';
```

### How to Use (Step by Step)

**Step 1: Make sure IMPLEMENTATION_PLAN.md exists**

```bash
# Check if file exists
ls docs/IMPLEMENTATION_PLAN.md
```

If it doesn't exist, create it:

```bash
@claude use skill prprompts-core/prd-analyzer
# Then generate IMPLEMENTATION_PLAN.md from PRD
```

**Step 2: Run the skill**

```bash
@claude use skill automation/feature-implementer
```

**Step 3: Answer the questions**

Claude will ask:

```
1. Feature name?
   → Type: authentication

2. Test coverage target? (default: 70%)
   → Type: 75 (or press Enter for default)

3. Generate integration tests? (default: no)
   → Type: yes (or press Enter for no)
```

**Step 4: Wait for completion (3-8 minutes)**

Claude will:
1. Read your IMPLEMENTATION_PLAN.md
2. Generate all domain, data, presentation files
3. Write tests
4. Run `flutter analyze` and `flutter test`
5. Validate security patterns
6. Show you a summary

**Step 5: Review the code**

```bash
# See what was created
git status

# Review a file
cat lib/features/auth/domain/usecases/login_with_email.dart

# Run tests
flutter test

# Check coverage
flutter test --coverage
genhtml coverage/lcov.info -o coverage/html
```

**Step 6: Commit if happy with results**

```bash
git add lib/features/auth
git add test/features/auth
git commit -m "feat(auth): implement authentication feature

- Add login, register, logout use cases
- Add JWT token management
- Add tests with 78% coverage"
```

### Common Mistakes (Avoid These!)

#### 1. **Running skill before bootstrapper**

```bash
# ❌ WRONG - Running feature-implementer first
@claude use skill automation/feature-implementer
# ERROR: lib/core/ directory not found

# ✅ CORRECT - Run bootstrapper first
@claude use skill automation/flutter-bootstrapper
@claude use skill automation/feature-implementer
```

#### 2. **IMPLEMENTATION_PLAN.md missing required sections**

```markdown
# ❌ BAD - Incomplete specification
### Feature 1: Authentication
- Add login

# ✅ GOOD - Complete specification
### Feature 1: Authentication
**Requirements:**
- Email/password login
- JWT token management

**Data Models:**
class User { ... }

**API Endpoints:**
- POST /api/auth/login

**UI Screens:**
- LoginScreen
```

#### 3. **Not checking tests after generation**

```bash
# ❌ WRONG - Assuming all tests pass
@claude use skill automation/feature-implementer
git add .
git commit -m "add auth"
# Later: CI fails because 2 tests are broken

# ✅ CORRECT - Always run tests
@claude use skill automation/feature-implementer
flutter test
# Fix any failing tests
git add .
git commit -m "add auth"
```

### What to Do If Something Goes Wrong

#### Problem 1: Skill says "Feature not found"

**Error Message:**
```
❌ ERROR: Feature "authentication" not found in IMPLEMENTATION_PLAN.md
```

**Solution:**
1. Open `docs/IMPLEMENTATION_PLAN.md`
2. Check the feature name exactly matches
3. Feature names are case-sensitive!

```markdown
# If your plan says:
### Feature 1: Authentication System

# Then use:
Feature name: Authentication System
# NOT: authentication system (wrong case)
```

#### Problem 2: Tests failing after generation

**Error Message:**
```
Some tests failed:
  × login_with_email_test.dart: MockAuthRepository not found
```

**Solution:**
1. Install mockito:
```bash
flutter pub add mockito --dev
flutter pub add build_runner --dev
```

2. Generate mocks:
```bash
flutter pub run build_runner build
```

3. Re-run tests:
```bash
flutter test
```

#### Problem 3: Flutter analyze shows errors

**Error Message:**
```
error • Undefined name 'NoParams' • lib/features/auth/domain/usecases/logout.dart:15
```

**Solution:**
1. Add missing import:
```dart
import '../../../../core/usecases/usecase.dart';
```

2. Re-run analyze:
```bash
flutter analyze
```

---

## For Intermediate Developers

### Architecture Deep Dive

#### Clean Architecture in Flutter

This skill implements Clean Architecture following Uncle Bob's principles:

**Dependency Rule:** Source code dependencies only point inwards. Inner circles know nothing about outer circles.

```
┌─────────────────────────────────────────┐
│         Presentation Layer              │  ← UI (Flutter Widgets, BLoC)
│  (BLoC, Screens, Widgets)              │
├─────────────────────────────────────────┤
│         Domain Layer                    │  ← Business Logic (Entities, Use Cases)
│  (Entities, Use Cases, Repositories)   │     NO dependencies on Flutter!
├─────────────────────────────────────────┤
│         Data Layer                      │  ← Data Access (APIs, Databases)
│  (Models, Data Sources, Repo Impls)    │
└─────────────────────────────────────────┘
```

**Key Principles:**

1. **Domain Independence:**
   - Pure Dart code (no Flutter imports)
   - Business rules stable even if framework changes
   - Testable without UI

2. **Dependency Inversion:**
   - Domain defines interfaces (Repository contracts)
   - Data implements interfaces
   - Inversion: Domain doesn't depend on Data, Data depends on Domain

3. **Single Responsibility:**
   - Each use case does ONE thing
   - Each repository manages ONE entity
   - Each BLoC manages ONE feature

#### File Generation Logic

**For each feature, this skill generates:**

**Domain Layer (Avg: 5-8 files)**

```dart
// Entities (pure business objects)
lib/features/{feature}/domain/entities/
  - {entity}.dart (Equatable, immutable)

// Use Cases (single-responsibility operations)
lib/features/{feature}/domain/usecases/
  - {action}.dart (implements UseCase<T, Params>)

// Repository Interface (data contract)
lib/features/{feature}/domain/repositories/
  - {feature}_repository.dart (abstract class)
```

**Data Layer (Avg: 5-8 files)**

```dart
// Models (JSON serialization)
lib/features/{feature}/data/models/
  - {entity}_model.dart (extends Entity, fromJson/toJson)

// Data Sources (external systems)
lib/features/{feature}/data/datasources/
  - {feature}_remote_data_source.dart (Dio/HTTP)
  - {feature}_local_data_source.dart (SharedPreferences/SQLite)

// Repository Implementation (orchestration)
lib/features/{feature}/data/repositories/
  - {feature}_repository_impl.dart (implements Repository)
```

**Presentation Layer (Avg: 8-12 files)**

```dart
// BLoC (state management)
lib/features/{feature}/presentation/bloc/
  - {feature}_bloc.dart (extends Bloc<Event, State>)
  - {feature}_event.dart (sealed classes or Equatable)
  - {feature}_state.dart (sealed classes or Equatable)

// Screens (top-level pages)
lib/features/{feature}/presentation/pages/
  - {screen}_screen.dart (StatefulWidget/StatelessWidget)

// Widgets (reusable components)
lib/features/{feature}/presentation/widgets/
  - {widget}.dart
```

**Tests (Avg: 8-15 files)**

```dart
// Unit tests (domain + data)
test/features/{feature}/domain/usecases/
  - {use_case}_test.dart

test/features/{feature}/data/
  - models/{model}_test.dart
  - repositories/{repository}_test.dart

// Widget tests (presentation)
test/features/{feature}/presentation/
  - pages/{screen}_test.dart
  - widgets/{widget}_test.dart

// Integration tests (full flows)
integration_test/
  - {feature}_test.dart
```

#### BLoC Pattern Implementation

**This skill generates BLoC following flutter_bloc best practices:**

**Event-Driven Architecture:**

```dart
// 1. Define Events (user actions)
abstract class AuthEvent extends Equatable {}

class LoginEvent extends AuthEvent {
  final String email;
  final String password;

  const LoginEvent({required this.email, required this.password});

  @override
  List<Object?> get props => [email, password];
}

// 2. Define States (UI representations)
abstract class AuthState extends Equatable {}

class AuthInitial extends AuthState {}
class AuthLoading extends AuthState {}
class Authenticated extends AuthState {
  final User user;
  const Authenticated({required this.user});

  @override
  List<Object?> get props => [user];
}
class AuthError extends AuthState {
  final String message;
  const AuthError({required this.message});

  @override
  List<Object?> get props => [message];
}

// 3. Implement BLoC (event → state transformer)
class AuthBloc extends Bloc<AuthEvent, AuthState> {
  final LoginWithEmail loginUseCase;

  AuthBloc({required this.loginUseCase}) : super(AuthInitial()) {
    on<LoginEvent>(_onLogin);
  }

  Future<void> _onLogin(LoginEvent event, Emitter<AuthState> emit) async {
    emit(AuthLoading());

    final result = await loginUseCase(LoginParams(
      email: event.email,
      password: event.password,
    ));

    result.fold(
      (failure) => emit(AuthError(message: failure.message)),
      (user) => emit(Authenticated(user: user)),
    );
  }
}
```

**BLoC Best Practices (Automatically Applied):**

1. **Immutable States:**
   - All states extend Equatable
   - Props define equality
   - BlocBuilder rebuilds only when state changes

2. **Separate Events/States:**
   - Events represent user intentions
   - States represent UI snapshots
   - Never mix concerns

3. **Use Cases in BLoC:**
   - BLoC doesn't contain business logic
   - Delegates to use cases
   - Single responsibility

4. **Error Handling:**
   - All errors converted to states
   - UI shows appropriate messages
   - No thrown exceptions in BLoC

#### Data Source Patterns

**Remote Data Source (API Communication):**

```dart
abstract class AuthRemoteDataSource {
  /// Throws [ServerException], [NetworkException], [AuthException]
  Future<UserModel> loginWithEmail({
    required String email,
    required String password,
  });
}

class AuthRemoteDataSourceImpl implements AuthRemoteDataSource {
  final Dio dio;

  AuthRemoteDataSourceImpl({required this.dio});

  @override
  Future<UserModel> loginWithEmail({
    required String email,
    required String password,
  }) async {
    try {
      final response = await dio.post('/auth/login', data: {
        'email': email,
        'password': password,
      });

      if (response.statusCode == 200) {
        return UserModel.fromJson(response.data);
      } else {
        throw ServerException(message: 'Unexpected status: ${response.statusCode}');
      }
    } on DioException catch (e) {
      _handleDioError(e);
      rethrow;
    }
  }

  void _handleDioError(DioException e) {
    if (e.response?.statusCode == 401) {
      throw AuthException(message: 'Invalid credentials');
    } else if (e.response?.statusCode == 400) {
      throw ValidationException(message: e.response?.data['message']);
    } else if (e.response?.statusCode != null && e.response!.statusCode! >= 500) {
      throw ServerException(message: 'Server error');
    } else {
      throw NetworkException(message: 'Network error: ${e.message}');
    }
  }
}
```

**Key Patterns:**

1. **Exception-Based Errors:**
   - Data sources throw exceptions
   - Repositories catch and convert to Failures
   - Clean separation of concerns

2. **HTTP Error Handling:**
   - 401/403: AuthException
   - 400: ValidationException
   - 500+: ServerException
   - Timeout: NetworkException

3. **Type Safety:**
   - Models for all API responses
   - Compile-time type checking
   - No dynamic typing

**Local Data Source (Storage):**

```dart
abstract class AuthLocalDataSource {
  /// Throws [CacheException] if not found
  Future<AuthTokensModel> getCachedTokens();

  /// Throws [CacheException] on failure
  Future<void> cacheTokens(AuthTokensModel tokens);

  Future<void> clearTokens();
}

class AuthLocalDataSourceImpl implements AuthLocalDataSource {
  final FlutterSecureStorage secureStorage;

  AuthLocalDataSourceImpl({required this.secureStorage});

  @override
  Future<AuthTokensModel> getCachedTokens() async {
    final accessToken = await secureStorage.read(key: 'access_token');
    final refreshToken = await secureStorage.read(key: 'refresh_token');

    if (accessToken == null || refreshToken == null) {
      throw CacheException(message: 'Tokens not found');
    }

    return AuthTokensModel(
      accessToken: accessToken,
      refreshToken: refreshToken,
      expiresAt: DateTime.parse(await secureStorage.read(key: 'expires_at')!),
    );
  }

  @override
  Future<void> cacheTokens(AuthTokensModel tokens) async {
    await secureStorage.write(key: 'access_token', value: tokens.accessToken);
    await secureStorage.write(key: 'refresh_token', value: tokens.refreshToken);
    await secureStorage.write(key: 'expires_at', value: tokens.expiresAt.toIso8601String());
  }

  @override
  Future<void> clearTokens() async {
    await secureStorage.delete(key: 'access_token');
    await secureStorage.delete(key: 'refresh_token');
    await secureStorage.delete(key: 'expires_at');
  }
}
```

**Storage Strategies:**

1. **Sensitive Data:** FlutterSecureStorage (encrypted)
   - JWT tokens
   - Refresh tokens
   - API keys

2. **Non-Sensitive Data:** SharedPreferences (plain text)
   - User preferences
   - Theme settings
   - Language selection

3. **Structured Data:** SQLite (local database)
   - Cached API responses
   - Offline data
   - Complex queries

#### Repository Pattern Implementation

**Repository coordinates data sources and converts exceptions to Failures:**

```dart
class AuthRepositoryImpl implements AuthRepository {
  final AuthRemoteDataSource remoteDataSource;
  final AuthLocalDataSource localDataSource;
  final NetworkInfo networkInfo;

  AuthRepositoryImpl({
    required this.remoteDataSource,
    required this.localDataSource,
    required this.networkInfo,
  });

  @override
  Future<Either<Failure, User>> loginWithEmail({
    required String email,
    required String password,
  }) async {
    // 1. Check network connectivity
    if (!await networkInfo.isConnected) {
      return Left(NetworkFailure(message: 'No internet connection'));
    }

    try {
      // 2. Attempt remote operation
      final result = await remoteDataSource.loginWithEmail(
        email: email,
        password: password,
      );

      // 3. Cache result
      await localDataSource.cacheTokens(result['tokens']);
      await localDataSource.cacheUser(result['user']);

      // 4. Return success
      return Right(result['user']);
    } on AuthException catch (e) {
      // 5. Convert exceptions to failures
      return Left(AuthFailure(message: e.message));
    } on NetworkException catch (e) {
      return Left(NetworkFailure(message: e.message));
    } on ServerException catch (e) {
      return Left(ServerFailure(message: e.message));
    } catch (e) {
      return Left(ServerFailure(message: 'Unexpected error: $e'));
    }
  }
}
```

**Key Responsibilities:**

1. **Network Check:** Verify connectivity before remote calls
2. **Exception Conversion:** Convert exceptions → Failures
3. **Caching:** Store results locally for offline access
4. **Orchestration:** Coordinate multiple data sources

#### Test Generation Strategy

**This skill generates tests targeting 70%+ coverage:**

**Unit Test Structure:**

```dart
void main() {
  late UseCase useCase;
  late MockRepository mockRepository;

  setUp(() {
    mockRepository = MockRepository();
    useCase = UseCase(mockRepository);
  });

  group('Success Cases', () {
    test('should return Entity when repository succeeds', () async {
      // arrange
      when(mockRepository.method(any)).thenAnswer((_) async => Right(entity));

      // act
      final result = await useCase(params);

      // assert
      expect(result, Right(entity));
      verify(mockRepository.method(params));
      verifyNoMoreInteractions(mockRepository);
    });
  });

  group('Failure Cases', () {
    test('should return Failure when repository fails', () async {
      // arrange
      when(mockRepository.method(any)).thenAnswer((_) async => Left(failure));

      // act
      final result = await useCase(params);

      // assert
      expect(result, Left(failure));
    });
  });

  group('Validation', () {
    test('should return ValidationFailure for invalid input', () async {
      // arrange
      final invalidParams = Params(invalidData);

      // act
      final result = await useCase(invalidParams);

      // assert
      expect(result.isLeft(), true);
      verifyZeroInteractions(mockRepository);
    });
  });
}
```

**Test Coverage Targets:**

- **Domain Layer:** 90%+ (critical business logic)
- **Data Layer:** 80%+ (data transformations, error handling)
- **Presentation Layer:** 60%+ (UI interactions, state transitions)
- **Overall:** 70%+ (production-ready)

**Integration Test Patterns:**

```dart
void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  group('Feature Integration', () {
    testWidgets('complete user flow', (tester) async {
      // 1. Start app
      app.main();
      await tester.pumpAndSettle();

      // 2. Navigate to feature
      await tester.tap(find.text('Feature'));
      await tester.pumpAndSettle();

      // 3. Interact with UI
      await tester.enterText(find.byKey(Key('input')), 'test data');
      await tester.tap(find.text('Submit'));
      await tester.pumpAndSettle();

      // 4. Verify result
      expect(find.text('Success'), findsOneWidget);
    });
  });
}
```

### Security Validation Details

**This skill enforces PRPROMPTS security standards:**

#### JWT Token Security

```dart
// ✅ CORRECT: Verify JWT in Flutter (public key only)
class JwtVerifier {
  final RSAPublicKey publicKey;

  bool verifyToken(String token) {
    try {
      final jwt = JWT.verify(token, publicKey);
      return !jwt.isExpired;
    } catch (e) {
      return false;
    }
  }
}

// ❌ WRONG: NEVER sign JWT in Flutter (exposes private key)
class JwtSigner {
  final RSAPrivateKey privateKey; // SECURITY VIOLATION!

  String signToken(Map<String, dynamic> payload) {
    return JWT.encode(payload, privateKey); // NEVER DO THIS!
  }
}
```

**JWT Best Practices Enforced:**

1. **Storage:** FlutterSecureStorage only (encrypted)
2. **Transmission:** HTTPS only
3. **Verification:** Public key only (RS256)
4. **Expiration:** Check before each API call
5. **Refresh:** Rotate tokens before expiration

#### Password Security

```dart
// ✅ CORRECT: Validate but never store
class PasswordValidator {
  static String? validate(String password) {
    if (password.length < 8) return 'Too short';
    if (!password.contains(RegExp(r'[A-Z]'))) return 'Need uppercase';
    if (!password.contains(RegExp(r'[a-z]'))) return 'Need lowercase';
    if (!password.contains(RegExp(r'[0-9]'))) return 'Need digit';
    if (!password.contains(RegExp(r'[!@#$%^&*]'))) return 'Need special char';
    return null; // Valid
  }
}

// Send over HTTPS to backend
await dio.post('/auth/login', data: {
  'email': email,
  'password': password, // Only in request, never stored
});

// ❌ WRONG: Storing password locally
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString('password', password); // SECURITY VIOLATION!
```

#### API Security

```dart
// ✅ CORRECT: HTTPS enforced, Authorization header
class SecureApiClient {
  final Dio dio;

  SecureApiClient() : dio = Dio(BaseOptions(
    baseUrl: 'https://api.example.com', // HTTPS required
    headers: {'Content-Type': 'application/json'},
  )) {
    // Add JWT token to all requests
    dio.interceptors.add(InterceptorsWrapper(
      onRequest: (options, handler) async {
        final token = await secureStorage.read(key: 'access_token');
        if (token != null) {
          options.headers['Authorization'] = 'Bearer $token';
        }
        handler.next(options);
      },
    ));
  }
}

// ❌ WRONG: HTTP (not HTTPS)
final dio = Dio(BaseOptions(
  baseUrl: 'http://api.example.com', // SECURITY VIOLATION!
));
```

#### Input Validation

```dart
// ✅ CORRECT: Validate all user inputs
class InputValidator {
  static String? validateEmail(String email) {
    final regex = RegExp(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$');
    if (!regex.hasMatch(email)) {
      return 'Invalid email format';
    }
    return null;
  }

  static String? validatePhoneNumber(String phone) {
    final regex = RegExp(r'^\+?[1-9]\d{1,14}$'); // E.164 format
    if (!regex.hasMatch(phone)) {
      return 'Invalid phone number';
    }
    return null;
  }

  // Prevent SQL injection (though using ORM, good practice)
  static String sanitizeSql(String input) {
    return input.replaceAll(RegExp(r"[;'\"\\]"), '');
  }
}

// ❌ WRONG: No validation
await dio.post('/api/users', data: {
  'email': emailController.text, // Could be malicious input
});
```

### Advanced Customization

#### Extending Generated Code

**Generated code is fully customizable:**

1. **Add Custom Validations:**

```dart
// Generated use case
class LoginWithEmail implements UseCase<User, LoginParams> {
  @override
  Future<Either<Failure, User>> call(LoginParams params) async {
    final validation = params.validate();
    if (validation != null) {
      return Left(ValidationFailure(validation));
    }
    return await repository.loginWithEmail(...);
  }
}

// Your customization: Add brute-force protection
class LoginWithEmail implements UseCase<User, LoginParams> {
  final RateLimiter rateLimiter; // ADD THIS

  @override
  Future<Either<Failure, User>> call(LoginParams params) async {
    // ADD: Check rate limit
    if (await rateLimiter.isRateLimited(params.email)) {
      return Left(AuthFailure('Too many attempts. Try again in 15 minutes.'));
    }

    final validation = params.validate();
    if (validation != null) {
      return Left(ValidationFailure(validation));
    }

    final result = await repository.loginWithEmail(...);

    // ADD: Record failed attempt
    result.fold(
      (failure) => rateLimiter.recordFailedAttempt(params.email),
      (_) => rateLimiter.clearAttempts(params.email),
    );

    return result;
  }
}
```

2. **Add Caching Logic:**

```dart
// Generated repository
class UserRepositoryImpl implements UserRepository {
  @override
  Future<Either<Failure, User>> getUser(String id) async {
    if (!await networkInfo.isConnected) {
      return Left(NetworkFailure('No connection'));
    }
    return await remoteDataSource.getUser(id);
  }
}

// Your customization: Add cache layer
class UserRepositoryImpl implements UserRepository {
  final UserCache cache; // ADD THIS

  @override
  Future<Either<Failure, User>> getUser(String id) async {
    // ADD: Try cache first
    try {
      final cachedUser = await cache.getUser(id);
      if (!cachedUser.isExpired) {
        return Right(cachedUser);
      }
    } on CacheException {
      // Cache miss, continue to remote
    }

    if (!await networkInfo.isConnected) {
      return Left(NetworkFailure('No connection'));
    }

    final result = await remoteDataSource.getUser(id);

    // ADD: Cache successful result
    result.fold(
      (_) => null,
      (user) => cache.cacheUser(user),
    );

    return result;
  }
}
```

3. **Add Analytics Tracking:**

```dart
// Generated BLoC
class AuthBloc extends Bloc<AuthEvent, AuthState> {
  Future<void> _onLogin(LoginEvent event, Emitter<AuthState> emit) async {
    emit(AuthLoading());
    final result = await loginUseCase(LoginParams(...));
    result.fold(
      (failure) => emit(AuthError(message: failure.message)),
      (user) => emit(Authenticated(user: user)),
    );
  }
}

// Your customization: Add analytics
class AuthBloc extends Bloc<AuthEvent, AuthState> {
  final Analytics analytics; // ADD THIS

  Future<void> _onLogin(LoginEvent event, Emitter<AuthState> emit) async {
    emit(AuthLoading());

    // ADD: Track login attempt
    analytics.logEvent('login_attempt', parameters: {
      'method': 'email',
    });

    final result = await loginUseCase(LoginParams(...));

    result.fold(
      (failure) {
        // ADD: Track login failure
        analytics.logEvent('login_failed', parameters: {
          'error': failure.message,
        });
        emit(AuthError(message: failure.message));
      },
      (user) {
        // ADD: Track login success
        analytics.logEvent('login_success', parameters: {
          'user_id': user.id,
        });
        emit(Authenticated(user: user));
      },
    );
  }
}
```

### Performance Optimization

**Generated code is optimized for performance, but you can improve further:**

#### 1. **Lazy Loading BLoCs**

```dart
// Instead of creating all BLoCs at app startup
final authBloc = AuthBloc(...);
final profileBloc = ProfileBloc(...);
final settingsBloc = SettingsBloc(...);

// Use BlocProvider.value only when needed
BlocProvider(
  create: (_) => AuthBloc(...), // Created lazily
  child: LoginScreen(),
);
```

#### 2. **Caching API Responses**

```dart
// Add cache interceptor to Dio
dio.interceptors.add(DioCacheInterceptor(options: CacheOptions(
  store: MemCacheStore(), // Or HiveCacheStore for persistence
  policy: CachePolicy.request, // Default policy
  maxStale: Duration(days: 7), // Optional
)));
```

#### 3. **Debouncing User Input**

```dart
// Debounce search queries
final searchController = TextEditingController();
Timer? _debounce;

searchController.addListener(() {
  if (_debounce?.isActive ?? false) _debounce!.cancel();
  _debounce = Timer(Duration(milliseconds: 500), () {
    // Perform search after 500ms of no typing
    context.read<SearchBloc>().add(SearchEvent(searchController.text));
  });
});
```

---

## For Senior Developers

### Architecture Decisions

#### Why Clean Architecture Over Other Patterns?

**Comparison with alternatives:**

| Pattern | Pros | Cons | Best For |
|---------|------|------|----------|
| **Clean Architecture** | Testable, scalable, maintainable, framework-independent | More files, learning curve | Large apps, teams, long-term projects |
| **MVC** | Simple, familiar, fast to build | Tight coupling, hard to test, messy controllers | Small apps, prototypes |
| **MVVM** | Good separation, testable ViewModels | Can become bloated, two-way binding issues | Medium apps, reactive UIs |
| **Feature-First** | Organized by feature, fast navigation | Can duplicate code across features | Medium apps, clear feature boundaries |

**Why Clean Architecture for PRPROMPTS:**

1. **Enterprise-Ready:** Healthcare, fintech apps need separation for compliance audits
2. **Testing:** 70%+ coverage required, domain layer 100% testable
3. **Scalability:** 50+ features in large apps, architecture doesn't break down
4. **Team Collaboration:** Clear boundaries, juniors work on presentation, seniors on domain
5. **Framework Agnostic:** If Flutter dies, domain layer reusable in other frameworks

#### Dependency Injection Strategy

**This skill assumes get_it for DI:**

```dart
// lib/core/di/injection_container.dart
final sl = GetIt.instance;

Future<void> init() async {
  // BLoCs (registered as factories - new instance per call)
  sl.registerFactory(() => AuthBloc(
    loginWithEmail: sl(),
    registerWithEmail: sl(),
    logout: sl(),
  ));

  // Use Cases (registered as lazy singletons - created when first used)
  sl.registerLazySingleton(() => LoginWithEmail(sl()));
  sl.registerLazySingleton(() => RegisterWithEmail(sl()));
  sl.registerLazySingleton(() => Logout(sl()));

  // Repositories (registered as lazy singletons)
  sl.registerLazySingleton<AuthRepository>(
    () => AuthRepositoryImpl(
      remoteDataSource: sl(),
      localDataSource: sl(),
      networkInfo: sl(),
    ),
  );

  // Data Sources (registered as lazy singletons)
  sl.registerLazySingleton<AuthRemoteDataSource>(
    () => AuthRemoteDataSourceImpl(dio: sl()),
  );
  sl.registerLazySingleton<AuthLocalDataSource>(
    () => AuthLocalDataSourceImpl(
      secureStorage: sl(),
      sharedPreferences: sl(),
    ),
  );

  // External (registered as singletons - created immediately)
  final sharedPreferences = await SharedPreferences.getInstance();
  sl.registerSingleton<SharedPreferences>(sharedPreferences);
  sl.registerSingleton<FlutterSecureStorage>(FlutterSecureStorage());
  sl.registerSingleton<Dio>(_createDio());
}

Dio _createDio() {
  final dio = Dio(BaseOptions(
    baseUrl: 'https://api.example.com',
    connectTimeout: Duration(seconds: 30),
    receiveTimeout: Duration(seconds: 30),
  ));

  // Add interceptors
  dio.interceptors.add(LogInterceptor(responseBody: true));
  dio.interceptors.add(AuthInterceptor()); // Custom JWT interceptor

  return dio;
}
```

**DI Best Practices:**

1. **Factory vs Singleton:**
   - Factory: BLoCs (need fresh state per screen)
   - Lazy Singleton: Use cases, repositories (stateless, expensive to create)
   - Singleton: External dependencies (SharedPreferences, Dio)

2. **Interface Registration:**
   ```dart
   // Register interface type, not implementation
   sl.registerLazySingleton<AuthRepository>( // Interface
     () => AuthRepositoryImpl(...), // Implementation
   );
   ```

3. **Testing:**
   ```dart
   // Easy to mock in tests
   setUp(() {
     sl.registerLazySingleton<AuthRepository>(
       () => MockAuthRepository(),
     );
   });
   ```

#### Error Handling Architecture

**Comprehensive error handling with Either<Failure, T>:**

```dart
// Core failures
abstract class Failure extends Equatable {
  final String message;
  const Failure({required this.message});

  @override
  List<Object?> get props => [message];
}

class ServerFailure extends Failure {
  const ServerFailure({required super.message});
}

class NetworkFailure extends Failure {
  const NetworkFailure({required super.message});
}

class CacheFailure extends Failure {
  const CacheFailure({required super.message});
}

class ValidationFailure extends Failure {
  const ValidationFailure({required super.message});
}

class AuthFailure extends Failure {
  const AuthFailure({required super.message});
}

// Usage in BLoC
result.fold(
  (failure) {
    if (failure is NetworkFailure) {
      emit(AuthError(message: 'No internet connection'));
    } else if (failure is AuthFailure) {
      emit(AuthError(message: failure.message));
    } else if (failure is ValidationFailure) {
      emit(AuthError(message: failure.message));
    } else {
      emit(AuthError(message: 'An unexpected error occurred'));
    }
  },
  (user) => emit(Authenticated(user: user)),
);
```

**Why Either over try/catch:**

1. **Explicit Error Handling:** Compiler forces you to handle both success and failure
2. **Type Safety:** Know exactly what failures can occur
3. **Composability:** Chain operations with flatMap, map
4. **Testability:** Easy to test both paths

**Alternative: Result type (if preferred):**

```dart
sealed class Result<T> {
  const Result();
}

class Success<T> extends Result<T> {
  final T data;
  const Success(this.data);
}

class Error<T> extends Result<T> {
  final Failure failure;
  const Error(this.failure);
}

// Pattern matching (Dart 3.0+)
switch (result) {
  case Success(data: final user):
    emit(Authenticated(user: user));
  case Error(failure: final failure):
    emit(AuthError(message: failure.message));
}
```

#### State Management Alternatives

**While this skill generates BLoC, you can adapt to other patterns:**

**Riverpod:**

```dart
// Domain layer stays the same
// Replace BLoC with StateNotifier

@riverpod
class AuthNotifier extends _$AuthNotifier {
  @override
  AuthState build() => const AuthInitial();

  Future<void> login(String email, String password) async {
    state = const AuthLoading();

    final result = await ref.read(loginUseCaseProvider)(LoginParams(
      email: email,
      password: password,
    ));

    state = result.fold(
      (failure) => AuthError(message: failure.message),
      (user) => Authenticated(user: user),
    );
  }
}

// In UI
ref.listen<AuthState>(authNotifierProvider, (previous, next) {
  if (next is AuthError) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text(next.message)),
    );
  }
});

final authState = ref.watch(authNotifierProvider);
```

**MobX:**

```dart
// Replace BLoC with Store

part 'auth_store.g.dart';

class AuthStore = _AuthStore with _$AuthStore;

abstract class _AuthStore with Store {
  final LoginWithEmail loginUseCase;

  _AuthStore({required this.loginUseCase});

  @observable
  AuthState state = const AuthInitial();

  @action
  Future<void> login(String email, String password) async {
    state = const AuthLoading();

    final result = await loginUseCase(LoginParams(
      email: email,
      password: password,
    ));

    state = result.fold(
      (failure) => AuthError(message: failure.message),
      (user) => Authenticated(user: user),
    );
  }
}

// In UI
Observer(
  builder: (_) {
    final authState = authStore.state;
    if (authState is AuthLoading) {
      return CircularProgressIndicator();
    } else if (authState is Authenticated) {
      return HomeScreen();
    } else {
      return LoginForm();
    }
  },
);
```

**Redux:**

```dart
// Domain layer stays the same
// Replace BLoC with Redux actions/reducers

// Actions
class LoginAction {
  final String email;
  final String password;
  const LoginAction({required this.email, required this.password});
}

class LoginSuccessAction {
  final User user;
  const LoginSuccessAction(this.user);
}

class LoginFailureAction {
  final String error;
  const LoginFailureAction(this.error);
}

// Reducer
AuthState authReducer(AuthState state, dynamic action) {
  if (action is LoginAction) {
    return const AuthLoading();
  } else if (action is LoginSuccessAction) {
    return Authenticated(user: action.user);
  } else if (action is LoginFailureAction) {
    return AuthError(message: action.error);
  }
  return state;
}

// Middleware
void authMiddleware(Store<AppState> store, dynamic action, NextDispatcher next) {
  if (action is LoginAction) {
    loginUseCase(LoginParams(email: action.email, password: action.password))
        .then((result) {
      result.fold(
        (failure) => store.dispatch(LoginFailureAction(failure.message)),
        (user) => store.dispatch(LoginSuccessAction(user)),
      );
    });
  }
  next(action);
}
```

**Key Insight:** Clean Architecture allows swapping state management without touching domain/data layers.

#### Advanced Testing Strategies

**Golden Tests for UI Consistency:**

```dart
testWidgets('login screen golden test', (tester) async {
  await tester.pumpWidget(createWidgetUnderTest());

  await expectLater(
    find.byType(LoginScreen),
    matchesGoldenFile('goldens/login_screen.png'),
  );
});
```

**Parameterized Tests:**

```dart
void main() {
  group('Email Validation', () {
    final testCases = [
      ('valid@example.com', true),
      ('invalid-email', false),
      ('missing@domain', false),
      ('with spaces@example.com', false),
      ('válid@example.com', true), // Unicode
    ];

    for (final (email, expected) in testCases) {
      test('validates "$email" as ${expected ? "valid" : "invalid"}', () {
        final result = EmailValidator.validate(email);
        expect(result == null, expected);
      });
    }
  });
}
```

**Mocking HTTP Responses:**

```dart
class MockDioAdapter extends HttpClientAdapter {
  final Map<String, dynamic> mockResponses;

  MockDioAdapter(this.mockResponses);

  @override
  Future<ResponseBody> fetch(RequestOptions options, ...) async {
    final response = mockResponses[options.path];
    return ResponseBody.fromString(
      jsonEncode(response),
      200,
      headers: {
        Headers.contentTypeHeader: [Headers.jsonContentType],
      },
    );
  }
}

// In test
setUp(() {
  final dio = Dio();
  dio.httpClientAdapter = MockDioAdapter({
    '/auth/login': {
      'user': {...},
      'tokens': {...},
    },
  });
});
```

**Test Coverage Analysis:**

```bash
# Generate coverage
flutter test --coverage

# Generate HTML report
genhtml coverage/lcov.info -o coverage/html

# Extract coverage percentage
lcov --summary coverage/lcov.info | grep 'lines' | awk '{print $2}'

# Fail CI if coverage < 70%
COVERAGE=$(lcov --summary coverage/lcov.info | grep 'lines' | awk '{print $2}' | tr -d '%')
if (( $(echo "$COVERAGE < 70" | bc -l) )); then
  echo "Coverage $COVERAGE% is below 70%"
  exit 1
fi
```

### Compliance and Security

#### HIPAA Compliance Patterns

**If PRD specifies HIPAA, generated code includes:**

1. **PHI Encryption at Rest:**

```dart
class SecureStorage {
  final FlutterSecureStorage storage;
  final Encryptor encryptor;

  Future<void> storePHI(String key, String phi) async {
    final encrypted = await encryptor.encrypt(phi);
    await storage.write(key: key, value: encrypted);

    // Audit log
    await auditLogger.log(AuditEvent(
      action: 'PHI_WRITE',
      resource: key,
      userId: currentUserId,
      timestamp: DateTime.now(),
    ));
  }

  Future<String?> retrievePHI(String key) async {
    final encrypted = await storage.read(key: key);
    if (encrypted == null) return null;

    // Audit log
    await auditLogger.log(AuditEvent(
      action: 'PHI_READ',
      resource: key,
      userId: currentUserId,
      timestamp: DateTime.now(),
    ));

    return await encryptor.decrypt(encrypted);
  }
}
```

2. **Session Timeouts:**

```dart
class SessionManager {
  Timer? _timeout;
  final Duration inactivityLimit = Duration(minutes: 15);

  void resetTimeout() {
    _timeout?.cancel();
    _timeout = Timer(inactivityLimit, () {
      // Log out user
      authBloc.add(LogoutEvent());

      // Show session expired dialog
      showDialog(
        context: context,
        barrierDismissible: false,
        builder: (_) => AlertDialog(
          title: Text('Session Expired'),
          content: Text('For security, you have been logged out due to inactivity.'),
          actions: [
            TextButton(
              onPressed: () => Navigator.of(context).pushReplacementNamed('/login'),
              child: Text('Log In Again'),
            ),
          ],
        ),
      );
    });
  }
}
```

3. **Audit Logging:**

```dart
class AuditLogger {
  final AuditRepository repository;

  Future<void> log(AuditEvent event) async {
    await repository.saveEvent(AuditEventModel(
      id: Uuid().v4(),
      userId: event.userId,
      action: event.action,
      resource: event.resource,
      timestamp: event.timestamp,
      ipAddress: await NetworkInfo.getIpAddress(),
      deviceId: await DeviceInfo.getDeviceId(),
    ));
  }
}

// Usage in use cases
class ViewPatientRecord implements UseCase<Patient, ViewPatientParams> {
  @override
  Future<Either<Failure, Patient>> call(ViewPatientParams params) async {
    final result = await repository.getPatient(params.patientId);

    result.fold(
      (_) => null,
      (patient) async {
        // Log PHI access
        await auditLogger.log(AuditEvent(
          action: 'VIEW_PATIENT_RECORD',
          resource: 'patients/${patient.id}',
          userId: params.currentUserId,
          timestamp: DateTime.now(),
        ));
      },
    );

    return result;
  }
}
```

#### PCI-DSS Compliance Patterns

**If PRD specifies PCI-DSS, generated code includes:**

1. **Payment Tokenization:**

```dart
// NEVER store credit card numbers
// Use tokenization (Stripe, PayPal, Braintree)

class PaymentService {
  final StripeService stripe;

  Future<Either<Failure, PaymentIntent>> processPayment({
    required int amount,
    required String currency,
  }) async {
    try {
      // Create payment intent (server-side)
      final paymentIntent = await stripe.createPaymentIntent(
        amount: amount,
        currency: currency,
      );

      // Client confirms with card details
      // Card details go directly to Stripe, NEVER to your backend
      final confirmedIntent = await Stripe.instance.confirmPayment(
        paymentIntentClientSecret: paymentIntent.clientSecret,
        data: PaymentMethodParams.card(
          paymentMethodData: PaymentMethodData(),
        ),
      );

      return Right(confirmedIntent);
    } catch (e) {
      return Left(PaymentFailure(message: e.toString()));
    }
  }
}
```

2. **Secure Display of Card Info:**

```dart
// Only show last 4 digits
class PaymentMethodWidget extends StatelessWidget {
  final PaymentMethod paymentMethod;

  @override
  Widget build(BuildContext context) {
    return ListTile(
      leading: Icon(_getCardIcon(paymentMethod.brand)),
      title: Text('•••• •••• •••• ${paymentMethod.last4}'),
      subtitle: Text('Expires ${paymentMethod.expiryMonth}/${paymentMethod.expiryYear}'),
    );
  }
}
```

#### GDPR Compliance Patterns

**If PRD specifies GDPR, generated code includes:**

1. **Data Export (Right to Data Portability):**

```dart
class ExportUserData implements UseCase<File, ExportParams> {
  @override
  Future<Either<Failure, File>> call(ExportParams params) async {
    final userData = await repository.getUserData(params.userId);

    final jsonData = {
      'user_profile': userData.profile.toJson(),
      'orders': userData.orders.map((o) => o.toJson()).toList(),
      'preferences': userData.preferences.toJson(),
      'activity_log': userData.activities.map((a) => a.toJson()).toList(),
    };

    final file = File('${params.outputPath}/user_data_${params.userId}.json');
    await file.writeAsString(jsonEncode(jsonData));

    return Right(file);
  }
}
```

2. **Data Deletion (Right to be Forgotten):**

```dart
class DeleteUserData implements UseCase<void, DeleteParams> {
  @override
  Future<Either<Failure, void>> call(DeleteParams params) async {
    // 1. Delete personal data
    await repository.deleteUserProfile(params.userId);

    // 2. Anonymize activity logs (keep for analytics)
    await repository.anonymizeUserActivities(params.userId);

    // 3. Delete authentication data
    await authRepository.deleteUserAuth(params.userId);

    // 4. Remove from third-party services
    await analyticsService.deleteUser(params.userId);

    // 5. Audit log
    await auditLogger.log(AuditEvent(
      action: 'USER_DATA_DELETED',
      resource: 'users/${params.userId}',
      timestamp: DateTime.now(),
    ));

    return const Right(null);
  }
}
```

3. **Consent Management:**

```dart
class ConsentManager {
  final ConsentRepository repository;

  Future<bool> hasConsent(String userId, ConsentType type) async {
    final consent = await repository.getConsent(userId, type);
    return consent?.granted ?? false;
  }

  Future<void> grantConsent(String userId, ConsentType type) async {
    await repository.saveConsent(Consent(
      userId: userId,
      type: type,
      granted: true,
      grantedAt: DateTime.now(),
    ));
  }

  Future<void> revokeConsent(String userId, ConsentType type) async {
    await repository.saveConsent(Consent(
      userId: userId,
      type: type,
      granted: false,
      revokedAt: DateTime.now(),
    ));
  }
}

enum ConsentType {
  essential, // Required for app to function
  analytics, // Usage analytics
  marketing, // Marketing emails
  thirdParty, // Sharing with third parties
}
```

### CI/CD Integration

**Generated code is CI/CD-ready:**

**GitHub Actions Workflow:**

```yaml
name: Flutter CI

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - uses: subosito/flutter-action@v2
        with:
          flutter-version: '3.16.0'

      - name: Install dependencies
        run: flutter pub get

      - name: Run code generation
        run: flutter pub run build_runner build --delete-conflicting-outputs

      - name: Analyze code
        run: flutter analyze

      - name: Run tests
        run: flutter test --coverage

      - name: Check coverage
        run: |
          COVERAGE=$(lcov --summary coverage/lcov.info | grep 'lines' | awk '{print $2}' | tr -d '%')
          if (( $(echo "$COVERAGE < 70" | bc -l) )); then
            echo "Coverage $COVERAGE% is below 70%"
            exit 1
          fi

      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v3
        with:
          files: ./coverage/lcov.info

  build-android:
    runs-on: ubuntu-latest
    needs: test
    steps:
      - uses: actions/checkout@v3

      - uses: subosito/flutter-action@v2

      - name: Build APK
        run: flutter build apk --release

      - name: Upload APK
        uses: actions/upload-artifact@v3
        with:
          name: app-release.apk
          path: build/app/outputs/flutter-apk/app-release.apk

  build-ios:
    runs-on: macos-latest
    needs: test
    steps:
      - uses: actions/checkout@v3

      - uses: subosito/flutter-action@v2

      - name: Build IPA
        run: flutter build ios --release --no-codesign

      - name: Upload IPA
        uses: actions/upload-artifact@v3
        with:
          name: Runner.app
          path: build/ios/iphoneos/Runner.app
```

**Pre-commit Hooks:**

```bash
# .git/hooks/pre-commit
#!/bin/bash

echo "Running pre-commit checks..."

# Format code
echo "Formatting code..."
dart format lib/ test/

# Analyze code
echo "Analyzing code..."
flutter analyze
if [ $? -ne 0 ]; then
  echo "❌ Flutter analyze found issues. Please fix them before committing."
  exit 1
fi

# Run tests
echo "Running tests..."
flutter test
if [ $? -ne 0 ]; then
  echo "❌ Tests failed. Please fix them before committing."
  exit 1
fi

echo "✅ All checks passed. Proceeding with commit."
```

---

## Usage Examples

### Example 1: Implement Authentication Feature

**IMPLEMENTATION_PLAN.md:**

```markdown
### Feature 1: Authentication
**Priority:** HIGH
**Estimated Time:** 6-8 hours

**Requirements:**
- Email/password login and registration
- JWT token management with refresh
- Session persistence
- Biometric authentication (optional)

**API Endpoints:**
- POST /api/auth/register
- POST /api/auth/login
- POST /api/auth/refresh
- POST /api/auth/logout

**Data Models:**
```dart
class User {
  final String id;
  final String email;
  final String? displayName;
  final bool emailVerified;
}

class AuthTokens {
  final String accessToken;
  final String refreshToken;
  final DateTime expiresAt;
}
```

**UI Screens:**
- LoginScreen
- RegisterScreen
- ForgotPasswordScreen
```

**Run the skill:**

```bash
@claude use skill automation/feature-implementer

# Input:
# Feature name: Authentication
# Test coverage target: 80
# Generate integration tests: yes
```

**Output:**

```
✅ Feature "Authentication" implemented successfully!

📊 Summary:
- Files Created: 24
  - Domain: 7 files
  - Data: 8 files
  - Presentation: 9 files
- Test Coverage: 82.4%
- Security Validated: Yes
- Architecture Compliant: Yes

📁 Files Created:
Domain Layer:
  - lib/features/auth/domain/entities/user.dart
  - lib/features/auth/domain/entities/auth_tokens.dart
  - lib/features/auth/domain/usecases/login_with_email.dart
  - lib/features/auth/domain/usecases/register_with_email.dart
  - lib/features/auth/domain/usecases/logout.dart
  - lib/features/auth/domain/usecases/get_current_user.dart
  - lib/features/auth/domain/repositories/auth_repository.dart

Data Layer:
  - lib/features/auth/data/models/user_model.dart
  - lib/features/auth/data/models/auth_tokens_model.dart
  - lib/features/auth/data/datasources/auth_remote_data_source.dart
  - lib/features/auth/data/datasources/auth_local_data_source.dart
  - lib/features/auth/data/repositories/auth_repository_impl.dart

Presentation Layer:
  - lib/features/auth/presentation/bloc/auth_bloc.dart
  - lib/features/auth/presentation/bloc/auth_event.dart
  - lib/features/auth/presentation/bloc/auth_state.dart
  - lib/features/auth/presentation/pages/login_screen.dart
  - lib/features/auth/presentation/pages/register_screen.dart
  - lib/features/auth/presentation/pages/forgot_password_screen.dart
  - lib/features/auth/presentation/widgets/custom_text_field.dart
  - lib/features/auth/presentation/widgets/primary_button.dart

Tests:
  - test/features/auth/domain/usecases/login_with_email_test.dart
  - test/features/auth/data/models/user_model_test.dart
  - test/features/auth/data/repositories/auth_repository_impl_test.dart
  - test/features/auth/presentation/pages/login_screen_test.dart
  - integration_test/auth_test.dart

🎉 Ready for code review and integration!
```

### Example 2: Implement User Profile Feature

**IMPLEMENTATION_PLAN.md:**

```markdown
### Feature 2: User Profile
**Priority:** MEDIUM
**Dependencies:** Authentication
**Estimated Time:** 4-6 hours

**Requirements:**
- View user profile (name, email, photo, bio)
- Edit profile information
- Upload profile photo
- Change password

**API Endpoints:**
- GET /api/users/me
- PUT /api/users/me
- POST /api/users/me/photo
- PUT /api/users/me/password

**Data Models:**
```dart
class UserProfile {
  final String id;
  final String name;
  final String email;
  final String? bio;
  final String? photoUrl;
  final DateTime updatedAt;
}
```

**UI Screens:**
- ProfileScreen (view)
- EditProfileScreen (edit)
- ChangePasswordScreen
```

**Run the skill:**

```bash
@claude use skill automation/feature-implementer

# Input:
# Feature name: User Profile
# Test coverage target: 75
# Generate integration tests: no
```

**Result:**

```
✅ Feature "User Profile" implemented successfully!

📊 Summary:
- Files Created: 20
- Test Coverage: 77.1%
- Implementation Time: 6 minutes
```

### Example 3: Implement Payment Processing (PCI-DSS)

**IMPLEMENTATION_PLAN.md:**

```markdown
### Feature 5: Payment Processing
**Priority:** HIGH
**Compliance:** PCI-DSS
**Estimated Time:** 8-10 hours

**Requirements:**
- Process credit card payments via Stripe
- Store payment methods securely (tokenized)
- View payment history
- Refund payments

**Security Requirements:**
- NEVER store full credit card numbers
- Use Stripe tokenization
- HTTPS only
- PCI-DSS Level 1 compliance

**API Endpoints:**
- POST /api/payments/intents
- POST /api/payments/confirm
- GET /api/payments/history
- POST /api/payments/{id}/refund

**Data Models:**
```dart
class Payment {
  final String id;
  final int amount;
  final String currency;
  final PaymentStatus status;
  final DateTime createdAt;
}

class PaymentMethod {
  final String id;
  final String brand; // visa, mastercard, etc.
  final String last4;
  final int expiryMonth;
  final int expiryYear;
}
```

**UI Screens:**
- PaymentScreen (enter card)
- PaymentMethodsScreen (saved cards)
- PaymentHistoryScreen
```

**Run the skill:**

```bash
@claude use skill automation/feature-implementer

# Input:
# Feature name: Payment Processing
# Test coverage target: 90
# Generate integration tests: yes
```

**Security Validation Output:**

```
🔒 Security Validation:

✅ PCI-DSS Compliance:
  - Stripe tokenization implemented
  - No credit card storage
  - Only last 4 digits displayed
  - HTTPS enforced
  - Payment details sent directly to Stripe

✅ Payment Security:
  - 3D Secure support added
  - Payment intent confirmation on server
  - Idempotency keys for duplicate prevention
  - Webhook signature verification

✅ Data Protection:
  - Payment history encrypted at rest
  - Audit logging for all payment operations
  - PII handling compliant with GDPR
```

---

## Troubleshooting

### Common Issues

#### 1. "Feature not found in IMPLEMENTATION_PLAN.md"

**Problem:** Skill can't locate the feature in your plan.

**Solution:**
- Ensure feature name matches exactly (case-sensitive)
- Check IMPLEMENTATION_PLAN.md exists at `docs/IMPLEMENTATION_PLAN.md`
- Verify feature has all required sections

#### 2. "flutter analyze shows errors"

**Problem:** Generated code has linting issues.

**Solution:**
```bash
# Fix formatting
dart format lib/ test/

# Check specific errors
flutter analyze --verbose

# Common fixes:
# - Add missing imports
# - Fix typos in file paths
# - Update pubspec.yaml dependencies
```

#### 3. "Tests failing after generation"

**Problem:** Some tests don't pass initially.

**Solution:**
```bash
# Generate mocks
flutter pub run build_runner build --delete-conflicting-outputs

# Update golden files
flutter test --update-goldens

# Check specific test
flutter test test/features/auth/domain/usecases/login_test.dart
```

#### 4. "Coverage below target"

**Problem:** Test coverage is 65%, target is 70%.

**Solution:**
- Identify uncovered lines:
```bash
flutter test --coverage
genhtml coverage/lcov.info -o coverage/html
open coverage/html/index.html  # View in browser
```

- Add tests for red (uncovered) lines:
```dart
// Example: Cover edge case
test('should return ValidationFailure for null email', () {
  final result = usecase(LoginParams(email: null, password: 'pass'));
  expect(result.isLeft(), true);
});
```

#### 5. "API calls failing in tests"

**Problem:** Tests try to make real HTTP requests.

**Solution:**
- Mock Dio:
```dart
class MockDio extends Mock implements Dio {}

setUp(() {
  mockDio = MockDio();
  remoteDataSource = AuthRemoteDataSourceImpl(dio: mockDio);
});

test('...', () {
  when(mockDio.post(any, data: anyNamed('data')))
      .thenAnswer((_) async => Response(
            data: {'user': {...}},
            statusCode: 200,
            requestOptions: RequestOptions(path: ''),
          ));
});
```

---

## FAQ

**Q: Can I use this skill on an existing project?**

A: Yes, but:
1. Run `flutter-bootstrapper` first if Clean Architecture structure doesn't exist
2. Ensure no file conflicts (skill won't overwrite existing files)
3. May need to adjust imports if your project structure differs

**Q: Does this work with Firebase Auth instead of custom backend?**

A: Yes! Modify `IMPLEMENTATION_PLAN.md`:
```markdown
**API Endpoints:**
- Use Firebase Auth SDK (no custom endpoints)

**Technical Details:**
- firebase_auth: ^4.15.0
- FirebaseAuth.instance.signInWithEmailAndPassword()
```

The skill will generate code adapted for Firebase.

**Q: Can I customize the generated BLoC to use Cubit instead?**

A: Not automatically, but easy to refactor:
- Skill generates full BLoC (events + states + bloc)
- Convert to Cubit by:
  1. Extend Cubit instead of Bloc
  2. Remove events, use methods directly
  3. Call `emit()` in methods

**Q: How do I handle pagination in generated code?**

A: Add to IMPLEMENTATION_PLAN.md:
```markdown
**Requirements:**
- Paginated list of posts (20 per page)
- Infinite scroll support

**Data Models:**
```dart
class PaginatedResponse<T> {
  final List<T> items;
  final int page;
  final int totalPages;
  final bool hasMore;
}
```

**API Endpoints:**
- GET /api/posts?page=1&limit=20
```

Skill will generate pagination handling in repository and BLoC.

**Q: Does this support offline-first apps?**

A: Yes! The generated repository pattern includes:
- Local caching (SQLite or Hive)
- Network connectivity checks
- Fallback to cached data when offline
- Sync queue for pending operations

**Q: Can I generate multiple features at once?**

A: Not directly (to maintain quality), but you can:
1. Run skill for feature A
2. Immediately run again for feature B
3. Use `automation-orchestrator` skill for batch processing

**Q: How do I add custom error types?**

A: Extend `Failure` base class:
```dart
// In lib/core/error/failures.dart
class PaymentFailure extends Failure {
  const PaymentFailure({required super.message});
}

// Use in repository
catch (StripeException e) {
  return Left(PaymentFailure(message: e.message));
}
```

**Q: Does this work for web and desktop?**

A: Yes! Generated code is platform-agnostic. Just note:
- FlutterSecureStorage: Use encrypted_shared_preferences on web
- Biometrics: Not available on web
- File uploads: Use different packages per platform

**Q: Can I use this with GraphQL instead of REST?**

A: Yes! Update data source implementation:
```dart
// Replace Dio with graphql_flutter
class AuthRemoteDataSourceImpl implements AuthRemoteDataSource {
  final GraphQLClient client;

  @override
  Future<UserModel> loginWithEmail({...}) async {
    final result = await client.mutate(MutationOptions(
      document: gql(loginMutation),
      variables: {'email': email, 'password': password},
    ));

    if (result.hasException) {
      throw ServerException(message: result.exception.toString());
    }

    return UserModel.fromJson(result.data!['login']);
  }
}
```

---

## Additional Resources

- **PRPROMPTS Methodology:** See `docs/PRPROMPTS-SPECIFICATION.md`
- **Clean Architecture Guide:** See `docs/ARCHITECTURE.md`
- **Security Best Practices:** See `PRPROMPTS/16-security_and_compliance.md`
- **Testing Strategies:** See `docs/TESTING-GUIDE.md`
- **CI/CD Setup:** See `.github/workflows/` examples

---

**Last Updated:** 2025-10-24
**Version:** 1.0.0
**Skill Status:** ✅ Implemented