feat(#190): метрики качества первички (AURORA-1759) #229

Merged
aep merged 45 commits from feat/190-ocr-metrics into main 2026-11-07 07:50:00 +03:00
Showing only changes of commit b20f3fa607 - Show all commits

View File

@ -227,6 +227,7 @@ PDF, точный вид выгрузки, разбиение на задачи.
| 05.11.2026 | Три новых enum-типа (`quality_outcome`, `quality_cause`, `quality_failure_kind`) — значения живут в схеме `SCHEMA` (`dkb`), НЕ в `METRICS_SCHEMA`, хотя используют их только таблицы `dkb_metrics` | `pg_enum()` (src/models/enums.py) без правок — единственный источник схемы enum'а; разводить enum'ы по двум схемам потребовало бы параметра схемы в фабрике без текущей пользы (Superset читает только таблицы, не типы) | таблица `dkb_metrics` зависит от типов в `dkb`; перенос схемы метрик на другой сервер БД без `dkb` невозможен без правки (сейчас design §10 этого не требует) |
| 05.11.2026 | Откат миграции 0012 НЕ удаляет схему `dkb_metrics` (оставляет её пустой), симметрично тому, что `SCHEMA` (`dkb`) никогда не удаляется в `env.py`/0001 | тест `test_upgrade_into_preprovisioned_schema_without_database_create` (api/tests/test_migrations.py) показал конкретный отказ: роль без `CREATE` на базу не могла бы создать `dkb_metrics` заново при повторном `upgrade head`, если бы платформа выдавала схему готовой, а откат её удалял; симметрия с `dkb` — тот же риск, то же решение | если отладочный откат до base оставляет пустую схему `dkb_metrics` — незначительный мусор, не ошибка |
| 05.11.2026 | В план (`docs/superpowers/plans/2026-11-05-quality-metrics-arm-core.md`) добавлена строка `**Ветка:**` (`feat/190-ocr-metrics`, worktree, issue, Jira) — без неё хук `require-plan.sh` блокировал любую правку в `api/src/**`, так как не находил имя ветки ни в одном файле `docs/superpowers/plans/*.md` | во всех остальных активных планах эта строка есть (сверено на `2026-10-28-corrections-table-ui.md`); её отсутствие — пропуск на этапе написания плана, не содержательное решение | минимальный — чисто метаданные плана |
| 06.11.2026 | Task 13: `web/src/api/types.ts` — `'QUALITY_METRICS'` дописан в конец union `PermissionObject` ОДНОЙ строкой (не многострочным форматом), итоговая строка ровно 140 символов — на пределе, но не сверх лимита ширины biome | сохраняет однострочный стиль, которым уже написана эта строка (и соседняя `PermissionAction`); многострочный вариант рассматривался как равноценная по типам альтернатива, выбор между ними непринципиален | нулевая — чисто форматирование, обе формы типобезопасно идентичны |
| 05.11.2026 | Коммит задачи 1 включает больше файлов, чем перечислено в брифе (`Makefile`, `README.md`, `api/.env.example`, `api/.env.test`, `api/alembic/env.py`, `api/scripts/check_dbml_vs_orm.py`, `api/scripts/dbml_parity.py`, `api/src/models/base.py`, `api/src/models/__init__.py`, восемь файлов `api/tests/test_*.py`) | все они требуют правки для согласованности версии v5.25 (имя DBML-файла в `Makefile`/README, `HEAD`-ревизия и допущение «всё в dkb» в тестах) или для поддержки второй схемы; список `git add` в брифе соответствовал более узкому ожидаемому дифу до того, как выяснилось, что `check_dbml_vs_orm.py` и тесты миграций не знают о второй схеме | коммит по списку брифа оставил бы `make test`/`make lint`/`make dbml-check` красными — хуже, чем более широкий, но согласованный коммит |
| 05.11.2026 | `api/contracts/quality-facts.schema.json` НЕ скопирован из `../docs/contracts/` в Task 1 (`test_contract.py::test_vendored_contracts_are_identical_to_docs` остаётся красным на этом файле) — копирование отложено на задачу, которая реально строит `payload` по этой схеме | файл уже есть в `../docs/contracts/` (сиблинг-репозиторий arm-ka-docs, работа по нему уже слита туда), а в `api/contracts/` копии нет и несовпадение чисто механическое; копия сейчас была бы мёртвой — Task 1 (схема/ORM/миграция) не читает и не пишет `payload`, валидация полезной нагрузки — логика, не схема БД, и не входит в её рамки | следующая задача может не заметить, что это отложено осознанно, и либо повторно принять то же решение не зная о нём, либо оставить контракт невендоренным навсегда |
| 06.11.2026 | Task 7 (`CONFIRMED`): нет сырого текста для сравнения у правки суммы/кода/шапки (`source_text`/`line_code_text`/`header_source[field].text` = `None`) — атрибуция «наш разбор» (`ours`), не пропуск правки. Уточняет направление решения 27.10.2026 «Спорное — в наш разбор» на случай «данных для сравнения нет вообще» — это НЕ тот же случай, что пример `1250\n1260` в исходном решении (там текст есть, но двусмысленный); `attribute_*` (Task 3) типизированы на `str`, случай отсутствия текста не предусматривают. Этим же решением подтверждается (не меняется) уже принятое 27.10.2026 направление для добавленной строки PDF (строка «Код добавленной строки ищется среди четырёхзначных токенов…», та же дата) — черновая реализация задачи 7 свела этот случай к вызову `attribute_added_row(code, raw_line_codes=(), is_excel=False)`, который из-за пустого `raw_line_codes` всегда возвращает «сервис», что противоречило уже принятому там направлению «совпадение с суммой даёт наш разбор»; исправлено прямой атрибуцией «наш разбор» для PDF-добавленных строк без вызова `attribute_added_row` (сырых токенов всё равно нет, инфраструктура их извлечения не построена — тот же пробел, что в строке 27.10.2026) | анти-цель §2/§5 («вина сервиса там, где ошиблись мы; спорные случаи — в наш разбор, не в сервис») распространяется и на случай, когда данных для сравнения нет вовсе: отсутствие доказательства ошибки сервиса не есть доказательство ошибки сервиса | если отсутствие сырого текста окажется частым, а не редким краевым случаем, `OUR_ERROR` может быть систематически завышен, а `SERVICE_ERROR` — недосчитан; метрика ослабнет как рычаг давления на поставщика распознавания (прямая цель §1), хотя остаётся безопасным дефолтом по анти-цели §2 |