ADR-0011: cornerstone-builder — pipeline spec-driven con arquetipos
- Status: Accepted
- Date: 2026-03-26
- Deciders: DeAcero Agentic Team
Context
El template Cornerstone actual scaffoldea proyectos Python genéricos con infraestructura Agentic CI. Pero los proyectos reales de DeAcero siguen patrones recurrentes y bien definidos:
- Servidores MCP — exponen lógica de negocio migrada como herramientas para agentes
- MCP + UI — servidor MCP con interfaz React para usuarios finales
- MCP + API — servidor MCP más una API REST para integración con sistemas externos
- API sola — FastAPI REST sin capa MCP
- SPs migrados — Stored Procedures SQL Server portados a Python + SQLAlchemy
- MCP + UI + API — la combinación completa
Hoy, cada proyecto nuevo requiere:
1. Generar el template base con cookiecutter
2. Configurar manualmente la estructura del proyecto según el patrón
3. Escribir features BDD desde cero o copiarlas de otro proyecto
Además, el pipeline de arqueología produce .feature files verificadas (# status: verified)
que deberían poder usarse directamente como input del scaffold — pero no hay nada que
conecte ese output con la generación del nuevo proyecto.
La oportunidad
Cerrar el pipeline completo:
[Legacy system]
↓
software-archeologist → bdd-writer → characterization-tester → [cornerstone-builder]
↑
[Nueva necesidad]
↓
problem-intake → bdd-writer (features nuevas) ─────────────────────────┘
El cornerstone-builder es el eslabón que falta: toma features verificadas y un arquetipo,
y produce un proyecto completamente scaffoldeado y BDD-first desde el primer commit.
Decision
Crear el directorio builder/ en el repositorio Cornerstone como un segundo template
Cookiecutter dentro del mismo monorepo, accesible vía:
cookiecutter gh:deagentic/cornerstone --directory builder
Arquetipos disponibles
Grupo: Servidor / API
| Arquetipo | Descripción | Stack generado |
|---|---|---|
mcp-only |
Servidor MCP puro — expone lógica de negocio a agentes | FastMCP, pytest-bdd, Docker |
mcp-api |
MCP + REST API — lógica accesible tanto a agentes como a sistemas externos | FastMCP, FastAPI, pytest-bdd, Docker Compose |
mcp-ui |
MCP + interfaz React — lógica con UI para usuarios finales | FastMCP, Next.js/React, shadcn-ui, Docker Compose |
mcp-ui-api |
Combinación completa | FastMCP + FastAPI + React, Docker Compose |
api-only |
REST API sin MCP — integración con sistemas externos sin capa agéntica | FastAPI, pytest, Docker |
Grupo: Datos y Migración
| Arquetipo | Descripción | Stack generado |
|---|---|---|
sql-procedures |
SPs SQL Server portados a Python | SQLAlchemy, pytest-bdd, Alembic, Docker |
etl-pipeline |
Reemplazo de paquetes SSIS o flujos de migración de datos | SQLAlchemy, pandas, pytest, Docker |
cobol-bridge |
Capa adaptadora COBOL → Python (para el pipeline cobol-analyst) |
ctypes/subprocess bridge, pytest-bdd, Docker |
Grupo: Procesamiento Asíncrono
| Arquetipo | Descripción | Stack generado |
|---|---|---|
scheduled-job |
Reemplazo de SQL Server Agent Jobs (RUNS_ON_SCHEDULE en el grafo) |
APScheduler / Celery Beat, pytest, Docker |
worker |
Procesamiento asíncrono en cola — tasks que antes eran SPs ad-hoc | Celery + Redis/RabbitMQ, pytest, Docker |
mcp-worker |
Servidor MCP + worker de cola — para flujos que requieren procesamiento diferido | FastMCP + Celery, pytest-bdd, Docker Compose |
Grupo: Utilitarios
| Arquetipo | Descripción | Stack generado |
|---|---|---|
library |
Librería Python pura — lógica de negocio compartida extraída de múltiples SPs | pyproject.toml, pytest, sin Docker |
cli-tool |
Herramienta de línea de comandos — utilitarios internos, scripts de migración | Typer/Click, pytest, Docker opcional |
report |
Servicio de reportes — reemplazo de SSRS, output PDF/Excel | ReportLab/Jinja2/openpyxl, pytest, Docker |
Input del builder
El cornerstone-builder acepta dos tipos de input:
Path de features verificadas (del pipeline de arqueología o greenfield):
builder/
└── input/
└── features/
├── sp_generar_factura.feature # status: verified
├── sp_aplicar_descuento.feature # status: verified
└── ...
cookiecutter.json ampliado:
{
"project_name": "facturacion-service",
"archetype": ["mcp-api", "mcp-only", "mcp-ui", "mcp-ui-api", "api-only",
"sql-procedures", "etl-pipeline", "cobol-bridge",
"scheduled-job", "worker", "mcp-worker",
"library", "cli-tool", "report"],
"features_path": "input/features/",
"database": ["sqlserver", "postgresql", "none"],
"python_version": "3.11",
"include_ui": false
}
El primer valor de cada lista es el default. Cookiecutter presenta un menú de selección interactivo.
Output del builder
Para el arquetipo mcp-api, el proyecto generado incluye:
facturacion-service/
├── AGENTS.md ← routing directives del proyecto
├── CLAUDE.md ← entry point para Claude Code
├── .agents/skills/ ← skills heredados de Cornerstone
├── docs/
│ └── adr/ ← ADR inicial generado desde las features
├── src/
│ └── facturacion/
│ ├── __init__.py
│ ├── mcp_server.py ← herramientas MCP (stubs desde features)
│ └── api/
│ └── routes.py ← endpoints REST (stubs desde features)
├── tests/
│ ├── features/ ← .feature files copiadas desde input/
│ │ └── *.feature
│ ├── step_defs/ ← stubs de step definitions (pytest-bdd)
│ │ └── conftest.py
│ └── characterization/ ← regression suite del sistema legacy (si aplica)
├── pyproject.toml
├── Dockerfile
├── docker-compose.yml
├── .github/
│ └── workflows/
│ └── ci.yml ← pipeline CI con ADR gate + BDD tests
└── setup/
└── install.sh
Generación de stubs desde features
Para cada .feature verificada, el builder genera automáticamente:
-
MCP tool stub (para arquetipos con MCP):
@mcp.tool() def generar_factura(pedido_id: int, cliente_id: str) -> dict: """ Generada desde: sp_generar_factura.feature (status: verified) Comportamiento verificado: retorna monto total con impuesto incluido TODO: implementar lógica migrada desde sp_generar_factura """ raise NotImplementedError -
API endpoint stub (para arquetipos con API):
@router.post("/facturas") async def create_factura(pedido_id: int, cliente_id: str): """Generada desde sp_generar_factura.feature""" raise NotImplementedError -
Step definition stub (para todos los arquetipos):
@given("un pedido con id {pedido_id} del cliente {cliente_id}") def step_pedido(context, pedido_id, cliente_id): # TODO: setup test data pass @when("se ejecuta generar_factura") def step_execute(context): # TODO: call MCP tool or API endpoint pass @then("el monto total es {expected_monto}") def step_assert(context, expected_monto): assert context.result["monto"] == float(expected_monto)
Los stubs garantizan que el proyecto arranca con tests que fallan de forma significativa (NotImplementedError / pending steps) — no con tests vacíos. El primer sprint consiste en hacer que esos tests pasen.
Skill asociado: cornerstone-builder
Se crea el skill .agents/skills/software/architecture/cornerstone-builder/SKILL.md que:
- Lee las features verificadas del characterization-tester o del bdd-writer (greenfield)
- Solicita al usuario que seleccione un arquetipo
- Ejecuta cookiecutter gh:deagentic/cornerstone --directory builder con los parámetros
- Post-procesa los stubs generados con las firmas correctas inferidas de las features
Flujo completo
═══════════════════════ ARQUEOLOGÍA ════════════════════════════
legacy SQL / DLL / JAR
↓
software-archeologist (mapea el sistema, genera graph)
↓
bdd-writer (features hypothesis)
↓
characterization-tester (features verified / conflict)
↓ (solo verified)
cornerstone-builder ────────────────────────────────────────────┐
│
═══════════════════════ GREENFIELD ═════════════════════════════│
nueva necesidad de negocio │
↓ │
problem-intake (genera Archaeology Brief) │
↓ │
bdd-writer (features nuevas desde brief) │
↓ │
cornerstone-builder ────────────────────────────────────────────┘
↓
proyecto scaffoldeado con:
- stubs MCP / API / SQL
- BDD test harness listo
- CI/CD con ADR gate
- regression suite del legacy (si aplica)
Consecuencias
Positivo
- Cierra el pipeline end-to-end: del legacy o del brief al proyecto nuevo en un comando
- Los proyectos nuevos nacen con tests que fallan significativamente — no con código vacío
- Los features verificadas se convierten en el contrato de paridad del sistema migrado
- Elimina la configuración manual repetitiva entre proyectos
- Estandariza la estructura de todos los proyectos de modernización de DeAcero
Negativo
- Los stubs generados desde features son punto de partida, no implementación completa — el equipo debe completarlos; existe riesgo de que queden como stubs permanentes
- Cookiecutter
--directoryrequiere que el templatebuilder/sea mantenido en paralelo con el template raíz — duplicación de algunos archivos comunes (AGENTS.md base, skills) - La selección del arquetipo es una decisión arquitectónica que debe ir acompañada de un ADR — el builder debe incluir un ADR plantilla pre-llenado para este propósito
- 14 arquetipos representan una superficie de mantenimiento significativa — se recomienda implementar por grupos: Servidor/API primero, luego Datos, luego Procesamiento Asíncrono, finalmente Utilitarios
Dependencias
bdd-writerskill — produce las features de entrada (ambas rutas)characterization-tester(ADR-0012) — produce features verificadas (ruta arqueología)problem-intakeskill (ADR-0009) — genera el brief para la ruta greenfieldstitch-skills(ADR-0008) — para arquetipos con UI, el builder invocastitch-design- Cookiecutter ≥ 2.1 — requerido para
--directoryen monorepos
Alternativas consideradas
Un template Cookiecutter por arquetipo (N repos): Más simple por arquetipo pero
fragmenta el mantenimiento. Cambios en skills comunes, hooks, o CI deben replicarse
en N repos. Descartado — el monorepo con --directory resuelve esto.
Generar el proyecto completamente desde código (sin Cookiecutter): Mayor flexibilidad pero elimina la familiaridad de Cookiecutter y complica el bootstrap para nuevos equipos. Cookiecutter es el estándar establecido en el proyecto. Descartado.
Solo generar el scaffold sin stubs de features: Más simple de implementar pero pierde el valor principal — que el proyecto nazca con su contrato de paridad listo. Descartado.