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

Синхронизация скиллов между проектами
Улучшил скилл в одном репозитории — в двенадцати остальных он старый.

Три стратегии для общих файлов: копирование руками, скрипт синхронизации, общий репозиторий. Что я выбрал для shared-модуля, почему для скиллов до сих пор нет ничего и какие части набора расходятся первыми.

Подкатегория: Скиллы

Чтение
5 мин
Технологии / версии
Coding agent · Laravel · Скиллы · Экосистема
Серия
Цикл «Скиллы» · часть 6 из 6
25 авг 2026 · 5 мин · 2 просмотра · AI
Один эталонный лист и его копии, разложенные по проектам
Скиллы 08/2026

Правлю скилл про ревью в блоге, добавляю строку про экранирование пользовательского HTML. Хорошая строка, выстраданная. В двенадцати остальных репозиториях её нет и не будет, пока я не открою каждый.

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

Три стратегии

Копирование руками. Файл живёт в каждом репозитории отдельно. Правка переносится, когда вспомнишь. Стоимость нулевая на старте, растёт линейно с числом проектов.

Скрипт синхронизации. Один репозиторий назначается источником правды, скрипт раскладывает файлы по остальным. Нужна дисциплина: правки делаются только в источнике.

Общий репозиторий. Скиллы живут отдельным пакетом, проекты подключают его подмодулем или зависимостью. Обновление — одна команда.

Про третий вариант пишут чаще всего, и на бумаге он выигрывает. У меня его нет, и это осознанно.

Почему не общий репозиторий

Три причины, по убыванию веса.

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

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

Третья, главная: правки ядра у меня редкие. С весны я поправил общие скиллы раза четыре. Инфраструктура ради четырёх правок за полгода не окупается.

Так что копирование руками — это не лень, а расчёт. Но с оговоркой, о которой ниже.

Где скрипт всё-таки понадобился

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

scripts/sync-almcreate.sh --dry-run   # показать, что изменится
scripts/sync-almcreate.sh --check     # ненулевой код возврата при расхождении
scripts/sync-almcreate.sh             # разложить по проектам

Источник правды — блог, приёмники — четыре соседних проекта. Двести восемьдесят пять строк на bash, из которых половина — аккуратное копирование с проверками.

Почему для кода скрипт нужен, а для скиллов нет. Код обязан совпадать байт в байт: плагин редактора, разъехавшийся между проектами, ломает вёрстку статей по-разному в каждом. Скилл, разъехавшийся между проектами, просто перестаёт быть общим — неприятно, но не сломано.

Что копируется целиком, а что не трогается

Устройство скрипта я подглядел у себя же и потом повторил в других местах.

копируется целиком:  ассеты плагина, стили, редактор изображений
копируется, если есть приёмник:  контроллеры, модели, страницы админки
не трогается:  маршруты, конфигурация, сидеры, всё, что специфично

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

Режим --check появился позже основного и оказался полезнее. Он ничего не пишет, только сравнивает и возвращает ненулевой код при расхождении. Я его гоняю руками раз в пару месяцев и вижу, где приёмник отстал.

Что расходится первым

По наблюдениям за эти месяцы порядок стабильный.

Команды. Меняется имя контейнера, версия PHP, форма вызова консоли — и скилл в отставшем проекте начинает советовать команду, которая не работает. Самая частая и самая заметная поломка.

Пути. Переехал каталог, переименовалась папка ресурсов. Ломается тише: ссылка ведёт в никуда, и это замечают не сразу.

Запреты. Новый запрет появляется после происшествия в одном проекте. В остальные не переносится, потому что там происшествия не было. Формально нормально, фактически — те же грабли ждут в двенадцати местах.

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

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

Версия и дата как индикатор

Единственное дешёвое, что я внедрил, — отметка в фронтматтере.

---
name: code-review
description: ...
applies_to: [claude, cursor, copilot, codex, gemini]
updated: 2026-08-11
source: blog
---

Два поля. updated — когда правился, source — откуда пришёл, если пришёл извне.

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

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

Чего у меня нет

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

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

Что бы я сделал, если бы делал сейчас. Отдельный маленький репозиторий с шестью скиллами ядра в обезличенном виде, без команд и путей. Скрипт, который раскладывает их по проектам и не трогает локальные доменные скиллы. Режим проверки расхождения, как в существующем скрипте.

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

Что осталось

Стратегия «копировать руками, сверять раз в квартал» — не лучшее решение, а сознательно принятое худшее из работающих. На тринадцати проектах она держится. На двадцати развалится.

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

Серия

Цикл «Скиллы»

#coding-agent #laravel #skills #ekosistema #bash