Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help


id: ADR-016 title: Las excepciones de holding-crate están acotadas, registradas y concedidas por el Core Team date: 2026-09-02 status: propuesto relates-to:

  • ADR-007
  • crates/zeroclaw-runtime/AGENTS.md
  • docs/book/src/foundations/fnd-001-intentional-architecture.md
  • https://github.com/zeroclaw-labs/zeroclaw/pull/10557
  • https://github.com/zeroclaw-labs/zeroclaw/pull/10410
  • https://github.com/zeroclaw-labs/zeroclaw/pull/10179

ADR-016: las excepciones del crate de retención son acotadas, registradas y otorgadas por el equipo central

Contexto

crates/zeroclaw-runtime/AGENTS.md declara que ese crate es un área de transición provisional, indica a los colaboradores que no añadan nueva funcionalidad allí y nombra los subsistemas que esperan ser extraídos. La instrucción es incondicional y no tiene un proceso de excepción.

Esa combinación no tiene respuesta para el caso habitual: el trabajo aceptado aterriza en un subsistema que todavía reside en el crate provisional, y el crate al que debería trasladarse aún no se ha creado. El contrato prohíbe el único destino disponible, y el destino todavía no existe. Tres pull requests llegaron a ese estado y lo resolvieron de tres maneras distintas.

La guarda de precondición de cron pasó por #10220, luego por una excepción puntual propuesta y, finalmente, por la extracción completa en #10557. La extracción fue el resultado correcto, pero se llegó a ella construyendo dos alternativas completas y descartando una. Un colaborador debería poder determinar si la extracción es necesaria antes de implementarla dos veces.

#10410 mantuvo la configuración compartida y la coordinación del ciclo de vida de los agentes en el runtime, en lugar de crear un crate de ciclo de vida antes de la extracción planificada del daemon. La justificación ofrecida para esa ubicación es que mover el código a zeroclaw-infra invertiría una dependencia existente, ya que config ya depende de infra, y que extraer el código de forma anticipada establecería un límite que la hoja de ruta no pretende. Ese es el argumento a favor de una excepción en ese punto, no una conclusión cerrada: la ubicación no ha sido aceptada, y #10410 necesita su propia resolución explícita según el proceso que establezca este registro.

#10179 encontró la misma regla, pero su transporte no tenía ningún llamador receptor. En ese caso, retirarlo o tomar una decisión explícita de propiedad era una mejor respuesta que cualquier excepción.

Esos tres casos difieren en naturaleza, no solo en tamaño. La extracción era proporcionada en uno, habría producido el límite incorrecto en otro y era irrelevante en el tercero. Una única instrucción incondicional no puede distinguirlos, y el silencio sobre las excepciones ha hecho que cada colaborador tenga que adivinar.

Las alternativas son mantener la instrucción incondicional y exigir la extracción en todos los casos, relajarla de forma general, o mantener la extracción como opción predeterminada y definir cómo se concede una excepción acotada.

Decisión

Extraer sigue siendo el valor predeterminado. El Equipo Principal puede aprobar una excepción acotada cuando la extracción inmediata requiera una refactorización desproporcionada o establezca un límite de crate que la hoja de ruta no pretende.

Lo que debe indicar una excepción

An approved exception names all four of:

  • Ámbito permitido. Las rutas específicas que cubre la excepción. No un subsistema en abstracto.
  • Destino previsto. El crate al que se espera que migre el código, de modo que la excepción describa un retraso y no una reversión.
  • Autoridad aprobadora. Quién la concedió.
  • Condición de vencimiento o de revisión. Qué la termina o cuándo se reconsidera. El registro debe indicar cuál de las dos es, porque se comportan de forma distinta (véase más abajo).

Qué significa la caducidad

Una excepción caduca o pasa a revisión, y el registro indica cuál.

Un vencimiento pone fin al permiso. Las adiciones posteriores al alcance cubierto requieren entonces la renovación del Core Team. No exige eliminar el código que ya se integró bajo la excepción: el permiso caduca hacia adelante, no hacia atrás, y deshacer lo que ya se aceptó corresponde a la extracción, no es una consecuencia de que pase una fecha.

Una condición de revisión no pone fin a nada por sí misma. Obliga al Core Team a reconsiderarla, y el resultado de esa reconsideración es la renovación, la expiración o la extracción.

Cómo se concede

La presentación se crea antes de que se fusione la función, y por separado de ella. Una pull request de una función no puede concederse a sí misma una excepción, porque el contrato que intentaría eximir es precisamente el que la limita.

Una excepción requiere un caso de uso concreto y compatible. El código sin ningún llamador receptor no cumple este requisito; en ese caso, la respuesta correcta es retirarlo o tomar una decisión explícita de propiedad.

Cómo se registra una excepción individual

Se concede una excepción de la misma forma que cualquier otra decisión del repositorio: mediante revisión en un pull request que añade la entrada a la tabla de excepciones activas en el AGENTS.md del crate responsable, aprobado por el Core Team. No existe un mecanismo separado ni aprobación fuera de las reglas de revisión habituales.

Una decisión que existe solo en un hilo de revisión no se ha tomado, porque nada que lea el contrato después la encontraría.

Lo que no es una excepción

Una excepción permite seguir trabajando en un subsistema que el crate que la contiene ya incluye. Nunca permite introducir un nuevo subsistema allí, y no se generaliza de un subsistema a otro. Conceder una para cron no dice nada sobre el daemon.

Adopción

Este registro convierte una prohibición incondicional en un permiso bajo condiciones establecidas, por lo que constituye un cambio de gobernanza y de proceso de contribución, y no una edición documental ordinaria. FND-003 §8 rige esa vía.

Adoptar esta propuesta es, por tanto, una decisión del Core Team que debe tomarse y registrarse explícitamente, incluyendo qué vía de FND-003 §8 aplica. Este pull request es la propuesta concreta, no la adopción. Hasta que esa decisión quede registrada, la instrucción incondicional sigue vigente y no se ha concedido ninguna excepción.

Consecuencias

Los colaboradores obtienen una ruta de decisión que puede resolverse antes de la implementación, en lugar de después. El caso de cron costó dos implementaciones completas para responder una pregunta que un registro breve podría haber resuelto primero.

Cada excepción es visible y tiene fecha. La tabla de excepciones activas del contrato de holding-crate hace legible la deuda acumulada, y cada entrada indica qué la pone fin, de modo que una excepción que se ha vuelto permanente sin que nadie lo notara resulta evidente en lugar de quedar oculta.

The Core Team asume la evaluación de la proporcionalidad caso por caso. Esto es deliberado: los tres casos anteriores muestran que el juicio no puede reducirse a un umbral de tamaño, porque “refactorización desproporcionada” y “límite mal definido” son motivos distintos que comparten el mismo síntoma.

La instrucción de holding-crate mantiene su fuerza. Esto no la debilita; proporciona el proceso que la instrucción daba por supuesto pero nunca definió.

Aceptación

ADR-016 permanece en estado propuesto hasta que:

  • crates/zeroclaw-runtime/AGENTS.md establece la regla de excepción y contiene una tabla de excepciones activas;
  • al menos una excepción se ha concedido o denegado a través de este proceso, lo que demuestra que es utilizable y no solo que está escrito.