Files
LegacyHUB/docs/ADR-shared-core.md
Vadim Malanov 4fcec8039b
Some checks failed
CI / Backend (lint + tests + compose) (push) Has been cancelled
CI / Frontend (lint + type-check + build) (push) Has been cancelled
chore: pin document recognition engine
2026-06-25 11:43:29 +03:00

76 lines
5.7 KiB
Markdown
Raw Permalink 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.
# ADR: Extract OCR / Markdown / Search into a shared `teamhub_core` engine
Status: accepted (staged, recognition engine extracted) · 2026-06-15 · scope: `legacy-knowledge-indexer` + `TeamHUB/Engines`
## Контекст
Платформа (08_DECISIONS D10, CONVENTIONS «Shared engines», plans/LegacyHUB.md §4)
требует вынести проверенный пайплайн LegacyHUB (OCR → Markdown → hybrid search)
в переиспользуемое **stateless** ядро, чтобы QMS-Hub и MailHUB потребляли его, а
не дублировали. LegacyHUB остаётся эталоном и первым потребителем.
## Решение
Ядро `teamhub_core` живёт в `C:\Users\manag\TeamHUB\Engines\engines/teamhub_core/`
(НЕ в этом репозитории, НЕ в `TeamHUB-Platform`) и потребляется как pinned
versioned dependency / git submodule (D10). Извлечение делается поэтапно, чтобы
не дестабилизировать работающий эталон; на каждом шаге тесты зелёные.
### Границы ядра (stateless)
| Пакет ядра | Источник в LegacyHUB | Содержимое |
|---|---|---|
| `ingest` | `app/ingestion/{ocr,docling_extractor,chunker,normalizer,quality,table_processor,figure_processor}.py` | OCRmyPDF, Docling, chunker, quality-flags, нормализация (сохранение ГОСТ/ID) |
| `search` | `app/indexing/{embeddings,reranker,hybrid_search,opensearch_client,qdrant_client}.py` | BGE-M3, reranker, `run_search`=RRF(BM25,dense)+rerank, bootstrap индексов |
| `storage` | `app/storage/{minio_client,artifacts}.py` | put/get + retry, `ensure_artifact` |
| `contracts` | search/citation Pydantic-типы | контракт поиска/цитирования |
| `obs` | `app/common/json_logger.py` | JSON-логи с маскированием (уже app-agnostic) |
Персистентность (`app/db/*`, Alembic), эмиссия событий, имена бакетов/индексов/
коллекций и REST-роуты ОСТАЮТСЯ в модуле.
## Что уже сделано для расцепления (этот репозиторий)
- **Имена параметризованы.** `opensearch_index_chunks`, `qdrant_collection_chunks`,
все `minio_bucket_*` читаются из `Settings` (env-aliases). Дефолты приведены к
платформенному стандарту (`teamhub-legacyhub-*`); потребитель (QMS/MailHUB)
переопределяет их через env, не трогая код. Жёстко вшитых `legacyhub-*` имён в
логике больше нет.
- **`run_search` не зависит от БД.** `app/indexing/hybrid_search.py` импортирует
только контракты (`app/api/schemas`), `Settings` и клиентов индексации — слой
поиска уже stateless по отношению к Postgres/ORM.
- **`obs`-ядро готово.** `app/common/json_logger.py` написан без app-specific
импортов и переносится в ядро как есть.
- **Плейтменеджмент секретов вынесен из дефолтов** (см. `_enforce_secret_policy`).
- **Первый физический engine вынесен.** OCRmyPDF/Tesseract + Docling recognition
теперь живут в `TeamHUB/Engines/engines/teamhub-document-recognition-engine`;
LegacyHUB оставляет `app/ingestion/ocr.py` и
`app/ingestion/docling_extractor.py` как тонкие адаптеры и source metadata в
`app/ingestion/ENGINE_SOURCE.md`.
## Остаточные шаги (staged, координируются с QMS/MailHUB)
1. Поддерживать LegacyHUB pin на `teamhub-document-recognition-engine-v0.1.0`
до следующего совместимого release.
2. Перенести `contracts` (типы поиска/цитирования) из `app/api/schemas` в
`teamhub_core.contracts`; `app/api/schemas` ре-экспортирует их для совместимости.
3. Перенести `search`/`ingest`/`storage`/`obs` в ядро; `run_search` принимает
имена индекса/коллекции/бакетов аргументами/конфигом, а не глобальным
`Settings` модуля.
4. Переключить LegacyHUB на ядро как pinned submodule; `app/indexing`,
`app/ingestion` становятся тонкими адаптерами. Временная vendored-копия — только
с задокументированным сроком удаления.
5. Контракт-тесты ядра единым сьютом (chunker/quality/hybrid/hashing/duplicates).
6. Подключить QMS-Hub (свои бакеты `teamhub-qms-*`, индекс `qms_chunks`, своя PG) и
MailHUB (поиск по письмам/вложениям) как вторых потребителей.
## Последствия
- Физический вынос затрагивает три репозитория (LegacyHUB, Engines, потребители) и
выполняется отдельной скоординированной работой; в этом проходе закрыта
**готовность к расцеплению** (параметризация имён, stateless `run_search`,
app-agnostic obs-core) и зафиксирован план.
- Риск регрессий минимизируется поэтапностью и зелёным тест-сьютом на каждом шаге.
См. также `docs/ADR-layers.md` (маппинг слоёв) и `docs/dispatch-contract.md`.