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.

La continuación estable de esta línea es R4.6-AG: fronteras semánticas de ejecución, Implementer Delivery Pack y READY como mutation boundary, sin debilitar las garantías de R4.4.