DEV Community

gentic news
gentic news

Posted on • Originally published at gentic.news

How to Build Architecture Guardrails in CLAUDE.md

Add a decision matrix to CLAUDE.md to stop Claude Code from mixing legacy and new architecture patterns during migrations. This technique from a 827-commit Flutter project cut migration time ~30%.

Key Takeaways

  • Add a decision matrix to CLAUDE.md to stop Claude Code from mixing legacy and new architecture patterns during migrations.
  • This technique from a 827-commit Flutter project cut migration time ~30%.

What Changed — The Real Problem with AI-Assisted Migrations

When you ask Claude Code to fix a bug in legacy code, its default instinct is to "improve" it. It sees a try/catch block and wants to refactor it into a fancier error-handling pattern. That instinct is correct for new features — and catastrophic during a migration.

One developer documented this exact problem across 827 commits in a Flutter e-commerce app for a Swiss retailer. The app had an 85% crash-free rate and three different error handling styles. The fix wasn't a smarter model. It was a CLAUDE.md file with architecture guardrails.

What It Means For You — Decision Matrices Over Guidelines

Most CLAUDE.md files list architecture rules like "use Clean Architecture" or "prefer Riverpod for state management." That's not enough. The AI needs conditional logic — a decision matrix that tells it which pattern to use depending on what it's doing.

Here's the simplified decision matrix from that production project:

## Architecture

This project uses Clean Architecture with feature-first organization.

![Cover image for AI-Assisted Flutter Development: Claude Code in Production](https://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fkhal.it%2Fblog%2Fai-assisted-development-production-flutter.webp)


### Decision Matrix
- Touching existing unmigrated code? -> Follow legacy patterns
- Writing a new feature? -> Use Clean Architecture
- Migrating an existing feature? -> Follow migration checklist

### Error Handling
- New code: TaskEither<AppFailure, T> from fpdart
- Legacy code: existing try/catch (do NOT refactor)

### State Management
- New features: Riverpod with code generation
- AsyncNotifier for async state
- Do NOT use ChangeNotifier, StateNotifier, or Bloc
Enter fullscreen mode Exit fullscreen mode

The key insight: the decision matrix is not documentation for humans. Humans have context from standups and PR reviews. This is documentation for the AI — explicit, unambiguous, with decision trees instead of guidelines.

Try It Now — Build Your Own Guardrails

Step 1: Map your codebase's architectural states

Identify every valid pattern currently in production. For the Flutter app, that meant:

  • Legacy code: try/catch, ChangeNotifier
  • New code: TaskEither, AsyncNotifier with Riverpod
  • Transition code: half-migrated features (follow migration checklist)

Step 2: Create custom skills for each mode

Custom skills are slash commands in Claude Code that override baseline context. Create three:

/migration — Enforces a strict sequence (domain layer first, then data, then presentation, then tests).

/legacy-code — "Follow existing patterns. Do not introduce Clean Architecture imports. Match the style of surrounding code."

/new-feature — "Use Clean Architecture with Riverpod and TaskEither. Follow the project's current conventions."

Step 3: Test with a real task

Ask Claude Code to fix a bug in legacy code without the guardrails. Then ask again with /legacy-code active. Compare the diffs. The second version should only touch the bug, not refactor surrounding code.

Why This Works — The Token Economics of Context

The AI's instinct to "improve" code comes from its training data, where writing clean code is rewarded. During a migration, "best code possible" is context-dependent. A bug fix in unmigrated code should follow legacy patterns. The same logic written during migration should follow the new architecture. No model training covers that distinction — it has to be configured per project.

The result from this production project: ~30% faster migration timeline. Not because the AI wrote perfect code, but because it handled the mechanical parts while the developer made decisions requiring judgment.


Source: dev.to


Originally published on gentic.news

Top comments (0)