Кандидат на удаление — поле задумывалось как metadata-сигнал «документ представляет historical records», ни в Node.js, ни в .NET не доросло до runtime branching, прокидывается насквозь без потребителя.
Контекст
Флаг historical: boolean | null появился в .NET migration 20250707222738_AddSummaryForTestContent (2025-07-07) — одной волной с Summary / MedicalAnalysis / Human. Все четыре поля написал recognition LLM (recognize_gpt) в test_info секцию JSON-ответа, миграция бэкфилила колонки из FormattedContent::jsonb -> 'test_info'.
Замысел (по контексту migration + промптной формулировки historical — true if the document represents historical records):
- Различать «свежий лаб-отчёт» vs «компиляция исторических данных» (старые анализы, retrospective dump)
- Возможно влиять на trends / interpretation (исторические записи не должны триггерить «новые данные»)
- Возможно скрывать в UI как «не свежий результат»
Реальное использование в обоих стэках:
| Стэк | Где написано | Где читается с branching |
|---|---|---|
| .NET | TestContent.Historical (entity) + migration backfill + MetadataResponse API + reset в AnalysisService:1266 | нигде (IsValidMedicalDocument использует Human и MedicalContext, не Historical) |
| Node.js | ImageTestInfoSchema (Zod), 4 schemas-duplicate (mastra/recognition, ocr-core/blood-parameters, analysis.types, generated SDK), image-crosscheck.function.ts:77 копирует, upload/service.ts:93, response-builder.ts:56 | нигде (116 hits на «historical» в коде — все либо это поле без branching, либо несвязанное historicalTests в trends-analysis / historicalDates в migration / UI bucket) |
Рассматривали
A. Удалить (предлагаемое)
Drop column в Postgres (.NET и/или Prisma migration), убрать из всех Zod schemas, убрать из API contract / OpenAPI / SDK, не просить LLM в промпте.
- ➕ Убирает мёртвый код, перестаём врать API consumer’у наличием поля
- ➕ Меньше surface area при добавлении настоящих document-классификаторов (uploaded-document-types-supported)
- ➖ Breaking change для любого SDK consumer, читающего поле — но т.к. оно
boolean \| nullбез значимой семантики, риск практически нулевой
B. Оставить и допилить routing
Реализовать ветви где флаг имеет смысл: если historical=true → не пушить в trends, не показывать как latest, не запускать interpret automatically.
- ➕ Сохраняет уже-собранные данные за 10 месяцев (Jul 2025 → May 2026)
- ➖ Никто не озвучивал requirement — ветка существует только потому что флаг существует, не наоборот
- ➖ Семантика
historicalнечёткая: «документ старее N дней» vs «document = compilation» vs «retrospective import». LLM сам решает по неформальному определению — данные шумные
C. Переименовать в is_compilation если есть конкретный usecase
Если действительно нужно отличать compilation (multi-date discharge summary, quarterly panels) от single-snapshot lab — это уже частично решает мульти-date support в recognize_image_to_fhir (test_date per-parameter).
- ➕ Конкретная семантика, потенциальный consumer (UI индикатор «multi-date document», trends обработка)
- ➖ Если consumer не появится сразу — то же что (B) с другим именем
Что нужно для разрешения
- Подтвердить у команды: никто не планирует использовать
historicalв обозримом будущем (Vlad / Artur / Maxim — кто-то мог иметь в виду этот флаг при clinical-data work). - Если (A) — cleanup только Node.js side, в одном PR.
Scope: .NET (TestContent.Historical column + entity + DTO + API surface) не трогаем. Legacy backend в режиме phase-out, изменения там создают coordination cost без бенефита для этой ветки. Если когда-нибудь будет .NET cleanup pass — Historical присоединяется отдельным item’ом, не связанным с этой decision.
Следствия (если выбрано A — Node.js only)
- Recognition prompt — убрать
historicalизtest_infoблока вpackages/analysis-core/src/prompts/recognize_image_to_fhir.md(live source-of-truth, см. chain notes про Langfuse miss) +recognize_gptв Langfuse если оно там есть - Schemas — удалить поле из:
packages/analysis-core/src/schemas/recognize-image-to-fhir.schema.ts(Zod + JSON Schema)packages/analysis-core/src/types/analysis.types.ts(две interface)packages/ocr-core/src/schemas/blood-parameters.ts(legacy schema)packages/ocr-core/src/types/index.tsapps/analysis-worker/src/mastra/schemas/recognition.schemas.ts(mastra duplicate)
- Pipeline / API surface — удалить:
apps/analysis-worker/src/inngest/functions/steps/image-crosscheck.function.ts:77(копированиеr.test_info.historical)apps/b2b-api/src/modules/upload/response-builder.ts:56(API response field)apps/b2b-api/src/modules/upload/service.ts:93apps/b2b-api/src/openapi/index.ts(OpenAPI schema)packages/sdk/generated/api/index.ts+hooks/index.ts(regenerate)
- OpenAPI / SDK breaking — поле в API response было
boolean | null, всегда null или невнятный signal. Риск что кто-то реально использует — низкий, но коммит-сообщение должно явно отметить removal для consumer’ов
Открытые вопросы
Summaryполе — рядом сhistoricalживётSummary(one-sentence summary документа), тоже изtest_info. Используется ли он? Если нет — кандидат на тот же путь.Human/MedicalAnalysis— оба используются вIsValidMedicalDocument(). Это полезные флаги — но семантика «is human document» vs «is medical document» overlap’ает. Можно ревизировать тот же блок одной задачей.- Если вместо удаления приходим к (C)
is_compilation— это пересекается с multi-date detection вtest_dateper-parameter. Возможноis_compilation = (unique test_dates > 1)derived, не отдельный LLM-флаг.
Связано
- uploaded-document-types-supported — proper document classification через
document_typeenum + LOINC; покрывает реальную потребность за которойhistoricalмог стоять - uploaded-document-types — таксономия типов
- fhir-resource-origin-and-lifecycle — origin tag через
meta.tag(user-uploaded / external-data / ai-generated); ортогонально historical, но связано как «как мы классифицируем входящий документ»