Medido el 2026-09-09 · 23:47 −03, ampliado 2026-09-10 · 00:10 −03 · cuatro repositorios

Cuatro casas, medidas

El antes y el después de una noche de trabajo. Cada número de esta página salió de un comando corrido sobre el árbol real, con el mismo instrumento en los dos extremos. Lo que no se pudo medir dice que no se pudo medir.

01

El alfabeto con el que se lee todo lo demás

Tres estados, no dos. La página entera usa estos tres colores y no significan nada más que esto.

0
Medí y está bien
Hay un comando, se corrió, y salió lo esperado.
1
Medí y está mal
Hay un número, y el número es malo. Se puede arreglar.
2
No pude medir
El instrumento no alcanzó al objeto. No es un cero.

Un 2 nunca se degrada a 1, y un 1 nunca a 0. Una salida vacía no es un cero medido: es que nadie miró.

02

La noche entera, en un dibujo

De izquierda a derecha: lo que estaba trabado al empezar, qué candado lo frenó o lo destrabó, y dónde terminó. Los tres rombos son los controles que se dispararon solos — ninguno de los tres defectos de abajo lo encontré yo mirando: los encontró un candado al intentar publicar.

flowchart LR
  classDef casa fill:#EDEAE2,stroke:#16202B,stroke-width:1.5px,color:#16202B,rx:4,ry:4
  classDef malo fill:#F7E5E2,stroke:#B3372C,stroke-width:1.5px,color:#7A241C,rx:4,ry:4
  classDef bueno fill:#E4F0EA,stroke:#1E7A5A,stroke-width:1.5px,color:#14513C,rx:4,ry:4
  classDef ambar fill:#F8EEDC,stroke:#B0761A,stroke-width:1.5px,color:#7A5211,rx:4,ry:4
  classDef porton fill:#FFFDF8,stroke:#16202B,stroke-width:1.5px,color:#16202B

  subgraph A["AGENTES-HQ · la plataforma"]
    A1["main EN ROJO
suite falla 2 veces"]:::malo A2{{"portón de push
mide el árbol"}}:::porton A3["PR #19 → main verde
PR #20 · 5 arreglos"]:::bueno A4["#17 y #21 cerrados
con la prueba de que
su trabajo está adentro"]:::bueno A1 --> A2 --> A3 --> A4 end subgraph R["LA RAMA VARADA · 502 líneas sólo en la Mac"] R1["registro/agentic-testing"]:::ambar R2{{"Ley 1
el contenedor no
NOMBRA una empresa"}}:::porton R3{{"Ley 2
el contenedor no
TRANSPORTA sus datos"}}:::porton R4["nunca tuvo casa acá:
era impublicable,
no olvidada"]:::ambar R5["ya estaba publicada
en SU casa desde ayer
552 líneas, mejores"]:::bueno R1 --> R2 -->|"16 nombres
en código"| R3 R3 -->|"no es configuración"| R4 --> R5 end subgraph L["ALARMAS-HQ · la casa dueña"] L1["la pared entre las dos
empresas no se podía
disparar fuera de esta Mac"]:::malo L2["+6 reglas gemelas
por nombre de carpeta"]:::bueno L3["candado + arnés
7 cazadas · 0 escapadas"]:::bueno L4["corrió EN LA NUBE
7/7 jobs verdes"]:::bueno L1 --> L2 --> L3 --> L4 end subgraph B["EL LIBRO DE PENDIENTES"] B1["una fila decía
5 ramas en riesgo"]:::malo B2{{"su contrato usaba
is-ancestor"}}:::porton B3["no ve un squash-merge:
contaba 5 donde había 2"]:::malo B4["contrato → git cherry
+ dos anclas de exit 2"]:::bueno B1 --> B2 --> B3 --> B4 end R5 -.->|"lo único propio
era la pared"| L1 A4 -.-> B1

Las flechas punteadas son las dos veces que un frente destrabó a otro: la rama varada resultó ser una copia vieja, y su único aporte real —el arreglo de la pared— se portó a la casa correcta.

03

Antes y ahora

El «antes» es el main de cada casa al terminar el 8 de septiembre; el «ahora» es el main de este momento. Mismo comando en los dos extremos.

Qué se midióAntesAhoraΔCon qué se midió
Agentes-HQ · la plataforma · dfc226e → c70930a
La suite de main 2 corridas en rojoverde destrabado gh run list --branch=main
Archivos de prueba 127146+19 git ls-tree -r origin/main
Arneses de mutación 3442+8 git ls-tree · mutar-
Candados 2224+2 git ls-tree · guard-
PRs abiertos 4 (medido 23:31)1 (de otra sesión)−3 gh pr list --state open
PRs mergeados hoy 1010 gh pr list --state merged
Commits en main hoy 2828 git log --since
Libro de pendientes no existía105 vivasnuevo grep -c '^### '
Alarmas-HQ · e9375b7 → 87a23af
Candados 710+3 git ls-tree · scripts/guard-
Arneses 2428+4 git ls-tree · scripts/mutar-
Vigías huérfanos (existen y nadie los corre) 3 de 120 de 12−3 guard-todo-vigia-tiene-quien-lo-corra
Corrida en la nube 4 fallas seguidas7/7 jobs verdes verde run 34430523667
PR #1 abierto 10 días
en conflicto
cerrado con evidencia cerrado gh pr view 1
Zymplo-HQ
PRs de dependabot abiertos 70−7 gh pr list --state open
Escaneo de secretos rojo 8c65e0fverde 67771c6 verde gh run list · workflow
Aviso de pillow rojo, sin explicarrojo, documentado sigue rojo POR-QUE-PILLOW-NO-SUBE.md
Carritos-HQ · 4d52f78 → 9088115
Workflows 01+1 git ls-tree · .github/workflows
Arnés de mutación 01 (5 mutaciones)+1 git ls-tree · mutar-
Corridas de CI 02, la última verdeencendido gh run list
Las cuatro juntas
Workflows activos en la nube 8 · 12 · 1 · 10 huecos API vs git ls-tree origin/main
PRs mergeados hoy 1818 gh pr list --search merged:>=09-09

«0 huecos» quiere decir: todo workflow versionado en main está registrado y activo en GitHub. Se comprobó comparando las dos listas, no mirando una sola.

04

Los tres defectos, y quién los encontró

Ninguno de los tres lo encontré leyendo código. Los tres los cazó un control automático en el momento exacto en que intenté publicar algo. Es la diferencia entre tener candados y tener opiniones.

I
Un control que no se dispara mide exactamente lo mismo que uno que no existe.

Las 6 prohibiciones que separan a las dos empresas estaban construidas sobre /Users/cr/Zymplo-HQ — una ruta que existe en una computadora. Esas fichas viajan a un repositorio público: en cualquier otro clon la regla no puede matchear nada. Y el archivo ya había arreglado esa misma forma para otra variable, y la dejó viva justo en la pared: la única parte cuyo trabajo es separar dos empresas. El arreglo suma 6 reglas gemelas por nombre de carpeta en vez de reemplazar — un deny de más nunca afloja al de al lado, así que no hace falta medir el matcher para saber que no puede romper nada.

lo cazó · el sello del portón, al intentar pushear · arreglado y con candado propio: 7 cazadas · 0 escapadas

II
Un instrumento que no distingue «no está» de «no lo veo» fabrica pendientes que nadie puede cerrar.

Una fila del libro decía «5 ramas viven sólo en la Mac · 3.476 líneas». Su contrato de cierre usaba git merge-base --is-ancestor, que no puede ver a través de un squash-merge: cuando un PR entra squasheado, el tip de la rama nunca vuelve a ser ancestro de main aunque su trabajo esté entero adentro. Medido con git cherry, que compara por patch-id: el número real es 2, no 5, y 1.056 de esas líneas nunca estuvieron en riesgo. Y la consecuencia es la cara: un rojo que no se puede apagar entrena a que las rojas no se lean, y se lleva puestas a las que sí se podían arreglar.

lo cazó · correr el contrato en vez de creerle · contrato reescrito, con dos anclas nuevas de exit 2

III
Esa rama no estaba olvidada: era estructuralmente impublicable, y nadie había medido por qué.

502 líneas que vivían sólo en la Mac. En flota/ las frenaba la Ley 1 (el contenedor compartido no nombra una empresa: 16 nombres en código). Movidas a instalaciones/, las frenaba la Ley 2 (el contenedor no transporta los datos de ninguna casa; ahí sólo viaja cómo está configurada). Nunca tuvo casa en ese repositorio. Y al buscarle una apareció lo mejor de la noche: el trabajo ya estaba publicado desde ayer en la casa que le corresponde, en una versión de 552 líneas y mejor. Lo único propio de la rama era el arreglo I, que se portó allá.

lo cazó · dos candados distintos, uno después del otro · el riesgo real era 526 líneas, no 3.476

05

Lo que queda rojo, y es honesto que lo esté

Dos rojos vivos. Los dos están medidos, los dos tienen dueño, y ninguno se puede apagar escribiendo código esta noche.

aprender · exit 2, no exit 1

No es «midió y salió mal»: es no pude medir. Necesita una credencial con permiso de API sobre otra casa. Probé crear el token por API: POST /user/personal-access-tokens devuelve 404 — ese camino no existe.

dueño · Carlos · 3 minutos

Zymplo · Dependabot Updates

Rojo estructural, no descuido: el aviso de seguridad exige pillow ≥ 12.3.0 y la cadena de dependencias lo fija en < 11.0.0. No hay versión que satisfaga a las dos. Queda documentado con los comandos para reproducirlo en 30 segundos.

dueño · Carlos · decisión de producto

105 filas vivas en el libro

No son las fallas de esta noche: es el mapa medido de lo que falta, levantado por 10 auditores en paralelo y sometido a 130 refutaciones. 🔴 59 · ⚠️ 32 · 🟡 9 · 🚫 5. El encabezado lo cuenta un candado, no lo escribe nadie: si mañana entra una fila y nadie toca la tabla, la suite lo canta.

dueño · yo 78 · Carlos 26 · terceros 1

06

Lo que queda encendido cuando se cierre la ventana

Regla inmutable dictada esta noche: cerrar la ventana no puede apagar nada. Cuatro patas, y las cuatro obligatorias — corre solo · se mide solo · avisa solo · aprende solo. Este es el inventario, medido reloj por reloj.

15
relojes en la nube
workflows con cron en la rama default
11
sonando
su última corrida agendada está en hora
2
callados
prometen más de lo que la nube entrega
2
sin juzgar
recién aterrizados: todavía sin oportunidades
IV
Un reloj que nunca disparó no es un reloj: es una intención escrita en YAML.

La pata 1 de esa regla no la miraba nadie, en ninguna de las cuatro casas. Se midió: el escaneo de secretos declaraba cron: '45 8 * * *', estaba en la rama default desde hacía un día, y de sus 37 corridas ninguna era agendada — con tres hermanos del mismo repo en 9, 16 y 9 como control positivo. Que el cron esté bien escrito no dice que haya sonado.

Ahora hay un candado que hace esa pregunta 4 veces por día, y distingue cinco respuestas, no dos: sonando · callado · exento escrito · todavía sin juzgar (un reloj joven no es un reloj roto) · y no pude medir. Al correrlo contra los repos reales cazó dos defectos míos: mi regex se comía los cron que tenían un comentario al final —vi 2 de 7 relojes de una casa y contesté «los 2 andando»— y una línea de borrador que el intérprete aceptaba sin chistar.

25 pruebas · el control positivo cae · el exento no puede tapar un reloj que nunca sonó

V
Iba a bajarle la cadencia al latido, y el propio repo ya había medido que eso no sirve.

El latido promete un pulso cada 30 minutos y entrega 15%. Mi primer impulso fue declarar una cadencia más honesta. Pero el repo ya lo había medido el 1 de septiembre sobre 24 corridas: la cadencia de 30 minutos nunca ocurrió —el hueco mínimo real fue de 2,39 h— y la degradación es función de la frecuencia, así que mover el minuto sólo compra la apariencia de un arreglo. El arreglo de verdad es un temporizador en una máquina que todavía no existe. Dueño escrito, con fecha.

Por eso el latido va a una lista de exentos escritos, con su motivo entero a la vista y su número al lado — no escondido. Y esa lista tiene tres cerrojos probados: no puede tapar un reloj con cero corridas, un exento huérfano da no pude medir, y uno sin motivo escrito se rechaza.

auditar antes de recomendar · leer antes de tocar