Saltar a contenido

Cómo funciona

Tres verdades con tiempos de vida distintos

Verdad Dónde Vive Cambia mediante
El contrato .atipspec/contract.md todo el proyecto una decisión aceptada
Las specs vivas .atipspec/specs/<capability>.md el producto atipspec deliver
Una entrega .atipspec/deliveries/<slug>/ días o semanas las fases

El contrato dice cómo está construido el sistema: stack, estructura, policy de dependencias, convenciones, quality gates y un bloque de reglas que el CLI evalúa. Las specs vivas dicen qué hace el producto, un fichero por capacidad. Una entrega es la unidad de cambio: su propia spec, plan, evidencia, revisión y hallazgos aplazados, creada, verificada y archivada como un todo.

Alrededor de ellas están el registro de decisiones, las iniciativas que agrupan entregas a lo largo de meses, y dos documentos curados, overview.md y glossary.md, que mantienen el proyecto explicable en una página.

Quién decide qué

Pregunta La responde
¿Qué construimos? Tú, aprobando la propuesta (escenarios, enfoque y pruebas) en la conversación
¿Bajo qué reglas? El contrato que aprobaste, registrado con atipspec accept contract --code <code> e impuesto por check y audit
¿Está terminada una tarea? El asistente lo declara con atipspec task-done, atado al acuerdo aprobado; una declaración de avance, no una prueba
¿Pasa sus comprobaciones? atipspec verify, que ejecuta la verificación final y registra los códigos de salida y el hash del árbol
¿Cumple la spec? Un revisor en una sesión aislada, declarada en review.md, con un veredicto por criterio y un puntero que la puerta resuelve
¿Se acepta el resultado? Tú, aceptando el resultado revisado que muestra atipspec report; o, bajo una policy de confianza, check --policy con evidencia de CI de confianza y aprobaciones de producto, ingeniería y QA (verified)
¿Cuándo se fusiona? La política de tu repositorio; antes, atipspec merge-check confirma la branch

El asistente presenta el acuerdo con su código de aprobación y ofrece Aprobar y continuar, Pedir cambios o Cancelar, con el selector del cliente o una respuesta escrita. Tras tu aprobación explícita, ejecuta atipspec accept ... --code <code> y continúa. Claude Code, configurado por init y abierto en la raíz del proyecto, te pregunta antes de que ese comando se ejecute; ese aviso confirma la misma aprobación. No tienes que ejecutar comandos ni editar estados. El verificador registra la evidencia y el revisor registra los veredictos; ninguno puede sustituir tu decisión. Un acuerdo que cambia necesita una nueva aprobación. Las policies de confianza externas conservan su procedimiento autenticado.

Una aceptación que puedes comprobar

Hay tres decisiones humanas, cada una presentada por una vista que imprime un código de aprobación (XXXX-XXXX, los primeros 40 bits del sha256 del contenido en base32 de Crockford):

Decisión Se presenta con Se registra con
La propuesta: escenarios, enfoque y pruebas atipspec proposal <slug> atipspec accept <slug> proposal --code <code>
El resultado revisado atipspec report <slug> atipspec accept <slug> result --code <code>
El contrato y sus decisiones, una vez por proyecto atipspec proposal contract atipspec accept contract --code <code>

accept se niega cuando el código no corresponde al contenido actual, así que el registro ata la versión que viste. Escribe un hash de ese contenido, los digests por fichero, el código y el canal en approvals/local-<phase>.json (el del contrato, en .atipspec/approvals/contract.json). check compara el hash con los ficheros en disco en cada ejecución; un solo byte editado después de tu aceptación devuelve la entrega a draft con un todo que nombra el fichero que cambió. Las entregas guiadas, fixes incluidos, necesitan el registro de la propuesta; un par de spec y plan no lo sustituye. Las entregas antiguas aprueban su spec, y su plan cuando approve_plan está activado, con accept <slug> spec|plan --code <code>; un fix creado antes de 0.3.0 aprueba solo su spec.

El canal dice cómo te llegó el comando:

Canal Significado
terminal El código se tecleó en la solicitud del CLI, en una terminal sin marcadores de agente
client-permission Claude Code ejecutó atipspec accept por sí mismo, y las reglas de este proyecto, intactas, hacen que te pregunte antes en una sesión abierta en la raíz del proyecto
assistant Nada te preguntó: un cliente sin reglas de permisos, reglas alteradas, el marcador de otro agente junto al de Claude Code, Claude Code ejecutado con el Agent SDK o con claude -p, o una línea de comandos que la regla no reconoce, como python -m atipspec.cli

El CLI solo ve su propio proceso, así que cada canal es lo que declara ese proceso. No puede ver si la sesión cargó las reglas: una sesión abierta en otra carpeta que entra en el proyecto con cd no pregunta y registra client-permission. Un script, o un agente que no fija ninguno de los marcadores listados en entorno, que Claude Code ejecuta y que llama dentro a atipspec accept también registra client-permission, aunque Claude Code solo te preguntó por el script o por el agente. Y un agente puede quitar sus marcadores y contestar a la solicitud del CLI desde una terminal que él crea, lo que registra terminal.

Esto es detección de deriva, no autenticación: el registro demuestra qué se aceptó y cómo se ejecutó el comando, no quién eres. Las aprobaciones firmadas bajo una policy externa son la forma autenticada, y cuando hay una policy configurada, la puerta ignora los registros locales. Consulta aceptación empresarial.

Las fases que abre el CLI

Una fase empieza con su comando: atipspec spec <slug>, atipspec plan <slug>, y así sucesivamente. El comando comprueba qué exige la fase y se niega con una línea cuando falta algo: los escenarios incompletos, la propuesta sin aprobar, una tarea sin registrar. Si no, imprime el workflow, las reglas y el contexto, para que el modelo trabaje a partir de lo que abrió el CLI y no de su propia lectura de la petición. atipspec ship <slug> nombra la siguiente fase a la que una entrega puede entrar. Consulta el flujo.

La puerta

atipspec check <slug> comprueba la consistencia local. La aceptación de confianza exige además --policy. Lee los ficheros y git, e informa de tres tipos de cosas:

  • error: algo está mal o falló. La puerta está en rojo.
  • todo: algo todavía no ha pasado. La puerta todavía no está en verde.
  • warning e info: merecen atención, no bloquean.
password-reset  [implemented]  tasks 2/2
  error   AC-003 FAIL: the link never expires
  error   F1 [blocker] contract: shop/domain/order.py:3 contains forbidden pattern 'from shop\.infrastructure'
  todo    review.md is stale (the working tree changed since the review); run `atipspec review password-reset` and review again
  info    F2 [minor] Missing docstring
Next: Fix: AC-003 FAIL: the link never expires

El código de salida 0 significa que las comprobaciones seleccionadas pasaron, 1 significa errores y 2 significa incompleto. La puerta falla de forma cerrada: sin git está en rojo, porque el commit base, las reglas del contrato y la frescura de la evidencia vienen de git. Sin una policy, el verde es solo checked, y deliver exige además tu aceptación registrada del resultado; con la policy externa, exige una puerta de confianza en verde. Antes de la fusión, atipspec merge-check --base <target> comprueba la branch entera: cada entrega que toca está aceptada, y el código sigue siendo el que aceptó cada recibo.

Evidencia atada al árbol

atipspec verify ejecuta los comandos que declara una tarea y escribe un fichero JSON con los comandos, los códigos de salida, las colas de salida, la duración y la huella del árbol de trabajo: un hash de contenido calculado a través de un índice de git temporal, idéntico antes y después de hacer commit del mismo contenido. La revisión registra la misma huella. Cuando el árbol cambia, ambas quedan obsoletas y la puerta las vuelve a pedir; renombrar una tarea en el plan es el único cambio que sobreviven. Integrar main también cambia el árbol, que es justo el objetivo: no existe eso de «funcionaba en mi branch». Un informe JUnit solo cuenta cuando lo escribió esa ejecución: verify lo borra primero, y check nunca ejecuta los tests por sí mismo.

Estado derivado

El estado nunca se almacena: status y check calculan en qué punto está una entrega a partir de sus ficheros y de git en cada ejecución. Lo que leen son registros en el repositorio: las aprobaciones, progress.json, la evidencia, review.md y el recibo.

draft → planned → in_progress → implemented → checked → accepted → delivered

checked es la puerta local en verde; accepted añade tu aceptación registrada de ese resultado; bajo una policy de confianza, verified es la puerta de confianza en verde. Una entrega antigua pasa también por ready, su spec aceptada antes de que exista un plan. atipspec accept mueve una spec a ready, y el contrato y sus decisiones a accepted. La puerta trata un ready escrito a mano sin un registro de aceptación correspondiente como un borrador, y un contrato, o una decisión que lo afecta, marcados accepted a mano sin un registro correspondiente como no aceptados. Una decisión sobre una capacidad es el único estado que escribe el asistente: la marca accepted después de que la apruebes en la conversación, sin código ni registro, y la siguiente atipspec proposal la lista para que veas lo que seguirán la implementación y la revisión.

Un contexto que no crece con el proyecto

atipspec context <slug> reúne exactamente lo que una fase necesita: el contrato, el overview, el glosario, las specs vivas que nombra la lista impact de la entrega, las decisiones aceptadas que las afectan y los propios ficheros de la entrega. Nunca archive/. Imprime el tamaño contra context_budget, y audit avisa cuando un documento supera su tope para que la fase curate pueda reducirlo.

Siguiente: el flujo.