Andrey Epifancev 8abbf50dd3 docs(#202): правки ревью ветки — is_scan, ОСВ без lines/values, retention raw/uploads
Критично: stored_file.is_scan был описан наоборот (true = цифровой вместо true = скан),
противоречил §14.6 и собственному имени столбца.

Важно: §14 не говорил явно, что ОСВ не получает lines/values в payload (теперь
dependentSchemas в контракте это ещё и проверяет); §14.3 не говорил, что
quality_outcome_fact.document_id не unique и метрики берут последний факт; амount в
контракте был float вместо decimal-строки (как money в recognition-result.schema.json);
правка "дата колонки" не имела счётчика — явно отнесена к fixes_header_*; правило
хранения S3 при удалении файла (OQ-179) не было согласовано между domain-rules,
architecture и spec.md (spec.md ошибочно утверждал, что uploads экспирится в отличие
от raw — не экспирится ни то, ни другое, если на них ссылается факт).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-11-05 15:02:48 +04:00

5.7 KiB
Raw Blame History

Spec Delta: quality-metrics-model

Purpose

Модель данных и контракт фактов качества распознавания первички (AURORA-1759): какие факты пишутся, в каком формате, как они переживают удаление/перераспознавание документа и чем отличаются от рабочих таблиц. Алгоритм подсчёта и атрибуции — context/05-domain-rules.md §14 (не дублируется здесь).

ADDED Requirements

Requirement: Факты качества — append-only и без FK на рабочие таблицы

quality_intake_fact, quality_outcome_fact, quality_failure_fact SHALL не иметь внешних ключей на document, stored_file, recognition_job, legal_entity, company_group — только простые uuid и денормализованные имена ЮЛ/ГК. Факты SHALL жить в отдельной схеме PostgreSQL (имя — настройка, по умолчанию dkb_metrics).

Scenario: Документ удалён после записи факта

  • WHEN документ, по которому есть quality_intake_fact, физически удалён (primary_files.delete)
  • THEN строка факта остаётся читаемой, её document_id не разрешается в существующий document, и запрос к факту не падает на отсутствующем FK

Requirement: quality_intake_fact — один факт на документ, кроме ОСВ без построчного снимка

Таблица SHALL иметь ровно один факт на document_id (unique). Для document_type = OSV payload SHALL не содержать lines/values — только счётчики строк и предупреждения OSV_*; для BALANCE/INCOME payload SHALL содержать построчный снимок (lines, values).

Scenario: Приём результата ОСВ

  • WHEN ядро мапит результат распознавания ОСВ в документ OSV
  • THEN quality_intake_fact.payload не содержит ключей lines/values, но содержит osv_warnings

Scenario: Приём результата ББ

  • WHEN ядро мапит результат распознавания в документ BALANCE
  • THEN quality_intake_fact.payload содержит lines и values построчно

Requirement: quality_outcome_fact — не unique на документ, метрики берут последний факт

Таблица SHALL допускать несколько строк с одним document_id (повторное подтверждение ОСВ после правки, исход *_AFTER_CONFIRM поверх прежнего). Любой читатель метрик SHALL использовать факт с максимальным outcome_at для данного document_id.

Scenario: Документ удалён после подтверждения

  • WHEN подтверждённый документ впоследствии удалён или вытеснен автозаменой
  • THEN пишется новый факт с outcome ∈ {DELETED_AFTER_CONFIRM, SUPERSEDED_AFTER_CONFIRM}, прежний факт (CONFIRMED/AUTO_CONFIRMED) не удаляется и не перезаписывается

Requirement: Сырой ответ ИС Сканирование регистрируется и не экспирится с файлом

s3_object SHALL поддерживать роль бакета raw; recognition_job.raw_s3_object_id SHALL ссылаться на зарегистрированный объект для image pipeline. Удаление stored_file SHALL НЕ устанавливать expires_at ни объекту с ролью raw, ни объекту uploads, на который ссылается quality_intake_fact (upload_s3_key) — оба нужны эталонному прогону (OQ-179). Объекты results и прочие uploads (без факта) — без изменений, expires_at = now() при удалении файла, как и раньше.

Scenario: Удаление файла с зарегистрированным сырым ответом

  • WHEN PDF-файл с заполненным recognition_job.raw_s3_object_id и существующим quality_intake_fact удаляется
  • THEN s3_object.expires_at остаётся NULL у объекта роли raw и у объекта uploads, на который ссылается факт; у объекта results того же файла expires_at проставляется now(), как для любого удаления того же файла

Requirement: Контракт payload не входит в make check этого репозитория

contracts/quality-facts.schema.json SHALL существовать как валидная JSON Schema (Draft 2020-12), но SHALL NOT быть подключена к scripts/validate_contracts.py — payload не является сообщением NATS-контракта распознавания.

Scenario: make check в arm-ka-docs

  • WHEN выполняется make check в этом репозитории
  • THEN quality-facts.schema.json не упоминается в выводе validate-contracts, и это не считается ошибкой