Files
contracts-flask/History/sonnet-review-comparison-only-2026-08-27.md
T
“Naeel” f9745e5c6b
Deploy contracts-flask / validate (push) Canceled after 0s
Document comparison review findings
2026-08-27 11:24:32 +03:00

232 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Промпт для Соннета: code review только собственно сверки
Нужно провести строгий code review **только той части системы, которая выполняет собственно сверку документов после формирования группы**.
Не анализируй и не ревьюируй upload, WebDAV/VM upload, ZIP-распаковку, выбор папки, дедупликацию файлов, парсинг DOC/DOCX, garbage-фильтры, классификацию документов, определение типа документа, matching/grouping документов и UI загрузки. Эти части находятся вне области данного ревью.
## Контекст
Система получает уже сформированную группу договора и связанных документов. Затем она должна:
1. определить порядок документов группы;
2. получить текущую спецификацию;
3. передать текущую спецификацию и текст очередного документа в LLM;
4. получить операции `ADD`, `UPDATE`, `DELETE`, `UNRESOLVED` или режим `full_replace`;
5. корректно транслировать ссылки LLM на строки текущей спецификации;
6. применить операции к БД и сохранить историю событий;
7. отдать прогресс и результат через SSE;
8. показать пользователю фактический итог сверки.
Особенно проверь, что система не выдаёт успешный результат, если часть операций или документов фактически не обработана.
## Файлы для обязательного изучения
Изучи только эти файлы и их прямые зависимости, необходимые для понимания сверки:
1. `contracts-flask/site/services/process.py`
- основной pipeline сверки;
- порядок документов;
- получение текущей спецификации;
- подготовка текста документа;
- вызов LLM;
- трансляция `target_id` в `target_hash`;
- обработка `full_replace`;
- применение операций;
- арифметическая проверка;
- SSE-события логического pipeline.
2. `contracts-flask/site/routes/pipeline_bp.py`
- endpoint `GET /process-v2`;
- генерация SSE;
- heartbeat;
- закрытие/обрыв соединения;
- преобразование исключений в SSE-события;
- различие HTTP-ошибки до начала стрима и ошибки внутри стрима.
3. `contracts-flask/site/static/compare.js`
- `startCompareSSE()`;
- обработка `extract_start`, `llm_done`, `applied`, `extract_error`, `apply_error`, `done`, `error`;
- обработка `EventSource.onerror`;
- закрытие EventSource;
- соответствие frontend-событий backend-событиям.
4. `contracts-flask/site/static/app.js`
- функции запуска сверки группы;
- вызов `/api/apply-groups`;
- получение `contract_id`;
- запуск `/process-v2`;
- обработка success/error/connection error;
- изменение состояния группы после завершения.
5. `contracts-flask/site/services/llm.py`
- фактический вызов LLM для сверки;
- формат prompt и ответа;
- timeout/retry;
- обработка невалидного ответа;
- возможная потеря или искажение операций.
6. `contracts-flask/site/llm_prompt.py`
- prompt сверки;
- формат текущей спецификации;
- формат ожидаемых операций;
- ограничения для `ADD`, `UPDATE`, `DELETE`, `UNRESOLVED`, `full_replace`.
7. `contracts-flask/site/db/spec_events.py`
- `reset()`;
- `clear_current()`;
- `apply_ops()`;
- транзакции и атомарность;
- сохранение истории;
- статусы применённых и неразрешённых операций;
- поведение при частичной ошибке.
8. `contracts-flask/site/db/spec_current.py`
- получение текущих строк спецификации;
- идентификаторы и `name_hash`;
- получение `elements_json`;
- согласованность данных между текущим состоянием и историей.
9. `contracts-flask/site/db/supplements.py`
- только функции, используемые `process.py` для получения документов уже сформированной группы;
- порядок и фильтрация документов;
- отсутствие/дублирование документов.
10. `contracts-flask/site/services/metrics.py`
- `check_arithmetic()`;
- что именно проверяется;
- может ли ошибка арифметики повлиять на результат;
- почему проверка не должна маскировать ошибку применения.
## Тесты для обязательного изучения
1. `contracts-flask/tests/test_process_pipeline.py`
- какие сценарии реально покрыты;
- корректность `full_replace`;
- корректность трансляции `target_id`;
- отсутствие тестов на реальные SSE и ошибки LLM.
2. `contracts-flask/tests/test_grouping.py`
- только часть, необходимая для понимания структуры группы, передаваемой в `apply_groups`.
3. `contracts-flask/tests/test_metrics.py`
- только тесты арифметической проверки, относящиеся к операциям сверки.
4. Найди все остальные тесты, которые напрямую вызывают `run_pipeline`, `apply_ops`, `process-v2` или `startCompareSSE`, и включи их в анализ только если они действительно относятся к собственно сверке.
## Что проверять
### 1. Корректность алгоритма сверки
- Не теряется ли первая спецификация или базовое состояние.
- Правильно ли строится `current_spec` перед каждым следующим документом.
- Гарантирован ли правильный порядок обработки документов.
- Не зависит ли порядок от нестабильного `created_at` или формата даты.
- Корректно ли работает переход между несколькими документами группы.
- Не дублируются ли строки при повторном запуске.
- Корректно ли работает `full_replace` при уже существующих строках.
- Может ли `full_replace` удалить корректные данные при ошибочном/неполном ответе LLM.
### 2. Операции LLM
- Как `target_id` переводится в фактический идентификатор строки.
- Что происходит при `r0`, `r999`, `rX`, отсутствующем `target_id`, неверном `target_hash`.
- Не может ли LLM обновить не ту строку из-за изменения порядка строк.
- Что происходит с неизвестными действиями.
- Что происходит с отсутствующими полями `name`, `price`, `qty`, `sum`, `date_start`.
- Не приводит ли частично валидная операция к тихой потере данных.
- Сохраняется ли исходный ответ LLM и prompt для аудита.
- Как обрабатываются пустой, обрезанный, markdown-обёрнутый или частично повреждённый JSON-ответ.
### 3. БД, транзакции и атомарность
- Атомарно ли применяются операции одного документа.
- Что происходит, если пятая операция из десяти падает.
- Может ли current state измениться, а event history не сохраниться, или наоборот.
- Не приводит ли `reset()` к потере истории при повторном запуске.
- Различаются ли `applied`, `unresolved`, `failed` и действительно ли эти статусы отражают результат.
- Безопасен ли параллельный запуск двух сравнений одного договора.
- Безопасен ли одновременный запуск сравнений разных групп.
- Есть ли race condition между `apply-groups`, `/process-v2` и frontend state.
### 4. SSE и сетевые ошибки
- Совпадает ли событие завершения backend (`complete` или `done`) с событием, которое ожидает frontend.
- Может ли frontend навсегда оставить сравнение в состоянии `⏳`.
- Что происходит при disconnect после `applied`, но до события завершения.
- Что происходит при heartbeat без данных.
- Может ли `EventSource.onerror` ошибочно объявить ошибку после нормального закрытия.
- Показывает ли UI частичный результат как полный.
- Есть ли таймаут на клиенте и сервере.
- Возвращается ли пользователю причина ошибки LLM/API, а не только «Ошибка соединения».
- Не теряются ли последние SSE-события из-за proxy buffering.
### 5. Числовая и предметная корректность
- Проверяется ли арифметика `price * qty = sum` до применения и после применения.
- Как обрабатываются `None`, строки с запятой, целые/дробные числа, отрицательные значения и большие числа.
- Не изменяет ли арифметическая проверка данные или только логирует ошибку.
- Может ли LLM вернуть арифметически неверную операцию, которая всё равно попадёт в current state.
- Сохраняется ли точность Decimal/float.
- Как обрабатываются даты и отсутствие даты.
### 6. Повторяемость и идемпотентность
- Что произойдёт при повторном нажатии «Сравнить эту группу».
- Можно ли безопасно повторить сравнение после сетевого обрыва.
- Будут ли повторно добавлены те же строки.
- Как отделяется новый запуск от предыдущей истории.
- Есть ли идентификатор запуска и защита от повторного применения одного ответа.
## Обязательные вопросы от ревьюера
Ответь отдельно на следующие вопросы, даже если для ответа придётся изучить прямую зависимость:
1. Почему в реальном тесте один допник смог попасть в группу без базового договора, и может ли собственно pipeline сверки безопасно обработать такую неполную группу?
2. При каком именно условии `run_pipeline()` считает сверку успешной?
3. Может ли pipeline отправить `complete`, если один документ дал `extract_error` или часть операций не применилась?
4. Почему backend использует событие `complete`, а frontend-код может ожидать `done`? Это реальный баг или только устаревший комментарий/другая ветка?
5. Если LLM вернул `full_replace` с пустым `ops`, будет ли текущая спецификация очищена? Должно ли так происходить?
6. Если `apply_ops()` применил только часть операций, как это отражается в SSE и UI?
7. Есть ли транзакция, гарантирующая согласованность `spec_current` и `spec_events`?
8. Можно ли повторно запустить `/process-v2` для того же `contract_id` без дублирования или повреждения результата?
9. Что происходит при одновременном сравнении двух групп, относящихся к одному договору?
10. Как система отличает «LLM вернул корректный пустой результат» от «LLM вернул повреждённый/неполный ответ»?
11. Какие операции считаются `UNRESOLVED`, где они сохраняются и видит ли их пользователь?
12. Может ли `check_arithmetic()` обнаружить ошибку, но pipeline всё равно завершиться успешно?
13. Какой минимальный набор интеграционных тестов нужен для доказательства корректности реальной сверки?
14. Какие риски остаются именно в собственно сверке после исключения upload/classify/grouping из области анализа?
## Формат отчёта
Пиши отчёт в формате code review.
Сначала findings, отсортированные по серьёзности:
- `BLOCKER` — возможна потеря/порча данных или ложный успешный результат сверки;
- `HIGH` — неверное применение операций, нарушение атомарности, повторное применение или потеря результата;
- `MEDIUM` — ошибочное отображение статуса, частичный результат, нестабильность или отсутствие важной защиты;
- `LOW` — локальная проблема качества, диагностики или сопровождаемости.
Для каждого finding укажи:
- severity;
- файл и конкретный символ/участок кода;
- точную последовательность, которая приводит к проблеме;
- воспроизводимый сценарий;
- фактический ущерб;
- минимальное исправление;
- обязательный тест.
Не предлагай изменения вне области собственно сверки. Не исправляй код самостоятельно. Не делай общий обзор всего проекта. Если findings нет, напиши это явно и перечисли оставшиеся пробелы тестирования.
## Жёсткое ограничение по стоимости
Не пиши код, патчи, diff и готовые реализации. Не изменяй файлы и не выполняй команды. Твоя задача — только code review: факты, findings, доказательства, вопросы и минимальные рекомендации словами. Любые предлагаемые исправления описывай концептуально, без реализации.
В конце добавь:
1. ответы на 14 обязательных вопросов;
2. таблицу покрытия тестами;
3. минимальный план исправлений, если они нужны;
4. список файлов, которые действительно были изучены.