Intelligence Core — registro de decisiones
Bitácora de las decisiones que el plan E10 (10-intelligence-core-plan.md §16)
marcó como pendientes de humano o de evidencia empírica. Una decisión aquí
tiene: qué se decidió, la alternativa literal que se descartó, quién puede
revertirla y qué costaría.
Append-only. Corregir una decisión = entrada nueva que la supersede, no una
edición silenciosa de la anterior.
D-001 · Clave del caché de assessments — queryVersionDiscriminator
Estado: APLICADA (default del plan). Reversible con una columna.
Referencia: plan §2 (nota tras los contratos), §5, §16.3. Tarjeta C0.1.
Decidido por: el implementador, aplicando el default que el plan propone.
El plan pedía un sí/no explícito del founder; se aplica el default y se deja
registrada la alternativa para que ese sí/no siga siendo posible sin
arqueología.
Lo que se aplicó
La clave única deintel_assessments es:
query_version_discriminator:
NULL= fit BASE — el juicio “esta oferta ↔ esta señal”, que no depende de la versión de la query. Reusable entre versiones del mismo encargo Y entre encargos distintos que compartancommercial_profile_hash.- no-
NULL= overlay de exclusión semántica — hash de las exclusionestipo: 'semantica'de esa versión de la query. Solo estas obligan a volver a preguntarle al modelo.
tipo: 'lexica' NO entran en la clave: se aplican
determinísticamente en la etapa de filtros, así que no cambian ningún juicio.
La alternativa literal descartada
El spec original pedíaquery_version en la clave:
version+1 sobre el mismo queryId, que es el gesto central de la
experiencia — invalidaría todo el caché de fit, incluido el juicio base que
no cambió. Con K=50 y lotes de 10, una sesión de refinamiento típica de 5
versiones pasa de ~5 llamadas al clasificador a ~25: ~5× en costo y latencia
por sesión, para re-derivar juicios idénticos.
Cómo revertir (si el founder prefiere la literalidad)
- Migración additive: columna
query_version integerenintel_assessments, nueva UNIQUE que la incluya, la vieja se retira. OpportunityAssessment.queryVersionDiscriminator→queryVersion: numberencontracts.ts(bump deINTEL_SCHEMA_VERSIONa 1.1).- La lógica de lookup en
persistence/assessments.store.ts(C3.2).
Qué observar para saber si fue la decisión correcta
reproducibilidad.assessmentsCacheHits en G9 (refinamiento). La decisión se
sostiene si el fit base sale 100% de caché y solo se evalúan overlays nuevos.
Si en la práctica casi toda refinación trae exclusiones semánticas, la ventaja
se evapora y la alternativa literal vuelve a ser preferible.
D-002 · Taxonomía de fit y pesos de ranking — PENDIENTE DE APROBACIÓN
Estado: REDACTADA, sin aprobar. Bloquea C3.3 y C5.1. Referencia: plan §16.1 y §16.6. Tarjeta C0.2.fit-tax/1.0.0 (apps/api/src/intelligence/taxonomy/fit-tax-1.0.0.md) y
rank/1.0.0 (.../rank-1.0.0.ts) están redactados tal como el plan los
propone, con los 2 ejemplos por nivel sobre el caso G1 y el vocabulario cerrado
de 13 códigos referenciado por contracts.ts.
No están aprobados. Codifican el juicio comercial del founder, y un agente
no puede firmarlo por él. El documento lleva el marcador
PENDIENTE DE APROBACIÓN y un test lo verifica mecánicamente
(rank-1.0.0.spec.ts), de modo que el gate no puede olvidarse.
Lo que sí avanzó sin la aprobación: C0.3, C0.4, C1 y C2 — ninguno depende de la
semántica de los niveles, solo de que el vocabulario sea cerrado.
Al aprobar: registrar aquí la entrada D-002b con la fecha, quién aprobó y las
correcciones aplicadas; quitar el marcador del doc y actualizar el test.
D-004 · La clave de dedupe NO puede ser event_group_key
Estado: APLICADA por necesidad. Un supuesto del plan resultó falso.
Referencia: plan §4.5. Tarjeta C1.3.
El supuesto que no se sostuvo
El §4.5 dice: agrupar por «entidad normalizada +event_group_key (existe en
el warehouse desde su migración 0009)». La columna existe en el warehouse, pero
no cruza el gateway: el contrato Market Intelligence 1.0 está congelado con
additionalProperties: false y MarketSignal no la expone. Exponerla sería
modificar gtm-fabrica, que este plan prohíbe explícitamente (§3, hard rule 7).
Lo que se aplicó
La clave más conservadora derivable de lo que SÍ cruza el gateway:entity.id es la entidad ya resuelta por el warehouse, no un nombre
parecido. Eso es lo que hace estructuralmente imposible la sobre-fusión de dos
entidades distintas.
La asimetría que gobierna la decisión
Los dos errores no cuestan lo mismo:- Sobre-fusionar (juntar dos oportunidades reales) pierde una venta y es invisible: el usuario nunca sabrá qué no vio.
- Sub-fusionar (no juntar dos constancias del mismo evento) repite una fila y es visible: molesta, y se corrige.
Cuándo revisitar
Si el golden muestra sub-fusión significativa, la salida NO es aflojar la clave (eso reintroduce el riesgo de sobre-fusión), sino pedir a gtm-fabrica que expongaevent_group_key en la versión 1.1 del contrato — una conversación
cross-repo, con su propio expand/contract, fuera del alcance de este plan.
D-005 · La señal no lleva geografía de entidad — G10 no se puede cerrar entero
Estado: APLICADA con límite declarado. G10 queda parcialmente bloqueado. Referencia: plan §2 (FilaOportunidad.entidad.geografia), §8 G10. Tarjeta C1.4.
El supuesto que no se sostuvo
El contrato de la fila declaraentidad.geografia: string[], y G10 pide que
«el componente geografia del score degrade las señales de CDMX para una
oferta de GDL». Ambas cosas suponen geografía por señal.
MarketSignal.entity es {id, display_name, kind}. No hay geografía, y el
contrato Market Intelligence 1.0 está congelado con
additionalProperties: false. Lo único geográfico que cruza el gateway es
geography_coverage, que es de la capability, no de la señal.
Lo que se aplicó
-
El componente
geografiase calcula a granularidad de capability, con la única distinción que se puede hacer con honestidad:- cobertura exacta de la zona pedida ⇒
1(toda señal suya está en zona); - cobertura más amplia (nacional para una consulta estatal) ⇒
0.6. Sus señales pueden estar fuera y no hay cómo saberlo por señal: el descuento es incertidumbre declarada, no un castigo inventado.
- cobertura exacta de la zona pedida ⇒
-
entidad.geografiade la fila queda vacía, y la fila declara'ubicación de la entidad'en susdesconocidos. Rellenarla con la cobertura de la capability afirmaría que la entidad está en todos los estados que la fuente cubre — un hecho inventado, exactamente lo que hecho≠inferencia prohíbe.
Consecuencia honesta para el golden
G10 no puede quedar verde por completo con el contrato actual. Lo que sí es verificable hoy: que una fuente de cobertura más amplia se degrada frente a una exacta. Lo que NO: que una señal concreta de CDMX se degrade dentro de una fuente nacional. Marcarlo verde sin esa mitad sería teatro. Cerrarlo entero requiere geografía por señal en un contrato 1.1 del warehouse — conversación cross-repo, fuera del alcance de este plan.D-002b · Taxonomía de fit y pesos de ranking — APROBADA
Estado: APROBADA TAL CUAL. Supersede el estado pendiente de D-002. Fecha: 2026-08-06. Aprobó: el founder, con confirmación explícita (sesión de revisión del Intelligence Core; se le presentó el documento completo y las tres decisiones de juicio que contiene: la pregunta definitoria de §1, la regla “soloalto destaca / abstencion > bajo inventado” de §2, y el
vocabulario de 13 códigos de §3).
fit-tax/1.0.0queda como el criterio comercial vigente;rank/1.0.0como punto de partida sujeto a la calibración de C5.1 (que tiene su propia revisión humana de top-3).- Se consideró y NO se pidió: un código de razón para umbral de monto (“monto
demasiado chico para valer la pena”). Si la calibración o el uso real lo
exigen, entra como
fit-tax/1.1.0con su propia entrada aquí. - Cambios aplicados al cerrar el gate: marcador del doc →
ESTADO: APROBADA, header derank-1.0.0.ts, y el test mecánico ahora protege la dirección contraria (el marcador pendiente no puede reaparecer sin decisión nueva). - Desbloquea: C3.3 (micro-eval del clasificador) y C5.1 (etiquetado y calibración). El etiquetado del golden sigue siendo trabajo humano (~2 h) — este gate no lo sustituye.
D-003 · Tier del clasificador — PENDIENTE (gate empírico C3.1)
Estado: NO DECIDIDA. Es una decisión empírica, no de diseño. Referencia: plan §10.1, §14, §16.4. Tarjeta C3.1. La elección entre (a) tier conjson_schema y (b) primario con json_object +
validación se decide midiendo la tasa de salida inválida contra 3 lotes de
señales reales, con gate <2%. El plan es explícito: si ambos tiers fallan el
gate, se para y se escala a humano — no se afloja el gate.
Esta sesión no llegó a C3.1.
D-006 · C1.3 no cumple aún su criterio literal «G8 verde» — deuda declarada
Estado: DEUDA ABIERTA, con fecha de cierre atada a C1.4. Abierta: 2026-08-06 (hallazgo de revisión externa de la sesión C0→C1.3). Referencia: plan §15, tarjeta C1.3 («Acepta: G8 verde; specs de no-sobre-fusión adversariales»).El hecho
C1.3 se declaró completa con sus specs unitarios verdes (11/11), pero su criterio de aceptación es literalmente «G8 verde», y G8 sigueNOT IMPLEMENTED. Las dos afirmaciones conviven sin contradicción, y conviene
decir por qué en vez de dejarlo a interpretación:
- El motor de dedupe existe y está probado: agrupa señales sin sobre-fundir
entidades distintas, y
fuentesDistintascuenta nombres de fuente, no documentos (13 constancias del mismo portal ⇒ 13 items, 1 fuente). - El eval G8 asere sobre un
OpportunityResult, y todavía no se construye ninguno:materialize.tses C1.4.
Por qué se registra en vez de corregirse en silencio
La regla de la sesión es que una tarjeta cuyo criterio de aceptación no se cumple no está done. Marcar C1.3 como completa sin esta nota dejaría el estado del proyecto un escalón por delante de la realidad — el mismo defecto que el golden set entero existe para impedir.Cierre
Esta deuda queda saldada al cerrar C1.4 (rank.ts + materialize.ts +
results.store.ts), que es cuando G8 puede correr de verdad. Si al cerrar C1.4
G8 NO queda verde, esta entrada se supersede con una nueva que diga por qué —
no se borra.
Cierre (misma sesión, al completar C1.4): G8 quedó PASS en modo
--sin-modelo y está en baseline.json. La deuda queda saldada tal como se
declaró: el motor de C1.3 era correcto y solo faltaba la materialización contra
la cual aserir.
D-007 · G9 no se marca verde por su mitad determinista
Estado: APLICADA. G9 sigueNOT IMPLEMENTED a propósito.
Referencia: plan §8 G9. Tarjetas C2.3 / C4.3.
El hecho
G9 declara cuatro expectativas:- el resultado v2 lleva
diffcontra v1; - conservadas y descartadas son correctas, cada descartada con su causa;
- el fit base sale 100 % de caché;
- solo se evalúan los overlays semánticos nuevos.
Lo que se aplicó
Los tests de la mitad determinista viven enapps/api/src/intelligence/golden/refinamiento-determinista.spec.ts, fuera
de la suite golden (el archivo no termina en .golden.spec.ts). Corren en la
suite unitaria y protegen el comportamiento igual, pero no reclaman el id
G9, así que el runner no lo marca PASS.
Por qué, y no al revés
Si esos tests estuvieran en la suite golden, el runner leería «G9 PASS» — y eso afirmaría que el caché de fit funciona sin que exista una sola línea de él. Es la misma trampa que se corrigió con la medición de G1: un eval que pasa por la mitad de sus expectativas es un verde de mentira, no un avance parcial. La alternativa descartada fue partir G9 en dos entradas del registro (G9-DET y G9-SEM). Se descartó porque el §8 del plan congela un set de 14
casos y cambiar su cardinalidad para poder pintar un verde es exactamente el
tipo de ajuste que el registro existe para impedir. Si el equipo prefiere el
split, es una línea en registry.mjs y un archivo renombrado — pero debe ser
una decisión suya, no una conveniencia del implementador.
Cierre
G9 queda verde en C4.3, cuando (3) y (4) se puedan verificar de verdad.D-003b · C3.1 NO se ejecutó — falta credencial, y el gate no se afloja
Estado: D-003 SIGUE ABIERTA. C3.1 esNOT RUN, no FAIL ni PASS.
Fecha: 2026-08-06 (sesión C3).
Referencia: plan §10.1, §14, §16.4. Tarjeta C3.1.
Qué se intentó
La sesión tenía autorización para ejecutar C3.1 si el entorno traíaTEST_GTM_DATABASE_URL (vault de staging, para los 3 lotes de señales reales) y
EXPERIENCE_V2_LIVE_API_KEY (acceso a modelo). Se verificaron ambas al abrir la
sesión: las dos ausentes, junto con ANTHROPIC_API_KEY, SUPABASE_URL e
INTEL_GTM_URL.
Por qué no se hizo igual
El gate de C3.1 es empírico y solo empírico: «tasa de salida inválida < 2 % contra 3 lotes de señales REALES». Sin señales reales y sin modelo, cualquier cosa que se produjera aquí sería una de dos:- una medición contra fixtures, que no mide lo que el gate mide — la tasa de salida inválida depende del modelo y del texto real de las señales, no de la forma del payload; o
- un prompt y un batch runner sin medición, presentados como si la decisión de tier estuviera tomada.
Lo que sí quedó listo para cuando haya credencial
- C3.2 completa:
intel_assessmentses un caché operativo con lookup por la clave de D-001, INSERT append-only e invalidación perezosa por versión. En cuanto el clasificador emita juicios, hay dónde guardarlos y de dónde leerlos. - El pipeline acepta el fit:
cacheFitinyecta juicios persistidos al ranking, concacheHitreportado enreproducibilidad. La costura está probada de punta a punta. - El listón del gate ya está medido: el baseline determinista NO resuelve G1
(
golden/g1-baseline.spec.ts), así que la comparación «el clasificador debe superar el baseline» tiene un punto de partida real y no una suposición. - El formato de etiquetado para C3.3/C5.1 (
evals/intelligence/etiquetado/).
