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

33 KiB
Raw Permalink Blame History

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; до тех пор правила прода не действуют.