Files
contracts-flask/History/session-02-fixes-2026-06-28.md
T

86 lines
4.5 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.
# Сессия 2026-06-28 — Итоги
## Decoupling пайплайна (Ф1-Ф4)
### Ф1 — Контракты + upload decouple
- `deploy/contracts.py` — 5 dataclass'ов: ParseResult, ClassifyResult, GroupingResult, BatchGroupingResult, CompareOp
- `deploy/services/upload.py` — выделены `parse_multipart()` и `store_document()`
- `handle_upload` теперь тонкий HTTP-handler
### Ф2 — LLM Client DI
- `deploy/services/llm_client.py` — протокол `LLMClient.complete(prompt)->str` + `HttpxLLMClient` + `FakeLLMClient`
- `deploy/services/llm.py``call_llm(..., llm_client=None)` — DI с обратной совместимостью
- `deploy/services/classify.py``_call_llm_classify(..., llm_client=None)` + `classify_batch(..., llm_client=None, repo=None)`
### Ф3 — Repository facade
- `deploy/repository.py` — Protocol `Repository`, `PgRepository`, `MemRepository` (17 методов)
### Ф4 — pytest
- `deploy/conftest.py` — фикстуры: `fake_llm`, `mem_repo`, `sample_docx_bytes`
- `deploy/tests/unit/test_contracts.py` — 13 тестов (contracts, garbage, multipart)
- `deploy/tests/unit/test_llm_repo.py` — 9 тестов (FakeLLM, MemRepository)
- `deploy/tests/unit/test_classify_batch.py` — 4 теста (garbage×2, LLM, no_pending)
- **26/26 PASS**
### Баги (ревью Opus)
- #1 Двойная сериализация JSON в `PgRepository.set_document_parsed` — исправлено
- #2 `db_docs``_db` в `classify_batch` — исправлено (6 вызовов)
- #3 `ParseResult.from_row` element_count=0 — исправлено
- #4 `GroupingResult.unresolved``BatchGroupingResult` — исправлено
- Protocol расширен: +7 методов
- `build_classify_prompt`: try/except вокруг `db.prompts.get_active()`
- `MemRepository.set_classification`: +`classify_raw`, `classify_input`
---
## Дедупликация + защита от careless user
### content_hash
- `db/documents.py``insert()` принимает `content_hash`, `get_by_hash()` для проверки
- `services/upload.py``store_document()` считает `sha256` и пропускает дубликаты
- `convert_server.py` — ALTER TABLE `content_hash`
### Сортировка по doc_date
- `services/process.py``supps.sort(key=lambda s: (doc_date, created_at))`
### date_start в name_hash
- `db/spec_events.py``_hash(name, date_start)` — хеш включает период, разные периоды = разные строки
### ZIP-защита
- `services/unzip.py` — лимит 500 файлов, 500 MB, проверка ratio (100x), санитизация имён (cp437→utf8, path-traversal)
### Статус «не распознан»
- `services/upload.py` — supplement НЕ создаётся при ошибке парсинга, `warning` при пустом результате
- `try/except: pass``logging.warning`
### UNRESOLVED вместо тихих no-op
- `db/spec_events.py``ADD` без имени → UNRESOLVED, `UPDATE/DELETE` с пустым `target_hash` → UNRESOLVED, неизвестный `action` → UNRESOLVED
- `_log_unresolved()` — общая функция
### Нормализация чисел и дат
- `services/metrics.py``_to_decimal`: пробелы → удалить, `,``.`
- `services/metrics.py``normalize_date()`: DD.MM.YYYY → YYYY-MM-DD
- `db/spec_events.py``_hash` применяет `normalize_date`
---
## Архитектура check.kube5s.ru
- ВМ: порт 8777, БД `contracts_check`, код `~/contracts-check/`
- Nginx: SSL (letsencrypt), CORS, proxy headers
- Managed Flask: `contracts-flask.git`, `site/` + `Dockerfile`
- VM_API = `https://check.kube5s.ru`
- Полная изоляция от прода (contracts.kube5s.ru)
---
## Файлы History
- `architecture.md` — архитектура Flask-стека
- `session-01-init-2026-06-27.md` — создание стека
- `opus-decoupling-plan-2026-06-28.md` — задание Opus
- `opus-decoupling-review-2026-06-28.md` — рецензия DeepSeek
- `opus-dialog-2026-06-28.md` — полный диалог DeepSeek↔Opus
- `opus-review-request-2026-06-28.md` — запрос ревью
- `opus-review-2-request-2026-06-28.md` — повторное ревью
- `opus-review-response-2026-06-28.md` — результат ревью
- `opus-dedup-2026-06-28.md` — дедупликация + засады (15 пунктов)