Contrato de interpretación de lenguaje natural
Panorama general
Este archivo define el contrato InterpretationResult versión "1" para todo intérprete de lenguaje natural de Plano. Su función es validar salidas de interpretación sin ejecutar acciones, sin escribir datos y sin tocar persistencia.
El módulo también fija los catálogos, los esquemas cerrados, las reglas de procedencia y la coherencia entre intención, capacidad, confirmación y dominio. Eso permite que el sistema siga siendo determinista, incluso cuando exista un intérprete basado en modelo.
[!IMPORTANT] Un intérprete solo propone. Nunca ejecuta ni completa acciones por su cuenta.
La ejecución real revalida cada argumento con los validadores de dominio existentes.
[!WARNING] El contrato rechaza cualquier
score,confidence,probabilityolikelihooden cualquier nivel del resultado.
Cómo funciona
flowchart TD
RT[validateRuntimeInterpretation] --> VR[validateInterpretationResult]
VR --> V1[Versiones y esquema superior]
VR --> I1[validateInput]
I1 --> P1[params]
I1 --> C1[changes]
I1 --> M1[missing]
I1 --> A1[ambiguities]
I1 --> U1[unparsed]
P1 --> L1[location]
C1 --> L1
L1 --> D1[domain]
D1 --> C2[capability]
C2 --> A2[proposedAction]
A2 --> R1[refinementScope]
R1 --> O1[valid or errors]
El flujo comienza con validateInterpretationResult(). Primero verifica el contenedor superior, luego valida input, después revisa parámetros, cambios, faltantes, ambigüedades y fragmentos no parseados. Al final comprueba la coherencia de ubicación, dominio, capacidad, acción propuesta y confirmación.
validateRuntimeInterpretation() actúa como envoltura estricta para ejecución. Exige expectedInput, prohíbe intérpretes de tipo reference y nunca permite acciones planificadas.
Componentes clave
{
"title": "validateInterpretationResult",
"content": "Valida un InterpretationResult completo y devuelve { valid, errors }. Revisa esquema cerrado, evidencia, procedencia, dominio, capacidad, confirmaci\u00f3n y coherencia de estado.",
"type": "function",
"filePath": "services/api/src/modules/interpretation/interpretation-contract.js",
"badges": [
"public"
]
}
{
"title": "validateRuntimeInterpretation",
"content": "Validador obligatorio para ejecuci\u00f3n. Exige expectedInput, rechaza etiquetas de referencia y desactiva acciones planificadas.",
"type": "function",
"filePath": "services/api/src/modules/interpretation/interpretation-contract.js",
"badges": [
"public"
]
}
{
"title": "resolveRefinedCriteria",
"content": "Aplica un refinamiento ya validado sobre criterios activos. Conserva lo no mencionado y reemplaza la ubicaci\u00f3n completa cuando cambia locationQuery o searchZones.",
"type": "function",
"filePath": "services/api/src/modules/interpretation/interpretation-contract.js",
"badges": [
"public"
]
}
{
"title": "checkDomainCombination",
"content": "Comprueba la compatibilidad entre entityType, operationType y subtipo de listado. Devuelve errores, missing y unrepresentable.",
"type": "function",
"filePath": "services/api/src/modules/interpretation/interpretation-contract.js",
"badges": [
"public"
]
}
{
"title": "validateParamValue",
"content": "Valida un valor contra la especificaci\u00f3n de su par\u00e1metro. Soporta enums, listas, zonas, n\u00fameros, enteros, booleanos, cadenas, ordinales y referencias activas.",
"type": "function",
"filePath": "services/api/src/modules/interpretation/interpretation-contract.js",
"badges": [
"public"
]
}
Datos y campos
El contrato usa esquemas cerrados. Cada objeto anidado rechaza llaves desconocidas. La entrada input la construye quien llama, no el intérprete.
[
{
"name": "contractVersion",
"type": "string",
"required": true,
"description": "Versión del contrato. Debe ser \"1\"."
},
{
"name": "interpreter",
"type": "object",
"required": true,
"description": "Identifica el intérprete que produjo el resultado.",
"children": [
{
"name": "kind",
"type": "deterministic | model | reference",
"required": true,
"description": "Tipo de intérprete."
},
{
"name": "id",
"type": "string",
"required": true,
"description": "Identificador no vacío del intérprete."
},
{
"name": "version",
"type": "string",
"required": true,
"description": "Versión no vacía del intérprete."
},
{
"name": "capabilityRegistryVersion",
"type": "string",
"description": "Si existe, debe coincidir con CAPABILITY_REGISTRY_VERSION."
},
{
"name": "lexiconVersion",
"type": "string",
"description": "Si existe, debe coincidir con LEXICON_VERSION."
}
]
},
{
"name": "input",
"type": "object",
"required": true,
"description": "Entrada original que recibió el intérprete.",
"children": [
{
"name": "text",
"type": "string",
"required": true,
"description": "Texto fuente. Máximo 2000 caracteres."
},
{
"name": "locale",
"type": "string",
"required": true,
"description": "Localidad admitida. Solo \"es-MX\"."
},
{
"name": "context",
"type": "object",
"required": true,
"description": "Contexto que aporta evidencia verificable.",
"children": [
{
"name": "surface",
"type": "wall | conversation | temporary",
"required": true,
"description": "Superficie de interacción actual."
},
{
"name": "conversationId",
"type": "string",
"description": "Identificador de conversación, cuando existe."
},
{
"name": "activeSearch",
"type": "object",
"description": "Búsqueda activa que puede ser temporary o saved.",
"children": [
{
"name": "kind",
"type": "temporary | saved",
"required": true,
"description": "Tipo de búsqueda activa."
},
{
"name": "requirementId",
"type": "string",
"description": "Obligatorio cuando kind es saved."
},
{
"name": "criteria",
"type": "object",
"description": "Criterios activos verificables."
}
]
},
{
"name": "visibleResults",
"type": "object",
"description": "Resumen de resultados visibles.",
"children": [
{
"name": "count",
"type": "integer",
"required": true,
"description": "Cantidad visible de resultados."
}
]
},
{
"name": "locationDefaults",
"type": "object",
"description": "Valores predeterminados de ubicación.",
"children": [
{
"name": "current",
"type": "object",
"description": "Ubicación actual autorizada.",
"children": [
{
"name": "consent",
"type": "\"granted\"",
"required": true,
"description": "Debe declarar consentimiento explícito."
},
{
"name": "searchZones",
"type": "zone list",
"required": true,
"description": "Zonas geocodificadas de la ubicación actual."
}
]
},
{
"name": "profile",
"type": "object",
"description": "Preferencias de ubicación del perfil.",
"children": [
{
"name": "locationQuery",
"type": "string",
"description": "Texto de ubicación del perfil."
},
{
"name": "searchZones",
"type": "zone list",
"description": "Zonas geocodificadas del perfil."
}
]
}
]
}
]
},
{
"name": "controlSelections",
"type": "array of controlSelection",
"description": "Selecciones hechas por controles de aclaración."
}
]
},
{
"name": "status",
"type": "recognized | needs_clarification | ambiguous_intent | unsupported | unrecognized",
"required": true,
"description": "Estado final de la interpretación."
},
{
"name": "intent",
"type": "string | null",
"required": true,
"description": "IntentId del catálogo, o null cuando el estado lo exige."
},
{
"name": "intentOptions",
"type": "array of string",
"description": "Opciones de intención solo para ambiguous_intent."
},
{
"name": "params",
"type": "object",
"required": true,
"description": "Parámetros interpretados. Cada entrada usa { value, source }."
},
{
"name": "changes",
"type": "array",
"description": "Cambios sobre criterios activos. Solo aplica a discover.refine."
},
{
"name": "missing",
"type": "array",
"description": "Parámetros obligatorios faltantes, con su control esperado."
},
{
"name": "ambiguities",
"type": "array",
"description": "Lecturas ambiguas con dos o más opciones válidas."
},
{
"name": "unparsed",
"type": "array",
"description": "Fragmentos no interpretados del texto."
},
{
"name": "location",
"type": "object",
"description": "Resolución de ubicación y su editabilidad."
},
{
"name": "capability",
"type": "object",
"description": "Capacidad declarada por el registro de acciones."
},
{
"name": "proposedAction",
"type": "object | null",
"required": true,
"description": "Acción propuesta. args debe ser {}."
},
{
"name": "confirmation",
"type": "none | required | required_public_visibility",
"required": true,
"description": "Nivel de confirmación requerido para la acción propuesta."
}
]
Vocabulario y catálogos de estado
Estos valores se usan para cerrar el contrato y limitar salidas válidas. Muchos de ellos dependen de validadores externos o de catálogos del backend.
INTERPRETATION_CONTRACT_VERSION— versión del contrato, fija en"1".CAPABILITY_REGISTRY_VERSION— versión del registro de capacidades, fija en"1".INTERPRETATION_STATUSES—recognized,needs_clarification,ambiguous_intent,unsupported,unrecognized.INTERPRETER_KINDS—deterministic,model,reference.INTERPRETATION_LOCALES— soloes-MX.INTERACTION_SURFACES—wall,conversation,temporary.ACTIVE_SEARCH_KINDS—temporary,saved.CONTEXT_REFS—activeSearch,visibleResults,conversation,locationDefaults.INTENT_IDS— catálogo cerrado de intenciones.CONFIRMATION_LEVELS—none,required,required_public_visibility.CLARIFICATION_CONTROLS—choice,number,range,toggle,text,place_search,requirement_picker,listing_picker,conversation_picker.UNPARSED_REASONS—UNKNOWN_TERM,UNSUPPORTED_FIELD,NEGATION_NOT_REPRESENTABLE,OUT_OF_SCOPE_REQUEST.PARAM_SOURCE_KINDS—text,context,control.CHANGE_OPS—set,clear,remove.CAPABILITY_STATUSES—available,planned,none.AUTHORIZATION_REQUIREMENTS—authenticated,owner,verified_email,publish_entitlement.LOCATION_RESOLUTIONS—explicit,conversation,current_location,profile,unresolved.
Vocabulario de dominio
Este bloque copia vocabulario controlado del backend. Los comentarios del archivo lo vinculan con models/Listing.js y modules/listings/listings.validators.js.
ENTITY_TYPE_VALUES—property,service,investment.OPERATION_TYPE_VALUES—sale,rent,temporary_rent,presale,investment_offer,service_offer,exchange,auction,transfer,service_request,investment_request.PROPERTY_TYPE_VALUES—house,apartment,land,office,warehouse,commercial,industrial,building,other.SERVICE_TYPE_VALUES—legal,notarial,architecture,construction,structural_steel,construction_engineering,insurance,mortgage,financial_advisory,valuation,property_management,photography,referral,other_service.INVESTMENT_TYPE_VALUES—fibra,fractional,development.LISTING_INTENTS—offer,requirement.AMENITY_VALUES— catálogo cerrado de amenidades.PERIODICITY_VALUES—unspecified,day,week,month.CURRENCY_VALUES—MXN,USD,EUR.
[!NOTE]
CURRENCY_VALUESes un vocabulario controlado del formulario.El archivo aclara que el backend guarda la moneda como texto libre.
Especificación de parámetros
PARAM_SPECS define el tipo, límites y targetPath de cada parámetro. PARAM_KEYS es la lista derivada de esas claves. CRITERIA_PARAMS marca qué campos forman parte de una búsqueda activa.
Parámetros de dominio
entityType— enum,meta.entityType.operationType— enum,meta.operationType.propertyType— enum,meta.propertyType.serviceType— enum,meta.serviceType.investmentType— enum,meta.investmentType.
Parámetros económicos
budgetMin— number, mínimo0,requirement.budget.min.budgetMax— number, mínimo0,requirement.budget.max.budgetCurrency— enum,requirement.budget.currency.budgetPeriodicity— enum,requirement.budget.periodicity.priceAmount— number, mínimo0,price.amount.priceCurrency— enum,price.currency.pricePeriodicity— enum,price.periodicity.
Parámetros físicos
bedrooms— integer, mínimo0,meta.bedrooms.bathrooms— integer, mínimo0,meta.bathrooms.halfBathrooms— integer, mínimo0,meta.halfBathrooms.parkingSpots— integer, mínimo0,meta.parkingSpots.constructionArea— number, mínimo0, unidadm2,meta.constructionArea.landArea— number, mínimo0, unidadm2,meta.landArea.
Preferencias y ubicación
desiredAmenities— enum list,requirement.desiredAmenities.hasPets— boolean,requirement.hasPets.petFriendlyRequired— boolean,requirement.petFriendlyRequired.locationQuery— string,targetPath: null.searchZones— zone list, máximo3,requirement.searchZones.titleQuery— string,targetPath: null.
Referencias e identificadores
listingReference— ordinal,targetPath: null.requirementId— string,targetPath: null.listingId— string,targetPath: null.conversationId— string,targetPath: null.requirementReference— referencia activa, usa evidencia deactiveSearch.
[!IMPORTANT]
searchZonesnunca sale del texto.Solo puede venir de
place_searcho de evidencia previa eninput.context.
Procedencia permitida
La procedencia está cerrada por tipo. Cada valor debe demostrar de dónde salió.
text- Requiere
span. - Requiere
matched. - Requiere
rule. matcheddebe ser exactamente el fragmento deinput.text.
- Requiere
context- Requiere
ref. - Requiere
pathcuando la evidencia debe apuntar a un valor. - Solo acepta
activeSearch,visibleResults,conversation,locationDefaults.
- Requiere
control- Requiere
control. - Requiere
selectionId. - Debe coincidir con
input.controlSelections.
- Requiere
Cambios sobre criterios activos
changes solo se permite con discover.refine. El archivo define tres operaciones:
set— establece o reemplaza un criterio.clear— elimina un criterio.remove— elimina un elemento de una lista.
resolveRefinedCriteria() aplica esos cambios sobre input.context.activeSearch.criteria. Cuando cambia locationQuery o searchZones, la ubicación completa se reemplaza.
Registro de acciones
ACTION_TYPES relaciona intención, permisos, confirmación, persistencia y disponibilidad. Cada acción incluye intents, writes, minimumConfirmation, available, authorization y otros requisitos.
-
match.preview_criteria- Intenciones:
discover.search,discover.refine,discover.show_matches. - No escribe.
- Requiere confirmación
none. - Está registrada como
available: false. - Se relaciona con una operación planificada sobre
generateCandidatesForRequirement.
- Intenciones:
-
match.requirement_candidates- Intenciones:
discover.show_matches,discover.search. - No escribe.
- Requiere
authenticatedyowner. - Solo admite
saved. - Se vincula con
GET /api/match/requirements/:requirementId/candidates.
- Intenciones:
-
requirement.refine- Solo
discover.refine. - Escribe.
- Requiere
authenticated,owner,verified_email. - Requiere
requirementReference. - Usa
persistentsobre una búsqueda guardada.
- Solo
-
requirement.save_private- Solo
discover.save. - Escribe.
- Está planificada, no disponible.
- Se vincula con una visibilidad privada de requirement.
- Solo
-
requirement.publishdiscover.allow_recommendations.- Escribe.
- Requiere
authenticated,owner,verified_email,publish_entitlement. - Hace pública información de la persona.
-
conversation.attach_requirement- Solo
discover.select_existing. - Escribe.
- Requiere
requirementIdyconversationId. - Se vincula con
PATCH /api/conversations/:id.
- Solo
-
conversation.opendiscover.recover.- No escribe.
- Requiere
authenticatedyowner. - Se vincula con consultas de conversaciones.
-
listing.openlisting.inspect.- No escribe.
- No requiere autenticación.
- Se vincula con
GET /api/listings/:id.
-
publish_wizard.openpublish.start_offer.- No escribe.
- Requiere
authenticated. - Se vincula con la ruta del asistente de publicación.
-
publish_wizard.continuepublish.continue.- No escribe.
- Requiere
authenticatedyowner. - Se vincula con listado propio y edición del asistente.
-
navigate.leadsattend.leads.- No escribe.
- Requiere
authenticated. - Se vincula con la ruta de atención y
GET /api/leads.
-
navigate.activityattend.activity.- No escribe.
- Requiere
authenticated. - Se vincula con la cuenta y
GET /api/listing-events.
-
navigate.wallnav.wall.- No escribe.
- Requiere
authenticated. - Se vincula con la ruta del feed.
-
help.showsystem.help.- No escribe.
- No requiere autenticación.
- Usa una plantilla determinista sin backend.
Esquemas cerrados
SCHEMA_KEYS enumera las llaves permitidas por objeto. Cualquier llave fuera de estas listas provoca error.
result— llaves superiores del resultado.interpreter— llaves del bloque del intérprete.input— llaves de la entrada.context— llaves de contexto.activeSearch— llaves de búsqueda activa.visibleResults— llaves de resultados visibles.locationDefaults— llaves de ubicación predeterminada.currentLocation— llaves delocationDefaults.current.profileLocation— llaves delocationDefaults.profile.controlSelection— llaves de una selección de control.paramEntry— llaves de una entrada de parámetro.source— llaves permitidas segúnkind.zone— llaves de una zona geocodificada.zoneCenter— llaves del centro geográfico.change— llaves de un cambio.missing— llaves de un faltante.ambiguity— llaves de una ambigüedad.ambiguityOption— llaves de una opción ambigua.unparsed— llaves de un fragmento no parseado.location— llaves del estado de ubicación.capability— llaves del bloque de capacidad.proposedAction— llaves de la acción propuesta.ordinalValue— llaves de un valor ordinal.activeRequirementValue— llaves de una referencia activa.
Comportamientos
Estas funciones son el núcleo operativo del archivo. Cada una devuelve errores estructurados, no lanza excepciones de dominio.
validateInterpretationResult()— valida el resultado completo y devuelve{ valid, errors }.validateRuntimeInterpretation()— valida en ejecución y exigeexpectedInput.resolveRefinedCriteria()— calcula los criterios resultantes tras aplicarparamsychanges.checkDomainCombination()— verifica compatibilidad entre entidad, operación y subtipo.validateParamValue()— valida un valor individual contraPARAM_SPECS.
Funciones internas relevantes:
validateZone()— valida zonas con centro geográfico y radio.validateSource()— despacha la validación segúntext,contextocontrol.validateContextSource()— comprueba evidencia de contexto.validateControlSource()— comprueba selecciones de controles.validateChanges()— valida y resume cambios sobre criterios activos.validateLocation()— aplica precedencia y coherencia de ubicación.validateDomain()— enlaza intención con reglas de creación de listings.validateCapability()— comparacapabilityconACTION_TYPES.validateProposedAction()— valida la acción propuesta y sus requisitos.validateRefinementScope()— restringe refinamientos persistentes.
Riesgos y casos límite
[!WARNING]
inputdebe coincidir con la entrada original en ejecución.
validateRuntimeInterpretation()rechaza cualquier resultado que no useexpectedInput.
[!CAUTION]
interpreter.kind = "reference"no se admite en ejecución.Ese valor existe para corpus de evaluación, no para producción.
[!WARNING]
proposedAction.argssiempre debe ser{}.Los argumentos se derivan de
paramsya verificados, no se reciben libres.
[!IMPORTANT]
changessolo es válido condiscover.refine.Además,
change.source.kindno puede sercontextcuando la operación esset.
[!WARNING]
recognizedexigeintent,capabilityy una acción coherente.También prohíbe faltantes obligatorios y ambigüedades.
[!WARNING]
ambiguous_intentexigeintent = nully al menos dosintentOptionsdistintas.También prohíbe
changesyproposedAction.
[!WARNING]
unsupportedrequiere un fragmentounparsedconreason = OUT_OF_SCOPE_REQUEST.No admite
params,changesniproposedAction.
[!NOTE]
location.resolution = "conversation"solo se hereda endiscover.refine.Si el refinamiento toca la ubicación, esa herencia deja de aplicar.
[!NOTE]
searchZonessolo puede venir deplace_searcho de contexto previo.El contrato rechaza cualquier procedencia textual para ese campo.
Relacionado
Este archivo se conecta con varios elementos citados explícitamente en sus comentarios y validaciones. También fija la base para el uso determinista de interpretación en Plano.
services/api/src/modules/interpretation/real-estate-lexicon.js— aportaLEXICON_VERSION.models/Listing.js— fuente del vocabulario de entidad y operación.modules/listings/listings.validators.js— fuente de reglas y catálogos reflejados aquí.test/interpretation-enum-sync.test.js— verifica sincronía entre enums del contrato y el backend.test/interpretation-versioning.test.js— registra la huella de versiones.tools/nlp/versioning-policy.md— política de versionado citada por el módulo.match/comparison-contract.js— aparece en comentarios como referencia paracomparePhysicalMinimum.validateListingPayload— referencia funcional usada para compatibilidad de dominio.applyRequirementRefinement()— referencia funcional usada para refinamientos persistentes.generateCandidatesForRequirement— referencia interna citada en la descripción de una acción planificada.
[!NOTE] El archivo no define endpoints HTTP reales.
Solo registra relaciones textuales hacia rutas y flujos ya existentes o planificados.