Кандидат на удаление — поле задумывалось как 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
.NETTestContent.Historical (entity) + migration backfill + MetadataResponse API + reset в AnalysisService:1266нигде (IsValidMedicalDocument использует Human и MedicalContext, не Historical)
Node.jsImageTestInfoSchema (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) с другим именем

Что нужно для разрешения

  1. Подтвердить у команды: никто не планирует использовать historical в обозримом будущем (Vlad / Artur / Maxim — кто-то мог иметь в виду этот флаг при clinical-data work).
  2. Если (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.ts
    • apps/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:93
    • apps/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_date per-parameter. Возможно is_compilation = (unique test_dates > 1) derived, не отдельный LLM-флаг.

Связано

  • uploaded-document-types-supported — proper document classification через document_type enum + LOINC; покрывает реальную потребность за которой historical мог стоять
  • uploaded-document-types — таксономия типов
  • fhir-resource-origin-and-lifecycle — origin tag через meta.tag (user-uploaded / external-data / ai-generated); ортогонально historical, но связано как «как мы классифицируем входящий документ»

Источники