Case Studies

Proto Artisan: AI Code Prototyper

Proto Artisan is an intelligent code analyzer that transforms AI-generated prototypes into production-ready applications by automatically detecting patterns, extracting reusable components, and reorganizing code according to LEGO Builder principles.

This case study explores how we built a tool that bridges the gap between rapid AI prototyping and maintainable software architecture.

The Problem: AI-Generated Technical Debt

AI coding assistants like Claude, ChatGPT, and GitHub Copilot have revolutionized prototyping. You can describe a feature and get working code in minutes. But there's a catch:

Developers faced a choice: spend hours manually refactoring AI code, or accept technical debt from day one. Proto Artisan offers a third option: automated refactoring guided by LEGO Builder principles.

The Solution: Intelligent Pattern Detection

Architecture Overview

Proto Artisan consists of three main systems:

// System Architecture
src/
├── analyzers/           // Detect patterns and duplications
├── extractors/          // Pull out reusable blocks
├── generators/          // Create modular file structure
├── validators/          // Ensure LEGO compliance
└── orchestrators/       // Coordinate the refactoring process

Pattern Detection Engine

The core of Proto Artisan is its pattern detection system:

// analyzers/pattern-detector.js (29 lines)
export function detectPatterns(codeString) {
    const ast = parseToAST(codeString);
    const patterns = {
        utilities: findPureFunctions(ast),
        builders: findObjectConstructors(ast),
        guards: findValidators(ast),
        processors: findBusinessLogic(ast),
        duplicates: findDuplicateLogic(ast)
    };

    return patterns;
}

// analyzers/duplicate-finder.js (27 lines)
export function findDuplicateLogic(ast) {
    const functionBodies = extractFunctionBodies(ast);
    const signatures = functionBodies.map(computeSignature);

    const duplicates = [];
    for (let i = 0; i < signatures.length; i++) {
        for (let j = i + 1; j < signatures.length; j++) {
            if (similarityScore(signatures[i], signatures[j]) > 0.8) {
                duplicates.push({
                    first: functionBodies[i],
                    second: functionBodies[j],
                    similarity: similarityScore(signatures[i], signatures[j])
                });
            }
        }
    }

    return duplicates;
}

Automatic Block Extraction

Once patterns are detected, Proto Artisan extracts them into proper LEGO blocks:

// extractors/utility-extractor.js (28 lines)
export function extractUtilities(patterns) {
    const utilities = [];

    patterns.utilities.forEach(func => {
        const utility = {
            name: generateDescriptiveName(func),
            code: func.code,
            inputs: func.parameters,
            output: func.returnType,
            category: categorizeUtility(func)
        };

        // Ensure LEGO compliance
        if (utility.code.split('\n').length > 30) {
            utility.needsRefactoring = true;
            utility.suggestions = suggestBreakdown(utility.code);
        }

        utilities.push(utility);
    });

    return utilities;
}

Real-World Example: Refactoring a Monolith

Before: AI-Generated Monolith (127 lines)

// AI generated this as a single function
async function handleUserRegistration(req, res) {
    // Validation (15 lines)
    const email = req.body.email;
    if (!email || !email.includes('@')) {
        return res.status(400).json({ error: 'Invalid email' });
    }
    // ... more validation

    // Database operations (25 lines)
    const userExists = await db.query('SELECT * FROM users WHERE email = $1', [email]);
    if (userExists.rows.length > 0) {
        return res.status(409).json({ error: 'User exists' });
    }
    // ... more database code

    // Password hashing (12 lines)
    const salt = await bcrypt.genSalt(10);
    const hashedPassword = await bcrypt.hash(req.body.password, salt);
    // ... more hashing logic

    // Email sending (20 lines)
    const transporter = nodemailer.createTransport({ /* config */ });
    const mailOptions = { /* options */ };
    await transporter.sendMail(mailOptions);
    // ... more email code

    // Token generation (15 lines)
    const token = jwt.sign({ userId: user.id }, process.env.JWT_SECRET);
    // ... more token logic

    // Response handling (10 lines)
    res.json({ success: true, token, user });
}

After: Proto Artisan Refactoring

// utilities/email-validator.js (8 lines)
export function isValidEmail(email) {
    return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}

// utilities/password-hasher.js (12 lines)
export async function hashPassword(password) {
    const salt = await bcrypt.genSalt(10);
    return bcrypt.hash(password, salt);
}

// guards/user-existence-guard.js (15 lines)
export async function requireNewUser(email) {
    const existing = await getUserByEmail(email);
    if (existing) {
        throw new Error('User already exists');
    }
}

// builders/user-builder.js (18 lines)
export function buildUser(userData, hashedPassword) {
    return {
        email: userData.email,
        password: hashedPassword,
        name: userData.name,
        createdAt: new Date()
    };
}

// bridges/email-bridge.js (22 lines)
export async function sendWelcomeEmail(email, name) {
    const transporter = createTransporter();
    const mailOptions = buildWelcomeEmail(email, name);
    await transporter.sendMail(mailOptions);
}

// utilities/token-generator.js (14 lines)
export function generateAuthToken(userId) {
    return jwt.sign(
        { userId },
        process.env.JWT_SECRET,
        { expiresIn: '7d' }
    );
}

// controllers/registration-controller.js (26 lines)
export async function handleUserRegistration(req, res) {
    try {
        const { email, password, name } = req.body;

        if (!isValidEmail(email)) {
            return res.status(400).json({ error: 'Invalid email' });
        }

        await requireNewUser(email);

        const hashedPassword = await hashPassword(password);
        const user = buildUser({ email, name }, hashedPassword);

        await saveUser(user);
        await sendWelcomeEmail(email, name);

        const token = generateAuthToken(user.id);

        res.json({ success: true, token, user });
    } catch (error) {
        res.status(500).json({ error: error.message });
    }
}

The Technical Stack

Core Technologies

Key Features

1. Smart Naming

Proto Artisan generates meaningful names based on function behavior:

// analyzers/name-generator.js (24 lines)
export function generateDescriptiveName(funcNode) {
    const verbs = extractVerbs(funcNode);
    const nouns = extractNouns(funcNode);

    if (funcNode.returnsPure) return `${verbs[0]}${capitalize(nouns[0])}`;
    if (funcNode.buildsObject) return `build${capitalize(nouns[0])}`;
    if (funcNode.validates) return `validate${capitalize(nouns[0])}`;
    if (funcNode.checks) return `is${capitalize(nouns[0])}Valid`;

    return `${verbs[0]}${capitalize(nouns[0])}`;
}

2. LEGO Compliance Validation

Every extracted block is validated against LEGO Builder rules:

3. Visual Diff Comparison

Developers can see before/after comparisons with:

Results and Impact

Measurable Improvements

Developer Productivity

Teams using Proto Artisan report:

Lessons Learned

1. AI Code Has Patterns

Despite different prompts, AI assistants generate similar patterns. These patterns are predictable and can be detected algorithmically.

2. Naming is Critical

Automatically generated names must be descriptive. Poor names defeat the purpose of modular code.

3. Developers Need Control

Proto Artisan suggests refactorings but lets developers approve or modify them. Full automation would miss context that humans understand.

4. LEGO Principles Scale

The same principles that make hand-written code maintainable also make AI-refactored code maintainable. The 30-line rule works whether a human or machine wrote the original code.

The Future of AI-Assisted Development

Proto Artisan represents a new paradigm: using AI to prototype rapidly, then using intelligent tooling to transform prototypes into production-quality architecture.

This workflow combines the best of both worlds:

As AI coding assistants become more powerful, tools like Proto Artisan will become essential for maintaining code quality at the speed of AI generation.

← Back to Blog