4.5 KiB
4.5 KiB
Сессия 2026-06-28 — Итоги
Decoupling пайплайна (Ф1-Ф4)
Ф1 — Контракты + upload decouple
deploy/contracts.py— 5 dataclass'ов: ParseResult, ClassifyResult, GroupingResult, BatchGroupingResult, CompareOpdeploy/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+FakeLLMClientdeploy/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— ProtocolRepository,PgRepository,MemRepository(17 методов)
Ф4 — pytest
deploy/conftest.py— фикстуры:fake_llm,mem_repo,sample_docx_bytesdeploy/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_rowelement_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 TABLEcontent_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-DDdb/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— задание Opusopus-decoupling-review-2026-06-28.md— рецензия DeepSeekopus-dialog-2026-06-28.md— полный диалог DeepSeek↔Opusopus-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 пунктов)