diff --git a/docs/superpowers/2026-08-03-ZAPISKA-sosednei-smene-vykat.md b/docs/superpowers/2026-08-03-ZAPISKA-sosednei-smene-vykat.md new file mode 100644 index 00000000..527b1c6e --- /dev/null +++ b/docs/superpowers/2026-08-03-ZAPISKA-sosednei-smene-vykat.md @@ -0,0 +1,174 @@ +# ЗАПИСКА соседней смене (телеграм-реклама) — чтобы мы больше не затирали друг друга + +**От:** смены СМС-модуля, ночь на 03.08.2026, после выката на боевой. +**Кому:** сессии, работающей в `.claude/worktrees/tg-zagolovok` (ветка `fix/tg-zagolovok-obyavleniya`). + +Читать целиком до первой выкладки на боевой. Ниже — что случилось, что уже сделано за вас +и как работать дальше, чтобы никто ничего не потерял. + +--- + +## 1. Коротко: что произошло этой ночью + +Мы дважды за два часа затёрли работу друг друга на боевом. + +1. **~02:15.** Я выкатывал СМС-модуль. Перед выкладкой сверил слепками, что лежит на бою, и + увидел там **вашу** телеграм-рекламу, которой не было ни в `main`, ни в моей ветке. Если бы + я выложил своё как есть — ваша реклама на бою откатилась бы на неделю назад. Поэтому я + **сперва свёл вашу ветку к себе** и только потом выкатывал. Ваша работа не пострадала: + после выката слепки `config/client_tg.php` и `TelegramTariffService.php` на бою остались + теми же, что были до него. + +2. **~01:55–02:00** (по времени вашей записи `f2ac3f4c7`). Вы выложили на боевой свою правку + поверх моей. Ваша выкладка заменила каталог сборки экранов целиком, а СМС-модуля в вашей + ветке нет — **экраны клиентских СМС с боя исчезли**. + + 🔴 Коварство в том, что снаружи всё выглядело здоровым: портал отвечал 200, журнал был + чист, PHP-код модуля, 46 маршрутов и 10 таблиц остались на месте. Не работал только сам + экран у клиента. **Такую поломку не видно ни по кодам ответа, ни по журналу.** + +Это не претензия — ровно то же самое чуть не сделал я. Причина общая, и она в п. 3. + +--- + +## 2. Что уже сделано — переделывать не надо + +- ✅ **Ваша запись `f2ac3f4c7` сведена в рабочую ветку** `feat/prospects-manual-testing-kp` + (слияние `4a439ebb`). Вся ваша работа, все 34 записи, теперь внутри неё. +- ✅ **Боевой починен:** пересобраны экраны из объединённого дерева и выложены заново. + Сейчас на бою работают **и ваша телеграм-реклама, и СМС-модуль**. +- ✅ **Проверено побайтово:** все **2626** файлов кода на бою совпадают с рабочей веткой, + расхождений — ноль. В сборке присутствуют и `AdvertisingTelegramView`, и `AdvertisingSmsView` + с `AdminSmsView`. +- ✅ Прогоны после сведения: экраны **251 файл / 2033 зелёных / 0 падений**, PHP по обоим + модулям **714 / 714**, статанализ **0**, проверка типов **0**. + +🪤 **Одна ваша правка изменена осознанно, скажите, если не согласны.** Мы оба завели в карте +значков имя `mdi-file-download-outline`, вышел дубль ключа. Оставлена одна запись — `FileDown` +вместо простой стрелки `Download`: в вашем комментарии сказано, что точного значка в Lucide +нет, но он есть. Запись обслуживает обе кнопки, в комментарии это записано. + +--- + +## 3. 🔴 Почему мы затираем друг друга — корень, а не симптом + +**Выкладка на боевой всегда несёт ВЕСЬ интерфейс одним куском.** Сборка `public/build` делается +из всего дерева ветки: выложить «только свои экраны» физически невозможно. Что бы вы ни правили, +в сборку попадут ВАШИ версии всех остальных экранов — включая те, которых в вашей ветке +вообще нет (их просто не будет). + +То же и с кодом: посылка распаковывается поверх, и общие файлы (`vuetify.ts`, `api/*.ts`, +`routes/*`, `phpstan-baseline.neon`) заменяются вашими версиями. + +Отсюда правило: **выкатывать можно только из дерева, в котором есть ОБЕ работы.** + +🪤 Ветка на сервере `gitea` — **не источник правды**. Серверная копия рабочей ветки отстаёт +на 206 записей. Брать оттуда нельзя. + +🟢 Зато репозиторий у нас **общий**: вы работаете в `.claude/worktrees/tg-zagolovok` того же +репозитория, что и я. Значит забрать чужую работу можно **локально, без всякой отправки на +сервер**. + +--- + +## 4. Порядок работы — выполнять по шагам + +### Перед тем как что-то менять + +```bash +git fetch . feat/prospects-manual-testing-kp # не обязательно: репозиторий общий +git log --oneline HEAD..feat/prospects-manual-testing-kp | head # что появилось у соседей +``` + +### Перед ЛЮБОЙ выкладкой на боевой — обязательно + +1. **Забрать чужую работу к себе:** + + ```bash + git merge feat/prospects-manual-testing-kp + ``` + + 🪤 Если мешает `docs/observer/STATUS.md` — это служебный файл наблюдателя, он сам себя + переписывает: `git stash push -- docs/observer/STATUS.md`, свести, потом решить. + 🪤 Склейка в `app/phpstan-baseline.neon` почти гарантирована. **Брать сторону, где записей + МЕНЬШЕ** — заметание туда возвращать нельзя, после сведения `composer stan` обязан дать **0**. + 🪤 Проверить дубли ключей в карте значков: + `grep -o "^ 'mdi-[a-z0-9-]*':" app/resources/js/plugins/vuetify.ts | sort | uniq -d` + +2. **Прогнать проверки** (обязательно, сведение ломает неожиданное): + + ```bash + composer stan # обязан дать 0. Звать именно так, не голый phpstan + npm run test:vue + DB_DATABASE=liderra_testing_prospects php artisan test tests/Feature/ClientTg tests/Feature/ClientSms + ``` + +3. **Пересобрать интерфейс** из объединённого дерева: `npm run build`. + Проверить, что в сборке есть ОБА модуля: + + ```bash + ls app/public/build/assets/ | grep -icE "AdvertisingSmsView|AdminSmsView" # ждём 4 + grep -c "AdvertisingTelegramView" app/public/build/manifest.json # ждём > 0 + ``` + +4. **Выложить** и сразу **сверить бой с веткой побайтово** (см. §5). + +### После выкладки — сверка обязательна + +Без неё поломка вида «экран пропал» не видна: портал отвечает 200, журнал чист. + +--- + +## 5. Готовая команда сверки боя с веткой + +На боевом сервере есть `git`, поэтому считаем тот же отпечаток, что считает сам git: + +```bash +git ls-tree -r HEAD --name-only -- app | ssh liderra-prod 'cd /var/www/liderra && cat > /tmp/sp.txt + && while IFS= read -r p; do if [ -f "$p" ]; then printf "%s %s\n" "$(git hash-object "$p")" "$p"; + else printf "NETFAYLA %s\n" "$p"; fi; done < /tmp/sp.txt' | sort > /tmp/boy.txt +git ls-tree -r HEAD -- app | awk '{print $3" "$4}' | sort > /tmp/vetka.txt +comm -3 /tmp/vetka.txt /tmp/boy.txt | awk '{print $NF}' | sort -u +``` + +Пусто — значит бой и ветка совпадают байт в байт. Что-то есть — разбираться ДО того, как +уходить со смены. + +🪤 **Папку `db/` так сверять нельзя в лоб.** У `app/**` в `.gitattributes` задано +`text=auto eol=lf`, у `db/**` правила нет, и `git archive` при `core.autocrlf=true` кладёт их +на боевой с виндовыми переводами строк. Отпечатки разойдутся, содержимое одинаковое — +сверять через `tr -d '\r'`. + +🪤 **Файлы «есть на бою, нет в ветке» — обычно мёртвые хвосты**, а не чужая потеря: распаковка +архива ничего не удаляет. На 03.08 их было 26 — 17 копий `.bak-*` и 9 файлов, удалённых из +кода осознанно. Проверять `git log --all -- <файл>`: git знает — хвост; не знает — чья-то +работа мимо git, и вот её терять нельзя. + +--- + +## 6. 🔴 Что на боевом трогать нельзя без разговора + +- **`client_sms_settings.allowed_operators = ["mts"]`** — поставлено 03.08 по решению владельца. + Имя отправителя `liderra.ru` подключено у МТС только на одного оператора; без ограничения + клиент платил бы за сообщения, которые не дойдут. Снимать — только когда МТС подключит имя + на остальных операторов. +- **`.env` боевого** — там боевые ключи, в посылку он не попадает и попасть не должен. +- **Роль миграций.** Штатная `crm_app_user` **не может создавать таблицы**. Миграции — только + под `crm_migrator`, пароль из Lockbox по **ID `e6qeooj45vqtn2fju58r`** (имя + `connection-a59ccntnhhik6s16918i` в `--id` молча отдаёт пустоту). +- 🪤 **Права каталога кэша после распаковки.** Если распаковывали от root — `bootstrap/cache` + становится владением root, и `artisan config:clear` от `www-data` **молча не срабатывает**: + старый кэш продолжает держать прежние настройки. Лечение — сразу после распаковки + `chown -R ubuntu:www-data storage bootstrap/cache` и удалить файлы кэша руками. + Датчик: спросить у базы `select current_user` **тем же путём**, каким пойдут миграции. + +--- + +## 7. Если проще — договоримся о простом правиле + +Идеально, если выкатывает **одна смена за раз** и обязательно из дерева с обеими работами. +Если так не выходит — минимум: **перед выкладкой `git merge` чужой ветки, после выкладки +сверка из §5.** Этого достаточно, чтобы ночная история не повторилась. + +Детали и полный протокол выката — `ПИЛОТ.md`, запись «03.08.2026 (ночь)»; +правило выката — `docs/superpowers/2026-08-02-PROMT-podgotovka-k-produ-9.md`, §5-бис.