schema: spec-driven context: | Language: Russian Пиши на русском, но: - Структурные заголовки оставляй на английском: ## ADDED/MODIFIED/REMOVED Requirements, ### Requirement:, #### Scenario: - Ключевые слова GIVEN/WHEN/THEN и RFC 2119 (SHALL/MUST/SHOULD) — на английском - Технические термины (API, REST, JSON, MCP), пути и код — на английском Имена capabilities: - Capability — это ПОВЕДЕНИЕ/домен системы, а не пакет кода (совпадение с именем пакета допустимо, но не критерий). - Существительное, понятное без знания кода: ingest, parsing, storage, read-api, self-description. НЕ store/httpapi (это реализация). - Гранулярность по принципу «требования меняются вместе». Дробить, когда в одной спеке смешиваются разные заботы. Переименовать дёшево (RENAMED Requirements) — не дроби преждевременно в маленьком проекте. RFC 2119 — это требование валидатора, не стиль: - Каждое ### Requirement ОБЯЗАНО содержать литерал SHALL или MUST, иначе `openspec validate` падает (проверено). Поэтому эти слова и WHEN/THEN не русифицируем — они несут точную нормативную/структурную семантику. Ревью (процесс, не артефакт): - Нетривиальная/архитектурная задача — два чекпоинта: ревью дизайна (после design/specs, ДО кода — дешевле чинить направление) и ревью кода (после apply, до archive). - Тривиальная задача — достаточно одного прохода (код). Конвенции кода (соблюдать при apply): - Механизируемое проверяет `task gate` (.golangci.yml: sloglint, forbidigo, errorlint, depguard; плюс сборка, тесты, race, покрытие изменённых строк, миграции, образцы конфига). Пересказывать его здесь не нужно — гейт скажет точнее. - Прозой остаётся то, что правилом не выражается, и это читаем в источнике: docs/conventions.md — уровень лога по адресату, единственный логирующий чекпоинт на доменной границе, трансляция доменной ошибки на внешней границе, самодокументируемый config.example.toml, время в БД в UTC RFC 3339 через store.Now(), ULID через internal/ident. - Безопасность: данные о здоровье чувствительнее токенов. Ни тела запросов, ни значения точек не попадают в логи выше DEBUG; ничего из ./data не попадает под контроль версий (гейт проверяет шагом no-health-data). Что это за проект: - docs/passport.md — паспорт: цель проекта и её граница (чем он НЕ является), восемь типовых сценариев работы и референсы. ЧИТАЙ ПЕРЕД ПРЕДЛОЖЕНИЕМ: там же правило «развилка или блокер — сперва prior art». Проект не уникален, и прежде чем проектировать своё, смотрим готовые решения в перечисленных проектах; отвергаем — с названной причиной, причина идёт в architecture.md. - healthlog — хранилище данных Apple Health, а не аналитика: принять, дедуплицировать, сохранить, отдать. Агрегат считается только в ответе на запрос и только там, где род метрики измерен сверкой слоёв. - Источников два: поток Health Auto Export (непрерывный и молчаливый) и родной экспорт Apple раз в 2–3 месяца. Вместе они образуют журнал событий: состояние = import(снапшот экспорта) + replay(доставки по received_at). Отсюда требование детерминированной свёртки. - Инварианты целиком — в CLAUDE.md, архитектура — в docs/architecture.md. Разведка уже проведена, догадки о формате не нужны: - docs/local-research.md — 50 находок на живом потоке, половина расходится с документацией Health Auto Export. ПРОВЕРЬ ТАМ, прежде чем строить предположение о формате входа: скорее всего вопрос закрыт измерением. - Тесты на разбор формата держим на реальных пакетах (testdata), а не на выдуманных: документация формата тонкая и местами врёт. # Per-artifact rules (optional) rules: proposal: - Capabilities называй по поведению/домену системы, не по пакету кода specs: # Кавычки обязательны: без них YAML обрежет строку на первом '#'. - "Каждое ### Requirement обязано содержать SHALL или MUST (иначе валидация падает)" - "Сценарий — ровно #### (четыре решётки); три или список молча теряются" - "SHALL/MUST должно стоять в ПЕРВОМ абзаце требования: валидатор смотрит только его, обоснование ниже он не видит (проверено)" - "Заголовки и WHEN/THEN/GIVEN — на английском, остальной текст на русском"