almdev Технический блог

Двенадцать проектов, один способ работы
Возврат к проекту через полгода стоил двадцати минут на вспоминание. Теперь — двух.

Что унифицировано между репозиториями: имена сервисов, раскладка .local, набор скиллов, словарь агентов. Что осталось разным и почему это правильно. Цена унификации на двух проектах, которые пришлось подгонять под общий формат.

Подкатегория: Воркфлоу

Чтение
4 мин
Технологии / версии
Docker · Воркфлоу · Скиллы · Subagents
Серия
Цикл «Воркфлоу» · часть 5 из 5
11 авг 2026 · 4 мин · 2 просмотра · AI
Одинаковая раскладка окружения в тринадцати репозиториях
Воркфлоу 08/2026

Возвращаюсь к проекту, которого не касался полгода. Первые двадцать минут уходят не на задачу, а на вспоминание: где тут файл композиции, как называется контейнер, чем гоняются тесты, есть ли миграции.

Двадцать минут на проект, дюжина проектов, несколько возвратов в год. Это не мелочь, это рабочая неделя.

Что унифицировано

Началось всё с окружения, потому что там разброд заметнее всего.

Раскладка локального окружения. В каждом репозитории каталог .local/ с одинаковым содержимым: файл композиции, Makefile, каталог логов.

.local/
├── docker-compose.yml
├── Makefile
└── logs/

Имена сервисов. Один шаблон на все проекты:

container_name: ${PROJECT_NAME}_webserver
container_name: ${PROJECT_NAME}_db
container_name: ${PROJECT_NAME}_redis
container_name: ${PROJECT_NAME}_worker
container_name: ${PROJECT_NAME}_scheduler
container_name: ${PROJECT_NAME}_nginx

Мелочь, которая экономит больше всего. Мне не надо помнить, как называется веб-сервер в конкретном проекте: он всегда <проект>_webserver.

Имена целей. up, down, ps, php-bash — одинаковые во всех Makefile. Дальше идут проектные цели, и они разные, но базовые четыре есть везде.

Скрипты жизненного цикла. install.sh, update.sh, deploy.sh в каталоге scripts/. Общие функции вынесены в lib.sh, который два скрипта подключают.

Файлы контекста и пакет. CLAUDE.md, AGENTS.md, .ai/skills/, .ai/agents/ — одинаковая раскладка в тринадцати репозиториях.

Общий словарь

Отдельная часть унификации, которая работает не на инструменты, а на голову: одинаковые имена ролей на разных стеках.

Laravel-проекты      Symfony-проекты
backend-filament  ←→ backend-symfony
blade-ui          ←→ frontend-twig
qa-runner            qa-runner
code-reviewer        code-reviewer
flow-orchestrator    flow-orchestrator

Пишущие агенты называются по стеку, потому что стек — часть их сути. Проверяющие и разведка называются одинаково везде, потому что их работа от стека не зависит.

Польза от словаря простая: фраза «отдай ревьюеру» или «позови разведку» работает во всех проектах и не требует вспоминать местное название. То же со скиллами: code-review, repo-discovery, visual-qa, a11y-check, developer есть везде под этими именами.

Что осталось разным

Унификация не самоцель, и половину различий я защищаю.

Стек. Два проекта на Symfony, одиннадцать на Laravel. Разные фреймворки означают разные конвенции, разные слои, разные способы описывать миграции. Выравнивать это было бы вредительством.

Доменные скиллы. Каталог хостингов, конвейер фотографий, каталог решений, публикация статей — по одному на проект и ни одного общего. Это ровно та часть, где лежит ценность, и она по определению не унифицируется.

Сборка фронта. В блоге Vite и сборка внутри контейнера. В фотопроектах сборка гоняется локально, потому что так быстрее на больших наборах ассетов. Это записано в файле контекста каждого проекта, и попытка привести к одному виду ломала бы удобство.

Способ хранения контента. Где-то контент в сидерах и пересоздаётся при развёртывании, где-то правится в админке и живёт в базе. Разница фундаментальная, из неё следуют разные процедуры.

Признак, по которому решаю: если различие следует из природы проекта — оставляю. Если оно следует из того, что я делал эти проекты в разные месяцы, — выравниваю.

Цена

Два проекта пришлось подгонять под общий формат, и это был не самый приятный вечер.

В одном из них раскладка окружения была своя и, честно говоря, удобнее: файл композиции лежал в корне, цели в Makefile были короче, логи писались туда, куда мне было привычно смотреть. Я это сломал ради единообразия.

Правильно ли — до сих пор не уверен. Аргумент за: теперь при переключении между проектами не надо помнить исключение. Аргумент против: я ухудшил один проект ради удобства переключения, которое случается раз в месяц.

Вторая часть цены — постоянная. Унификация требует поддержки: появляется новая общая практика, и её надо разнести по тринадцати репозиториям. Разношу руками, и это узкое место, о котором ниже.

Как переносится улучшение

Никак. Точнее, руками.

Улучшил скилл ревью в блоге — в двенадцати остальных он старый. Скрипт синхронизации у меня есть только для общего модуля редактора, где файлы обязаны совпадать байт в байт. Для скиллов и файлов контекста ничего нет.

Работает это так: раз в квартал я обхожу репозитории и смотрю даты правок в фронтматтере. Вижу, что где отстало, переношу то, что считаю нужным. Занимает вечер, делается нерегулярно.

Почему не автоматизировал: правок ядра у меня было четыре за все эти месяцы, и инфраструктура под них не окупается. Аргумент честный, но подозреваю, что он неполный. Он учитывает мои правки и не учитывает, что в двенадцати проектах лежат скиллы, отставшие ровно настолько, насколько я поленился.

Чего не хватает

Эталона. Репозитория, из которого берётся стартовый набор и с которым сверяются остальные.

Сейчас роль эталона играет «последний проект, где я это делал», и его надо вспоминать. Для общего модуля редактора эталон назначен явно, и там всё в порядке. Для способа работы — не назначен, потому что кандидат должен быть выше стека, а все мои репозитории на конкретном стеке.

Как бы я это сделал: маленький репозиторий с шестёркой скиллов ядра в обезличенном виде, шаблоном AGENTS.md, шаблоном .local/ и скриптом раскладки, который не трогает доменные части. Вечер работы, откладываемый с весны.

Что осталось

Двадцать минут на вспоминание превратились в две. Это единственная метрика, которая меня интересовала, и она достигнута — не за счёт документации, а за счёт того, что вспоминать почти нечего: всё лежит там же, где в соседнем проекте.

Побочный эффект оказался важнее основного. Одинаковая раскладка сделала возможным перенос практик вообще: если бы каждый проект был устроен по-своему, улучшение из одного не переносилось бы в другой даже руками. Так что унификация окупилась не экономией на возвратах, а тем, что тринадцать репозиториев стали одним полем, а не тринадцатью островами.

Серия

Цикл «Воркфлоу»

#docker #workflow #skills #subagents #ekosistema