Архитектура, 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 генерирует работающий, но неуправляемый код. С правильной организацией — строит системы.


Почему это не "очередной pet project на ChatGPT"

Давайте сразу разберёмся с масштабом. Это не 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 (об этом ниже).

Production-инфраструктура

  • Vultr VPS (2 vCPU, 2GB RAM) + AWS RDS PostgreSQL

  • CI/CD через GitHub Actions

Разница между "AI написал код" и "AI построил систему" — в архитектуре процесса, а не в возможностях модели.


CLAUDE.md — конституция проекта

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 обязательных правил:

  1. Никаких Repo-вызовов внутри Enum.map/each/reduce

  2. Общие данные загружаются один раз (prefetch once)

  3. Один и тот же запрос не выполняется дважды за job

  4. Только batch-записи (Repo.insert_all / Repo.update_all)

  5. Query budget документируется в @moduledoc каждого воркера

  6. Чеклист перед мержем нового воркера

Живой документ

CLAUDE.md растёт вместе с проектом. Каждый инцидент, каждая ошибка AI превращается в новое правило.

ConnectionWatchdog убил пул соединений? Добавлено правило про агрессивные таймауты. AI использовал DISTINCT ON? Добавлен запрет с объяснением, почему LATERAL JOIN в 34 раза быстрее. AI показал неполные данные портфеля? Добавлено железное правило: "если хотя бы одна акция без цены — пропустить весь день".

CLAUDE.md — это как coding standards документ для команды. Только команда — это AI, и он действительно следует правилам каждый раз.


Director/Implementor — 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%+ покрытие

Цепочка на практике — 3 фазы

  1. Brainstorming — я описываю задачу, AI задаёт уточняющие вопросы один за другим, предлагает 2-3 подхода с trade-offs, формирует дизайн-документ

  2. Write Plan — дизайн превращается в пошаговый план: точные файлы, точные тесты, задачи по 2-5 минут каждая

  3. Execute Plan — Implementor выполняет план по шагам с чекпоинтами, строго TDD, без отклонений от плана

Каждая фаза — отдельный skill. Ссылки на skills будут в конце статьи.

Результат

Архитектурные решения документированы и консистентны. Новая сессия AI читает ADR и планы — контекст не теряется. 13 контекстов с чёткими границами — не случайность, а результат Director-фазы.


94.83% покрытие — TDD без компромиссов

Железный закон

В 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 не спорит с процессом.


Production-инциденты — AI тоже ломает прод

Было бы нечестно писать только про успехи. AI ломал прод. Дважды. И это самые ценные уроки.

Инцидент 1: Pool Exhaustion (февраль 2026)

Что случилось: 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 для каждого воркера, ограничена конкурентность очередей.

Инцидент 2: ConnectionWatchdog Cascade Failure (февраль 2026)

Ирония: мониторинг, написанный AI для предотвращения первого инцидента, сам стал причиной второго.

Что случилось: ConnectionWatchdog проверял здоровье пула через ObanRepo с таймаутом 2 секунды. Под нагрузкой запрос не успевал — DBConnection убивал соединение. С 5 соединениями в ObanRepo watchdog убил весь пул за ~25 секунд.

Oban-продюсеры упали. SSL-реконнект занимал 15 секунд каждый. Спираль смерти.

Решение: Удалить ConnectionWatchdog полностью. Мониторинг стал угрозой.

"Никогда не используй pooled connections с агрессивными таймаутами для мониторинга — монитор становится угрозой"

Система памяти

После каждого инцидента AI записывает урок в memory-файл. Новая сессия читает эти уроки — ошибка не повторяется. CLAUDE.md обрастает новыми правилами как кора дерева — каждое правило имеет свою историю.

Два постмортема хранятся в docs/ — с timeline, root cause analysis и action items. Точно как у человеческих команд.


MCP Debug Server — AI дебажит свой код в проде

В приложение встроен MCP-сервер (Model Context Protocol) на /mcp/* — SSE-транспорт, bearer token аутентификация. Claude Code подключается к production как к инструменту.

Инструменты

Инструмент

Что делает

query_db

SQL-запросы к production базе

read_logs

Чтение логов приложения

inspect_oban

Состояние очередей, задач, воркеров

system_metrics

CPU, память, BEAM-метрики

beam_inspect

Инспекция процессов Erlang VM

query_stats

Статистика запросов (pg_stat_statements)

query_anomalies

Аномалии в скоринге

Плюс Worker Catalog — триггер, отмена, ретрай задач с валидацией аргументов.

Как это работает

Я говорю Claude Code "проверь почему скоры не обновились" — он сам подключается к проду, смотрит Oban-очереди, проверяет логи, находит застрявший воркер, перезапускает его. Без SSH, без Grafana, без ручного дебага.

Безопасность: WorkerCatalog — белый список воркеров, которые можно триггерить через MCP. Не всё доступно — это security boundary.


1 700 коммитов за 4 месяца — скорость и что за ней стоит

Сырые цифры

  • 1 702 коммита с ноября 2025 по март 2026

  • ~14 коммитов в день в среднем

  • 80 миграций БД — схема активно эволюционировала

  • 410 файлов удалено — рефакторинг без сентиментальности

Откуда скорость

AI не тратит время на "вспомнить синтаксис", "загуглить API", "посмотреть как делали в прошлый раз". Boilerplate генерируется мгновенно — миграции, контексты, тесты, LiveView-компоненты. Рефакторинг без страха — 3 880 тестов ловят регрессии. Нет переключения контекста — AI держит в голове всю кодовую базу через CLAUDE.md и memory.

Где AI медленнее или слабее (честно)

Дизайн UI-компонентов — самая заметная слабость. AI генерирует функциональные, но визуально "generic" интерфейсы. Тонкости UX, визуальная иерархия, "чтобы выглядело как продукт, а не как bootstrap-шаблон" — это требует многих итераций и ручного направления.

Архитектурные решения — я трачу время на обдумывание, brainstorming-сессии, иногда возвращаюсь и переделываю.

Отладка нетривиальных багов — AI может пойти по ложному следу, нужно направлять.

Первый раз с новым паттерном — AI иногда предлагает over-engineering, нужно стопить и упрощать.

Главный инсайт

Скорость — побочный эффект. Главное — консистентность. Каждый коммит проходит через format, credo, тесты. Нет "быстрых грязных фиксов в пятницу вечером".


Выводы

5 главных уроков

  1. AI без рамок — хаос. CLAUDE.md, guardrails, NEVER_DO — без этого AI генерирует работающий, но неуправляемый код. Инвестиция в правила окупается с первого дня.

  2. TDD + AI = идеальная пара. AI не спорит с процессом, не ленится писать тесты, не говорит "потом". Strict TDD с AI проще, чем с людьми.

  3. Разделяй роли. Brainstorming → Plan → Execute. Когда AI одновременно проектирует и кодит — качество падает. Разделение на Director/Implementor через skills решает эту проблему.

  4. Система памяти важнее модели. Claude 3.5, 4, Opus — модель будет меняться. CLAUDE.md, memory, ADR — останутся. Знания проекта живут в файлах, не в контексте чата.

  5. AI ломает прод — и это нормально. Важно не "не ломать", а быстро чинить и превращать каждый инцидент в правило. Постмортем → правило в CLAUDE.md → ошибка не повторяется.

Для кого это подходит

  • Вы понимаете архитектуру и можете ревьюить решения AI

  • Вы готовы инвестировать в процесс (CLAUDE.md, skills, guardrails) до написания первой строчки

  • Вам нужна скорость без потери качества

Для кого НЕ подходит

  • "Напиши мне приложение" без понимания что должно получиться

  • Проекты, где дизайн и UX важнее backend-логики (пока)

Завершение

скиллы для агента

easystocksai.tech работает в проде. 1 000+ акций, реальные пользователи, реальные инциденты