MidТеория4 min

Паттерн Ralph Loop

Основной паттерн автономной разработки: цикл read-plan-implement-validate-commit

Что такое Ralph Loop

Ralph Loop -- это паттерн автономной AI-разработки, названный в честь Ральфа Виггама из мультсериала "Симпсоны". Создатель паттерна -- Джеффри Хантли (Geoffrey Huntley), один из пионеров "виб-кодинга", который осознал критическую проблему: AI-ассистенты могут генерировать код, но без структурированного цикла обратной связи результат непредсказуем.

Ключевая идея: Ralph Loop -- это детерминированный цикл, работающий в недетерминированной среде. Цикл сам по себе предсказуем и повторяем, даже если AI внутри него -- нет.

Почему именно Ральф Виггам? Потому что AI-агент, как и Ральф, действует простодушно и прямолинейно. Он не хитрит, не срезает углы -- просто выполняет инструкции шаг за шагом, снова и снова. И именно эта простота делает паттерн мощным.

Простейшая форма

В своей самой базовой форме Ralph Loop выглядит обескураживающе просто:

# The simplest Ralph Loop
while :; do
  cat PROMPT.md | claude-code
done

Это бесконечный цикл, который раз за разом скармливает один и тот же промпт AI-агенту. Агент читает инструкцию, выполняет одну задачу, завершается. Цикл запускает его снова -- и агент читает обновлённое состояние проекта, выполняет следующую задачу. И так до тех пор, пока все задачи не будут выполнены.


Цикл RPIVC: пять фаз

Ralph Loop следует строгому циклу из пяти фаз -- RPIVC:

┌─────────────────────────────────────────────┐
│                                             │
│   Read → Plan → Implement → Validate → Commit
│     ↑                                    │
│     └────────────────────────────────────┘
│                  (repeat)                   │
│                                             │
└─────────────────────────────────────────────┘

1. Read (Чтение)

Агент читает три ключевых документа:

Документ Назначение Пример
AGENT.md Конвенции проекта, команды сборки/тестирования Стек, паттерны, запреты
spec.md Спецификация фичи Требования, API-контракты, модели данных
fix_plan.md Упорядоченный список задач Чеклист с приоритетами

На этом этапе агент формирует полную картину: что нужно сделать, какие стандарты соблюдать и какая задача следующая.

2. Plan (Планирование)

Агент анализирует текущее состояние кодовой базы и планирует наименьший возможный следующий шаг. Это критически важно -- не "реализовать всю фичу", а "создать одну сущность" или "добавить один метод".

Плохой план:
  "Реализовать пользовательскую аутентификацию"

Хороший план:
  "Создать файл src/Entity/User.php с полями id, email, passwordHash, createdAt"

3. Implement (Реализация)

Агент пишет код, строго следуя конвенциям из AGENT.md. Один файл, одна функция, одна забота.

4. Validate (Валидация)

Агент запускает все проверки:

# Type checking
npm run typecheck    # or: phpstan analyse

# Unit tests
npm test             # or: phpunit --testsuite=unit

# Linting
npm run lint         # or: phpcs, golangci-lint run

# Build verification
npm run build        # or: go build ./...

Если хотя бы одна проверка не прошла -- агент не переходит к коммиту, а возвращается к фазе Implement для исправления.

5. Commit (Фиксация)

Если все проверки пройдены, агент коммитит изменения, отмечает задачу как выполненную в fix_plan.md и переходит к следующей итерации.


Четыре ключевых принципа

Принцип 1: Монолитность

Ralph Loop работает с одним репозиторием, одним процессом, одной задачей. Нет микросервисной оркестрации, нет параллельных агентов (на базовом уровне), нет переключения контекстов.

Монолитный подход:
  1 репозиторий + 1 агент + 1 задача = предсказуемый результат

Распределённый подход:
  N репозиториев + M агентов + K задач = хаос

Правило: Начинайте с монолита. Переходите к мульти-агентам только когда однозначно упрётесь в ограничения одного агента.

Принцип 2: One Task Per Loop

Это самое жёсткое ограничение Ralph Loop. Каждая итерация цикла выполняет ровно одну задачу. Не две, не "примерно одну", а строго одну.

Почему это работает:

Подход Размер изменения Вероятность успеха Откат при ошибке
Одна задача 20-100 строк ~95% Тривиальный
Несколько задач 200-500 строк ~60% Сложный
"Сделай всю фичу" 1000+ строк ~20% Невозможный

Принцип 3: Детерминированная загрузка стека

Каждая итерация цикла загружает одни и те же документы заново. Агент не полагается на "память" предыдущих итераций -- он каждый раз получает полный контекст из файлов.

Итерация 1: Read(AGENT.md, spec.md, fix_plan.md) → Plan → Implement → Validate → Commit
Итерация 2: Read(AGENT.md, spec.md, fix_plan.md) → Plan → Implement → Validate → Commit
Итерация 3: Read(AGENT.md, spec.md, fix_plan.md) → Plan → Implement → Validate → Commit
...

Каждая итерация начинается с одинаковой базы,
но fix_plan.md обновляется после каждого коммита.

Это делает систему устойчивой к сбоям: если агент "запутался" на итерации N, итерация N+1 начнётся с чистого листа.

Принцип 4: Search Before Assuming

Перед реализацией агент обязан просканировать кодовую базу. Не "предполагать", что UserRepository выглядит так-то, а найти его и прочитать.

# In AGENT.md or PROMPT.md:

## RULES
- ALWAYS search the codebase before implementing
- Use grep/ripgrep to find existing patterns
- Read related files before writing new code
- Never assume file structure -- verify it

Это предотвращает одну из самых частых ошибок AI-агентов: генерацию кода, который не согласуется с существующим проектом.


Механизм обратного давления (Backpressure)

Backpressure -- это система проверок, которая "давит" на агента, заставляя его генерировать корректный код. Чем строже backpressure, тем выше качество результата.

Уровни backpressure

Уровень 1 (слабый):     Линтер + форматтер
Уровень 2 (средний):    + Юнит-тесты
Уровень 3 (сильный):    + Статический анализ (PHPStan, TypeScript strict)
Уровень 4 (максимум):   + Система типов языка (Rust, Go)
Уровень 5 (кастомный):  + Собственные валидаторы (security scanners, architecture tests)

Примеры эффективного backpressure

TypeScript в strict mode:

// tsconfig.json
{
  "compilerOptions": {
    "strict": true,              // Enable all strict checks
    "noImplicitAny": true,       // No implicit 'any' types
    "noImplicitReturns": true,   // All paths must return
    "noUncheckedIndexedAccess": true, // Array access might be undefined
    "exactOptionalPropertyTypes": true
  }
}

Каждое из этих правил -- это ещё один "барьер", который AI-агент должен преодолеть. Если он сгенерирует any тип -- TypeScript отклонит код, и агент будет вынужден исправить.

PHPStan уровень 9:

# phpstan.neon
parameters:
  level: 9
  paths:
    - src
  treatPhpDocTypesAsCertain: false

Go с golangci-lint:

# .golangci.yml
linters:
  enable:
    - errcheck       # Check error handling
    - govet          # Report suspicious constructs
    - staticcheck    # Advanced static analysis
    - gosec          # Security checks
    - exhaustive     # Check exhaustive enum switches

Ключевой принцип: Язык программирования с сильной системой типов -- это лучший backpressure для AI-агента. TypeScript strict > JavaScript. Go > Python. Rust > C.

Backpressure и скорость итерации

Существует баланс между строгостью проверок и скоростью цикла:

Скорость итерации (критично для Ralph Loop):

  Быстрый typecheck (2 сек)   ████████████████████  Высокая ценность
  Unit tests (10 сек)          ████████████████      Высокая ценность
  Lint (5 сек)                 ██████████████████    Высокая ценность
  Integration tests (60 сек)   ████████              Средняя ценность
  E2E tests (5 мин)            ████                  Низкая для loop
  Full build (3 мин)           ██████                Низкая для loop

"Колесо должно вращаться быстро"

Это один из центральных принципов Ralph Loop: скорость итерации важнее полноты проверки на каждом шаге.

Почему скорость критична

Медленный цикл (10 минут на итерацию):
  8 часов работы = 48 итераций = 48 задач максимум

Быстрый цикл (2 минуты на итерацию):
  8 часов работы = 240 итераций = 240 задач максимум

Разница: 5x в продуктивности

Стратегии ускорения

Стратегия До После Выигрыш
Инкрементальная сборка 30 сек полный билд 3 сек инкрементальный 10x
Параллельные тесты 60 сек последовательно 15 сек параллельно 4x
Watch mode для типов 5 сек при каждом запуске 0.5 сек инкрементально 10x
Кэширование линтера 10 сек полный анализ 2 сек только изменённые файлы 5x
# Optimized validation script for fast iterations
#!/bin/bash
set -e

# Step 1: Quick type check (incremental, ~1-2 sec)
npx tsc --noEmit --incremental

# Step 2: Run only affected tests (~3-5 sec)
npx vitest --changed --reporter=verbose

# Step 3: Lint only changed files (~1-2 sec)
npx eslint $(git diff --name-only --diff-filter=ACMR '*.ts' '*.tsx')

echo "All checks passed in $(date +%s) seconds"

Анатомия хорошего промпта для Ralph Loop

Эффективный промпт для Ralph Loop состоит из четырёх секций:

# SPEC
[Спецификация фичи -- что нужно реализовать]

## Feature: User Registration API
- POST /api/v1/auth/register
- Accepts: email, password, name
- Returns: 201 with user data, 422 with validation errors
- Password requirements: min 8 chars, 1 uppercase, 1 digit

# STANDARDS
[Стандарты кодирования -- как нужно реализовать]

## Coding Standards
- Use repository pattern for data access
- DTOs for all API responses
- Validation via custom validators (not inline)
- All methods must have PHPDoc
- PSR-12 code style

# FIX PLAN
[Упорядоченный список оставшихся задач]

## Remaining Tasks
- [x] Create User entity with validation
- [x] Create UserRepository with CRUD
- [ ] Create RegisterUserDTO
- [ ] Create UserRegistrationService
- [ ] Create RegisterController
- [ ] Write unit tests for registration service
- [ ] Write integration tests for API endpoint

# RULES
[Правила поведения агента]

## Agent Rules
- Search the codebase before implementing anything
- Implement only ONE unchecked task per iteration
- Run tests after every change
- If tests fail, fix the issue before proceeding
- Update fix_plan.md: mark completed task with [x]
- Never modify files unrelated to the current task
- Follow existing patterns in the codebase

Что отличает хороший промпт от плохого

Критерий Плохой промпт Хороший промпт
Спецификация "Сделай регистрацию" Конкретный API-контракт с полями и кодами ответов
Стандарты Отсутствуют Паттерны, стиль, конвенции именования
План "Реализуй всё" Пронумерованный чеклист с гранулярными задачами
Правила Отсутствуют Явные ограничения: search first, one task, run tests

Результаты и экономика

Джеффри Хантли и другие практики Ralph Loop сообщают о впечатляющих результатах:

Традиционная разработка:
  Контракт на $50,000 → 2-3 месяца работы → MVP

Ralph Loop:
  Тот же контракт → $297 в API-затратах → MVP за 1-2 дня

ROI: ~168x (не преувеличение, но требует идеальные условия)

Важный контекст: Эти результаты достигнуты на greenfield-проектах с чётко определёнными спецификациями. Для существующих кодовых баз с техническим долгом цифры будут значительно скромнее.

Факторы, влияющие на эффективность

Фактор Увеличивает эффективность Снижает эффективность
Спецификация Детальная, однозначная Расплывчатая, неполная
Тесты Быстрые, автоматические Медленные, ручные
Система типов Строгая (TypeScript, Go) Слабая (JavaScript, Python)
Проект Greenfield Legacy с тех. долгом
Задачи CRUD, API, типовые паттерны Алгоритмы, оптимизация, UI

Ограничения Ralph Loop

Где паттерн работает отлично

  • Greenfield-проекты с нуля
  • CRUD API-эндпоинты
  • Типовые фичи по известным паттернам
  • Кодовые базы с хорошим покрытием тестами
  • Проекты с сильной системой типов

Где паттерн буксует

  • Большие legacy-кодовые базы: агент не может уместить весь контекст в окно
  • Архитектурные решения: агент следует инструкциям, но не принимает стратегических решений
  • UI/UX-задачи: визуальный результат сложно верифицировать автоматически
  • Интеграции с внешними API: невозможно тестировать без моков
  • Производительность: агент не может профилировать и оптимизировать hot paths

Философское ограничение

Ralph Loop автоматизирует реализацию, но не проектирование. Человек по-прежнему необходим для:

  1. Определения требований (что строить)
  2. Архитектурных решений (как строить на высоком уровне)
  3. Декомпозиции задач (как разбить на атомарные шаги)
  4. Ревью результата (всё ли сделано правильно)
  5. Принятия решения о деплое (готово ли к продакшену)
Роль человека в Ralph Loop:

  Человек: Архитектура → Спецификация → Декомпозиция → [RALPH LOOP] → Ревью → Деплой
                                                          ↑
                                                    AI выполняет
                                                    только эту часть

Связь с другими паттернами

Ralph Loop -- это базовый паттерн, на котором строятся более сложные конструкции:

Ralph Loop (базовый)
  ├── Multi-Agent Loop (несколько параллельных агентов)
  ├── Cascade Loop (выход одного цикла → вход другого)
  ├── Supervised Loop (агент-супервизор контролирует рабочих)
  └── Compound Learning Loop (агент учится между итерациями)

Каждый из этих паттернов подробно рассматривается в разделе "Агентные паттерны разработки".


Выводы

  1. Ralph Loop -- это детерминированный цикл в недетерминированном мире. Повторяемая структура компенсирует непредсказуемость AI.

  2. One task per loop -- главное правило. Маленькие изменения = высокая вероятность успеха = быстрый откат при ошибке.

  3. Backpressure -- секрет качества. Чем строже проверки (типы, тесты, линтер), тем лучше код.

  4. Скорость итерации -- мультипликатор продуктивности. Быстрые проверки важнее полных проверок.

  5. Человек остаётся архитектором. AI автоматизирует реализацию, но не проектирование.