# Задание для Antigravity, круг 3: довести две ветки синхронизации до влития - Репозиторий: https://git.ochenstarik.ru/ochenstarik/krona-staff - Основа: `codex/bootstrap-platform-foundation` (`f5ac179`) - Итоги приёмки: `docs/audit/2026-09-26/ACCEPTANCE-2.md`. Задание `TASK-ANTIGRAVITY-2.md` остаётся в силе, этот файл его дополняет и задаёт порядок. ## Итог приёмки твоих веток | Ветка | Коммит | Что подтверждено | Что мешает влить | | -------------------------------------- | --------- | ------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `antigravity/fix-reject-device-shifts` | `1df2019` | S1 исправлен: у Grok SYNC-A и SYNC-B зелёные | `tests/integration/sync-rejection.test.ts:81` вставляет столбец `created_by` в `staff_employees`, а такого столбца нет. Файл целиком FAIL | | `antigravity/fix-sync-c0-bootstrap` | `8baad55` | SYNC-C0 исправлен: на стенде Grok зелёный, оба теста `sync-bootstrap.test.ts` на реальной базе проходят | Файл всё равно FAIL: `Called end on pool more than once` в `afterAll` (строка 96). Пул закрывает `app.close()` через хук `onClose` (`src/app.ts:148`), а тест закрывает его второй раз | | обе вместе | — | — | **Конфликт** в `src/domain/sync/service.ts`: обе ветки созданы от `f5ac179` и правят один файл | Проверка у меня: PostgreSQL 17.10, роль приложения без SUPERUSER и BYPASSRLS, миграции 0001–0011 на чистой базе. ## 1. Починить тесты (сегодня) **1.1. `sync-rejection.test.ts`.** Подготовку данных сверить со схемой из миграций, а не писать по памяти: в `staff_employees` нет `created_by`. Смотри `migrations/*.up.sql` или `\d staff_employees`. **1.2. `sync-bootstrap.test.ts`.** Закрывать пул один раз. Либо только `app.close()`, либо свою `Database`, которую приложение не закрывает, — но не обе сразу. **Готово, когда** на реальной базе оба файла дают `Test Files 1 passed`, а не только `Tests N passed`: ошибка в хуке тоже делает файл красным, и CI его не пропустит. ```text DATABASE_TEST_URL=<роль приложения> DATABASE_MIGRATION_URL=<мигратор> npx vitest run tests/integration/sync-rejection.test.ts tests/integration/sync-bootstrap.test.ts ``` ## 2. Одна цепочка вместо двух конфликтующих веток Две ветки от одной основы с правками одного файла нельзя влить обе без ручного разрешения конфликта, а разрешать его за тебя никто не будет. Сделай цепочку: 1. `antigravity/fix-reject-device-shifts` — исправленный тест (пункт 1.1), без новых функций. 2. `antigravity/fix-sync-c0-bootstrap` — **перебазировать поверх** пункта 1 и разрешить конфликт у себя. Исправленный тест пункта 1.2 — здесь же. 3. Пуш обеих веток с `--force-with-lease`. Тогда вливается сначала первая ветка, потом вторая — без конфликтов. **Готово, когда:** - `git merge-base --is-ancestor origin/antigravity/fix-reject-device-shifts origin/antigravity/fix-sync-c0-bootstrap` выполняется успешно; - на вершине цепочки у Grok зелёные SYNC-A, SYNC-B и SYNC-C0, и оба интеграционных файла дают `passed`. ## 3. Форматирование синхронизации — твоё В ветке Codex `codex/fix-format-baseline` (`513cdff`) до сих пор лежит твоё исправление S1: после prettier `service.ts` и `sync.test.ts` в ней совпадают с твоей веткой построчно. Codex получил задание убрать оттуда `src/domain/sync/**` и `tests/unit/sync.test.ts`. Поэтому: - форматирование файлов синхронизации (`prettier --write src/domain/sync tests/unit/sync.test.ts tests/integration/sync-*.test.ts`) делаешь ты, в своей цепочке, **отдельным коммитом** `style(sync): …` без изменений поведения; - после этого `npx prettier --check src/domain/sync tests/unit/sync.test.ts` на вершине цепочки проходит. ## 4. Перед каждым пушем В прошлых двух кругах интеграционный тест пушился без запуска на настоящей базе. Порядок перед каждым пушем: 1. `npm run check`. 2. Интеграционные тесты своей зоны на реальной PostgreSQL — результат `Test Files … passed`. 3. Стенд Grok: `node scripts/test/run-e2e.mjs` поверх своей ветки. Ни один сценарий, зелёный на основе, не должен покраснеть. 4. В описании коммита или ветки — вывод пунктов 2 и 3 (строки `Test Files`, `Tests`, таблица по ID). Если реальная база недоступна, так и напиши в отчёте. Не пиши «проверено», если не запускал. ## 5. Дальше — по TASK-ANTIGRAVITY-2, новыми ветками поверх цепочки После пунктов 1–3 продолжай по разделам 3–6 `TASK-ANTIGRAVITY-2.md`. Одна тема — одна ветка, каждая следующая — от вершины предыдущей, пока они не влиты: | Порядок | Ветка | ID | Готово, когда | | ------- | ------------------------------- | ------------------ | --------------------------------------------------------------------------------------------- | | 1 | `antigravity/sync-device-scope` | S4, S8, S9 | SYNC-E, SYNC-F, SYNC-H зелёные; точку с устройством можно удалить или получить понятный отказ | | 2 | `antigravity/sync-idempotency` | S3, S2 | SYNC-G, SYNC-J зелёные | | 3 | `antigravity/sync-cursor` | S5, S6, S7 | SYNC-C, SYNC-D зелёные; отметка через синхронизацию пишет outbox | | 4 | `antigravity/push-hardening` | K12, N8, N9, U1–U7 | N3 и N9 зелёные | | 5 | `antigravity/outbox-publisher` | раздел 6 | по TASK-ANTIGRAVITY-2 | Оповещения процесса подтверждения (раздел 5 TASK-ANTIGRAVITY-2) — только после того, как Codex вольёт этап 4. Зона файлов прежняя: `src/domain/sync/**`, `src/domain/notifications/**`, push-модули, их миграции и тесты. Если нужна правка вне зоны — отдельный коммит с объяснением и пометкой в отчёте. Лучше попроси Codex. ## Отчёт Для каждой ветки: имя, коммит вершины, основа, какие ID закрыты, вывод интеграционных тестов и стенда Grok, что осталось.