go-learn/docs/decisions/ADR-0001-triage-litany.md
sab.code.lab 1c85091186 chore: восстановление репозитория из снапшота v0.3.1
Прежняя git-история утрачена при переносе проекта на машину владельца
(снапшот без .git). Хэши коммитов в docs/reports/* относятся к утраченной
истории.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 09:34:02 +02:00

89 lines
33 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ADR-0001. Триаж prestart-litany для профиля M
- Дата: 2026-08-05
- Статус: принят
- Ссылки на литанию — слагами/названиями пунктов, не номерами (`gotcha-renumbered-parent`).
## Контекст
Проект «Сайт обучения Го»: профиль **M** (продукт без своего прода) — код, тесты,
релизы, но нет своего сервера/БД (до опциональных этапов 89). Полностью клиентский:
статическая сборка на шаред-хостинг, движок и ИИ — в браузере. Один разработчик,
сессии ведут разные ИИ-модели без общей памяти.
## Триаж
| Пункт литании | Вердикт | Причина / условие |
| ---------------------------------------------------- | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 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 | Нет внешних сервисов на этапах 17. Загрузка весов 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 → честный однопоточный фолбэк; фича-флаги (этапы 89) по умолчанию выключены |
| 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 | Правку 13 строк не делегировать; субагентам — правило контекст-экономии и запрет на 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.1V.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. **Этапы 89 остаются недо-триаженными** — раздел V литании активируется отдельным
до-триажем при старте этапа 8; до тех пор правила прода не действуют.