Una metodología spec-driven, tool-agnóstica, que empieza antes de la SPEC: de una idea vaga + material de referencia, el asistente propone la forma del sistema, vos decidís, y recién ahí se especifica, se construye y se avanza solo con evidencia. Este doc cubre la instanciación en Claude Code con el dev-loop-kit.
Convención de este doc: en el kit ya está implementado · nuevo incorporado en esta versión. Todo lo de este doc está implementado y probado en 1.1.0.
El motor de evidencia al centro, las fases del flujo a la izquierda, las seis capas de verificación a la derecha, los principios en la franja, y las piezas de Claude Code que lo sostienen abajo.
El ciclo completo es una sola línea, ejecutable por una persona, un agente o el CI. La herramienta ejecuta; la metodología gobierna; la evidencia decide; el humano aprueba.
Dos cosas que el flujo garantiza: bajar el costo de entrada (no tenés que diseñar el sistema para poder empezar — eso lo propone el Discovery) y subir la certeza de salida (un estado honesto, con evidencia y blockers, dice cuán listo está de verdad). En Claude Code todo esto vive en cuatro skills invocables y un motor de medición en Python.
El error clásico es pedirte que escribas entidades, endpoints y casos de error desde el inicio. Pero un sistema nuevo arranca antes: solo sabés qué querés lograr. Por eso hay dos frentes que emiten el mismo paquete; elegís por punto de partida.
/discovery — "no sé el cómo"Greenfield. Traés idea + restricciones + material de referencia. El asistente propone dominio, superficie de API y opciones de arquitectura; vos reaccionás y decidís. La inversión clave: vos no autorás la estructura, la aprobás. Una pregunta a la vez, cada una con su respuesta recomendada.
/adr-refine — "sé el qué, falta precisión"Feature dentro de un sistema existente. La forma ya se conoce; la entrevista adversarial pinta los bordes: casos sucios, errores, idempotencia, restricciones inviolables, out-of-scope. No emite artefactos hasta converger.
Ambos skills tienen allowed-tools: Read, Write, Glob, Grep (discovery suma WebFetch para leer manuales/PDFs/URLs). Ninguno de los dos toca código: generan claridad, no implementación.
Grill, don't agree. Un discovery donde estuviste de acuerdo con todo, falló. El valor está en las preguntas — contradicciones, términos difusos, modos de falla faltantes, restricciones no dichas — no en validar.
El frente termina escribiendo el paquete directo en el repo a medida que las decisiones se cristalizan — no junta todo para el final. El build lo lee de los archivos, no del chat.
| Archivo | Qué contiene |
|---|---|
| CONTEXT.md | Glosario del dominio. Se crea con el primer término resuelto; afila lenguaje difuso ("¿'cuenta' es Customer o User?"). |
| DOMAIN-MODEL.md | Las entidades núcleo propuestas y sus relaciones — la "forma" que propusiste y el humano aprobó. |
| SPEC.md | Objetivo/valor, riesgo, scope/out-of-scope, comportamiento, entradas/salidas/errores, acceptance, test plan, operación, rollback. |
| docs/adr/*.md | Una por decisión durable. Incluye Implementation Plan + Verification (checkboxes) → es una spec ejecutable. |
| ACCEPTANCE.md | Definition of Done como - [ ] + métricas de éxito. Es el archivo que el readiness KPI mide río abajo. |
| RISKS.md | Riesgos residuales, supuestos, puntos que necesitan aprobación humana. |
| HANDOFF.md | Qué leer antes de codear + reglas duras de "no hacer" + evidencia requerida. |
Por qué importa aunque sea todo Claude Code: el contexto se resetea (una sesión nueva, un /clear o una compactación no tienen el chat), los sub-agentes leen archivos, un compañero o el CI construyen desde el repo, y la auditoría queda durable. La verdad vive en archivos versionados.
Si describe comportamiento observable, va en SPEC. Si justifica una elección entre alternativas, va en ADR. Casi todo cambio no trivial necesita SPEC; solo algunos necesitan ADR formal.
Comportamiento, reglas, entradas/salidas/errores, criterios de aceptación, tests, operación. Es el contrato de construcción y verificación.
Una decisión técnica, las alternativas descartadas y las consecuencias. Memoria arquitectónica, no lista de tareas.
Solo si la decisión cumple las tres: difícil de revertir, sorprendente sin contexto, y fruto de un trade-off real. Si no, es ruido que entierra a los importantes.
# docs/adr/ADR-NNN-<slug>.md ## Estado: Aceptado # proposed/accepted/deprecated/superseded ## Contexto / Fuerzas ## Alternativas: A) … B) … C) … ## Decisión ## Razones ## Consecuencias (+ / -) ## Implementation Plan # affected paths · patrones · tests ## Verification - [ ] <criterio chequeable por un agente>
El Implementation Plan es lo que vuelve al ADR ejecutable: Claude Code lo lee y lo implementa sin volver a preguntar. Durante el build, el código linkea: // ADR: <slug> — see docs/adr/ADR-NNN-<slug>.md, lo que hace seguro hacer supersede (encontrás todo lo que el ADR gobierna).
El ADR elige entre alternativas. La CONSTITUTION prohíbe: registra los invariantes que ningún ADR ni SPEC puede violar, gane el trade-off que gane. Es la jerarquía de la verdad del proyecto.
SPEC dice qué debe pasar. ADR dice por qué se eligió esta forma. CONSTITUTION dice qué nunca es aceptable. Un ADR puede elegir MSSQL vs Redis para cachear el TicketAcceso; un ADR no puede elegir "guardar el certificado en texto plano" — eso lo veta la CONSTITUTION antes de discutir alternativas.
## CONSTITUTION.md — invariantes del proyecto # Seguridad (no-negociable) - Secretos nunca en logs ni en repo # CWE-532 / CWE-798 - Toda entrada externa validada # CWE-20 - Solo SQL parametrizado, nunca concat # CWE-89 # Fiscal (dominio) - Idempotencia obligatoria al emitir CAE - Numeración secuencial sin huecos lógicos - Jamás dos comprobantes por un mismo requestId # Operación - Sin migration destructiva sin rollback explícito - Ningún merge sin human gate
Desde 1.1.0 es una capa propia: templates/CONSTITUTION.md versionada con invariantes mapeados a CWE. /discovery y /adr-refine la escriben/extienden (un ADR no puede contradecirla: se escala, no se aprueba); /dev-loop la lee en Fase 0 y la consulta antes de tocar áreas gobernadas. Una violación se loguea como finding BLOCKER → capea readiness ≤65 y bloquea convergencia por construcción.
No es un agregado suelto: es donde aterrizó el SOTA. Spec Kit tiene /speckit.constitution; el OSS dpolivaev/spec-loop (mismo nombre que el tuyo) define sus reglas en CONSTITUTION.md con gates de aprobación humana. Formalizarlo te alinea con la convergencia del campo.
Pregunta inicial: ¿qué puede romper esto y cuánto cuesta si se rompe? El riesgo escala el aparato — el perfil A no arrastra toda la maquinaria.
| Perfil | Ejemplo | Documentos | Gates mínimos |
|---|---|---|---|
| A · Bajo | UI menor, config no crítica | SPEC mini | build + test relevante |
| B · Normal | feature local, bugfix | SPEC + acceptance | tests + static + review |
| C · Crítico | pagos, facturación, seguridad | SPEC formal + ADR | unit+integration+security+rollback |
| D · Multi-sistema | API pública, eventos | SPEC + contratos + ADR | contract tests + versionado |
| E · Legacy grande | refactor, migración | SPEC incremental + baseline | characterization + no regression |
/dev-loop fase por fase.El dev-loop es un orquestador spec-driven multi-repo. Toma el ADR set + ACCEPTANCE.md como input, construye, y corre un loop de review severity-gated que converge en vez de loopear para siempre, con los tests como guardrail entre pasos. Para en el merge gate. Tres principios no-negociables lo gobiernan: convergé no persigas el cero; los tests son guardrail no finale; generar tests no es correr tests.
qa_ledger.py init --config dev-loop.config.json. La config lista cada repo y su tipo (maven/flutter). En multi-repo, los otros repos se montan con --add-dir./adr-refine primero. Los acceptance criteria se vuelven los contract tests de la fase 1.snapshot --phase pre + check-coverage. Si coverage ≥ umbral, la suite existente es el guardrail. Si está por debajo (o no hay reporte): escribís characterization/contract tests en el borde (API pública, endpoints) — que el humano revise antes de confiar en ellos.qa_tools_order (default: code-review → judgment-day → improve-deep). Un pase de todas = un ciclo. Tras cada tool: aplicá solo fixes ≥ severity gate (el resto a ISSUES-DEFERRED.md), corré los tests, logueá con log-step, ingestá el static gate con ingest-gate. Chequeos advisory de fin de ciclo: converged y oscillation.--repo integration. Es la segunda capa de la arquitectura de QA: per-repo verde no implica que las costuras estén verdes./improve test escribe el coverage fino que diferiste. Suite completa verde + coverage ≥ umbral antes de seguir.summary + readiness, después /sys-doc para el deck. Retrospectiva sacada del ledger.La grieta que el método cierra: si el mismo agente que hace el cambio escribe el ledger, puede poner exit_code: 0 sin correr nada. La garantía solo vale si la evidencia la produce la ejecución — el qa_ledger.py parsea artefactos reales (JaCoCo XML, Surefire XML, los reportes de los linters), no transcribe lo que el agente dice.
# el ledger NO confía en el agente: parsea archivos
coverage ← target/site/jacoco/jacoco.xml (LINE counter)
tests ← target/surefire-reports/TEST-*.xml
static ← checkstyle-result.xml · pmd.xml · spotbugsXml.xml
LOC ← conteo propio (prod vs test), stdlib pura
Ausente = sin evidencia, nunca "OK". Un reporte de linter que existe pero está vacío acredita el fix; un reporte ausente no se trata como limpio (significa que el gate no corrió). Una herramienta que no corrió no se inventa en verde.
qa_ledger.py — referencia de comandos.Stdlib pura, Python 3.8+, sin dependencias. Es dueño de todo lo que debe ser exacto y reproducible. Los juicios (¿convergió? ¿oscila? ¿hay que escalar?) los hace el skill leyendo estos datos; el script solo expone helpers advisory deterministas.
| Subcomando | Qué hace |
|---|---|
| init | Crea el ledger desde dev-loop.config.json (repos, umbrales, comandos). |
| snapshot | Mide coverage / tests / LOC de un repo (--phase pre|post). |
| check-coverage | Exit 0 si ≥ umbral, 1 si está por debajo. Es el gate de la fase 1. |
| log-step | Registra un pase de una QA tool: reported / gated-reported / fixed / deferred / suppressed / tests-passed / files-changed / fingerprint. |
| ingest-gate | Parsea Checkstyle/PMD/SpotBugs/FindSecBugs, normaliza severidades y computa el fixed real diffeando finding-IDs contra el pase anterior. |
| converged | Advisory. Exit 0 = convergió (último ciclo de agente limpio + static gate limpio en todos los linters). |
| oscillation | Advisory. Detecta que el fingerprint de findings de una tool se repite con período 2 (pase N == pase N-2). |
| escalate | Registra un evento de escalación humana con razón. |
| summary | Métricas retrospectivas (--json lo consume /sys-doc). |
| readiness | El KPI de estado del proyecto: score 0–100 con pesos y caps duros. |
| rebuild | El rebuild test: completitud de la SPEC. --mode baseline firma el sistema; --mode compare puntúa la regeneración (COVERS/PARTIAL/DIVERGE). |
# un pase típico del loop QL=./.claude/skills/dev-loop/qa_ledger.py python3 $QL init --config dev-loop.config.json python3 $QL snapshot --repo TsTicket --phase pre python3 $QL check-coverage --repo TsTicket # exit 0/1 # ...build + una tool de QA... python3 $QL log-step --repo TsTicket --tool code-review --iteration 1 \ --reported 12 --gated-reported 4 --fixed 9 --deferred 2 --suppressed 1 \ --tests-passed true --files-changed 7 --fingerprint a,b,c python3 $QL ingest-gate --repo TsTicket --iteration 1 python3 $QL converged --repo TsTicket --tools-per-cycle 3
El static gate (tu java-qa-gate: Checkstyle/PMD/SpotBugs/FindSecBugs) no se cuenta a mano. Corrés el gate para que escriba sus XML, y ingest-gate los parsea, normaliza a una escala de severidad común, separa FindSecBugs de SpotBugs, y computa el fixed real por diff de IDs.
| Linter | Severidad nativa → escala común |
|---|---|
| Checkstyle | error → HIGH · warning → MEDIUM · info → INFO |
| PMD | priority 1 → BLOCKER · 2 → CRITICAL · 3 → HIGH · 4 → MEDIUM · 5 → LOW |
| SpotBugs | priority 1 → HIGH · 2 → MEDIUM · 3 → LOW |
| FindSecBugs | findings categoría SECURITY → piso HIGH (se separan bajo tool findsecbugs) |
Escala completa, de menor a mayor: INFO · LOW · MEDIUM · HIGH · CRITICAL · BLOCKER. El severity gate por defecto bloquea en BLOCKER / CRITICAL / HIGH; todo lo de abajo va a ISSUES-DEFERRED.md, nunca al loop. Granularidad de finding-ID configurable (file o line) para el diffing de fixed y oscilación.
Mide el estado del resultado, nunca el esfuerzo. Score ponderado 0–100 con caps duros que pisan el promedio. Los ciclos/regresiones son churn (salud del proceso) y se reportan aparte — nunca suben el readiness. Mostralo después de cualquier tarea, no solo de runs completos.
Siempre se presenta el headline con el desglose de dimensiones y el blocker que capea — así queda claro qué falta, no solo el número. Sin fórmula, no hay número: eso sería la numerología que el método evita.
El ledger prueba corrección (este build pasó). El rebuild test prueba completitud (la SPEC es suficiente para volver a generar el sistema). Dos preguntas distintas. Es el benchmark de completitud que se está estandarizando en el SOTA.
La mecánica: en un árbol limpio, una sesión fresca apunta solo al paquete (SPEC/ADR/ACCEPTANCE — no al chat) y regenera. Si reconstruye y pasa acceptance + tests → la SPEC cubre. Si diverge → la SPEC tiene huecos: casi siempre decisiones implícitas (códigos de error, estrategia de cache, elección de librería) que vivían en tu cabeza y nunca llegaron a la SPEC.
# rebuild test — subcomando real (1.1.0) # 1) tree ORIGINAL: capturá la firma $ python3 $QL rebuild --mode baseline --config dev-loop.config.json → REBUILD-BASELINE.json # 2) tree LIMPIO / sesión fresca: regenerá SOLO producción desde # SPEC/ADR/ACCEPTANCE, PRESERVANDO los tests, y corré la suite # 3) puntuá el tree regenerado contra la baseline $ python3 $QL rebuild --mode compare --baseline REBUILD-BASELINE.json REBUILD: 72.2/100 — PARTIAL ! 1 test(s) fail on regenerated code — behavior the SPEC left implicit ! coverage 45.0% vs baseline 80.0% (tolerance 5)
Implementado y probado en 1.1.0. Pesos: tests 60 · acceptance 20 · coverage 15 · surface 5. Veredictos: COVERS ≥90 · PARTIAL ≥70 · DIVERGE <70 (exit 0 solo si COVERS; --json lo consume /sys-doc). La señal dominante es la suite preservada: un test que pasaba y falla en el código regenerado = comportamiento que la SPEC dejó implícito. Cuándo correrlo: perfil C+ y E, o periódico en CI — es el QA del output del Discovery.
No limpiar todo; no empeorar nada. La deuda legacy se congela, la nueva se bloquea. Y el loop tiene techo: superarlo no es seguir solo, es escalar.
max_iterations: 5 · tools_per_cycle: 3Escalar no es fallar: es que apareció una decisión humana. El proceso detectó que no debía seguir solo. Nunca auto-merge, nunca exceder el cap en silencio, nunca arreglar por debajo del gate para que el número quede mejor.
"Loop engineering" explotó en una semana de junio 2026 (Steinberger, Cherny, Osmani): "no promptees agentes; diseñá loops que los prompteen". Cuando el frente lo bajó a spec-driven, convergió en estos mismos principios. spec-loop no quedó atrás: llegó a la misma forma por separado.
| Principio del loop autónomo trending | spec-loop | Dónde vive en el kit |
|---|---|---|
| Done-criteria que rechaza loops abiertos | ✓ | ACCEPTANCE.md (acceptance que puede fallar) |
| Iteration budget / techo duro | ✓ | max_iterations: 5 · change budget |
| Maker ≠ checker: el que escribe no se autocalifica | ✓ | evidencia capturada (ledger parsea artefactos) |
| Estado externalizado a disco | ✓ | QA-LEDGER.json + paquete en el repo |
| Done solo con checker-pass + human sign-off | ✓ | fase 6: para en el merge (human gate) |
| Detección de oscilación / stuck | ✓ | oscillation (fingerprint período-2) |
| Outer loop auto-agendado (timer / routine) | ✗ | deliberadamente no — lo disparás vos |
No solo lo alcanzamos: llegamos a la misma forma por separado, y en integridad de verificación (maker ≠ checker) lo articulamos tan filoso como cualquiera. La única diferencia es que el loop lo dispara una persona, no un cron — y eso es la decisión, no la carencia.
Código descartable para aprender. No SPEC; sí una nota de qué se aprendió. Lo que sobreviva, se especifica después.
Demo que no va a producción. Marcado como tal, aislado, con fecha de muerte.
Incidente en producción: arreglás primero. Pero la evidencia mínima (qué se cambió, cómo se revierte) y la SPEC/ADR retroactivos son obligatorios dentro de 24h. Sin válvula de escape, la gente le hace cargo-cult a los descartables o abandona el método bajo presión.
La capa genérica que hace correr la metodología: Claude Code + Python + git/gh + los skills. Lo específico del stack (JDK/Maven, MSSQL, los linters) es el adapter del proyecto y vive en el CLAUDE.md de cada repo — no en el workbench.
| Componente | Para qué | Mínimo |
|---|---|---|
| Claude Code | el agente / orquestador | cuenta Pro / Max / Team / Enterprise / Console |
| Python 3.8+ | corre qa_ledger.py (stdlib pura) | python3 en PATH |
| git | versionado | 2.x con user.name/email |
| gh | crear repo / abrir PR | opcional, recomendado |
| skills del kit | discovery, adr-refine, dev-loop, sys-doc | en ~/.claude/skills/ |
| skills de QA | code-review, judgment-day, improve | tus skills globales (el dev-loop los orquesta, no los trae) |
# Claude Code (native installer — no requiere Node, se auto-actualiza) curl -fsSL https://claude.ai/install.sh | bash # macOS/Linux/WSL irm https://claude.ai/install.ps1 | iex # Windows PowerShell claude # login OAuth # Skills del kit (global) cp -r dev-loop-kit/.claude/skills/* ~/.claude/skills/ claude --version && claude doctor # verificar
En Windows, WSL2 es el camino recomendado (instalás y corrés claude dentro de WSL). Para headless/servidor: export ANTHROPIC_API_KEY=...
Protocolo estable del repo: comandos, no-go zones, DoD, cómo registrar evidencia. Lo permanente vive acá; lo puntual en SPEC/ADR.
discovery, adr-refine, dev-loop, sys-doc en .claude/skills/. Invocables, versionables, compartibles con el equipo.
Paralelizan las tools de QA (review, security, mejoras) sin ensuciar el contexto principal.
Corren gates solos: tests post-edit, lint pre-commit. La evidencia se captura por ejecución, no se narra.
Montás varios repos en una sesión para QA de integración/contratos (tu caso TipreSuite).
Seguís y manejás la sesión desde el celular mientras corre el loop. Sumá plan mode, settings.local.json para permisos, y ccusage para monitorear uso.
Reglas permanentes que Claude Code lee en cada sesión. Lo puntual de cada cambio vive en SPEC/ADR/ACCEPTANCE, no acá. (Si usás otros agentes, copiá este archivo como AGENTS.md.)
/discovery o /adr-refine).// ADR: <slug>.Antes de modificar cualquier .md trackeado (CLAUDE.md, V2_DELTA, V21_*, docs/), pedí la versión actual del repo primero. Esos archivos llevan progreso real (checkboxes, notas); nunca los regeneres desde cero.
El gateway de CAE para ARCA (Java 21, Spring Boot 4, React, MSSQL), de la idea al PR, todo en Claude Code:
claude code · sesión única $ claude > /discovery grilla 1×1, propone entidades/endpoints, vos decidís 3 cosas ✓ CONTEXT.md · DOMAIN-MODEL.md · SPEC-001 · ADR-001/2/3 ✓ ACCEPTANCE.md · RISKS.md · HANDOFF.md > /dev-loop plan → coverage gate → build → QA loop (sub-agentes) → integration CONVERGED · PR abierto. Paro en el merge. > !python3 .claude/skills/dev-loop/qa_ledger.py readiness --acceptance ACCEPTANCE.md READINESS: 88/100 — RELEASE CANDIDATE > /sys-doc # deck de dos vistas desde el ledger # (vos) revisás el PR y mergeás — el human gate no se automatiza
La herramienta ejecuta. La metodología gobierna. La evidencia decide. El humano aprueba.