feat(readme): switch support link to /contacts (#270)
* feat(tool): switch create-readme support link to /contacts * feat(scripts): warn on deprecated support link in readme check * feat(templates): switch cookiecutter readme support links to contacts * docs(skill): drop removed validate mode from repo-readme docs * test(status): cover contacts link warn/fail/ok cases * fix(ci): shorten lines to satisfy ruff * fix(ci): apply ruff format --------- Co-authored-by: opencode-agent <agent@opencode.local>
This commit is contained in:
parent
c0e8ec816a
commit
70b8203704
9 changed files with 70 additions and 33 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
---
|
---
|
||||||
description: Standardize repo README + cover image (create/validate)
|
description: Standardize repo README + cover image (create)
|
||||||
agent: build
|
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.
|
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.
|
||||||
|
|
@ -1013,12 +1013,21 @@ def _readme_required_sections(content: str) -> list[CheckResult]:
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
results.append(CheckResult(CheckStatus.OK, "[Русский](#-русский)", "присутствует"))
|
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(
|
results.append(
|
||||||
CheckResult(CheckStatus.FAIL, "slaid098.dev/support", "отсутствует support link")
|
CheckResult(
|
||||||
|
CheckStatus.WARN,
|
||||||
|
"slaid098.dev/contacts",
|
||||||
|
"deprecated: найдена старая ссылка slaid098.dev/support, "
|
||||||
|
"перегенерируй README через create-readme",
|
||||||
|
)
|
||||||
)
|
)
|
||||||
else:
|
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:
|
if "Quick Start" not in content:
|
||||||
results.append(
|
results.append(
|
||||||
CheckResult(CheckStatus.FAIL, "Quick Start", "отсутствует EN секция Quick Start")
|
CheckResult(CheckStatus.FAIL, "Quick Start", "отсутствует EN секция Quick Start")
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,11 @@ Support block, Quick Start, language switcher). Скилл даёт контек
|
||||||
|
|
||||||
- **Новый репо** → `create-readme` (mode: `create`) — генерирует
|
- **Новый репо** → `create-readme` (mode: `create`) — генерирует
|
||||||
стандартизированный двуязычный README с нуля.
|
стандартизированный двуязычный README с нуля.
|
||||||
- **Проверка существующего README** → `create-readme` (mode: `validate`) —
|
- **Проверка существующего README** → `.opencode/scripts/project-status.py`
|
||||||
проверяет, что структура соответствует стандарту витрины.
|
(`check_readme`) — проверяет, что структура соответствует стандарту витрины.
|
||||||
- **После ручных правок README** → всегда `validate`. Любая правка руками
|
- **После ручных правок README** → всегда проверка через `check_readme`. Любая правка руками
|
||||||
агента (через Edit/Write) может нарушить разделители — после правок
|
агента (через Edit/Write) может нарушить разделители — после правок
|
||||||
обязательна валидация.
|
обязательна проверка.
|
||||||
|
|
||||||
Не генерируй README вручную через Write — структура критична для парсинга
|
Не генерируй README вручную через Write — структура критична для парсинга
|
||||||
витриной. Только через тулзу `create-readme`.
|
витриной. Только через тулзу `create-readme`.
|
||||||
|
|
@ -44,9 +44,10 @@ Support block, Quick Start, language switcher). Скилл даёт контек
|
||||||
`"./assets/cover.png"` — можно не передавать.
|
`"./assets/cover.png"` — можно не передавать.
|
||||||
3. Ручные правки если нужно (агент редактирует файл напрямую через Edit) —
|
3. Ручные правки если нужно (агент редактирует файл напрямую через Edit) —
|
||||||
например, расширить `custom_sections`, поправить формулировки.
|
например, расширить `custom_sections`, поправить формулировки.
|
||||||
4. `create-readme` (mode: `validate`) → проверяет, что структура не нарушена
|
4. Проверка через `.opencode/scripts/project-status.py` (`check_readme`) →
|
||||||
(теперь в т.ч. наличие `assets/cover.png` reference).
|
структура соответствует стандарту витрины (в т.ч. наличие
|
||||||
5. Если `validate` fails → фикс нарушения → re-`validate`. Цикл пока не
|
`assets/cover.png` reference).
|
||||||
|
5. Если проверка fails → фикс нарушения → повторная проверка. Цикл пока не
|
||||||
пройдёт.
|
пройдёт.
|
||||||
|
|
||||||
Локальный режим (по умолчанию): тулза пишет в `file_path` (default
|
Локальный режим (по умолчанию): тулза пишет в `file_path` (default
|
||||||
|
|
@ -95,7 +96,7 @@ README ссылается именно на этот путь через `**
|
👉 **[slaid098.dev/contacts](https://slaid098.dev/contacts)**
|
||||||
```
|
```
|
||||||
|
|
||||||
`validate` проверяет: наличие всех 6 пар EN/RU разделителей (tagline + summary +
|
`check_readme` (project-status.py) проверяет: наличие всех 6 пар EN/RU
|
||||||
features), непустой контент между ними, H1 title prefix `# 🚀 `, **cover image
|
разделителей (tagline + summary + features), непустой контент между ними, H1
|
||||||
|
title prefix `# 🚀 `, **cover image
|
||||||
reference `assets/cover.png`** (substring-чек, без проверки существования
|
reference `assets/cover.png`** (substring-чек, без проверки существования
|
||||||
файла), ссылку
|
файла), ссылку
|
||||||
`slaid098.dev/support`, секции Quick Start (EN) и Быстрый старт (RU), language
|
`slaid098.dev/contacts`, секции Quick Start (EN) и Быстрый старт (RU), language
|
||||||
switcher `[English]` / `[Русский]`, заголовок `## 🇷🇺 Русский` (не "Русская
|
switcher `[English]` / `[Русский]`, заголовок `## 🇷🇺 Русский` (не "Русская
|
||||||
версия"), anchor `[Русский](#-русский)` (не `#-русская-версия`). Флагирует
|
версия"), anchor `[Русский](#-русский)` (не `#-русская-версия`). Флагирует
|
||||||
ручной заголовок `## License` / `## LICENSE` / `## Лицензия` как ERROR —
|
ручной заголовок `## License` / `## LICENSE` / `## Лицензия` как FAIL —
|
||||||
дубликат GitHub sidebar (GitHub рендерит license из LICENSE-файла). Шаги
|
дубликат GitHub sidebar (GitHub рендерит license из LICENSE-файла). Шаги
|
||||||
`quick_start_steps_*` не влияют на валидацию — они рендерятся вне delimiter-пар
|
`quick_start_steps_*` не влияют на валидацию — они рендерятся вне delimiter-пар
|
||||||
(summary/features).
|
(summary/features).
|
||||||
|
|
@ -209,7 +211,7 @@ switcher `[English]` / `[Русский]`, заголовок `## 🇷🇺 Ру
|
||||||
|
|
||||||
`create-readme`:
|
`create-readme`:
|
||||||
|
|
||||||
- `mode` — `"create"` | `"validate"` (обязательный).
|
- `mode` — `"create"` (обязательный).
|
||||||
- `repo_name`, `tagline_en`, `tagline_ru`, `why_en`, `what_en`, `why_ru`,
|
- `repo_name`, `tagline_en`, `tagline_ru`, `why_en`, `what_en`, `why_ru`,
|
||||||
`what_ru`, `quick_start`, `features_en`, `features_ru` — обязательны для
|
`what_ru`, `quick_start`, `features_en`, `features_ru` — обязательны для
|
||||||
`create`.
|
`create`.
|
||||||
|
|
@ -315,6 +317,6 @@ Access at [http://localhost:4096](http://localhost:4096)
|
||||||
`❌ tagline_en is required for create mode`.
|
`❌ tagline_en is required for create mode`.
|
||||||
|
|
||||||
**Существующие README** (без tagline delimiter-тегов) станут invalid при
|
**Существующие README** (без tagline delimiter-тегов) станут invalid при
|
||||||
`validate` — `Missing <!-- tagline-en:start --> delimiter` и
|
проверке `check_readme` — `Missing <!-- tagline-en:start --> delimiter` и
|
||||||
`Missing <!-- tagline-ru:start --> delimiter`. Регенерация README через
|
`Missing <!-- tagline-ru:start --> delimiter`. Регенерация README через
|
||||||
`create` (с новыми параметрами) делается отдельным шагом после merge.
|
`create` (с новыми параметрами) делается отдельным шагом после merge.
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ uv run uvicorn main:app --reload
|
||||||
|
|
||||||
## 💬 Support and contacts / Поддержка и контакты
|
## 💬 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 / Поддержка и контакты
|
## 💬 Support and contacts / Поддержка и контакты
|
||||||
|
|
||||||
👉 **[slaid098.dev/support](https://slaid098.dev/support)**
|
👉 **[slaid098.dev/contacts](https://slaid098.dev/contacts)**
|
||||||
|
|
@ -31,7 +31,7 @@ uv sync --extra dev
|
||||||
|
|
||||||
## 💬 Support and contacts / Поддержка и контакты
|
## 💬 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 / Поддержка и контакты
|
## 💬 Support and contacts / Поддержка и контакты
|
||||||
|
|
||||||
👉 **[slaid098.dev/support](https://slaid098.dev/support)**
|
👉 **[slaid098.dev/contacts](https://slaid098.dev/contacts)**
|
||||||
|
|
@ -32,7 +32,7 @@ cd frontend && npm install && npm run dev
|
||||||
|
|
||||||
## 💬 Support and contacts / Поддержка и контакты
|
## 💬 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 / Поддержка и контакты
|
## 💬 Support and contacts / Поддержка и контакты
|
||||||
|
|
||||||
👉 **[slaid098.dev/support](https://slaid098.dev/support)**
|
👉 **[slaid098.dev/contacts](https://slaid098.dev/contacts)**
|
||||||
|
|
@ -126,7 +126,7 @@ ${bashBlockRu}${stepsRu}${accessLineRu}${developmentBlockRu}
|
||||||
|
|
||||||
## 💬 Support and contacts / Поддержка и контакты
|
## 💬 Support and contacts / Поддержка и контакты
|
||||||
|
|
||||||
👉 **[slaid098.dev/support](https://slaid098.dev/support)**
|
👉 **[slaid098.dev/contacts](https://slaid098.dev/contacts)**
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -125,7 +125,7 @@ pip install -r requirements.txt
|
||||||
|
|
||||||
## 💬 Support and contacts / Поддержка и контакты
|
## 💬 Support and contacts / Поддержка и контакты
|
||||||
|
|
||||||
👉 **[slaid098.dev/support](https://slaid098.dev/support)**
|
👉 **[slaid098.dev/contacts](https://slaid098.dev/contacts)**
|
||||||
"""
|
"""
|
||||||
|
|
||||||
DELIMITERS = [
|
DELIMITERS = [
|
||||||
|
|
|
||||||
|
|
@ -860,7 +860,7 @@ def _write_valid_readme(tmp_path: Path) -> None:
|
||||||
content = (
|
content = (
|
||||||
"# 🚀 Title\n[English](#-english) [Русский](#-русский)\n"
|
"# 🚀 Title\n[English](#-english) [Русский](#-русский)\n"
|
||||||
"## 🇺🇸 English\n## 🇷🇺 Русский\nassets/cover.png\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:
|
for d in ps.README_DELIMITERS:
|
||||||
content += f"<!-- {d} -->\n"
|
content += f"<!-- {d} -->\n"
|
||||||
|
|
@ -887,7 +887,7 @@ def test_readme_missing(tmp_path, ctx):
|
||||||
def test_readme_missing_delimiters(tmp_path, ctx):
|
def test_readme_missing_delimiters(tmp_path, ctx):
|
||||||
(tmp_path / "README.md").write_text(
|
(tmp_path / "README.md").write_text(
|
||||||
"# 🚀 Title\n## 🇺🇸 English\n## 🇷🇺 Русский\n[English](#-english)\n"
|
"# 🚀 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)
|
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)
|
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):
|
def test_readme_missing_support_link_fail(tmp_path, ctx):
|
||||||
"""README без ``slaid098.dev/support`` → FAIL."""
|
"""README без обеих ссылок (contacts/support) → FAIL."""
|
||||||
_write_valid_readme(tmp_path)
|
_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)
|
(tmp_path / "README.md").write_text(content)
|
||||||
group = ps.check_readme(ps.ProjectType.BACKEND, ctx)
|
group = ps.check_readme(ps.ProjectType.BACKEND, ctx)
|
||||||
assert any(
|
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
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue