Skip to content
AI CraftsmanSUPERPOWERS
Blog
  • Craftsmanship
  • DDD
  • Clean Architecture

The Iron Law Pattern: Zero Drift Across Sessions

How loading canonical examples before generation guarantees consistent code quality.

Alexandre Mallet2 min read

Every team has a "correct way" to write things. A canonical Repository implementation. The exact shape of a Value Object. The way a Command Handler is structured. This knowledge lives in senior developers' heads, in occasional code review comments, and: if you're lucky: in a documented ADR somewhere.

When Claude generates code, it ignores all of that. It produces something reasonable by its own standards, which are averaged from millions of open-source repositories. Not your standards. Theirs.

The Iron Law Pattern closes this gap.

What Makes It Different from Templates

Templates are static. You write a template once, Claude fills in the blanks. The problem: templates go stale, they don't capture nuance, and developers stop updating them after the first sprint.

The Iron Law Pattern is dynamic. Before generating anything, it fetches the actual production file that best matches what you're about to create. Not a template: a living example from your codebase.

The prompt sent to Claude isn't "write a Repository." It's:

"Here is an existing Repository from this codebase that follows our conventions exactly. Use it as the canonical reference. Generate a new Repository for OrderAggregate that matches this structure precisely."

The difference is enormous. Claude isn't inferring your standards from scratch: it's replicating a proven example.

How It Works in Practice

When you run /craftsman:scaffold Repository OrderAggregate, the plugin:

  1. Scans your codebase for the most relevant existing file (same type, same layer)
  2. Loads it as the "iron law reference" in the context
  3. Injects your rules on top (the MUST constraints from your config)
  4. Generates the new file with both the example and the rules as hard constraints

Here's what that canonical reference looks like for a PHP Repository:

<?php

declare(strict_types=1);

namespace App\Infrastructure\Persistence\Doctrine;

use App\Domain\Order\OrderRepository;
use App\Domain\Order\Order;
use App\Domain\Order\OrderId;
use Doctrine\ORM\EntityManagerInterface;

final class DoctrineOrderRepository implements OrderRepository
{
    public function __construct(
        private readonly EntityManagerInterface $em,
    ) {}

    public function findById(OrderId $id): ?Order
    {
        return $this->em->find(Order::class, $id->value());
    }

    public function save(Order $order): void
    {
        $this->em->persist($order);
    }
}

And the TypeScript equivalent for a React hook:

import { useQuery } from '@tanstack/react-query';
import type { Order } from '../domain/Order';

interface UseOrderResult {
  readonly order: Order | undefined;
  readonly isLoading: boolean;
  readonly error: Error | null;
}

export const useOrder = (orderId: string): UseOrderResult => {
  const { data, isLoading, error } = useQuery({
    queryKey: ['order', orderId],
    queryFn: () => fetchOrder(orderId),
    enabled: orderId.length > 0,
  });

  return { order: data, isLoading, error: error as Error | null };
};

Claude sees these, sees your rules, and generates code that looks like it was written by the same developer who wrote the originals. Because in a meaningful sense, it was.

Why "Iron Law"

The name comes from the immutability of the constraint. It's not a suggestion. It's not a style preference. It's the law for this codebase.

When the rule is load-canonical-first, there's no drift path. Each new file reinforces the pattern rather than diverging from it. The codebase becomes more consistent over time, not less: which is the opposite of what most teams experience with AI assistance.

The Iron Law Pattern is one of the 10 superpowers in the plugin. It's also the one that has the most immediate, visible impact on code consistency from day one.