docs: OQ-117 индексы osv_entry, актуализация плана срезов и qa-guide

- 07-open-questions: OQ-117 — индексы osv_entry(parent_entry_id),
  osv_entry(recognition_job_id), stored_file(current_recognition_job_id); без них
  DELETE /files/{id} делает seq scan на проверке self-FK (I-1 final review, R-24);
  нужны DBML v5.16 и миграция 0004, блокер до прода / до подсреза 2d.
- 09-delivery-plan: итог make check-full приведён к фактическому прогону
  (e2e skipped в check-full, отдельный e2e 1 passed, fixtures 13 + 1 skipped);
  решения без обсуждения №1–52 (T12.6).
- qa-guide U16: до ERROR файл остаётся UPLOADED (ack нет) (T12.7).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
This commit is contained in:
Andrey Epifancev 2026-10-06 00:37:53 +04:00
parent 45ee08c0f8
commit 8c73fe941c
3 changed files with 6 additions and 3 deletions

View File

@ -122,6 +122,7 @@
| OQ-114 | `EntryOut` (API строк ОСВ) не отдаёт `is_modified`/`original_*`: панели правки подсреза 2d нужен признак правки аналитика (инвариант «первичка не мутируется»: правка — рядом, с аудитом). Добавить поля в схему и контракт API при проектировании 2d | arm-core Срез 2c: Task 9 (T9.7) | подсрез 2d | открыт: в 2c строк не правят, `is_modified = false` у всех |
| OQ-115 | Автозамена: если новый файл содержит лишь часть документов прежнего (прежний — ОСВ 60 и 51, новый — только 60), прежний уходит в `SUPERSEDED` **целиком**, документ 51 пропадает из списка файлов; в `FILE_REPLACE.description` о нём ничего нет. Подтвердить «замена файлом целиком» (OQ-06) для этого случая или заменять по документам | arm-core Срез 2c: Task 8 (T8.4) | Срез 2d (список файлов), Срез 4 (комплект документов) | допущение принято: замена файлом целиком, документы заменённого файла сохраняются в БД |
| OQ-116 | ОСВ Q2–Q4, признанная нарастающей по данным Q1 (сальдо на начало корня равно сальдо Q1, §1.5), получает предупреждение маппинга и поэтому остаётся `NEEDS_CHECK`, а не `RECOGNIZED` (буквально D-7/D-9 спеки: `RECOGNIZED` только без предупреждений). Верно ли, что аналитик подтверждает такие документы вручную, или нарастающая по данным — штатный случай без предупреждения (OQ-02, OQ-05) | arm-core Срез 2c: Task 7 (R-17, design №30) | Срез 2d (нагрузка на аналитика), §9.3 | допущение принято: `NEEDS_CHECK`; снять предупреждение — одна правка в `result_mapping.py` и правило статуса |
| OQ-117 | Индексы `osv_entry(parent_entry_id)`, `osv_entry(recognition_job_id)`, `stored_file(current_recognition_job_id)`: `DELETE /files/{id}` (и очистка файла при повторном маппинге) делает seq scan на проверке self-FK — на временной таблице 200 тыс. строк удаление документа в 1000 строк 8,6 с без индекса и 16 мс с индексом (замер в psql на временной таблице, final review); при ~3 млн строк DELETE ≈ 2 мин → HTTP-таймаут и долгое удержание блокировок. Требуется DBML v5.16 + миграция 0004. Решает владелец (источник истины — DBML) | arm-core Срез 2c: final review (I-1, R-24, design №51) | `DELETE /files/{id}`, повторный маппинг; подсрез 2d (UI удаления), прод | открыт, **блокер: до прода / до подсреза 2d (UI удаления)**; в 2c индексов нет |
Служебные идентификаторы в DBML/аналитике: `ANL-nnn` — замечания аналитика к макету; `ARCH-nnn` — архитектурные решения;
`DECISION-n` — решения по модели; `FIX-nn` — исправления дефектов v4.

View File

@ -136,9 +136,11 @@ Change'и: `arm-core/openspec/changes/slice-2c-osv-ingest` (issue arm-core#14,
`POST /documents/{id}/confirm`, `DELETE /files/{id}` (запрет при `CONFIRMED` и при заменивших другие, `expires_at` у объектов S3).
- **Проверки на реальных данных:** golden — все 82 снимка парсера (85 документов, 13 510 строк, ≈ 4 с) разобраны, инварианты
спеки выполняются; сквозной прогон `make e2e` с реальным `tabular-parser` через compose (ОСВ_66 за 2024 → `PROCESSED`, 9
строк). Итог `make check-full`: 900 unit, 437 integration, e2e 1, `-m fixtures` 13 (+1 e2e skip без профиля).
строк). Итог `make check-full` (контроллер, HEAD f9b8a21): EXIT 0 — unit 900, integration 437, e2e skipped (профиль
`services` не поднят), docker-build и web-check OK; отдельный прогон e2e с реальным `tabular-parser`: 1 passed (4,3 с);
`-m fixtures`: 13 passed + 1 skipped.
- **Решения без обсуждения** — `arm-core/openspec/changes/slice-2c-osv-ingest/design.md`, разделы «Decisions made without
discussion» (№1–50). Правила — `05-domain-rules.md` §1.3, §1.5, §3 п. 4, §9.2–9.5; архитектура — `03-architecture.md`
discussion» (№1–52). Правила — `05-domain-rules.md` §1.3, §1.5, §3 п. 4, §9.2–9.5; архитектура — `03-architecture.md`
(«Цикл маппинга результата и порядок блокировок»); QA — `dev/qa-guide.md` §6.6.
- **Закрыты OQ:** 67, 69, 70, 59, 109. **Открыты новые:** OQ-110 (удаление файла после консолидаций), OQ-111 (ретеншн S3
при удалении), OQ-112 (остаточные объекты e2e), OQ-113 (полнота субсчетов seed), OQ-114 (`is_modified` в `EntryOut`),

View File

@ -297,7 +297,7 @@ curl -s -X DELETE "localhost:8000/api/v1/files/$FILE" -H "$H" -w '%{http_code}\n
| U13 | ka_go | `POST /documents/{id}/confirm` для документа первого файла из U10 (`SUPERSEDED`), до удаления в U12 | 409 `FILE_SUPERSEDED` |
| U14 | expert | `POST .../files` | 403 (нет `DOCUMENT_EDIT`); `GET /files/{id}` — 200 (есть `DOCUMENT_VIEW`) |
| U15 | client_manager | `GET /files/{id}` файла ЮЛ другого филиала | 404, тело как у случайного uuid |
| U16 | ka_go | остановить tabular-parser, загрузить новый файл | `status` остаётся `UPLOADED`/`PROCESSING` ~2 мин (3 повтора по 30 с), затем `ERROR`, `job.error_code` заполнен; `DELETE` такого файла — 204 |
| U16 | ka_go | остановить tabular-parser, загрузить новый файл | `status` остаётся `UPLOADED` (ack нет — в `PROCESSING` файл не переходит) ~2 мин (3 повтора по 30 с), затем `ERROR`, `job.error_code` заполнен; `DELETE` такого файла — 204 |
Аудит (6.4 — запрос из psql): после U1 — `FILE_UPLOAD`; U8 — `DOCUMENT_CONFIRM`; U10 — `FILE_REPLACE` с пустым `user_id`
(системное событие) и `description`, где перечислены документы заменённого файла; U12 — `FILE_DELETE` с карточкой файла