Крестики-нолики
В этом упражнении идеи книги превращаются в рабочий процесс на твоём собственном коде. Ты берёшь небольшую систему — крестики-нолики в реальном времени, где окончательные решения принимает сервер, — и проводишь её от приблизительного замысла до слитого pull request, управляя всем процессом так, как предписывает книга. Главный результат — освоенный процесс, а не готовый артефакт: способность провести любую возможность через спецификацию, которой подчиняется агент, ограниченные запуски с подтверждениями, критическое ревью и изменение, за которое ты отвечаешь. Этот путь использует небольшой набор инструментов и эталонный процесс, который можно принять или заменить.
Почему этот проект
Игра выбрана так, чтобы о ней можно было забыть: ты уже знаешь правила, поэтому не тратишь внимание на механику, а направляешь его целиком на процесс — как замысел становится спецификацией, спецификация — подтверждениями, а подтверждения — изменением, которое ты способен обосновать. Пространство проектных решений намеренно оставлено открытым. От тебя не требуется быть экспертом в архитектуре или визуальном дизайне, поэтому эти решения оставлены вопросами, которые нужно исследовать вместе с агентом. Это первый урок упражнения на практике: открытый вопрос превращается в утверждённое решение.
Даже настолько простая вещь остаётся настоящей системой: два клиента, один источник окончательных решений, долговечное состояние и реальные сбои — переподключение, вытеснение, некорректный кадр. Надёжно проверить всё это нетривиально. Но система конечна по построению: матч не может длиться более девяти ходов, когда заняты все клетки и наступает ничья. Этот жёсткий предел удерживает пространство состояний достаточно маленьким, чтобы даже исчерпывающая проверка воспроизведения оставалась осуществимой.
Анонимные игроки снимают вторую половину привычных затрат. Без учётных записей нечего аутентифицировать: не нужно моделировать личность, истечение сессии или восстановление доступа. Аутентификация — место, где большинство простых систем прячет свою сложность. Отказ от неё позволяет оставить систему настоящей, а не игрушечной, и достаточно маленькой, чтобы закончить за один рабочий день.
Какую игру ты построишь
Два человека открывают одну ссылку и по очереди ходят на поле три на три. Ни у одного нет учётной записи, и нигде её не просят создать. Главная страница создаёт игру и отправляет тебя на её собственный URL, /g/:id; открыв чужой URL, ты занимаешь первое свободное место — сначала X, потом O; cookie запоминает твоё место, поэтому обновление страницы возвращает тебя туда же; третьему посетителю отказывают во входе.
Само поле находится на сервере, а не в браузере. Щелчок отправляет ход; сервер решает, допустим ли он, вычисляет позицию и затем передаёт результат всем участникам матча через WebSocket. Клиент никогда не применяет ход самостоятельно — он рисует то, что ему сообщают. Одно это правило превращает сетку в распределённую систему: два браузера, один источник окончательных решений и сеть между ними, которая может оборваться.
Упражнение
Один сервер, два клиента, один журнал для воспроизведения
Рассматривай рисунок как упражнение в миниатюре. В нём четыре блока: два анонимных места — игрок X и игрок O, — игровой сервер, который единственный вправе принимать решение о ходе, и хранилище SQLite с текущим состоянием и журналом, допускающим только добавление. Между ними идут две полосы, по одной в каждую сторону: полоса ходов переносит заявку каждого игрока на сервер, а полоса отправки состояния возвращает подтверждённое поле обоим игрокам. Запись в хранилище показана структурно, а не полосой: ход попадает в журнал прежде, чем любой игрок получает ответ. Именно такой порядок должна гарантировать вся реализация.
Каждый из четырёх этапов процесса соответствует этому рисунку. Сбор фактической основы определяет, что должны переносить полосы и что вправе отклонять два решения сервера — сначала проверить, затем применить. Ограниченные запуски воспроизводят журнал из хранилища и проверяют, что оба места сходятся к одному полю. Ревью исследует единственную асимметрию, видимую на рисунке: сделавший ход игрок рисует свой знак как предварительный кандидат, пока остальные ждут отправки состояния. Поэтому обрыв сокета, некорректный кадр или перезапуск посреди матча всё равно должны привести каждого клиента к одной позиции. В конце ты вливаешь именно эту гарантию — вместе с подтверждениями, позволяющими её обосновать.
Каждое изменение добавляется в журнал событий SQLite со строго возрастающим порядковым номером, рядом с текущим состоянием. Журнал — долговечная запись; состояние — то, что передаётся. Клиент, потерявший сокет, переподключается с увеличивающимися задержками, сообщает последний увиденный номер и получает всё последующее по порядку. Поэтому ноутбук, уснувший посреди игры, просыпается на той же позиции, которую видят остальные. Поскольку матч ограничен, весь журнал и есть окно воспроизведения: без снимков и обрезки.
Это небольшая система, но каждый режим отказа в ней реален: обрыв сокета, некорректный кадр, перезапуск посреди матча. По-настоящему трудно не написать воспроизведение, а доказать его детерминированность — и это первый вопрос, который должна решить спецификация.
В итоге получается небольшое, понятное рабочее пространство из четырёх модулей: чистые правила, долговечная история, сервер, управляющий этой историей и живыми соединениями, и клиент, рисующий то, что ему сообщают. В основе обычный стек: Node.js, React, SQLite. Набор тестов закрепляет гарантии порядка и воспроизведения, а изменение попадает в проект через слитый pull request. Каждому утверждению о процессе соответствует файл в этой реализации.
Какой стек ты установишь
Игра — то, что ты строишь. А то, с помощью чего ты её строишь, — отдельный стек: агентная оболочка, которую нужно установить прежде, чем начнётся всё остальное.
Раздел книги CLI-агенты для программирования ранжирует инструменты и ставит на первое место pi — независимый от поставщика и ориентированный на расширения. Упражнение придерживается этого выбора и намеренно не универсально: оно работает на рекомендованном книгой стеке, в котором ChunkHound и pi-schematic специально созданы для применения описанных приёмов, а не для их иллюстрации. Оба инструмента созданы автором книги раскрытие интересов.
В pi 1.0 встроены MCP, codemode и tool_search, поэтому серверные инструменты остаются за пределами промпта, пока задача к ним не обратится. Остальное добавляет оболочка: субагентов, память и исследовательский конвейер.
- pi-schematic
ручная инженерия контекста — это временные Markdown-файлы и копирование состояния; этот инструмент превращает её в примитивы: spawn, блокнот, передачу работы, группы моделей — чтобы независимость от поставщика ускоряла процесс с несколькими моделями.
Настройка - ChunkHound
необработанные результаты поиска вытесняют собственную работу оркестратора; это агент рабочего процесса для сбора фактической основы: он исследует код, веб и историю git и возвращает синтезированные выводы — RAG корпоративного масштаба на одном ноутбуке, подключаемый к встроенному MCP в pi одной командой
Настройкаpi mcp add. - agent-browser
некоторые вопросы решает только отрисованная страница; этот инструмент управляет браузером и возвращает компактные снимки, чтобы агент проверял выпущенный результат.
Настройка
Именно эта оболочка запускает всё в движение: направляет каждую задачу подходящей модели, делегирует через spawn ради изоляции, собирает фактическую основу в ChunkHound и сохраняет контекстное окно небольшим с помощью блокнота и передачи работы. Когда она установлена и отвечает, сама игра становится малой частью задачи: процесс из четырёх этапов — собрать факты, спланировать, выполнить, проверить — требует, чтобы всё работало ещё до того, как спецификация обретёт смысл.