@saulwade/swl-ses 1.6.7 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: swl-claudemd
3
3
  description: Conocimiento operacional para auditar y mantener archivos CLAUDE.md — contrato canónico de secciones (best practices Anthropic, ADR-0016), umbrales de bloat (líneas totales, bullets gigantes, placeholders, @references rotas), reglas de extracción a archivos referenciados con @, y plantillas de inicialización (init-user para ~/.claude/CLAUDE.md, init-project para CLAUDE.md raíz detectando stack). Provee las reglas; el comando /swl:claudemd ejecuta el flujo. Cargar desde ese comando o cuando el hook claudemd-bloat-detector sugiera intervención.
4
- version: "1.0.2"
4
+ version: "1.2.0"
5
5
  herramientasPermitidas: [Read, Write, Edit, Bash, Glob, Grep]
6
6
  exclusiones:
7
7
  - "No cargar para editar reglas globales en ~/.claude/rules/ — usar Edit directo."
@@ -9,6 +9,11 @@ exclusiones:
9
9
  - "No cargar para validar otros archivos (.md de docs, READMEs) — solo CLAUDE.md tiene contrato canónico."
10
10
  - "No cargar para generar el bloque del installer en CLAUDE.md de proyectos destino — eso lo hace scripts/lib/transformadores/claude.js."
11
11
  evolvable: true
12
+ evolved: true
13
+ evolved-from: "1.1.0"
14
+ evolved-at: "2026-05-22"
15
+ evolved-by: "aprender"
16
+ evolved-note: "Dimensión 8 — detección de duplicación de reglas globales (catálogo declarativo en scripts/lib/reglas-globales-conocidas.json). Refactor propone reemplazo canónico. Hook claudemd-duplicacion-detector.js complementa la capa async. Aplica regla nueva reglas/sin-duplicacion-reglas-globales.md (v1.7.0)."
12
17
  ---
13
18
 
14
19
  # Habilidad: Tratamiento profesional de CLAUDE.md
@@ -58,7 +63,7 @@ node scripts/auditar-claudemd.js --json # para parsing
58
63
  node scripts/auditar-claudemd.js --strict # exit 1 si WARN
59
64
  ```
60
65
 
61
- El auditor verifica seis dimensiones:
66
+ El auditor verifica ocho dimensiones:
62
67
 
63
68
  | Dimensión | Regla | Severidad |
64
69
  |---|---|---|
@@ -68,6 +73,8 @@ El auditor verifica seis dimensiones:
68
73
  | Secciones canónicas | Stack, Comandos, Code style, Conventions presentes | WARN |
69
74
  | @references | Archivos >80 líneas usan al menos un `@docs/...md` | WARN |
70
75
  | Placeholders | `[TBD]`, `[TODO]`, `[COMPLETAR]` | ERROR |
76
+ | Karpathy reference | Project-level >50 LOC menciona "Karpathy", los 4 principios, o `prevencion-sobreingenieria` | WARN |
77
+ | Duplicación reglas globales | Bloque inline parafrasea regla de `~/.claude/rules/` ya cargada globalmente (catálogo en `scripts/lib/reglas-globales-conocidas.json`) | WARN |
71
78
 
72
79
  Veredicto final: ERROR → WARN → OK (el más severo gana).
73
80
 
@@ -168,6 +175,9 @@ Genera `./CLAUDE.md` raíz del proyecto detectando stack actual.
168
175
  2. Ejecutar `detectarStackDetallado(process.cwd())` (de
169
176
  `scripts/lib/detectar-stack-detallado.js`).
170
177
  3. Generar archivo con secciones pobladas:
178
+ - **Reglas obligatorias**: `@reglas/usar-sistema-swl.md`
179
+ - **Reglas de máxima prioridad** con sub-sección **Cuatro principios de
180
+ implementación (Karpathy)** — bloque exacto definido abajo
171
181
  - **Stack**: lenguaje + framework + ORM + package manager detectados
172
182
  - **Comandos**: npm scripts detectados o comandos típicos por lenguaje
173
183
  - **Code style**: placeholders explícitos (`<!-- pendiente: definir convención de X -->`)
@@ -177,6 +187,218 @@ Genera `./CLAUDE.md` raíz del proyecto detectando stack actual.
177
187
  4. Imprimir mensaje con próximo paso: "ejecuta `/swl:claudemd audit`
178
188
  para verificar".
179
189
 
190
+ ### Bloque obligatorio Karpathy en init-project
191
+
192
+ Toda generación nueva incluye esta sub-sección literal en "Reglas de
193
+ máxima prioridad":
194
+
195
+ ```markdown
196
+ ### Cuatro principios de implementación (Karpathy)
197
+ Antes de implementar, refactorizar o corregir bugs: (1) **pensar antes de codificar** (no asumir en silencio), (2) **simplicidad primero** (sin abstracciones especulativas), (3) **cambios quirúrgicos** (leer archivo completo antes de editar, no refactor de oportunidad), (4) **ejecución orientada a metas** (criterios verificables, test que reproduce bugs antes del fix). Detalle + 9 ejemplos MAL→BIEN: `Skill("prevencion-sobreingenieria")` + `recursos/EXAMPLES.md`.
198
+ ```
199
+
200
+ Justificación: el skill `prevencion-sobreingenieria` y su `recursos/EXAMPLES.md`
201
+ se distribuyen con cada instalación SWL, así que la referencia siempre resuelve.
202
+ La sub-sección compacta (5 líneas) ataca los gaps cognitivos más frecuentes
203
+ de cualquier proyecto sin agregar opinión específica.
204
+
205
+ ### Check Karpathy en audit
206
+
207
+ `scripts/auditar-claudemd.js` debe verificar (search regex case-insensitive):
208
+
209
+ - `/karpathy/i`
210
+ - `/cuatro principios/i` o `/4 principios/i`
211
+ - `/prevencion-sobreingenieria/`
212
+ - `/Skill\(["'`]prevencion-sobreingenieria["'`]\)/`
213
+
214
+ Si NO encuentra ninguna AND el archivo tiene >50 LOC AND es project-level
215
+ (no `~/.claude/CLAUDE.md`): emitir hallazgo WARN con mensaje:
216
+
217
+ ```
218
+ CLAUDE.md no menciona los cuatro principios Karpathy ni el skill
219
+ prevencion-sobreingenieria. Considerar agregar la sub-sección compacta
220
+ (ver /swl:claudemd init-project § Bloque obligatorio Karpathy).
221
+ ```
222
+
223
+ Esta dimensión es WARN, no ERROR — guía sin imponer. CLAUDE.md user-level
224
+ (`~/.claude/`) NO se evalúa contra este check.
225
+
226
+ ---
227
+
228
+ ## Interacción con /swl:aprender (contrato cruzado)
229
+
230
+ `/swl:aprender` y `/swl:claudemd` operan sobre el mismo archivo desde
231
+ ángulos opuestos: aprender **muta**, claudemd **prescribe contrato**.
232
+ Sin coordinación explícita, una sesión de aprender puede romper el
233
+ contrato silenciosamente.
234
+
235
+ ### El gap arquitectural que esta interacción cierra
236
+
237
+ `/swl:aprender` Paso 6 Tipo A agrega reglas a `CLAUDE.md` del proyecto.
238
+ El hook `claudemd-bloat-detector.js` (PostToolUse, async, no bloqueante)
239
+ emite nudge tras Write/Edit/MultiEdit sobre CLAUDE.md, pero **el nudge
240
+ llega después** del comando de aprender. Resultado: aprender termina,
241
+ reporta éxito al usuario, y solo después aparece el nudge — con el
242
+ commit ya hecho.
243
+
244
+ Origen detectado: sesión 2026-05-22 al evaluar el flujo SIGAF→swl-ses.
245
+ CLAUDE.md SIGAF recibió ~25 líneas inline de "Triangulación schema
246
+ cross-stack" sin validación post-mutación → archivo probablemente
247
+ superó el umbral de 200 LOC sin warning consciente.
248
+
249
+ ### Contrato canónico de interacción
250
+
251
+ Para cualquier comando SWL que escriba a CLAUDE.md del proyecto
252
+ (`/swl:aprender`, `/swl:adoptar-proyecto`, `/swl:nuevo-proyecto`,
253
+ `/swl:claudemd init-project`, futuros comandos similares):
254
+
255
+ 1. **Antes de escribir**: opcional, pero recomendado — leer el tamaño
256
+ actual del archivo y estimar el delta.
257
+ 2. **Después de escribir**: OBLIGATORIO ejecutar el auditor síncrono:
258
+
259
+ ```bash
260
+ node scripts/auditar-claudemd.js --json
261
+ # o fallback:
262
+ npx -y @saulwade/swl-ses@latest audit-claudemd --json
263
+ ```
264
+
265
+ 3. **Evaluar veredicto**:
266
+ - `OK` → continuar
267
+ - `WARN tamano-total` → proponer condensar o extraer a `@docs/lessons-<tema>.md`
268
+ - `WARN bullet-gigante` → proponer condensar a tabla/lista jerárquica
269
+ - `WARN secciones-canonicas` / `WARN sin-at-references` / `WARN karpathy-reference` → reportar al usuario, permitir continuar
270
+ - `ERROR placeholders` → **DETENER** y revertir
271
+
272
+ 4. **Re-ejecutar el auditor** tras la corrección hasta veredicto OK o
273
+ WARN aceptable.
274
+
275
+ ### Doble red de seguridad
276
+
277
+ El sistema tiene dos capas de protección complementarias:
278
+
279
+ | Capa | Mecanismo | Cuándo actúa | Bloqueo |
280
+ |------|-----------|--------------|---------|
281
+ | Síncrona | Paso 6.5 de `/swl:aprender` (y equivalente en otros comandos) | Justo después del Write/Edit, antes del reporte final | Bloquea pasos posteriores hasta resolver |
282
+ | Asíncrona | Hook `claudemd-bloat-detector.js` (PostToolUse) | Tras cualquier Write/Edit/MultiEdit a CLAUDE.md (incluso fuera de comandos SWL) | No bloquea — emite nudge a `.planning/evolucion/nudges.jsonl` |
283
+
284
+ La capa síncrona es proactiva (detiene el comando antes de reportar
285
+ éxito). La asíncrona es retroactiva (cubre escrituras desde fuera de
286
+ comandos SWL, ej. edición manual).
287
+
288
+ ### Por qué NO se duplica al hook
289
+
290
+ El hook async existente cubre el caso de escrituras desde **cualquier
291
+ fuente** (edición manual del usuario, otros comandos, scripts externos).
292
+ Es la red de seguridad universal. La validación síncrona en aprender es
293
+ específica para el flujo del comando — donde el agente puede actuar
294
+ sobre el WARN antes de continuar.
295
+
296
+ NO crear un hook nuevo dedicado a aprender — duplicaría el rol del
297
+ existente. La invocación síncrona en el Paso 6.5 es suficiente.
298
+
299
+ ### Reglas duras
300
+
301
+ - `/swl:aprender` Paso 6.5 es OBLIGATORIO si se aplicó Tipo A.
302
+ - `/swl:adoptar-proyecto` Paso 8 debe ejecutar el auditor tras
303
+ generar/modificar CLAUDE.md.
304
+ - `/swl:nuevo-proyecto` Paso 6 debe ejecutar el auditor tras generar
305
+ CLAUDE.md inicial.
306
+ - `/swl:claudemd init-project` debe ejecutar el auditor sobre el
307
+ archivo recién generado.
308
+
309
+ Cualquier comando futuro que escriba a CLAUDE.md DEBE seguir este
310
+ contrato.
311
+
312
+ ---
313
+
314
+ ---
315
+
316
+ ## Detección de duplicación de reglas globales (dimensión 8)
317
+
318
+ ### Por qué existe
319
+
320
+ Las reglas en `~/.claude/rules/` se cargan automáticamente en cada
321
+ sesión SWL. Si un proyecto duplica inline el contenido de esas reglas
322
+ en su `CLAUDE.md`, ocurren tres patologías:
323
+
324
+ 1. **Bloat acumulativo**: 7-15 líneas por regla duplicada × N proyectos
325
+ = inflación silenciosa que rompe el umbral de 200 LOC.
326
+ 2. **Drift al actualizar la global**: si la regla global cambia, las
327
+ copias en cada CLAUDE.md quedan obsoletas sin alerta.
328
+ 3. **Erosión del contrato canónico**: cada CLAUDE.md re-deriva el
329
+ principio con palabras propias, generando 4 paráfrasis distintas
330
+ del mismo contenido.
331
+
332
+ La regla `reglas/sin-duplicacion-reglas-globales.md` (v1.7.0) prohíbe
333
+ esta duplicación. Esta dimensión del auditor la detecta.
334
+
335
+ ### Catálogo declarativo
336
+
337
+ `scripts/lib/reglas-globales-conocidas.json` lista las reglas globales
338
+ conocidas con sus patrones de detección. Estructura por entrada:
339
+
340
+ ```json
341
+ {
342
+ "id": "idioma-espanol-mexico",
343
+ "regla_global": "brevedad-output.md",
344
+ "seccion_canonica": "Idioma obligatorio: español de México",
345
+ "referencia_canonica": "@~/.claude/rules/brevedad-output.md § Idioma obligatorio",
346
+ "patrones": ["\\bespañol\\s+de\\s+M[ée]xico\\b", "..."],
347
+ "min_matches": 2,
348
+ "remediacion_sugerida": "Eliminar el bloque local..."
349
+ }
350
+ ```
351
+
352
+ Reglas incluidas en v1.7.0:
353
+
354
+ - `idioma-espanol-mexico` (brevedad-output.md § Idioma)
355
+ - `brevedad-sin-aiisms` (brevedad-output.md § Brevedad)
356
+ - `git-sin-coautores` (git-coauthor.md)
357
+ - `arreglar-al-detectar` (arreglar-al-detectar.md)
358
+ - `debatir-antes-de-aceptar` (debatir-antes-de-aceptar.md)
359
+ - `usar-context7` (usar-context7.md)
360
+
361
+ ### Cuándo NO se evalúa
362
+
363
+ - **User-level** (`~/.claude/CLAUDE.md`): ahí sí pueden declararse
364
+ preferencias personales que parafrasean reglas globales. La opción
365
+ `esUserLevel: true` skipea la evaluación.
366
+ - **Archivos < 20 LOC**: CLAUDE.md mínimos no acumulan duplicaciones
367
+ con suficiente densidad para evaluar.
368
+
369
+ ### Capa async — hook
370
+
371
+ `hooks/claudemd-duplicacion-detector.js` (PostToolUse, no bloquea)
372
+ ejecuta el detector tras cualquier Write/Edit a CLAUDE.md y emite
373
+ nudge a `.planning/evolucion/nudges.jsonl` con `kind:
374
+ claudemd-duplicacion-reglas`. Opt-out: `SWL_CLAUDEMD_DUPLICACION=0`.
375
+
376
+ ### Cómo refactorizar duplicaciones detectadas
377
+
378
+ Tres opciones para cada hallazgo:
379
+
380
+ 1. **Eliminar** (default recomendado): el bloque solo repite la regla
381
+ global, eliminarlo no pierde información.
382
+ 2. **Convertir a matiz local** (≤3 líneas): si el bloque agrega valor
383
+ local genuino, reescribirlo corto referenciando la regla global:
384
+ ```markdown
385
+ Convenciones locales: identificadores técnicos en inglés (rutas,
386
+ comandos). Ver @~/.claude/rules/brevedad-output.md.
387
+ ```
388
+ 3. **Documentar override explícito** (raro): si el proyecto contradice
389
+ la regla global por requerimiento documentable:
390
+ ```markdown
391
+ Override de @~/.claude/rules/brevedad-output.md § Brevedad: este
392
+ proyecto exige docstrings extendidos por compliance regulatorio.
393
+ ```
394
+
395
+ ### Anti-patrón: "lo dejo por claridad"
396
+
397
+ La regla global YA es visible — se carga automáticamente. Duplicarla
398
+ no aumenta su prioridad ni su claridad; solo crea deuda. Si el WARN
399
+ del auditor incomoda, la respuesta correcta es **resolver la
400
+ duplicación**, no aceptar el WARN.
401
+
180
402
  ---
181
403
 
182
404
  ## Gotchas / Errores comunes no obvios
@@ -0,0 +1,170 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * Hook: claudemd-duplicacion-detector.js
6
+ * Tipo: PostToolUse (aplica a: Write, Edit, MultiEdit)
7
+ *
8
+ * Detecta duplicación de reglas globales (`~/.claude/rules/`) inline en
9
+ * `CLAUDE.md` de proyecto recién modificados. Consume el detector
10
+ * `scripts/lib/detector-reglas-duplicadas.js` que lee el catálogo
11
+ * declarativo `scripts/lib/reglas-globales-conocidas.json`.
12
+ *
13
+ * Aplica la regla `reglas/sin-duplicacion-reglas-globales.md`:
14
+ * el `CLAUDE.md` del proyecto NO debe duplicar reglas que ya viven en
15
+ * `~/.claude/rules/`. La regla global es fuente de verdad; el proyecto
16
+ * referencia, no duplica.
17
+ *
18
+ * Opt-out: SWL_CLAUDEMD_DUPLICACION=0 desactiva completamente el hook.
19
+ *
20
+ * Comportamiento:
21
+ * - Nunca bloquea operaciones (exit code 0 siempre)
22
+ * - Solo emite nudge cuando hay duplicaciones detectadas
23
+ * - Solo se dispara con archivos cuyo basename sea exactamente CLAUDE.md
24
+ * - Respeta exclusiones: temp/, node_modules/, respositorios-git/
25
+ * - NO evalúa user-level (~/.claude/CLAUDE.md) — ahí sí pueden
26
+ * declararse preferencias personales
27
+ *
28
+ * Formato del nudge:
29
+ * {
30
+ * id: string,
31
+ * kind: "claudemd-duplicacion-reglas",
32
+ * target: "documentador-swl",
33
+ * source: "hooks/claudemd-duplicacion-detector.js",
34
+ * message: "...",
35
+ * data: { archivo, duplicaciones: [...] },
36
+ * ts: ISO,
37
+ * accionado: false
38
+ * }
39
+ */
40
+
41
+ const fs = require('fs');
42
+ const path = require('path');
43
+ const os = require('os');
44
+ const crypto = require('crypto');
45
+
46
+ // ─── Opt-out global ───────────────────────────────────────────────────────
47
+ if (process.env.SWL_CLAUDEMD_DUPLICACION === '0') {
48
+ process.exit(0);
49
+ }
50
+
51
+ let hookInput = '';
52
+ try {
53
+ hookInput = fs.readFileSync(0, 'utf-8');
54
+ } catch (_) {
55
+ process.exit(0);
56
+ }
57
+
58
+ let evento;
59
+ try {
60
+ evento = JSON.parse(hookInput);
61
+ } catch (_) {
62
+ process.exit(0);
63
+ }
64
+
65
+ const toolName = evento?.tool_name;
66
+ const toolInput = evento?.tool_input;
67
+
68
+ if (!toolName || !['Write', 'Edit', 'MultiEdit'].includes(toolName)) {
69
+ process.exit(0);
70
+ }
71
+
72
+ const filePath = toolInput?.file_path;
73
+ if (!filePath) {
74
+ process.exit(0);
75
+ }
76
+
77
+ // Solo CLAUDE.md (basename exacto, case-sensitive)
78
+ const basename = path.basename(filePath);
79
+ if (basename !== 'CLAUDE.md') {
80
+ process.exit(0);
81
+ }
82
+
83
+ const pathNormalized = filePath.replace(/\\/g, '/');
84
+ const RUTAS_EXCLUIDAS = [
85
+ '/temp/',
86
+ '/node_modules/',
87
+ '/respositorios-git/',
88
+ '/.planning/',
89
+ ];
90
+ if (RUTAS_EXCLUIDAS.some((excluida) => pathNormalized.includes(excluida))) {
91
+ process.exit(0);
92
+ }
93
+
94
+ // User-level: no evaluar (puede declarar preferencias personales)
95
+ const homeClaudeDir = path.resolve(path.join(os.homedir(), '.claude'));
96
+ const rutaAbs = path.resolve(filePath);
97
+ const esUserLevel = rutaAbs.startsWith(homeClaudeDir + path.sep) || rutaAbs === path.join(homeClaudeDir, 'CLAUDE.md');
98
+
99
+ // El archivo debe existir
100
+ if (!fs.existsSync(filePath)) {
101
+ process.exit(0);
102
+ }
103
+
104
+ // ─── Cargar detector ──────────────────────────────────────────────────────
105
+ const CWD = process.cwd();
106
+ const detectorPath = path.join(CWD, 'scripts', 'lib', 'detector-reglas-duplicadas.js');
107
+ if (!fs.existsSync(detectorPath)) {
108
+ // No hay detector instalado en este destino; salir silenciosamente
109
+ process.exit(0);
110
+ }
111
+
112
+ let resultado;
113
+ try {
114
+ const { detectarDuplicaciones } = require(detectorPath);
115
+ const contenido = fs.readFileSync(filePath, 'utf8');
116
+ resultado = detectarDuplicaciones(contenido, null, { esUserLevel });
117
+ } catch (_) {
118
+ // Cualquier error del detector: salir silenciosamente
119
+ process.exit(0);
120
+ }
121
+
122
+ // Solo emitir nudge si hay duplicaciones detectadas
123
+ if (!resultado || !resultado.evaluado || resultado.duplicaciones.length === 0) {
124
+ process.exit(0);
125
+ }
126
+
127
+ // ─── Construir nudge ──────────────────────────────────────────────────────
128
+ const rutaRelativa = path.relative(CWD, filePath).replace(/\\/g, '/');
129
+ const topDuplicaciones = resultado.duplicaciones
130
+ .slice(0, 5)
131
+ .map((d) => ` - [${d.severidad}] ${d.id} (regla global: ${d.regla_global}, línea ~${d.linea_aproximada})`)
132
+ .join('\n');
133
+
134
+ const nudge = {
135
+ id: crypto.randomBytes(8).toString('hex'),
136
+ kind: 'claudemd-duplicacion-reglas',
137
+ target: 'documentador-swl',
138
+ source: 'hooks/claudemd-duplicacion-detector.js',
139
+ message:
140
+ `[claudemd-dup] ${rutaRelativa} duplica ${resultado.duplicaciones.length} regla(s) global(es):\n` +
141
+ topDuplicaciones + '\n' +
142
+ ` Ejecutar \`/swl:claudemd audit\` para detalle, ` +
143
+ `\`/swl:claudemd refactor\` para sugerencias de reemplazo.\n` +
144
+ ` Ver regla: \`reglas/sin-duplicacion-reglas-globales.md\`.`,
145
+ data: {
146
+ archivo: rutaRelativa,
147
+ total_evaluadas: resultado.total_reglas_evaluadas,
148
+ detectadas: resultado.duplicaciones.length,
149
+ ids: resultado.duplicaciones.map((d) => d.id),
150
+ reglas_globales: [...new Set(resultado.duplicaciones.map((d) => d.regla_global))],
151
+ },
152
+ ts: new Date().toISOString(),
153
+ accionado: false,
154
+ accionado_ts: null,
155
+ accionado_por: null,
156
+ };
157
+
158
+ // ─── Persistir a nudges.jsonl ─────────────────────────────────────────────
159
+ try {
160
+ const nudgesPath = path.join(CWD, '.planning', 'evolucion', 'nudges.jsonl');
161
+ const nudgesDir = path.dirname(nudgesPath);
162
+ if (!fs.existsSync(nudgesDir)) {
163
+ fs.mkdirSync(nudgesDir, { recursive: true });
164
+ }
165
+ fs.appendFileSync(nudgesPath, JSON.stringify(nudge) + '\n', 'utf-8');
166
+ } catch (_) {
167
+ // No fallar el hook por error de escritura
168
+ }
169
+
170
+ process.exit(0);
@@ -356,6 +356,15 @@
356
356
  "maxConsecutiveFailures": 5,
357
357
  "degradeOnFailure": "skip"
358
358
  },
359
+ "claudemd-duplicacion-detector.js": {
360
+ "event": "PostToolUse",
361
+ "matcher": "Write|Edit|MultiEdit",
362
+ "description": "Detecta duplicación de reglas globales (~/.claude/rules/) inline en CLAUDE.md de proyecto. Consume scripts/lib/detector-reglas-duplicadas.js + catálogo scripts/lib/reglas-globales-conocidas.json. Aplica regla reglas/sin-duplicacion-reglas-globales.md. Emite nudge a .planning/evolucion/nudges.jsonl si hay duplicaciones detectadas. No bloquea — kind: claudemd-duplicacion-reglas. Excluye temp/, node_modules/, respositorios-git/, .planning/, ~/.claude/ (user-level). Opt-out: SWL_CLAUDEMD_DUPLICACION=0.",
363
+ "blocking": false,
364
+ "async": true,
365
+ "maxConsecutiveFailures": 5,
366
+ "degradeOnFailure": "skip"
367
+ },
359
368
  "validar-intent-spec.js": {
360
369
  "event": "PostToolUse",
361
370
  "matcher": "Write|Edit|MultiEdit",
@@ -905,7 +905,9 @@
905
905
  "reglas/registro-componentes-nuevos.md",
906
906
  "reglas/auditorias-documentales-estructurales.md",
907
907
  "reglas/intent-engineering.md",
908
- "reglas/tests-cleanup.md"
908
+ "reglas/tests-cleanup.md",
909
+ "reglas/verificar-citas-temporales.md",
910
+ "reglas/sin-duplicacion-reglas-globales.md"
909
911
  ],
910
912
  "targets": [
911
913
  "claude",
@@ -1024,6 +1026,7 @@
1024
1026
  "hooks/inbox-aviso.js",
1025
1027
  "hooks/aiisms-detector.js",
1026
1028
  "hooks/claudemd-bloat-detector.js",
1029
+ "hooks/claudemd-duplicacion-detector.js",
1027
1030
  "hooks/validar-intent-spec.js",
1028
1031
  "hooks/sugerir-regenerar-inventario.js",
1029
1032
  "hooks/sugerir-contribuir.js",
@@ -1219,6 +1222,8 @@
1219
1222
  "tipo": "scripts",
1220
1223
  "archivos": [
1221
1224
  "scripts/auditar-claudemd.js",
1225
+ "scripts/lib/detector-reglas-duplicadas.js",
1226
+ "scripts/lib/reglas-globales-conocidas.json",
1222
1227
  "docs/variables-entorno.md"
1223
1228
  ],
1224
1229
  "targets": [
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "lockfileVersion": 1,
3
- "generatedAt": "2026-05-21T20:46:43.799Z",
3
+ "generatedAt": "2026-05-22T23:28:47.439Z",
4
4
  "skillsCount": 177,
5
- "lockHash": "sha256:f87e22a97a86a4abe7f1da215dc894433c3c8c9dfe9434e53d5a70e5b4912406",
5
+ "lockHash": "sha256:d0306679d924ecbbd0071f532df9f2cfb499817eb42b0bb5e6e5ebcdacb941f2",
6
6
  "skills": [
7
7
  {
8
8
  "nombre": "accesibilidad-a11y",
@@ -889,9 +889,9 @@
889
889
  {
890
890
  "nombre": "prevencion-sobreingenieria",
891
891
  "path": "habilidades/prevencion-sobreingenieria/SKILL.md",
892
- "hash": "sha256:7396e1d8e7c87dd0154e9b34d1eff4124997566ca9a9da63b8a0514680af131e",
893
- "bytes": 16468,
894
- "version": "\"1.1.0\""
892
+ "hash": "sha256:9f6d0d4f5c54e29aff3e5fa66d89c42a0dabfd0a59eefcfbf6715ca085984f3e",
893
+ "bytes": 16812,
894
+ "version": "\"1.2.0\""
895
895
  },
896
896
  {
897
897
  "nombre": "privacy-memoria",
@@ -1099,9 +1099,9 @@
1099
1099
  {
1100
1100
  "nombre": "swl-claudemd",
1101
1101
  "path": "habilidades/swl-claudemd/SKILL.md",
1102
- "hash": "sha256:18cef250bd32a7841db3b6362b9303679bf2851e5e1efe7f3d81f0dd514ec5eb",
1103
- "bytes": 11585,
1104
- "version": "\"1.0.2\""
1102
+ "hash": "sha256:0f5eed29f3fedb3bca8036ae5680901712520b31190ad416700c732b2b5897e4",
1103
+ "bytes": 21518,
1104
+ "version": "\"1.2.0\""
1105
1105
  },
1106
1106
  {
1107
1107
  "nombre": "swl-dashboard",