diff --git a/.opencode/commands/repo-readme.md b/.opencode/commands/repo-readme.md index 1b540e5..6b77523 100644 --- a/.opencode/commands/repo-readme.md +++ b/.opencode/commands/repo-readme.md @@ -1,5 +1,5 @@ --- -description: Standardize repo README + cover image (create/validate) +description: Standardize repo README + cover image (create) agent: build --- -Load the `repo-readme` skill via `skill({name: "repo-readme"})` and follow its ПРОТОКОЛ strictly. Workflow: create-readme (generate) → draw-image (cover) → validate → fix cycle. One command = full README + cover standardization. \ No newline at end of file +Load the `repo-readme` skill via `skill({name: "repo-readme"})` and follow its ПРОТОКОЛ strictly. Workflow: create-readme (create) → draw-image (cover) → проверка через project-status check_readme. One command = full README + cover standardization. \ No newline at end of file diff --git a/.opencode/scripts/project-status.py b/.opencode/scripts/project-status.py index a6b2a12..442439d 100644 --- a/.opencode/scripts/project-status.py +++ b/.opencode/scripts/project-status.py @@ -1013,12 +1013,21 @@ def _readme_required_sections(content: str) -> list[CheckResult]: ) else: results.append(CheckResult(CheckStatus.OK, "[Русский](#-русский)", "присутствует")) - if "slaid098.dev/support" not in content: + if "slaid098.dev/contacts" in content: + results.append(CheckResult(CheckStatus.OK, "slaid098.dev/contacts", "присутствует")) + elif "slaid098.dev/support" in content: results.append( - CheckResult(CheckStatus.FAIL, "slaid098.dev/support", "отсутствует support link") + CheckResult( + CheckStatus.WARN, + "slaid098.dev/contacts", + "deprecated: найдена старая ссылка slaid098.dev/support, " + "перегенерируй README через create-readme", + ) ) else: - results.append(CheckResult(CheckStatus.OK, "slaid098.dev/support", "присутствует")) + results.append( + CheckResult(CheckStatus.FAIL, "slaid098.dev/contacts", "отсутствует support link") + ) if "Quick Start" not in content: results.append( CheckResult(CheckStatus.FAIL, "Quick Start", "отсутствует EN секция Quick Start") diff --git a/.opencode/skills/repo-readme/SKILL.md b/.opencode/skills/repo-readme/SKILL.md index 0a97ce4..51942be 100644 --- a/.opencode/skills/repo-readme/SKILL.md +++ b/.opencode/skills/repo-readme/SKILL.md @@ -14,11 +14,11 @@ Support block, Quick Start, language switcher). Скилл даёт контек - **Новый репо** → `create-readme` (mode: `create`) — генерирует стандартизированный двуязычный README с нуля. -- **Проверка существующего README** → `create-readme` (mode: `validate`) — - проверяет, что структура соответствует стандарту витрины. -- **После ручных правок README** → всегда `validate`. Любая правка руками +- **Проверка существующего README** → `.opencode/scripts/project-status.py` + (`check_readme`) — проверяет, что структура соответствует стандарту витрины. +- **После ручных правок README** → всегда проверка через `check_readme`. Любая правка руками агента (через Edit/Write) может нарушить разделители — после правок - обязательна валидация. + обязательна проверка. Не генерируй README вручную через Write — структура критична для парсинга витриной. Только через тулзу `create-readme`. @@ -44,9 +44,10 @@ Support block, Quick Start, language switcher). Скилл даёт контек `"./assets/cover.png"` — можно не передавать. 3. Ручные правки если нужно (агент редактирует файл напрямую через Edit) — например, расширить `custom_sections`, поправить формулировки. -4. `create-readme` (mode: `validate`) → проверяет, что структура не нарушена - (теперь в т.ч. наличие `assets/cover.png` reference). -5. Если `validate` fails → фикс нарушения → re-`validate`. Цикл пока не +4. Проверка через `.opencode/scripts/project-status.py` (`check_readme`) → + структура соответствует стандарту витрины (в т.ч. наличие + `assets/cover.png` reference). +5. Если проверка fails → фикс нарушения → повторная проверка. Цикл пока не пройдёт. Локальный режим (по умолчанию): тулза пишет в `file_path` (default @@ -95,7 +96,7 @@ README ссылается именно на этот путь через `![Cove Поэтому структура README **должна быть гарантирована тулзой**, а не агентом. Агент может менять текст *внутри* разделителей, но не должен удалять/двигать -сами разделители. `validate` ловит такие нарушения. +сами разделители. `check_readme` ловит такие нарушения. ## 5. Шаблон README (reference) @@ -181,17 +182,18 @@ README ссылается именно на этот путь через `![Cove ## 💬 Support and contacts / Поддержка и контакты -👉 **[slaid098.dev/support](https://slaid098.dev/support)** +👉 **[slaid098.dev/contacts](https://slaid098.dev/contacts)** ``` -`validate` проверяет: наличие всех 6 пар EN/RU разделителей (tagline + summary + -features), непустой контент между ними, H1 title prefix `# 🚀 `, **cover image +`check_readme` (project-status.py) проверяет: наличие всех 6 пар EN/RU +разделителей (tagline + summary + features), непустой контент между ними, H1 +title prefix `# 🚀 `, **cover image reference `assets/cover.png`** (substring-чек, без проверки существования файла), ссылку -`slaid098.dev/support`, секции Quick Start (EN) и Быстрый старт (RU), language +`slaid098.dev/contacts`, секции Quick Start (EN) и Быстрый старт (RU), language switcher `[English]` / `[Русский]`, заголовок `## 🇷🇺 Русский` (не "Русская версия"), anchor `[Русский](#-русский)` (не `#-русская-версия`). Флагирует -ручной заголовок `## License` / `## LICENSE` / `## Лицензия` как ERROR — +ручной заголовок `## License` / `## LICENSE` / `## Лицензия` как FAIL — дубликат GitHub sidebar (GitHub рендерит license из LICENSE-файла). Шаги `quick_start_steps_*` не влияют на валидацию — они рендерятся вне delimiter-пар (summary/features). @@ -209,7 +211,7 @@ switcher `[English]` / `[Русский]`, заголовок `## 🇷🇺 Ру `create-readme`: -- `mode` — `"create"` | `"validate"` (обязательный). +- `mode` — `"create"` (обязательный). - `repo_name`, `tagline_en`, `tagline_ru`, `why_en`, `what_en`, `why_ru`, `what_ru`, `quick_start`, `features_en`, `features_ru` — обязательны для `create`. @@ -315,6 +317,6 @@ Access at [http://localhost:4096](http://localhost:4096) `❌ tagline_en is required for create mode`. **Существующие README** (без tagline delimiter-тегов) станут invalid при -`validate` — `Missing delimiter` и +проверке `check_readme` — `Missing delimiter` и `Missing delimiter`. Регенерация README через `create` (с новыми параметрами) делается отдельным шагом после merge. diff --git a/.opencode/templates/backend/{{cookiecutter.project_name}}/README.md b/.opencode/templates/backend/{{cookiecutter.project_name}}/README.md index 4f9f883..26baca5 100644 --- a/.opencode/templates/backend/{{cookiecutter.project_name}}/README.md +++ b/.opencode/templates/backend/{{cookiecutter.project_name}}/README.md @@ -32,7 +32,7 @@ uv run uvicorn main:app --reload ## 💬 Support and contacts / Поддержка и контакты -👉 **[slaid098.dev/support](https://slaid098.dev/support)** +👉 **[slaid098.dev/contacts](https://slaid098.dev/contacts)** --- @@ -64,4 +64,4 @@ uv run uvicorn main:app --reload ## 💬 Support and contacts / Поддержка и контакты -👉 **[slaid098.dev/support](https://slaid098.dev/support)** \ No newline at end of file +👉 **[slaid098.dev/contacts](https://slaid098.dev/contacts)** \ No newline at end of file diff --git a/.opencode/templates/cli/{{cookiecutter.project_name}}/README.md b/.opencode/templates/cli/{{cookiecutter.project_name}}/README.md index 7ee5d14..6a4d457 100644 --- a/.opencode/templates/cli/{{cookiecutter.project_name}}/README.md +++ b/.opencode/templates/cli/{{cookiecutter.project_name}}/README.md @@ -31,7 +31,7 @@ uv sync --extra dev ## 💬 Support and contacts / Поддержка и контакты -👉 **[slaid098.dev/support](https://slaid098.dev/support)** +👉 **[slaid098.dev/contacts](https://slaid098.dev/contacts)** --- @@ -62,4 +62,4 @@ uv sync --extra dev ## 💬 Support and contacts / Поддержка и контакты -👉 **[slaid098.dev/support](https://slaid098.dev/support)** \ No newline at end of file +👉 **[slaid098.dev/contacts](https://slaid098.dev/contacts)** \ No newline at end of file diff --git a/.opencode/templates/fullstack/{{cookiecutter.project_name}}/README.md b/.opencode/templates/fullstack/{{cookiecutter.project_name}}/README.md index 4d8cbd0..2b78295 100644 --- a/.opencode/templates/fullstack/{{cookiecutter.project_name}}/README.md +++ b/.opencode/templates/fullstack/{{cookiecutter.project_name}}/README.md @@ -32,7 +32,7 @@ cd frontend && npm install && npm run dev ## 💬 Support and contacts / Поддержка и контакты -👉 **[slaid098.dev/support](https://slaid098.dev/support)** +👉 **[slaid098.dev/contacts](https://slaid098.dev/contacts)** --- @@ -64,4 +64,4 @@ cd frontend && npm install && npm run dev ## 💬 Support and contacts / Поддержка и контакты -👉 **[slaid098.dev/support](https://slaid098.dev/support)** \ No newline at end of file +👉 **[slaid098.dev/contacts](https://slaid098.dev/contacts)** \ No newline at end of file diff --git a/.opencode/tools/create-readme.ts b/.opencode/tools/create-readme.ts index e15f0f3..6724355 100644 --- a/.opencode/tools/create-readme.ts +++ b/.opencode/tools/create-readme.ts @@ -126,7 +126,7 @@ ${bashBlockRu}${stepsRu}${accessLineRu}${developmentBlockRu} ## 💬 Support and contacts / Поддержка и контакты -👉 **[slaid098.dev/support](https://slaid098.dev/support)** +👉 **[slaid098.dev/contacts](https://slaid098.dev/contacts)** ` } diff --git a/tests/test_create_readme_tool.py b/tests/test_create_readme_tool.py index 7e22264..5ec8f24 100644 --- a/tests/test_create_readme_tool.py +++ b/tests/test_create_readme_tool.py @@ -125,7 +125,7 @@ pip install -r requirements.txt ## 💬 Support and contacts / Поддержка и контакты -👉 **[slaid098.dev/support](https://slaid098.dev/support)** +👉 **[slaid098.dev/contacts](https://slaid098.dev/contacts)** """ DELIMITERS = [ diff --git a/tests/test_project_status.py b/tests/test_project_status.py index bab9462..c10e29a 100644 --- a/tests/test_project_status.py +++ b/tests/test_project_status.py @@ -860,7 +860,7 @@ def _write_valid_readme(tmp_path: Path) -> None: content = ( "# 🚀 Title\n[English](#-english) [Русский](#-русский)\n" "## 🇺🇸 English\n## 🇷🇺 Русский\nassets/cover.png\n" - "Quick Start\nБыстрый старт\nslaid098.dev/support\n" + "Quick Start\nБыстрый старт\nslaid098.dev/contacts\n" ) for d in ps.README_DELIMITERS: content += f"\n" @@ -887,7 +887,7 @@ def test_readme_missing(tmp_path, ctx): def test_readme_missing_delimiters(tmp_path, ctx): (tmp_path / "README.md").write_text( "# 🚀 Title\n## 🇺🇸 English\n## 🇷🇺 Русский\n[English](#-english)\n" - "[Русский](#-русский)\nQuick Start\nБыстрый старт\nslaid098.dev/support\n" + "[Русский](#-русский)\nQuick Start\nБыстрый старт\nslaid098.dev/contacts\n" ) group = ps.check_readme(ps.ProjectType.BACKEND, ctx) assert any("delimiter" in c.name and c.status == ps.CheckStatus.FAIL for c in group.checks) @@ -905,13 +905,39 @@ def test_readme_missing_ru_switcher_fail(tmp_path, ctx): def test_readme_missing_support_link_fail(tmp_path, ctx): - """README без ``slaid098.dev/support`` → FAIL.""" + """README без обеих ссылок (contacts/support) → FAIL.""" _write_valid_readme(tmp_path) - content = (tmp_path / "README.md").read_text().replace("slaid098.dev/support", "") + content = (tmp_path / "README.md").read_text().replace("slaid098.dev/contacts", "") (tmp_path / "README.md").write_text(content) group = ps.check_readme(ps.ProjectType.BACKEND, ctx) assert any( - c.name == "slaid098.dev/support" and c.status == ps.CheckStatus.FAIL for c in group.checks + c.name == "slaid098.dev/contacts" and c.status == ps.CheckStatus.FAIL for c in group.checks + ) + assert group.overall() == ps.CheckStatus.FAIL + + +def test_readme_deprecated_support_link_warn(tmp_path, ctx): + """README только со старой ссылкой ``slaid098.dev/support`` → WARN (не FAIL).""" + _write_valid_readme(tmp_path) + content = ( + (tmp_path / "README.md") + .read_text() + .replace("slaid098.dev/contacts", "slaid098.dev/support") + ) + (tmp_path / "README.md").write_text(content) + group = ps.check_readme(ps.ProjectType.BACKEND, ctx) + assert any( + c.name == "slaid098.dev/contacts" and c.status == ps.CheckStatus.WARN for c in group.checks + ) + assert group.overall() == ps.CheckStatus.WARN + + +def test_readme_contacts_link_ok(tmp_path, ctx): + """README со ссылкой ``slaid098.dev/contacts`` → OK.""" + _write_valid_readme(tmp_path) + group = ps.check_readme(ps.ProjectType.BACKEND, ctx) + assert any( + c.name == "slaid098.dev/contacts" and c.status == ps.CheckStatus.OK for c in group.checks )