Утро начинается не с кофе
Просыпаешься, открываешь ноутбук, запускаешь сессию с Claude 3.7 Sonnet. Вчера он сам написал систему инвентаря на 200 строк, а сегодня на вопрос «добавь зелье лечения» предлагает переписать всю архитектуру с нуля. И не помнит, что такое «состояние игры». Чувствуешь? Это контекстная амнезия. Она убивает твой проект. Мой проект — игра на 114 000 строк TypeScript. И я прошел через это.
За полгода я отправил AI-агенту около 2500 промптов. Проект вырос до 340 файлов. И в какой-то момент модель перестала видеть связи между модулями. Она генерировала код, который компилировался, но ломал игровую логику. 60% времени я тратил на то, чтобы заново впихнуть контекст в голову AI. Это ад.
Но я нашел систему. Реальную, а не советы из туториалов. Сейчас расскажу.
Предупреждение: Если ваш проект меньше 10 000 строк — не парьтесь. Просто работайте одной длинной сессией. Но когда код переваливает за 50k, старые методы ломаются.
Почему модели сходят с ума на больших проектах
Есть феномен «Lost in the Middle»: LLM хуже всего обрабатывает информацию из середины контекста. Вы проверяли — первые и последние 10% она помнит, а середину теряет. В проекте на 114k строк середина — это 80% кода. Модель просто не видит взаимосвязей.
Вторая проблема — деградация контекста. Она не плавная, а ступенчатая. Сегодня AI еще помнит, как работает физика, завтра — уже нет. Связи между компонентами рвутся. Начинается спагетти-код.
Третья — цена. Каждый промпт с полным контекстом проекта стоит копейки, но при 2500 запросах выходит сотни долларов. И время — ждать ответа 30 секунд вместо 2, когда контекст перегружен.
В предыдущей статье про деградацию контекста в играх я разбирал теорию. Теперь покажу, как это работает на практике.
Моя система: контекстные слои и «якоря»
Вместо того чтобы пихать весь код в одно окно, я разбил проект на семь независимых эпиков. Каждый эпик — самодостаточный модуль с четкими границами. Идею я подсмотрел в статье про декомпозицию игры на AI-агентах.
| Эпик | Строк кода | Что внутри | Контекст (токенов) |
|---|---|---|---|
| Ядро движка | 12 400 | ECS, рендер, ввод | 6 000 |
| Геймплей-системы | 28 000 | Физика, коллизии, AI врагов | 14 000 |
| UI/UX | 18 500 | Меню, HUD, диалоги | 9 000 |
| Инвентарь и предметы | 14 200 | Слоты, крафт, эффекты | 7 000 |
| Квесты и сюжет | 22 100 | Древо диалогов, триггеры | 11 000 |
| Сохранения | 8 800 | Сериализация, лоадер | 4 000 |
| Инструменты (debug) | 10 000 | Тесты, профилирование | 5 000 |
Каждый эпик я держу в отдельном контекстном файле — CONTEXT_EPIC.md. В нем — описание архитектуры, ключевые интерфейсы, зависимости и «якоря». Якоря — это сигнатуры функций или классов, которые модель должна использовать при генерации. Например: interface Inventory { addItem(item: Item): void; removeItem(slotId: number): void; }. Без якорей AI начинает плодить свои версии — и связи рвутся.
Шаг 1: создай файл-ядро
Первый файл в проекте — AI_CONTEXT.md. Это не README, а промпт-оболочка. В ней я перечисляю:
- Общую архитектуру (одним абзацем)
- Список всех эпиков и их назначение
- Глобальные правила (например, «не используй сторонние библиотеки без моего разрешения»)
- Шаблон ответа: всегда показывай diff, тестируй код, описывай изменения в 2-3 предложениях
Этот файл я копирую в начало каждого промпта. Да, это дублирование, но без него модель сбивается. В статье про vibe coding для игр я писал, что ИИ не читает код проекта — он читает только то, что ты ему отправил.
1Структурируй промпт как расследование
Не пиши «добавь зелье». Пиши:
Задача: Добавить предмет "Зелье лечения" в систему инвентаря.
Контекст: Инвентарь лежит в src/inventory/. Интерфейс: IInventory (см. якорь).
Требования:
- При использовании восстанавливает 25 HP игрока.
- Стакается до 5 единиц.
- Дропается из врагов с шансом 30%.
Ограничения: Не трогать другие системы. Верни только diff файла inventory.ts и effect.ts.
Такой промпт занимает 200 токенов, а не 15 000. Модель не перегружена, и она выдает точный код.
Шаг 2: используй «режим атласа» для связей между эпиками
Когда нужно затронуть несколько эпиков (например, квест срабатывает при открытии сундука, а сундук — часть инвентаря), я создаю временный слой-атлас. Это — файл, в котором явно прописаны точки соединения: «Квестовая система вызывает InventoryManager.openChest(chestId). После открытия SystemQuest.trigger(questId)».
Атлас я передаю модели вместе с контекстами двух эпиков. Итоговый промпт получается около 3000 токенов, но модель не теряет связи. Без атласа она начинает путать, где чей вызов.
💡 Этот трюк спас меня от переписывания 20 000 строк. Всего один файл — и модель не плодит дублирующие функции.
Шаг 3: автоматизируй передачу контекста
Ручное копирование AI_CONTEXT.md — боль. Я написал скрипт на Node.js, который перед отправкой запроса к API собирает:
- Содержимое AI_CONTEXT.md
- Контекст запрашиваемого эпика (CONTEXT_EPIC.md)
- Последние 10 сообщений из истории (если она есть)
- Сам промпт
Скрипт обрезает лишнее, оставляя не более 30 000 токенов. Если нужно больше — разбивает задачу на несколько итераций. Это превратило хаотичные сессии в предсказуемый pipeline.
Подход похож на харнесс для AI-агентов, который я описывал в статье про построение эффективного харнесса. Но там упор на веб, а тут на игры — разница в более жестких временных ограничениях.
Шаг 4: рефакторинг как сброс контекста
Каждые 15 000–20 000 строк я проводил «генеральную уборку». Скрипт собирал весь код эпика, удалял мертвые функции, переименовывал плохие имена, переписывал комментарии. После этого я обновлял CONTEXT_EPIC.md. И дальше опять работал с AI.
Зачем? Потому что модель, видя чистый код с хорошими названиями, реже ошибается. Она как человек: чем понятнее код, тем выше качество генерации.
Кстати, рефакторинг тоже делал AI. Я давал ему блок кода и промпт: «найди дублирование, переименуй нечитаемые переменные, добавь JSDoc комментарии». И он чистил. Это экономило мне дни работы.
⚠️ Ошибка: никогда не разрешай AI рефакторить весь проект одной командой. Он сломает связи. Только по эпикам.
Нюансы и грабли, о которые я разбил лоб
Расскажу о трёх конкретных ошибках, каждая стоила мне дня отката.
1. AI изобрёл велосипед для сериализации
Модель забыла про мою систему сохранений и написала свою — через JSON.stringify с циклическими ссылками. Я не заметил, и в релизе игра вылетала при загрузке. Исправить удалось только ручным переписыванием 500 строк.
Решение: перед генерацией любой новой системы — проверять AI_CONTEXT.md, есть ли уже готовые решения. И не доверять AI на слово.
2. Потеря состояния между сессиями
Claude Code хранит историю сессии, но я обновлял API-ключ и всё терял. Пришлось завести свой лог-файл с JSON-массивом промптов и ответов. Теперь даже если сессия сбросится — я загружаю последние 5-10 сообщений как «память». Это спасло меня дважды.
3. «Зона тупости» при переполнении контекста
Когда я пытался передать 50 000 токенов, модель начинала генерировать белиберду: undefined переменные, неправильные типы, отсутствие точек с запятой. Решение — держать контекст не более 25 000 токенов. Если нужно больше — разбить задачу на подзадачи.
В статье про AI-мастера D&D похожий вывод: переполнение контекста убивает качество.
Инструменты, которые реально помогли
- cline.ai — утилита для управления контекстными файлами. Позволяет выборочно отправлять части проекта.
- git + pre-commit хуки — перед коммитом скрипт проверяет, не содержит ли код дублирующихся функций (через AST-анализ).
- tokei — подсчет строк в каждом эпике. Держу под контролем.
Что вышло: 114k строк, 2500 промптов, 0 critical багов после релиза
Да, это возможно. Главное — не пытайся скормить модель весь код. Учись декомпозировать контекст. Каждая функция должна быть объяснена в одном абзаце, каждый модуль — в одном файле, каждый эпик — в одном контекстном окне.
Многие думают, что AI-агенты заменят разработчиков. Но мой опыт показывает: хороший разработчик становится в 10 раз эффективнее, а плохой — в 10 раз быстрее накосячит. Система управления контекстом — вот что отличает профессионала от любителя.
Начинаешь свой AI-проект? Создай файл AI_CONTEXT.md прямо сейчас. Не откладывай. Через 10 000 строк будет поздно.