Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,22 @@ Formato basado en [Keep a Changelog](https://keepachangelog.com/) y [SemVer](htt

## [No publicado]

## [3.6.0] - 2026-11-03

### Notas de actualización
- `npx -y github:lacasoft/dev-starter-kit#v3.6.0 --update --yes`. Si tu `CLAUDE.project.md` ya tiene *Responsabilidades y límites*, corre `/architecture-tests` (en Pi, `/skill:architecture-tests`) para convertirlos en reglas.

### Added
- **Skill `architecture-tests`: de la intención a la restricción.** Convierte los límites de `CLAUDE.project.md` (*Responsabilidades y límites*, *Contextos y propiedad*, reglas de límite) en reglas del lint o de los tests que fallan si alguien los cruza:
- dependencias entre módulos, interfaz pública (los repositorios y modelos del ORM no salen de su módulo), propiedad de los datos (solo el dueño importa sus modelos) y ciclos;
- con una herramienta libre por stack: dependency-cruiser (MIT) en JavaScript y TypeScript, import-linter (BSD) en Python, Spring Modulith o ArchUnit (Apache-2.0) en Spring, ArchUnitNET (Apache-2.0) en .NET, deptrac (MIT) en PHP y lakos (MIT) para los ciclos en Flutter;
- o, si la persona no quiere dependencias nuevas, con un test del propio proyecto que lee los imports, marcado como más débil.
- Antes de dar una regla por buena, provoca una violación a propósito y comprueba que falla. Si el código ya viola un límite, no lo arregla en el mismo cambio: deja la excepción explícita, con su motivo, y anota la deuda.
- Anota en *Testing → Restricciones de arquitectura* qué límite está automatizado y cuál sigue como intención.
- `/project-context`, desde un `design.md`, deja cada límite en *Restricciones de arquitectura* como "intención: sin automatizar" y propone `architecture-tests`.
- **Baseline §7:** un límite solo está garantizado si una regla lo comprueba; una carpeta o un módulo del framework no aíslan nada. Los overlays de NestJS y Django lo dicen para `@Module` y las apps.
- `ship-gate` comprueba que las restricciones corran en el lint o los tests, y marca **manual** las que siguen como intención. El `reviewer` marca los cambios que cruzan un límite o agregan una excepción sin motivo.

## [3.5.0] - 2026-11-03

### Notas de actualización
Expand Down
19 changes: 12 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Configuración `.claude` unificada para backend, frontend, mobile y blockchain.
│ ├── CLAUDE.base.md # baseline universal (comportamiento, agentes, memoria, seguridad, calidad)
│ ├── settings.json # hooks + permisos + statusLine
│ ├── agents/ # 14 agentes (5 core + 9 especialistas) — ver "Agentes incluidos"
│ ├── skills/ # 19 skills (flujo + contexto + ingeniería + seguridad) — ver "Skills incluidas"
│ ├── skills/ # 20 skills (flujo + contexto + ingeniería + seguridad) — ver "Skills incluidas"
│ ├── commands/ # /swarm, /kit:status
│ ├── helpers/ # claude-imports, claude-permissions, claude-rules, hook-handler, loop, statusline
│ └── templates/ # PROJECT.template.md (definición del proyecto)
Expand All @@ -35,7 +35,7 @@ Dentro de **cualquier proyecto** (nuevo o heredado), sin clonar nada:
```bash
npx -y github:lacasoft/dev-starter-kit # interactivo
npx -y github:lacasoft/dev-starter-kit --yes --all # desatendido (todo)
npx -y github:lacasoft/dev-starter-kit#v3.5.0 # fijar una versión (recomendado)
npx -y github:lacasoft/dev-starter-kit#v3.6.0 # fijar una versión (recomendado)
```

Toma siempre la última versión de `master` (o el tag indicado). Repo **público (MIT)**.
Expand Down Expand Up @@ -125,7 +125,7 @@ Además, el kit instala por stack agentes/skills externos curados (`frontend-dev

**Flujo de trabajo**: `tdd` · `diagnose` · `grill-me` · `handoff` · `swarm-orchestration` · `verification` · `code-review-response` · `git-worktrees` · `loop-task`
**Contexto y memoria**: `project-context` (rellena `CLAUDE.project.md` a partir del repo real) · `adr` (registro de decisiones en `docs/adr/`)
**Ingeniería/entrega**: `ci-cd` · `performance-profiling` · `migration` · `monorepo` · `release` · `ship-gate` · `iac`
**Ingeniería/entrega**: `ci-cd` · `performance-profiling` · `migration` · `monorepo` · `release` · `ship-gate` · `iac` · `architecture-tests` (convierte los límites de `CLAUDE.project.md` en reglas que fallan solas)
**Seguridad**: `owasp-review` (revisión contra OWASP Top 10:2025, ASVS 5.0 y CWE; LLM y agentes 2026)

Las de ingeniería se destilaron (en español, a nuestra profundidad) del catálogo MIT
Expand Down Expand Up @@ -172,6 +172,11 @@ En Pi Agent (instalado con `--pi`) no hace falta `--add-dir`: `/skill:project-co
| Decisiones clave y tradeoffs | **Un ADR por decisión** en `docs/adr/`, con la plantilla de la skill `adr` |
| Supuestos sin confirmar | *Pendiente de confirmar* |

Los límites llegan como **intención**: el diseño los nombra, pero nada los comprueba todavía. La skill
`architecture-tests` los convierte en reglas del lint o de los tests que fallan si alguien los cruza
(dependency-cruiser, import-linter, Spring Modulith o ArchUnit, ArchUnitNET, deptrac; todas libres),
y anota en *Testing → Restricciones de arquitectura* cuál está automatizada y cuál sigue como intención.

Lo que el repo sí sabe (stack real, comandos, estructura) sigue saliendo del repo. El archivo
anota de qué diseño salió y su fecha, así que si el diseño cambia, volver a correrlo actualiza
solo lo que vino de ahí; un ADR aceptado no se edita, se reemplaza por otro.
Expand Down Expand Up @@ -292,8 +297,8 @@ modelos de varios proveedores, también locales. Con `--pi`, el kit añade una c
las mismas skills, reglas y helpers: no hay una segunda copia que mantener.

```bash
npx -y github:lacasoft/dev-starter-kit#v3.5.0 --pi # proyecto nuevo
npx -y github:lacasoft/dev-starter-kit#v3.5.0 --update --pi --yes # proyecto que ya usa el kit
npx -y github:lacasoft/dev-starter-kit#v3.6.0 --pi # proyecto nuevo
npx -y github:lacasoft/dev-starter-kit#v3.6.0 --update --pi --yes # proyecto que ya usa el kit
```

**Requisitos:** Pi 1.4.0 o superior (paquete `@earendil-works/pi-coding-agent`, pide Node.js 22.19+),
Expand Down Expand Up @@ -431,7 +436,7 @@ recibir la copia vieja. La solución buena es la misma que exige la baseline §6
versión** — y de paso hace la instalación reproducible:

```bash
npx -y github:lacasoft/dev-starter-kit#v3.5.0 --update --yes # por tag
npx -y github:lacasoft/dev-starter-kit#v3.6.0 --update --yes # por tag
npx -y github:lacasoft/dev-starter-kit#<commit> --update --yes # por commit (el SHA del tag)
```

Expand All @@ -453,4 +458,4 @@ Repo **público (MIT)** distribuido por `npx github:` → la rama **`master` deb
(dry-run) y en un monorepo multi-stack, en cada PR, más un job que prueba la capa de Pi dentro de Pi 1.4.0. La lista sale de `scripts/stacks.cjs`, que la deriva de `install.js`.
- **Cómo añadir** agentes, skills, stacks o externos: ver [CONTRIBUTING.md](CONTRIBUTING.md).
- **Versionado**: SemVer en `package.json` + `CHANGELOG.md`, con tag anotado por versión
(`v3.5.0`). Instala siempre pineando (`#v3.5.0`): es reproducible y evita la cache de npx.
(`v3.5.0`). Instala siempre pineando (`#v3.6.0`): es reproducible y evita la cache de npx.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@lacasoft/dev-starter-kit",
"version": "3.5.0",
"version": "3.6.0",
"private": true,
"description": "Base .claude coherente (agentes, skills, helpers, orquestación multiagente nativa) instalable en cualquier proyecto lacasoft (backend/frontend/mobile/blockchain).",
"bin": {
Expand Down
2 changes: 1 addition & 1 deletion shared/.claude/CLAUDE.base.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ Esto no es solo documentación: el hook `pre-bash` (`helpers/hook-handler.cjs`)
- Nada de código muerto ni comentado "por si acaso".
- Manejo de errores explícito; nunca tragar excepciones en silencio.
- Tests para la nueva funcionalidad y para cada regresión corregida.
- **Respeta los límites** de *Arquitectura → Responsabilidades y límites* en `CLAUDE.project.md`: cada regla de negocio va en su dueño (no en el controlador, el adaptador ni el job), y ningún módulo escribe el estado de otro. Si una tarea exige cruzar un límite, dilo antes de hacerlo.
- **Respeta los límites** de *Arquitectura → Responsabilidades y límites* en `CLAUDE.project.md`: cada regla de negocio va en su dueño (no en el controlador, el adaptador ni el job), y ningún módulo escribe el estado de otro. Si una tarea exige cruzar un límite, dilo antes de hacerlo. Un límite solo está garantizado si una regla lo comprueba (*Testing → Restricciones de arquitectura*, skill `architecture-tests`): una carpeta o un módulo del framework no aíslan nada.
- TypeScript/tipado **strict**; evita `any` (usa `unknown` + narrowing).
- **Gate de código nuevo** (*clean as you code*): lo que cambia no introduce issues nuevos de lint, tipos ni seguridad; **cobertura ≥ 80 % de las líneas nuevas o modificadas** donde se mida; duplicación nueva ≤ 3 %. La deuda heredada no bloquea el cambio, pero no se amplía.
- En lógica crítica (dinero, permisos, cálculos), la cobertura no basta: **mutation testing** (Stryker, mutmut, PIT) o **property-based testing** demuestran que los tests fallan cuando el código se rompe.
Expand Down
2 changes: 1 addition & 1 deletion shared/.claude/agents/reviewer.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Asertan comportamiento, no implementación. Edge cases cubiertos: inputs vacíos
N+1 (queries dentro de loops). Colecciones grandes paginadas/streamed, no cargadas enteras en memoria. Índices en columnas usadas en `JOIN`/`WHERE`. Trabajo pesado fuera del hilo crítico.

### Diseño
SOLID, DRY con criterio, niveles de abstracción coherentes, dirección de dependencias, acoplamiento/cohesión, diseño de interfaces, extensibilidad. Funciones con complejidad cognitiva > 15 se marcan con su alternativa.
SOLID, DRY con criterio, niveles de abstracción coherentes, dirección de dependencias, acoplamiento/cohesión, diseño de interfaces, extensibilidad. Funciones con complejidad cognitiva > 15 se marcan con su alternativa. Si `CLAUDE.project.md` tiene *Responsabilidades y límites*, marca el cambio que los cruza: una regla de negocio fuera de su dueño, un módulo que escribe el estado de otro, o una excepción nueva en las restricciones de arquitectura sin motivo escrito.

### Gate de código nuevo
El cambio no introduce issues nuevos (lint, tipos, seguridad); cobertura ≥ 80 % de las líneas nuevas o modificadas si el proyecto la mide; duplicación nueva ≤ 3 %. La deuda heredada no bloquea, pero el diff no la amplía. Si el proyecto no mide algo de esto, dilo en vez de suponerlo.
Expand Down
61 changes: 61 additions & 0 deletions shared/.claude/skills/architecture-tests/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
---
name: architecture-tests
description: Úsalo para convertir los límites de CLAUDE.project.md (Responsabilidades y límites, Contextos y propiedad) en reglas que fallen solas en el lint o los tests (quién importa a quién, quién escribe qué datos, qué expone cada módulo, sin ciclos), o cuando alguien dé por aislado un módulo solo porque tiene su carpeta o es un módulo del framework.
---

# Tests de arquitectura: de la intención a la restricción

Las rutas que nombra esta skill (`CLAUDE.project.md`, `.claude/…`) son relativas a la raíz del proyecto, donde está `CLAUDE.md`; no a la carpeta de la skill.

Un límite escrito en `CLAUDE.project.md` es una **intención**: se cumple mientras todos lo recuerdan. Se vuelve **restricción** cuando una regla lo comprueba en cada corrida del lint o de los tests y falla si alguien lo cruza. Las carpetas, los routers y los módulos del framework (módulos de NestJS o de Angular, apps de Django) no impiden ningún import: no des un módulo por aislado solo por eso.

## Qué se puede comprobar

| Límite | Regla | Ejemplo |
|---|---|---|
| Dependencias | A no importa de B, o las capas solo dependen hacia adentro | `solicitudes` no importa nada de `nomina` |
| Interfaz pública | Desde fuera, un módulo solo se usa por su entrada pública. Sus repositorios y modelos del ORM no salen de él | Otros módulos importan `saldos/index.ts`, nunca `saldos/saldo.repository.ts` |
| Propiedad de los datos | Solo el dueño importa el modelo o el repositorio de sus tablas | Solo `saldos` importa `SaldoEntity` |
| Ciclos | Ningún ciclo entre módulos | `solicitudes → aprobaciones → solicitudes` falla |
| Contratos, invariantes y recuperación | No son reglas de dependencias: son tests, y los escribe la skill `tdd` | Aprobar una solicitud no modifica el saldo |

La regla de imports protege la propiedad de los datos en el código. Si el riesgo lo pide (dinero, datos personales, varios servicios sobre la misma base), la protección fuerte está en la base: un esquema y un usuario por módulo, con permisos solo sobre lo suyo. Propónla; no la impongas.

## Herramientas por stack

Todas son libres y no piden cuenta ni clave. Revisa en su documentación lo que trae la versión que instales.

| Stack | Herramienta (licencia) | Qué usar |
|---|---|---|
| NestJS, Express, React, Next.js, Angular, React Native | dependency-cruiser (MIT) | Reglas `forbidden` con `from` y `to`; interfaz pública con `pathNot`; ciclos con `circular: true`. En un monorepo Nx, `@nx/enforce-module-boundaries` (MIT) |
| FastAPI, Django | import-linter (BSD-2-Clause) | Contratos `forbidden`, `protected` (solo una lista de módulos puede importar), `layers`, `independence` y `acyclic_siblings` |
| Spring | Spring Modulith (Apache-2.0) para un monolito modular, o ArchUnit (Apache-2.0) para reglas a la medida | `ApplicationModules.of(App.class).verify()` comprueba la interfaz pública y los ciclos entre módulos. En ArchUnit, `noClasses()…` y `slices().matching(…).should().beFreeOfCycles()` |
| .NET | ArchUnitNET (Apache-2.0) | Reglas de dependencia, y `Slices().Matching(…).Should().BeFreeOfCycles()` |
| PHP | deptrac (MIT) | Capas y las dependencias permitidas entre ellas: todo lo que no se permite, falla |
| Flutter | lakos (MIT) | `--no-cycles-allowed` para los ciclos. Para las demás reglas, el test sin dependencias (abajo) |
| Solidity | No aplica | Los límites entre contratos se protegen con control de acceso y tests de invariantes (Foundry) |

**Sin dependencias nuevas.** Si la persona no quiere agregar una herramienta, o el stack no tiene una, escribe un test con el framework de tests del proyecto que lea los archivos fuente y falle ante un import prohibido. Es más débil: no resuelve alias, reexportaciones ni imports dinámicos. Dilo en la línea de esa restricción.

## Proceso
1. **Lee los límites** en `CLAUDE.project.md`: *Arquitectura → Responsabilidades y límites*, *Modelo / dominio → Contextos y propiedad* y las reglas de límite de *Reglas de negocio*. Si no hay ninguno, no los inventes: propón correr `project-context`, o pregunta cuáles son los módulos y quién es dueño de qué.
2. **Ubica cada módulo en el código.** Si un límite no corresponde a ninguna carpeta o paquete, dilo antes de seguir: primero hay que decidir dónde vive.
3. **Traduce cada límite a una regla**, una por límite, con un mensaje que lo nombre (por ejemplo, "Solo Saldos escribe el saldo; ver CLAUDE.project.md"). Lo que no se pueda expresar como regla queda como intención, con el motivo.
4. **Elige la herramienta** del stack. Agregarla es instalar una dependencia de desarrollo: pide confirmación y sigue la baseline §6.1 (versión exacta, publicada hace 7 días o más y licencia revisada en su archivo LICENSE).
5. **Prueba que cada regla falla.** Introduce a propósito una violación (un import prohibido en un archivo temporal), corre la regla, confirma que falla con su mensaje y deshaz el cambio. Una regla que nunca falló no protege nada, igual que un test que nunca estuvo en rojo.
6. **Hazla correr sola.** Que forme parte del comando de lint o de tests que ya corren la CI, la skill `ship-gate` y el verificador de `loop-task`, no de un comando aparte que nadie recuerda.
7. **Si el código ya viola un límite**, no lo arregles en el mismo cambio. Deja la excepción explícita en la regla, con el archivo y el motivo, y anota la deuda en *Notas / gotchas*. La excepción no se amplía.
8. **Anota el resultado** en `CLAUDE.project.md` → *Testing* → "Restricciones de arquitectura": una línea por límite, con dónde se comprueba o "intención" y el motivo.

```markdown
### Restricciones de arquitectura
- Solo Saldos escribe el saldo → automatizada: `.dependency-cruiser.cjs` (regla `solo-saldos-escribe-saldo`), en `npm run lint`
- Sin ciclos entre módulos → automatizada: `.dependency-cruiser.cjs` (regla `no-circular`), en `npm run lint`
- Aprobaciones no decide el saldo → intención: es comportamiento, no dependencia; lo cubre el test `aprobar-no-modifica-saldo`
```

## Reglas
- No digas que un módulo está "aislado", "desacoplado" o es "independiente" sin una regla que lo compruebe. Si no la hay, di "por convención".
- Las reglas reflejan los límites decididos; no inventes límites nuevos. Si ves uno que falta, propónlo.
- Una excepción sin motivo escrito es un límite borrado.
- En un monorepo, la dirección entre paquetes la dan sus dependencias declaradas (skill `monorepo`); estas reglas cuidan los límites dentro de cada paquete.
1 change: 1 addition & 0 deletions shared/.claude/skills/project-context/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Si partiste de un `design.md`, pregunta solo lo que el diseño no responde. Si n
## 5. Escribe y cierra
- Elimina el comentario de plantilla y las secciones que no aplican; deja las preguntas abiertas en una sección final **Pendiente de confirmar**.
- Si encontraste decisiones de arquitectura importantes sin registrar, propón ADRs (skill `adr`) en vez de narrarlas en este archivo.
- Si trasladaste límites (*Responsabilidades y límites*, *Contextos y propiedad*), quedan como intención: propón la skill `architecture-tests` para convertirlos en reglas que fallen solas.
- Lo que aprendiste del repo que no cabe aquí pero conviene recordar (dónde vive algo, trampas) va a la memoria del agente `researcher`.
- Resume a la persona qué se confirmó, qué se infirió y qué quedó pendiente.

Expand Down
1 change: 1 addition & 0 deletions shared/.claude/skills/project-context/desde-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ reescriba requisitos ni decisiones: el diseño se **traslada**, resumido y con l
| `architecture` | **Arquitectura** | Componentes y flujo principal, síncrono y asíncrono; enlaza el diagrama del diseño en vez de copiarlo |
| `architecture` (*Ficha de responsabilidades*, si existe) | **Arquitectura** → "Responsabilidades y límites" | La tabla tal cual: componente, responsable de, no le toca, estado del que es dueño y ejecución. Son los límites que el código respeta: ahí se ve dónde va cada regla |
| `architecture` y `api-data-model` (dueños) | **Reglas de negocio (invariantes)** | Las de límite, en una línea cada una: qué componente decide qué, y que ningún contexto escribe los datos de otro |
| `architecture` y `api-data-model` (límites) | **Testing** → "Restricciones de arquitectura" | Una línea por límite, marcada "intención: sin automatizar". La skill `architecture-tests` las convierte en reglas que fallan solas y cambia la marca. No digas que un límite está garantizado porque el diseño lo nombra |
| `failures` | **Arquitectura** → "Fallas previstas" y **Testing** | Una línea por escenario (escenario → mitigación). En *Testing*, los que merecen test de regresión |
| `failures` (*Flujos críticos*, si existen) | **Testing** → "Tests de recuperación" | Uno por cada paso con efecto **desconocido** o con recuperación (duplicado, timeout, concurrencia, reinicio): qué se simula y qué evidencia de cierre se comprueba. No los escribas ahora: quedan como lista para la skill `tdd` |
| `requirements` (no funcionales) + `scale` | **Atributos de calidad** | Los umbrales con número (latencia, disponibilidad, consistencia) y el orden de magnitud de carga |
Expand Down
Loading
Loading