Módulo 7: Blameless Postmortems And Runbooks

4. *Action items* que de verdad se cumplen

Descripción

POSTMORTEM.md terminó con una tabla de cuatro action items, cada uno atado a una causa raíz específica — pero, tal como quedó en la lección 3, esa tabla tiene un problema real: nadie es dueño de nada, no hay ninguna fecha, y no hay ninguna forma de confirmar, con evidencia, que alguno de los cuatro se cumplió de verdad. Esta lección cierra esa brecha con un criterio concreto —SMART— y con la misma cita de Google SRE que explica, con precisión, por qué un action item sin dueño casi nunca se cumple.

Conexión con el módulo

Esta lección expande, sin modificar ninguna causa raíz ya establecida, la tabla breve que POSTMORTEM.md (lección 3) dejó al final. El action item #1 de esta lección —prevent_destroy sobre Shipments— es la pieza exacta que cloud-security-and-guardrails-guide, Módulo 1, lección 6 dejó declarada como hueco pendiente en todo el ecosistema: "Ninguna guía de este ecosistema la construye todavía para Andes Cargo — es, honestamente, un hueco declarado, no una pieza escondida". El action item #3 —el runbook— es, textualmente, el entregable que la lección 6 de este mismo módulo construye completo.


Paso 1 — Por qué la mayoría de los action items de postmortem nunca se cumplen

Google SRE no deja este problema como una observación anecdótica — lo trata como un requisito de diseño del propio proceso:

"All action items have both an owner and a tracking number" [...] "All action items are assigned a priority level."

Google SRE Workbook — Postmortem Culture

La razón detrás de esta regla, citada en la misma fuente: un action item sin un dueño único claro tiende a difundirse entre "el equipo" en general, y lo que le pertenece a todo el equipo, en la práctica, no le pertenece a nadie en particular — nadie se siente responsable de moverlo de "pendiente" a "hecho". La misma fuente recomienda un dueño único, con colaboradores adicionales si hace falta, en vez de responsabilidad distribuida entre varias personas por igual.

Y hay una segunda cita, del propio fundador de la disciplina SRE en Google, que conecta directamente esta lección con el propósito completo de un postmortem:

"To our users, a postmortem without subsequent action is indistinguishable from no postmortem."

— Ben Treynor Sloss, citado en Google SRE Workbook — Postmortem Culture

Esta cita es, con precisión, la razón por la que esta lección existe como un paso separado —no como una nota al pie de POSTMORTEM.md—: un postmortem impecablemente escrito, con causa raíz correctamente distinguida del disparador, con la disciplina sin culpa completa, que termina en una lista de buenas intenciones sin dueño ni fecha, tiene, desde la perspectiva de quien depende de que el sistema sea más confiable, el mismo valor que no haber escrito ningún postmortem.


Paso 2 — El criterio SMART, aplicado sin relleno

SMART es un acrónimo de cinco condiciones que, juntas, distinguen un compromiso real de una intención vaga:

LetraCondiciónLa pregunta que contesta
SpecificEspecífico¿Qué, exactamente, va a cambiar? Sin ambigüedad sobre el alcance.
MeasurableMedible¿Cómo se sabría, con evidencia verificable, que ya se cumplió?
AssignableAsignable¿Quién, una sola persona, es responsable de que esto avance?
RealisticRealista¿Es posible completarlo con los recursos y el tiempo disponibles?
Time-boundCon plazo¿Para cuándo? Sin fecha, no hay forma de saber si está atrasado.

El error más común al aplicar este criterio no es olvidar una letra — es escribir un action item que suena específico pero, al leerlo con cuidado, no contesta ninguna de las cinco preguntas con precisión verificable. Antes de construir los cuatro action items reales de esta lección, vale la pena ver el contraste exacto:

   ACTION ITEM VAGO                          ACTION ITEM SMART
   (no pasa el criterio)                      (pasa las cinco letras)
   ─────────────────────                      ───────────────────────
   "Investigar por que el humano              "Agregar prevent_destroy al
   no detuvo al agente"                       recurso aws_dynamodb_table.shipments
                                                en andes-cargo-infra/"
        │                                            │
        ▼                                            ▼
   Specific?   NO -- "investigar" no          Specific?   SI -- un recurso,
               dice que va a cambiar                       un bloque HCL exacto
   Measurable? NO -- ¿que evidencia            Measurable? SI -- terraform plan
               confirma que se completo?                   muestra el lifecycle
   Assignable? NO -- sin dueño                 Assignable? SI -- Bruno (Operations
                                                             Lead, INCIDENT-RESPONSE-
                                                             PLAN.md)
   Time-bound? NO -- sin fecha                 Time-bound? SI -- antes del proximo
                                                             ciclo de sprint (2 semanas)
        │                                            │
        ▼                                            ▼
   Ademas: viola la disciplina sin             Ademas: es una accion de sistema,
   culpa de la Leccion 2 -- "investigar        no un juicio sobre una persona --
   a una persona" no es un action              exactamente el tipo de action
   item de sistema                             item que la Leccion 2 exige

Paso 3 — Los cuatro action items reales de Andes Cargo, con criterio SMART completo

Cada uno de los cuatro action items de POSTMORTEM.md (lección 3), expandido con las cinco condiciones, un dueño de INCIDENT-RESPONSE-PLAN.md (Módulo 5), y una prioridad:

Action item #1 — prevent_destroy sobre Shipments

CondiciónCómo se cumple
SpecificAgregar un bloque lifecycle { prevent_destroy = true } al recurso aws_dynamodb_table.shipments en andes-cargo-infra/.
Measurableterraform plan contra cualquier cambio que intente eliminar o reemplazar la tabla falla con el error nativo de Terraform: "Instance cannot be destroyed [...] Resource has lifecycle.prevent_destroy set" — verificable corriendo el plan una sola vez.
AssignableBruno — Operations Lead (INCIDENT-RESPONSE-PLAN.md, Módulo 5), la única persona con permiso de modificar andes-cargo-infra/ fuera de un incidente activo.
RealisticUn bloque lifecycle de tres líneas, sin dependencias externas — el mismo tipo de cambio de bajo riesgo que cualquier otro archivo .tf de este ecosistema.
Time-boundAntes del próximo ciclo de sprint — dos semanas desde la fecha de este postmortem, el mismo plazo que INCIDENT-RESPONSE-PLAN.md ya usa como referencia para action items de prioridad P1.
PriorityP1 — cierra la causa raíz #3 (POSTMORTEM.md), la última línea de defensa que el incidente real nunca tuvo, y el hueco que cloud-security-and-guardrails-guide dejó declarado sin construir.

Action item #2 — Cobertura de no-destroy-shipments.rego sobre terraform destroy

CondiciónCómo se cumple
SpecificVerificar, con una prueba de conftest test dedicada, que la política Rego construida en cloud-security-and-guardrails-guide (Módulo 4, lección 6) evalúa correctamente un plan generado por terraform plan -destroy, no solo un plan de apply que contiene una acción de eliminación incidental.
MeasurableUn archivo de prueba nuevo, destroy_plan_test.rego, con un plan.json sintético que simula terraform plan -destroy sobre Shipments; conftest test debe fallar ese plan con el mismo mensaje que ya falla un plan de apply equivalente.
AssignableCarla — la tercera persona de la rotación (oncall/schedule.py, Módulo 5, lección 7), asignada aquí como dueña de la verificación de política, distinta de Bruno para no concentrar los cuatro action items en una sola persona.
RealisticNo requiere reescribir la política — solo agregar un caso de prueba nuevo y confirmar el resultado; si la cobertura ya existe, el resultado del action item es "confirmado", no "reescrito".
Time-boundUn sprint completo (cuatro semanas) — prioridad más baja que el #1 porque no-destroy-shipments.rego ya existe y funciona contra el caso más común (apply); esto verifica un caso de borde, no cierra un hueco abierto.
PriorityP2 — refuerza la causa raíz #2, pero no la deja abierta si se retrasa: el gate de apply ya existe.

Action item #3 — Escribir runbooks/manifest-processor-error-rate.md

CondiciónCómo se cumple
SpecificUn documento nuevo en andes-cargo-infra/runbooks/, con los pasos exactos para responder cuando la alarma de observability.tf (Módulo 4, lección 5) dispara.
MeasurableEl documento existe, cada comando que contiene fue verificado (o etiquetado con precisión como representativo, con la razón), y pasa la prueba de "alguien nuevo en el equipo lo sigue sin preguntar nada" — el mismo criterio que la lección 6 de este módulo aplica al escribirlo.
AssignableAna — Incident Commander (INCIDENT-RESPONSE-PLAN.md), dueña de la documentación operativa del equipo.
RealisticCompletamente realista — este mismo módulo lo entrega completo en la lección 6, sin ninguna dependencia externa pendiente.
Time-boundUna semana — el plazo más corto de los cuatro, porque cierra una ausencia total (Andes Cargo no tenía ningún runbook antes de este módulo).
PriorityP1 — cierra las causas raíz #1 y #2 desde el ángulo de "qué hace un humano, no solo qué bloquea un sistema": incluso con prevent_destroy y conftest en su lugar, un runbook reduce el tiempo de respuesta ante cualquier otra clase de incidente que esos dos controles no cubran.

Action item #4 — Evaluar backup/PITR propio para Shipments

CondiciónCómo se cumple
SpecificIntentar, contra LocalStack, awslocal dynamodb create-backup y restore-table-from-backup sobre una copia desechable de Shipments, y documentar el resultado real —funcione, falle, o quede parcialmente confirmado—.
MeasurableUn documento con el resultado exacto del intento, sin inventar un desenlace que no ocurrió — el mismo estándar que cloud-security-and-guardrails-guide ya aplicó con CloudTrail en su Módulo 7.
AssignableDiego — la cuarta persona de la rotación, para que los cuatro action items de este postmortem tengan cuatro dueños distintos, ninguno sobrecargado.
RealisticParcialmente incierto por diseño — la propia documentación de LocalStack confirma DynamoDB en el plan Hobby, pero no confirma explícitamente la cobertura de la API de backup (ver lección 7 de este módulo); el action item es "documentar el resultado real", no "garantizar que funcione", así que sigue siendo realista incluso si el resultado es un límite técnico documentado.
Time-boundDos semanas — la lección 7 de este módulo, inmediatamente después, ya completa este intento dentro del propio ecosistema de la guía.
PriorityP2 — depende del resultado técnico incierto; no bloquea nada más mientras se investiga.

Paso 4 — Por qué ningún action item de esta lección menciona a una persona del incidente real

Fíjate en un detalle que conecta directamente con la lección 2: ninguno de los cuatro action items de esta lección dice "capacitar al humano que aprobó el destroy" ni "revisar el criterio del agente antes de proponer una acción destructiva". Ambas ideas suenan razonables a primera vista, y ambas fallan el mismo criterio: no son medibles de forma verificable (¿cómo confirmarías que alguien "tiene mejor criterio" ahora?), y dependen, otra vez, de que la atención o el juicio de una persona específica sea la salvaguarda —el mismo punto único de falla que produjo el incidente en primer lugar—. Los cuatro action items reales de esta lección, en cambio, son verificables con un comando (terraform plan, conftest test) o con un documento terminado (el runbook, el resultado del intento de backup) — ninguno depende de que nadie "aprenda la lección" en un sentido no verificable.


Errores comunes

Escribir un action item que sí tiene las cinco letras de SMART pero sigue siendo, en el fondo, una tarea sobre una persona (de pasar el criterio de forma superficial). Qué pasa: alguien escribe "Bruno revisa manualmente cada plan antes de cualquier apply en producción, todas las semanas, a partir de hoy" — tiene dueño, plazo, y parece específico. Cómo detectarlo: si tu action item, aunque tenga las cinco condiciones, sigue dependiendo de que una persona específica preste atención en cada ocasión futura, en vez de que un mecanismo automático haga el trabajo. Cómo corregirlo: SMART es una condición necesaria, no suficiente — un action item también debe superar la pregunta de la lección 2: "¿esto es un cambio de sistema, o depende otra vez de la atención humana en el momento crítico?". Los cuatro action items de esta lección pasan ambas pruebas: SMART, y "no depende de que alguien recuerde hacer algo cada vez".

Asignar los cuatro action items a la misma persona, "porque es quien más sabe de infraestructura" (de repetir, a nivel de action items, el mismo patrón de concentración de responsabilidad que ya causó parte del incidente). Qué pasa: alguien, al asignar dueños, pone a la persona técnicamente más capaz en los cuatro, sin considerar la carga resultante. Cómo detectarlo: si tu tabla de action items tiene un solo nombre en la columna "Assignable". Cómo corregirlo: el Paso 3 de esta lección distribuye los cuatro entre Ana, Bruno, Carla y Diego —los cuatro nombres de la rotación real de INCIDENT-RESPONSE-PLAN.md—, precisamente para que ningún action item espere a que una sola persona tenga tiempo disponible; Google SRE recomienda un dueño único por item, no un dueño único para todos los action items de un mismo postmortem.

Marcar un action item como "completado" sin la evidencia medible que su propia definición exige (de declarar sin verificar, el mismo error ya nombrado en TIMELINE.md y POSTMORTEM.md). Qué pasa: alguien cierra el action item #1 diciendo "ya está resuelto" sin haber corrido terraform plan para confirmar que el bloque lifecycle de verdad bloquea la eliminación. Cómo detectarlo: si no puedes señalar la salida exacta de un comando, o el documento exacto, que demuestra que el criterio "Measurable" de ese action item se cumplió. Cómo corregirlo: cada fila "Measurable" de la tabla del Paso 3 describe una verificación ejecutable, no una promesa — antes de marcar cualquier action item de esta guía como cerrado, la verificación descrita en esa fila debe correrse de verdad, exactamente la misma disciplina que SLO.md, INCIDENT-RESPONSE-PLAN.md y TIMELINE.md ya exigieron para sí mismos.


Ejercicios

Ejercicio 1 — Reescribe, con criterio SMART completo, este action item vago: "Mejorar la documentación de Terraform para que sea más clara".

Ver solución

Una versión SMART posible: "Agregar, a andes-cargo-infra/README.md, una sección 'State file handling' que documente explícitamente el origen esperado del state activo y el procedimiento para validarlo contra la infraestructura real antes de cualquier plan — Specific: una sección nueva, con contenido definido; Measurable: la sección existe y contiene, como mínimo, los tres pasos de validación descritos; Assignable: un solo dueño nombrado (por ejemplo, Ana); Realistic: es un cambio de documentación, sin dependencias técnicas; Time-bound: dentro de una semana." La versión original ("mejorar la documentación para que sea más clara") falla las cinco condiciones a la vez: no dice qué documentación, no dice cómo se mediría "más clara", no tiene dueño, no dice si es realista sin conocer el alcance, y no tiene plazo.

Ejercicio 2 — Explica por qué el action item #4 de esta lección (evaluar backup/PITR) tiene la palabra "documentar el resultado real" en su condición "Specific", en vez de "confirmar que funciona".

Ver solución

Porque el resultado técnico real todavía no se conoce en el momento de escribir este action item —la propia lección 3 y la sección "Realistic" de esta tabla ya reconocen que la cobertura de la API de backup de LocalStack no está confirmada con la misma certeza que CloudWatch—. Si el action item prometiera "confirmar que funciona", un resultado honesto pero negativo (la API no está soportada, o falla por una razón técnica específica) haría que el action item pareciera "fallido" o "incumplido", cuando en realidad se cumplió exactamente lo que pedía: investigar y documentar la verdad, sea cual sea. Esta es la misma disciplina que cloud-security-and-guardrails-guide ya aplicó con CloudTrail en su Módulo 7 — un action item de investigación honesta se cumple documentando el resultado real, no garantizando de antemano cuál va a ser ese resultado.

Ejercicio 3 — Un compañero propone fusionar los action items #1 y #2 en uno solo ("agregar controles automáticos contra destroy en Shipments"), argumentando que ambos apuntan al mismo objetivo. ¿Estás de acuerdo, usando el Ejercicio 2 de la lección 3 de este módulo?

Ver solución

En desacuerdo. El Ejercicio 2 de la lección 3 de este módulo ya estableció que las causas raíz #2 y #3 —el gate automático antes del apply, y la protección a nivel de recurso— actúan en puntos distintos de la cadena, con consecuencias distintas si solo una funciona: el gate detiene el plan antes de que exista la opción de aplicarlo; prevent_destroy bloquea la ejecución del propio recurso como última línea de defensa, incluso si el gate falla por cualquier razón. Fusionar los action items #1 y #2 en uno solo perdería exactamente esa distinción — un solo action item "Specific" que en realidad cubre dos mecanismos independientes es más difícil de verificar con precisión ("Measurable"), porque completar solo uno de los dos podría marcarse, incorrectamente, como el action item entero resuelto. Mantenerlos separados, cada uno con su propio dueño y su propia verificación, es más fiel al principio de defensa en profundidad que sostiene ambas causas raíz.


Resumen y siguiente paso

Esta lección expandió la tabla breve de POSTMORTEM.md en cuatro action items SMART completos: prevent_destroy sobre Shipments (Bruno, P1), la cobertura de no-destroy-shipments.rego sobre terraform destroy (Carla, P2), el runbook completo de Andes Cargo (Ana, P1), y el intento honesto de backup/restore (Diego, P2) — cada uno con un dueño único de la rotación real de INCIDENT-RESPONSE-PLAN.md, una condición medible con evidencia verificable, y una fecha. Confirmaste, con la cita de Ben Treynor Sloss, por qué esta lección no es un paso opcional: un postmortem sin action items que se cumplen tiene, para quien depende del sistema, el mismo valor que ningún postmortem.

Antes de avanzar deberías poder: aplicar las cinco condiciones de SMART a cualquier action item nuevo; explicar por qué un action item puede pasar SMART y seguir siendo, en el fondo, una tarea sobre una persona; y nombrar los cuatro dueños y prioridades de esta lección de memoria.

La lección 5 cambia de documento por completo: qué es (y qué no es) un runbook, la pieza que el action item #3 de esta lección todavía debe entregar.

Recursos

  1. Google SRE Workbook — Postmortem Culture — la fuente de las citas sobre dueño único, número de seguimiento y prioridad de cada action item.
  2. cloud-security-and-guardrails-guide, Módulo 1, lección 6 (06-blast-radius-revisited-what-would-have-stopped-it.md) — la fuente del hueco declarado de prevent_destroy sobre Shipments, cerrado por el action item #1 de esta lección.
  3. Este mismo repositorio, Módulo 5, lección 8 (08-project-andes-cargos-incident-response-plan.md) — INCIDENT-RESPONSE-PLAN.md, la fuente de los cuatro nombres asignados como dueños.
  4. Este mismo repositorio, Módulo 7, lección 3 (03-hands-on-writing-the-claude-code-incident-postmortem.md) — POSTMORTEM.md, la fuente de la tabla breve que esta lección expande.