Прежняя git-история утрачена при переносе проекта на машину владельца (снапшот без .git). Хэши коммитов в docs/reports/* относятся к утраченной истории. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
89 lines
33 KiB
Markdown
89 lines
33 KiB
Markdown
# ADR-0001. Триаж prestart-litany для профиля M
|
||
|
||
- Дата: 2026-08-05
|
||
- Статус: принят
|
||
- Ссылки на литанию — слагами/названиями пунктов, не номерами (`gotcha-renumbered-parent`).
|
||
|
||
## Контекст
|
||
|
||
Проект «Сайт обучения Го»: профиль **M** (продукт без своего прода) — код, тесты,
|
||
релизы, но нет своего сервера/БД (до опциональных этапов 8–9). Полностью клиентский:
|
||
статическая сборка на шаред-хостинг, движок и ИИ — в браузере. Один разработчик,
|
||
сессии ведут разные ИИ-модели без общей памяти.
|
||
|
||
## Триаж
|
||
|
||
| Пункт литании | Вердикт | Причина / условие |
|
||
| ---------------------------------------------------- | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||
| 0.2 Минимальное ядро (все 9 пунктов) | IN | Действует всегда, для любого профиля |
|
||
| 0.3-D/S/A профильные добавки | OUT | Не наш профиль |
|
||
| 0.3-M профильные добавки | IN | Чистое ядро и детерминизм (II), версионирование локального состояния (I.14), адаптер платформы, CI-матрица ОС (II.11), профиль публичного релиза (V.9), роли (IV) |
|
||
| 0.3-XL литания целиком | DEFERRED | Активация: старт этапа 8 (PHP+SQLite, свой прод) — до-триаж раздела V обязателен по спеке |
|
||
| I.1 Модульность / Module Map | IN | packages/* = модули; Module Map в AGENTS.md |
|
||
| I.2 Сервисный слой | IN (адаптация) | Без backend: контроллер→сервис читается как UI→чистые функции ядра; логика только в packages/core и packages/ai |
|
||
| I.3 Статусы = конечный автомат | IN | Состояние партии/урока — именованные переходы, прямое присваивание запрещено |
|
||
| I.4 Аудит-след | OUT | Нет транзакций, денег, сервера. Журнал ходов партии существует как доменная сущность (история с ветвлением), не как аудит |
|
||
| I.5 Soft delete | OUT | Нет БД и документов |
|
||
| I.6 Числа/единицы/стандартные форматы | IN | Координаты доски, коми (0.5-шаг), размер доски — объявлены письменно в INTERFACES.md; SGF FF[4] — стандартный формат обмена, берём его |
|
||
| I.7 Миграции схемы append-only | IN (адаптация) | Схема localStorage: version + миграция при загрузке; БД-миграции — DEFERRED до этапа 8 |
|
||
| I.8 Внешние вызовы | OUT | Нет внешних сервисов на этапах 1–7. Загрузка весов KataGo (этап 9) — статический файл, не API; адаптер площадки не нужен (свой сайт, не маркетплейс) |
|
||
| I.9 Парные операции симметричны | IN | Сделать ход ↔ отмена хода; поставить разметку ↔ снять; тесты на пары |
|
||
| I.10 Без хардкода / доменные параметры | IN | Коми, бюджеты времени ИИ, вероятности уровней — константы/конфиг одним местом (packages/core/src/config или данные уроков) |
|
||
| I.11 Contract First | IN | INTERFACES.md — контракт движка, протокол postMessage воркера, форматы уроков, схема localStorage. Сначала запись, потом код; удалил сущность — докажи grep'ом |
|
||
| I.12 Docker-first | OUT | Статика на шаред-хостинге, контейнеров нет |
|
||
| I.13 Fail-safe | IN | Битый сейв → старт с дефолтов с пометкой; нет SharedArrayBuffer → честный однопоточный фолбэк; фича-флаги (этапы 8–9) по умолчанию выключены |
|
||
| I.14 Персистентное состояние вне БД | IN | localStorage: version + checksum + атомарность (насколько позволяет API) + миграция + roundtrip-тест — прямо в спеке |
|
||
| I.15 Права на уровне выборки | OUT | Нет сервера и пользователей |
|
||
| I.16 Retention / классы данных для AI | IN (частично) | Сборов данных нет по спеке; класс «данные пользователя не покидают браузер» объявлен письменно здесь: прогресс и партии — только localStorage, во внешние сервисы (включая облачные AI) не отправляются |
|
||
| I.17 Один назначенный писатель | IN | Состояние партии пишет только UI-поток; воркер ИИ — чистый вычислитель, обмен через postMessage |
|
||
| I.18 Не создавай второй канал доставки | IN | Вся статика (включая веса сети на этапе 9) отдаётся тем же хостингом, что и код |
|
||
| I.19 Файлы | IN (адаптация) | SGF-файлы — только через File API в браузере, без сервера |
|
||
| I.20 Автономный/демо-режим | IN | Детерминированные реплеи и тестовые партии — обычные входные данные движка, не ветки if |
|
||
| II.1 Гейты с первого коммита | IN | prettier + eslint + tsc -b --noEmit + vitest = `npm run gates`; hard-блокирующие. Поведение при провале: стоп, показать гейт и stderr, не чинить молча |
|
||
| II.2 Правило→хук | OUT | Проект ведётся разными инструментами/моделями, PreToolUse-хуки — фича одного инструмента; машинная проверка — через npm-гейты и CI (`gotcha-two-agent-configs`) |
|
||
| II.3 Проверяй каждый слой сразу | IN | Прогон gates после каждого слоя каркаса и каждого модуля |
|
||
| II.4 Тулчейн проверяй фактически | IN | Выполнено при развёртывании: версии сверены через npm view 2026-08-05 и запинены |
|
||
| II.5 Типы обязательны, функции ≤40 строк | IN | strict без any; превышение 40 строк — с явным обоснованием в комментарии |
|
||
| II.6 Тесты зеркалят структуру, багфикс приносит тест | IN | AAA; тест = полная жизненная цепочка; для ядра — инварианты алгоритма в docstring + property-based тесты (fast-check, добавляется на этапе 1) |
|
||
| II.7 Тесты wiring — отдельный класс | IN | Orphan-check по каждой публичной функции ядра + интеграционный тест полной партии — прямо в спеке этапа 1 (`gotcha-green-modules-dead-system`) |
|
||
| II.8 Тест без боевой среды — спроектирован | IN | Ядро не импортирует DOM и воркер-API (две оси изоляции); Date.now()/Math.random() запрещены в ядре, часы и seeded RNG инжектируются; headless-прогон партий ботом с проверкой метрик |
|
||
| II.9 Фоновые задачи/очередь | OUT | Нет очереди; Web Worker — не таска в смысле пункта, протокол фиксируется в INTERFACES.md |
|
||
| II.10 Фронтенд | IN (адаптация) | strict без any; без react-query/zustand/RHF — UI минимальный, состояние своё; строки UI — в один ресурсный файл с первого дня; error boundary на маршрут; бюджеты числом (страница урока ≤ 300 КБ) |
|
||
| II.11 CI — не только гейты | IN | GitHub Actions: gates + матрица ubuntu+windows + гейт «чистый клон собирается» + npm audit. Настраивается на этапе 1 вместе с первым кодом |
|
||
| II.12 Лицензионный гейт | IN | Только пермиссивные лицензии зависимостей; THIRD_PARTY_LICENSES.md; цумэ-го — свободная лицензия с атрибуцией (CREDITS.md); лицензия весов KataGo проверяется на этапе 9 |
|
||
| III.1 Карта навигации | IN | Module Map в AGENTS.md + docs/navigation.md (появится с кодом); крупные файлы — порог + команда генерации |
|
||
| III.2 Один индекс и один гейт документации | IN (адаптация) | Доки — markdown в docs/, индекс — docs/README.md; гейт ссылок — легковесный скрипт проверки относительных ссылок (в gates), без mkdocs |
|
||
| III.3 ADR | IN | Этот файл — первый. Существующие ADR не редактируются |
|
||
| III.4 Ритуал закрытия сессии | IN | Триггер «закрываем сессию»; если сводить нечего — сказать явно |
|
||
| III.5 Статусы в планах по факту кода | IN | Реестр «Критические долги» в начале roadmap; закрытие долга — двухфазно |
|
||
| III.6 Версии | IN | SemVer; SoT версии — корневой package.json; версия наблюдаема в подвале сайта; бамп только по явной команде владельца; push тега — отдельное «да» |
|
||
| IV.1 Модель ветвления | IN | Trunk-based: один разработчик, ревью — сам сверка с гейтами; фиксируется здесь |
|
||
| IV.2 Делегирование субагентам | IN | Правку 1–3 строк не делегировать; субагентам — правило контекст-экономии и запрет на commit/push |
|
||
| IV.3 Опасные команды письменно | IN | Список в AGENTS.md; одно «да» = одно действие; escape-вектора (cd && git push, sh -c, eval, xargs) не использовать |
|
||
| IV.4 Не переспрашивай и не угадывай | IN | Дублируется в мастер-промпте |
|
||
| IV.5 TodoWrite, планы в docs/plans/ | IN | Двухфазность: фикс отдельным коммитом, доки отдельным |
|
||
| IV.6 Бюджет точки входа агента | IN | Точка входа — AGENTS.md (инструменто-нейтральная), только то, что нужно каждую сессию; чужие конфиг-каталоги не заводить |
|
||
| IV.7 Нарушаемое правило — дефект системы | IN | Заморозки и осознанные исключения — письменно в самом правиле |
|
||
| IV.8 Гигиена сессии | IN | Ссылки на docs/ в ответах; конфиги сторонних сервисов — по актуальной доке (`gotcha-llm-stale-configs`) |
|
||
| IV.9 Протокол отладки | IN | «Снаружи внутрь»: UI → воркер → движок; зафиксирован в мастер-промпте |
|
||
| V.1–V.8 Прод/эксплуатация/бэкапы | DEFERRED | Активация: этап 8 (свой backend на шареде). До него прода нет — деплой = FTP-заливка статики |
|
||
| V.9 Профиль публичного релиза | IN | Сайт публичный: LICENSE, README-витрина со скриншотами (с этапа 7), CREDITS.md, внутренние доки на русском — записано здесь |
|
||
| V.10 Межпроектные контракты | OUT | Потребителей значений проекта вне его нет |
|
||
| VI Грабли: [Docker] группа | OUT | Контейнеров нет |
|
||
| VI Грабли: [инфра/прод] группа | DEFERRED | Активация с этапом 8. Исключения, уже в спеке этапа 7: `gotcha-https-redirect-proxy` (IN — редирект средствами панели), `gotcha-robots-secret` (IN — актуально при открытии индексации) |
|
||
| VI Грабли: данные и логика, версии, Windows, процесс | IN | Все применимые — постоянный чеклист; особо: `gotcha-gitattributes` (закрыт первым коммитом), `gotcha-non-ascii-toolchain` (файлы для тулчейна — ASCII), `gotcha-green-modules-dead-system` и `gotcha-orphan-config` (wiring-тесты этапа 1), `gotcha-docs-drift` (ритуал закрытия), `gotcha-phantom-tails` (сверка плана с кодом в начале сессии), `gotcha-modal-drag-close` (этап 5, UI) |
|
||
|
||
## Компромиссы — что осознанно потеряли
|
||
|
||
1. **Нет машинных хуков (II.2 OUT)** — дисциплина опирается на npm-гейты и CI, а не на
|
||
блокирующие хуки инструмента. Цена: правило можно нарушить в спешке и узнать об этом
|
||
только на прогоне gates. Принято, потому что проект ведётся разными моделями и
|
||
инструментами (`gotcha-two-agent-configs`, `gotcha-hook-shell-blind`).
|
||
2. **Нет Docker-воспроизводимости среды сборки** — воспроизводимость обеспечивается
|
||
запиненными версиями + engines.node + CI-гейтом «чистый клон собирается».
|
||
3. **Гейт документации — самодельный скрипт ссылок, не mkdocs --strict** — проще, но
|
||
ловит только битые относительные ссылки, не полноту nav.
|
||
4. **Trunk-based без внешнего ревью** — роль ревью выполняют гейты + ритуал закрытия +
|
||
сверка владельца; ошибка может дойти до main, откат — реверт-коммитом.
|
||
5. **Этапы 8–9 остаются недо-триаженными** — раздел V литании активируется отдельным
|
||
до-триажем при старте этапа 8; до тех пор правила прода не действуют.
|