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

4.5 KiB
Raw Permalink Blame History

Сессия 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.pycall_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.unresolvedBatchGroupingResult — исправлено
  • Protocol расширен: +7 методов
  • build_classify_prompt: try/except вокруг db.prompts.get_active()
  • MemRepository.set_classification: +classify_raw, classify_input

Дедупликация + защита от careless user

content_hash

  • db/documents.pyinsert() принимает content_hash, get_by_hash() для проверки
  • services/upload.pystore_document() считает sha256 и пропускает дубликаты
  • convert_server.py — ALTER TABLE content_hash

Сортировка по doc_date

  • services/process.pysupps.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: passlogging.warning

UNRESOLVED вместо тихих no-op

  • db/spec_events.pyADD без имени → UNRESOLVED, UPDATE/DELETE с пустым target_hash → UNRESOLVED, неизвестный action → UNRESOLVED
  • _log_unresolved() — общая функция

Нормализация чисел и дат

  • services/metrics.py_to_decimal: пробелы → удалить, ,.
  • services/metrics.pynormalize_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 пунктов)