Тема
Релиз 2026-08-18 — ВЫКАЧЕН (записка закрыта)
Выкат состоялся 2026-08-18 14:38Z. Все четыре артефакта на коммите 990fbc21, dirty=false, расхождений нет. Схема config.db — 4, строка выбрана по активации (weather-harvester), /api/strategies отвечает 200. Набор отката: .deploy/backups/20260818T143331Z-990fbc2149a2.
Разбор того, как выкат сорвался с первого раза, — в памяти reference_validate_config_migrates_db_2026-08-18.
Состояние на 14:30 — расхождение УСТРАНЕНО
Ветка feat/telemetry-metrics-sinks слита в main. Проверено:
- боевой коммит
20b9d937теперь предокmain— то есть выкат больше ничего не откатывает, он только двигает вперёд; mainопережает бой на 69 коммитов;- не слитых веток не осталось (
git branch --no-merged mainпуст), включаяfeat/scanner-loop-lag-p99— она вошла через ту же ветку; - полные ворота
scripts/gate.sh— 11/11 при нагрузке 1.5 на 14 ядрах, то есть прогон достоверный, а не «повезло на тихой машине».
Как слияние прошло
Перемотке мешали три коммита в main, сделанных перед ней. Один из них (be3b7cab) вносил УСТАРЕВШИЙ слепок артефактов analytics-telemetry-to-clickhouse: проверка отпечатками показала побайтное тождество с 99eb6b4b — прошлым состоянием самой ветки. Он отменён обратным коммитом. Две другие правки — дополнение .gitignore и актуализация состояния entry-observation-stage (она НОВЕЕ версии в ветке, проверено поиском блоба по всей её истории) — сохранены и уцелели после слияния.
Два неотслеживаемых файла мешали слиянию и были перемещены, а не удалены: локальный .mcp.json оказался пустышкой в 0 байт, а локальный разбор сессии — устаревшей редакцией с заглушкой «ЗАПОЛНИТЬ: прогон контрфакта», тогда как в ветке этот раздел уже заполнен. Слияние вернуло обе полные версии; копии прежних лежат в .tmp/premerge/.
Что на бою (замер 2026-08-18)
| Что | Значение | Чем измерено |
|---|---|---|
| Выкаченный коммит | 20b9d937 | отпечаток сборки в строке старта движка |
| Из какой ветки | feat/telemetry-metrics-sinks (в main НЕ слита) | git branch --contains |
| Собран | 2026-08-17 16:44Z, dirty=false | та же строка старта |
Схема config.db | v3 | sqlite3 -readonly config/config.db |
| Активная строка | weather-harvester, кошелёк live (одна) | там же |
| Открытых позиций | 0 | data/engine.db |
| Дрейн | включён с 2026-08-11, причина operator_drain | /api/local/drain |
Работают контейнеры pm-victoriametrics и pm-vm-mcp — часть телеметрии, которой в main нет.
Четыре артефакта на бою — три собраны из ГРЯЗНОГО дерева
scripts/deploy-vps.sh verify (read-only, прогон 2026-08-18): agree=2, mismatch=0.
| Артефакт | Коммит | dirty | В main? | Выкачен |
|---|---|---|---|---|
pm-engine | 20b9d937 | нет | НЕТ (ветка телеметрии) | 2026-08-17 16:57Z |
pm-engine-dashboard | 4ae36c14 | да | да | 2026-08-16 22:33Z |
pm-cli | 4ae36c14 | да | да | 2026-08-16 22:33Z |
| SPA | 4102d415 | да | да | 2026-08-17 16:41Z |
Два следствия:
- Вне
mainтолько ДВИЖОК. Дашборд, CLI и SPA собраны из предковmain— их релиз ничего не откатывает. dirty=trueозначает, что в дереве сборки были незафиксированные правки, и какие именно — установить нечем. После релиза они исчезнут. Если на бою наблюдалось поведение дашборда, которого нет вmain, его источник — эти правки, и восстановить их будет неоткуда.
Расхождение — СНЯТО слиянием (историческая запись)
Ниже — состояние ДО слияния; оставлено, чтобы был виден масштаб того, что едва не уехало в бой откатом.
Ветки разошлись СИММЕТРИЧНО, по 16 коммитов в каждую сторону:
- в
main, нет на бою: активация стратегии изconfig.db(схема v4, атомарная активация, отказ старта при унаследованном инвентаре) + версионирование контракта настроек (штамп версии, диспетчер переездов); - на бою, нет в
main: линия телеметрии — VictoriaMetrics, read-only MCP, ряды метрик воронки входа.
Ветка feat/scanner-loop-lag-p99 включает всю телеметрию плюс работу по задержке цикла: 44 коммита сверх main.
Что блокировало слияние — СНЯТО
Обе помехи устранены: чужие правки зафиксированы их автором в ветке, два неотслеживаемых файла перемещены. Запись оставлена как образец того, чем кончается выкат из невлитой ветки.
- Пять файлов
openspec/changes/analytics-telemetry-to-clickhouse/*изменены в рабочей копииmainДРУГОЙ сессией и ровно они же меняются сливаемой веткой. Git откажет; обойти — потерять чужую незафиксированную работу. Решение оператора: дождаться. - В ворктри
scanner-loop-lag-p99идёт сборка — работа не окончена.
Пробные слияния конфликтов НЕ дают (git merge-tree): и телеметрия, и p99 сливаются чисто. Ждём только фиксации чужих правок.
Предусловия выката — ВЫПОЛНЕНЫ
scripts/deploy-vps.sh engine отказывается работать, пока движок не в дрейне и не плоский ("draining":true И "open_positions":0). Оба условия сейчас выполнены, дополнительных действий перед выкатом не требуется.
Порядок — остался ОДИН шаг
Шаги 1–3 выполнены 2026-08-18: чужие правки зафиксированы, ветка слита, полные ворота пройдены 11/11 на спокойной машине.
Осталось: scripts/deploy-vps.sh engine. Он сам делает сверку sha256, проверку настроек штатным бинарём (pm-engine --validate-config), резервную копию и рестарт. Предусловия (дрейн включён, позиций 0) выполнены — дополнительных действий не требуется.
Выкат запускает оператор. Дрейн после выката снимается ОТДЕЛЬНЫМ решением.
Откат — ЧИТАТЬ ДО ВЫКАТА
Откат бинаря БЕЗ отката базы невозможен. Новый движок мигрирует config.db с v3 на v4 автоматически при первом открытии, а прежний бинарь на базе v4 стартовать ОТКАЗЫВАЕТСЯ:
config.db schema_version `4` is newer than this build supports (current=3).
Refusing to open to prevent data corruption.Скрипт это предусмотрел: перед заменой он снимает sqlite3 .backup с config.db (с проверкой PRAGMA integrity_check) и копии обоих бинарей в $VPS_ROOT/.deploy/backups/<rid> и печатает путь строкой rollback set: …. Откат = восстановить И базу, И бинарь из этого каталога. Восстановить только бинарь — значит получить движок, который не поднимется.
Отдельно: штамп версии контракта в публикуемую колонку НЕ пишется именно ради отката — подробности в openspec/specs/strategy-config-schema-contract/spec.md.
Приёмка после выката
- Строка старта несёт ожидаемый
commit=иdirty=false. scripts/deploy-vps.sh verify— сверка манифеста с файлами и работающими процессами.sqlite3 -readonly config/config.db "SELECT value FROM schema_meta WHERE key='schema_version'"→4.- Движок выбрал строку по активации: в логе
strategy_label=weather-harvester. - Дрейн снимать ОТДЕЛЬНЫМ решением — выкат его не трогает.