Instruction file imported from luischanferoni/bioenlace (
.cursor/rules/source-of-truth-catalogos.mdc). Copyright stays with the author.
Source of truth — catálogos y listas cerradas
Complementa runtime-datos-vs-metadata.mdc y metadata-yaml-uso.mdc.
Principio
Cada lista cerrada que el runtime valida o inyecta en prompts tiene exactamente una fuente y un loader PHP que la consume. Prohibido mantener la misma lista en dos sitios (const PHP + YAML, JSON en prompt + enum en schema, categories_json + categories_human, etc.).
YAML del catálogo = vocabulario + textos (para prompt o UX). PHP del loader = all() / isValid() / listForPrompt() y, si hace falta, mapas técnicos (wiring id→id, tags extra sin copy). No mezclar esos mapas en el YAML. No mantener capas de retrocompatibilidad en metadata ni en PHP.
Dónde va cada cosa
| Tipo de dato | Source of truth | Loader / validación |
|---|---|---|
| Categorías extracción preprocess | textos: Platform/Assistant/Application/Catalog/preprocess-extraction-categories.yaml; ids: HintCandidateProviderInterface::declaredEntities() |
PreprocessExtractionCategoryCatalog |
routing_hint preprocess (id → texto IA) |
Platform/Assistant/Application/Catalog/preprocess-routing-hints.yaml |
PreprocessRoutingHintCatalog |
Alias / mapas técnicos preprocess (user_goal, tags extra) |
constantes en PreprocessRoutingHintCatalog |
mismo loader |
| Tags preprocess (vocabulario IA) | tags de intents Domain + extraPreprocessTags() PHP |
PreprocessTagVocabularyCatalog |
| Aspectos HIS / plan declarativo (legado) | constantes ASPECTS en AssistantContextHISAreaAspect |
AssistantContextHISAreaAspect, AssistantContextAreaAspectCatalog |
| Entidades hint (flows) | declaredEntities() en cada *HintCandidateProvider (ownership compuesto) |
HintCandidateProviderRegistry, HintResolutionMetadata |
| Copy límites de canal (fuera HIS) | Platform/Assistant/Application/Routing/channel-limits.yaml |
metadata loader |
| Copy de notificaciones del journey clínico | Domain/Clinical/Encounter/Application/Catalog/encounter-journey-notifications.yaml |
EncounterJourneyNotificationCatalog |
| Copy de notificaciones B01 (staff/paciente) | Domain/Clinical/CareCohort/Application/Catalog/care-followup-notifications.yaml |
CareFollowupNotificationCatalog |
| Copy de notificaciones B03 (laboratorio) | Domain/Clinical/Laboratory/Application/Catalog/post-lab-classification-notifications.yaml |
PostLabClassificationNotificationCatalog |
| Maestros consultados en request (geo, recursos) | BD + seed console | servicio dominio + cache |
Reglas PHP
- Constantes nombradas (
PreprocessRoutingHintCatalog::CLARA, etc.) solo como alias del id string; la listaall()/isValid()sale del YAML (cuando el catálogo es vocabulario+texto). - Mapas técnicos viven en el loader; no en un segundo YAML ni en otro service.
- Prompts: placeholders
{…_list}generados por el loader; no repetir enums en el cuerpo del prompt si ya se inyectan. - Schemas (
assistant/schemas/*.yaml): referenciar path del catálogo encategory_values/ notas; no duplicar arrays completos salvo ejemplo ilustrativo. - Validación:
normalize*y motores llaman al catalog loader; categorías/hints inventados se descartan.
Al agregar o cambiar un valor
- Si es id + texto para IA/usuario: editar solo el YAML catálogo (o BD + seed si es maestro runtime).
- Si es alias / mapa / tag auxiliar: editar el loader PHP.
- Si hace falta código nuevo: extender el loader existente, no otra lista en un service.
- Test: catálogo carga y constantes nombradas (si existen) siguen en el catálogo.
- No copiar la lista al prompt, al schema ni a un
private consten otro archivo. - Para notificaciones, mantener el copy en el catálogo YAML y las condiciones de disparo en la política PHP; no duplicar mensajes en jobs, schedulers ni agentes.
Anti-patrones
ROUTING_HINTSen PHP distinto del YAML de routing hints.aliases:/legacy_user_goal:/ listas de ids sin texto en el YAML de hints.- Mismo vocabulario en preprocess.yaml y en smart-catalog sin derivación.
- Enum hardcodeado en
SmartCatalogRoutingServiceen lugar del catalog loader.
