# MAST

Method for Agents, Sessions and Tasks — плагин Claude Code, который разворачивает в чужом
проекте наш способ работы: роадмап с пунктами, worktree на пункт, диспетчер, правила с `paths:`,
архив закрытого.

## Куда смотреть

| Документ | Когда читать |
|---|---|
| [ROADMAP.md](ROADMAP.md) | что осталось сделать |
| [docs/roadmap/done/A-1/SPEC.md](docs/roadmap/done/A-1/SPEC.md) | зачем плагин так устроен, ограничения площадки, состав ядра |
| [docs/roadmap/DONE.md](docs/roadmap/DONE.md) | что уже закрыто |
| [TECH_DEBT.md](TECH_DEBT.md) | что оставлено криво и при каком условии чиним |

## Стек

- Markdown — тексты ядра, скиллов и шаблонов, по комплекту на язык в `locales/`.
- Python 3 (только stdlib) — скрипты хуков и сторожа́.
- pytest — сторожа́ в `tests/`.

Из одного репозитория собирается **два плагина**: `plugins/en` → `mast` и `plugins/ru` →
`mast-ru`. Язык — это выбор плагина при установке, а не настройка внутри одного.

## Команды

```bash
git config core.hooksPath .githooks       # один раз после клонирования
pytest                                    # весь набор
python3 hooks/roadmap_lint.py ROADMAP.md  # проверка формата роадмапа
python3 hooks/roadmap_lint.py --ready ROADMAP.md
python3 tools/sync_plugins.py             # разложить код и тексты по plugins/<язык>/
python3 tools/sync_plugins.py --check     # копии отстали от источника? (в pre-commit)
```

`.git/hooks/` не версионируется, поэтому pre-commit едет в `.githooks/` и
подключается этой командой. Не подключил — правку без бампа версии поймает
`tests/test_version_bump.py`, но уже после коммита.

## Инварианты проекта

- **Плагин не трогает чужое.** Ни `~/.claude/CLAUDE.md`, ни `settings.json` пользователя, ни файлы его проекта без подтверждения. Любая правка существующего файла — только через дифф и вопрос.
- **Ядро в `SessionStart` ≤ 8200 символов** при лимите площадки 10 000. Не влезает — секция уезжает в скилл, а не сокращается до непонятности. Уехала — в ядре остаётся правило одной строкой **и имя скилла в том месте, где оно применяется**: ссылка одним списком в конце не работает, агент не знает, когда её открыть.
- **Два языка равноправны.** Правка текста на одном языке без правки на другом не вливается: сторож локалей сверяет состав файлов и дерево заголовков.
- **Пути внутри плагина — через `${CLAUDE_PLUGIN_ROOT}`.** Никаких `$HOME/.claude/...`: у пользователя плагина такого пути нет. Путь из текста скилла или команды резолвится относительно `plugins/<язык>/`, а код и тексты лежат в корне — отсюда `../../`; каждый такой путь проверяет сторож в `tests/test_plugin_manifest.py`.
- **Имя плагина в коде — только из `hooks/plugin_names.py`.** Литерал `mast`/`mast-ru` в хуке расходится с манифестом молча, и пользователь получает ссылку на несуществующую команду или скилл.
- **Числа в «Готово когда» получены замером**, а не переписаны из примера.
- **Плагин самодостаточен, источник один.** Площадка копирует в кэш только содержимое
  `plugins/<язык>/` — проверено живьём на установке из маркетплейса, `../../` из плагина ведёт
  в пустоту. Поэтому код и тексты лежат и внутри плагина, но правятся **только** в корневых
  `hooks/` и `locales/`: копии раскладывает `python3 tools/sync_plugins.py`, а `--check`
  в pre-commit и сторож в тестах не дают закоммитить отставшую копию.
- **Версия растёт вместе с методом и одинакова у обоих плагинов.** Правка `hooks/`,
  `locales/` или `plugins/` без бампа — релиз, которого не получит ни один пользователь:
  Claude Code обновляет плагин с явной версией только при её росте.
- **Новое правило метода — это пол или потолок?** Пол — инвариант, который проверяет guard
  (число в критерии, линт, владение путями). Потолок — «как именно и в каком порядке ходить».
  Потолок в ядро и скиллы не вливается: он устареет ровно тогда, когда модель поумнеет,
  и его придётся выдирать.
