--- title: "project-discipline — четыре правила работы в проекте" type: concept updated: 2026-05-01 --- # project-discipline — четыре правила работы в проекте _2026-05-01._ ## Problem Дисциплина в работе агента в проекте сейчас держится на двух источниках, которые друг с другом не согласованы: 1. **Defaults внешних скиллов** (superpowers и пр.) — например, `superpowers:brainstorming` пишет spec в `docs/superpowers/specs/YYYY-MM-DD--design.md`. Этот путь зашит в скилл и применяется по умолчанию во всех проектах. 2. **Конвенции конкретного проекта** — например, в `claude-skills` spec'и живут в `.wiki/concepts/-design.md`, а не в `docs/superpowers/`. Эта конвенция нигде явно не объявлена; держится только на том, что текущий агент случайно читает `.wiki/CLAUDE.md` до того, как применить дефолт скилла. В `claude-skills` это работает потому что репо плотно дисциплинирован. В **других** проектах того же пользователя такое не работает: агент по умолчанию пишет в `docs/superpowers/`, ветвится на feature-branches, забывает bump'ить версии скиллов, и push'ит без подтверждения. Пользователь хочет четыре правила, действующие во всех его проектах: 1. **Project conventions > skill defaults** — то, что в `CLAUDE.md` / `.wiki/CLAUDE.md` / `.tasks/`, перекрывает defaults любого скилла. 2. **Master-only** — вся работа на главной ветке, никаких feature-branches без явного запроса. 3. **Versioning discipline** — bump version'у на каждом edit'е версионированного артефакта, по semver, в commit-message. 4. **Commit yes, push no** — каждый сеанс стартует с "ask before push"; разрешение на автопуш выдаётся устно в рамках сессии и обнуляется при её завершении. Текущий механизм передачи кросс-проектных правил — строки-триггеры в `CLAUDE.md`, активирующие соответствующие скиллы (`use superpowers`, `use project wiki`, `pull remote before work`, и т.д.). `project-bootstrap` v1.4.0 уже умеет идемпотентный merge новых строк в существующий `CLAUDE.md` (см. [bootstrap-claude-md-merge.md](bootstrap-claude-md-merge.md)). Эта схема естественно расширяется на новый policy-скилл. ## Decision Два артефакта: 1. **Новый policy-скилл `project-discipline`** (`skills/project-discipline/SKILL.md`, v0.1.0) — кодифицирует все четыре правила, активируется триггером `follow project discipline` в `CLAUDE.md`. 2. **`project-bootstrap` v1.4.0 → v1.5.0** (MINOR, добавляет capability) — новая строка в `assets/CLAUDE.md.template` сразу после `pull remote before work`. Идемпотентный merge в Step 5 переносит её в существующие проекты без ручного edit'а. `bootstrap-manifest.md` получает новую строку для `project-discipline`. Этот репо (`claude-skills`) получает trigger'ную строку в свой `CLAUDE.md` как dogfood. ### Почему один скилл, а не четыре Все четыре правила — про дисциплину работы в проекте, единая тема. Разделение на четыре скилла + четыре строки в `CLAUDE.md` (`use master-only`, `confirm before push`, и т.д.) раздуло бы template и плодит файлы. Если позже какое-то правило отделится в самостоятельный универсальный механизм — выделим его тогда. Сейчас YAGNI. ### Почему скилл, а не просто прямые строки в `CLAUDE.md` template Прямые строки (`work on master only`, `commit but don't push`) тоже сработали бы как триггеры — каждая инструкция в `CLAUDE.md` имеет высший приоритет. Но: - **Версионирование** — правила со временем меняются (например, добавится исключение для force-push). Если они зашиты в template и разосланы по N проектам, обновление = ручной edit в каждом. Скилл со своей версией обновляется централизованно. - **Полнота описания** — четыре правила требуют ~150 строк подробной формулировки (что считается push'ем, какие исключения, как выдаётся grant). В `CLAUDE.md` это не помещается; в скилле — нормальный объём. - **Обнаруживаемость** — `Skill` tool listing показывает скилл с описанием. Прямые строки в `CLAUDE.md` агент видит, но не воспринимает как один связанный набор. ## Skill behaviour ### Activation (description field) Trigger conditions: - `CLAUDE.md` содержит строку `follow project discipline` — скилл активируется при старте сессии и применяет все четыре правила к остальной работе. - Пользователь явно ссылается на дисциплину: "use project discipline", "соблюди дисциплину", "проектные правила", "что у меня по правилам?". Скилл сам по себе не выполняет действий и не имеет внешних эффектов; он — policy-документ, читаемый агентом. ### Rule 1 — Project conventions override skill defaults **Текст правила в SKILL.md:** > До применения defaults любого другого скилла (superpowers, frontend-design, mcp-builder, и т.д.), агент читает в этом порядке: > > 1. `CLAUDE.md` в корне проекта; > 2. `.wiki/CLAUDE.md` (если существует); > 3. `.tasks/STATUS.md` (если существует). > > Любой путь, формат, или workflow, явно указанный в этих файлах, **перекрывает дефолт скилла**. > > Конкретные следствия: > > - **Spec'и / design-документы** идут в `.wiki/concepts/-design.md`, **не** в `docs/superpowers/specs/`. > - **Task tracking** — в `.tasks/.md` + `STATUS.md` (формат `using-tasks`), **не** в `docs/superpowers/plans/` или ином inline-формате. > - **Frontmatter, naming-conventions, log-формат** — как описано в `.wiki/CLAUDE.md` проекта. > > Если конвенция не указана явно — применяется дефолт скилла. **Почему:** в `claude-skills` это уже работает (поэтому `pulling-before-work-design.md` лежит в `.wiki/concepts/`, а не в `docs/superpowers/specs/`). Цель правила — перенести эту дисциплину в **другие** проекты пользователя, где она сейчас держится только на удаче. ### Rule 2 — Master-only **Текст правила в SKILL.md:** > Вся работа идёт на главной ветке репозитория — обычно `master`, но если проект использует `main`, скилл считает `main` эквивалентом. > > - Никаких `git checkout -b feature/foo` для соло-работы. > - Sync с remote — `git pull --ff-only` или `git pull --rebase`. **Никаких merge-коммитов** для соло-работы. > - Если задача реально требует изоляции (большой эксперимент, рискованный refactor с возможностью отката, multi-day работа с промежуточными WIP-коммитами) — агент **спрашивает** пользователя: "это требует отдельной ветки, ок?" — и ждёт явного разрешения. Без разрешения — на master. > > При detached HEAD или нахождении на не-главной ветке (например, после `git checkout`) — агент сообщает об этом и спрашивает, нужно ли вернуться на master перед работой. **Почему:** соло-разработка с CI/CD не получает выгоды от feature-branches; PR-workflow это overhead для одного человека. Master-only сводит к нулю vocabulary "merge conflict / rebase onto / rebase interactive" в обычном дне. ### Rule 3 — Versioning discipline **Текст правила в SKILL.md:** > При редактировании любого артефакта с semver-полем агент **bump'ит версию перед коммитом** по правилам: > > - **MAJOR** (X+1.0.0) — ломает контракт. Переименование скилла, удаление триггеров, изменение layout, удаление публичных функций, breaking change в API. > - **MINOR** (X.Y+1.0) — добавляет capability без ломки. Новый триггер, новый опциональный шаг, новая публичная функция. > - **PATCH** (X.Y.Z+1) — wording, clarity, исправление опечаток без изменения поведения. > > Bump указывается в commit-message: `feat(): … [v]` или эквивалент. Точный формат подгоняется под convention'ы проекта (см. Rule 1). > > **Применяется к:** `skills//SKILL.md` (frontmatter `version:`), `package.json` (`"version":`), `pyproject.toml` (`version = `), `Cargo.toml` (`version = `), и любым другим semver-полям. > > **Если артефакт пакуется** в `dist/.skill`, `dist/*.tgz` и т.п. — **rebuild** пакета в том же или следующем коммите. Забытые dist'ы — частая причина деплоя устаревшего бинаря. > > **Первый edit unversioned артефакта**, у которого ВОЗМОЖНО semver-поле (новый скилл без `version:`, новый `package.json` без `"version":`) — агент **добавляет** `version: 0.1.0` (или эквивалент) перед коммитом, не bump'ит существующее. > > **Не применяется к:** артефактам без semver-поля и без потенциала его иметь (concept-страницы wiki, README.md, скрипты shell без публичного интерфейса). **Почему:** в `.wiki/concepts/skill-versioning.md` уже описана semver-схема, но (а) она была scoped только на infra-набор скиллов; (б) дисциплина держалась только на текущем агенте. Правило 3 расширяет её **на все** скиллы в этом репо и на все версионируемые артефакты в любом проекте. **Расширение scope.** Концепт-страница `skill-versioning.md` будет обновлена с пометкой, что после v0.1.0 `project-discipline` требование версионирования действует **на все скиллы**, не только infra-subset. Communication-mode скиллы (caveman, ...) и discovery-скиллы (find-skills, active-platform) тоже получают `version:` поле в frontmatter — это разовый migration, отдельная задача после shipping `project-discipline`. ### Rule 4 — Commit yes, push no (session-scoped) **Текст правила в SKILL.md:** > **Старт каждой сессии:** агент находится в режиме **ask-before-push**. На каждый `git push` он спрашивает: > > > Готов push'нуть в `/` (N коммитов: ). Ок? > > и ждёт явного `yes` / `да` / `push` / эквивалента. Без подтверждения — не push'ит. > > **Выдача grant'а в сессии.** Пользователь говорит: > > - "разреши автопуш" / "allow auto-push" / "автопуш ок" / эквивалент > > — после этого агент push'ит без вопросов до конца сессии или до отзыва. > > **Отзыв grant'а в сессии.** Пользователь говорит: > > - "отзови автопуш" / "revoke auto-push" / "снова спрашивай" / эквивалент > > — агент возвращается в ask-mode. > > **Конец сессии — состояние не сохраняется.** Следующая сессия снова стартует в ask-mode. Это намеренно: grant выдаётся под конкретный текущий контекст (пользователь рядом, осознанно решил что push'ить безопасно), и не должен переживать смену контекста. > > **Исключения — всегда ask, даже с активным grant'ом:** > > - `git push --force` / `--force-with-lease` (перезапись истории); > - `git push origin --delete ` (удаление ветки); > - push не в текущий tracked upstream (`git push other-remote ...`, `git push origin other-branch`); > - push в главную ветку, требующий не-fast-forward (т.е. потребовался бы force). > > Логика: grant выдан под обычный fast-forward push в апстрим; всё остальное — отдельный класс операций, требует отдельного решения. > > **Что считается "push":** только команды семейства `git push`. Локальные коммиты, `git stash push`, и т.п. — не push, grant на них не нужен. **Почему:** пользователь хочет чтобы каждая сессия начиналась с явного "коммить, но не пуш!" — даже если в прошлой сессии всё было разрешено. Это страховка от "вчера агент думал что все ок, сегодня он же думает что всё ок, и заpush'ил то что не должен был". Persistent grant (файл-флаг в проекте) был бы удобнее но менее безопасен — поэтому намеренно отвергнут. ### Out of scope Скилл **не** делает: - **Не модифицирует `CLAUDE.md`** — это работа `project-bootstrap`. Скилл — текстовая policy, не tooling. - **Не enforce'ит правила через hooks / git hooks / pre-commit** — дисциплина агента, не CI. Если пользователь хочет твёрдый enforcement (например, `pre-push` hook, который ломается без явной env-переменной) — это отдельный setup-скилл, не часть `project-discipline`. - **Не управляет `settings.json` permissions** — это `update-config`. Можно представить вариант, в котором `git push` запрещён по умолчанию через `permissions.deny: ["Bash(git push:*)"]`, и Rule 4 его временно ослабляет. Этот вариант **отвергнут** на v0.1.0: пользователь хочет policy-уровень, не tool-уровень. Если правило Rule 4 окажется недостаточным — вернёмся к идее. - **Не проверяет наличие `.wiki/`/`.tasks/`** — это работа `setup-wiki`/`setup-tasks`/`project-bootstrap`. Скилл предполагает что layout уже на месте; если `.wiki/CLAUDE.md` отсутствует — Rule 1 просто не находит конвенций для override'а и работает как пустой fallback. ## Bootstrap integration ### `assets/CLAUDE.md.template` Текущий вид: ```markdown talk like a caveman use superpowers use project wiki use task management system check across all projects pull remote before work we're on Windows ``` После v1.5.0: ```markdown talk like a caveman use superpowers use project wiki use task management system check across all projects pull remote before work follow project discipline we're on Windows ``` `follow project discipline` ставится **после** `pull remote before work` и **до** платформенной строки — потому что: - Pull остаётся первым в logical order'е (сначала подтягиваем код, потом думаем о правилах). - `follow project discipline` логически суммирует все остальные триггеры, должна стоять близко к их концу. - Платформенная строка — мета-конфиг, всегда последняя. ### `project-bootstrap` SKILL.md изменения - Frontmatter: `version: 1.4.0` → `version: 1.5.0`. - Step 5 — добавить параграф commentary о новой строке (по образцу commentary для `pull remote before work`): > The `follow project discipline` line activates the `project-discipline` skill, which codifies four cross-project rules: (1) project CLAUDE.md / .wiki/CLAUDE.md / .tasks/ override skill defaults; (2) all work on master/main, no feature branches; (3) version bump on every edit per semver; (4) commit freely, push only after explicit per-session approval. Install the skill on the host if `project-discipline` is not in `~/.claude/skills/`; otherwise the trigger is silently dead like any other absent skill. - Step 5.5 (manifest) — добавить `project-discipline` в таблицу: ```markdown | Skill | Version | Role | |---|---|---| | `project-bootstrap` | | orchestrator | | `setup-wiki` | | wiki canonical layout | | `setup-tasks` | | tasks canonical layout | | `project-discipline` | | cross-project policy | ``` Манифест читает `version:` из frontmatter `project-discipline/SKILL.md` как для остальных. Если скилл не установлен — `unknown`, как уже принято. ### Idempotent merge — что произойдёт в существующих проектах Step 5 upgrade-mode (см. [bootstrap-claude-md-merge.md](bootstrap-claude-md-merge.md)) на следующем bootstrap: 1. Прочитает существующий `CLAUDE.md`. 2. Не найдёт substring `follow project discipline` в нём. 3. Покажет user'у diff: "Append 1 missing canonical trigger: `follow project discipline`?" 4. По подтверждению — допишет строку в конец. Существующий порядок (например, если `we're on Windows` уже не в конце, а в середине) не пересортировывается — это сделанное решение upgrade-merge'а, чтобы не ломать пользовательские edit'ы. ## Cross-impact | Файл | Изменение | |---|---| | `skills/project-discipline/SKILL.md` | новый, v0.1.0 | | `skills/project-discipline/README.md` | новый | | `skills/project-bootstrap/SKILL.md` | bump 1.4.0→1.5.0; commentary + manifest row | | `skills/project-bootstrap/assets/CLAUDE.md.template` | +1 строка | | `skills/project-bootstrap/README.md` | sync (упомянуть новый триггер) | | `dist/project-bootstrap.skill` | rebuild | | `dist/project-discipline.skill` | новый archive | | `~/.claude/skills/project-discipline/` | install (через `install.sh` или `install.ps1`) | | `CLAUDE.md` (этого репо) | +1 строка `follow project discipline` (dogfood) | | `.wiki/concepts/skill-versioning.md` | заметка о расширении scope (Rule 3 теперь требует version: на ВСЕХ скиллах) | | `.wiki/concepts/project-discipline-design.md` | этот файл | | `.wiki/concepts/bootstrap-manifest.md` | regenerate с новой строкой | | `.wiki/index.md` | +1 концепт-page link | | `.wiki/log.md` | +1 entry `decision \| project-discipline — четыре правила работы в проекте` | | `.tasks/project-discipline-skill.md` | новый task-file | | `.tasks/STATUS.md` | новый 🔴 active block | ## Open questions - **Нужен ли отдельный setup-скилл?** По образцу `setup-context7` / `using-context7`. Сейчас — нет: `project-discipline` ничего не устанавливает, просто policy. Если в будущем добавится tooling-enforcement (git hooks, settings.json overrides) — выделим `setup-project-discipline`. - **Wide vs narrow Rule 3 scope.** Сейчас правило применяется ко **всем** артефактам с semver-полем. Если окажется что в каких-то проектах семвер реально неуместен (например, исследовательский notebook) — добавим explicit opt-out через `.wiki/CLAUDE.md` (`# project-discipline: skip versioning`). - **Migration communication-mode скиллов на `version:`.** Это побочная работа после shipping `project-discipline`. Открывается отдельной задачей в `.tasks/`. - **Отслеживание session-state Rule 4.** В текущей имплементации — чисто conversational ("я помню что разрешил"). Если auto-compaction обрезает раннюю часть сессии где был выдан grant — fallback на ask-mode (безопаснее). Это намеренно: лучше переспросить чем накосячить. ## References - [bootstrap-claude-md-merge.md](bootstrap-claude-md-merge.md) — механизм идемпотентного merge, который перенесёт триггер в существующие проекты. - [pulling-before-work-design.md](pulling-before-work-design.md) — образец policy-скилла + bootstrap-integration, который этот проект мимикрирует. - [skill-versioning.md](skill-versioning.md) — текущая semver-схема, которую Rule 3 расширяет на все скиллы. - [bootstrap-manifest.md](bootstrap-manifest.md) — формат манифеста, в который добавляется новая строка.