Spec: diseño de Fase 0 y Fase 1 del plugin de propuesta consultiva con IA

Convierte el análisis de negocio de docs/BI-propuesta-consultiva-IA.md en una
especificación cerrada para las dos primeras fases del roadmap.

El análisis previo destapó cuatro problemas que el documento de negocio no
anticipaba, los cuatro verificados en disco:

- POST /mcp no tiene autenticación (api/main.py:107) y _obtener_cotizacion hace
  SELECT c.* sin lista blanca, con dominio público en producción. Publicaría la
  columna de notas internas sin tocar una línea de código.
- No existe una fuente de verdad para los totales: el cálculo está duplicado en
  siete consumidores y el IVA está hardcodeado como * 1.16 en PDF y Excel.
- El Excel es un documento del cliente, no una herramienta interna. El diseño
  inicial proponía poner ahí las notas internas; se corrigió.
- Las transcripciones se sincronizarían a la nube de MEGA: .megaignore solo
  excluye .next, node_modules y .turbo.

También reconcilia nueve contradicciones de contrato entre los diseños
explorados (clave de partida, forma de la evidencia, nombres del valor anual)
que habrían hecho que la capa de validación validara el vacío.

Actualiza AGENTS.md, que había quedado desfasado: 14 modelos y 10 migraciones
(decía 13 y 3), el registro de horas, la doble propuesta, los modelos de cobro
y la convención de no usar diálogos nativos del navegador.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
urieljareth
2026-07-28 14:20:03 -06:00
co-authored by Claude Opus 5
parent 26e6d3a9bf
commit 0ff783fd65
3 changed files with 1357 additions and 11 deletions
+859
View File
@@ -0,0 +1,859 @@
# Business Intelligence — Plugin de Propuesta Consultiva con IA
> **Qué es este documento:** el análisis de negocio, la filosofía y los lineamientos para una **futura** implementación de un plugin que, a partir de transcripciones de reuniones y notas de texto, genere un **segundo documento** de cotización — narrativo y consultivo — como complemento al documento económico que hoy produce el Cotizador E3 de forma manual.
>
> **Qué NO es:** una especificación técnica cerrada ni un plan de implementación. No hay código aquí. Es el mapa que debe leerse antes de escribir la primera línea.
>
> **Fuentes analizadas:**
> - Proyecto real: `H:\MegaSync\Proyectos\Cotizador` (Next.js 16 + Prisma 7 + PostgreSQL, con API Python/MCP paralela)
> - Plantilla de referencia: `D:\Documents\plantilla_cotizacion.html`
> - Base de conocimiento: `Guia_Onboarding_Cliente_y_Ruta_de_Trabajo.md`, `08-Monetizacion-Onboarding-Pricing-Seguimiento.md`, `Onboarding-Cliente/04-Sesion-Propuesta-y-Continuidad.md`, `sintesis/s2-Pricing-Cobranza.md`, `sintesis/s8-Prompts-Plantillas.md`, `00-Guia-de-Uso-y-Checklist-Calidad.md`
>
> **Fecha:** 2026-07-28 · **Estado:** análisis previo a implementación
---
## 1. Resumen ejecutivo
El Cotizador E3 hoy resuelve muy bien **el qué y el cuánto**: un catálogo de servicios por fase, precios, IVA, financiamiento, planes Bucéfalo, exportación a PDF y Excel. Es un motor contable y comercial sólido.
Lo que no resuelve —y lo que la base de conocimiento identifica como el factor que multiplica el ticket entre 3x y 15x— es **el por qué**: el diagnóstico del dolor del cliente en sus propias palabras, la cuantificación del costo de no hacer nada, el anclaje del precio en el valor anual, y la narrativa que permite al cliente defender la inversión internamente.
Ese "por qué" ya se está capturando de forma parcial pero **se está tirando a la basura**:
- El campo `observaciones` de `Cotizacion` y el campo `notas` de cada `ServicioCotizado` se guardan en la base de datos y **no se imprimen ni en el PDF ni en el Excel** (verificado por búsqueda en `src/lib/pdf-generator.ts` y `src/lib/excel-builder.ts`: cero coincidencias).
- Las reuniones de discovery generan transcripciones que hoy viven fuera del sistema.
- La plantilla HTML de `D:\Documents\` ya tiene la estructura narrativa correcta (diagnóstico con semáforo, exclusiones explícitas, argumentos de venta, estado de materiales) pero se llena **a mano**, una por una.
**La oportunidad:** un plugin que lea el contexto humano disperso (transcripción + notas + observaciones + la cotización ya armada) y genere un segundo archivo —el documento consultivo— siguiendo la filosofía de la plantilla HTML, sin tocar un solo número.
**La tesis central, en una frase:**
> El documento manual es la **fuente de verdad económica**. El documento de IA es la **fuente de verdad narrativa**. La IA nunca inventa un precio; sólo explica el que ya existe.
---
## 2. Inventario: los tres activos que ya existen
### 2.1 El Cotizador real (`H:\MegaSync\Proyectos\Cotizador`)
**Stack.** Next.js 16 (App Router) + React 19 + Tailwind v4 + Zustand · Prisma 7 (cliente generado en `src/generated/prisma`, driver adapter `PrismaPg`) · PostgreSQL 16 en Docker · JWT con `jose` en cookie httpOnly · PDFKit server-side · despliegue en Coolify.
**Segundo backend.** Un servicio FastAPI en `api/` que expone el mismo dominio como REST **y un servidor MCP en `/mcp`** con 12 herramientas y 3 recursos para agentes de IA. Esto es el hallazgo arquitectónico más importante del inventario: **el proyecto ya tiene una superficie diseñada para que una IA lo opere.**
Herramientas MCP existentes: `buscar_servicios`, `crear_cotizacion`, `obtener_cotizacion`, `listar_cotizaciones`, `cambiar_estado_cotizacion`, `actualizar_precio_servicio`, `duplicar_cotizacion`, `calcular_financiamiento`, `generar_pdf_cotizacion`, `obtener_configuracion`, `listar_bonos`, `listar_planes_bucefalo`. Recursos: `cotizador://servicios`, `cotizador://categorias`, `cotizador://configuracion`.
**Modelo de datos relevante.**
| Modelo | Campos que importan para el plugin |
|---|---|
| `Cotizacion` | `numero`, `fecha`, `vigencia`, `moneda`, `esquemaPago`, `estado`, `esDoble`, `opcionesMetadata` (JSON), **`observaciones`** |
| `ServicioCotizado` | `nombre`, `fase`, `tipoPago`, `precio`, `tiempoEntrega`, `entregables` (JSON), `beneficios` (JSON), **`notas`**, `modeloCobro`, `horas`, `tarifaHora`, `opcion` |
| `ServicioCatalogo` | `precioBase`, `descripcion`, `entregablesDefault`, `fase`, `nivel`, `variante` |
| `Cliente` | `nombre`, `empresa`, `email`, `telefono`, `rfc` |
| `RegistroHoras` | `fecha`, rango horario, `horas`, `tarifaHora`, `descripcion`, `estadoPago` |
| `PlanBucefaloCotizacion` | `nivel`, `precio` |
| `FinanciamientoPlan` | `meses` (3/6/9/12), `tasa`, `comision`, `montoMinimo`, `iva` |
| `Bono` | `numero`, `titulo`, `descripcion` |
| `Configuracion` | key-value: `color_primario`, `color_secundario`, `logo_base64` |
**Reglas de negocio ya codificadas** (`src/lib/calculators.ts`):
- `IVA_RATE = 0.16`
- `TARIFA_HORA_DEFAULT = 700`
- Número de cotización: `UJ{YY}{MM}{InicialesAsesor}{seq}` (ej. `UJ2605AG001`)
- Vigencia = 15 días hábiles desde la fecha (excluye sábado y domingo)
- 4 fases: F0 Auditoría · F1 Setup/Infra · F2 Publicidad/Manejo · F3 Contenido/SEO
- Planes Bucéfalo mensuales: básico $1,000 · estándar $3,500 · premium $4,500 · empresarial $7,500 (hardcodeados en `calculators.ts`, **no en la BD**)
- Modelos de cobro: `fijo`, `horas`, `retainer`, `demanda`
- 6 paquetes PyME pre-armados + paquete "General" con todo el catálogo
**El hallazgo clave: `esDoble` ya existe.** El sistema soporta cotización de doble propuesta: `esDoble: boolean` + `opcionesMetadata` con estructura `{ "1": {titulo, descripcion, noIncluye}, "2": {...} }`, y cada `ServicioCotizado` puede asignarse a la opción `"1"`, `"2"` o `"ambas"`. La herramienta MCP `crear_cotizacion` ya acepta `es_doble=true`. **Ya hay una vía nativa para presentar opciones comparables** — y la base de conocimiento dice que 3 opciones cierran 16-28% más alto. Está a mitad de camino.
### 2.2 La plantilla HTML (`D:\Documents\plantilla_cotizacion.html`)
Un documento de 690 líneas, autocontenido, con tokens CSS, tipografía editorial (Playfair Display serif + DM Sans), tema oscuro (`--bg: #0a0f1e`), responsive y con reglas `@media print` (`page-break-inside: avoid`).
Su valor no es el CSS. Es **la arquitectura argumental**:
| # | Sección | Función retórica |
|---|---|---|
| Hero | Título + subtítulo + 4 metadatos (elaborado por / cliente / plataforma / vigencia) | Encuadre y contexto |
| 01 | **Diagnóstico del proyecto** — un `.quote` con el insight clave + filas con semáforo (`dot-red` problema crítico, `dot-amber` área de mejora, `dot-blue` oportunidad, `dot-green` ventaja existente) | Demuestra que entendiste el negocio antes de vender |
| 02 | **Alcance y desglose económico** — filas categoría / entregable+descripción / precio, más caja de totales (subtotal, descuento, IVA, total) | El qué y el cuánto |
| 03 | **Qué no incluye esta propuesta** — lista con ✕ | Anti-scope-creep, preventivo |
| 04 | **Por qué tiene sentido esta solución** — pares etiqueta/explicación | Argumentos de venta traducidos a beneficio |
| 05 | **Plan de mantenimiento opcional** — dos tarjetas (mensual vs anual, una `.featured`) con features `highlight` / `good` / `muted` | Siembra de recurrencia, con límites explícitos |
| 06 | **Estado de materiales del cliente** — dos tarjetas: materiales (`done`/`pend`) y decisiones pendientes (`pend`/`neutral`) | Transparencia y transferencia de responsabilidad |
| Footer | Datos de contacto + condiciones (50/50, CFDI, avance condicionado a materiales, cambios se cotizan aparte) | Blindaje comercial |
**El semáforo de la sección 01 es el activo intelectual más valioso de la plantilla.** Obliga a clasificar cada hallazgo por urgencia — exactamente lo que la base de conocimiento pide en las 3 Preguntas de Oro. Y el marcador `dot-green` ("ventaja existente") obliga a reconocer lo que el cliente ya hizo bien, que es el detalle que convierte una propuesta en una conversación entre pares.
**La sección 06 es la que resuelve la honestidad de la IA.** Ver §10.2.
### 2.3 La base de conocimiento (vault de Obsidian)
Sintetizada desde 91 transcripts. Lo que aporta al plugin, en orden de utilidad:
**Framework de diagnóstico (Fase 2 del playbook):**
- Las 3 Preguntas de Oro: (1) ¿cuál es el problema de **negocio**, no técnico? (2) ¿cuánto le está costando hoy? (3) ¿cuánto ingreso/ahorro esperas en 12 meses?
- Costo desglosado en 4 dimensiones: dinero directo · tiempo del equipo · costo de oportunidad · costo de error humano
- Filtro de viabilidad de 4 preguntas: costo de no hacer nada · ¿los datos existen HOY? · ¿quién es el usuario final real? · ¿qué pasa si funciona?
- The Mom Test: preguntas ancladas en el pasado ("¿cómo lo resolvieron la última vez?"), no en el futuro hipotético
**Framework de pricing:**
- `Valor Anual = (horas/mes × costo horario × 12) + costo anual de errores + ingresos recuperados`
- `Precio objetivo = 15% a 25% del Valor Anual`
- Marco VALOR (techo) / COSTO real (piso, 2-3× horas técnicas) / MERCADO
- Anclaje: presentar A (2× objetivo) → B (objetivo, se elige 60%) → C (50% del objetivo)
- 3 opciones cierran **16-28% más alto** que una sola
**Reglas transversales de comunicación** (del checklist de calidad):
1. Hablar de resultados, no de herramientas
2. **Usar las palabras del cliente** — registrar frases textuales del dolor y reutilizarlas
3. Investigar hechos pasados
4. 80% habla el cliente / 20% el consultor
5. **Distinguir evidencia de hipótesis** — etiquetar cifras como confirmadas, estimadas o pendientes de validar
6. No prometer solución antes de validar
7. Recapitular y confirmar
8. Comunicar riesgos temprano
**Separación de tres conceptos** (Sesión 4 de onboarding): proyecto inicial ≠ mantenimiento ≠ evolución/retainer. Cada uno con su alcance, precio y forma de contratación explícitos.
**Criterio ético de monetización:** una mejora posterior se propone sólo si hay evidencia de que resuelve un problema real, el cliente puede decidir libremente, y el nuevo alcance/precio/plazo quedan claros.
**Los 15 errores de monetización más caros** — de los cuales el plugin puede prevenir directamente: mandar propuesta con 1 sola opción (#4), aceptar scope creep sin orden de cambio (#7), entregar sin documentación (#8), no ofrecer retainer post-entrega (#9), vender habilidades técnicas en vez de resultados (#13).
---
## 3. Diagnóstico: la brecha entre los tres activos
Aplico a este proyecto el mismo semáforo de la plantilla.
### 🔴 Problema crítico — el contexto humano se captura y se descarta
`Cotizacion.observaciones` y `ServicioCotizado.notas` existen en el esquema, se llenan en el formulario (`CotizacionForm.tsx:1222`, placeholder literal *"Notas adicionales para la cotizacion..."*) y **no aparecen en ningún exportador**. Es información de discovery que el asesor ya se tomó el trabajo de escribir y que muere en la base de datos.
Esto no es sólo desperdicio: es la evidencia de que el sistema fue diseñado como calculadora y no como instrumento de venta consultiva. El plugin no tiene que crear el canal de entrada — **tiene que empezar a leerlo.**
### 🔴 Problema crítico — el pricing es de menú, la filosofía es de valor
El Cotizador calcula desde `ServicioCatalogo.precioBase`: precio fijo por servicio, sumado. Es pricing de catálogo. La base de conocimiento predica pricing por valor: 15-25% del valor anual del problema.
**No son incompatibles, pero hoy no se hablan.** El precio de catálogo es el piso operativo y la base de facturación (con CFDI, IVA, RFC — cosas que un porcentaje del valor anual no te da). El valor anual es el argumento que justifica ese precio ante el cliente.
El plugin no debe reemplazar uno por el otro. Debe **superponer la capa de valor sobre la capa contable**: tomar el total que el humano ya fijó y demostrar que representa X% del valor anual del problema. Si el asesor cotizó $50,000 MXN y la IA detecta en la transcripción un dolor de ~$400,000 MXN/año, la propuesta escribe *"la inversión equivale al 12.5% del costo anual del problema"* — sin mover el $50,000.
### 🟠 Área de mejora — la doble propuesta existe pero está subutilizada
`esDoble` + `opcionesMetadata` da dos opciones. La filosofía pide tres, con anclaje psicológico (cara primero). El plugin puede generar el **argumento** de las tres opciones en su documento narrativo aun cuando el documento económico sólo tenga dos, o recomendar al asesor cómo estructurar las dos que sí caben.
Aquí hay que ser honesto: **no** hay que forzar tres opciones si el proyecto no las admite. La Sesión 4 lo dice explícito: *"Cuando haya alternativas reales, usa tres opciones… las otras no son una trampa ni una lista de extras artificiales."*
### 🟠 Área de mejora — la base de conocimiento es de otro negocio
Esto es una tensión real que hay que documentar antes de que alguien la descubra a medio proyecto:
| | Base de conocimiento | Cotizador E3 |
|---|---|---|
| Negocio | Freelance/consultoría de automatización con Python | Consultoría de digitalización y marketing digital |
| Geografía | LATAM, cobro internacional | Querétaro, MX |
| Moneda | USD (Wise/Stripe/Payoneer) | MXN con IVA 16% y CFDI |
| Rangos | $300 $25,000 USD | $7,490 $90,800 MXN (paquetes) |
| Servicios | Scripts, RAG, dashboards, APIs | Ads, SEO, WordPress, CRM Bucéfalo, contenido |
| Recurrencia | Retainer de mantenimiento de software | Mensualidades de manejo de pauta y CRM |
**Los frameworks son transferibles; las cifras no.** La IA debe importar el *método* de diagnóstico, el *marco* de pricing y las *reglas* de comunicación — y jamás las tablas de precios en USD. Si el plugin sugiere "$1,800 USD" en una cotización de E3, es un bug, no una feature.
### 🔵 Oportunidad — el servidor MCP ya está construido
`api/app/mcp/server.py` (453 líneas) + `tools.py` (305 líneas) exponen el catálogo, las cotizaciones y la configuración a agentes. El plugin no necesita una capa de acceso a datos nueva: puede consumir la que existe. Y como los cálculos viven duplicados en `src/lib/calculators.ts` y `api/app/services/calculators.py` con paridad obligatoria, la IA puede **leer** totales sin riesgo de recalcularlos mal.
### 🔵 Oportunidad — la plantilla HTML es un contrato de salida listo
No hay que diseñar el formato del segundo documento. La plantilla ya define las secciones, la jerarquía y el vocabulario visual. El trabajo es mapear cada sección a su fuente de datos (ver §7) y dejar que la IA llene el contenido, no la estructura.
### 🟢 Ventaja existente — el asesor ya hace el trabajo difícil
El humano ya: califica al cliente, corre la reunión, elige servicios del catálogo, ajusta precios, decide el esquema de pago. El plugin no reemplaza ese juicio. **Se monta sobre él.** Esto reduce drásticamente el riesgo: si la IA falla, el documento manual sigue siendo entregable.
### 🟢 Ventaja existente — el vault ya tiene el system prompt esbozado
`sintesis/s8-Prompts-Plantillas.md` §1 tiene un system prompt maestro, §3 un prompt de diagnóstico de proyecto, §4 un prompt de propuesta comercial y §9 una plantilla de output estándar. No hay que empezar de cero — hay que **adaptar de USD/Python a MXN/marketing digital**.
---
## 4. Filosofía: los 10 principios del plugin
Estos son los principios no negociables. Si una decisión de implementación los contradice, la decisión está mal.
### P1 · La IA no toca los números
La IA **lee** precios, totales, IVA, vigencia y financiamiento. **Nunca los calcula, propone ni modifica.** Todo número que aparezca en el documento de IA debe ser byte-por-byte el mismo que produjo `calculators.ts`.
*Por qué:* un precio inventado por la IA en un documento con el logo de E3 es un pasivo comercial y potencialmente fiscal. Además destruye la confianza en todo el resto del documento.
*Implicación técnica:* los totales se inyectan como datos ya calculados en el prompt y se instruye a la IA a citarlos literalmente; idealmente el render final los toma del objeto de cotización, no del texto generado.
### P2 · Dos documentos, dos trabajos, cero solapamiento
| | Documento 1 (manual, PDF/Excel) | Documento 2 (IA, HTML) |
|---|---|---|
| Autor | Asesor humano | IA, revisada por el asesor |
| Función | Contractual y económica | Consultiva y narrativa |
| Contenido | Servicios, precios, totales, condiciones | Diagnóstico, valor, argumentos, exclusiones, pendientes |
| Números | **Fuente de verdad** | Espejo, sólo citados |
| Si se contradicen | Gana este | Se corrige este |
| Vive en | `pdf-generator.ts` / `excel-builder.ts` | Nuevo generador |
El documento 2 es un **superconjunto narrativo** y un **subconjunto numérico** del documento 1.
### P3 · Toda afirmación es trazable
Cada dato que la IA escriba sobre el cliente debe apuntar a su origen: una línea de transcripción, un archivo de notas, un campo del formulario, o el catálogo. Si no hay origen, no se escribe.
*Implicación:* el contrato de salida (§8) lleva un campo `evidencia` por afirmación. El documento renderizado puede ocultarlo al cliente, pero el asesor debe poder auditarlo antes de enviar.
### P4 · Evidencia, estimación e hipótesis se etiquetan distinto
Directo de la regla 5 del checklist de calidad. Tres estados:
- **Confirmado** — el cliente lo dijo textualmente o hay un dato duro.
- **Estimado** — se derivó de algo que el cliente dijo, con un cálculo explícito.
- **Por validar** — hipótesis del consultor que aún nadie confirmó.
Un "estimado" presentado como "confirmado" es la forma más rápida de perder credibilidad en una reunión de presentación. La IA debe marcar cada cifra.
### P5 · Las palabras del cliente son sagradas
La sección de diagnóstico debe usar frases textuales del cliente, no paráfrasis corporativas. Si en la transcripción dice *"se nos van los clientes porque nadie contesta el WhatsApp el fin de semana"*, eso va entre comillas — no *"oportunidades de mejora en la gestión omnicanal de la comunicación"*.
*Regla operativa:* el bloque `.quote` de la sección 01 debe ser **siempre** una cita literal, nunca una síntesis de la IA.
### P6 · Se vende resultado, no herramienta
Error #13 de la lista de errores de monetización. Traducir toda capacidad técnica a tiempo recuperado, errores evitados, ingresos protegidos o tranquilidad operativa.
*Malo:* "Configuración de Google Ads con estructura SKAG y scripts de puja automatizada."
*Bueno:* "Cada peso de pauta se dirige a las búsquedas que sí compran, en lugar de repartirse entre términos que sólo generan clics. Reportamos costo por prospecto real, no impresiones."
### P7 · Lo que NO incluye vale tanto como lo que sí
La sección 03 de la plantilla no es un trámite: es prevención de scope creep, que según la base de conocimiento promedia **27% de sobrecosto** en proyectos sin control de alcance. La IA debe generar exclusiones **específicas del proyecto**, no genéricas.
*Malo:* "No incluye servicios no mencionados."
*Bueno:* "No incluye la migración del histórico de 4 años de pedidos que mencionaron en la reunión; eso se evalúa como fase 2 cuando el sistema base esté operando."
### P8 · Mantenimiento y evolución van separados, con límites por escrito
De la Sesión 4: *"No prometas mantenimiento gratuito indefinido y no vendas un retainer como si incluyera trabajo ilimitado."* La sección 05 debe listar explícitamente qué **no** cubre el plan (la plantilla ya tiene la clase `.plan-feat.muted` con ✕ para eso). El backlog de evolución se registra aparte y **no se compromete**.
### P9 · La incertidumbre se declara, no se rellena
Si falta información, la IA **no la inventa ni la omite silenciosamente**: la escribe en la sección 06 como material o decisión pendiente. Ver §10.2 — esto es el mecanismo central de honestidad del sistema.
### P10 · El asesor aprueba antes de enviar
El documento de IA nace en estado borrador. Nadie lo manda al cliente sin que un humano lo lea. El plugin es un copiloto de redacción, no un autopiloto de ventas.
*Corolario:* el flujo de UI debe hacer que revisar sea fácil (diff, semáforo de confianza, evidencia expandible), no que aprobar sea rápido.
---
## 5. Insights de monetización que hay que codificar
Estos son los mecanismos concretos de la base de conocimiento que el plugin debe hacer operativos. Cada uno con su traducción a comportamiento del sistema.
| # | Insight de la base de conocimiento | Cómo lo codifica el plugin |
|---|---|---|
| M1 | El cliente describe síntomas; tu trabajo es diagnosticar la enfermedad | La sección 01 nunca repite la petición del cliente ("quiero una página web"); reformula al problema de negocio ("pierden prospectos porque no tienen dónde mandarlos desde los anuncios") |
| M2 | El costo del problema se desglosa en 4 dimensiones | La IA busca en la transcripción las 4 dimensiones y las presenta con su etiqueta de confianza; las que faltan van a la sección 06 como pendiente de validar |
| M3 | Precio = 15-25% del valor anual | La IA calcula el **ratio inverso**: dado el total que fijó el humano y el valor anual detectado, reporta qué porcentaje representa. Si sale <10%, señala al asesor que probablemente subcotizó. Si sale >40%, señala que va a haber objeción de precio |
| M4 | 3 opciones cierran 16-28% más alto | Si `esDoble = false`, el plugin sugiere al asesor un esquema de 2-3 opciones basado en los servicios ya elegidos (quitando o agregando del mismo catálogo, sin inventar servicios) |
| M5 | Anclaje: la opción cara primero | En el render de la sección de opciones, el orden es A (mayor) → B (recomendada, `.featured`) → C (esencial) |
| M6 | La objeción de precio se responde con alcance, no con descuento | El documento incluye, en notas internas para el asesor (no visibles al cliente), el "plan de recorte": qué servicios quitar primero si el cliente pide bajar el precio, ordenados por menor impacto en el resultado prometido |
| M7 | Anticipo 50% obligatorio antes de empezar | El footer lo enuncia siempre; no es opcional ni negociable por la IA |
| M8 | Updates 2×/semana aumentan confiabilidad percibida +125% | La propuesta incluye el compromiso de cadencia de comunicación como **parte del alcance**, no como cortesía |
| M9 | El retainer se ofrece a las 2 semanas post-entrega, no al inicio | La sección 05 presenta el mantenimiento como **opción con límites explícitos**, nunca como requisito ni como amenaza velada ("para que no se rompa") |
| M10 | Las 3 capas de documentación triplican la tarifa | Los entregables documentales (README ejecutivo, registro de decisiones, guía de mantenimiento — adaptados a marketing digital: manual de operación de campañas, bitácora de decisiones de segmentación, guía de qué puede ajustar el cliente solo) se listan como entregables con valor, no como anexos |
| M11 | Red flags del cliente | El plugin genera, en notas internas, una sección de riesgo: red flags detectadas en la transcripción (pidió descuento antes de entender el valor, no hay decisor presente, no hay cifra del problema, "hagan todo y luego vemos") |
| M12 | Separar proyecto / mantenimiento / evolución | Tres bloques distintos en el documento, con encabezados que lo hagan obvio. El backlog de evolución dice explícitamente "no comprometido en esta propuesta" |
| M13 | Criterio ético: sólo se propone lo que hay evidencia de que resuelve un problema real | La IA **no puede** agregar un servicio del catálogo que el asesor no eligió. Puede señalar en notas internas *"el cliente mencionó X, que el catálogo cubre con el servicio Y; considera si aplica"* — pero no lo mete en la propuesta |
### 5.1 El indicador de salud de la cotización
De M3 y M11 sale la feature más útil para el negocio y la más fácil de implementar: un semáforo interno, sólo para el asesor, que evalúa la cotización antes de enviarla.
| Señal | Cómo se calcula | Qué significa |
|---|---|---|
| Ratio precio/valor | `total / valor_anual_detectado` | <10% subcotizado · 15-25% en rango · >40% objeción probable |
| Dolor cuantificado | ¿hay al menos una cifra confirmada del costo del problema? | Si no: no hay ancla de valor; la propuesta va a competir por precio |
| Usuario final entrevistado | ¿la transcripción incluye a quien operará, no sólo al que firma? | Si no: riesgo de baja adopción |
| Decisor presente | ¿se identificó a quien autoriza el gasto? | Si no: riesgo de "voy a preguntar" |
| Exclusiones definidas | ¿hay al menos 3 exclusiones específicas? | Si no: riesgo de scope creep |
| Materiales pendientes | conteo de la sección 06 | Alto: la fecha de entrega es irreal |
| Red flags | conteo de señales de la lista | ≥2: evaluar si conviene el proyecto |
Esto no es un adorno. Es **business intelligence real** sobre el pipeline: agregado en el tiempo, dice qué tipo de cotizaciones cierran y cuáles no.
---
## 6. Anatomía del documento de IA
El documento 2 hereda la estructura de la plantilla HTML, con tres cambios. Marcados **[NUEVO]** los que no existen en la plantilla.
| Sección | Origen del contenido | Notas |
|---|---|---|
| **Hero** | `Cliente`, `Cotizacion.numero`, `fecha`, `vigencia`, `proyecto`, asesor | El subtítulo lo redacta la IA: una o dos oraciones que enmarcan el problema en lenguaje del cliente |
| **01 · Diagnóstico** | Transcripción + notas + observaciones | `.quote` = cita literal obligatoria. Filas con semáforo: al menos 1 rojo, 1 ámbar, 1 azul, 1 verde. Cada fila con etiqueta de confianza |
| **01b · Valor del problema** **[NUEVO]** | Transcripción, con las 4 dimensiones de costo | Tabla: dimensión / cifra / estado (confirmado/estimado/por validar) / evidencia. Cierra con el valor anual y el ratio de M3 |
| **02 · Resultados a lograr** **[NUEVO]** | Derivado del diagnóstico + entregables de los servicios elegidos | 3-5 resultados de negocio cuantificados. Es el puente entre problema y precio. La plantilla no lo tiene y la base de conocimiento lo pide en toda propuesta |
| **03 · Alcance y desglose económico** | `ServicioCotizado[]`, agrupado por fase y `tipoPago` | **Números literales del documento 1.** La IA sólo reescribe las descripciones en lenguaje de resultado (P6). Separar pago único de mensual, como ya hace el PDF |
| **04 · Opciones de inversión** | `esDoble` + `opcionesMetadata` | Sólo si hay opciones reales. Orden A → B(`.featured`) → C |
| **05 · Qué no incluye** | Transcripción (menciones fuera de alcance) + `opcionesMetadata.noIncluye` | Exclusiones específicas, nunca genéricas (P7) |
| **06 · Por qué tiene sentido** | `ServicioCotizado.beneficios` + diagnóstico | Cada beneficio amarrado a un hallazgo del diagnóstico. Si un beneficio no responde a ningún dolor detectado, se elimina |
| **07 · Plan de mantenimiento** | `PlanBucefaloCotizacion`, servicios `tipoPago: mensual`, `modeloCobro: retainer` | Con exclusiones explícitas (`.plan-feat.muted`). Mensual vs anual si aplica |
| **08 · Estado de materiales y decisiones** | Todo lo que la IA no pudo determinar + menciones de dependencias en la transcripción | **El canal de honestidad.** Ver §10.2 |
| **09 · Backlog de evolución** **[NUEVO]** | Fricciones mencionadas por el cliente que no entran en fase 1 | Con encabezado explícito: "registrado, no comprometido en esta propuesta" |
| **Footer** | `Configuracion` (logo, colores) + condiciones fijas | 50/50, CFDI, avance condicionado a materiales, cambios se cotizan aparte, MXN |
| **Anexo interno** **[NUEVO]** | Todo lo de §5.1 + M6 + M11 | **No se entrega al cliente.** Semáforo de salud, plan de recorte, red flags, evidencia completa. Puede ser una segunda página o un archivo aparte |
### 6.1 Nota sobre el anexo interno
Esta es la parte del diseño que más valor operativo tiene y la que más cuidado necesita. Un documento con "plan de recorte de precio" y "red flags del cliente" enviado por error al cliente es un incidente serio.
Recomendación: **archivo separado**, nombre distinto y visualmente inconfundible (fondo distinto, marca de agua "INTERNO — NO ENVIAR"). No una sección oculta del mismo archivo, no un `display: none`, no un comentario HTML.
---
## 7. Arquitectura de ingesta de contexto
### 7.1 Las cuatro fuentes
| Fuente | Formato | Volumen típico | Confianza |
|---|---|---|---|
| **Transcripción de reunión** | `.txt`, `.md`, `.vtt`, `.srt` | 60 min ≈ 9,000 palabras ≈ 13K tokens | Alta para citas; media para cifras (la gente redondea al hablar) |
| **Notas del asesor** | `.md`, `.txt` | 200-2,000 palabras | Alta — es interpretación experta |
| **Campos del formulario** | `Cotizacion.observaciones`, `ServicioCotizado.notas` | 50-500 palabras | Alta — escrito con intención |
| **Cotización estructurada** | JSON desde Prisma/MCP | 3-5K tokens | **Absoluta** — es la fuente de verdad |
### 7.2 Precedencia en caso de conflicto
Cuando dos fuentes se contradicen:
```
Cotización estructurada > Notas del asesor > Observaciones > Transcripción
```
*Razón:* la cotización es dato validado; las notas son interpretación experta posterior a la reunión; la transcripción es materia prima cruda con ruido de ASR, muletillas y correcciones en vivo ("son como 20 horas… no, más bien 30").
Si el conflicto es sobre una **cifra**, la IA no elige: lo reporta en la sección 08 como decisión pendiente. *"En la reunión se mencionaron 20 y 30 horas semanales en momentos distintos; confirmar la cifra antes de calcular el valor anual."*
### 7.3 Pipeline de preprocesamiento
Antes de que un token llegue al modelo:
1. **Normalización de formato** — VTT/SRT a texto plano con marcas de tiempo opcionales; Markdown se conserva.
2. **Sanitización de PII** — Esto es obligatorio, no opcional. Las transcripciones contienen nombres de empleados, comentarios sobre desempeño, cifras salariales, quejas sobre terceros. Se redactan nombres de personas que no son el interlocutor comercial, y se marca cualquier mención de temas laborales, legales o de salud como bloque excluido del documento final.
3. **Segmentación por hablante** cuando el formato lo permite — permite aplicar la regla 80/20 y detectar si se entrevistó al usuario operativo o sólo al decisor.
4. **Conteo de tokens** con `client.messages.countTokens` (nunca con estimadores de otros proveedores) para decidir si cabe entero o requiere segmentación.
5. **Detección de idioma** — si la transcripción tiene mezcla, se preserva; el documento final va en español.
### 7.4 Dónde se suben los archivos
Tres opciones, en orden de preferencia:
1. **Nuevo campo en la UI de cotización** — una zona de drop en la pestaña de observaciones. Los archivos se guardan como adjuntos vinculados a la `Cotizacion`. Requiere un modelo nuevo (`ContextoCotizacion`: `cotizacionId`, `tipo`, `nombreArchivo`, `contenido`/`ruta`, `createdAt`).
2. **Carpeta convenida en disco** — más simple para un MVP, peor para el despliegue en Coolify (contenedor sin volumen persistente por defecto). Sirve para probar localmente.
3. **Files API de Anthropic** (beta `files-api-2025-04-14`) — útil si se quiere pasar un PDF de reunión sin extraer texto; límite 500 MB. Requiere el header beta tanto en el upload como en el `messages.create` que lo referencia.
Para el MVP: opción 2 para validar la calidad del output; opción 1 para producción.
---
## 8. Contrato de salida
La IA **no genera HTML**. Genera un objeto estructurado que un renderizador convierte a HTML usando la plantilla. Esto es crítico por tres razones: valida la estructura antes de renderizar, permite que el asesor edite campo por campo, y evita que la IA rompa el CSS o inyecte markup arbitrario.
La API soporta esto nativamente con `output_config: { format: { type: "json_schema", schema: {...} } }` (structured outputs), disponible en Opus 5, Sonnet 5 y Haiku 4.5. En TypeScript hay helper de Zod: `zodOutputFormat()` + `client.messages.parse()`, que devuelve el objeto ya validado en `response.parsed_output`.
### 8.1 Forma conceptual del schema
```
PropuestaConsultiva
├─ meta: { numeroCotizacion, cliente, empresa, proyecto, vigencia, asesor }
├─ hero: { titulo, subtitulo }
├─ diagnostico:
│ ├─ citaLiteral: { texto, origen } ← obligatorio, literal
│ └─ hallazgos[]: { urgencia: rojo|ambar|azul|verde,
│ titulo, descripcion,
│ confianza: confirmado|estimado|por_validar,
│ evidencia }
├─ valorProblema:
│ ├─ dimensiones[]: { tipo: dinero|tiempo|oportunidad|error,
│ descripcion, montoAnualMXN|null,
│ confianza, evidencia }
│ ├─ valorAnualEstimadoMXN: number|null
│ └─ notaMetodologia: string ← cómo se llegó a la cifra
├─ resultados[]: { enunciado, metrica, lineaBase|null, periodoMedicion }
├─ alcance:
│ └─ items[]: { fase, categoria, nombre,
│ descripcionResultado, ← reescritura en lenguaje de beneficio
│ precioMXN, tipoPago, tiempoEntrega }
├─ totales: { subtotal, descuento, iva, total, moneda } ← COPIADO, nunca calculado
├─ opciones[]|null: { etiqueta, titulo, descripcion, paraQuien,
│ incluye[], noIncluye[], recomendada: bool }
├─ exclusiones[]: { texto, razon, origen } ← específicas del proyecto
├─ beneficios[]: { etiqueta, texto, hallazgoRelacionado } ← amarrado al diagnóstico
├─ mantenimiento|null:
│ └─ planes[]: { nombre, periodicidad, precioMXN, incluye[], noIncluye[], destacado }
├─ pendientes:
│ ├─ materiales[]: { texto, estado: recibido|pendiente, bloqueaEntrega: bool }
│ └─ decisiones[]: { texto, quienDecide, fechaSugerida }
├─ backlogEvolucion[]: { problema, impactoPosible, evidencia, momentoSugerido }
└─ interno: ← NUNCA en el documento del cliente
├─ salud: { ratioPrecioValor, dolorCuantificado, usuarioFinalEntrevistado,
│ decisorPresente, exclusionesDefinidas, materialesPendientes }
├─ planRecorte[]: { servicio, impactoEnResultado: bajo|medio|alto, ordenSugerido }
├─ redFlags[]: { señal, evidencia, severidad }
└─ huecos[]: { queFalta, porQueImporta, comoObtenerlo }
```
### 8.2 Restricciones del JSON Schema en la API
Hay que diseñar el schema con estos límites en mente:
- **Soportado:** tipos básicos, `enum`, `const`, `anyOf`, `allOf`, `$ref`/`$def`, formatos de string (`date`, `date-time`, `email`, `uri`, `uuid`).
- **No soportado:** esquemas recursivos, restricciones numéricas (`minimum`, `maximum`, `multipleOf`), restricciones de string (`minLength`, `maxLength`), restricciones complejas de array.
- **Obligatorio:** `additionalProperties: false` en todos los objetos.
- Los SDK de Python y TypeScript quitan automáticamente las restricciones no soportadas del schema enviado y las validan del lado del cliente — así que se pueden usar en Zod, sabiendo que la validación es local.
- Incompatible con citations (devuelve 400) y con prefill de mensaje de asistente.
- Primera petición con un schema nuevo tiene costo de compilación; después hay caché de 24h.
### 8.3 Reglas de validación post-generación (código, no IA)
Después de recibir el objeto y antes de renderizar:
1. `totales` debe ser **idéntico** al de la cotización en BD. Si no, se descarta el objeto y se registra el fallo. Sin excepciones.
2. Cada `alcance.items[].precioMXN` debe existir en `ServicioCotizado`. Ningún item nuevo, ningún precio distinto.
3. `diagnostico.citaLiteral.texto` debe encontrarse como substring (normalizado) en alguna fuente de contexto. Si no aparece, se marca como no verificada y se pide revisión.
4. Todo `hallazgo` con `confianza: confirmado` debe tener `evidencia` no vacía.
5. `interno` se separa del objeto antes de pasar al renderizador del documento del cliente.
6. Si `valorProblema.valorAnualEstimadoMXN` es `null`, el documento **no** puede afirmar un ratio precio/valor.
---
## 9. Lineamientos del prompt
### 9.1 Estructura de capas
El prompt se arma en tres capas, ordenadas por estabilidad (esto importa para el caché — ver §11.3):
```
Capa 1 — ESTABLE (idéntica en toda cotización, cacheable)
· Identidad y rol
· Filosofía (los 10 principios de §4)
· Frameworks de diagnóstico y pricing
· Reglas de marca y confidencialidad
· Contrato de salida y reglas de validación
· Catálogo de servicios activo (snapshot)
· Ejemplos de buena y mala redacción
Capa 2 — SEMI-ESTABLE (por cliente o sector)
· Historial del cliente si es recurrente
· Notas del sector
Capa 3 — VOLÁTIL (por cotización)
· Cotización estructurada (JSON)
· Transcripción sanitizada
· Notas y observaciones
· Instrucción específica del asesor
```
Nada dinámico —fechas, IDs, timestamps— debe entrar en la capa 1. Una fecha interpolada en el system prompt invalida el caché de todo lo que viene después.
### 9.2 Reglas del system prompt
Adaptando el prompt maestro de `s8-Prompts-Plantillas.md` §1 al contexto de E3:
**Identidad.** Consultor senior de digitalización de negocios para PyMEs mexicanas. Redacta propuestas comerciales consultivas para Consultoría E3 (Querétaro, MX). No es vendedor: es diagnosticador.
**Reglas de contenido.**
1. Cita fuentes internamente para cada dato del cliente. Si no hay fuente, no se escribe.
2. Etiqueta toda cifra como confirmada, estimada o por validar.
3. Traduce toda capacidad técnica a dinero, tiempo, riesgo evitado o tranquilidad operativa.
4. Usa las palabras textuales del cliente en el diagnóstico.
5. Nunca proponer un servicio que el asesor no eligió.
6. Nunca calcular, sugerir ni modificar un precio.
7. Cuando falte información, escribirla como pendiente — jamás rellenarla.
8. Español de México, tono cercano y profesional, tuteo con el cliente cuando el registro de la reunión lo permita. Sin lenguaje corporativo vacío (*sinergias*, *holístico*, *stakeholders*, *ecosistema*, *disruptivo*).
9. Moneda: MXN. IVA 16%. Facturación CFDI.
10. El CRM se llama **Bucéfalo**. No se menciona ninguna otra plataforma de CRM.
11. E3 ofrece únicamente servicios digitales. Si en la reunión se pidió algo de marketing tradicional o diseño para imprenta, va a la sección de exclusiones aclarando que no es un servicio de E3.
**Prohibiciones explícitas.**
- No importar rangos de precio en USD de ninguna base de conocimiento.
- No incluir datos personales de empleados del cliente, información salarial, ni temas legales o de prestaciones. Si la reunión los tocó, se omiten del documento y se anota en el bloque interno que el tema debe manejarse por el canal correspondiente.
- No prometer resultados garantizados en pauta o posicionamiento (número de ventas, posición #1 en Google). Se prometen entregables, procesos y métricas de seguimiento.
- No prometer soporte ilimitado.
- No usar la palabra "garantizado" sobre resultados de mercado.
**Formato de razonamiento.** Con `claude-opus-5` el thinking está activo por defecto. Conviene dejarlo así: el diagnóstico requiere razonamiento multi-paso (leer transcripción → detectar dolor → cuantificar → cruzar con servicios elegidos → redactar). No hay que desactivarlo.
### 9.3 Descomposición en tareas
Un solo prompt monolítico va a producir un documento mediocre en todas sus partes. Mejor pipeline de 3 pasos, cada uno con su schema:
| Paso | Entrada | Salida | Modelo sugerido |
|---|---|---|---|
| **1 · Extracción** | Transcripción + notas | Hechos estructurados: dolores, cifras con confianza, citas literales, materiales mencionados, decisiones pendientes, red flags, menciones fuera de alcance | Opus 5 (`effort: high`) — es el paso que determina la calidad de todo lo demás |
| **2 · Diagnóstico y valoración** | Hechos del paso 1 + cotización estructurada + catálogo | Hallazgos con semáforo, valor del problema, resultados a lograr, ratio precio/valor, semáforo de salud | Opus 5 (`effort: high`) |
| **3 · Redacción** | Salida de pasos 1 y 2 | `PropuestaConsultiva` completa | Opus 5 (`effort: medium`) — con el análisis hecho, esto es principalmente escritura |
Ventajas de separar: cada paso se evalúa por separado, el paso 1 se puede cachear si sólo cambia la cotización, y el asesor puede corregir los hechos del paso 1 antes de que se propaguen.
### 9.4 Ejemplos en el prompt
La base de conocimiento es enfática en que los **ejemplos positivos** funcionan mejor que las prohibiciones. Hay que incluir en la capa 1 al menos:
- 2 ejemplos de diagnóstico bien escrito (uno con dolor cuantificado, uno donde falta la cifra y se declara)
- 2 ejemplos de descripción de servicio traducida a resultado
- 2 ejemplos de exclusión específica vs. genérica
- 1 ejemplo de sección 08 bien poblada
- 1 ejemplo de qué se ve cuando la transcripción es pobre (documento honesto con muchos pendientes, en lugar de documento inventado)
Ese último ejemplo es el más importante y el que se suele omitir.
---
## 10. Guardarraíles y riesgos
### 10.1 Matriz de riesgos
| Riesgo | Severidad | Mitigación |
|---|---|---|
| **La IA inventa un precio** | Crítica | P1 + validación programática §8.3.1. Los totales se toman del objeto de cotización en el render, no del texto generado |
| **La IA inventa una cifra del cliente** | Crítica | Etiqueta de confianza obligatoria + campo `evidencia` + validación de que las citas existan en las fuentes |
| **Fuga de datos personales de empleados** | Crítica | Sanitización de PII previa (§7.3.2) + prohibición explícita en el prompt + revisión humana |
| **El anexo interno llega al cliente** | Crítica | Archivo separado con marca visual inconfundible, nunca sección oculta (§6.1) |
| **Promesa de resultado garantizado en pauta/SEO** | Alta | Prohibición explícita + lista de palabras vetadas en validación post-generación |
| **Importación de precios en USD desde el vault** | Alta | Prohibición explícita + validación: ningún monto del documento puede estar en USD ni ser un número que no exista en la cotización |
| **Se menciona una plataforma de CRM que no es Bucéfalo** | Alta | Regla de marca en prompt + validación por lista de términos prohibidos |
| **La propuesta contradice el PDF manual** | Alta | Los dos documentos se generan del mismo objeto de cotización; el de IA se regenera si la cotización cambia (invalidación por `updatedAt`) |
| **Scope creep porque las exclusiones son genéricas** | Media | Requerir mínimo 3 exclusiones con campo `origen` no vacío; si la IA no puede justificarlas, el documento se marca como incompleto |
| **La IA propone servicios que el asesor no eligió** | Media | P1 + validación §8.3.2. Las sugerencias van sólo al bloque interno |
| **Costo de API descontrolado** | Baja | Ver §11.4: el costo es despreciable frente al ticket. Aun así: caché de prefijo + límite de tamaño de transcripción + conteo previo de tokens |
| **El asesor aprueba sin leer** | Media | La UI debe hacer visible el semáforo de salud y el conteo de afirmaciones sin evidencia **antes** del botón de aprobar |
| **Rechazo por clasificador de seguridad** | Baja | Manejar `stop_reason: "refusal"` antes de leer `content`; activar `fallbacks: "default"`. Poco probable en este dominio pero el código debe no reventar |
### 10.2 El mecanismo central de honestidad
Este es el diseño del que depende que el sistema sea confiable, y merece su propia sección.
**El problema.** Todo generador de documentos con LLM tiene la misma tentación: cuando falta información, rellenar con plausible. Una propuesta comercial con una cifra inventada del negocio del cliente no es un error cosmético — es una mentira con el logo de E3 encima, que el cliente puede refutar en la reunión de presentación.
**La solución.** La plantilla HTML ya trae el canal de salida para la incertidumbre: la **sección 06, Estado de materiales del cliente**, con sus dos tarjetas y tres estados (`done` ✓, `pend` ○, `neutral` ·).
Se convierte esa sección en el destino obligatorio de todo hueco de información:
```
¿La IA no encontró el dato?
├─ ¿Es un material que el cliente debe entregar?
│ → sección 08, tarjeta "Materiales", estado pendiente
├─ ¿Es una decisión que el cliente debe tomar?
│ → sección 08, tarjeta "Decisiones", con quién decide y fecha sugerida
├─ ¿Es una cifra del negocio que nadie confirmó?
│ → sección 01b con confianza "por_validar", y punto a confirmar en la 08
└─ ¿Es información que el asesor necesita conseguir?
→ bloque interno, campo `huecos`, con "qué falta / por qué importa / cómo obtenerlo"
```
**Lo elegante del diseño:** un hueco de información deja de ser un defecto del documento y se vuelve **contenido de valor**. Un cliente que recibe una propuesta con una sección clara de "esto necesitamos de ustedes, y esto está pendiente de decidir" percibe rigor, no incompetencia. Y de paso transfiere la responsabilidad del retraso a donde corresponde — que es exactamente lo que dice el footer de la plantilla: *"El avance queda condicionado a la entrega de materiales por parte del cliente."*
**La regla de oro operativa:** una propuesta con 8 pendientes honestos es infinitamente mejor que una con 8 cifras inventadas. El prompt debe decir esto literalmente, y el ejemplo de §9.4 debe demostrarlo.
---
## 11. Consideraciones técnicas
### 11.1 Elección de modelo
Recomendación: **`claude-opus-5`** para los tres pasos del pipeline.
| Modelo | Precio (entrada / salida por MTok) | Contexto | Cuándo usarlo aquí |
|---|---|---|---|
| `claude-opus-5` | $5 / $25 | 1M | **Recomendado.** Los tres pasos. Es una cotización de decenas de miles de pesos; la diferencia de costo con Sonnet es de centavos |
| `claude-sonnet-5` | $3 / $15 (intro $2 / $10 hasta 2026-08-31) | 1M | Alternativa si el volumen crece mucho. Probar en el paso 3 (redacción) antes que en el 1 (extracción) |
| `claude-haiku-4-5` | $1 / $5 | 200K | Sólo para tareas mecánicas auxiliares: detectar idioma, clasificar tipo de archivo, sanitizar formato |
**Por qué Opus 5 y no el más barato:** la calidad del diagnóstico es el producto. Un diagnóstico mediocre produce una propuesta que compite por precio, y eso cuesta miles de pesos de margen. Ahorrar $0.15 USD por documento para perder 10% de ticket es una decisión de negocio terrible. El costo del modelo no es la variable a optimizar aquí.
**Detalles de la API que importan:**
- El thinking está **activo por defecto** en Opus 5 — no hay que configurarlo. `output_config: { effort: "high" }` para pasos 1 y 2, `"medium"` para el 3.
- `max_tokens` limita thinking + texto juntos. Para el paso 3, que produce un documento completo, hay que dar holgura: **usar streaming** con `max_tokens` alto (>16K obliga a streaming para no chocar con timeouts HTTP del SDK).
- No usar `temperature`, `top_p` ni `top_k` — están removidos en Opus 5 y devuelven 400.
- No usar prefill de mensaje de asistente — devuelve 400. Para forzar formato: structured outputs.
- Manejar `stop_reason: "refusal"` antes de leer `content`, y activar `fallbacks: "default"` con el header beta `server-side-fallback-2026-07-01`.
### 11.2 SDK y punto de integración
El proyecto es TypeScript/Next.js → **`@anthropic-ai/sdk`**. Nada de llamadas HTTP crudas ni de shims compatibles con otros proveedores.
Dos alternativas de arquitectura:
**Opción A — Route handler en Next.js.** `src/app/api/propuesta-ia/[id]/route.ts`, siguiendo el patrón de `export/pdf/[id]`. Más simple, un solo despliegue, comparte auth JWT y middleware. Riesgo: un paso de 3 llamadas con `effort: high` puede tardar minutos; requiere streaming al cliente o un patrón de job asíncrono (crear job → poll de estado → descargar).
**Opción B — En el servicio Python de `api/`.** Ya tiene MCP y auth por API key, y está pensado para agentes. Ventaja: la generación no bloquea el servidor web. Desventaja: duplica la lógica del prompt en otro lenguaje, y el proyecto ya sufre de duplicación de `calculators`.
**Recomendación:** Opción A con patrón de job. Un modelo nuevo (`PropuestaIA`: `cotizacionId`, `estado`, `objetoGenerado` JSON, `htmlRenderizado`, `costoTokens`, `createdAt`, `aprobadaPor`, `aprobadaAt`) permite historial, auditoría y regeneración sin perder versiones anteriores.
### 11.3 Caché de prompt
El caché es prefix match: cualquier cambio de un byte invalida todo lo que sigue. Orden de render: `tools``system``messages`.
Diseño para este caso:
| Contenido | Tamaño estimado | Cacheable | Notas |
|---|---|---|---|
| Filosofía + frameworks + reglas + contrato + ejemplos | 12-20K tokens | **Sí** — breakpoint aquí | Congelado. Cambia sólo cuando se edita la filosofía |
| Catálogo de servicios activo | 3-6K tokens | **Sí** — segundo breakpoint | Cambia cuando se edita el catálogo; serializar con orden determinista (por `orden`, `id`) |
| Cotización estructurada | 3-5K tokens | No | Varía por cotización |
| Transcripción + notas | 5-20K tokens | No | Varía por cotización |
Notas operativas:
- El mínimo cacheable en Opus 5 es **512 tokens** (bajó desde 1024 en Opus 4.8). La capa 1 lo supera con holgura.
- Máximo 4 breakpoints por petición. Con dos alcanza.
- Lectura de caché ≈ 0.1× del precio de entrada; escritura 1.25× (TTL 5 min) o 2× (TTL 1h). Con 2+ peticiones el TTL de 5 minutos ya sale a favor — y el pipeline de 3 pasos garantiza al menos 3 peticiones seguidas con el mismo prefijo.
- **Invalidadores silenciosos a evitar:** `new Date()` en el system prompt, `JSON.stringify` de un objeto con orden de llaves no determinista, el número de cotización en la capa 1, cambio de modelo a media conversación.
- Verificar con `response.usage.cache_read_input_tokens`. Si sale 0 en peticiones repetidas con el mismo prefijo, hay un invalidador escondido.
### 11.4 Costos estimados
Escenario base por documento (una cotización con transcripción de 60 min):
```
Entrada: capa estable ~18K + catálogo ~5K + cotización ~4K + contexto ~15K ≈ 42K tokens
Salida: objeto estructurado + razonamiento ≈ 8K tokens
Peticiones: 3 (pipeline de §9.3), las 3 comparten prefijo de 23K
```
| Configuración | Costo estimado por documento |
|---|---|
| Opus 5 sin caché, 1 petición | ≈ $0.41 USD |
| Opus 5 con caché, pipeline de 3 pasos | ≈ **$0.30 $0.55 USD** |
| Sonnet 5 con caché (precio intro) | ≈ $0.12 $0.22 USD |
| Batch API (50% descuento) si se generan en lote nocturno | ≈ mitad de lo anterior |
A 20 MXN/USD: **entre $6 y $11 MXN por documento** con Opus 5.
**El insight de negocio:** el paquete PyME más barato del catálogo es de ~$7,490 MXN. El costo de generar su propuesta consultiva es **0.1% del ticket**. En el paquete de escalamiento ($90,800 MXN) es 0.01%.
Con 40 cotizaciones al mes: **~$1222 USD/mes** (~$240440 MXN). Menos que una comida.
Conclusión: **el costo del modelo no es una restricción de diseño.** Cualquier decisión que sacrifique calidad de output para ahorrar tokens está optimizando la variable equivocada. Optimizar para calidad, medir con `countTokens` para no llevarse sorpresas, y ya.
### 11.5 Renderizado del documento
La plantilla HTML es autocontenida (CSS inline, sin dependencias externas más que Google Fonts). Dos rutas:
1. **HTML directo** — un renderizador toma el objeto validado y produce el HTML usando la plantilla como base. Ventajas: fiel al diseño, imprimible con `@media print`, editable, ligero. Requiere sustituir Google Fonts por fuentes embebidas si se quiere funcionamiento offline o dentro de un PDF.
2. **PDF vía PDFKit** — reutiliza `pdf-generator.ts`. Coherente con el resto del sistema, pero la plantilla HTML tiene gradientes, radial-gradients y tipografía serif/sans mezclada que en PDFKit son trabajo considerable.
**Recomendación:** HTML como entregable primario (se ve mejor, se comparte por link o adjunto, y el cliente lo abre en el celular). Si se necesita PDF, imprimir el HTML desde el navegador o con un headless — no reimplementar el diseño en PDFKit.
Nota heredada del proyecto: en `pdf-generator.ts` hay un bug documentado de auto-page-break en el footer (`doc.text()` en `y > page.height - margins.bottom` dispara página nueva). Si se va por PDFKit, ese bug ya tiene workaround en el código: poner `margins.bottom = 0` temporalmente.
Los colores y el logo salen de `Configuracion` (`color_primario`, `color_secundario`, `logo_base64`), así que el documento respeta la marca sin hardcodear.
---
## 12. Métricas de éxito del plugin
Si no se puede medir, no se sabe si sirvió. Estas son las métricas, separadas por qué preguntan.
### 12.1 ¿La IA escribe bien? (calidad del output)
| Métrica | Cómo medirla | Meta inicial |
|---|---|---|
| Tasa de edición del asesor | % de campos del objeto modificados antes de aprobar | <30% |
| Afirmaciones sin evidencia | Conteo por documento (validación automática) | 0 |
| Citas no verificables | Citas que no aparecen en las fuentes | 0 |
| Rechazos completos | Documentos descartados y regenerados desde cero | <10% |
| Tiempo de revisión | Minutos entre generación y aprobación | <15 min |
### 12.2 ¿Sirvió comercialmente? (impacto en el negocio)
| Métrica | Cómo medirla | Por qué importa |
|---|---|---|
| Tasa de cierre con vs. sin documento consultivo | Comparar `estado: aprobada` entre cotizaciones con y sin propuesta de IA | La prueba central de la tesis |
| Ticket promedio | Total promedio de cotizaciones aprobadas, ambos grupos | La base de conocimiento predice +16-28% con opciones bien presentadas |
| Objeciones de precio | Registrar en `observaciones` si el cliente pidió descuento | Un buen anclaje de valor debería reducirlas |
| Tiempo de ciclo | Días entre `fecha` y cambio a `aprobada`/`rechazada` | Una propuesta clara decide más rápido, en cualquier dirección |
| Scope creep | Cotizaciones que requirieron orden de cambio | El objetivo de las exclusiones específicas |
| Conversión a mensualidad | % de cotizaciones aprobadas que incluyen servicio `mensual` o plan Bucéfalo | El objetivo de la sección de mantenimiento |
**Advertencia metodológica:** con 40 cotizaciones al mes, cualquier comparación de tasa de cierre tarda meses en ser significativa, y hay mil variables confundidas (el asesor, el sector, la temporada, el tamaño del cliente). No conviene tomar decisiones grandes con 3 semanas de datos. Lo honesto es empezar midiendo §12.1, que sí es medible de inmediato, y dejar §12.2 acumular.
### 12.3 ¿Cuesta lo que debe? (operación)
- Costo por documento generado (tokens de entrada/salida × precio, guardado en `PropuestaIA.costoTokens`)
- Tasa de aciertos de caché (`cache_read_input_tokens / total`)
- Latencia p50 y p95 del pipeline completo
- Tasa de fallos: refusals, timeouts, validaciones rechazadas
---
## 13. Roadmap sugerido
Cada fase entrega algo usable. Ninguna requiere la siguiente para tener valor.
### Fase 0 — Ganancia inmediata sin IA (días)
**Imprimir `observaciones` y `notas` en el PDF y el Excel.** Es un cambio de pocas líneas en `pdf-generator.ts` y `excel-builder.ts`, y recupera información que ya se está capturando y descartando.
Esto no requiere nada de este documento. Debería hacerse ya, independientemente de si el plugin se construye.
### Fase 1 — Validación de calidad (1-2 semanas)
Sin UI, sin base de datos, sin despliegue. Un script que:
- Lee una cotización existente vía la API o Prisma
- Lee una transcripción de un archivo local
- Corre el pipeline de 3 pasos
- Escupe el objeto JSON y un HTML
**El entregable real no es el script: son 5-10 documentos generados sobre cotizaciones reales pasadas, revisados por el asesor.** Si esos documentos no son buenos, nada de lo demás importa y hay que iterar el prompt, no construir infraestructura.
Criterio de avance: el asesor dice *"esto lo mandaría a un cliente después de editarlo 10 minutos."*
### Fase 2 — Integración mínima (2-3 semanas)
- Modelo `PropuestaIA` y `ContextoCotizacion` en Prisma
- Zona de carga de archivos en `CotizacionForm.tsx`
- Route handler con patrón de job (crear → poll → descargar)
- Renderizador HTML desde la plantilla
- Vista de revisión con semáforo de salud y evidencia expandible
- Botón de aprobación que registra quién y cuándo
### Fase 3 — Inteligencia comercial (3-4 semanas)
- Anexo interno como archivo separado
- Semáforo de salud de §5.1 en el dashboard, agregado sobre todas las cotizaciones
- Sugerencia de esquema de 2-3 opciones cuando `esDoble = false`
- Alerta de subcotización (ratio precio/valor <10%)
- Métricas de §12.1 instrumentadas
### Fase 4 — Cierre del ciclo (después, con datos)
- Aprendizaje de las ediciones del asesor: qué corrige sistemáticamente → ajuste del prompt
- Comparación de tasa de cierre (sólo cuando haya volumen suficiente)
- Herramienta MCP nueva: `generar_propuesta_consultiva` en `api/app/mcp/tools.py`, para que un agente externo pueda pedirla
- Reutilización del documento en la conversación de retainer a las 2 semanas post-entrega (M9)
---
## 14. Decisiones abiertas
Cosas que hay que decidir antes de implementar y que este análisis no puede resolver solo.
| # | Decisión | Opciones | Recomendación |
|---|---|---|---|
| D1 | ¿Dónde se genera? | Route handler en Next.js vs. servicio Python | Next.js con patrón de job (§11.2) |
| D2 | ¿Dónde viven las transcripciones? | Adjuntos en BD · disco · Files API | Disco para Fase 1, adjuntos en BD para Fase 2 |
| D3 | ¿Un documento o dos archivos? | Documento del cliente + anexo interno separados, o uno solo | **Dos archivos.** El riesgo de fuga del anexo es demasiado alto (§6.1) |
| D4 | ¿HTML o PDF como entregable? | HTML · PDF · ambos | HTML primario; PDF por impresión del navegador si se necesita |
| D5 | ¿El plugin puede sugerir servicios? | Sí en la propuesta · sólo en el anexo interno · no | **Sólo en el anexo interno** (M13, criterio ético) |
| D6 | ¿Se regenera al cambiar la cotización? | Automático · manual con aviso · manual silencioso | Manual con aviso de desincronización visible |
| D7 | ¿Quién puede aprobar? | Cualquier asesor · sólo el dueño de la cotización · rol admin | El asesor dueño; admin puede aprobar cualquiera |
| D8 | ¿Se guarda la transcripción cruda o sólo la sanitizada? | Cruda · sanitizada · ambas | Sólo sanitizada en BD. La cruda no debe persistir con datos de empleados |
| D9 | ¿Se versiona el prompt? | Sí, con las propuestas apuntando a su versión · no | Sí. Sin esto no se puede saber si un cambio de prompt mejoró o empeoró |
| D10 | ¿Qué pasa si no hay transcripción? | Bloquear · generar con lo que haya · generar sólo el esqueleto | Generar con lo que haya, con la sección 08 muy poblada y aviso claro de confianza baja |
---
## Anexo A — Mapeo campo → sección
Referencia rápida para implementación.
| Sección del documento | Fuentes de datos |
|---|---|
| Hero | `Cliente.nombre`, `.empresa`, `Cotizacion.numero`, `.fecha`, `.vigencia`, `.proyecto`, `User.name` (asesor) |
| 01 Diagnóstico | Transcripción, `Cotizacion.observaciones`, `ServicioCotizado.notas`, archivos de notas |
| 01b Valor del problema | Transcripción (4 dimensiones), `totales.total` para el ratio |
| 02 Resultados | Derivado del diagnóstico + `ServicioCotizado.entregables` |
| 03 Alcance | `ServicioCotizado[]` (nombre, fase, tipoPago, precio, tiempoEntrega, entregables), `Categoria.nombre` |
| Totales | `calculators.ts` — copiados literalmente, `IVA_RATE`, descuentos |
| 04 Opciones | `Cotizacion.esDoble`, `.opcionesMetadata`, `ServicioCotizado.opcion` |
| 05 No incluye | Transcripción (menciones fuera de alcance), `opcionesMetadata[].noIncluye` |
| 06 Por qué tiene sentido | `ServicioCotizado.beneficios`, cruzado con hallazgos del diagnóstico |
| 07 Mantenimiento | `PlanBucefaloCotizacion`, servicios con `tipoPago: mensual`, `modeloCobro: retainer`, `Bono[]` |
| 08 Materiales y decisiones | Huecos detectados + dependencias mencionadas en la transcripción |
| 09 Backlog | Fricciones mencionadas fuera del alcance de fase 1 |
| Footer | `Configuracion.logo_base64`, `.color_primario`, `.color_secundario` + condiciones fijas |
| Financiamiento (si aplica) | `FinanciamientoPlan[]`, `Cotizacion.incluirFinanciamiento`, `calcularFinanciamiento()` |
| Anexo interno | Todo lo anterior + `RegistroHoras` si aplica + análisis de §5.1 |
---
## Anexo B — Checklist de calidad antes de enviar
Adaptado de `Onboarding-Cliente/00-Guia-de-Uso-y-Checklist-Calidad.md`. Este checklist debe estar visible en la UI de revisión, no enterrado en un documento.
**Problema y valor**
- [ ] El problema está redactado en lenguaje del cliente, sin jerga técnica
- [ ] Hay al menos un ejemplo real y reciente del problema, citado
- [ ] Se estimó el costo anual, con las cifras etiquetadas por confianza
- [ ] La métrica de éxito tiene línea base, resultado deseado y periodo
- [ ] Consta si se habló con el usuario operativo, no sólo con quien autoriza
**Viabilidad y alcance**
- [ ] Se sabe dónde viven los datos/accesos y quién los autoriza
- [ ] La fase 1 resuelve un cuello de botella prioritario, no todos
- [ ] Está explícito: incluido ahora / excluido ahora / backlog futuro
- [ ] Hay responsables del cliente y decisiones pendientes identificadas
- [ ] Está definido qué significa "terminado" y quién acepta
**Propuesta comercial**
- [ ] Si hay opciones, cambian alcance o nivel de servicio — no sólo el precio
- [ ] La opción recomendada sí cumple el resultado de negocio definido
- [ ] El precio se sustenta en valor, costo real y mercado
- [ ] El mantenimiento aparece con servicios concretos, límites y tiempos de respuesta
- [ ] Se presentará en llamada, no como cifra suelta por mensajería
**Integridad del documento generado**
- [ ] Todo número coincide con el documento manual
- [ ] Cero afirmaciones sin evidencia
- [ ] Cero cifras marcadas como confirmadas sin origen
- [ ] Ningún dato personal de empleados del cliente
- [ ] Ningún monto en USD
- [ ] Ninguna promesa de resultado garantizado
- [ ] El CRM se menciona como Bucéfalo
- [ ] El anexo interno está en archivo separado y no se va a enviar
---
## Anexo C — Cruce con la base de conocimiento
Para profundizar durante la implementación:
- **Preguntas de diagnóstico completas:** `Base de Conocimiento - IA Negocios y Dev/03-Preguntas-Guia.md`
- **Playbooks de pricing y cierre:** `08-Monetizacion-Onboarding-Pricing-Seguimiento.md`
- **Errores a evitar:** `01-Errores-a-Evitar.md`, `sintesis/s3-Errores-Fatales.md`
- **Modelos de pricing detallados:** `sintesis/s2-Pricing-Cobranza.md`
- **Prompts y plantillas base:** `sintesis/s8-Prompts-Plantillas.md` (§1 system prompt, §3 diagnóstico, §4 propuesta, §9 output estándar)
- **Las cuatro sesiones de onboarding:** `Onboarding-Cliente/01` a `04`, con `00-Guia-de-Uso-y-Checklist-Calidad.md` como criterio de calidad
- **Playbook maestro:** `Guia_Onboarding_Cliente_y_Ruta_de_Trabajo.md`
- **Paquetes del catálogo:** `docs/paquetes-recomendados-pyme.md` (este repo)
- **Convenciones del proyecto:** `AGENTS.md` (este repo)
---
## Cierre
El Cotizador E3 ya sabe cuánto cobrar. Lo que le falta es explicar por qué vale.
Ese "por qué" no se inventa: se extrae de lo que el cliente ya dijo en la reunión, de lo que el asesor ya anotó en el campo de observaciones, y del catálogo que ya está armado. Está todo ahí, disperso y sin usar.
El plugin no es un generador de texto bonito. Es un **traductor**: convierte una lista de precios en un argumento de negocio, usando material que ya existe y sin tocar un solo número. Y cuando no tiene material suficiente, lo dice — porque una propuesta con pendientes honestos cierra mejor que una con cifras inventadas, y porque el día que un cliente refute un dato inventado, el costo no lo paga el modelo: lo paga la marca.
---
*Documento de análisis previo a implementación · Consultoría E3 · 2026-07-28*