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.
Tres estados, no dos. La página entera usa estos tres colores y no significan nada más que esto.
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ó.
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.
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ó | Antes | Ahora | Δ | Con qué se midió |
|---|---|---|---|---|
| Agentes-HQ · la plataforma · dfc226e → c70930a | ||||
| La suite de main | 2 corridas en rojo | verde | destrabado | gh run list --branch=main |
| Archivos de prueba | 127 | 146 | +19 | git ls-tree -r origin/main |
| Arneses de mutación | 34 | 42 | +8 | git ls-tree · mutar- |
| Candados | 22 | 24 | +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 | — | 10 | 10 | gh pr list --state merged |
| Commits en main hoy | — | 28 | 28 | git log --since |
| Libro de pendientes | no existía | 105 vivas | nuevo | grep -c '^### ' |
| Alarmas-HQ · e9375b7 → 87a23af | ||||
| Candados | 7 | 10 | +3 | git ls-tree · scripts/guard- |
| Arneses | 24 | 28 | +4 | git ls-tree · scripts/mutar- |
| Vigías huérfanos (existen y nadie los corre) | 3 de 12 | 0 de 12 | −3 | guard-todo-vigia-tiene-quien-lo-corra |
| Corrida en la nube | 4 fallas seguidas | 7/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 | 7 | 0 | −7 | gh pr list --state open |
| Escaneo de secretos | rojo 8c65e0f | verde 67771c6 | verde | gh run list · workflow |
| Aviso de pillow | rojo, sin explicar | rojo, documentado | sigue rojo | POR-QUE-PILLOW-NO-SUBE.md |
| Carritos-HQ · 4d52f78 → 9088115 | ||||
| Workflows | 0 | 1 | +1 | git ls-tree · .github/workflows |
| Arnés de mutación | 0 | 1 (5 mutaciones) | +1 | git ls-tree · mutar- |
| Corridas de CI | 0 | 2, la última verde | encendido | gh run list |
| Las cuatro juntas | ||||
| Workflows activos en la nube | — | 8 · 12 · 1 · 1 | 0 huecos | API vs git ls-tree origin/main |
| PRs mergeados hoy | — | 18 | 18 | 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.
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.
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
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
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
Dos rojos vivos. Los dos están medidos, los dos tienen dueño, y ninguno se puede apagar escribiendo código esta noche.
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
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
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
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.
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ó
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