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
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,25 @@ Formato basado en [Keep a Changelog](https://keepachangelog.com/) y [SemVer](htt

## [No publicado]

## [3.5.0] - 2026-11-03

### Notas de actualización
- `npx -y github:lacasoft/dev-starter-kit#v3.5.0 --update --yes`. Si tu proyecto vino de un `design.md` de system-design-kit ≥ 1.4, vuelve a correr `/project-context <ruta>/design.md` para traer la ficha y los flujos: actualiza solo lo que vino del diseño.

### Added
- **La ficha de responsabilidades del diseño llega al código.** `/project-context` traslada desde un `design.md`:
- la *Ficha de responsabilidades* a *Arquitectura → Responsabilidades y límites*;
- las reglas de límite (qué componente decide qué, y que ningún contexto escribe los datos de otro) a *Reglas de negocio*;
- los *Flujos críticos* a *Testing → Tests de recuperación*: uno por cada paso con efecto desconocido o con recuperación, como lista para `tdd`;
- la tabla *Contextos y propiedad* a *Modelo / dominio*, con un módulo por contexto si el repo todavía no tiene estructura.
- **Baseline §7:** respeta los límites de *Responsabilidades y límites*. Cada regla 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, se dice antes de hacerlo.
- La plantilla de `CLAUDE.project.md` pide las responsabilidades en *Arquitectura*.

### Fixed
- **WSL con Node de Windows:** el instalador fallaba con `EPERM` en `C:\Windows`, porque CMD no acepta la carpeta de WSL y se cambia ahí. Ahora lo detecta antes de escribir nada y explica qué hacer.
- **`project-context` en Pi:** ya no sugiere `claude --add-dir`; en Pi la ruta se lee directo.
- **En Pi, las referencias de una skill podían quedar sin leer.** Una instrucción escrita a media frase se salta: en la prueba con Sonnet, `/skill:project-context` no leyó `desde-design.md` e improvisó el mapeo, sin la ficha y con los tests de recuperación en una línea. Ahora `project-context` y `owasp-review` piden leer su referencia como paso explícito y con la ruta completa. Repetida la prueba, la ficha llegó completa y quedaron 6 tests de recuperación.

## [3.4.0] - 2026-10-30

Completa el soporte para [Pi Agent](https://github.com/earendil-works/pi): reglas por carpeta en monorepos y `/loop-task`. Para Claude Code no cambia nada.
Expand Down
15 changes: 10 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.4.0 # fijar una versión (recomendado)
npx -y github:lacasoft/dev-starter-kit#v3.5.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 @@ -158,12 +158,17 @@ claude --add-dir ../acortador-urls # para que pueda leer la carpeta del dis
> /project-context ../acortador-urls/design.md
```

En Pi Agent (instalado con `--pi`) no hace falta `--add-dir`: `/skill:project-context ../acortador-urls/design.md`.

| Del diseño | Al proyecto |
| --- | --- |
| Requisitos y fuera de alcance | *Visión del producto* (con "Fuera de alcance (v1)") |
| Requisitos no funcionales y escala | *Atributos de calidad* con sus umbrales |
| API y modelo de datos | *Modelo / dominio* y contratos en *Arquitectura* |
| Arquitectura inicial y escenarios de falla | *Arquitectura* (con "Fallas previstas") y tests de regresión en *Testing* |
| Ficha de responsabilidades (system-design-kit ≥ 1.4) | *Arquitectura → Responsabilidades y límites*, y las reglas de límite en *Reglas de negocio*: el agente que programa sabe dónde va cada regla |
| Flujos críticos | *Testing → Tests de recuperación*: uno por cada paso con efecto desconocido o con recuperación, como lista para `tdd` |
| Contextos y propiedad (system-design-kit ≥ 1.5) | *Modelo / dominio*, y un módulo por contexto si el repo todavía no tiene estructura |
| 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* |

Expand Down Expand Up @@ -287,8 +292,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.4.0 --pi # proyecto nuevo
npx -y github:lacasoft/dev-starter-kit#v3.4.0 --update --pi --yes # proyecto que ya usa el kit
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
```

**Requisitos:** Pi 1.4.0 o superior (paquete `@earendil-works/pi-coding-agent`, pide Node.js 22.19+),
Expand Down Expand Up @@ -426,7 +431,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.4.0 --update --yes # por tag
npx -y github:lacasoft/dev-starter-kit#v3.5.0 --update --yes # por tag
npx -y github:lacasoft/dev-starter-kit#<commit> --update --yes # por commit (el SHA del tag)
```

Expand All @@ -448,4 +453,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.4.0`). Instala siempre pineando (`#v3.4.0`): es reproducible y evita la cache de npx.
(`v3.5.0`). Instala siempre pineando (`#v3.5.0`): es reproducible y evita la cache de npx.
33 changes: 28 additions & 5 deletions install.js
Original file line number Diff line number Diff line change
Expand Up @@ -1137,7 +1137,26 @@ function summarizeProject(stacks) {
}

// ---------- main ----------
// ---------- Node de Windows desde WSL ----------
// Con WSL y Node instalado solo en Windows, npx corre en Windows: CMD no acepta la carpeta de WSL
// (\\wsl.localhost\…) y se cambia a C:\Windows, donde el kit se instalaría o fallaría con EPERM.
function windowsSystemDir(platform = process.platform, cwd = CWD, env = process.env) {
if (platform !== "win32") return false;
const sys = path.win32.resolve(env.SystemRoot || env.windir || "C:\\Windows").toLowerCase();
const dir = path.win32.resolve(cwd).toLowerCase();
return dir === sys || dir.startsWith(sys + "\\") || /^\\\\wsl/i.test(env.INIT_CWD || "");
}

async function main() {
if (windowsSystemDir()) {
console.error(`❌ El instalador está corriendo con el Node de Windows en ${CWD}.
Si usas WSL: instala Node dentro de WSL (por ejemplo con nvm), comprueba que
\`command -v node npx\` muestre rutas de Linux y no /mnt/c/…, y vuelve a correrlo.
Si usas Windows: córrelo desde la carpeta de tu proyecto, no desde una carpeta del sistema.`);
closeInput();
process.exitCode = 1;
return;
}
const VERSION = (readJSON(path.join(KIT, "package.json")) || {}).version || "?";
console.log("\n╔════════════════════════════════════════════╗");
console.log(`║ Dev Starter Kit v${VERSION} — instalador `.slice(0, 45) + "║");
Expand Down Expand Up @@ -1359,8 +1378,12 @@ async function main() {
closeInput();
}

main().catch((e) => {
console.error(e);
closeInput();
process.exit(1);
});
module.exports = { windowsSystemDir };

if (require.main === module) {
main().catch((e) => {
console.error(e);
closeInput();
process.exit(1);
});
}
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.4.0",
"version": "3.5.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
1 change: 1 addition & 0 deletions shared/.claude/CLAUDE.base.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +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.
- 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
4 changes: 2 additions & 2 deletions shared/.claude/skills/owasp-review/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ Las listas completas (las 10 categorías con qué buscar, los 17 capítulos de A
Antes de buscar patrones, dibuja el mapa: puntos de entrada (rutas, handlers, webhooks, jobs, CLI, mensajes de cola), fronteras de confianza, datos sensibles que cruzan cada frontera, dependencias nuevas y llamadas salientes (HTTP, shell, LLM, otras herramientas). Sin mapa, el barrido es ruido.

## 3. Barrido por categoría
Recorre A01→A10 sobre la superficie del paso 2 (tabla en `referencia.md`). Para cada sospecha, **traza fuente → sink**: de dónde viene el dato, qué validación o codificación recibe y dónde se usa. Si no puedes trazarlo, es sospecha, no hallazgo.
**Primero lee `.claude/skills/owasp-review/referencia.md`**: su tabla dice qué buscar en cada categoría. Luego recorre A01→A10 sobre la superficie del paso 2. Para cada sospecha, **traza fuente → sink**: de dónde viene el dato, qué validación o codificación recibe y dónde se usa. Si no puedes trazarlo, es sospecha, no hallazgo.

Prioridades que más se escapan:
- **A01**: autorización por objeto en cada acceso por id (no basta estar autenticado); SSRF también vive aquí desde 2025.
- **A03**: dependencias añadidas en el diff (nombre exacto, versión fijada, antigüedad de la versión, scripts de instalación).
- **A10**: qué pasa cuando algo falla. Un `catch` que deja pasar, un check de autorización que concede si lanza excepción, un error que filtra internals.

## 4. ASVS por tipo de cambio
Según lo que toque el cambio, verifica los capítulos correspondientes al nivel elegido (mapa en `referencia.md`): auth → V6/V7/V9/V10, permisos → V8, archivos → V5, API → V4, frontend → V3, configuración → V13, cripto → V11, logs y errores → V16.
Según lo que toque el cambio, verifica los capítulos correspondientes al nivel elegido (mapa en `.claude/skills/owasp-review/referencia.md`): auth → V6/V7/V9/V10, permisos → V8, archivos → V5, API → V4, frontend → V3, configuración → V13, cripto → V11, logs y errores → V16.

## 5. LLM y agentes (si el proyecto los usa)
Si el código llama a un LLM, revisa contra el **OWASP Top 10 for LLM Applications 2026**; si construye agentes, herramientas o servidores MCP, también contra el **Top 10 for Agentic Applications 2026**. Lo mínimo: el texto que el modelo lee es dato no confiable, su salida se valida antes de tocar SQL/shell/HTML/herramientas, y lo irreversible pide confirmación humana.
Expand Down
4 changes: 3 additions & 1 deletion shared/.claude/skills/project-context/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ Las rutas que nombra esta skill (`CLAUDE.project.md`, `docs/adr/`, `.claude/…`
- **Cero secretos**: nombres de variables de entorno sí; valores nunca.

## 0. Si partes de un diseño (design.md)
Si el argumento es una ruta a un `design.md` del **system-design-kit** (front matter con `language` y marcas `<!-- section:<id> -->`), ese documento es la fuente de **lo que el repo no puede decir**: visión, requisitos, escala, decisiones y fallas. La persona ya lo pensó y lo decidió; tu trabajo es trasladarlo sin reescribirlo ni reinterpretarlo. Lee [desde-design.md](desde-design.md) y sigue su mapeo. Lo derivable del repo (stack real, comandos, estructura) sigue saliendo de los pasos 1-3: el diseño no sustituye al código.
Si el argumento es una ruta a un `design.md` del **system-design-kit** (front matter con `language` y marcas `<!-- section:<id> -->`), ese documento es la fuente de **lo que el repo no puede decir**: visión, requisitos, escala, decisiones y fallas. La persona ya lo pensó y lo decidió; tu trabajo es trasladarlo sin reescribirlo ni reinterpretarlo. Lo derivable del repo (stack real, comandos, estructura) sigue saliendo de los pasos 1-3: el diseño no sustituye al código.

**Antes de escribir nada, lee [desde-design.md](desde-design.md)**, que está junto a este archivo (`.claude/skills/project-context/desde-design.md`). Su tabla dice a qué sección de `CLAUDE.project.md` va cada parte del diseño, incluida la ficha de responsabilidades, que se copia tal cual, y los flujos críticos, que se vuelven tests de recuperación. Sin esa tabla, no traslades nada.

## 1. Lee lo que hay
`CLAUDE.project.md` actual (si existe, **actualízalo**, no lo reescribas: conserva lo que escribió el equipo), `README`, manifiestos y lockfiles, configuración de lint/format/tests, `Makefile`/scripts, Dockerfile y compose, workflows de CI, `.env.example`, `docs/adr/`, y la estructura de primer y segundo nivel. Si el argumento nombra un área, profundiza ahí.
Expand Down
7 changes: 6 additions & 1 deletion shared/.claude/skills/project-context/desde-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ reescriba requisitos ni decisiones: el diseño se **traslada**, resumido y con l
`api-data-model`, `architecture`, `decisions`, `failures`, `ai-review`.
- Una sección que solo tiene `_⏳ Pendiente_` / `_⏳ Pending_` está vacía: no hay nada que trasladar.
- Si la ruta está fuera del proyecto, Claude Code pedirá permiso para leerla (o arranca con
`claude --add-dir <carpeta del diseño>`).
`claude --add-dir <carpeta del diseño>`). En Pi Agent no hace falta: la ruta se lee directo
(`/skill:project-context ../<carpeta del diseño>/design.md`).

## Mapeo a CLAUDE.project.md

Expand All @@ -20,9 +21,13 @@ reescriba requisitos ni decisiones: el diseño se **traslada**, resumido y con l
| título + `requirements` (funcionales) | **Visión del producto** | 2-4 líneas: qué es, para quién, los casos de uso principales |
| `out-of-scope` | **Visión del producto** → línea "Fuera de alcance (v1)" | Lista corta. Es lo que más evita que el agente construya de más |
| `api-data-model` (entidades, términos) | **Modelo / dominio** | Glosario de entidades y su clave de acceso |
| `api-data-model` (*Contextos y propiedad*, si existe) | **Modelo / dominio** → "Contextos y propiedad" | La tabla tal cual: contexto, reglas, dueño de los datos, contratos. Si el repo todavía no tiene estructura, en **Estructura del repositorio** sugiere un módulo por contexto, sin imponerlo |
| `api-data-model` (endpoints, eventos) | **Arquitectura** → "Contratos" | Solo los de los casos de uso principales, con idempotencia y paginación si el diseño las fija |
| `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 |
| `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 |
| `requirements` (seguridad, privacidad) | **Seguridad y compliance** | Si el diseño fija el nivel ASVS, úsalo; si no, propónlo y márcalo como pendiente |
| `decisions` | **Decisiones de arquitectura** | Un ADR por decisión (abajo) y aquí solo la línea con el enlace |
Expand Down
4 changes: 3 additions & 1 deletion shared/templates/PROJECT.template.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@
-->

## Arquitectura
<!-- Estilo (capas, hexagonal, DDD), bounded contexts, límites de servicio, flujos principales. -->
<!-- Estilo (capas, hexagonal, DDD), bounded contexts, límites de servicio, flujos principales.
Responsabilidades y límites: por componente o módulo, de qué es responsable, qué no le toca y de qué
estado es dueño. Es lo que dice dónde va cada regla de negocio. -->

## Reglas de negocio (invariantes)
<!-- Las reglas que NUNCA se deben violar. Lo que el agente debe respetar sí o sí.
Expand Down
12 changes: 12 additions & 0 deletions test/install-detect.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,15 @@ test("lo que cuelga de un proyecto detectado no cuenta como otro proyecto", () =
});
assert.equal(r.stack, "mobile/react-native");
});

// ---- Node de Windows desde WSL ----
test("detecta el Node de Windows corriendo desde WSL o en una carpeta del sistema", () => {
const { windowsSystemDir } = require(path.join(__dirname, "..", "install.js"));
const sys = { SystemRoot: "C:\\Windows" };
assert.equal(windowsSystemDir("win32", "C:\\Windows", sys), true, "CMD cayó a C:\\Windows");
assert.equal(windowsSystemDir("win32", "C:\\Windows\\System32", sys), true);
assert.equal(windowsSystemDir("win32", "C:\\Users\\ana\\x", { ...sys, INIT_CWD: "\\\\wsl.localhost\\Ubuntu\\home\\ana\\x" }), true, "npx se lanzó desde WSL");
assert.equal(windowsSystemDir("win32", "C:\\Users\\ana\\proyecto", sys), false, "Windows normal: sigue");
assert.equal(windowsSystemDir("win32", "C:\\WindowsApps\\x", sys), false, "no confunde carpetas con nombre parecido");
assert.equal(windowsSystemDir("linux", "/home/ana/x", {}), false);
});
Loading