Skip to content

Релиз 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.dbv3sqlite3 -readonly config/config.db
Активная строкаweather-harvester, кошелёк live (одна)там же
Открытых позиций0data/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-engine20b9d937нетНЕТ (ветка телеметрии)2026-08-17 16:57Z
pm-engine-dashboard4ae36c14дада2026-08-16 22:33Z
pm-cli4ae36c14дада2026-08-16 22:33Z
SPA4102d415дада2026-08-17 16:41Z

Два следствия:

  1. Вне main только ДВИЖОК. Дашборд, CLI и SPA собраны из предков main — их релиз ничего не откатывает.
  2. dirty=true означает, что в дереве сборки были незафиксированные правки, и какие именно — установить нечем. После релиза они исчезнут. Если на бою наблюдалось поведение дашборда, которого нет в main, его источник — эти правки, и восстановить их будет неоткуда.

Расхождение — СНЯТО слиянием (историческая запись) ​

Ниже — состояние ДО слияния; оставлено, чтобы был виден масштаб того, что едва не уехало в бой откатом.

Ветки разошлись СИММЕТРИЧНО, по 16 коммитов в каждую сторону:

  • в main, нет на бою: активация стратегии из config.db (схема v4, атомарная активация, отказ старта при унаследованном инвентаре) + версионирование контракта настроек (штамп версии, диспетчер переездов);
  • на бою, нет в main: линия телеметрии — VictoriaMetrics, read-only MCP, ряды метрик воронки входа.

Ветка feat/scanner-loop-lag-p99 включает всю телеметрию плюс работу по задержке цикла: 44 коммита сверх main.

Что блокировало слияние — СНЯТО ​

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

  1. Пять файлов openspec/changes/analytics-telemetry-to-clickhouse/* изменены в рабочей копии main ДРУГОЙ сессией и ровно они же меняются сливаемой веткой. Git откажет; обойти — потерять чужую незафиксированную работу. Решение оператора: дождаться.
  2. В ворктри 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.

Приёмка после выката ​

  1. Строка старта несёт ожидаемый commit= и dirty=false.
  2. scripts/deploy-vps.sh verify — сверка манифеста с файлами и работающими процессами.
  3. sqlite3 -readonly config/config.db "SELECT value FROM schema_meta WHERE key='schema_version'" → 4.
  4. Движок выбрал строку по активации: в логе strategy_label=weather-harvester.
  5. Дрейн снимать ОТДЕЛЬНЫМ решением — выкат его не трогает.