diff --git a/docs/audit/2026-09-26/ACCEPTANCE-2.md b/docs/audit/2026-09-26/ACCEPTANCE-2.md new file mode 100644 index 0000000..3a73e1e --- /dev/null +++ b/docs/audit/2026-09-26/ACCEPTANCE-2.md @@ -0,0 +1,126 @@ +# Приёмка №2: Grok, Codex, Antigravity — 2026-09-26 + +Проверка независимая, на живой PostgreSQL 17.10, в отдельных рабочих копиях. Ветки исполнителей не менялись. Основная ветка — `f5ac179`. + +## Итог + +| Исполнитель | Ветка | Вердикт | +| ----------- | --------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | +| Grok | `grok/e2e-harness` @ `ba59a48` | **Принять и влить первым.** Всё из TASK-GROK-2 сделано и подтверждено | +| Codex | `codex/fix-live-database` @ `b289dd6` | **K3 и K4 исправлены** (подтверждено мной и Grok). Влить после пересборки ветки форматирования | +| Codex | `codex/fix-format-baseline` @ `fd1ec3d` | **Переделать:** в коммит форматирования попало функциональное изменение Antigravity | +| Antigravity | `antigravity/fix-reject-device-shifts` @ `1df2019` | **Не принимать пока:** S1 исправлен, но интеграционный тест на реальной базе по-прежнему красный | +| Antigravity | `antigravity/fix-sync-c0-bootstrap` @ `8baad55` | **SYNC-C0 исправлен**, но тест падает в `afterAll`, и ветка конфликтует с предыдущей. См. дополнение ниже | +| Codex | `codex/fix-format-baseline` @ `513cdff` (перезалив) | **По-прежнему переделать:** синхронизация Antigravity осталась в коммите. См. дополнение ниже | + +## Grok — принято + +Проверено мной: + +- **Windows.** `node scripts/test/run-e2e.mjs` запускается на Windows 11 **без правок**: 54 сценария, 45 красных (все — известные дефекты), 9 зелёных, проверка списка известных дефектов проходит. После прогона рабочая копия чистая — прогонные файлы в git больше не попадают. +- **Сопоставление ID.** Сделано по таблице аудита: сценарии называются двойными ID вида `K3/N2`, ключи `known-defects.json` переименованы так же. +- **Недостающие сценарии добавлены:** K6, K7, K8, K9, S9, A4, N12-DATE. Все красные, как и должно быть. K7 уже показывает потерю денег при импорте: итог 22 200 вместо 33 300 и 37 700. +- **Приёмка веток исполнителей подтверждена.** На ветке Codex `codex/fix-live-database` я сам прогнал стенд Grok и получил 41 красный и 13 зелёных — ровно как в его отчёте. Позеленели K3/N2, K4/N1, K13/SYNC-A, K13/SYNC-B. +- **Зона не нарушена**, все коммиты с объяснением причины. + +Замечания на следующий круг: + +- Windows-раннера нет, поэтому задача `windows` в CI выключена переменной. Это честно отмечено в отчёте. +- В приёмке веток запускались только сценарии `tests/e2e`, а интеграционные тесты самих исполнителей — нет. Из-за этого не пойман красный тест Antigravity (см. ниже). + +## Codex + +**`codex/fix-live-database`: K3 и K4 исправлены.** + +- Подтверждение смены, расчёт и утверждение работают на реальной базе; создание сотрудника отвечает 201. +- Цепочка расчёта теперь доходит до денежных дефектов, и они подтверждаются по существу: + - K5 — одна смена начисляется дважды: 196 800 вместо 98 400; + - K6 — после отклонения оплаченной смены нет сторно. + + Это следующий этап задания (этап 3), а не ошибка ветки. + +- Остаток A4: `month=2026-13` по-прежнему отвечает 500 и возвращает код PostgreSQL. + +**`codex/fix-format-baseline`: переделать.** Grok установил, что «стилевой» коммит `fd1ec3d` содержит функциональное изменение: после нормализации форматирования `src/domain/sync/service.ts` совпадает с исправлением Antigravity, а `tests/unit/sync.test.ts` — тоже. Два нарушения AGENTS.md сразу: + +- смешение тем — поведение спрятано в коммите форматирования; +- правка чужой зоны: синхронизация принадлежит Antigravity. + +Если влить обе ветки, изменение Antigravity придёт дважды, и одна из веток получит конфликт. Нужно пересобрать коммит форматирования **без** изменений в `src/domain/sync/**` и `tests/unit/sync.test.ts`. Исправление S1 должно прийти только из ветки Antigravity. + +## Antigravity + +**`antigravity/fix-reject-device-shifts` @ `1df2019`.** + +- S1 исправлен: у Grok SYNC-A и SYNC-B зелёные. +- Сообщение коммита приведено к формату: короткий заголовок, причина в теле. +- Очистка теста переведена на роль мигратора. + +**Но тест по-прежнему красный на реальной базе.** Теперь он падает раньше, на подготовке данных: `column "created_by" of relation "staff_employees" does not exist` (`tests/integration/sync-rejection.test.ts:81`). Оба теста файла пропускаются, файл целиком — FAIL. Значит, на настоящей базе тест снова не запускали. Пункт 1 задания не закрыт. + +Как проверить у себя до пуша: + +```text +DATABASE_TEST_URL=<роль приложения> DATABASE_MIGRATION_URL=<мигратор> npx vitest run tests/integration/sync-rejection.test.ts +``` + +Готово, когда: `Tests 2 passed`. + +## Порядок влития + +1. `grok/e2e-harness` — влить сейчас: только тесты и CI. +2. Codex пересобирает `codex/fix-format-baseline` без синхронизации, затем вливаются форматирование и `codex/fix-live-database`. Grok отдельным коммитом убирает K3/N2 и K4/N1 из `known-defects.json`. +3. Antigravity чинит тест, затем вливается его ветка. Grok убирает K13/SYNC-A и K13/SYNC-B. + +## Новое: задача по пилоту от сессии платформы + +Сессия «БП» по просьбе владельца и в режиме только чтения выяснила два факта. + +1. Пилот на 192.168.1.81 пишет все данные под арендатором-заглушкой `01J00000000000000000000000`. Настоящий арендатор владельца в платформе — `01M2R6AC5652NPT3MG34DKN4ZP` («Сушигедза»). +2. Скрипта сопоставления standalone → platform, обещанного в `docs/PLATFORM-INTEGRATION.md`, нет. + +В репозитории я подтвердил: + +- заглушку записывает сам `deploy/pilot/setup.sh:20`; +- она же стоит значением по умолчанию в `compose.yaml:16` и в `.env.example:14`; +- в `scripts/` скрипта сопоставления нет. + +Задание — [TASK-CODEX-2.md](TASK-CODEX-2.md). + +Договор идентичности с платформой (модуль ждёт JWT, платформа шлёт неподписанные заголовки) исправляется на стороне платформы: пункты А-5, С-6, С-7 её плана. Этим занимается сессия «БП». Модулю — не менять `PlatformIdentityAdapter` под неподписанные заголовки. + +## Дополнение: перезаливы после первой версии приёмки + +**`antigravity/fix-sync-c0-bootstrap` @ `8baad55`** (от `f5ac179`). + +- Статус точки при начальной загрузке теперь вычисляется из `is_active` и `deleted_at`. На стенде Grok SYNC-C0 зелёный, итог стенда — 44 красных, 10 зелёных. +- `tests/integration/sync-bootstrap.test.ts` на реальной базе: `Tests 2 passed`, но файл FAIL. Пул закрывается дважды: `app.close()` уже закрывает его через хук `onClose` (`src/app.ts:148`), а тест в `afterAll` (строка 96) закрывает его снова — `Called end on pool more than once`. +- Конфликтует с `antigravity/fix-reject-device-shifts` в `src/domain/sync/service.ts`: обе ветки созданы от одной основы. + +**`codex/fix-format-baseline` @ `513cdff`** (перезалив от `f5ac179`). + +- Я нормализовал prettier'ом версии из основы, из ветки Codex и из ветки Antigravity. `src/domain/sync/service.ts` и `tests/unit/sync.test.ts` у Codex **построчно совпадают** с веткой Antigravity и отличаются от основы на 255 и 139 строк. Исправление S1 по-прежнему в коммите форматирования. Пункт 1 TASK-CODEX-2 не выполнен. +- `codex/fix-live-database` перебазирован на него (`8e955b0`), поэтому тоже несёт эту копию. + +**Конфликты между ветками** (`git merge-tree`): + +| Пара | Результат | +| ------------------------ | ----------------------------------------------------- | +| AG reject + AG c0 | конфликт | +| Codex format + AG c0 | конфликт | +| Codex format + AG reject | чисто — потому что в Codex лежит копия исправления AG | +| Grok + AG c0 | чисто | + +**Задания следующего круга:** + +- [TASK-ANTIGRAVITY-3.md](TASK-ANTIGRAVITY-3.md) — починить оба теста, выстроить ветки в цепочку, отдельный коммит форматирования синхронизации, дальше S2–S9 и push; +- [TASK-GROK-3.md](TASK-GROK-3.md) — приёмка с интеграционными тестами и проверкой конфликтов, проверка «форматирование без поведения», храповик после влития, сценарий переноса арендатора; +- [TASK-CODEX-2.md](TASK-CODEX-2.md) — без изменений. + +**Порядок влития, уточнённый:** + +1. Grok. +2. Цепочка Antigravity: reject → c0. +3. Codex: форматирование без синхронизации, затем `fix-live-database`. + +Цепочка Antigravity идёт раньше Codex, потому что после пересборки форматирования у Codex не останется пересечений с синхронизацией. diff --git a/docs/audit/2026-09-26/README.md b/docs/audit/2026-09-26/README.md index ddaf54e..7aece58 100644 --- a/docs/audit/2026-09-26/README.md +++ b/docs/audit/2026-09-26/README.md @@ -2,21 +2,24 @@ Рабочая папка аудита: исполнители берут отсюда задания и отчитываются через git. -| Файл | Что это | -| ------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------- | -| [AUDIT.md](AUDIT.md) | Полный аудит на живой PostgreSQL 17: находки P0–P3, сверка с аудитом Grok, решения владельца | -| [ACCEPTANCE-1.md](ACCEPTANCE-1.md) | Приёмка первого круга работ Grok и Antigravity | -| [TASK-CODEX.md](TASK-CODEX.md) | Codex: сервер, расчёт, база, пилот, терминал, роли, подтверждение и согласие — этапы 0–6 | -| [TASK-ANTIGRAVITY-2.md](TASK-ANTIGRAVITY-2.md) | Antigravity, **текущий круг**: синхронизация, push, оповещения, outbox | -| [TASK-GROK-2.md](TASK-GROK-2.md) | Grok, **текущий круг**: запуск стенда под Windows, сопоставление ID, недостающие сценарии, приёмка | -| [TASK-ANTIGRAVITY.md](TASK-ANTIGRAVITY.md), [TASK-GROK.md](TASK-GROK.md) | Задания первого круга, для истории | -| [evidence/](evidence) | Сценарии живой проверки и их фактический вывод | +| Файл | Что это | +| ---------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | +| [AUDIT.md](AUDIT.md) | Полный аудит на живой PostgreSQL 17: находки P0–P3, сверка с аудитом Grok, решения владельца | +| [ACCEPTANCE-1.md](ACCEPTANCE-1.md) | Приёмка первого круга работ Grok и Antigravity | +| [TASK-CODEX.md](TASK-CODEX.md) | Codex: сервер, расчёт, база, пилот, терминал, роли, подтверждение и согласие — этапы 0–6 | +| [ACCEPTANCE-2.md](ACCEPTANCE-2.md) | Приёмка второго круга: Grok принят, Codex и Antigravity — что доделать, порядок влития | +| [TASK-CODEX-2.md](TASK-CODEX-2.md) | Codex, **текущий круг**: форматирование без синхронизации, пилот на настоящего арендатора, сопоставление с платформой | +| [TASK-ANTIGRAVITY-3.md](TASK-ANTIGRAVITY-3.md) | Antigravity, **текущий круг**: починить тесты, цепочка веток, дальше S2–S9 и push | +| [TASK-GROK-3.md](TASK-GROK-3.md) | Grok, **текущий круг**: приёмка с интеграционными тестами и конфликтами, перенос арендатора | +| [TASK-ANTIGRAVITY-2.md](TASK-ANTIGRAVITY-2.md) | Antigravity, круг 2: полный список S2–S9, push, оповещения, outbox — остаётся в силе | +| [TASK-GROK-2.md](TASK-GROK-2.md), [TASK-ANTIGRAVITY.md](TASK-ANTIGRAVITY.md), [TASK-GROK.md](TASK-GROK.md) | Прошлые круги, для истории | +| [evidence/](evidence) | Сценарии живой проверки и их фактический вывод | ## Как работать - Каждый исполнитель работает в своих ветках и только в своей зоне файлов — зоны перечислены в задании. - Готовность пункта подтверждается зелёным сценарием стенда Grok (`node scripts/test/run-e2e.mjs`) на живой PostgreSQL, а не тестами на поддельной базе. - Отчёт о выполненном — в описании ветки или коммита: ID, коммит, какой сценарий стал зелёным. -- Приёмку каждой ветки независимо проводит Grok; итог следующего круга появится здесь как `ACCEPTANCE-2.md`. +- Приёмку каждой ветки независимо проводит Grok; итоги — в файлах `ACCEPTANCE-N.md`. Решения владельца (роли, точки, процесс подтверждения, согласие) — раздел 12 в [AUDIT.md](AUDIT.md) и раздел «Решения владельца» в [TASK-CODEX.md](TASK-CODEX.md). diff --git a/docs/audit/2026-09-26/TASK-ANTIGRAVITY-3.md b/docs/audit/2026-09-26/TASK-ANTIGRAVITY-3.md new file mode 100644 index 0000000..ca0478f --- /dev/null +++ b/docs/audit/2026-09-26/TASK-ANTIGRAVITY-3.md @@ -0,0 +1,80 @@ +# Задание для 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, что осталось. diff --git a/docs/audit/2026-09-26/TASK-CODEX-2.md b/docs/audit/2026-09-26/TASK-CODEX-2.md new file mode 100644 index 0000000..72cb6eb --- /dev/null +++ b/docs/audit/2026-09-26/TASK-CODEX-2.md @@ -0,0 +1,80 @@ +# Задание для Codex, круг 2: исправить ветку форматирования, перевести пилот на настоящего арендатора + +- Репозиторий: https://git.ochenstarik.ru/ochenstarik/krona-staff +- Основа: `codex/bootstrap-platform-foundation` (`f5ac179`) +- Итоги приёмки: `docs/audit/2026-09-26/ACCEPTANCE-2.md`. Основное задание `TASK-CODEX.md` остаётся в силе, этот файл его дополняет. + +## 1. Пересобрать ветку форматирования (сегодня) + +По данным приёмки, коммит `fd1ec3d` в ветке `codex/fix-format-baseline` содержит, кроме форматирования, функциональное изменение Antigravity. После нормализации prettier файлы `src/domain/sync/service.ts` и `tests/unit/sync.test.ts` совпадают с его исправлением S1. Это одновременно смешение тем и правка чужой зоны (AGENTS.md). Кроме того, при влитии обеих веток изменение придёт дважды. + +**Что сделать:** пересобрать коммит форматирования от `f5ac179` так, чтобы в нём было только `prettier --write`, без изменений в `src/domain/sync/**` и `tests/unit/sync.test.ts`. Исправление S1 должно приходить только из ветки Antigravity. Затем перебазировать `codex/fix-live-database` на новый коммит форматирования. + +**Готово, когда:** + +- `git diff <новый коммит>~1 <новый коммит> -w` после `prettier --check` не содержит изменений поведения; +- стенд Grok на `codex/fix-live-database` даёт K3/N2 и K4/N1 зелёными, а K13/SYNC-A и K13/SYNC-B — красными (они придут от Antigravity). + +## 2. Пилот — на настоящего арендатора + +По данным сессии «БП» (запросы только на чтение к `krona-staff-pilot-postgres-1`), под заглушкой `01J00000000000000000000000` сейчас лежит: + +| Таблица | Строк | +| ---------------------- | ----- | +| `staff_employees` | 51 | +| `staff_payroll_ledger` | 3 830 | +| `staff_work_items` | 3 353 | +| `staff_daily_metrics` | 2 894 | +| `staff_audit_log` | 49 | + +Остальные таблицы — единицы строк. + +Настоящий арендатор владельца в платформе — `01M2R6AC5652NPT3MG34DKN4ZP` («Сушигедза»). + +### 2.1 Чтобы заглушка не вернулась + +| Где | Что сделать | +| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | +| `deploy/pilot/setup.sh:20` | Не генерировать `STANDALONE_TENANT_ID` со значением-заглушкой: требовать его явно, без значения по умолчанию, с понятной ошибкой | +| `compose.yaml:16` | `${STANDALONE_TENANT_ID:?…}` вместо `${STANDALONE_TENANT_ID:-01J000…}` | +| `.env.example:14` | Оставить пустым с комментарием, откуда берётся значение (идентификатор организации в платформе) | +| `src/config.ts` | Вне режима разработки на loopback отклонять `01J00000000000000000000000` при старте как известную заглушку | + +### 2.2 Перенос уже внесённых данных + +Способ выбираешь сам: однократная перезапись `tenant_id` или переимпорт книги владельца. В обоих случаях обязательно: + +1. **Сначала резервная копия** (задача K18 из основного задания) и проверка, что из неё действительно можно восстановиться. Без этого перенос не начинать. +2. **Сначала прогон на копии** пилотной базы, затем на пилоте в согласованное окно, при остановленном приложении. Терминалы на это время копят отметки у себя. +3. **Перезапись выполняет привилегированная роль администратора БД**, а не роль приложения. RLS с `FORCE`, составные внешние ключи `(tenant_id, id)`, неизменяемые журналы (`staff_payroll_ledger`, `staff_audit_log`) — всё это нужно учесть явно: одна транзакция, внешние ключи переустанавливаются в ней же, триггеры неизменяемости отключаются только внутри неё. +4. **Скрипт в репозитории:** `scripts/rehome-tenant.mjs` (или аналог) с режимом `--dry-run` (только отчёт о количестве строк по таблицам) и отказом работать, если целевой арендатор уже содержит данные. +5. **Запись о переносе** в `staff_audit_log` нового арендатора: кто, когда, откуда, куда, сколько строк. + +**Готово, когда:** + +- `SELECT DISTINCT tenant_id` по всем таблицам со столбцом `tenant_id` возвращает только `01M2R6AC5652NPT3MG34DKN4ZP`; +- количество строк в каждой таблице до и после совпадает; +- сумма `amount_minor` в реестре начислений до и после совпадает; +- пилот под новым арендатором показывает тех же 51 сотрудника; +- тест изоляции арендаторов зелёный. + +Вывод `--dry-run` и итоговые запросы приложи к отчёту. Grok проверит скрипт на копии: данные под старым арендатором → перенос → сверка. + +### 2.3 Скрипт сопоставления с платформой + +`docs/PLATFORM-INTEGRATION.md` обещает сопоставление standalone ULID с записями Core, но скрипта нет. После пункта 2.2 перенос арендатора уже решён, поэтому скрипт сводится к заполнению `core_user_id` у сотрудников: + +- вход — выгрузка пользователей платформы (JSON или CSV: идентификатор пользователя Core и признак сопоставления — табельный номер, e-mail или телефон); +- режим `--dry-run` с отчётом: сопоставлены, не найдены, найдены неоднозначно; +- идемпотентность: повторный запуск ничего не меняет, существующие `core_user_id` не перезаписываются без флага; +- запись в журнал аудита. + +**Готово, когда** скрипт есть, покрыт тестом на реальной PostgreSQL и описан в `docs/PLATFORM-INTEGRATION.md`. + +## 3. Не делать + +**Не менять `PlatformIdentityAdapter` под нынешние неподписанные заголовки `x-tenant-id`**, которые платформа передаёт модулю. Договор будет с подписью: пункты А-5, С-6, С-7 плана платформы. Им занимается сессия «БП» в репозитории `business-platform`. Режим `platform` остаётся недоступным, пока платформа этого не сделает. + +## Порядок + +Пункт 1 → пункт 2.1 → резервная копия (K18) → пункт 2.2 на копии → 2.2 на пилоте → пункт 2.3. Параллельно продолжается основное задание: этап 2 — доступ и пилот, этап 3 — деньги (K5 и K6 теперь воспроизводятся по существу). diff --git a/docs/audit/2026-09-26/TASK-GROK-3.md b/docs/audit/2026-09-26/TASK-GROK-3.md new file mode 100644 index 0000000..3273ee6 --- /dev/null +++ b/docs/audit/2026-09-26/TASK-GROK-3.md @@ -0,0 +1,88 @@ +# Задание для Grok, круг 3: приёмка с интеграционными тестами, конфликты веток, сценарий переноса арендатора + +- Репозиторий: https://git.ochenstarik.ru/ochenstarik/krona-staff +- Основа: `codex/bootstrap-platform-foundation` (`f5ac179`) +- Итоги приёмки: `docs/audit/2026-09-26/ACCEPTANCE-2.md`. Ветка `grok/e2e-harness` (`ba59a48`) принята и вливается первой. + +## Итог прошлого круга + +Принято без замечаний по существу: стенд работает на Windows без правок, ID сопоставлены с аудитом, недостающие сценарии добавлены, приёмка ветки Codex совпала с моей до цифры (41 красный / 13 зелёных). Твоя находка про поведение в «стилевом» коммите Codex подтверждена. + +Одно упущение: в приёмке запускались только `tests/e2e`, а интеграционные тесты самих исполнителей — нет. Из-за этого два красных файла Antigravity прошли бы как «принято». + +## Правила — как раньше + +Только твоя зона: `tests/e2e/**`, `scripts/test/**`, `known-defects.json`, CI. В код исполнителей не коммитишь. Ветки исполнителей не меняешь — проверяешь в отдельных рабочих копиях. + +## 1. Приёмка = стенд + интеграционные тесты + конфликты + +Добавь в `scripts/test/` режим приёмки ветки, например `node scripts/test/accept-branch.mjs <ветка> [<ветка>…]`. Для каждой ветки он: + +1. Создаёт отдельную рабочую копию (`git worktree`) и накладывает текущий стенд. +2. Запускает `npm run check`. +3. Запускает **все** `tests/integration/*.test.ts` на реальной PostgreSQL. Считает файл красным по итоговой строке `Test Files`, а не `Tests`: ошибка в `beforeAll`/`afterAll` делает файл красным даже при зелёных тестах. +4. Запускает e2e-стенд и сравнивает с основой: что позеленело, что покраснело. +5. Проверяет попарно слияние всех переданных веток между собой и с основой (`git merge-tree --write-tree`). Печатает таблицу «чисто / конфликт, файлы». +6. Печатает итог в markdown, чтобы его можно было вставить в отчёт. + +**Роли базы.** Стенд пересоздаёт роли со случайными паролями на общем кластере — это ломает параллельную работу других. Сделай так, чтобы роли и пароли можно было передать переменными (`E2E_MIGRATOR_URL`, `E2E_APP_URL`) и стенд их тогда не трогал. По умолчанию — как сейчас. + +**Готово, когда** запуск на `antigravity/fix-reject-device-shifts antigravity/fix-sync-c0-bootstrap codex/fix-format-baseline` сам показывает то, что я нашёл вручную: + +| Что | Ожидаемый результат на сегодня | +| ------------------------------------- | -------------------------------------------------------------------- | +| `sync-rejection.test.ts` на `1df2019` | FAIL: `column "created_by" … does not exist` | +| `sync-bootstrap.test.ts` на `8baad55` | FAIL: `Called end on pool more than once` при `Tests 2 passed` | +| SYNC-C0 на `8baad55` | зелёный | +| AG reject + AG c0 | конфликт, `src/domain/sync/service.ts` | +| Codex format + AG c0 | конфликт | +| Codex format + AG reject | чисто (потому что в форматировании Codex лежит копия исправления S1) | + +## 2. Проверка «форматирование без поведения» + +Для ветки `codex/fix-format-baseline` (сейчас `513cdff`) добавь в режим приёмки проверку: для каждого изменённого файла взять версию из основы, прогнать через prettier и сравнить с версией из ветки. Любое отличие после нормализации — это поведение, а не стиль. Печатать список таких файлов. + +На сегодня ожидается: `src/domain/sync/service.ts` и `tests/unit/sync.test.ts` отличаются. После нормализации они совпадают с веткой Antigravity построчно. Я проверил это на `513cdff`: Codex перезалил ветку, но синхронизацию не убрал. + +**Готово, когда** проверка ловит `513cdff` и пропускает ветку, где остался только prettier. + +## 3. Храповик после каждого влития + +Когда владелец вливает ветку, отдельным коммитом убери из `known-defects.json` то, что стало зелёным на основе: + +| После влития | Убрать | +| --------------------------------- | ------------------------------- | +| `codex/fix-live-database` | K3/N2, K4/N1 | +| цепочка Antigravity (reject → c0) | K13/SYNC-A, K13/SYNC-B, SYNC-C0 | + +Коммит — только `known-defects.json`, в теле — вывод стенда на основе после влития. + +## 4. Сценарий переноса арендатора (для TASK-CODEX-2, п. 2.2) + +Codex пишет `scripts/rehome-tenant.mjs`: перенос всех данных пилота из заглушки `01J00000000000000000000000` в арендатора `01M2R6AC5652NPT3MG34DKN4ZP`. Подготовь проверку заранее, чтобы принять скрипт в день пуша: + +1. Наполнить базу под заглушкой: сотрудники, точки, смены, начисления в реестре, строки аудита, устройства синхронизации, push-подписки — по несколько строк в каждой таблице со столбцом `tenant_id`. Плюс второй, посторонний арендатор с собственными данными. +2. Снять контрольные цифры: число строк по каждой таблице и арендатору, `SUM(amount_minor)` реестра. +3. `--dry-run` — ничего не меняет, печатает те же числа. +4. Перенос ролью администратора БД. +5. Сверка: + - `DISTINCT tenant_id` — только новый арендатор и посторонний; + - число строк и суммы совпадают; + - данные постороннего арендатора не тронуты; + - в `staff_audit_log` нового арендатора есть запись о переносе; + - приложение ролью `krona_staff_app` под новым арендатором видит тех же сотрудников, а под старым — ничего; + - журналы остались неизменяемыми: после переноса `UPDATE` в `staff_payroll_ledger` отклоняется. +6. Повторный запуск отказывает: целевой арендатор уже содержит данные. + +Пока скрипта нет, сценарий красный с понятным сообщением и заносится в `known-defects.json` как `PILOT-REHOME`. Список таблиц со столбцом `tenant_id` бери из `information_schema.columns`, а не руками — так новая таблица без переноса сразу даст красный. + +## Порядок + +1 → 2 → прогнать приёмку по всем открытым веткам и выложить результат → 3 по мере влития → 4. + +## Отчёт + +- ветка и коммит; +- вывод режима приёмки по всем открытым веткам (`codex/*`, `antigravity/*`) на момент отчёта; +- что изменилось в `known-defects.json`; +- что не запускалось и почему.