* 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>
6.5 KiB
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).
Решение
CreateArgstype —tagline: stringпереименован вtagline_en: string+tagline_ru: string(оба required, без?). Старый параметр удалён (breaking).- Рендер top-блока — tagline обёрнут в delimiter-пары:
EN-пара идёт первой, затем RU-пара, подряд без пустых строк между ними; пустая строка перед language switcher. Spacing критичен для парсера.# 🚀 {repo_name} <!-- tagline-en:start --> > {tagline_en} <!-- tagline-en:end --> <!-- tagline-ru:start --> > {tagline_ru} <!-- tagline-ru:end --> [English](#-english) | [Русский](#-русский) - 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.
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).- Schema —
taglineпереименован вtagline_en, обновлён.describe()("Must not contain Cyrillic"); добавленtagline_ru(".describe": "Must contain Cyrillic"). Оба.optional()(required-логика вexecute()). - 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" с инструкцией миграции. - Backward compatibility — BREAKING:
taglineудалён, старые вызовы падают с❌ tagline_en is required for create mode. Существующие README (без tagline delimiter-тегов) станут invalid приvalidate—Missing <!-- 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), а не «одна из трёх валидаций не прошла».