fix(create-readme): validate EN switcher anchor symmetrically (#155)

* fix(create-readme): validate EN switcher anchor symmetrically

* docs(handoff): add handoff and ADR for switcher validation

* docs(handoff): set PR number

---------

Co-authored-by: opencode-agent <agent@opencode.local>
This commit is contained in:
Sergey 2026-07-30 19:57:46 +03:00 committed by GitHub
parent 7330f05055
commit 556a5b57eb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 35 additions and 5 deletions

View file

@ -133,7 +133,7 @@ ${bashBlockRu}${stepsRu}${accessLineRu}${developmentBlockRu}
` `
} }
function validateReadme(content: string): { ok: boolean; issues: string[] } { export function validateReadme(content: string): { ok: boolean; issues: string[] } {
const issues: string[] = [] const issues: string[] = []
const delimiters = [ const delimiters = [
@ -179,10 +179,8 @@ function validateReadme(content: string): { ok: boolean; issues: string[] } {
issues.push("Missing 'Quick Start' section (English)") issues.push("Missing 'Quick Start' section (English)")
if (!content.includes("Быстрый старт")) if (!content.includes("Быстрый старт"))
issues.push("Missing 'Быстрый старт' section (Russian)") issues.push("Missing 'Быстрый старт' section (Russian)")
if (!content.includes("[English]")) if (!content.includes("[English](#-english)"))
issues.push("Missing [English] language switcher link") issues.push("Missing or wrong [English](#-english) switcher link (should be #-english)")
if (!content.includes("[Русский]"))
issues.push("Missing [Русский] language switcher link")
if (!content.includes("## 🇷🇺 Русский")) if (!content.includes("## 🇷🇺 Русский"))
issues.push("Missing '## 🇷🇺 Русский' header (should be 'Русский', not 'Русская версия')") issues.push("Missing '## 🇷🇺 Русский' header (should be 'Русский', not 'Русская версия')")
if (!content.includes("## 🇺🇸 English")) if (!content.includes("## 🇺🇸 English"))

View file

@ -0,0 +1,13 @@
# ADR-066: Symmetric switcher anchor validation
## Статус
Accepted (2026-07-30)
## Контекст
`validateReadme` в `.opencode/tools/create-readme.ts` проверяла language switcher асимметрично: RU-переключатель проверялся строгим full-anchor чеком `[Русский](#-русский)`, а EN — только подстрокой `[English]` без проверки anchor. Template рендерит switcher симметрично: `[English](#-english) | [Русский](#-русский)`, но валидация не зеркалировала это.
## Решение
Убрать 2 избыточных substring-чека и заменить на 2 строгих симметричных full-anchor чека: `[English](#-english)` и `[Русский](#-русский)`. Substring-чеки были избыточны — строгий чек субсумирует их (`[English](#-english)` содержит `[English]`).
## Альтернативы
Оставить асимметрию и добавить отдельный regex-чек для EN anchor — отвергнуто как избыточное усложнение. Простой `includes()` достаточен и зеркалирует существующий RU-чек.

View file

@ -0,0 +1,19 @@
---
pr: 155
title: Symmetric EN/RU switcher anchor validation in validateReadme
---
## Что сделано
- Удалены 2 избыточных substring-чека (`[English]` и `[Русский]` как подстроки) — они субсумируются строгими full-anchor чеками.
- Добавлен строгий full-anchor чек для EN: `[English](#-english)` (зеркало существующего RU-чека `[Русский](#-русский)`).
- Добавлен `export` к функции `validateReadme` для возможности импорта в тестах.
- Smoke-тест: 8/8 edge cases passed (валидный switcher, битые EN/RU anchors, отсутствие anchor, битые ссылки, не-markdown текст).
## Почему
Валидация language switcher была асимметричной: RU проверялся строго (полный anchor `[Русский](#-русский)`), а EN — только подстрокой `[English]` без проверки anchor. 4 класса дефектов EN-switcher пропускались: битый anchor, отсутствие anchor, битая ссылка, не-markdown-ссылка.
## Pending
## Watch out
Функция `validateReadme` теперь экспортируется — это публичный API. Ранее была module-private.