# ADR-0003: buildPosition в core + разметка цели CR вместо MA (этап 6) Дата: 2026-08-06. Статус: принято. ## Контекст Этап 6 (уроки и цумэ-го) требует стартовать задачу с произвольной позиции. План-фаза 6 фиксировала «packages/* не трогаем», но аудит выявил два пробела контракта: 1. parseSgf (этап 1) не поддерживает setup-свойства AB/AW — произвольную позицию из SGF не собрать, а конструировать BoardState вручную вне core опасно (positionHashes для суперко считает внутренний hashPosition). 2. NodeMarkup не содержит стрелок MA (только LB/TR/SQ/CR) — разметка цели «connect» по контракту была невыразима. ## Решение 1. В packages/core добавлена ОДНА аддитивная функция `buildPosition(size, black, white, toPlay)` (board.ts, экспорт через index.ts): валидация (вне доски / дубли / группа без дамэ → Error), корректный positionHashes. Поведение существующих функций не меняется, зона core в остальном заморожена. 2. Разметка цели connect в задачах — CR (круги) вместо MA; контракт INTERFACES.md обновлён. SGF задачи хранит позицию данными JSON (setupBlack/setupWhite), а SGF-поле несёт только дерево вариантов (B/W-ходы от стартовой позиции, TR/CR-разметку цели на корневом узле). ## Последствия - Позиция задачи: JSON-поля setupBlack/setupWhite + buildPosition; дерево вариантов парсится parseSgf и накатывается applyMove на построенную позицию. - При расширении parseSgf поддержкой AB/AW в будущем формат можно упростить до чистого SGF (миграция контента, отдельной задачей).