@saulwade/swl-ses 1.7.2 → 1.7.4
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.
- package/CLAUDE.md +2 -2
- package/README.md +2 -2
- package/habilidades/calidad-anti-patrones-universales/SKILL.md +368 -0
- package/habilidades/estilo-sin-ai-isms/SKILL.md +52 -1
- package/manifiestos/modulos.json +1351 -1350
- package/manifiestos/skills-lock.json +1254 -1247
- package/package.json +2 -2
- package/plugin.json +3 -2
- package/reglas/harness-claude-code.md +39 -0
- package/scripts/lib/pr-analyzer.js +399 -0
package/CLAUDE.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# CLAUDE.md — @saulwade/swl-ses v1.7.
|
|
1
|
+
# CLAUDE.md — @saulwade/swl-ses v1.7.4
|
|
2
2
|
|
|
3
3
|
## Reglas de máxima prioridad (aplican SIEMPRE, sin excepción)
|
|
4
4
|
|
|
@@ -95,7 +95,7 @@ NUNCA asumir, sugerir como hecho consumado, ni escribir en ADRs/manifiestos/CHAN
|
|
|
95
95
|
## Qué es este repositorio
|
|
96
96
|
|
|
97
97
|
Sistema de ingeniería de software auto-evolutivo multi-runtime polyglot (SDLC completo).
|
|
98
|
-
11 lenguajes, 7 runtimes (Claude, OpenClaude, OpenCode, Gemini, Cursor, Codex, Copilot), 61 agentes,
|
|
98
|
+
11 lenguajes, 7 runtimes (Claude, OpenClaude, OpenCode, Gemini, Cursor, Codex, Copilot), 61 agentes, 178 skills, 44 comandos, 71 reglas, 43 hooks.
|
|
99
99
|
|
|
100
100
|
## Estructura del repositorio
|
|
101
101
|
|
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# swl-ses v1.7.
|
|
1
|
+
# swl-ses v1.7.4
|
|
2
2
|
|
|
3
3
|
> El paquete anterior `@saulwadeleon/swl-software-engineering-system` está deprecado. Migrar a `@saulwade/swl-ses` (npmjs.org canónico) o `@saul-wade/swl-ses` (mirror en GitHub Packages) — el CLI `swl-ses` no cambia.
|
|
4
4
|
|
|
@@ -195,7 +195,7 @@ claude
|
|
|
195
195
|
| `mobile` | Android + iOS + React Native/Flutter + UX |
|
|
196
196
|
| `devops` | CI/CD + cloud + observabilidad + releases + seguridad |
|
|
197
197
|
| `polyglot` | Todos los lenguajes: 11 lenguajes + revisores + build resolvers |
|
|
198
|
-
| `completo` | Todo: 61 agentes +
|
|
198
|
+
| `completo` | Todo: 61 agentes + 178 habilidades + 44 comandos + 71 reglas + 43 hooks |
|
|
199
199
|
|
|
200
200
|
### Targets soportados
|
|
201
201
|
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: calidad-anti-patrones-universales
|
|
3
|
+
description: >
|
|
4
|
+
Catálogo de 10 anti-patrones universales de calidad de código, nombrados con
|
|
5
|
+
vocabulario común y ejemplos MAL/BIEN en Python y TypeScript. Cubre auditoría
|
|
6
|
+
de reutilización, proliferación de parámetros, abstracciones con fuga, tipado
|
|
7
|
+
por string, condicionales anidadas, variantes copy-paste, actualizaciones sin
|
|
8
|
+
efecto, race conditions TOCTOU, operaciones demasiado amplias y estado
|
|
9
|
+
redundante. Cargar desde revisor-codigo-swl o revisores especializados cuando
|
|
10
|
+
el código bajo revisión presenta señales (>4 parámetros, magic strings en
|
|
11
|
+
condiciones, if anidadas ≥3 niveles, queries en loops, dos funciones casi
|
|
12
|
+
idénticas, mutaciones de estado sin guard). NO sustituye a los revisores —
|
|
13
|
+
los enriquece con vocabulario nombrado para reportes consistentes.
|
|
14
|
+
version: "1.0.0"
|
|
15
|
+
herramientasPermitidas: [Read, Grep, Glob]
|
|
16
|
+
exclusiones:
|
|
17
|
+
- "No cargar como sustituto de revisor-codigo-swl ni de los revisores especializados — este skill aporta vocabulario y ejemplos, los revisores ejecutan el análisis."
|
|
18
|
+
- "No cargar para code review con foco en seguridad (OWASP, inyección, autenticación) — para eso cargar checklist-seguridad."
|
|
19
|
+
- "No cargar para análisis de rendimiento (queries lentas, profiling) — eso corresponde a rendimiento-swl + performance-baseline."
|
|
20
|
+
- "No cargar para refactor agresivo de código heredado — eso corresponde a legacy-code-rescue."
|
|
21
|
+
evolvable: true
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
# Habilidad: Catálogo de anti-patrones universales de calidad
|
|
25
|
+
|
|
26
|
+
Catálogo de 10 anti-patrones nombrados que aparecen cross-lenguaje. Cada entrada
|
|
27
|
+
incluye señal de detección, ejemplo MAL, ejemplo BIEN y vocabulario para el
|
|
28
|
+
reporte del revisor.
|
|
29
|
+
|
|
30
|
+
## Cuándo cargar
|
|
31
|
+
|
|
32
|
+
Desde `revisor-codigo-swl` o un revisor especializado (`revisor-typescript-swl`,
|
|
33
|
+
`revisor-react-swl`, `revisor-python-swl`, etc.) cuando el código bajo revisión
|
|
34
|
+
muestra al menos una de las señales:
|
|
35
|
+
|
|
36
|
+
- Función con ≥5 parámetros posicionales
|
|
37
|
+
- Condicionales anidadas con ≥3 niveles
|
|
38
|
+
- Magic strings repetidos en condiciones o switches
|
|
39
|
+
- Dos funciones que difieren solo en nombres de campos
|
|
40
|
+
- Acceso a propiedades de un ORM o cliente HTTP desde código de negocio
|
|
41
|
+
- Llamadas a BD dentro de un `for` (loops con `await` en cada iteración)
|
|
42
|
+
- Mutación de estado sin guard previo
|
|
43
|
+
- Función con verbo genérico (`process`, `handle`, `manage`) que afecta múltiples dominios
|
|
44
|
+
|
|
45
|
+
## Cuándo NO cargar
|
|
46
|
+
|
|
47
|
+
- Code review enfocado en seguridad → `checklist-seguridad`
|
|
48
|
+
- Profiling y queries lentas → `rendimiento-swl` + `performance-baseline`
|
|
49
|
+
- Refactor de código heredado → `legacy-code-rescue`
|
|
50
|
+
- Implementación de feature nueva → cargar el skill del stack (`fastapi-experto`, `react-experto`, etc.)
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Los 10 anti-patrones
|
|
55
|
+
|
|
56
|
+
### 1. Auditoría de reutilización (reuse audit)
|
|
57
|
+
|
|
58
|
+
Antes de aceptar código nuevo, buscar utilidades existentes que ya hagan lo mismo.
|
|
59
|
+
|
|
60
|
+
**MAL** — debounce hecho a mano cuando `utils/debounce.ts` ya existe:
|
|
61
|
+
```typescript
|
|
62
|
+
function debounce(fn: Function, ms: number) {
|
|
63
|
+
let timer: ReturnType<typeof setTimeout>;
|
|
64
|
+
return (...args: unknown[]) => {
|
|
65
|
+
clearTimeout(timer);
|
|
66
|
+
timer = setTimeout(() => fn(...args), ms);
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**BIEN** — importar la utilidad del proyecto:
|
|
72
|
+
```typescript
|
|
73
|
+
import { debounce } from '@/utils/debounce';
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Reporte**: "Reuse audit — `<archivo:línea>` reimplementa `<utilidad-existente>`. Importar en su lugar."
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
### 2. Proliferación de parámetros (parameter sprawl)
|
|
81
|
+
|
|
82
|
+
Una función con ≥5 parámetros posicionales no escala. Cada nueva necesidad agrega otro.
|
|
83
|
+
|
|
84
|
+
**MAL**:
|
|
85
|
+
```python
|
|
86
|
+
def crear_usuario(nombre, email, rol, equipo, activo, avatar_url, zona_horaria):
|
|
87
|
+
...
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**BIEN** — objeto de parámetros con defaults:
|
|
91
|
+
```python
|
|
92
|
+
from dataclasses import dataclass
|
|
93
|
+
|
|
94
|
+
@dataclass
|
|
95
|
+
class CrearUsuarioParams:
|
|
96
|
+
nombre: str
|
|
97
|
+
email: str
|
|
98
|
+
rol: Rol = Rol.MIEMBRO
|
|
99
|
+
equipo: str | None = None
|
|
100
|
+
activo: bool = True
|
|
101
|
+
avatar_url: str | None = None
|
|
102
|
+
zona_horaria: str = "America/Mexico_City"
|
|
103
|
+
|
|
104
|
+
def crear_usuario(params: CrearUsuarioParams) -> Usuario:
|
|
105
|
+
...
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**Reporte**: "Parameter sprawl — `<función>` recibe N parámetros. Consolidar en dataclass/interface."
|
|
109
|
+
|
|
110
|
+
Señal adicional: parámetros booleanos mutuamente exclusivos (`activar_x`, `desactivar_y`) → enum o strategy pattern.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
### 3. Abstracciones con fuga (leaky abstractions)
|
|
115
|
+
|
|
116
|
+
Exponer detalles internos obliga al llamador a conocerlos.
|
|
117
|
+
|
|
118
|
+
**MAL** — el caller recibe un objeto ORM:
|
|
119
|
+
```python
|
|
120
|
+
def listar_usuarios():
|
|
121
|
+
return session.query(Usuario).filter(Usuario.activo == True).all()
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**BIEN** — el caller recibe un DTO de dominio:
|
|
125
|
+
```python
|
|
126
|
+
def listar_usuarios_activos() -> list[UsuarioDTO]:
|
|
127
|
+
filas = usuario_repo.find_activos()
|
|
128
|
+
return [UsuarioDTO.from_row(f) for f in filas]
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**Reporte**: "Leaky abstraction — `<función>` retorna objeto ORM/cliente; envolver en DTO."
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
### 4. Tipado por string (stringly-typed)
|
|
136
|
+
|
|
137
|
+
Magic strings esparcidos por el código en lugar de constantes o enums.
|
|
138
|
+
|
|
139
|
+
**MAL**:
|
|
140
|
+
```typescript
|
|
141
|
+
if (usuario.rol === 'admin') { ... }
|
|
142
|
+
if (usuario.rol === 'Admin') { ... } // typo silencioso
|
|
143
|
+
if (pedido.estado === 'pendiente') { ... }
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**BIEN** — enum tipado:
|
|
147
|
+
```typescript
|
|
148
|
+
enum Rol { Admin = 'admin', Miembro = 'miembro' }
|
|
149
|
+
enum EstadoPedido { Pendiente = 'pendiente', Confirmado = 'confirmado' }
|
|
150
|
+
|
|
151
|
+
if (usuario.rol === Rol.Admin) { ... }
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**Reporte**: "Stringly-typed — `<archivo:línea>` compara contra string literal repetido. Extraer enum/constante."
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
### 5. Condicionales anidadas (nested conditionals)
|
|
159
|
+
|
|
160
|
+
`if/else` con ≥3 niveles o cadenas ternarias rompen la lectura lineal.
|
|
161
|
+
|
|
162
|
+
**MAL**:
|
|
163
|
+
```python
|
|
164
|
+
if usuario:
|
|
165
|
+
if usuario.activo:
|
|
166
|
+
if usuario.tiene_permiso("editar"):
|
|
167
|
+
if recurso.disponible:
|
|
168
|
+
return editar(usuario, recurso)
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
**BIEN** — early return con guard clauses:
|
|
172
|
+
```python
|
|
173
|
+
def editar_recurso(usuario, recurso):
|
|
174
|
+
if not usuario or not usuario.activo:
|
|
175
|
+
raise UsuarioInvalidoError
|
|
176
|
+
if not usuario.tiene_permiso("editar"):
|
|
177
|
+
raise PermisoDenegadoError
|
|
178
|
+
if not recurso.disponible:
|
|
179
|
+
raise RecursoNoDisponibleError
|
|
180
|
+
return editar(usuario, recurso)
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
**Reporte**: "Nested conditionals — `<función>` tiene N niveles de anidamiento. Aplicar guard clauses con early return."
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
### 6. Variantes copy-paste (copy-paste variants)
|
|
188
|
+
|
|
189
|
+
Dos bloques de código casi idénticos que solo difieren en nombres de campos o constantes.
|
|
190
|
+
|
|
191
|
+
**MAL**:
|
|
192
|
+
```python
|
|
193
|
+
def calcular_iva(monto):
|
|
194
|
+
return monto * 0.16
|
|
195
|
+
|
|
196
|
+
def calcular_ieps(monto):
|
|
197
|
+
return monto * 0.08
|
|
198
|
+
|
|
199
|
+
def calcular_isr(monto):
|
|
200
|
+
return monto * 0.30
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
**BIEN** — abstracción con tabla de tasas:
|
|
204
|
+
```python
|
|
205
|
+
TASAS = {"iva": 0.16, "ieps": 0.08, "isr": 0.30}
|
|
206
|
+
|
|
207
|
+
def calcular_impuesto(monto: Decimal, tipo: str) -> Decimal:
|
|
208
|
+
return monto * TASAS[tipo]
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
**Reporte**: "Copy-paste variants — funciones `<a>`, `<b>` difieren solo en constantes. Consolidar."
|
|
212
|
+
|
|
213
|
+
Cuidado: NO consolidar si las funciones evolucionan independientemente por razones de negocio distintas (regla de tres).
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
### 7. Actualizaciones sin efecto (no-op updates)
|
|
218
|
+
|
|
219
|
+
Disparar `setState`, `UPDATE` o re-render sin verificar que el valor cambió.
|
|
220
|
+
|
|
221
|
+
**MAL** — re-render cada vez aunque `usuario` sea el mismo:
|
|
222
|
+
```typescript
|
|
223
|
+
useEffect(() => {
|
|
224
|
+
setUsuarioActivo(usuario);
|
|
225
|
+
}, [usuario]);
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
**BIEN** — comparar antes de actualizar:
|
|
229
|
+
```typescript
|
|
230
|
+
useEffect(() => {
|
|
231
|
+
if (usuario && usuario.id !== usuarioActivoActual?.id) {
|
|
232
|
+
setUsuarioActivo(usuario);
|
|
233
|
+
}
|
|
234
|
+
}, [usuario, usuarioActivoActual]);
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
**Reporte**: "No-op update — `<archivo:línea>` actualiza estado sin guard de cambio. Verificar si el valor difiere."
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
### 8. TOCTOU — Time-of-Check vs Time-of-Use
|
|
242
|
+
|
|
243
|
+
Entre la verificación y el uso, el estado puede cambiar. Race condition silenciosa.
|
|
244
|
+
|
|
245
|
+
**MAL**:
|
|
246
|
+
```python
|
|
247
|
+
if os.path.exists(ruta):
|
|
248
|
+
with open(ruta) as f: # archivo puede haber desaparecido aquí
|
|
249
|
+
return f.read()
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
**BIEN** — intentar y manejar excepción:
|
|
253
|
+
```python
|
|
254
|
+
try:
|
|
255
|
+
with open(ruta) as f:
|
|
256
|
+
return f.read()
|
|
257
|
+
except FileNotFoundError:
|
|
258
|
+
return None
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
**MAL** en BD — check-then-act sin transacción:
|
|
262
|
+
```python
|
|
263
|
+
saldo = obtener_saldo(cuenta_id)
|
|
264
|
+
if saldo >= monto:
|
|
265
|
+
debitar(cuenta_id, monto) # otro proceso pudo cambiar el saldo
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
**BIEN** — lock pesimista o transacción atómica:
|
|
269
|
+
```python
|
|
270
|
+
async with conn.transaction():
|
|
271
|
+
saldo = await obtener_saldo_for_update(cuenta_id) # SELECT ... FOR UPDATE
|
|
272
|
+
if saldo < monto:
|
|
273
|
+
raise SaldoInsuficienteError
|
|
274
|
+
await debitar(cuenta_id, monto)
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
**Reporte**: "TOCTOU — `<archivo:línea>` verifica condición fuera de transacción/lock. Reordenar a try-catch o SELECT FOR UPDATE."
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
### 9. Operaciones demasiado amplias (overly broad operations)
|
|
282
|
+
|
|
283
|
+
Funciones con verbos genéricos (`process`, `handle`, `manage`) que tocan múltiples dominios.
|
|
284
|
+
|
|
285
|
+
**MAL**:
|
|
286
|
+
```typescript
|
|
287
|
+
async function procesarPedido(pedido: Pedido) {
|
|
288
|
+
await validarCliente(pedido.clienteId);
|
|
289
|
+
await debitarInventario(pedido.items);
|
|
290
|
+
await cobrarTarjeta(pedido.pago);
|
|
291
|
+
await enviarEmail(pedido.clienteId);
|
|
292
|
+
await registrarAuditoria(pedido);
|
|
293
|
+
await notificarAlmacen(pedido);
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
**BIEN** — fases nombradas, una responsabilidad por función:
|
|
298
|
+
```typescript
|
|
299
|
+
async function emitirPedido(pedido: Pedido) {
|
|
300
|
+
const validado = await validarPedido(pedido);
|
|
301
|
+
const cobrado = await procesarCobro(validado);
|
|
302
|
+
const confirmado = await confirmarPedido(cobrado);
|
|
303
|
+
await notificarParticipantes(confirmado);
|
|
304
|
+
return confirmado;
|
|
305
|
+
}
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
**Reporte**: "Overly broad operation — `<función>` orquesta N dominios distintos. Dividir por fase o extraer use cases."
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
### 10. Estado redundante (redundant state)
|
|
313
|
+
|
|
314
|
+
Mantener estado derivable de otro estado introduce drift garantizado.
|
|
315
|
+
|
|
316
|
+
**MAL**:
|
|
317
|
+
```typescript
|
|
318
|
+
const [items, setItems] = useState<Item[]>([]);
|
|
319
|
+
const [total, setTotal] = useState(0); // derivable de items
|
|
320
|
+
const [vacio, setVacio] = useState(true); // derivable de items.length
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
**BIEN** — derivar con `useMemo`:
|
|
324
|
+
```typescript
|
|
325
|
+
const [items, setItems] = useState<Item[]>([]);
|
|
326
|
+
const total = useMemo(() => items.reduce((s, i) => s + i.precio, 0), [items]);
|
|
327
|
+
const vacio = items.length === 0;
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
**Reporte**: "Redundant state — `<componente>` mantiene N campos derivables de uno solo. Computar con `useMemo` o getter."
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
## Formato de reporte sugerido
|
|
335
|
+
|
|
336
|
+
Cuando un revisor detecta uno o más anti-patrones, integrarlo en su reporte
|
|
337
|
+
estándar con esta forma:
|
|
338
|
+
|
|
339
|
+
```markdown
|
|
340
|
+
### Anti-patrones detectados
|
|
341
|
+
|
|
342
|
+
| # | Patrón | Archivo:línea | Severidad | Remediación |
|
|
343
|
+
|---|---|---|---|---|
|
|
344
|
+
| 1 | Parameter sprawl | usuarios/service.py:42 | P1 | Extraer a `CrearUsuarioParams` |
|
|
345
|
+
| 2 | Stringly-typed | pedidos/handler.ts:88 | P2 | Crear `enum EstadoPedido` |
|
|
346
|
+
| 3 | TOCTOU | inventario/repo.py:120 | P0 | Envolver en `SELECT FOR UPDATE` |
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
Mapeo a severidades estándar de revisor-codigo-swl:
|
|
350
|
+
- **P0** (mata credibilidad): TOCTOU sin lock cuando hay concurrencia real
|
|
351
|
+
- **P1** (arreglar antes de merge): parameter sprawl >6, leaky abstraction cross-capa
|
|
352
|
+
- **P2** (pulir): stringly-typed con 2-3 usos, no-op updates cosméticos
|
|
353
|
+
|
|
354
|
+
## Lo que esta skill NO hace
|
|
355
|
+
|
|
356
|
+
- No reemplaza al revisor — el revisor ejecuta el análisis y decide.
|
|
357
|
+
- No verifica seguridad (eso es `checklist-seguridad`).
|
|
358
|
+
- No mide rendimiento (eso es `rendimiento-swl`).
|
|
359
|
+
- No corrige código — solo nombra el patrón y propone forma idiomática.
|
|
360
|
+
|
|
361
|
+
## Origen
|
|
362
|
+
|
|
363
|
+
Adaptación curada en es-MX de `reference/code-quality-universal.md` del repo
|
|
364
|
+
`anthropic-skills/code-review-skill` analizado en `temp/code-review-skill-main/`
|
|
365
|
+
(sesión 2026-05-24). Los 10 anti-patrones del catálogo original se tradujeron
|
|
366
|
+
y se ajustaron al stack Python + TypeScript predominante en proyectos SWL.
|
|
367
|
+
Material original bajo licencia compatible; adaptación con vocabulario
|
|
368
|
+
es-MX y ejemplos contextualizados.
|
|
@@ -9,7 +9,7 @@ description: >
|
|
|
9
9
|
cualquier prosa destinada a humanos. Dos modos: rewrite (reescribe) y detect
|
|
10
10
|
(solo señala). NO cargar para código fuente, JSON de configuración, schemas,
|
|
11
11
|
o salida estrictamente determinista.
|
|
12
|
-
version: "1.1.
|
|
12
|
+
version: "1.1.1"
|
|
13
13
|
herramientasPermitidas: [Read, Bash]
|
|
14
14
|
exclusiones:
|
|
15
15
|
- "No cargar para reescribir código fuente, JSON de configuración, schemas, trazas JSONL, mensajes de error del sistema o cualquier salida determinista — este skill opera solo sobre prosa destinada a humanos."
|
|
@@ -282,6 +282,57 @@ párrafo y es la palabra correcta, las tres veces se quedan.
|
|
|
282
282
|
"Los líderes de la industria coinciden" — sin nombrar al experto, estudio o
|
|
283
283
|
líder. Citar fuente específica o afirmar directamente sin la atribución.
|
|
284
284
|
|
|
285
|
+
### Agencia falsa (cosas inanimadas haciendo verbos humanos)
|
|
286
|
+
|
|
287
|
+
IA evita nombrar al actor humano dándole agencia a cosas inanimadas. Las
|
|
288
|
+
quejas no "se transforman en arreglos"; las decisiones no "emergen"; los
|
|
289
|
+
datos no "nos dicen". Una persona hace algo para que esas cosas ocurran.
|
|
290
|
+
|
|
291
|
+
| Patrón | Problema | Reescritura |
|
|
292
|
+
|---|---|---|
|
|
293
|
+
| "los datos nos dicen que..." | Los datos no hablan; alguien los lee | "Al revisar los logs vi que..." |
|
|
294
|
+
| "la decisión emergió" | Las decisiones no emergen | "El equipo decidió que..." |
|
|
295
|
+
| "la queja se transformó en un arreglo" | La queja no hizo nada | "El equipo arregló el bug esa semana" |
|
|
296
|
+
| "el mercado recompensa" | Los mercados no recompensan | "Los clientes pagaron por..." |
|
|
297
|
+
| "la cultura se desplaza hacia" | Las culturas no se desplazan solas | "El equipo cambió cómo..." |
|
|
298
|
+
| "la conversación se mueve hacia" | Las conversaciones no se mueven | "Alguien redirigió la discusión hacia..." |
|
|
299
|
+
| "el código se autoexplica" | El código no explica | "El lector entiende el código sin comentarios" |
|
|
300
|
+
|
|
301
|
+
**Regla**: si una cosa inanimada es sujeto de un verbo humano (decir,
|
|
302
|
+
decidir, querer, transformar, moverse), buscar al humano real. Si no hay
|
|
303
|
+
uno específico, usar "tú" para poner al lector en el lugar de la acción.
|
|
304
|
+
|
|
305
|
+
### Voz de narrador-distancia
|
|
306
|
+
|
|
307
|
+
Flotar sobre la escena en vez de poner al lector dentro. Aleja, no acerca.
|
|
308
|
+
|
|
309
|
+
| Patrón | Reescritura |
|
|
310
|
+
|---|---|
|
|
311
|
+
| "Nadie diseñó esto" | "Tú no te sientas un día a decidir..." |
|
|
312
|
+
| "Esto pasa porque..." | "Cuando X ocurre, tú ves Y" |
|
|
313
|
+
| "La gente tiende a..." | "Si has trabajado en X, sabes que..." |
|
|
314
|
+
| "Es común que los equipos..." | "Los equipos de SIGAF caen en..." |
|
|
315
|
+
|
|
316
|
+
**Regla**: cambiar tercera persona genérica ("la gente", "los equipos",
|
|
317
|
+
"nadie", "uno") por segunda persona ("tú") con escenario concreto, o por
|
|
318
|
+
nombres específicos.
|
|
319
|
+
|
|
320
|
+
### Aperturas Wh-
|
|
321
|
+
|
|
322
|
+
Oraciones que empiezan con "Lo que", "Cómo", "Por qué", "Cuándo", "Dónde"
|
|
323
|
+
seguidas de cláusula explicativa son muletilla retórica. Reestructurar
|
|
324
|
+
para liderar con el sujeto o el verbo real.
|
|
325
|
+
|
|
326
|
+
| Patrón | Reescritura |
|
|
327
|
+
|---|---|
|
|
328
|
+
| "Lo que hace difícil esto es X" | "La restricción es X" o nombrar X directamente |
|
|
329
|
+
| "Por qué importa esto: ..." | Quitar la pregunta y afirmar el por qué |
|
|
330
|
+
| "Cómo funciona: ..." | "El flujo es: ..." o describir el flujo sin anuncio |
|
|
331
|
+
| "Cuándo aplica X..." | "X aplica cuando..." |
|
|
332
|
+
|
|
333
|
+
Excepción: títulos de sección H2/H3 que sí preguntan ("Cuándo cargar") son
|
|
334
|
+
estructura legítima de skill, no muletilla retórica.
|
|
335
|
+
|
|
285
336
|
### Frases relleno
|
|
286
337
|
|
|
287
338
|
- "Es importante notar que" → (solo afirmarlo)
|