Módulo 7: El lazo de datos y de retroalimentación

3. Observabilidad para IA: más allá del log de servidor

Descripción

Al terminar esta lección vas a entender por qué la observabilidad de un componente de IA es distinta a la de un servicio clásico, y vas a haber montado un tablero que lo demuestra. La tesis es concreta y contraintuitiva: un log de servidor clásico puede decir que tu feature de IA está perfecta —100% de respuestas exitosas, latencia sana— mientras la mitad de sus respuestas son malas, porque el log clásico mide si el servicio respondió, no si respondió bien. Un servicio clásico y un componente de IA fallan de formas tan distintas que la observabilidad que sirve para uno es ciega para el otro. La diferencia, otra vez, es la naturaleza probabilística del LLM: un endpoint clásico que devuelve HTTP 200 hizo su trabajo; un LLM que devuelve HTTP 200 con una respuesta alucinada o irrelevante falló, pero el status HTTP no tiene forma de saberlo.

Esto importa porque la observabilidad es la precondición del lazo de datos. En la lección 2 mediste el flywheel y viste que la rueda solo gira si el lazo se cierra; pero antes de cerrar nada, tienes que ver qué está fallando —no puedes mejorar lo que no mides—. Y "ver" en un sistema de IA significa capturar cosas que un servidor nunca tuvo que capturar: cuántos tokens consumió cada llamada (porque los tokens son costo y latencia), cuánto costó, cuánto tardó, y —lo nuevo, lo que ningún log clásico tiene— una señal de calidad: ¿la respuesta fue buena? Sin esa señal, tu feature de IA es una caja negra que dice "respondí" sin decir "respondí bien", y un flywheel montado sobre una caja negra no tiene de dónde sacar la nieve.

Conexión con el módulo: esta lección instala la primera pieza del lazo. La lección 2 te dio la motivación (el flywheel compone); aquí montas el instrumento que hace posible girarlo: la observabilidad que te deja ver la calidad. Es el cimiento de las tres lecciones que siguen: la captura de feedback (lección 4) es cómo obtienes la señal de calidad; cerrar el lazo (lección 5) es qué haces con ella; enrutar (lección 7) es a qué palanca la mandas. Todo eso necesita, primero, que puedas medir la calidad —que es justo lo que esta lección monta—. Y una conexión hacia atrás: el approval_rate que vas a medir aquí es la versión en vivo, por request de lo que el eval-set del módulo 3 mide en agregado, contra casos fijos. El eval te dice si el componente es bueno contra tu conjunto de prueba; la observabilidad te dice si es bueno en producción, ahora. Los dos números juntos son el sistema de calidad completo.

Analogía: el tablero del coche que solo mira el motor

Imagina un coche cuyo tablero solo tiene tres luces: motor encendido, gasolina, y temperatura. Es un buen tablero para saber si el coche funciona —el motor arranca, hay combustible, no se sobrecalienta—. Ahora súbete a ese coche para un viaje largo. El tablero está todo en verde: motor bien, gasolina llena, temperatura normal. Y sin embargo, vas en la dirección equivocada, a 20 km/h en una autopista de 120, y con una llanta a punto de reventar. Nada de eso lo ve el tablero, porque el tablero fue diseñado para vigilar el motor, no el viaje. Todo en verde no significa "llegarás bien"; significa "el motor está bien". Son cosas distintas.

El log de servidor clásico es ese tablero. Vigila el "motor" del sistema —¿el servicio respondió (status 2xx)?, ¿en cuánto tiempo (latencia)?, ¿se cayó (tasa de error)?— y para un servicio clásico eso basta, porque si un endpoint clásico devuelve 200, hizo lo que debía. Pero una feature de IA tiene un "viaje" que el tablero del motor no ve: ¿la respuesta fue relevante?, ¿fue correcta?, ¿el usuario la aceptó? Un componente de IA puede tener el motor perfecto (200, rápido, sin caídas) e ir en la dirección equivocada (respuestas malas). La observabilidad para IA es agregarle al tablero las luces del viaje: no solo "el motor anda", sino "vamos bien". Y la luz más importante de esas —la que este módulo llama la señal de calidad— es la que te dice si las respuestas de verdad sirven, la única que no venía en el tablero del coche clásico.

Ejemplo trabajado: el tablero clásico vs el tablero de IA

No vamos a decir que el log clásico esconde la degradación: lo vamos a ver. Modelamos un flujo de producción de dos features de Mercado —el agente de soporte y la búsqueda semántica— con sus traces (una fila por request: status, latencia, tokens, costo y el thumbs del usuario). Luego lo miramos con dos tableros: primero el clásico (status + latencia), que es lo que la mayoría de los equipos tiene; luego el de observabilidad para IA (tokens + costo + la señal de calidad). La búsqueda semántica quedó, sin que nadie se diera cuenta, en un modelo más barato que degradó su calidad. Veamos cuál de los dos tableros lo detecta.

# Leccion 03 (M7) — OBSERVABILIDAD para IA: mas alla del log de servidor. SIMULADO.
# Cero red, cero API, cero claves. Determinista (semilla fija).
#
# Un log de servidor clasico ve status HTTP y latencia. Para una feature de IA
# eso NO basta: hay que ver tokens, costo y —lo que ningun log clasico tiene—
# una senal de CALIDAD (approval_rate). El tablero agrega todo eso POR feature.
import random

random.seed(11)

# Modelo de costo (consistente con M2): USD por 1000 tokens, latencia en ms.
MODELS = {
    "cheap":  dict(usd_in=0.0008, usd_out=0.004, base_ms=90,  ms_per_tok=0.4),
    "strong": dict(usd_in=0.008,  usd_out=0.040, base_ms=300, ms_per_tok=3.0),
}

def call_cost_latency(model, tin, tout):
    m = MODELS[model]
    latency = m["base_ms"] + tout * m["ms_per_tok"]
    cost = (tin / 1000) * m["usd_in"] + (tout / 1000) * m["usd_out"]
    return latency, cost

# Cada feature: su modelo, su rango de tokens, y su tasa REAL de aprobacion.
# La busqueda semantica quedo en un modelo mas barato y su calidad se degrado:
# approval_rate real 0.62. El agente de soporte va sano: 0.88.
FEATURES = {
    "support_agent":  dict(model="strong", n=120, tin=(250, 400), tout=(80, 200),  approval=0.88),
    "semantic_search": dict(model="cheap",  n=200, tin=(20, 40),   tout=(40, 60),   approval=0.62),
}

# --- Generamos el log de traces (una fila por request). Todo en memoria. ---
traces = []
for feature, cfg in FEATURES.items():
    for _ in range(cfg["n"]):
        tin = random.randint(*cfg["tin"])
        tout = random.randint(*cfg["tout"])
        latency, cost = call_cost_latency(cfg["model"], tin, tout)
        # El status HTTP: la llamada al modelo tuvo exito (200). Aqui esta la trampa:
        # el servidor respondio 200 aunque la respuesta fuera de mala calidad.
        http_status = 200
        # La senal de calidad: thumbs up/down del usuario (approval_rate real).
        feedback = "up" if random.random() < cfg["approval"] else "down"
        traces.append(dict(feature=feature, http_status=http_status, latency_ms=latency,
                           tokens=tin + tout, cost=cost, feedback=feedback))

def pct(vals, p):
    s = sorted(vals)
    return s[min(len(s) - 1, int(len(s) * p))]

def aggregate(feature):
    rows = [t for t in traces if t["feature"] == feature]
    lats = [t["latency_ms"] for t in rows]
    ups = sum(1 for t in rows if t["feedback"] == "up")
    return dict(
        calls=len(rows),
        ok_2xx=sum(1 for t in rows if 200 <= t["http_status"] < 300),
        avg_lat=sum(lats) / len(lats),
        p95_lat=pct(lats, 0.95),
        avg_tokens=sum(t["tokens"] for t in rows) / len(rows),
        total_cost=sum(t["cost"] for t in rows),
        approval_rate=ups / len(rows),
    )

print("=== VISTA 1: el log de servidor CLASICO (status + latencia) ===")
print(f"{'feature':<18}{'calls':>7}{'2xx_ok':>9}{'avg_ms':>9}{'p95_ms':>9}")
for f in FEATURES:
    a = aggregate(f)
    print(f"{f:<18}{a['calls']:>7}{a['ok_2xx']/a['calls']:>8.0%}{a['avg_lat']:>9.0f}{a['p95_lat']:>9.0f}")
print("  Veredicto del monitoreo clasico: TODO VERDE. 100% 2xx, latencias sanas.")
print()

print("=== VISTA 2: el tablero de OBSERVABILIDAD para IA (agrega la calidad) ===")
print(f"{'feature':<18}{'calls':>7}{'avg_tok':>9}{'cost_usd':>10}{'approval':>10}  senal")
for f in FEATURES:
    a = aggregate(f)
    flag = "OK" if a["approval_rate"] >= 0.80 else "ALERTA: calidad baja"
    print(f"{f:<18}{a['calls']:>7}{a['avg_tokens']:>9.0f}"
          f"{a['total_cost']:>10.4f}{a['approval_rate']:>10.0%}  {flag}")
print()
print("Lo que el log clasico NO vio: semantic_search responde 200 en todas,")
print("pero su approval_rate real es 62% — una feature degradada e INVISIBLE")
print("para el monitoreo de servidor. Solo la senal de calidad la revela.")

Qué esperar. Al correrlo, la salida es exactamente esta:

=== VISTA 1: el log de servidor CLASICO (status + latencia) ===
feature             calls   2xx_ok   avg_ms   p95_ms
support_agent         120    100%      709      879
semantic_search       200    100%      110      114
  Veredicto del monitoreo clasico: TODO VERDE. 100% 2xx, latencias sanas.

=== VISTA 2: el tablero de OBSERVABILIDAD para IA (agrega la calidad) ===
feature             calls  avg_tok  cost_usd  approval  senal
support_agent         120      460    0.9649       92%  OK
semantic_search       200       80    0.0452       65%  ALERTA: calidad baja

Lo que el log clasico NO vio: semantic_search responde 200 en todas,
pero su approval_rate real es 62% — una feature degradada e INVISIBLE
para el monitoreo de servidor. Solo la senal de calidad la revela.

Lee las dos vistas con calma, porque la comparación es el punto entero de la lección.

El tablero clásico dice: todo perfecto. En la vista 1, las dos features se ven impecables: 100% de respuestas 2xx en ambas, latencias sanas (el agente en 709 ms promedio, la búsqueda en 110 ms, ambas dentro de presupuestos razonables del módulo 2). Si tu monitoreo fuera este —y el de la mayoría de los equipos lo es—, dormirías tranquilo: el servicio responde, es rápido, no se cae. El veredicto es "todo verde". Y es un veredicto honesto sobre lo que mide: el motor anda bien. El problema no es que el tablero clásico mienta; es que mira la parte equivocada.

El tablero de IA dice: una feature está degradada. En la vista 2 aparece la columna que lo cambia todo: approval_rate, la señal de calidad. El agente de soporte va bien (92% de aprobación, sobre el umbral de 0.80 → OK). Pero la búsqueda semántica tiene un approval_rate de 65% —muy por debajo del umbral— y el tablero la marca con ALERTA: calidad baja. Es exactamente la misma búsqueda que en la vista 1 se veía perfecta (100% 2xx, 110 ms). El servidor respondió 200 en las 200 requests; en 70 de ellas la respuesta fue mala. El monitoreo de servidor no tenía forma de verlo, porque una respuesta mala también es un HTTP 200. Solo la señal de calidad —que alguien tuvo que diseñar para capturarla— revela que esta feature está fallando a una tercera parte de sus usuarios.

Y el tablero de IA además te da el costo y los tokens. Fíjate en las otras dos columnas nuevas, que el log clásico tampoco tiene: avg_tok y cost_usd. El agente de soporte consume 460 tokens promedio por request y gastó $0.96 en las 120 llamadas; la búsqueda, con un modelo barato y prompts cortos, consume 80 tokens y gastó $0.045 en 200 llamadas. Esos números no son decorativos: son las métricas del módulo 2 (costo y latencia) observadas en vivo, y son las que te dejan detectar, por ejemplo, que un cambio de prompt duplicó los tokens (y el costo) sin que nadie lo notara. Un componente de IA cuesta por token, así que la observabilidad para IA tiene que contar tokens —es dinero corriendo—. El log clásico nunca contó tokens porque un servicio clásico no cobra por ellos.

La lección en una frase: el status HTTP dice si el servicio respondió; la señal de calidad dice si respondió bien; y para una feature de IA, las dos cosas son distintas. Sin la segunda, tienes una feature que puede degradarse durante semanas con el tablero en verde.

Qué mide la observabilidad para IA (y por qué cada cosa)

El ejemplo mostró las columnas; vale la pena entender por qué cada una es necesaria para un componente de IA y no lo era para un servicio clásico.

Las métricas operativas: latencia y status (lo que ya tenías). La latencia y el status 2xx/5xx no desaparecen —siguen siendo necesarias, un modelo caído o lento sigue siendo un problema (módulo 5)—. La observabilidad para IA incluye el tablero clásico; no lo reemplaza. Lo que hace es agregarle las columnas que faltan.

Los tokens: la métrica que es dinero y latencia a la vez. Cada llamada al LLM consume tokens de entrada y de salida, y los tokens son directamente costo (pagas por token) y directamente latencia (más tokens de salida, más tiempo de generación —lo viste en el modelo de costo del módulo 2—). Por eso la observabilidad para IA cuenta tokens por request y los agrega por feature: un salto en los tokens promedio es un salto en la factura y en el tiempo de respuesta. Es la métrica que conecta esta lección con los presupuestos del módulo 2: el cost_budget y el latency_budget se vigilan con esta observabilidad.

El costo: la factura, desglosada por feature. Agregar el costo por feature responde la pregunta que ningún tablero clásico podía responder: "¿cuánto me cuesta esta feature de IA al mes, y cuál de mis features se está comiendo el presupuesto?". Es lo que te deja detectar que una feature de bajo tráfico pero de modelo caro cuesta más que una de alto tráfico y modelo barato, o que un cambio de prompt disparó el costo. El costo por token, observado, es lo que hace gobernable el cost budget del módulo 2.

La señal de calidad: lo verdaderamente nuevo. Esta es la columna que no tiene equivalente en un servidor clásico, y la razón de ser de la lección. La señal de calidad es una medida —agregada, en vivo— de si las respuestas del componente son buenas. En el ejemplo la modelamos como approval_rate (fracción de thumbs_up), pero puede tomar muchas formas según la feature: la tasa de clicks relevantes en una búsqueda, la fracción de respuestas que un agente humano mandó sin editar, la tasa de escalamiento a un humano. La lección 4 desarrolla estas señales a fondo. Lo que importa aquí es la idea arquitectónica: sin una señal de calidad en tu observabilidad, tu feature de IA es una caja negra que reporta "respondí" sin reportar "respondí bien", y ninguna de las lecciones que siguen —cerrar el lazo, enrutar el feedback— es posible, porque no tienes de dónde partir.

Una nota sobre la relación con el eval del módulo 3, porque es fácil confundirlos. El eval mide la calidad en agregado, contra un conjunto de casos fijos, antes del deploy —es la compuerta—. La observabilidad mide la calidad en vivo, sobre el tráfico real, después del deploy —es el monitoreo—. Son complementarios: el eval te deja no desplegar algo malo; la observabilidad te deja detectar que algo bueno se degradó en producción (por drift, por un cambio de datos, por un modelo que el proveedor actualizó). Y el puente entre los dos es el lazo: la observabilidad detecta un caso malo en vivo, y ese caso se realimenta al eval-set (lección 5), cerrando el círculo.

Errores comunes

Loguear como servidor clásico, sin señal de calidad (de modelo mental). Qué pasa: es el error central de la lección. El equipo monitorea la feature de IA con el mismo stack que usa para sus servicios clásicos —status, latencia, tasa de error— y nunca agrega una señal de calidad. La feature se degrada (un cambio de modelo, drift, un prompt que alguien tocó) y el tablero sigue en verde porque las respuestas malas también devuelven 200. El problema se descubre por quejas de clientes o caída de una métrica de negocio, semanas después. Por qué pasa: el instinto es reusar el monitoreo que ya se tiene, y ese monitoreo nunca tuvo que medir "¿estuvo bien la respuesta?" porque los servicios clásicos no fallan así. Cómo detectarlo: si tu tablero de una feature de IA no tiene una columna de calidad, no estás observando la parte que importa. Cómo corregirlo: agrega la señal de calidad (approval_rate o el equivalente de tu feature) al tablero; el status dice si respondió, la calidad dice si respondió bien.

No contar tokens y descubrir la factura a fin de mes (de omisión). Qué pasa: el equipo no instrumenta los tokens por request, así que no ve el costo en vivo. Un cambio de prompt que agrega instrucciones, o un modelo que empezó a dar respuestas más largas, duplica los tokens promedio —y el costo— sin ninguna alarma, y la sorpresa llega en la factura del proveedor a fin de mes. Por qué pasa: un servicio clásico no cobra por token, así que el instinto de instrumentación no incluye contarlos. Cómo detectarlo: si no puedes graficar los tokens promedio por feature a lo largo del tiempo, no verás venir un salto de costo. Cómo corregirlo: cuenta tokens de entrada y salida por request y agrégalos por feature; es la métrica que vigila el cost budget del módulo 2 en vivo.

Confundir la observabilidad con el eval, y tener solo una (de alcance). Qué pasa: el equipo tiene un buen eval-set (módulo 3) y cree que con eso "ya mide la calidad", así que no monta observabilidad en producción; o al revés, tiene un buen tablero de approval_rate y cree que no necesita eval antes del deploy. En el primer caso, no detecta cuando la feature se degrada en vivo (el eval es contra casos fijos, no contra el tráfico real). En el segundo, deja pasar a producción cambios malos que un eval habría bloqueado. Por qué pasa: los dos miden "calidad" y suenan redundantes. Cómo detectarlo: si no puedes decir tanto "¿este cambio pasa la compuerta antes del deploy?" como "¿cuál es el approval_rate en vivo de esta feature hoy?", te falta una de las dos. Cómo corregirlo: ten las dos —el eval es la compuerta pre-deploy, la observabilidad es el monitoreo post-deploy—, y conéctalas con el lazo (lección 5).

Ejercicios

Ejercicio 1 — El tablero del coche. Traduce la analogía al diseño. (a) ¿Qué representa "el motor anda bien" (motor, gasolina, temperatura en verde) en la observabilidad de una feature de IA? (b) ¿Qué representa "vamos en la dirección correcta y a buena velocidad"? (c) En el ejemplo trabajado, ¿qué luz del tablero estaba en verde para la búsqueda semántica y cuál en rojo, y por qué el tablero clásico solo veía la verde?

Ver solución
  • (a) "El motor anda bien" → las métricas operativas: status 2xx, latencia, tasa de error. Son las que dicen que el servicio funciona —respondió, rápido, sin caerse—. Es lo que el tablero clásico mide, y es necesario (un modelo caído o lento sigue siendo un problema, módulo 5).
  • (b) "Vamos bien" → la señal de calidad: approval_rate (o clicks relevantes, o respuestas aceptadas sin editar). Es la que dice si el componente hace bien su trabajo, no solo si respondió. Es la luz que el tablero clásico no tenía.
  • (c) Para la búsqueda semántica, la luz "motor" estaba en verde (100% 2xx, 110 ms) y la luz "calidad" en rojo (approval_rate 65%, bajo el umbral). El tablero clásico solo veía la verde porque fue diseñado para vigilar el motor (status, latencia), y una respuesta mala también es un HTTP 200 —el motor "anda" aunque la respuesta no sirva—. Solo un tablero con la luz de calidad ve que la feature va en la dirección equivocada.

Ejercicio 2 — La feature invisible. En el ejemplo, la búsqueda semántica tenía 100% de 2xx y un approval_rate de 65%. Un compañero dice: "el 100% de 2xx prueba que la feature funciona; el approval_rate es subjetivo y no debería alarmarnos". Explica por qué ambas afirmaciones están mal, y qué habría que hacer con esa feature.

Ver solución

La primera afirmación —"el 100% de 2xx prueba que funciona"— confunde respondió con respondió bien. El 100% de 2xx solo prueba que el servidor devolvió una respuesta HTTP exitosa en todas las requests; no dice nada sobre si esas respuestas eran útiles. Una búsqueda que devuelve resultados irrelevantes con status 200 es un 2xx "exitoso" y un fracaso para el usuario. En un componente de IA, el status HTTP y la calidad de la respuesta son dimensiones independientes: puedes tener 200 con basura.

La segunda —"el approval_rate es subjetivo"— también está mal. El approval_rate es una medida agregada y objetiva de una señal real: qué fracción de usuarios marcó la respuesta como buena (o, en la búsqueda, hizo click en un resultado relevante). No es una opinión de un ingeniero mirando ejemplos; es el juicio de cientos de usuarios reales, contado. Que un tercio de los usuarios rechace las respuestas no es "subjetivo": es un dato duro de que la feature falla a un tercio de su tráfico.

Qué habría que hacer: investigar y cerrar el lazo. La alerta de calidad (65%) es el disparador; el siguiente paso es capturar qué casos fallan (lección 4), convertirlos en casos del eval-set (lección 5), y enrutarlos a la palanca correcta —aquí, probablemente, revertir el cambio a un modelo más barato que degradó la relevancia, o mejorar el retrieval (lección 7)—. La observabilidad no arregla la feature; detecta que hay que arreglarla, que es su trabajo. Sin ella, la degradación habría seguido invisible.

Ejercicio 3 — ¿Qué señal de calidad para cada feature? La señal de calidad toma formas distintas según la feature. Para cada una de estas features de Mercado, propón una señal de calidad medible en producción (no un eval de casos fijos, sino algo que puedas contar del tráfico real) y explica qué captura. (a) El agente de soporte que propone respuestas a un agente humano. (b) La búsqueda semántica de productos. (c) El generador "describe tu producto" para vendedores.

Ver solución
  • (a) El agente de soporte → la tasa de respuestas que el agente humano mandó sin editar (o su complemento, la correction_rate). Si el humano manda la propuesta tal cual, el componente acertó; si la reescribe, falló. Es una señal de acción, gratis (surge del flujo normal de trabajo) y honesta. También sirve el thumbs del cliente final y la tasa de escalamiento (¿cuántos tickets el agente no pudo resolver?). La lección 4 desarrolla estas señales.
  • (b) La búsqueda semántica → la relevant_click_rate: fracción de búsquedas donde el usuario hizo click en un resultado del top-3 (o la posición promedio del click). Un click arriba = la búsqueda puso lo relevante donde el usuario lo ve; un click abajo o una reformulación de la query = la búsqueda enterró lo relevante. Es feedback implícito: el usuario no marca nada, su comportamiento (dónde hace click) es la señal. Es la que usa el proyecto (lección 8).
  • (c) El generador "describe tu producto" → la tasa de descripciones que el vendedor publicó sin editar, y/o cuánto editó cuando editó. Si el vendedor publica la descripción generada tal cual, sirvió; si la reescribe entera, no. También sirve una señal más indirecta (¿las descripciones generadas se asocian a más ventas o vistas que las escritas a mano?), aunque esa es más difícil de atribuir. La señal de "aceptó sin editar" es la más directa y barata.

El patrón general: la mejor señal de calidad en producción suele ser una acción natural del usuario (aceptar, hacer click, no reformular) más que un thumbs explícito, porque la acción no requiere que el usuario haga trabajo extra y no miente. La lección 4 profundiza en esto.

Resumen y siguiente paso

En esta lección montaste la primera pieza del lazo de datos: la observabilidad para IA. Viste la tesis con la analogía del tablero del coche que solo mira el motor —todo en verde mientras vas en la dirección equivocada— y la mediste: dos features con 100% de respuestas 2xx y latencias sanas en el tablero clásico, pero el tablero de IA reveló que una de ellas, la búsqueda semántica, tenía un approval_rate de 65% —una feature degradada e invisible para el monitoreo de servidor—. Entendiste las columnas que la observabilidad para IA agrega y por qué cada una: los tokens (que son costo y latencia), el costo por feature (que gobierna el cost budget del módulo 2 en vivo), y —lo verdaderamente nuevo— la señal de calidad, que dice si el componente respondió bien, no solo si respondió. Y ubicaste la relación con el eval del módulo 3: el eval es la compuerta pre-deploy contra casos fijos; la observabilidad es el monitoreo post-deploy sobre el tráfico real.

Antes de avanzar deberías poder: explicar por qué un log de servidor clásico es ciego a la calidad de un componente de IA; nombrar las columnas de la observabilidad para IA (operativas + tokens + costo + señal de calidad); distinguir la observabilidad (en vivo) del eval (contra casos fijos); y proponer una señal de calidad medible para una feature dada.

Lo que sigue es la pieza que produce esa señal de calidad: el lazo de retroalimentación. En la lección 4 vas a ver que el feedback no es una sola cosa —son tres señales distintas: el thumbs explícito, la corrección, y la acción que el humano tomó tras la sugerencia— y vas a ejecutar un feedback_loop que las captura las tres. Vas a descubrir que las tres no coinciden, y que la más honesta —la acción— revela trabajo humano oculto que el thumbs esconde. Es el paso de "necesito una señal de calidad" a "sé exactamente qué señales existen, cómo capturarlas, y por qué el punto de captura es una decisión de arquitectura".

Recursos