Tugolukov.tech blog

Опыт использования ChatGPT Codex

Статьи
Задумка:
Мне нравится вести задачи системно, поэтому я пробовал разные таск-трекеры, но мало что подходило под меня прям на 100%. Поэтому, имея в запасе немного времени, а так же подписку на ChatGPT Plus, куда входит и Codex, я решил попробовал запилить таск-трекер под себя.

Сразу спойлер: таск-трекер я сделал, даже купил для него домен, вывел наружу, и пользуюсь постоянно, и с десктопа, и с телефона.
Далее я по тексту я буду использовать пару названий - "ChatGPT/GPT" - веб версия в режиме Chat (это важно!) и Codex - собственно агент от OpenAPI.
Внешний вид desktop-приложения Codex.
Начало начал
Скачал Codex Desktop App, запустил - все ок. С виду это обычное desktop-приложение. Залогинился, раздал все необходимые доступы, открыл папку, где у меня будет проект.

Далее, с помощью ChatGPT запилил основные файлы проекта:
  • PRODUCT.md;
  • ARCHITECTURE.md;
  • MVP.md;
  • AGENTS.md (очень важная штука).

Эти документы говорят Codex'у, что за приложение мы делаем, какие архитектурные требования и ограничения, а так же по какой инструкции мы работаем (это в AGENTS.md).

Все эти документы я делал вместе с ChatGPT, потом просто копировал в директорию проекта. Важно написать максимально конкретно, чтобы небыло разночтений.

Фишка в том, что потом Codex это будет использовать и верифицировать задачи. У меня были случаи, когда я давал ему задачу на реализацию какой-то фичи, и он находил конфликты с изначальной постановкой.

AGENTS.md
Очень важная штука. Прям реально важная. По сути, здесь содержатся инструкции по тому, как агенту работать. Как архитектор я понимал, что делаю продакшн-сервис и выставил достаточно жесткие требования, в том числе куча валидаций, тестов. И для бекенда, и для фронтенда.

Вот как выглядит мой AGENTS.md
# AGENTS.md

## Назначение

Этот файл определяет обязательные правила работы Codex в репозитории.

Главные принципы:

- Делать небольшие, законченные и проверяемые изменения.
- Не расширять scope задачи без явного запроса.
- Не считать работу завершенной без запуска доступных проверок.
- Сохранять пользовательские изменения и не затрагивать несвязанный код.

## Источники требований

Перед началом работы изучи релевантные документы проекта:

- `docs/PRODUCT.md` - назначение и модель продукта.
- `docs/REQUIREMENTS.md` - функциональные и нефункциональные требования.
- `docs/MVP.md` - границы первой версии.
- `docs/ARCHITECTURE.md` - архитектура системы.
- `docs/DATA_MODEL.md` - модель данных.
- `docs/ADR/*` - принятые архитектурные решения.
- `docs/Future version.md` - идеи после MVP, которые нельзя реализовывать без явного запроса.

Если документы противоречат друг другу, не выбирай трактовку молча. Опиши конфликт и запроси решение.

Не изменяй принятое ADR задним числом. Для изменения архитектурного решения предложи новое ADR.

## Рабочий процесс

Для каждой задачи:

1. Изучи релевантный код, документацию и текущее состояние Git.
2. Проверь задачу в `TASKS.md`. Если задача поставлена в чате и ещё не зарегистрирована, сначала зарегистрируй её по правилам раздела «Работа с задачами».
3. Для нетривиальной задачи сначала предложи краткий план.
4. Отметь задачу как `IN PROGRESS`.
5. Реализуй минимальное изменение, закрывающее задачу.
6. Добавь или обнови тесты.
7. Запусти необходимые проверки.
8. Проведи самопроверку diff на ошибки, регрессии и выход за scope.
9. Обнови документацию, описание задачи в `TASKS_DESCRIPTIONS/` и её статус в `TASKS.md`.
10. Сообщи результат, выполненные проверки и оставшиеся ограничения.

Не начинай следующую задачу, пока текущая не доведена до Definition of Done или явно не отмечена как `BLOCKED`.

## Работа с задачами

`TASKS.md` является единым реестром текущих, будущих и выполненных задач. Отдельный список выполненных задач не нужен.

Каждая задача должна иметь уникальный ID в формате `TASK-NNNN`, где `NNNN` — последовательный номер с ведущими нулями. ID не переиспользуются, в том числе после удаления или отмены задачи.

В `TASKS.md` для задачи хранятся только статус, ID, краткий заголовок и относительная ссылка на файл с подробным описанием:

```markdown
- [ ] [TODO] [TASK-0001] Краткий заголовок — [описание](TASKS_DESCRIPTIONS/TASK-0001.md)
- [ ] [IN PROGRESS] [TASK-0002] Краткий заголовок — [описание](TASKS_DESCRIPTIONS/TASK-0002.md)
- [ ] [BLOCKED] [TASK-0003] Краткий заголовок — [описание](TASKS_DESCRIPTIONS/TASK-0003.md) — причина блокировки
- [x] [DONE] [TASK-0004] Краткий заголовок — [описание](TASKS_DESCRIPTIONS/TASK-0004.md)
```

Подробное описание каждой задачи хранится в отдельном файле `TASKS_DESCRIPTIONS/<ID>.md`. Файл должен содержать как минимум заголовок с ID, источник задачи, описание, ожидаемый результат и критерии приемки. Изменения scope и существенные уточнения фиксируются в этом же файле.

Если задача поставлена в чате:

1. До начала реализации найди её в `TASKS.md` по явно указанному ID.
2. Если ID не указан или задача с ним отсутствует, назначь следующий свободный ID, добавь в `TASKS.md` заголовок задачи и создай `TASKS_DESCRIPTIONS/<ID>.md`.
3. Перенеси в файл описания существенные требования и критерии приемки из чата, не добавляя новый scope.
4. Только после регистрации переведи задачу в `IN PROGRESS` и приступай к реализации.

Правила:

- Одновременно должна быть только одна задача `IN PROGRESS`, если явно не разрешена параллельная работа.
- Перед реализацией задача должна иметь понятный результат и критерии приемки.
- Новую обнаруженную работу добавляй в `TASKS.md` и создавай для неё файл в `TASKS_DESCRIPTIONS/`, но не реализуй автоматически, если она выходит за текущий scope.
- Отмечай задачу `DONE` только после выполнения Definition of Done.
- При блокировке указывай причину и конкретное действие, необходимое для продолжения.
- При изменении scope обновляй описание задачи и связанные документы.
- Не реализуй элементы из `docs/Future version.md` в рамках MVP без явного запроса.

## Работа с Git и коммитами

Перед изменениями выполни `git status` и учитывай уже существующие изменения пользователя.

Начиная с первой задачи после `TASK-0006`, каждую задачу выполняй в отдельной ветке, созданной от актуальной `master`. Используй имя вида `task/TASK-NNNN-short-title`. Не начинай реализацию задачи непосредственно в `master`.

После завершения задачи оставляй проверенный коммит в её ветке. Сливай ветку задачи в `master` только после явного одобрения пользователя. Не удаляй ветку после слияния без отдельного запроса.

Правила коммитов:

- Один коммит должен содержать одно логически законченное изменение.
- Не смешивай рефакторинг, исправления и новые функции без необходимости.
- Добавляй в индекс только файлы текущей задачи.
- Не изменяй и не удаляй несвязанные пользовательские изменения.
- Не создавай коммит, если обязательные проверки не прошли.
- По умолчанию не создавай коммит автоматически. Сначала покажи итог и дождись явного разрешения.
- Если в задаче явно разрешен автоматический коммит, создай его только после успешного `.\scripts\verify.ps1`.
- Не выполняй `push`, `force push`, `rebase`, переписывание истории или удаление веток без явного запроса.
- Не используй разрушительные команды вроде `git reset --hard` или `git checkout --` для удаления изменений.

Формат сообщений Conventional Commits:

```text
feat: add personal kanban board
fix: persist task status after drag and drop
test: reject task move between swimlanes
refactor: extract task ordering service
docs: update migration workflow
chore: configure local development environment
```

## Контур ревью

После выполнения задачи, но до итогового отчёта, разверни ветку задачи в локальном контуре ревью командой `./scripts/review.ps1`. Контур должен быть изолирован от dev-окружения собственным Docker Compose project, сетью, volume и host-портами.

В итоговом отчёте по каждой выполненной задаче указывай:

- что контур ревью развёрнут из ветки задачи;
- адреса frontend, API, Swagger UI, health endpoints и PostgreSQL;
- состояние health checks;
- отсутствие доменных тестовых данных, если seed-шаг ещё не содержит их.

Не останавливай контур ревью после успешной проверки. Остановить его или удалить review-volume можно только по явному запросу пользователя через `./scripts/review.ps1 -Action Stop` или `Reset`.

## Команды проекта

Проект должен предоставлять единый интерфейс через PowerShell-скрипты в директории `scripts/`:

```powershell
.\scripts\setup.ps1
.\scripts\dev.ps1
.\scripts\format.ps1
.\scripts\lint.ps1
.\scripts\test.ps1
.\scripts\test-integration.ps1
.\scripts\test-e2e.ps1
.\scripts\build.ps1
.\scripts\verify.ps1
```

`.\scripts\verify.ps1` должен запускать все обязательные проверки, применимые к проекту, и завершаться с ненулевым кодом при ошибке любой из них.

Если команда еще не реализована, добавь соответствующую задачу в `TASKS.md` и создай для неё файл в `TASKS_DESCRIPTIONS/`. Не сообщай об успешной проверке, если команда отсутствовала или не запускалась.

## Работа с тестами

Тесты создаются одновременно с кодом, а не отдельным этапом после реализации MVP.

Минимальная стратегия:

- Unit-тесты для бизнес-правил и чистой логики.
- Интеграционные тесты для API, хранилищ и PostgreSQL.
- E2E-тесты для ключевых пользовательских сценариев.
- Регрессионный тест для каждого исправленного бага, если это технически возможно.

Для этого приложения обязательно проверяй:

- Изменение статуса задачи отображается на личной доске и доске проекта.
- Перемещение задачи между swimlane запрещено и не меняет ее проект.
- Выполненные и архивные задачи отображаются согласно требованиям.
- Операции с задачами не создают дубликаты.

Правила:

- Не удаляй и не ослабляй существующие тесты ради успешного результата.
- Не подменяй интеграционные тесты моками там, где проверяется работа с базой.
- Тесты должны быть воспроизводимыми и не зависеть от порядка запуска.
- Не используй реальные внешние сервисы без необходимости.
- Если проверку невозможно выполнить, сообщи точную причину и что осталось непроверенным.

## База данных и миграции

PostgreSQL для локальной разработки и тестов должен запускаться через Docker Compose или Testcontainers.

Для каждой миграции:

1. Запусти чистый экземпляр PostgreSQL.
2. Дождись успешного health check.
3. Примени все миграции с нуля.
4. Запусти интеграционные тесты.
5. Проверь откат и повторное применение, если инструмент поддерживает миграции вниз.
6. Проверь итоговую схему на соответствие `docs/DATA_MODEL.md`.

Дополнительные правила:

- Не меняй уже опубликованную миграцию. Создавай новую корректирующую миграцию.
- Не выполняй миграции на production или пользовательской базе без явного разрешения.
- Не удаляй данные в миграциях без отдельного подтверждения и плана восстановления.
- Не помещай пароли базы и другие секреты в репозиторий.

## UI и визуальная проверка

При работе с интерфейсом:

- Следуй существующим UI-спецификациям и дизайн-системе.
- Не меняй визуальный стиль приложения без явного запроса.
- Сначала обеспечь корректное поведение, затем визуальную полировку.
- Проверяй desktop и mobile представления.
- Запускай приложение и визуально проверяй измененные экраны в браузере.
- Для drag-and-drop проверяй перемещение между колонками внутри одного swimlane и запрет переноса между swimlane.
- Добавляй E2E-тест для критичного пользовательского сценария, если изменение влияет на него.

Если визуальная проверка недоступна, укажи это в итоговом отчете.

## Качество кода

- Следуй архитектуре проекта и сохраняй границы модулей.
- Не добавляй новые production-зависимости без обоснования.
- Не создавай абстракции для гипотетических будущих требований.
- Не выполняй крупный рефакторинг внутри функциональной задачи без необходимости.
- Обрабатывай ошибки явно и возвращай понятные сообщения.
- Добавляй комментарии только там, где код не объясняет причину решения.
- Форматирование, линтер и сборка должны проходить без ошибок.

## Безопасность и конфигурация

- Никогда не добавляй секреты, токены, пароли или реальные `.env` файлы в Git.
- Поддерживай актуальный `.env.example` без секретных значений.
- Валидируй входные данные на границе системы.
- Не логируй чувствительные данные.
- Запрашивай подтверждение перед разрушительными операциями и изменением данных пользователя.
- Используй минимально необходимые права для приложения и базы данных.

## Документация

Обновляй документацию в том же изменении, если меняются:

- Поведение продукта.
- API.
- Модель данных.
- Архитектура.
- Команды запуска или проверки.
- Переменные окружения.

Не обновляй документы формально, если фактическое поведение не изменилось.

## Definition of Done

Задача может быть отмечена `DONE`, только если:

- Реализованы критерии приемки.
- Добавлены или обновлены необходимые тесты.
- Пройдены форматирование и линтер.
- Пройдены unit-тесты.
- Пройдены применимые интеграционные и E2E-тесты.
- Проект успешно собирается.
- Миграции проверены на чистой базе, если они менялись.
- UI проверен визуально, если он менялся.
- Diff проверен на регрессии и несвязанные изменения.
- Обновлены документация, `TASKS.md` и описание задачи в `TASKS_DESCRIPTIONS/`.
- Известные ограничения явно перечислены.

Финальной обязательной проверкой является:

```powershell
.\scripts\verify.ps1
```

## Итоговый отчет Codex

После выполнения задачи кратко сообщи:

- Что изменено.
- Какие тесты и проверки запущены.
- Их результат.
- Что не удалось проверить и почему.
- Какие документы и задачи обновлены.
- Готов ли diff к коммиту.

Не утверждай, что задача полностью выполнена, если часть обязательных проверок не запускалась.
Работа с задачами и общение
Я мыслил в терминах задач: для этого я завел TASKS.md, туда через Codex добавлял собственно задачи. При необходимости, в диалоге задачи конкретизировались, и для каждой тасочки добавлялось описание, которое складывалось в отдельный файлик. После каждой задачи я проводил ревью фичей (всегда) и кода (сильно реже).
Вот как выглядит мой список задач:
# Задачи

- [x] [DONE] [TASK-0001] Обновить правила учета задач в AGENTS.md — [описание](TASKS_DESCRIPTIONS/TASK-0001.md)
- [x] [DONE] [TASK-0002] Добавить единый интерфейс команд проекта через PowerShell — [описание](TASKS_DESCRIPTIONS/TASK-0002.md)
- [x] [DONE] [TASK-0003] Устранить противоречия в правилах drag-and-drop — [описание](TASKS_DESCRIPTIONS/TASK-0003.md)
- [x] [DONE] [TASK-0004] Перевести интерфейс команд проекта на PowerShell — [описание](TASKS_DESCRIPTIONS/TASK-0004.md)
- [x] [DONE] [TASK-0005] Создать локальный Git-репозиторий — [описание](TASKS_DESCRIPTIONS/TASK-0005.md)
- [x] [DONE] [TASK-0006] Создать базовый каркас backend-приложения — [описание](TASKS_DESCRIPTIONS/TASK-0006.md)
- [x] [DONE] [TASK-0007] Перенести проектную документацию в отдельный каталог — [описание](TASKS_DESCRIPTIONS/TASK-0007.md)
- [x] [DONE] [TASK-0008] Создать базовый каркас frontend-приложения — [описание](TASKS_DESCRIPTIONS/TASK-0008.md)
- [x] [DONE] [TASK-0009] Подключить API-приложение к PostgreSQL и добавить миграции — [описание](TASKS_DESCRIPTIONS/TASK-0009.md)
- [x] [DONE] [TASK-0010] Реализовать экран My Board с тестовыми данными — [описание](TASKS_DESCRIPTIONS/TASK-0010.md)
- [x] [DONE] [TASK-0011] Создать изолированный контур ревью — [описание](TASKS_DESCRIPTIONS/TASK-0011.md)
- [x] [DONE] [TASK-0012] Добавить навигацию проектов и пустую страницу проекта — [описание](TASKS_DESCRIPTIONS/TASK-0012.md)
- [x] [DONE] [TASK-0013] Обновить вёрстку главной страницы — [описание](TASKS_DESCRIPTIONS/TASK-0013.md)
- [x] [DONE] [TASK-0014] Реализовать API для работы с проектами — [описание](TASKS_DESCRIPTIONS/TASK-0014.md)
- [x] [DONE] [TASK-0015] Подключить боковую панель к API проектов — [описание](TASKS_DESCRIPTIONS/TASK-0015.md)
- [x] [DONE] [TASK-0016] Реализовать страницу проекта — [описание](TASKS_DESCRIPTIONS/TASK-0016.md)
- [x] [DONE] [TASK-0017] Сделать шапку страницы проекта компактнее — [описание](TASKS_DESCRIPTIONS/TASK-0017.md)
- [x] [DONE] [TASK-0018] Добавить локальную канбан-доску на страницу проекта — [описание](TASKS_DESCRIPTIONS/TASK-0018.md)
- [x] [DONE] [TASK-0019] Добавить создание проекта из боковой панели — [описание](TASKS_DESCRIPTIONS/TASK-0019.md)
- [x] [DONE] [TASK-0020] Отсортировать проекты и выровнять заголовок страницы — [описание](TASKS_DESCRIPTIONS/TASK-0020.md)
- [x] [DONE] [TASK-0021] Создать и редактировать задачи через панель — [описание](TASKS_DESCRIPTIONS/TASK-0021.md)
- [x] [DONE] [TASK-0022] Реализовать API задач и подключить доски — [описание](TASKS_DESCRIPTIONS/TASK-0022.md)
- [x] [DONE] [TASK-0023] Добавить комментарии к задачам — [описание](TASKS_DESCRIPTIONS/TASK-0023.md)
- [x] [DONE] [TASK-0024] Закрывать панель задачи кликом вне неё — [описание](TASKS_DESCRIPTIONS/TASK-0024.md)
- [ ] [TODO] [TASK-0025] Добавить сочетания клавиш для панели задачи — [описание](TASKS_DESCRIPTIONS/TASK-0025.md)
- [ ] [TODO] [TASK-0026] Добавить rich text для описаний и комментариев — [описание](TASKS_DESCRIPTIONS/TASK-0026.md)
- [ ] [TODO] [TASK-0027] Добавить чек-листы в задачи — [описание](TASKS_DESCRIPTIONS/TASK-0027.md)
- [ ] [TODO] [TASK-0028] Добавить быстрое создание задачи в колонке — [описание](TASKS_DESCRIPTIONS/TASK-0028.md)
- [x] [DONE] [TASK-0029] Добавить production-деплой через SSH с backup базы — [описание](TASKS_DESCRIPTIONS/TASK-0029.md)
- [x] [DONE] [TASK-0030] Добавить отображение версии приложения — [описание](TASKS_DESCRIPTIONS/TASK-0030.md)
Здесь есть как выполненные задачи, так и что-то на будущее.

Вот как выглядит собственное общение с агентом:
Бывало так, что я просто просил зарегистрировать задачу, без ее выполнения. Также я иногда просил проверить задачу на конфликты. Работает прямо все супер.
Архитектура
Я же архитектор, и мне надо было, чтобы некоторые вещи работали прям как я хочу, а не как агент сделает. Такой конфликт случился во время реализации миграций на базу данных: Codex реализовал отдельный сервис, который надо было запускать руками. Мне это не подошло, мне надо было чтобы это делала сама API-шка. В итоге я детально расписал, как должна выглядеть реализация, и только тогда получилась конфетка.

Ревью контур
Когда сам программируешь задачи, тебе приходится запускать приложение для проверки. Здесь такого нет. Несмотря на то, что агент запускает задачу в докере для проверки, я не могу эти же контейнеры использовать, потому что там непонятное состояние баз данных и версий кода.
В итоге я попросил сделать мне отдельный локальный review-контур, с фиксированными адресами (т.е. портами, т.к. это все локально), и с фиксированными данными.
После каждого выполнения задачи агент сам обновлял ревью контур, я проверял, и давал апрув на создание коммита и вливание в мастер.

Work-мод, модели и лимиты
В какой-то момент я обратил внимание на то, что у меня уже подходит к концу недельный лимит. Радовало то, что я успел сделать практически весь проект. Я покурил тему с лимитами, и вот к чему пришел:
  • Я использовал самую старшую модель (Sol), и средний "Reasoning";
  • Для сложных задач вполне окей использовать флагманскую модель;
  • Я в итоге перешел на самую нижнюю модель и нижний reasoning, делал практически все задачи в этой конфигурации. Единственное что потребовалось более конкретной описывать задачи. Но лимиты стали расходоваться сильно медленнее;
  • На будущее я выделил для себя 2 опции, которые еще попробую: memora для хранения в спец. памяти всех *.md файлов и codebase-memory-mcp для индексации кода, чтобы агент читал меньше файлов. Надеюсь, поможет;

Итого
  • Опыт позитивный, я уже пользуюсь сервисом на day2day основе;
  • Важное - проработать AGENTS.md и сопутствующую информацию, типа фичи и прочее;
  • Для сложных задач стоит использовать старшие модели, для простых - младшие, так можно сэкономить на лимитам;
  • Локальный ревью контур прям решает;
  • Работа с задачами оказалось очень удобной.

Всем спасибо и приятного вайб-кодинга :)
Share Buttons