# Полная регрессия перед выкладкой Один прогон проверяет `main` всех репозиториев workspace так, как его увидит контур: проверки качества каждого репозитория, интеграционные и сквозные тесты, образы, стенд с нуля со сценарием по API и контрольными цифрами, UI-смоук и прогон парсера по банку первички. В отличие от `make check-full`, прогон не останавливается на первой ошибке: перед выкладкой нужна вся картина. Задача — arm-ka-docs#179. ```bash make regress # из корня docs, workspace — родитель docs scripts/regression/regress.sh --only stand,ui # только часть этапов (список: --list) scripts/regression/regress.sh --skip bank --keep-stand ARM_KA_WORKSPACE=~/projects/awp-ca scripts/regression/regress.sh # из worktree docs: проверяются основные checkout'ы ``` Результат — `admin/regression/<дата_время>/` в workspace (`--out` — другой каталог; повторный запуск этапов в тот же каталог заменяет только их строки): `summary.md` — итог, `logs/<этап>.<шаг>.log`, `stand/` (отчёт сценария, снимки свода, шахматки и форм, экспорт xlsx), `ui/` (скриншоты экранов), `bank/` (результаты парсера по doc-bank). Каталог содержит производные реальных данных — в git не класть. Код возврата: `0` — всё зелёное, `1` — есть красные шаги, `2` — preflight не пройден. ## Этапы | Этап | Что проверяет | |---|---| | `preflight` | все репозитории (`docs`, `fixtures`, `arm-statements`, `arm-core`, `tabular-parser`, `scan-gateway`) на `main`, равны `origin/main`, без правок; Docker, `uv`, `npm`, `openspec`; нет чужих потребителей общей NATS (контейнеры сервисов `arm-ka`, ядро на `:8000`) — иначе интеграционные тесты и e2e падают по таймауту. Не пройден — прогон останавливается (`--allow-dirty` — прогнать как есть, с пометкой в итоге) | | `venv` | `make venv` во всех репозиториях (окружения по текущим зависимостям) | | `static` | `make check` docs (контракты, OpenSpec, снимок контура, `sync-statements`), обзор свежести копий `arm_statements`, `lint` и `test` arm-statements и трёх сервисов, `dbml-check` ядра | | `web` | фронт `arm-core/web` в **чистой копии** во временном каталоге: `npm ci` (как пайплайн; при расхождении lock с `package.json` — красный, копия доустанавливается `npm install`), biome, `tsc`, ESLint + Prettier, vitest, сборка. `main` не меняется | | `integration` | инфраструктура общего compose-проекта `arm-ka` (`make up`), `check-infra`, `test-integration` трёх сервисов; у ядра — с циклом миграций `upgrade → downgrade base → upgrade`. Тесты создают свои БД, рабочую `armka` не трогают | | `fixtures` | реальные данные парсера: `test-fixtures` (golden, покрытие словарей) и `golden-check` tabular-parser | | `images` | сборка образов `arm-core:dev`, `tabular-parser:dev`, `scan-gateway:dev` из `main` (профиль `services`) | | `e2e` | сквозной тест ядра с настоящим tabular-parser (контейнер в `arm-ka`, после теста возвращается в прежнее состояние); пропуск теста — красный | | `stand` | **изолированный стенд с нуля**: compose-проект `arm-ka-regress` на своих портах (ядро `:18000`, парсер `:18001`, шлюз `:18002`, PostgreSQL `:15432`, NATS `:14222`, MinIO `:19000`), миграции и `seed --dev`, эмулятор ИС Сканирование; сценарий `stand_scenario.py` по `expected.json` | | `ui` | dev-сервер фронта против стенда, Playwright (`ui_smoke.py`) по основным экранам: исключения страницы, ответы `/api` ≥ 400, пустые экраны, скриншоты | | `bank` | CLI tabular-parser по всем табличным файлам `doc-bank` (если он есть) и сравнение с прошлым прогоном (`parser_bank.py`) | Стенд снимается (`down -v`) после этапа `ui`; `--keep-stand` оставляет его для ручной проверки. Общий стенд `arm-ka` (данные, тома, порты) этапы `stand` и `ui` не трогают; `integration` и `e2e` пользуются его инфраструктурой. ## Сценарий стенда и контрольные цифры `expected.json` — данные, а не код: ГК/ГСК dev-seed, пользователи, по сценарию — файлы фикстур для загрузки, `summary` свода, пробелы, контрольные строки с суммами, пары шахматки, ожидаемые формы ББ/ОФР. Источники цифр — `dev/qa-guide.md` §7.1–7.3 (РБ 2024 Q3, посчитаны вручную по файлам), прогоны 08.10 и 14.10.2026 (РБ 2025 Q1) и `test_intercompany_matrix_golden` ядра. Новая цифра — только с причиной в описании PR. На каждый сценарий: создание консолидации (и повтор — 409), блокировка, загрузка файлов в версию, ожидание распознавания (PDF — через эмулятор ИС), подтверждение ОСВ-документов, `summary`, пробелы, контрольные строки, свод постранично = `rows_total`, экспорт xlsx (строки листов «Сводная ОСВ» и «Пробелы», `Content-Disposition`), чек-лист, шахматка по всем предустановленным правилам, результирующая таблица, итоги элиминации, формы ББ/ОФР; в конце — права (эксперт читает, но не блокирует — 403) и 404. Помимо ручных цифр, сценарий сохраняет **снимки** (`stand/snapshots/`: весь свод построчно, шахматка, формы, документы) и сравнивает их со снимками последнего прошлого прогона в `admin/regression/`. Расхождения не красные — их нужно просмотреть: изменение свода или шахматки между выкладками должно объясняться задачами выкладки. ## Банк первички `parser_bank.py` разбирает все файлы `doc-bank/index/index.csv` с маршрутом «парсер» и пишет отпечаток каждого документа (тип, статус, счёт, период, число строк, сумма денежных колонок, коды предупреждений). База сравнения — последний прошлый прогон (`--bank-baseline DIR` — явно), на первом прогоне — колонка `parse_status` индекса (прогон 20.10.2026). Итог — переходы «хуже» (кандидаты в регрессию, таблица в `summary.md`), «лучше» и «тот же статус, другой разбор» (`bank/transitions.json`). Этап не красный по переходам: регрессия это или исправление — решает человек. ## Если шаг красный Сначала лог шага (`logs/<этап>.<шаг>.log`, путь — в `summary.md`). Частые причины не в коде: занятая NATS (preflight `shared-consumers`), не поднятая инфраструктура, сеть для `npm ci` / `uv`. Шаг можно перезапустить отдельно: `--only <этап> --out <тот же каталог>`.