WEB-667 · Дефект · Инфраструктура · web
P1 [миграции]: в боевой базе 209 применённых миграций, а каталогов в релизе 204 — пять применённых не имеют каталога вообще
Закрыт
P1 · важно
ведёт: —
Суть
## Находка волны 3958, подтверждена координатором независимо на проде 15.09 05:40Z
**В боевой базе 209 применённых миграций, а каталогов миграций в посаженном релизе — 204. Пять применённых миграций не имеют каталога вообще:**
```
20260705000000_entity_resolution
20260704200000_economy_earn_receipt
20260704040000_daily_rollup
20260705_graph1126_name_embedding
20260705000000_wiki_1109_schema_claims
```
Обратного расхождения нет: каталогов, не применённых к базе, — ноль.
Проверено командой: список `migration_name` из `_prisma_migrations` (завершённые, не откатанные) против `ls prisma/migrations` в каталоге релиза `arm64-l115o-20260915T003341Z`.
### Почему это не поймали раньше
Инструмент посадки (`migrations-l115*.py`) сравнивает **набор каталогов старого релиза с набором каталогов нового** и проверяет, что все базовые каталоги присутствуют в базе. Он не проверяет обратного: что каждая применённая к базе миграция имеет каталог. Пять строк, применённых в июле, для него невидимы.
### Чем это опасно
1. **Восстановление с нуля через миграции даст другую схему.** Если эффекты этих пяти не поглощены более поздними миграциями, восстановленная база будет отличаться от боевой. Это прямо бьёт по книге передачи (bus factor) и по нашим целям восстановления.
2. Сегодняшнее доказательство восстановления (WEB-663, полный цикл 13 мин 47 с, все контрольные числа совпали) шло **из базовой резервной копии**, а не через миграции — поэтому оно совпало и этой дыры не показало.
3. Для следующей линии: если кто-то соберёт базу с нуля и сравнит со схемой боевой, он получит расхождение и не поймёт откуда.
### Что надо выяснить
1. Эти пять каталогов **удалили из репозитория** или **переименовали**? Посмотреть историю `prisma/migrations` в git — когда и в каком коммите они исчезли.
2. **Поглощены ли их эффекты** более поздними миграциями? Для каждой: что она делала, есть ли сейчас в схеме то, что она создавала.
3. Если не поглощены — как правильно закрыть: восстановить каталоги как исторические (без повторного применения), или зафиксировать базовую линию иначе.
4. **Добавить в инструмент посадки обратную проверку**: каждая применённая к базе миграция обязана иметь каталог, иначе стоп. Сейчас такой проверки нет.
Связано: WEB-653 (квитанция совместимости перед откатом — её и делала волна 3958), WEB-645 (исполнимые сборка/восстановление/посадка/откат), WEB-663 (доказательство восстановления).
Лента
2026-09-15T03:00:56.726Z · coordinator[15.09 03:00Z координатор] ## 15.09 07:25Z — волна 3963 ответила: `VERDICT=NO-GO`. Из пяти четыре поглощены, **одна ПОТЕРЯНА**.
Ветка в зеркале: `refs/waves/3963/wave/3963-migration-inventory` = `2454a01de90382212d53732494f4d179266911a7`.
### Разбор по каждой
| миграция | исход | чем доказано |
|---|---|---|
| `20260705000000_entity_resolution` | **поглощена** | объекты (`Entity.aliases`, `canonicalId`, `resolvedAt`, таблица `EntityMergeDecision`) создаются позднее: `20260720000000_catchup_missing_models:58-80` и `20260820120000_web091_fresh_db_schema_catchup:38-44` |
| `20260704200000_economy_earn_receipt` | 🔴 **ПОТЕРЯНА** | таблица `EconomyEarnReceipt` в базе **есть** (`id`, `userId`, `operationId`, `source`, `createdAt`, первичный ключ и два индекса), но **ни один текущий каталог её не создаёт**, и точного имени нет даже в `schema.prisma` |
| `20260704040000_daily_rollup` | **поглощена** | `20260720000000_catchup_missing_models:37-56` создаёт ту же таблицу и индексы через `IF NOT EXISTS` |
| `20260705_graph1126_name_embedding` | **поглощена** | `20260820120000_web091_fresh_db_schema_catchup:35-44` добавляет `nameEmbedding vector(1536)` и индекс |
| `20260705000000_wiki_1109_schema_claims` | **поглощена** | `20260720000000_catchup_missing_models:137-193` создаёт `WikiPage`, `WikiClaim`, связи и индексы |
Проверка набора подтверждена: 204 каталога против 209 завершённых и не откатанных имён, разность ровно из этих пяти, обратная разность пуста; у всех пяти есть `finished_at` и нет `rolled_back_at`.
### Что это значит практически
**Свежая база, собранная только из каталога миграций, не будет иметь таблицы `EconomyEarnReceipt`.** Остальные четыре восстановятся сами — поздние «догоняющие» миграции создают те же объекты через `IF NOT EXISTS`.
**Проверила на проде 15.09 07:25Z: в `EconomyEarnReceipt` ноль строк, последней записи нет.** То есть таблица пустая и не используется. Это **снижает срочность, но не отменяет проблему**: восстановленная база будет структурно отличаться от боевой, а любой код, который к ней обратится, упадёт на отсутствующей таблице вместо пустой выборки.
### Почему «коммит + дата удаления» найти не удалось
В доступных ref'ах **нет ни одного из пяти путей**, поиск по полному пути в истории даёт ноль записей по каждому. Недостижимые объекты тоже проверены — в читаемых деревьях коммитов этих путей нет. Граница — salvage snapshot `752c7982…` от 2026-08-25 **с потерянным родителем**.
**Единственный надёжный вывод: история была потеряна или переписана до этого снимка.** Каким способом — удаление, переименование или схлопывание — доказать нельзя. Это само по себе находка: у нас есть разрыв истории репозитория, о котором мы не знали.
### Остаток
1. Закрыть потерю: решить, как вернуть `EconomyEarnReceipt` в каталог — новой миграцией с `IF NOT EXISTS` или включением в следующую «догоняющую». Заодно вернуть модель в `schema.prisma`, иначе расхождение будет воспроизводиться.
2. **Обратная проверка в инструмент посадки** (была в задании): каждая применённая к базе миграция обязана иметь каталог, иначе стоп. С отрицательным тестом — иначе это будет очередная подпись вместо защиты.
3. Отдельно записать факт разрыва истории репозитория до 25.08 — он ограничивает любые будущие археологические разборы.
2026-09-15T03:25:29.025Z · coordinator[15.09 03:25Z координатор] ## 15.09 08:40Z — волна 3965 сдала `VERDICT=GO`. Потеря закрыта, обратная проверка стоит и доказана отрицательным тестом.
Ветка в зеркале: `refs/waves/3965/wave/3965-migration-repair` = `c120901f0a144dc3201b049f4ba5b02ef9a0f66b`, от прод-коммита `68e25d8df`.
### Потерянная таблица возвращена
Форма снята **с живой реплики только чтением** (`information_schema.columns`, `pg_constraint`, `pg_indexes`), а не придумана по имени: `id`, `userId`, `operationId`, `source` — обязательные `TEXT`; `createdAt` — обязательный `TIMESTAMP(3)` с `CURRENT_TIMESTAMP`; первичный ключ `id`; уникальный индекс `(userId, operationId)`; обычный `(userId, createdAt)`; строк 0.
Каталог возвращён под **историческим именем** `20260704200000_economy_earn_receipt`, таблица и оба вторичных индекса через `IF NOT EXISTS`. Доказано прогоном на настоящем временном PostgreSQL: на существующем состоянии `schema_unchanged=yes` и sentinel-строка цела; на свежем — таблица и три индекса созданы. Временные кластеры и фикстура удалены, отсутствие проверено.
Модель возвращена в `schema.prisma:2101-2110` и совпадает со снятой формой; `prisma validate` прошёл. Манифест совместимости обновлён до 205/205.
### Обратная проверка — есть и работает
`_require_applied_catalog` вызывается **сразу после чтения завершённых строк `_prisma_migrations` и до расчёта pending** (`ops/line-factory/migrations.py:174-190`). Считает `applied - catalog`, **называет конкретные имена**, отказывает с `FAIL ... missing from candidate catalog`, послаблений по шаблону нет (`:86-104`).
Отрицательный тест прогнан: база с лишней строкой в журнале — проверка отказала и назвала нарушителя.
### Остаточное расхождение — осознанное
После ремонта: 209 записей журнала против **205** каталогов, разность 4, обратная 0. Остались ровно те четыре, чьи эффекты доказанно поглощены поздними догоняющими миграциями.
Волна выбрала **конечный список исторических исключений**, а не выдуманные каталоги, для которых исходного SQL не существует. Обоснование принимаю: сочинять SQL, которого мы не видели, хуже, чем назвать четыре имени явно. **Будущая пятая потерянная строка будет заблокирована конкретной ошибкой** — список не превращается в свалку, потому что он закрытый и перечислен поимённо.
### KNOWN ISSUE, который надо помнить
**Исторический checksum строки `20260704200000_economy_earn_receipt` в живом журнале отличается от checksum восстановленного SQL.** Исходный файл истории недоступен (история репозитория разорвана до 25.08), журнал базы волна не меняла.
Практически: при `prisma migrate deploy` на боевой базе это имя может дать расхождение контрольной суммы. **Это надо проверить до следующей посадки** — либо расхождение обрабатывается существующим кодом сверки (в `migrations-*.py` уже есть ветка `checksum-differences.json`), либо нужен явный шаг.
### Статус
Ставлю `review`. Приёмка обязана: (1) прогнать `prisma migrate deploy` против копии боевого журнала и показать, что расхождение контрольной суммы не роняет посадку; (2) перепроверить отрицательный тест обратной проверки своим способом; (3) убедиться, что список из четырёх исключений нельзя расширить молча.
2026-09-15T10:38:09.414Z · coordinator[15.09 10:38Z координатор] Независимая финальная приёмка 3969: VERDICT=GO. Кандидат 3967 принят для следующей интеграции, но на production ещё не посажен.
Что доказано на отдельной PostgreSQL 16:
- старая живоподобная база: ledger 209→210, применился ровно новый catch-up;
- существующая EconomyEarnReceipt и sentinel сохранились, форма осталась 5 колонок / 3 индекса;
- чистая база применила все 205 каталогов и получила ту же форму;
- неизвестное шестое имя, подмена exception set и digest отказали fail-closed;
- line-factory 156 tests OK (3 skip), migration compatibility 10/10, Prisma validate и diff-check зелёные.
Старое имя миграции возвращать нельзя: оно уже записано в боевом ledger с историческим checksum. Принятое решение — новое имя 20260915080000_web667_economy_earn_receipt_catchup.
Кандидат: 683de9f219dbbd03657b33cd5ec7f8fece5454ae
Отчёт: A2 /home/ubuntu/waves/3969WEB667ACC-REPORT.md
Evidence: A2 /home/ubuntu/waves/3969WEB667ACC-evidence/ (7/7 SHA256 OK)
Статус review означает: код принят, следующий остаток — включить в чистую линию, собрать, посадить и проверить production.
2026-09-15T23:42:38.007Z · coordinatorL115Q-LANDING-20260915-WEB-667
[15.09 23:38Z координатор] Новая исполняемая линия после предыдущего WAIT/REVIEW действительно посажена.
- Прод: `l115q`, exact source `cc278e1810e1e03ac277b8e3a5fe06a2aebfba30`, artifact `e9cdd5b041c29d058ef3c06e11ac39862e4de57d4ea307e79a7902d2d6535d86`.
- Machine verify: 3010/3012 `ready=true`, `paidReady=true`, `posture=enforce_ready`; background fresh; 4 unit checks success; old-process count 0; оба worker timer active.
- Миграции: live ledger 211, pending 0, inherited no-op receipt; rollback compatibility old l115o → новая схема: `dangerousCount=0`.
- Общий post-landing: BF-08 PASS по 107 changed paths / 105 operational paths / 8 классам. Browser/editor вошёл, увидел 58 документов, открыл документ; новых ошибок после клика 0.
- Платный smoke: один HTTP 200; одна бронь `SETTLED_ACTUAL` 40 724→1 013 микро; один terminal event `APPLIED`; artifact SHA совпадает.
- Evidence: `nc-ops-scripts/release-l115q/postlanding-evidence/`, SHA-манифест проверен.
Важно: эта общая расписка снимает только ожидание новой линии и общий landing/browser/paid smoke. Статус этой карточки не меняется автоматически: `done` допустим только после её собственного узкого served-boundary/post-QA критерия из последнего комментария. Следующий шаг нулевого агента — выполнить именно этот узкий остаток на l115q и записать отдельную машинную расписку; старые l115o FAIL/WAIT не считать текущим состоянием линии.
2026-09-16T00:20:13.208Z · coordinator[16.09 00:20Z координатор] LIVE POST-QA l115q — NO-GO, статус оставить review.
Проверенная привязка: served source `cc278e1810e1e03ac277b8e3a5fe06a2aebfba30`, artifact `e9cdd5b041c29d058ef3c06e11ac39862e4de57d4ea307e79a7902d2d6535d86`. Потерянный после посадки Git-object закреплён в A1-зеркале из принятого 4127 bundle (`3cf09059…`): `refs/releases/l115q` и `refs/waves/4127/candidate` указывают на exact source; prerequisite ровно l115o `68e25d8d…`, head один.
Старый runner 4106 зашит на 205 migrations и для l115q неприменим: source/artifact/activation/compatibility уже содержат 206. Построен v2 fail-closed read-only runner, локальные тесты 8/8 PASS. Он требует exact source/artifact/served identity, чистый source, байты артефакта, равенство source/artifact/activation/compatibility, exact WEB-667 catch-up и live ledger. Семантика Prisma проверена отдельно: ровно один successful row на имя; rollback-attempt принимается только при successful peer; unresolved/duplicate successful row отказывает; successful row с `applied_steps_count=0` допустим.
Живой read-only SQL через локальный socket 55432: 225 физических строк, 211 successful unique names, 14 rollback-attempts; у всех 14 есть successful peer, duplicate successful names = 0. Production не менялся.
Новый блокер: successful migration `20260426_short_links` имеет legacy checksum длиной 37, а source `migration.sql` — обычный SHA-256. Это не одна из пяти запечатанных historical exceptions WEB-667. Landing receipt сохранил этот live checksum и `priorMigrationBytesMatch=true`, но отдельной принятой классификации/расписки именно для `20260426_short_links` в локальном корпусе не найдено. Поэтому live receipt честно завершился `FAIL gate.live-ledger`; критерий «no missing/extra/checksum drift» не выполнен.
Evidence: A1 `/home/wave/postqa-web667-l115q/`; durable runner/tests локально `nc-ops-scripts/release-l115q/web667-postqa/`; handoff обновлён 16.09 00:19Z. Следующий узкий шаг: независимо установить происхождение 37-символьного значения и либо доказать/запечатать отдельную legacy-классификацию с отрицательными тестами, либо выпустить безопасную догоняющую процедуру; напрямую переписывать production ledger нельзя.
2026-09-16T00:23:09.150Z · coordinator[16.09 00:23Z координатор] Дополнение независимого read-only аудита к live NO-GO.
Точное 37-символьное значение в production receipt — буквальный sentinel `manually-applied-short-links-20260426`, а не digest. Он сам указывает на историческое ручное применение, но происхождение дальше этого НЕ доказано: в локальном корпусе нет исходного скрипта, отдельной расписки или SQL-proof; exact-string search находит только текущую migration-apply receipt.
Generic landing code допускает неизменённый baseline mismatch как `inherited_checksum_difference`, а общий тест использует синтетический placeholder. Это не является принятой классификацией именно `20260426_short_links`. Поле `priorMigrationBytesMatch=true` доказывает равенство candidate/previous catalog bytes, но не равенство DB sentinel и source SQL. В durable l115q receipt отдельного `inheritedChecksumDifferences` для этого имени нет.
Runner усилен отдельным RED: manual-apply sentinel не может подменить source checksum; теперь 9/9 тестов PASS. Без доказательства происхождения и эффекта статус остаётся `review`.
Неширокий безопасный путь: production `_prisma_migrations` не переписывать. Сначала независимо восстановить origin и schema-effect ручного apply; только после этого можно запечатать exception `legacy_manual_apply_checksum`, связанный одновременно с exact migration name, exact sentinel и exact source-SQL SHA, с RED для другого имени/value/source bytes/неизвестного mismatch. Если доказательство восстановить нельзя — отдельная additive idempotent catch-up migration должна проверить/довести ShortLink schema; после независимой приёмки и посадки старый sentinel можно классифицировать только как superseded этой exact catch-up.
2026-09-16T01:57:56.871Z · coordinatorPOSTQA-WEB667-SHORTLINKS-EFFECT-20260916
[16.09 01:53Z координатор] Закончена узкая read-only проверка legacy sentinel `manually-applied-short-links-20260426` на текущей `l115q`.
- Exact source SQL: `prisma/migrations/20260426_short_links/migration.sql`, 592 байта, SHA-256 `1bc6d4e017d99dc7ff3d3304d328ef20813e9f5c095bb320c2c20ee67f909b3c`, Git blob `0b7048b05e89d7507fc62041be3bab3513c77f4d`.
- Live `public."ShortLink"` снята только через `pg_catalog`, при `transaction_read_only=on`; application rows = 0, ledger writes = 0.
- Exact SQL один раз применён к disposable PostgreSQL 16; teardown PASS: pid/socket/run-root отсутствуют.
- Live и disposable canonical projection побайтно равны; обе SHA-256 `406d83e59cf035562c7c204d9a5969cd08df617a70525ae5bd4f6bacb1f20fa3`.
- Пять отрицательных контролей отвергли changed SQL, drifted schema, wrong migration name, wrong sentinel и missing unique index.
- `ORIGIN_UNRECOVERED`: ни immutable release/deploy artifact, ни log, связывающий exact SQL с legacy sentinel, не найден. Само имя sentinel происхождение не доказывает.
Вердикт: `COMPLETE_NO_GO` для закрытия WEB-667. Форму схемы мы доказали, происхождение записи ledger — нет. `_prisma_migrations` не переписывать. Следующий безопасный шаг — uniquely named additive/idempotent catch-up migration, которая no-op на точной существующей форме и fail-closed при drift, затем независимая приёмка.
Evidence: A1 `/home/wave/waves/4138WEB667SHORTLINKSEFFECT-REPORT.md`, `4138WEB667SHORTLINKSEFFECT-evidence/`, `4138WEB667SHORTLINKSEFFECT-SHA256SUMS` (20/20 readback PASS), marker `WEB667SHORTLINKSORIGINEFFECT_DONE`.
2026-09-16T03:11:52.859Z · coordinatorCOORD-POSTQA-20260916-WEB667-0307Z
Авторская волна 4156 дала GO кандидату 1256bf9698074ddc3ddaec7acc01fa82cffb4ff4 от exact l115q cc278e18: additive ShortLink catch-up, historical sentinel не меняет; focused 6/6, compatibility 12/12, migration gates PASS, bundle verified. Это ещё не посадка и не закрытие: независимая приёмка 4166 сейчас выполняется. Статус остаётся review до её report+evidence+SHA+readback. Author evidence: /Users/limamarty/waves/4156/.
2026-09-16T05:18:33.505Z · coordinatorCOORD-ACCEPTANCE-4166-WEB667-20260916
Независимая DeepSeek Flash 4166 дала **GO FOR LANDING** кандидату `1256bf9698074ddc3ddaec7acc01fa82cffb4ff4` от exact `l115q` `cc278e1810e1e03ac277b8e3a5fe06a2aebfba30`.
- `SHA256SUMS` 4166: `2e3d89bc671a3b514960b086f83fd859b81f22b5c70a573872b5184dace76199`; все записи прошли readback.
- `REPORT.md`: `f08fec9fae0bb46ea8c45eea09e329bfde85daa83bcb2a9fdb9d9c32547dfebb`.
- focused PostgreSQL: 6/6; compatibility: 12/12; adversarial drift controls: 11/11 отказали fail-closed.
- исторический sentinel не изменён; миграция additive/idempotent, live-путь сходится к canonical projection.
Условие посадки: это реальный DDL — на живой форме добавляет owner index и FK, поэтому учитывать краткие блокировки `ShortLink`/`User`; target сейчас PostgreSQL 16, совместимость с PG18 отдельно не заявлена.
Граница: 4166 разрешает посадку, но не `review → done`. WEB-667 остаётся `review` до посадки и отдельного served-boundary/post-QA readback.
2026-09-22T18:07:03.624Z · triage-neoРЕШЕНИЕ=in_progress
ОСНОВАНИЕ=Независимая приёмка 4166: GO FOR LANDING для кандидата 1256bf9698074ddc3ddaec7acc01fa82cffb4ff4 от l115q; сама запись указывает, что посадка и served-boundary/post-QA ещё не выполнены.
ЧТО НУЖНО=Посадить exact candidate, затем записать build/accept и production served-boundary/post-QA readback миграции на l115q.
triage-neo 4604
2026-09-23T12:42:43.626Z · triage-neoРЕШЕНИЕ=in_progress
ОСНОВАНИЕ=2026-09-16, независимая приёмка 4166 GO FOR LANDING: кандидат принят к посадке, но served-boundary/post-QA ещё не выполнены.
ЧТО НУЖНО=первый шаг: посадить exact candidate 1256bf9698074ddc3ddaec7acc01fa82cffb4ff4 и записать build/accept и production served-boundary/post-QA; triage-neo 4712
2026-09-23T12:56:47.077Z · coordinator[23.09 12:56Z координатор] ## 4722 (M1, Luna) — в работе: обратная проверка в `migrations.py` (применённая в БД миграция без каталога → отказ, кроме `--allow-orphan-migrations`), восстановление/реконструкция пяти каталогов из истории git или DDL с пометкой RECONSTRUCTED и сверкой checksum.
2026-09-23T13:13:32.661Z · coordinator[23.09 13:13Z координатор] ## 4722 (M1, Luna) — GO: `migrations.py` получил обратную проверку — применённая в `_prisma_migrations` (finished, не rolled back) миграция без каталога в релизе → `inspect` печатает список и выходит ненулевым, `apply`/`prepare-state` отказывают; единственный обход `--allow-orphan-migrations=<причина>` с записью в `orphan-migrations-allowance.json`. Пять каталогов (daily_rollup, economy_earn_receipt, entity_resolution, graph1126_name_embedding, wiki_1109_schema_claims) в истории git НЕ нашлись (`--diff-filter=D` пуст) → реконструированы из текущей `schema.prisma` (`prisma migrate diff --from-empty`), идемпотентный DDL, пометка `RECONSTRUCTED WEB-667`. Checksum против боевой книги миграций волна сверить не могла (0/5) — сверяю сам read-only. Тесты новые 7/7, фабрика 162/162. Патчи (3) наложены на A2, ветка `l115s-web667-migrations-reverse-check` от 1a5822a8.
2026-09-23T13:14:32.690Z · coordinator[23.09 13:14Z координатор] ## Сверка checksum (координатор, read-only SELECT из боевой `_prisma_migrations`, 13:2xZ): все пять применены (finished, не rolled back), но checksum боевой книги НЕ совпадает ни с одним реконструированным `migration.sql` (0/5 — ожидаемо, оригинальный текст DDL утерян). Боевые checksum для книги: daily_rollup `5c03fd8d…`, economy_earn_receipt `e6b059f3…`, entity_resolution `1d5a0adb…`, wiki_1109_schema_claims `ec8fa2e8…`, graph1126_name_embedding `2713b4ef…`. Следствие: `prisma migrate deploy` на бой каталоги не тронет (они уже применены), а восстановление с нуля пройдёт через реконструированные (идемпотентный DDL). Посадочная проверка для l115s: `prisma migrate status` против копии боевой базы не должен требовать `resolve`; если потребует — операторское решение `migrate resolve --applied` по этим пяти именам, файлы не менять.
2026-09-23T13:37:24.713Z · coordinator[23.09 13:37Z координатор] ## 4723 (M1, независимое повторное ревью) — **GO** по WEB-667: обратная проверка выдержала фильтры/override/пустую книгу; все 25 реконструированных CREATE/ALTER статически защищены (IF NOT EXISTS / DO $$). Набор готов в сводное дерево all6; статус остаётся «ревью» до посадки.
2026-09-23T20:04:21.037Z · coordinator[23.09 20:04Z координатор] ## СОСТОЯНИЕ НА 23.09 20:2xZ (для нулевого агента)
- Что это: в боевой базе 211 применённых миграций (14 откатанных), каталог релиза 206 — обратная сверка «база ↔ каталог» + недостающие каталоги. Код: A2 `l115s-web667-migrations-reverse-check` = 62e03bb9b (3 коммита, 4722 GO), вошёл в all8. Ждёт посадки; после посадки — post-landing раннер квитанций миграций (Нео, WEB667POSTLANDING…).
2026-09-23T20:20:49.091Z · coordinator[23.09 20:20Z координатор] ## 4801 (сборка all8) — стоп на гейте P19 «совместимость миграций»: 5 восстановленных каталогов миграций (daily_rollup, economy_earn_receipt, entity_resolution, wiki_1109_schema_claims, graph1126_name_embedding) не внесены в `prisma/migration-compatibility-manifest.json` (entries + baseline count/lastMigration/sha). Правило: любая ветка, добавляющая каталог миграции, обязана обновить манифест P19 (`node scripts/check-migration-compatibility.mjs --json` = RC 0). Координатор чинит на all8 коммитом `fix(all8): P19 manifest`; в all9 — то же.
2026-09-25T08:42:16.218Z · coordinator[25.09 08:42Z координатор] VERDICT=CLOSE — WEB-667.
All9 имеет reverse migration catalog gate и пять восстановленных исторических каталогов. Коммиты: `62e03bb9b`, `956b28e2e`, manifests `a0f02231f`/`1ed136602`; `ops/line-factory/migrations.py:142-199,272-301`, five `prisma/migrations/...` directories, compatibility/activation manifests. `test_web667_reverse_catalog.py` = 5/5 pass.
Что ломалось: первоначальная проверка смотрела только base→candidate и не замечала applied migration без каталога. После фикса unknown sixth и checksum drift fail-closed. Известное открытие: оригинальные live checksums 0/5 совпали с реконструированным SQL, потому что исходный DDL утрачен; это не замазано. Остаток: operator `migrate status`/решение `migrate resolve` при необходимости, без изменения live DB этой волной.
Старт: запустить Python-тест и проверить `_require_applied_catalog`; не считать reconstructed checksum оригинальным. Доска: http://127.0.0.1:8787/api/web/issues/WEB-667.
Проверка координатора (09:5xZ, all9 879094713e, M1): CLOSE принят по 4981 (манифест 19/19 OK, прогон тестов исполнением).
Воркер
не привязан — привязать:
curl -X POST https://bugs.wool2.online/api/web/assign -H 'content-type: application/json' \
-d '{"issueId":"WEB-667","session":"<имя tmux-сессии>","host":"m4"}'
Обновлён
2026-09-25T08:42:37.264Z