feat(release): create-changelog tool with Russian validation #60
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/release/create-changelog-tool"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Что сделано
Добавлен детерминированный инструмент
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 varWORKTREE_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/tools/только при старте.WORKTREE_STUBenv 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
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
VERSION_REGEX,MAX_ENTRY_LEN,VALID_PLATFORMS,SECTION_MAP), функции <30 строк (latinRatio,validateEntries,buildVersionBlock,todayDate), нетany-типов, нет dead code. Валидация fail-fast с RULES — агент не может вставить мусорную запись.RULESconst, валидация в началеexecute(), возврат❌ ... \n\n${RULES}при ошибке,context.worktreeдля cwd. Консистентность с существующими тулзами — отличная.__init__) возвращён и описан как автоматический, "НЕ обновляй pyproject.toml version" убран из Safety rules (было противоречие с Шагом 3.5). Платформа описана с правилами выбора (Windows-ONLY / кроссплатформа / конфиг-репо / omit). Цикл валидации задокументирован.__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 viaWORKTREE_STUB), не зависят от порядка.WORKTREE_STUBenv var обратно-совместим (default=REPO_ROOT), позволяет file-writing тулзам писать в tmp dir. Изменение минимальное (13 строк diff), не ломает существующие тесты.rgпо репо показывает: новый tool не имеет readers кромеrelease/SKILL.md(обновлён в этом же PR = paired update). Oracle-скрипты (pipeline-status.py,project-status.py,spec-status.py) не парсят CHANGELOG. Нет breakage risk.## Что сделано,## Почему,## Watch out,## Pending) заполнены осмысленно. Watch out содержит 5 конкретных предупреждений (перезапуск opencode, WORKTREE_STUB,__init__.pyв корне, latin warn, untracked files). Pending перечисляет 3 отложенных issue.Suggestions (info, not blocking)
pyproject.tomlversion regex/^version = ".*"$/mтребует двойные кавычки. Если проект использует одинарные (version = '0.1.0'), бамп молча пропустится.__init__.pyregex (line 181) уже обрабатывает оба варианта (["']). Для консистентности можно унифицировать:/^version\s*=\s*["'].*["']/m. Не критично — hatchling и PEP 621 рекомендуют двойные кавычки, и все репо slaid098 используютversion = "...".unreleasedRe = /^## \[Unreleased\]\s*$/m— если CHANGELOG имеет## [Unreleased]с trailing content в той же строке (например## [Unreleased] — TBD), regex не совпадёт → fallback на создание нового header'а поверх. Тесты покрывают стандартный случай (## [Unreleased]\n). Acceptable — Keep a Changelog формат не допускает trailing content.78e4290). Minor — body писалось до platform feature. Не блокирующее.VALID_PLATFORMS: string[]вместоSet<string>— documented в PR body как workaround для TS-лоадера. Acceptable, не баг.Verdict: APPROVE