feat(release): create-changelog tool with Russian validation #60

Merged
slaid098 merged 5 commits from feat/release/create-changelog-tool into main 2026-08-12 15:18:05 +03:00
Owner

Что сделано

Добавлен детерминированный инструмент create-changelog (.opencode/tools/create-changelog.ts) для валидации и записи CHANGELOG с бампом pyproject.toml и __init__.__version__. Скилл release переведён на использование тулзы вместо ручного bash, возвращён потерянный Шаг 3.5.

  • create-changelog.ts: валидация версии (vX.Y.Z), кириллицы, одной строки, ≤200 символов, запрещённых паттернов ((PR#N), Closes #N, **Category**:). Действие: переименование ## [Unreleased] → ## [X.Y.Z] - YYYY-MM-DD, новый пустой ## [Unreleased] сверху, секции ### Добавлено/Изменено/Исправлено/Удалено, бамп pyproject.toml (version = "X.Y.Z") и __init__.py (__version__) при наличии файлов.
  • release/SKILL.md: Шаг 3 вызывает тулзу; добавлен Шаг 3.5 (бамп pyproject + __init__ — теперь делает тулза автоматически); убрано правило "НЕ обновляй pyproject.toml version"; описан стандарт записей и цикл валидации (тулза вернула ошибки → агент исправляет → повтор).
  • tests/_ts_loader.mjs: добавлен env var WORKTREE_STUB для переопределения context.worktree в exec_stub_json/exec_real режимах — файловые тулзы (create-changelog) могут писать в tmp dir, не затирая CHANGELOG репо. Обратно-совместимо (default=REPO_ROOT).
  • tests/test_create_changelog_tool.py: 13 тестов — happy path (CHANGELOG + pyproject + __init__), invalid version (без v), no Cyrillic, multi-line entry, >200 chars, запрещённые паттерны (PR#4)/Closes #1/**Audio**:, all sections empty, missing CHANGELOG (создаётся с нуля), missing pyproject (пропуск), missing __init__ (пропуск).

Почему

Процесс релизов создавал мусорные release notes: скрипт create_release.py пихал весь CHANGELOG.md (267 строк, 29 КБ) в body релиза. Записи — смесь английского и русского, абзацы вместо однострочников, мусор (PR#N), **Category**:. Шаг 3.5 (бамп pyproject + __init__) был потерян (правили в ~/.config/opencode/ bind-mount, а не в workspace-клоне). Детерминированная тулза с валидацией устраняет эти проблемы: одинаковые args → одинаковый результат, агент не может вставить мусорную запись (fail-fast с RULES).

Watch out

  • Перезапуск opencode обязателен — тулза авто-обнаруживается из .opencode/tools/ только при старте.
  • WORKTREE_STUB env var в _ts_loader.mjs меняет context.worktree для всех тулз в exec_stub_json/exec_real — если существующие тесты не задают его, поведение не меняется (default=REPO_ROOT).
  • Бамп __init__.py ищет файл в корне worktree (__init__.py), не рекурсивно — если __version__ в подпакете (например src/pkg/__init__.py), тулза его не найдёт. Это намеренно (issue #59 контракт: __init__.py в корне).
  • Предупреждение >30% латиницы — console.warn, не блокирует (технические термины ffmpeg, PyInstaller допустимы).
  • node_modules/ и .opencode/draw-image/templates/*.svg в untracked — не коммитятся (вне scope).

Pending

  • Экстрактор в create_release.py (video_uniq, voice_assistant) — отдельные issue.
  • Удаление дубликата скилла release из arena-models — отдельный issue.
  • Пермишены в opencode.json (create_changelog: true для general) — опционально, тулза авто-обнаруживается без явного пермишена.

Closes #59

Closes #59

## Что сделано Добавлен детерминированный инструмент `create-changelog` (`.opencode/tools/create-changelog.ts`) для валидации и записи CHANGELOG с бампом `pyproject.toml` и `__init__.__version__`. Скилл `release` переведён на использование тулзы вместо ручного bash, возвращён потерянный Шаг 3.5. - **`create-changelog.ts`**: валидация версии (`vX.Y.Z`), кириллицы, одной строки, ≤200 символов, запрещённых паттернов (`(PR#N)`, `Closes #N`, `**Category**:`). Действие: переименование `## [Unreleased]` → `## [X.Y.Z] - YYYY-MM-DD`, новый пустой `## [Unreleased]` сверху, секции `### Добавлено/Изменено/Исправлено/Удалено`, бамп `pyproject.toml` (`version = "X.Y.Z"`) и `__init__.py` (`__version__`) при наличии файлов. - **`release/SKILL.md`**: Шаг 3 вызывает тулзу; добавлен Шаг 3.5 (бамп pyproject + `__init__` — теперь делает тулза автоматически); убрано правило "НЕ обновляй pyproject.toml version"; описан стандарт записей и цикл валидации (тулза вернула ошибки → агент исправляет → повтор). - **`tests/_ts_loader.mjs`**: добавлен env var `WORKTREE_STUB` для переопределения `context.worktree` в `exec_stub_json`/`exec_real` режимах — файловые тулзы (create-changelog) могут писать в tmp dir, не затирая CHANGELOG репо. Обратно-совместимо (default=REPO_ROOT). - **`tests/test_create_changelog_tool.py`**: 13 тестов — happy path (CHANGELOG + pyproject + `__init__`), invalid version (без v), no Cyrillic, multi-line entry, >200 chars, запрещённые паттерны `(PR#4)`/`Closes #1`/`**Audio**:`, all sections empty, missing CHANGELOG (создаётся с нуля), missing pyproject (пропуск), missing `__init__` (пропуск). ## Почему Процесс релизов создавал мусорные release notes: скрипт `create_release.py` пихал весь CHANGELOG.md (267 строк, 29 КБ) в body релиза. Записи — смесь английского и русского, абзацы вместо однострочников, мусор `(PR#N)`, `**Category**:`. Шаг 3.5 (бамп pyproject + `__init__`) был потерян (правили в `~/.config/opencode/` bind-mount, а не в workspace-клоне). Детерминированная тулза с валидацией устраняет эти проблемы: одинаковые args → одинаковый результат, агент не может вставить мусорную запись (fail-fast с RULES). ## Watch out - Перезапуск opencode обязателен — тулза авто-обнаруживается из `.opencode/tools/` только при старте. - `WORKTREE_STUB` env var в `_ts_loader.mjs` меняет `context.worktree` для всех тулз в `exec_stub_json`/`exec_real` — если существующие тесты не задают его, поведение не меняется (default=REPO_ROOT). - Бамп `__init__.py` ищет файл в корне worktree (`__init__.py`), не рекурсивно — если `__version__` в подпакете (например `src/pkg/__init__.py`), тулза его не найдёт. Это намеренно (issue #59 контракт: `__init__.py` в корне). - Предупреждение `>30% латиницы` — `console.warn`, не блокирует (технические термины `ffmpeg`, `PyInstaller` допустимы). - `node_modules/` и `.opencode/draw-image/templates/*.svg` в untracked — не коммитятся (вне scope). ## Pending - Экстрактор в `create_release.py` (video_uniq, voice_assistant) — отдельные issue. - Удаление дубликата скилла `release` из arena-models — отдельный issue. - Пермишены в `opencode.json` (`create_changelog: true` для `general`) — опционально, тулза авто-обнаруживается без явного пермишена. Closes #59 Closes #59
test(tools): add create-changelog tool tests
All checks were successful
CI (always) / bootstrap (pull_request) Successful in 6s
CI / bootstrap (pull_request) Successful in 9s
CI / lint (pull_request) Successful in 30s
CI / typecheck (pull_request) Successful in 30s
CI / complexity (pull_request) Successful in 30s
CI / test (3.13) (pull_request) Successful in 1m42s
d6cdf34b5e
feat(release): document platform marking in release skill
Some checks failed
CI (always) / bootstrap (pull_request) Successful in 6s
CI / bootstrap (pull_request) Successful in 8s
CI / typecheck (pull_request) Successful in 29s
CI / lint (pull_request) Failing after 29s
CI / complexity (pull_request) Successful in 30s
CI / test (3.13) (pull_request) Successful in 1m43s
51fc0f2ec3
Author
Owner

Code Review Summary

Добавлен детерминированный инструмент create-changelog (192 строки) с валидацией Russian-only записей, бампом pyproject.toml + __init__.__version__, и marking платформы. Скилл release переведён на тулзу, возвращён потерянный Шаг 3.5. 19 тестов (включая platform cases) проходят. Качество высокое, соответствует паттерну create-issue.ts/create-pr.ts.

Positives

  • create-changelog.ts — чистая структура: константы извлечены (VERSION_REGEX, MAX_ENTRY_LEN, VALID_PLATFORMS, SECTION_MAP), функции <30 строк (latinRatio, validateEntries, buildVersionBlock, todayDate), нет any-типов, нет dead code. Валидация fail-fast с RULES — агент не может вставить мусорную запись.
  • Соответствие паттерну create-issue.ts/create-pr.ts — тот же стиль: RULES const, валидация в начале execute(), возврат ❌ ... \n\n${RULES} при ошибке, context.worktree для cwd. Консистентность с существующими тулзами — отличная.
  • release/SKILL.md — Шаг 3 переведён на тулзу, Шаг 3.5 (бамп pyproject + __init__) возвращён и описан как автоматический, "НЕ обновляй pyproject.toml version" убран из Safety rules (было противоречие с Шагом 3.5). Платформа описана с правилами выбора (Windows-ONLY / кроссплатформа / конфиг-репо / omit). Цикл валидации задокументирован.
  • tests/test_create_changelog_tool.py (378 строк, 19 тестов) — покрывает happy path (CHANGELOG + pyproject + __init__), все 5 валидаций (version без v, no Cyrillic, multi-line, >200 chars, 3 forbidden patterns), all-sections-empty, missing CHANGELOG (создание с нуля), missing pyproject/__init__ (пропуск), 5 platform cases (single/multi/macos/invalid/omitted/empty). Тесты детерминированы (tmp dir via WORKTREE_STUB), не зависят от порядка.
  • _ts_loader.mjs — WORKTREE_STUB env var обратно-совместим (default=REPO_ROOT), позволяет file-writing тулзам писать в tmp dir. Изменение минимальное (13 строк diff), не ломает существующие тесты.
  • Cross-file impact — rg по репо показывает: новый tool не имеет readers кроме release/SKILL.md (обновлён в этом же PR = paired update). Oracle-скрипты (pipeline-status.py, project-status.py, spec-status.py) не парсят CHANGELOG. Нет breakage risk.
  • PR body — 4 heading'а (## Что сделано, ## Почему, ## Watch out, ## Pending) заполнены осмысленно. Watch out содержит 5 конкретных предупреждений (перезапуск opencode, WORKTREE_STUB, __init__.py в корне, latin warn, untracked files). Pending перечисляет 3 отложенных issue.

Suggestions (info, not blocking)

  • create-changelog.ts:171 [robustness] pyproject.toml version regex /^version = ".*"$/m требует двойные кавычки. Если проект использует одинарные (version = '0.1.0'), бамп молча пропустится. __init__.py regex (line 181) уже обрабатывает оба варианта (["']). Для консистентности можно унифицировать: /^version\s*=\s*["'].*["']/m. Не критично — hatchling и PEP 621 рекомендуют двойные кавычки, и все репо slaid098 используют version = "...".
  • create-changelog.ts:160 [edge case] unreleasedRe = /^## \[Unreleased\]\s*$/m — если CHANGELOG имеет ## [Unreleased] с trailing content в той же строке (например ## [Unreleased] — TBD), regex не совпадёт → fallback на создание нового header'а поверх. Тесты покрывают стандартный случай (## [Unreleased]\n). Acceptable — Keep a Changelog формат не допускает trailing content.
  • tests/test_create_changelog_tool.py [docs] PR body говорит "13 тестов", фактически 19 (5 platform tests добавлены позже коммитом 78e4290). Minor — body писалось до platform feature. Не блокирующее.
  • create-changelog.ts:12 [style] VALID_PLATFORMS: string[] вместо Set<string> — documented в PR body как workaround для TS-лоадера. Acceptable, не баг.

Verdict: APPROVE

## Code Review Summary Добавлен детерминированный инструмент `create-changelog` (192 строки) с валидацией Russian-only записей, бампом `pyproject.toml` + `__init__.__version__`, и marking платформы. Скилл `release` переведён на тулзу, возвращён потерянный Шаг 3.5. 19 тестов (включая platform cases) проходят. Качество высокое, соответствует паттерну `create-issue.ts`/`create-pr.ts`. ### Positives - **create-changelog.ts** — чистая структура: константы извлечены (`VERSION_REGEX`, `MAX_ENTRY_LEN`, `VALID_PLATFORMS`, `SECTION_MAP`), функции <30 строк (`latinRatio`, `validateEntries`, `buildVersionBlock`, `todayDate`), нет `any`-типов, нет dead code. Валидация fail-fast с RULES — агент не может вставить мусорную запись. - **Соответствие паттерну create-issue.ts/create-pr.ts** — тот же стиль: `RULES` const, валидация в начале `execute()`, возврат `❌ ... \n\n${RULES}` при ошибке, `context.worktree` для cwd. Консистентность с существующими тулзами — отличная. - **release/SKILL.md** — Шаг 3 переведён на тулзу, Шаг 3.5 (бамп pyproject + `__init__`) возвращён и описан как автоматический, "НЕ обновляй pyproject.toml version" убран из Safety rules (было противоречие с Шагом 3.5). Платформа описана с правилами выбора (Windows-ONLY / кроссплатформа / конфиг-репо / omit). Цикл валидации задокументирован. - **tests/test_create_changelog_tool.py** (378 строк, 19 тестов) — покрывает happy path (CHANGELOG + pyproject + `__init__`), все 5 валидаций (version без v, no Cyrillic, multi-line, >200 chars, 3 forbidden patterns), all-sections-empty, missing CHANGELOG (создание с нуля), missing pyproject/`__init__` (пропуск), 5 platform cases (single/multi/macos/invalid/omitted/empty). Тесты детерминированы (tmp dir via `WORKTREE_STUB`), не зависят от порядка. - **_ts_loader.mjs** — `WORKTREE_STUB` env var обратно-совместим (default=REPO_ROOT), позволяет file-writing тулзам писать в tmp dir. Изменение минимальное (13 строк diff), не ломает существующие тесты. - **Cross-file impact** — `rg` по репо показывает: новый tool не имеет readers кроме `release/SKILL.md` (обновлён в этом же PR = paired update). Oracle-скрипты (`pipeline-status.py`, `project-status.py`, `spec-status.py`) не парсят CHANGELOG. Нет breakage risk. - **PR body** — 4 heading'а (`## Что сделано`, `## Почему`, `## Watch out`, `## Pending`) заполнены осмысленно. Watch out содержит 5 конкретных предупреждений (перезапуск opencode, WORKTREE_STUB, `__init__.py` в корне, latin warn, untracked files). Pending перечисляет 3 отложенных issue. ### Suggestions (info, not blocking) - **create-changelog.ts:171** [robustness] `pyproject.toml` version regex `/^version = ".*"$/m` требует двойные кавычки. Если проект использует одинарные (`version = '0.1.0'`), бамп молча пропустится. `__init__.py` regex (line 181) уже обрабатывает оба варианта (`["']`). Для консистентности можно унифицировать: `/^version\s*=\s*["'].*["']/m`. Не критично — hatchling и PEP 621 рекомендуют двойные кавычки, и все репо slaid098 используют `version = "..."`. - **create-changelog.ts:160** [edge case] `unreleasedRe = /^## \[Unreleased\]\s*$/m` — если CHANGELOG имеет `## [Unreleased]` с trailing content в той же строке (например `## [Unreleased] — TBD`), regex не совпадёт → fallback на создание нового header'а поверх. Тесты покрывают стандартный случай (`## [Unreleased]\n`). Acceptable — Keep a Changelog формат не допускает trailing content. - **tests/test_create_changelog_tool.py** [docs] PR body говорит "13 тестов", фактически 19 (5 platform tests добавлены позже коммитом `78e4290`). Minor — body писалось до platform feature. Не блокирующее. - **create-changelog.ts:12** [style] `VALID_PLATFORMS: string[]` вместо `Set<string>` — documented в PR body как workaround для TS-лоадера. Acceptable, не баг. ### Verdict: APPROVE
slaid098 deleted branch feat/release/create-changelog-tool 2026-08-12 15:18:05 +03:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
slaid098/opencode-config!60
No description provided.