Jesús Erro
Explorar conexiones
Flujo luminoso de un único HEAD de feature hacia un gate CI, aceptación humana y merge a main con una CI distinta, junto a localhost, facade y navegador en contenedor.

Director–Implementer Loop R4.4-AG: una CI por HEAD y Playwright sin fricción

La Revisión 4 fijó quién decide. La Revisión 4.1 dio hogar al handoff y gate al humano. R4.3-AG afinó la operación agent-first: contexto fresco, CI despachada sin espera, validación visual canónica y cierre verificable hasta producción.

R4.4-AG no reescribe ese loop. Elimina dos formas de orquestación accidental que el dogfooding real dejó a la vista:

  1. volver a lanzar feature CI sobre el mismo HEAD sólo porque una PR pasa de Draft a Ready;
  2. obligar a cada Implementer a redescubrir el networking Docker ↔ WSL para validar una página.

La forma corta sigue siendo la misma:

Implementer:
builds → validates → launches → shows → stops

Human:
reviews → accepts

Director:
audits → interprets → merges → verifies → closes

La evolución está en cómo se ejecuta, no en quién decide. Menos orquestación accidental; los mismos gates.

De dónde venimos

La genealogía deliberada es esta:

R4
ownership

R4.1
GitHub handoff + localhost + human gate

R4.2
rejected automatic wake-up experiment

R4.3-AG
fresh context + CI dispatched + rendered validation + full closure

R4.4-AG
one feature CI per HEAD + canonical Playwright facade

R4.2 permanece como experimento rechazado. Automatizar el gesto de «despertar al Director» añadió opacidad y agentes esperando. R4.4 avanza por el otro camino: quitar fricción que no aporta gate nuevo.

Primer hallazgo: CI redundante al pasar a Ready

R4.3 había resuelto correctamente una ambigüedad importante:

expected CI
≠ CI DISPATCHED
≠ observed CI
≠ interpreted CI

El Implementer confirma el dispatch una vez y se detiene. El Director observa e interpreta. Eso funcionaba.

Pero el workflow del adapter todavía reaccionaba al evento ready_for_review.

Durante dogfooding real la secuencia fue esta:

  1. el HEAD de feature ya había sido validado;
  2. el humano aceptaba localhost;
  3. el Director pasaba la PR de Draft a Ready;
  4. la plataforma lanzaba otra feature CI sobre exactamente el mismo SHA.

La evidencia histórica fue una ejecución redundante —en aquel momento, la #363— sobre un commit que no había cambiado. Cambiar el estado administrativo de una PR no cambia el código que estamos validando.

El principio quedó claro:

same HEAD
+ already green CI
+ no new commit
= reuse evidence

No ejecutar otra feature CI sólo porque Draft cambie a Ready. Ready debe significar aceptación humana y continuidad del Director, no «vuelve a comprobar el mismo código».

Contrato R4.4: una feature CI por HEAD

La corrección que consolidó la versión estable redujo los triggers de feature a eventos que pueden justificar una validación nueva del HEAD:

opened
synchronize
reopened

ready_for_review deja de ser trigger de CI.

El flujo conceptual queda así:

feature HEAD A

      └── CI A ── green

       human accepts

        Draft → Ready

             └── NO CI

             expected-head merge

               main HEAD M

                    └── CI M

La CI de main no es duplicada. Valida otro commit y otro estado del sistema: el árbol ya mergeado, con su post-merge y su camino a despliegue. Reutilizar la feature CI verde del HEAD exacto no elimina la CI de main; elimina la repetición inútil sobre el mismo SHA.

Prueba final real

El último dogfood antes de promover R4.4 cerró el contrato con un caso concreto:

PR de promoción del facade / covers
feature HEAD b2828ec…
feature CI #370

Secuencia verificada:

HEAD b2828ec…
→ #370
→ green
→ Draft → Ready
→ no nueva CI feature
→ expected-head merge
→ nuevo commit en main
→ #371
→ green
→ deployments verdes

Ready dejó de significar «vuelve a comprobar el mismo código». Volvió a significar únicamente:

el gate humano ha sido aceptado y el Director puede continuar.

Esa es la semántica que R4.4 quiere conservar.

Segundo hallazgo: Playwright funcionaba, pero filtraba infraestructura

playwright-docker ya era un runtime válido. El problema no era Playwright.

El problema era que cada implementación acababa conociendo detalles como:

WSL IP
Docker bridge
host.docker.internal
--add-host
bind address
container → host networking
effective base URL
cleanup

Ese conocimiento reaparecía en handoffs y sesiones del Implementer. No aportaba un gate nuevo. Era fricción operacional accidental: el agente aprendía topología de red en lugar de validar la superficie del producto.

El facade canónico

R4.4 separa tres capas con responsabilidades distintas:

playwright-ui-validation

validation contract

devx playwright

operational facade

playwright-docker

browser runtime

playwright-ui-validation

Define qué debe validar el agente: páginas, interacciones, responsive, consola, requests, screenshots o evidencia razonable, y ausencia de errores relevantes.

devx playwright

Define cómo alcanzar el runtime desde el entorno real. Absorbe bridge efímero cuando hace falta, host aliasing, traducción de URL, PLAYWRIGHT_BASE_URL, preparación de Docker y cleanup.

playwright-docker

Sigue siendo la pieza de bajo nivel que ejecuta el navegador de forma reproducible.

No se sustituyen entre sí. Un HO de producto no debería reinventar ninguna de las tres.

Qué desaparece del HO normal

Un handoff R4.4 ya no debería enseñar al Implementer procedimientos manuales como:

descubre la IP de WSL
cambia el bind
crea un --add-host
prueba host.docker.internal
recalcula la URL visible desde Docker

El contrato normal pasa a ser:

localhost está disponible

devx playwright

effective runtime URL

browser validation

La señal fuerte de aceptación del facade es:

FACADE_ACCEPTANCE: PASS

Significa que la validación se realizó sin workaround manual de networking. Si el agente tuvo que inventar IPs o flags ad-hoc, el facade no ha cumplido su promesa aunque la página acabe validándose.

Dogfood real del facade

El caso Books Explorer / validación de carátulas lo demostró en vivo.

El humano seguía viendo la URL estable:

http://127.0.0.1:8000

Mientras el facade podía proporcionar automáticamente otra URL efectiva al navegador dentro de Docker. El harness debe consumir PLAYWRIGHT_BASE_URL y no asumir que la URL observada desde el contenedor coincide literalmente con la URL local.

Se validaron superficies reales: listado, filtros, búsqueda, paginación, detalle, carátulas, Private Notes, responsive, consola, page errors y network errors.

El propio dogfood detectó dos supuestos del harness —ignoraba PLAYWRIGHT_BASE_URL y asumía un trailing slash concreto— y permitió corregirlos. Eso es exactamente por qué dogfoodear infraestructura es más útil que diseñarla sólo en abstracto: el contrato se prueba contra el harness que realmente ejecuta el agente.

Al publicar este mismo artículo con R4.4 apareció otro detalle del adapter Astro/Vite: el servidor de desarrollo rechazaba el host hostmachine que el facade usa para alcanzar localhost desde Docker. La corrección no fue inventar networking ad-hoc en el HO; fue permitir ese host en la configuración del servidor para que el facade siga siendo la entrada canónica.

Golden flow R4.4-AG

Director

HO

Implementer pre-flight

implementation

local validation

self-review

commit + push

Draft PR

exact-head Evidence Pack

feature CI dispatched once

rendered validation
  playwright-ui-validation
  + devx playwright

localhost human gate

STOP

Human

accepts

Director

audit exact HEAD

reuse existing green feature CI

Ready
  └─ no redispatch

expected-head merge

main CI

deployment

production verification

issue close

cleanup

El Implementer sigue deteniéndose después de evidencia, dispatch y localhost. El humano conserva el gate visual. El Director conserva interpretación de CI, Ready, merge, producción y cierre.

Qué R4.4 deliberadamente NO automatiza

R4.4 no introduce:

  • Tasks despertando al Director;
  • webhooks de wake-up;
  • CI watchers;
  • Implementer haciendo polling;
  • merge autónomo;
  • eliminación del gate humano;
  • eliminación de localhost;
  • generic workflow engine;
  • state-machine framework;
  • agentes observadores permanentes.

El aprendizaje de R4.2 sigue vigente:

automatizar un gesto no es una mejora si para hacerlo añadimos una nueva capa de orquestación, opacidad o agentes esperando.

R4.4 reduce fricción dentro del recorrido existente. No convierte el loop en una orquestación genérica.

DIL Core frente al adapter de jesuserro.com

DIL Core

Conceptos portables:

  • Director;
  • Implementer;
  • Human;
  • exact-head evidence;
  • CI ownership;
  • human acceptance;
  • expected-head merge;
  • post-merge verification;
  • failure routing;
  • STOP boundaries.

Adapter actual

Tecnologías concretas de este proyecto:

  • GitHub;
  • GitHub Actions;
  • Vercel;
  • WSL;
  • Docker;
  • Playwright;
  • devx;
  • GitNexus.

Otro proyecto puede conservar el Core y sustituir por completo este adapter. GitHub, Vercel o WSL no son requisitos universales del patrón; son la expresión actual en jesuserro.com.

Cómo se promovió R4.4

No se declaró estable de inmediato.

R4.4 rc1

dogfood

duplicate Ready CI discovered

rc2

trigger corrected

Books Explorer dogfood

Playwright facade dogfood

final Draft → Ready self-test

feature #370 once

main #371

promotion PR

R4.4-AG stable

La idea editorial importante:

una versión del proceso que gobierna las entregas debe demostrar su comportamiento entregando trabajo real.

Los nombres rc1 y rc2 pertenecen a la historia de promoción. La versión pública estable se llama R4.4-AG.

Epílogo: la propia promoción probó failure routing

Durante el post-merge de la promoción, la CI #373 empezó en rojo. canonical-postgres falló al descargar PostgreSQL desde Docker Hub: la conexión con auth.docker.io se reseteó. El fallo no había llegado a Liquibase ni al código del repositorio.

Se clasificó como infraestructura externa. El Director no inventó un cambio de código ni relanzó indiscriminadamente toda la entrega. Hubo un rerun dirigido del job afectado. El segundo intento arrancó PostgreSQL, ejecutó Liquibase y terminó verde. La CI #373 acabó verde.

Eso ilustra dos frases que R4 ya pedía y R4.4 sigue practicando:

red ≠ code defect

y:

observe
→ classify
→ route
→ rerun only when justified

R4.4 terminó dogfoodeándose incluso durante su propia promoción.

R4.4-AG en una frase

R4.3 enseñó a despachar CI sin quedarse esperando. R4.4 enseña a no despacharla otra vez sin motivo y a validar lo renderizado sin convertir cada HO en un tutorial de networking Docker/WSL.

Menos orquestación accidental. Los mismos gates. El mismo ownership.