Архитектура, TDD, инциденты и уроки 4 месяцев разработки с Claude Code
В ноябре 2025 я начал эксперимент — построить полноценное финансовое приложение, не написав ни одной строчки кода руками. Спустя 4 месяца: 1 702 коммита, 3 880 тестов, 94.83% покрытие, два серьёзных production-инцидента и работающий продукт.
Моя роль — архитектор и продакт. Я задаю направление, принимаю решения, ревьюю результат. AI реализует. Код руками не пишу.
Проект — EasyStocksAI: скоринг 1 000+ акций по 15 метрикам (4 столпа по 25 баллов = 100), портфели с историей и benchmark-стратегиями, интерактивные графики, блог с кастомным Markdown-парсером. Стек: Elixir/Phoenix LiveView, PostgreSQL, Oban, Tailwind, Lightweight Charts.
Эта статья не про то, что "AI умеет писать код" — это все уже знают. Она про то, как организовать процесс, чтобы AI выдавал production-quality результат. Без guardrails AI генерирует работающий, но неуправляемый код. С правильной организацией — строит системы.
Давайте сразу разберёмся с масштабом. Это не TODO-лист и не лендинг.
|
Метрика |
Значение |
|---|---|
|
Elixir-код |
422 000 строк |
|
JavaScript |
6 350 строк |
|
Тестовый код |
73 000 строк |
|
Модули |
300+ (214 бизнес-логика + 86 веб-слой) |
|
Тесты |
3 880+ |
|
Покрытие |
94.83% |
|
Oban-воркеры |
34 (11 по расписанию, 23 по требованию) |
|
Миграции БД |
80 |
|
Контексты (DDD) |
13 |
|
Зависимости |
33 |
4-столповая система скоринга — чистые функции без побочных эффектов:
Shareholder Returns (доходность для акционеров)
Growth Quality (качество роста)
Valuation Quality (качество оценки)
Track Record & Resilience (история и устойчивость)
Данные из 5 API-источников с каскадным fallback: Finnhub → Polygon → Alpha Vantage → FMP → Yahoo Finance. Если один источник недоступен — автоматический переход к следующему.
Портфели с историей транзакций, benchmark-стратегии (S&P 500, All Weather, Classic с учётом возраста инвестора), публичное шаринг-ссылки по токену.
Графики на Lightweight Charts с lazy-loading и LRU-кешем. Блог с кастомным Markdown-парсером: [[AAPL]] превращается в ссылку на акцию, {{chart:AAPL|1Y}} — в интерактивный график.
MCP Debug Server — AI может дебажить production прямо через Claude Code (об этом ниже).
Vultr VPS (2 vCPU, 2GB RAM) + AWS RDS PostgreSQL
CI/CD через GitHub Actions
Разница между "AI написал код" и "AI построил систему" — в архитектуре процесса, а не в возможностях модели.
AI без ограничений пишет "как попало". Over-engineering, забытые тесты, сломанный существующий код, каждая новая сессия с чистого листа. Знакомо?
Решение — CLAUDE.md. Единый файл, который Claude Code читает при каждом запуске. Это не README и не документация — это набор жёстких правил, которые AI обязан соблюдать.
Обязательные команды — mix format && mix credo --strict после каждого изменения. Без исключений. Не "желательно" — обязательно.
Strict TDD — железный закон: НИ ОДНОЙ строчки продакшн-кода без падающего теста. Red → Green → Refactor. Если AI написал код до теста — стоп.
Список запретов (13 пунктов):
Никаких Process.sleep в тестах (используй assert_receive)
Никаких float для финансовых данных (только Decimal)
Никаких @dialyzer для подавления предупреждений (почини типы)
Никогда docker-compose down -v (уничтожает данные)
Никаких DB-запросов внутри циклов в Oban-воркерах
Архитектурные принципы:
Database as Source of Truth — не GenServers
Functional Core / Imperative Shell — чистая бизнес-логика отделена от побочных эффектов
Let It Crash — паттерн-матчинг вместо defensive nil-checking
Query-правила для Oban-воркеров — 6 обязательных правил:
Никаких Repo-вызовов внутри Enum.map/each/reduce
Общие данные загружаются один раз (prefetch once)
Один и тот же запрос не выполняется дважды за job
Только batch-записи (Repo.insert_all / Repo.update_all)
Query budget документируется в @moduledoc каждого воркера
Чеклист перед мержем нового воркера
CLAUDE.md растёт вместе с проектом. Каждый инцидент, каждая ошибка AI превращается в новое правило.
ConnectionWatchdog убил пул соединений? Добавлено правило про агрессивные таймауты. AI использовал DISTINCT ON? Добавлен запрет с объяснением, почему LATERAL JOIN в 34 раза быстрее. AI показал неполные данные портфеля? Добавлено железное правило: "если хотя бы одна акция без цены — пропустить весь день".
CLAUDE.md — это как coding standards документ для команды. Только команда — это AI, и он действительно следует правилам каждый раз.
Один AI в одной сессии — и архитектор, и кодер, и ревьюер. Результат: решения принимаются на лету, архитектура дрейфует, через 20 сессий проект — лоскутное одеяло.
Через систему кастомных skills для Claude Code AI работает в двух чётко разделённых режимах:
Director (Архитектор) — проектирует, не пишет код:
Создаёт ADR (Architectural Decision Records) — 6 штук в проекте
Определяет контексты и границы модулей
Пишет планы реализации с точными файлами и тестами
Принимает технологические решения (Pure Ecto vs Ash Framework, JSONB vs отдельные таблицы)
Implementor (Исполнитель) — пишет код строго по плану:
Только TDD: сначала тест, потом код
Не может менять схему БД или границы контекстов без "одобрения Director"
Обязан пройти чеклист: format, credo, 90%+ покрытие
Brainstorming — я описываю задачу, AI задаёт уточняющие вопросы один за другим, предлагает 2-3 подхода с trade-offs, формирует дизайн-документ
Write Plan — дизайн превращается в пошаговый план: точные файлы, точные тесты, задачи по 2-5 минут каждая
Execute Plan — Implementor выполняет план по шагам с чекпоинтами, строго TDD, без отклонений от плана
Каждая фаза — отдельный skill. Ссылки на skills будут в конце статьи.
Архитектурные решения документированы и консистентны. Новая сессия AI читает ADR и планы — контекст не теряется. 13 контекстов с чёткими границами — не случайность, а результат Director-фазы.
В CLAUDE.md записано: "НИ ОДНОЙ строчки продакшн-кода без падающего теста." Не рекомендация — требование. AI, который пишет код до тестов, получает стоп-сигнал.
|
Метрика |
Значение |
|---|---|
|
Тесты |
3 880+ |
|
Файлов тестов |
319 |
|
Строк тестового кода |
73 000 |
|
Покрытие |
94.83% |
|
JS-тесты (Vitest) |
22 |
73 000 строк тестового кода — больше, чем у многих проектов всего кода.
Только публичные API контекстов — не внутренние функции
Один behaviour per test — никаких "и ещё проверим вот это"
ExVCR для HTTP-мокинга с уникальной кассетой на каждый тест
ETS-кеш тесты с async: false — потому что глобальная таблица не изолируется как Ecto Sandbox
AI обязан остановиться, если:
Тест прошёл сразу → что-то не так с тестом
"Это слишком просто для теста" → нет, не слишком
"Добавлю тест потом" → нет, сейчас
AI не устаёт, не ленится, не говорит "давай потом напишем тесты". Если правила в CLAUDE.md жёсткие — он их выполняет. Strict TDD с AI оказался проще, чем с людьми, потому что AI не спорит с процессом.
Было бы нечестно писать только про успехи. AI ломал прод. Дважды. И это самые ценные уроки.
Что случилось: Oban-воркеры и веб-запросы делили один пул из 15 соединений к PostgreSQL. Запустили бэкфилл на 923 задачи — веб-интерфейс лёг.
Корневая причина: AI не учёл, что db.t3.micro на AWS RDS имеет ~80 max_connections, и один пул на всё — это бомба замедленного действия.
Решение: ObanRepo — выделенный пул из 5 соединений для внутренних операций Oban (fetch, ack, prune), изолированный от основного Repo (15 соединений). Паттерн из официальной документации Oban.
Урок → новое правило в CLAUDE.md: документирован query budget для каждого воркера, ограничена конкурентность очередей.
Ирония: мониторинг, написанный AI для предотвращения первого инцидента, сам стал причиной второго.
Что случилось: ConnectionWatchdog проверял здоровье пула через ObanRepo с таймаутом 2 секунды. Под нагрузкой запрос не успевал — DBConnection убивал соединение. С 5 соединениями в ObanRepo watchdog убил весь пул за ~25 секунд.
Oban-продюсеры упали. SSL-реконнект занимал 15 секунд каждый. Спираль смерти.
Решение: Удалить ConnectionWatchdog полностью. Мониторинг стал угрозой.
После каждого инцидента AI записывает урок в memory-файл. Новая сессия читает эти уроки — ошибка не повторяется. CLAUDE.md обрастает новыми правилами как кора дерева — каждое правило имеет свою историю.
Два постмортема хранятся в docs/ — с timeline, root cause analysis и action items. Точно как у человеческих команд.
В приложение встроен MCP-сервер (Model Context Protocol) на /mcp/* — SSE-транспорт, bearer token аутентификация. Claude Code подключается к production как к инструменту.
|
Инструмент |
Что делает |
|---|---|
|
|
SQL-запросы к production базе |
|
|
Чтение логов приложения |
|
|
Состояние очередей, задач, воркеров |
|
|
CPU, память, BEAM-метрики |
|
|
Инспекция процессов Erlang VM |
|
|
Статистика запросов (pg_stat_statements) |
|
|
Аномалии в скоринге |
Плюс Worker Catalog — триггер, отмена, ретрай задач с валидацией аргументов.
Я говорю Claude Code "проверь почему скоры не обновились" — он сам подключается к проду, смотрит Oban-очереди, проверяет логи, находит застрявший воркер, перезапускает его. Без SSH, без Grafana, без ручного дебага.
Безопасность: WorkerCatalog — белый список воркеров, которые можно триггерить через MCP. Не всё доступно — это security boundary.
1 702 коммита с ноября 2025 по март 2026
~14 коммитов в день в среднем
80 миграций БД — схема активно эволюционировала
410 файлов удалено — рефакторинг без сентиментальности
AI не тратит время на "вспомнить синтаксис", "загуглить API", "посмотреть как делали в прошлый раз". Boilerplate генерируется мгновенно — миграции, контексты, тесты, LiveView-компоненты. Рефакторинг без страха — 3 880 тестов ловят регрессии. Нет переключения контекста — AI держит в голове всю кодовую базу через CLAUDE.md и memory.
Дизайн UI-компонентов — самая заметная слабость. AI генерирует функциональные, но визуально "generic" интерфейсы. Тонкости UX, визуальная иерархия, "чтобы выглядело как продукт, а не как bootstrap-шаблон" — это требует многих итераций и ручного направления.
Архитектурные решения — я трачу время на обдумывание, brainstorming-сессии, иногда возвращаюсь и переделываю.
Отладка нетривиальных багов — AI может пойти по ложному следу, нужно направлять.
Первый раз с новым паттерном — AI иногда предлагает over-engineering, нужно стопить и упрощать.
Скорость — побочный эффект. Главное — консистентность. Каждый коммит проходит через format, credo, тесты. Нет "быстрых грязных фиксов в пятницу вечером".
AI без рамок — хаос. CLAUDE.md, guardrails, NEVER_DO — без этого AI генерирует работающий, но неуправляемый код. Инвестиция в правила окупается с первого дня.
TDD + AI = идеальная пара. AI не спорит с процессом, не ленится писать тесты, не говорит "потом". Strict TDD с AI проще, чем с людьми.
Разделяй роли. Brainstorming → Plan → Execute. Когда AI одновременно проектирует и кодит — качество падает. Разделение на Director/Implementor через skills решает эту проблему.
Система памяти важнее модели. Claude 3.5, 4, Opus — модель будет меняться. CLAUDE.md, memory, ADR — останутся. Знания проекта живут в файлах, не в контексте чата.
AI ломает прод — и это нормально. Важно не "не ломать", а быстро чинить и превращать каждый инцидент в правило. Постмортем → правило в CLAUDE.md → ошибка не повторяется.
Вы понимаете архитектуру и можете ревьюить решения AI
Вы готовы инвестировать в процесс (CLAUDE.md, skills, guardrails) до написания первой строчки
Вам нужна скорость без потери качества
"Напиши мне приложение" без понимания что должно получиться
Проекты, где дизайн и UX важнее backend-логики (пока)
скиллы для агента
easystocksai.tech работает в проде. 1 000+ акций, реальные пользователи, реальные инциденты
Источник


