opencode-config/docs/decisions/064-pr-151-bilingual-tagline.md
Sergey 6c80eb8458
feat(create-readme): add bilingual tagline and repo_name validation (#151)
* feat(create-readme): add bilingual tagline and repo_name validation

* docs(repo-readme): bilingual tagline + repo_name validation rules

* docs(handoff): add handoff and ADR-064 for bilingual tagline

* docs(handoff): set PR number

* docs(project-map): update after PR#151 bilingual tagline changes

---------

Co-authored-by: opencode-agent <agent@opencode.local>
2026-07-30 04:50:50 +03:00

6.5 KiB
Raw Permalink Blame History

ADR-064: Bilingual tagline and repo_name validation (PR-151)

Статус

Accepted (2026-07-30)

Контекст

ADR-062 (PR-146) и ADR-063 (PR-149) эволюционировали тулзу create-readme вокруг Quick Start. Параметр tagline оставался единым английским теглайном с момента ADR-058 (PR-116, README standard v2). Витрина slaid098.dev парсит README через delimiter-теги (summary/features), но tagline рендерился вне delimiterов — парсер не мог его надёжно извлечь, и RU tagline отсутствовал вообще. Дополнительно: repo_name принимал любой строки (uppercase, underscores, пробелы) — генерировал git clone ссылки вида https://github.com/slaid098/MyRepo.git (валидные, но не matching actual repo slug); tagline_en никто не проверял на отсутствие кириллицы, а tagline_ru не существовало. Issue #150 требует: (A) билингвальный tagline EN+RU с delimiter-тегами, (B) валидация английского repo_name (lowercase kebab-case) и tagline_en (no Cyrillic), tagline_ru (require Cyrillic).

Решение

  1. CreateArgs typetagline: string переименован в tagline_en: string + tagline_ru: string (оба required, без ?). Старый параметр удалён (breaking).
  2. Рендер top-блока — tagline обёрнут в delimiter-пары:
    # 🚀 {repo_name}
    <!-- tagline-en:start -->
    > {tagline_en}
    <!-- tagline-en:end -->
    <!-- tagline-ru:start -->
    > {tagline_ru}
    <!-- tagline-ru:end -->
    
    [English](#-english) | [Русский](#-русский)
    
    EN-пара идёт первой, затем RU-пара, подряд без пустых строк между ними; пустая строка перед language switcher. Spacing критичен для парсера.
  3. Content-валидация в execute() — после presence-чеков (required Record, falsy !v), ДО Quick Start guard (PR #149), добавлены:
    • repo_name: ^[a-z0-9]+(-[a-z0-9]+)*$ — lowercase kebab-case, только a-z/0-9, одиночные дефисы (не leading/trailing/consecutive).
    • tagline_en: /[ЁА-яё]/ reject — если есть кириллица → ошибка.
    • tagline_ru: /[ЁА-яё]/ require — если нет кириллицы → ошибка (ловит копию английского tagline). Порядок: presence → content (regex) → Quick Start guard.
  4. validateReadme — добавлено 4 delimiter'а в массив (tagline-en/ru start/end, итого 12), +2 пары в pairs (EN/RU tagline, с empty-content check), +check H1 prefix # 🚀 (substring). repo_name regex в validate НЕ добавлен — legacy README с uppercase repo_name не должны ломаться (валидируется только в create mode).
  5. Schematagline переименован в tagline_en, обновлён .describe() ("Must not contain Cyrillic"); добавлен tagline_ru (".describe": "Must contain Cyrillic"). Оба .optional() (required-логика в execute()).
  6. SKILL.md — раздел 4 (delimiters): +tagline-en/ru; раздел 5 (шаблон): top-блок с delimiter-тегами; раздел 5 (validate): "6 пар EN/RU разделителей (tagline + summary + features)" + H1 prefix; раздел 7 (параметры): tagline_en/tagline_ru с правилами, repo_name с regex; раздел 8 (пример): tagline_en/tagline_ru; новый раздел 9 "Breaking change: tagline → tagline_en + tagline_ru" с инструкцией миграции.
  7. Backward compatibility — BREAKING: tagline удалён, старые вызовы падают с ❌ tagline_en is required for create mode. Существующие README (без tagline delimiter-тегов) станут invalid при validateMissing <!-- tagline-en:start --> delimiter и тег. Регенерация README отдельный шаг после merge.

Альтернативы

  • Оставить tagline как alias к tagline_en — отвергнуто: молчаливый дуализм (то tagline, то tagline_en) запутывает пользователей и парсер. Явный breaking с понятным сообщением ❌ tagline_en is required лучше для миграции (одна правка вызова, а не поиск «почему RU tagline пустой»).
  • Один tagline + авто-перевод — отвергнуто: перевод tagline — не responsibility тулзы, качество перевода критично для карточки slaid098.dev. Явный tagline_ru с require-Cyrillic-чеком гарантирует осмысленный русский.
  • Валидировать repo_name в validateReadme — отвергнуто: legacy README с uppercase repo_name (например, старые репо до стандарта) не должны ломаться при validate. Regex только в create (новые README генерируются по стандарту). validate проверяет структуру (delimiterы, заголовки), не контент repo_name.
  • Строгий H1 check (regex на полный # 🚀 {repo_name}) — отвергнуто: validate не знает repo_name (работает с произвольным README). Substring-чек # 🚀 ловит отсутствие префикса, не валидирует что после него. Достаточно для regression-детекции.
  • Три отдельных tagline-чек (presence + regex EN + regex RU) как один guard — отвергнуто: три независимых if return с разными сообщениями читаемее, чем комбинированный guard. Пользователь видит конкретную ошибку (repo_name / tagline_en / tagline_ru), а не «одна из трёх валидаций не прошла».