@saulwade/swl-ses 1.8.0 → 2.0.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.
- package/CLAUDE.md +8 -8
- package/README.md +13 -13
- package/agentes/accesibilidad-wcag-swl.md +3 -3
- package/agentes/auto-evolucion-swl.md +908 -908
- package/agentes/disenador-ui-swl.md +6 -5
- package/agentes/frontend-angular-swl.md +2 -2
- package/agentes/frontend-css-swl.md +2 -2
- package/agentes/frontend-react-swl.md +4 -4
- package/agentes/frontend-swl.md +6 -6
- package/agentes/investigador-ux-swl.md +5 -5
- package/agentes/orquestador-swl.md +96 -8
- package/agentes/perfilador-usuario-swl.md +308 -308
- package/agentes/producto-prd-swl.md +1 -1
- package/agentes/red-team-swl.md +218 -218
- package/agentes/revisor-codigo-swl.md +34 -10
- package/agentes/revisor-seguridad-swl.md +7 -0
- package/agentes/tdd-qa-swl.md +39 -2
- package/comandos/swl/actualizar.md +1 -1
- package/comandos/swl/aprender.md +2 -2
- package/comandos/swl/aprobar-plan.md +152 -0
- package/comandos/swl/autoresearch.md +102 -6
- package/comandos/swl/ayuda.md +3 -3
- package/comandos/swl/discutir-fase.md +20 -2
- package/comandos/swl/ejecutar-fase.md +53 -6
- package/comandos/swl/evolucionar.md +1 -1
- package/comandos/swl/inbox.md +1 -1
- package/comandos/swl/instalar.md +1 -1
- package/comandos/swl/nemesis.md +42 -1
- package/comandos/swl/planear-fase.md +25 -1
- package/comandos/swl/plugins.md +1 -1
- package/comandos/swl/predecir.md +139 -0
- package/comandos/swl/release.md +1 -1
- package/comandos/swl/status.md +279 -0
- package/comandos/swl/verificar.md +75 -7
- package/habilidades/ai-runtime-security/SKILL.md +1 -1
- package/habilidades/angular-moderno/SKILL.md +44 -1
- package/habilidades/auto-evolucion-protocolo/SKILL.md +276 -276
- package/habilidades/autoresearch/SKILL.md +15 -1
- package/habilidades/benchmark-memoria/SKILL.md +1 -1
- package/habilidades/calidad-contract-testing/SKILL.md +165 -0
- package/habilidades/calidad-mutation-testing/SKILL.md +170 -0
- package/habilidades/changelog-generator/SKILL.md +9 -2
- package/habilidades/changelog-generator/scripts/parse-commits.js +12 -1
- package/habilidades/checklist-seguridad/SKILL.md +29 -1
- package/habilidades/checklist-seguridad/recursos/stride-cobertura.md +60 -0
- package/habilidades/css-moderno/SKILL.md +3 -1
- package/habilidades/diagrama-arquitectura/SKILL.md +1 -1
- package/habilidades/drift-detection/SKILL.md +179 -179
- package/habilidades/ejecutar-fase/SKILL.md +64 -14
- package/habilidades/estructura-proyecto-claude/SKILL.md +17 -14
- package/habilidades/estructura-proyecto-claude/recursos/configuracion-y-extensiones.md +34 -23
- package/habilidades/estructura-proyecto-claude/recursos/frontmatter-y-hooks-referencia.md +70 -53
- package/habilidades/estructura-proyecto-claude/recursos/mcp-json-template.json +57 -77
- package/habilidades/extractor-de-aprendizajes/SKILL.md +9 -5
- package/habilidades/fastapi-experto/SKILL.md +56 -5
- package/habilidades/harness-claude-code/SKILL.md +10 -7
- package/{reglas/harness-claude-code.md → habilidades/harness-claude-code/recursos/disciplina-harness-regla.md} +2 -2
- package/habilidades/instalar-sistema/SKILL.md +3 -3
- package/habilidades/meta-skills-estandar/recursos/frameworks-seguridad.md +1 -1
- package/habilidades/patrones-python/SKILL.md +8 -5
- package/habilidades/perfil-usuario/SKILL.md +200 -200
- package/habilidades/planear-fase/SKILL.md +25 -4
- package/habilidades/proceso-ddia-fundamentos/SKILL.md +1 -1
- package/habilidades/proceso-ddia-streaming/SKILL.md +4 -4
- package/habilidades/proceso-debate-adversarial/SKILL.md +164 -0
- package/habilidades/proceso-debate-adversarial/recursos/personas.md +105 -0
- package/habilidades/proceso-dynamic-workflows/SKILL.md +138 -0
- package/habilidades/proceso-dynamic-workflows/recursos/template-adversarial-verify.js +65 -0
- package/habilidades/proceso-dynamic-workflows/recursos/template-triage.js +65 -0
- package/habilidades/protocolo-revision-swl/SKILL.md +1 -1
- package/habilidades/seguridad-skills-ia/SKILL.md +1 -1
- package/habilidades/swl-claudemd/SKILL.md +50 -210
- package/habilidades/swl-claudemd/recursos/contrato-aprender.md +83 -0
- package/habilidades/swl-claudemd/recursos/duplicacion-reglas-globales.md +85 -0
- package/habilidades/swl-claudemd/recursos/plantillas-init.md +94 -0
- package/habilidades/swl-dashboard/SKILL.md +9 -9
- package/habilidades/swl-revisar-impacto/SKILL.md +1 -1
- package/habilidades/tdd-workflow/SKILL.md +58 -5
- package/habilidades/tdd-workflow/recursos/gherkin-bdd.md +111 -0
- package/habilidades/validacion-ci-sistema/SKILL.md +3 -3
- package/hooks/calidad-pre-commit.js +340 -3
- package/hooks/ciclo-evolucion-subagente.js +26 -0
- package/hooks/ciclo-evolucion.js +26 -0
- package/hooks/contexto-iteracion.js +144 -0
- package/hooks/extraccion-aprendizajes.js +13 -0
- package/hooks/lib/ciclo-evolucion.js +47 -0
- package/hooks/{auto-evolucion.js → lib/etapa-auto-evolucion.js} +701 -700
- package/hooks/{metricas-evolucion.js → lib/etapa-metricas.js} +388 -376
- package/hooks/{actualizar-perfil-usuario.js → lib/etapa-perfil-usuario.js} +376 -364
- package/hooks/lib/evolution-tracker.js +24 -3
- package/hooks/lib/loop-telemetry.js +321 -0
- package/hooks/notificacion-telegram.js +11 -3
- package/hooks/spec-gate.js +211 -0
- package/hooks/tdd-gate.js +241 -0
- package/hooks/validar-intent-spec.js +30 -10
- package/llms.txt +29 -0
- package/manifiestos/hooks-config.json +36 -18
- package/manifiestos/modulos.json +23 -14
- package/manifiestos/skills-lock.json +100 -72
- package/package.json +4 -3
- package/plugin.json +9 -10
- package/reglas/accesibilidad.md +10 -0
- package/reglas/api-diseno.md +9 -0
- package/reglas/arquitectura.evolved.json +7 -0
- package/reglas/arquitectura.md +65 -0
- package/reglas/auditorias-documentales-estructurales.md +7 -0
- package/reglas/cloud-infra.md +8 -0
- package/reglas/fragmentos-compartidos.md +5 -0
- package/reglas/gobernanza.md +4 -4
- package/reglas/hooks.md +6 -0
- package/reglas/intent-engineering.md +4 -0
- package/reglas/markitdown.md +8 -0
- package/reglas/memoria-consolidada.md +1 -1
- package/reglas/patrones.md +6 -0
- package/reglas/registro-componentes-nuevos.md +10 -1
- package/reglas/seguridad-agentes.md +1 -1
- package/reglas/seguridad.evolved.json +7 -0
- package/reglas/seguridad.md +144 -0
- package/reglas/skills-estandar.md +6 -0
- package/reglas/testing.md +7 -0
- package/reglas/tests-cleanup.md +4 -0
- package/reglas/usar-sistema-swl.md +1 -1
- package/scripts/generar-inventario.js +64 -1
- package/scripts/instalador.js +32 -2
- package/scripts/lib/gitignore-manifest.js +29 -1
- package/scripts/lib/plan-lock.js +275 -0
- package/scripts/migrar-fase-dominio.js +0 -1
- package/scripts/smoke-test.js +24 -2
- package/scripts/verificar-trazabilidad.js +292 -0
- package/agentes/ux-disenador-swl.md +0 -503
- package/comandos/swl/dashboard.md +0 -146
- package/comandos/swl/evolucion-estado.md +0 -191
- package/comandos/swl/metricas.md +0 -342
- package/comandos/swl/salud.md +0 -481
- package/reglas/verificar-citas-temporales.md +0 -139
|
@@ -28,41 +28,42 @@ completos de settings.json, .mcp.json, plugins y checklists detallados.
|
|
|
28
28
|
"PreToolUse": [
|
|
29
29
|
{
|
|
30
30
|
"matcher": "Bash",
|
|
31
|
-
"
|
|
32
|
-
|
|
31
|
+
"hooks": [
|
|
32
|
+
{ "type": "command", "command": "node .claude/hooks/lint-check.js" }
|
|
33
|
+
]
|
|
33
34
|
}
|
|
34
35
|
],
|
|
35
36
|
"PostToolUse": [
|
|
36
37
|
{
|
|
37
38
|
"matcher": "Write",
|
|
38
|
-
"
|
|
39
|
-
|
|
39
|
+
"hooks": [
|
|
40
|
+
{ "type": "command", "command": "node .claude/hooks/format-on-save.js" }
|
|
41
|
+
]
|
|
40
42
|
}
|
|
41
43
|
],
|
|
42
44
|
"SessionStart": [
|
|
43
45
|
{
|
|
44
46
|
"matcher": "startup",
|
|
45
|
-
"
|
|
46
|
-
|
|
47
|
+
"hooks": [
|
|
48
|
+
{ "type": "command", "command": "node .claude/hooks/load-context.js" }
|
|
49
|
+
]
|
|
47
50
|
}
|
|
48
51
|
]
|
|
49
|
-
},
|
|
50
|
-
"context": {
|
|
51
|
-
"rules": [
|
|
52
|
-
"CLAUDE.md"
|
|
53
|
-
]
|
|
54
52
|
}
|
|
55
53
|
}
|
|
56
54
|
```
|
|
57
55
|
|
|
58
56
|
### Jerarquía de settings (mayor a menor prioridad)
|
|
59
57
|
|
|
60
|
-
1. **Managed** (MDM plist / Registry / Server-managed / `managed-settings.
|
|
58
|
+
1. **Managed** (MDM plist / Registry / Server-managed / `managed-settings.json`)
|
|
61
59
|
2. **CLI arguments** (solo sesión actual)
|
|
62
60
|
3. **`.claude/settings.local.json`** (personal, git-ignored)
|
|
63
61
|
4. **`.claude/settings.json`** (equipo, commiteado)
|
|
64
62
|
5. **`~/.claude/settings.json`** (global personal)
|
|
65
63
|
|
|
64
|
+
**Excepción**: los `permissions` (allow/deny) se **fusionan** entre scopes, no se
|
|
65
|
+
sobreescriben por precedencia simple.
|
|
66
|
+
|
|
66
67
|
---
|
|
67
68
|
|
|
68
69
|
## Settings avanzados y variables de entorno
|
|
@@ -90,13 +91,20 @@ Settings poco documentados pero de alto impacto:
|
|
|
90
91
|
|
|
91
92
|
| Flag | Efecto |
|
|
92
93
|
|------|--------|
|
|
93
|
-
| `--bare` |
|
|
94
|
-
| `--add-dir <path>` | Agregar directorio adicional a la sesión — sesiones multi-repo sin copiar archivos |
|
|
95
|
-
| `-w` / `--worktree` | Git worktree aislado
|
|
96
|
-
| `--agent
|
|
97
|
-
| `--effort
|
|
98
|
-
|
|
|
99
|
-
|
|
94
|
+
| `--bare` | Modo mínimo: omite auto-discovery de hooks, skills, plugins, MCP servers, auto memory y CLAUDE.md — arranque más rápido para scripts |
|
|
95
|
+
| `--add-dir <path>` | Agregar directorio adicional a la sesión — sesiones multi-repo sin copiar archivos. Los CLAUDE.md de esos directorios NO se cargan por defecto (`CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1` para cargarlos) |
|
|
96
|
+
| `-w` / `--worktree` | Git worktree aislado en `<repo>/.claude/worktrees/<nombre>` |
|
|
97
|
+
| `--agent <nombre>` | Usar agente custom como agente principal de la sesión |
|
|
98
|
+
| `--effort <nivel>` | Nivel de esfuerzo de la sesión: `low`, `medium`, `high`, `xhigh`, `max` |
|
|
99
|
+
| `--max-budget-usd <n>` | Tope de gasto en API antes de detenerse (solo print mode) |
|
|
100
|
+
|
|
101
|
+
### Comando `/sandbox` (Bash sandbox)
|
|
102
|
+
|
|
103
|
+
Abre el panel del sandbox de Bash: aislamiento de filesystem y red **a nivel de SO**
|
|
104
|
+
(Seatbelt en macOS, bubblewrap en Linux/WSL2 — no soportado en Windows nativo). En modo
|
|
105
|
+
auto-allow, los comandos sandboxeados corren sin diálogos de permiso; los que requieren
|
|
106
|
+
acceso fuera del boundary caen al flujo regular de permisos. Configuración persistente
|
|
107
|
+
vía `sandbox.enabled` y `sandbox.filesystem.*` en settings.json.
|
|
100
108
|
|
|
101
109
|
---
|
|
102
110
|
|
|
@@ -110,18 +118,21 @@ Settings poco documentados pero de alto impacto:
|
|
|
110
118
|
"args": ["-y", "@upstash/context7-mcp@latest"]
|
|
111
119
|
},
|
|
112
120
|
"github": {
|
|
113
|
-
"
|
|
114
|
-
"
|
|
115
|
-
"env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "" }
|
|
121
|
+
"type": "http",
|
|
122
|
+
"url": "https://api.githubcopilot.com/mcp/"
|
|
116
123
|
},
|
|
117
124
|
"playwright": {
|
|
118
125
|
"command": "npx",
|
|
119
|
-
"args": ["-y", "@
|
|
126
|
+
"args": ["-y", "@playwright/mcp@latest"]
|
|
120
127
|
}
|
|
121
128
|
}
|
|
122
129
|
}
|
|
123
130
|
```
|
|
124
131
|
|
|
132
|
+
> El GitHub MCP server oficial es remoto (`api.githubcopilot.com/mcp/`) — el paquete
|
|
133
|
+
> npm `@modelcontextprotocol/server-github` fue archivado. El de Playwright oficial
|
|
134
|
+
> es `@playwright/mcp` (Microsoft).
|
|
135
|
+
|
|
125
136
|
Ver catalogo completo en [mcp-json-template.json](mcp-json-template.json).
|
|
126
137
|
|
|
127
138
|
---
|
|
@@ -4,19 +4,23 @@ Fuente: https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overvi
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
## Frontmatter completo de SKILL.md (
|
|
7
|
+
## Frontmatter completo de SKILL.md (16 campos — aplica también a commands, que se fusionaron con skills)
|
|
8
8
|
|
|
9
9
|
| Campo | Requerido | Tipo | Descripción |
|
|
10
10
|
|-------|-----------|------|-------------|
|
|
11
|
-
| `name` | No* | string | Nombre
|
|
12
|
-
| `description` | Recomendado | string |
|
|
11
|
+
| `name` | No* | string | Nombre mostrado en listados. *Si se omite, usa el nombre del directorio |
|
|
12
|
+
| `description` | Recomendado | string | QUÉ hace + CUÁNDO usar. Guía la auto-activación. `description` + `when_to_use` se truncan a 1,536 chars combinados en el listado |
|
|
13
|
+
| `when_to_use` | Opcional | string | Contexto adicional de activación (frases trigger, ejemplos). Se anexa a `description` y cuenta para el tope de 1,536 chars |
|
|
13
14
|
| `argument-hint` | Opcional | string | Hint de autocompletado: `[archivo]`, `[issue-num]`, `[file] [format]` |
|
|
14
|
-
| `
|
|
15
|
+
| `arguments` | Opcional | array/string | Argumentos posicionales con nombre para sustitución `$nombre` en el contenido |
|
|
16
|
+
| `allowed-tools` | Opcional | array/string | Tools que Claude puede usar sin pedir permiso cuando la skill está activa |
|
|
17
|
+
| `disallowed-tools` | Opcional | array/string | Tools removidas del pool de Claude mientras la skill está activa |
|
|
15
18
|
| `paths` | Opcional | array/string | Patrones glob: cargar skill SOLO al trabajar con archivos que coinciden |
|
|
16
19
|
| `context` | Opcional | string | `fork` = ejecutar en subagente aislado con su propia conversación |
|
|
17
20
|
| `agent` | Opcional | string | Tipo de subagente si `context: fork` (Explore, Plan, general-purpose) |
|
|
18
|
-
| `model` | Opcional | string | Override de modelo
|
|
19
|
-
| `effort` | Opcional | string | Nivel de esfuerzo: `low`, `medium`, `high`, `max` (
|
|
21
|
+
| `model` | Opcional | string | Override de modelo mientras la skill está activa (mismos valores que `/model`, o `inherit`) |
|
|
22
|
+
| `effort` | Opcional | string | Nivel de esfuerzo: `low`, `medium`, `high`, `xhigh`, `max` (los niveles disponibles dependen del modelo) |
|
|
23
|
+
| `hooks` | Opcional | object | Hooks acotados al ciclo de vida de esta skill |
|
|
20
24
|
| `shell` | Opcional | string | `bash` o `powershell`. Controla bloques `!comando` embebidos |
|
|
21
25
|
| `disable-model-invocation` | Opcional | boolean | `true` = solo el usuario puede invocar (no auto-trigger). Usar para skills con side-effects como `/deploy` |
|
|
22
26
|
| `user-invocable` | Opcional | boolean | `false` = solo Claude la ve (conocimiento de background). No aparece en menú `/` |
|
|
@@ -46,21 +50,24 @@ user-invocable: true
|
|
|
46
50
|
|
|
47
51
|
| Variable | Valor |
|
|
48
52
|
|----------|-------|
|
|
49
|
-
| `$ARGUMENTS` |
|
|
50
|
-
| `$
|
|
53
|
+
| `$ARGUMENTS` | Todos los argumentos pasados al invocar la skill (si no aparece, se anexan como `ARGUMENTS: <valor>`) |
|
|
54
|
+
| `$ARGUMENTS[N]` | Argumento específico por índice 0-based |
|
|
55
|
+
| `$0`, `$1`, `$2`... | Shorthand de `$ARGUMENTS[N]` |
|
|
56
|
+
| `$nombre` | Argumento con nombre declarado en `arguments:` del frontmatter |
|
|
51
57
|
| `${CLAUDE_SESSION_ID}` | ID unico de la sesion actual |
|
|
58
|
+
| `${CLAUDE_EFFORT}` | Nivel de esfuerzo activo (`low`...`max`) |
|
|
52
59
|
| `${CLAUDE_SKILL_DIR}` | Path absoluto al directorio de la skill |
|
|
53
|
-
| `${env:VAR_NAME}` | Variable de entorno del sistema |
|
|
54
60
|
|
|
55
61
|
---
|
|
56
62
|
|
|
57
|
-
##
|
|
63
|
+
## 30 Hook Events oficiales
|
|
58
64
|
|
|
59
65
|
### Ciclo de vida de sesión
|
|
60
66
|
|
|
61
67
|
| Evento | Cuándo se dispara | Matchers | Uso típico |
|
|
62
68
|
|--------|-------------------|----------|-----------|
|
|
63
69
|
| `SessionStart` | Al iniciar o resumir sesión | `startup`, `resume`, `clear`, `compact` | Cargar contexto, setup env |
|
|
70
|
+
| `Setup` | Inicialización one-time (`--init-only`, `--maintenance`) | `init`, `maintenance` | Bootstrap de repo, mantenimiento |
|
|
64
71
|
| `SessionEnd` | Al terminar sesión | `clear`, `resume`, `logout`, `other` | Cleanup, archivado |
|
|
65
72
|
| `InstructionsLoaded` | CLAUDE.md o rules/ cargados | `session_start`, `nested_traversal`, `path_glob_match`, `include`, `compact` | Log que instrucciones se cargaron |
|
|
66
73
|
|
|
@@ -71,7 +78,9 @@ user-invocable: true
|
|
|
71
78
|
| `PreToolUse` | Antes de ejecutar herramienta | Nombre de tool (Bash, Edit, Read, mcp__*) | Bloquear ops inseguras, validar |
|
|
72
79
|
| `PostToolUse` | Después de ejecutar herramienta (éxito) | Nombre de tool | Auto-lint, format, log |
|
|
73
80
|
| `PostToolUseFailure` | Cuando falla herramienta | Nombre de tool | Notificar, reintentar |
|
|
81
|
+
| `PostToolBatch` | Al resolver un batch completo de tool calls paralelos | Ninguno | Métricas de batch |
|
|
74
82
|
| `PermissionRequest` | Se muestra diálogo de permiso | Nombre de tool | Auto-aprobar acciones seguras |
|
|
83
|
+
| `PermissionDenied` | El clasificador de auto mode niega un tool call | Nombre de tool | Log, escalar |
|
|
75
84
|
|
|
76
85
|
### Respuesta y control
|
|
77
86
|
|
|
@@ -80,6 +89,8 @@ user-invocable: true
|
|
|
80
89
|
| `Stop` | Claude termina de responder | Ninguno (siempre se dispara) | Verificar tarea completa |
|
|
81
90
|
| `StopFailure` | Error de API en Stop | `rate_limit`, `authentication_failed`, `billing_error`, `server_error` | Notificar fallos |
|
|
82
91
|
| `UserPromptSubmit` | Usuario envía prompt | Ninguno | Interceptar/enriquecer input |
|
|
92
|
+
| `UserPromptExpansion` | Un comando del usuario se expande a prompt | Ninguno | Transformar input |
|
|
93
|
+
| `MessageDisplay` | Mientras se muestra texto del asistente | Ninguno | Modificar texto en pantalla |
|
|
83
94
|
|
|
84
95
|
### Compactación de contexto
|
|
85
96
|
|
|
@@ -135,44 +146,40 @@ user-invocable: true
|
|
|
135
146
|
|
|
136
147
|
## Frontmatter completo de agents (.claude/agents/*.md) — 16 campos
|
|
137
148
|
|
|
138
|
-
| Campo | Tipo | Descripción |
|
|
139
|
-
|
|
140
|
-
| `name` | string |
|
|
141
|
-
| `description` | string | Cuándo
|
|
142
|
-
| `
|
|
143
|
-
| `
|
|
144
|
-
| `
|
|
145
|
-
| `permissionMode` | string | `acceptEdits`, `dontAsk`, `
|
|
146
|
-
| `
|
|
147
|
-
| `skills` | array | Skills
|
|
148
|
-
| `
|
|
149
|
-
| `
|
|
150
|
-
| `
|
|
151
|
-
| `
|
|
152
|
-
| `
|
|
153
|
-
| `
|
|
154
|
-
| `
|
|
155
|
-
| `
|
|
156
|
-
|
|
157
|
-
**Gotcha**: El evento `Stop` en
|
|
149
|
+
| Campo | Requerido | Tipo | Descripción |
|
|
150
|
+
|-------|-----------|------|-------------|
|
|
151
|
+
| `name` | Sí | string | Identificador único en minúsculas con guiones. Los hooks lo reciben como `agent_type` |
|
|
152
|
+
| `description` | Sí | string | Cuándo Claude debe delegar a este subagente |
|
|
153
|
+
| `tools` | No | array | Tools que el subagente puede usar. Hereda todas si se omite. Para precargar skills usar `skills`, no listar `Skill` aquí |
|
|
154
|
+
| `disallowedTools` | No | array | Tools negadas — se remueven de la lista heredada o especificada |
|
|
155
|
+
| `model` | No | string | `sonnet`, `opus`, `haiku`, `fable`, un model ID completo, o `inherit` (default) |
|
|
156
|
+
| `permissionMode` | No | string | `default`, `acceptEdits`, `auto`, `dontAsk`, `bypassPermissions`, `plan` |
|
|
157
|
+
| `maxTurns` | No | number | Máximo de turnos agénticos antes de detenerse |
|
|
158
|
+
| `skills` | No | array | Skills precargadas al contexto al inicio (se inyecta el contenido completo) |
|
|
159
|
+
| `mcpServers` | No | array/object | MCP servers disponibles para este subagente (nombre de server ya configurado o definición inline) |
|
|
160
|
+
| `hooks` | No | object | Hooks acotados al ciclo de vida del subagente (`Stop` se convierte en `SubagentStop` en runtime) |
|
|
161
|
+
| `memory` | No | string | Memoria persistente cross-sesión: `user`, `project`, `local` |
|
|
162
|
+
| `background` | No | boolean | `true` = siempre corre como background task |
|
|
163
|
+
| `effort` | No | string | `low`, `medium`, `high`, `xhigh`, `max` — override del nivel de sesión |
|
|
164
|
+
| `isolation` | No | string | `worktree` = git worktree temporal aislado (auto-limpiado si no hay cambios) |
|
|
165
|
+
| `color` | No | string | Color en task list/transcript: `red`, `blue`, `green`, `yellow`, `purple`, `orange`, `pink`, `cyan` |
|
|
166
|
+
| `initialPrompt` | No | string | Primer turno auto-enviado cuando el agente corre como agente principal (`--agent`) |
|
|
167
|
+
|
|
168
|
+
**Gotcha**: El evento `Stop` declarado en `hooks:` de un agente se dispara como `SubagentStop`, no como `Stop`.
|
|
158
169
|
|
|
159
170
|
---
|
|
160
171
|
|
|
161
|
-
## Frontmatter de commands (.claude/commands/*.md)
|
|
172
|
+
## Frontmatter de commands (.claude/commands/*.md)
|
|
162
173
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
| `argument-hint` | string | Hint visual: `[archivo]`, `[issue-num]` |
|
|
168
|
-
| `allowed-tools` | array | Tools permitidos sin pedir permiso |
|
|
169
|
-
| `model` | string | Override de modelo |
|
|
170
|
-
| `effort` | string | Nivel de esfuerzo |
|
|
171
|
-
| `shell` | string | `bash` o `powershell` |
|
|
172
|
-
| `user-invocable` | boolean | Default `true` — commands siempre son user-invocable |
|
|
173
|
-
| `disable-model-invocation` | boolean | `true` = Claude no puede auto-invocar |
|
|
174
|
+
**Los commands se fusionaron con las skills**: un archivo en `.claude/commands/deploy.md`
|
|
175
|
+
y una skill en `.claude/skills/deploy/SKILL.md` crean ambos `/deploy` y funcionan igual.
|
|
176
|
+
Los archivos existentes en `.claude/commands/` siguen funcionando y aceptan el **mismo
|
|
177
|
+
frontmatter de 16 campos de SKILL.md** (ver tabla arriba).
|
|
174
178
|
|
|
175
|
-
|
|
179
|
+
Las skills agregan sobre los commands legacy: directorio de archivos de apoyo,
|
|
180
|
+
control de invocación (`disable-model-invocation`, `user-invocable`) y auto-activación
|
|
181
|
+
por relevancia. Para forzar que un comando NUNCA se auto-invoque (comportamiento
|
|
182
|
+
del command clásico), declarar `disable-model-invocation: true`.
|
|
176
183
|
|
|
177
184
|
---
|
|
178
185
|
|
|
@@ -195,6 +202,7 @@ porque se ejecuta inline sin el overhead de un subagente.
|
|
|
195
202
|
| `prompt` | Claude decide qué hacer | `"prompt": "Verifica que el archivo..."` |
|
|
196
203
|
| `agent` | Claude con herramientas propias | `"agent": "Analiza y corrige..."` |
|
|
197
204
|
| `http` | POST a endpoint HTTP | `"url": "https://webhook.example.com/hook"` |
|
|
205
|
+
| `mcp_tool` | Llama una tool de un MCP server configurado | `"server": "slack", "tool": "send_message"` |
|
|
198
206
|
|
|
199
207
|
### Códigos de retorno para hooks command
|
|
200
208
|
|
|
@@ -209,22 +217,31 @@ porque se ejecuta inline sin el overhead de un subagente.
|
|
|
209
217
|
| Opción | Tipo | Descripción |
|
|
210
218
|
|--------|------|-------------|
|
|
211
219
|
| `async` | boolean | Ejecutar en background sin bloquear — fire-and-forget |
|
|
212
|
-
| `timeout` | number | Timeout en
|
|
213
|
-
| `once` | boolean | Ejecutar solo
|
|
214
|
-
| `asyncRewake` | boolean |
|
|
215
|
-
| `statusMessage` | string | Mensaje
|
|
216
|
-
| `if` | string |
|
|
220
|
+
| `timeout` | number | Timeout en **segundos** (defaults: 600 command/http/mcp_tool, 30 prompt, 60 agent) |
|
|
221
|
+
| `once` | boolean | Ejecutar una sola vez por sesión y removerse (solo en hooks de frontmatter de skill) |
|
|
222
|
+
| `asyncRewake` | boolean | Background + re-despertar a Claude si el hook sale con exit code 2 (implica `async`) |
|
|
223
|
+
| `statusMessage` | string | Mensaje del spinner mientras el hook ejecuta |
|
|
224
|
+
| `if` | string | Filtro con sintaxis de regla de permisos: `"Bash(git *)"`, `"Edit(*.ts)"` |
|
|
217
225
|
|
|
218
226
|
### Campos JSON de retorno del hook
|
|
219
227
|
|
|
228
|
+
Campos universales (nivel superior):
|
|
229
|
+
|
|
230
|
+
| Campo | Tipo | Efecto |
|
|
231
|
+
|-------|------|--------|
|
|
232
|
+
| `continue` | boolean | `false` = detener el procesamiento por completo |
|
|
233
|
+
| `stopReason` | string | Mensaje mostrado cuando `continue: false` |
|
|
234
|
+
| `suppressOutput` | boolean | Ocultar el stdout del hook del transcript |
|
|
235
|
+
| `systemMessage` | string | Mensaje de advertencia mostrado al usuario |
|
|
236
|
+
|
|
237
|
+
Campos dentro de `hookSpecificOutput` (con `hookEventName` obligatorio):
|
|
238
|
+
|
|
220
239
|
| Campo | Tipo | Efecto |
|
|
221
240
|
|-------|------|--------|
|
|
222
|
-
| `continue` | boolean | `false` = detener la cadena de hooks |
|
|
223
|
-
| `stopReason` | string | Razón de detención (si `continue: false`) |
|
|
224
|
-
| `suppressOutput` | boolean | No mostrar output del hook al usuario |
|
|
225
|
-
| `systemMessage` | string | Inyectar mensaje al contexto del sistema |
|
|
226
241
|
| `additionalContext` | string | Agregar contexto adicional a la conversación |
|
|
227
|
-
| `updatedInput` | object |
|
|
242
|
+
| `updatedInput` | object | Reescribir el input de la herramienta (PreToolUse, PostToolUse) |
|
|
243
|
+
| `updatedToolOutput` | object | Reescribir el output de la herramienta (PostToolUse) |
|
|
244
|
+
| `permissionDecision` | string | Solo PreToolUse: `allow`, `deny`, `ask`, `defer` |
|
|
228
245
|
|
|
229
246
|
---
|
|
230
247
|
|
|
@@ -1,77 +1,57 @@
|
|
|
1
|
-
{
|
|
2
|
-
"_comentario": "Template de .mcp.json para proyectos Claude-ready. Eliminar los servidores que no se usen. Las variables de entorno con valor vacío deben completarse en .env o exportarse antes de correr claude.",
|
|
3
|
-
"_instrucciones": [
|
|
4
|
-
"1. Copiar este archivo a la raíz del proyecto como .mcp.json",
|
|
5
|
-
"2. Eliminar el bloque _comentario y _instrucciones (no son JSON válido en producción)",
|
|
6
|
-
"3. Configurar las variables de entorno requeridas por cada servidor activo",
|
|
7
|
-
"4. Agregar .mcp.json al repositorio (no contiene secretos — los secretos van en env vars)",
|
|
8
|
-
"5. Agregar a .gitignore cualquier archivo .mcp.local.json con credenciales"
|
|
9
|
-
],
|
|
10
|
-
"
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
"memory": {
|
|
59
|
-
"_descripcion": "Memoria persistente entre sesiones. Almacena entidades y relaciones en grafo.",
|
|
60
|
-
"_activar": "Útil para proyectos largos donde se quiere persistir contexto entre sesiones",
|
|
61
|
-
"command": "npx",
|
|
62
|
-
"args": ["-y", "@modelcontextprotocol/server-memory"]
|
|
63
|
-
},
|
|
64
|
-
"puppeteer": {
|
|
65
|
-
"_descripcion": "Control de navegador. Útil para testing E2E, scraping o automatización web.",
|
|
66
|
-
"_activar": "Requiere Chrome/Chromium instalado",
|
|
67
|
-
"command": "npx",
|
|
68
|
-
"args": ["-y", "@modelcontextprotocol/server-puppeteer"]
|
|
69
|
-
},
|
|
70
|
-
"sequential-thinking": {
|
|
71
|
-
"_descripcion": "Herramienta de razonamiento estructurado para problemas complejos.",
|
|
72
|
-
"_activar": "Útil para arquitectura, debugging complejo, decisiones de diseño",
|
|
73
|
-
"command": "npx",
|
|
74
|
-
"args": ["-y", "@modelcontextprotocol/server-sequential-thinking"]
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"_comentario": "Template de .mcp.json para proyectos Claude-ready. Eliminar los servidores que no se usen. Las variables de entorno con valor vacío deben completarse en .env o exportarse antes de correr claude.",
|
|
3
|
+
"_instrucciones": [
|
|
4
|
+
"1. Copiar este archivo a la raíz del proyecto como .mcp.json",
|
|
5
|
+
"2. Eliminar el bloque _comentario y _instrucciones (no son JSON válido en producción)",
|
|
6
|
+
"3. Configurar las variables de entorno requeridas por cada servidor activo",
|
|
7
|
+
"4. Agregar .mcp.json al repositorio (no contiene secretos — los secretos van en env vars)",
|
|
8
|
+
"5. Agregar a .gitignore cualquier archivo .mcp.local.json con credenciales"
|
|
9
|
+
],
|
|
10
|
+
"_nota_archivados": "Los reference servers @modelcontextprotocol/server-github, server-postgres, server-sqlite, server-brave-search y server-puppeteer fueron ARCHIVADOS por el proyecto MCP. No usarlos en proyectos nuevos — los reemplazos vigentes están abajo (GitHub remoto oficial, Playwright oficial de Microsoft).",
|
|
11
|
+
"mcpServers": {
|
|
12
|
+
"context7": {
|
|
13
|
+
"_descripcion": "Documentación actualizada de librerías. Uso: 'use context7' en el prompt.",
|
|
14
|
+
"command": "npx",
|
|
15
|
+
"args": ["-y", "@upstash/context7-mcp@latest"]
|
|
16
|
+
},
|
|
17
|
+
"github": {
|
|
18
|
+
"_descripcion": "GitHub MCP server oficial (remoto): issues, PRs, repos, commits. Reemplaza al archivado @modelcontextprotocol/server-github. Autenticación OAuth al conectar, o PAT vía header.",
|
|
19
|
+
"type": "http",
|
|
20
|
+
"url": "https://api.githubcopilot.com/mcp/"
|
|
21
|
+
},
|
|
22
|
+
"playwright": {
|
|
23
|
+
"_descripcion": "Control de navegador con Playwright (oficial de Microsoft). Testing E2E, scraping, automatización web. Reemplaza al archivado server-puppeteer.",
|
|
24
|
+
"_activar": "Requiere Node 18+ — descarga browsers en el primer uso",
|
|
25
|
+
"command": "npx",
|
|
26
|
+
"args": ["-y", "@playwright/mcp@latest"]
|
|
27
|
+
},
|
|
28
|
+
"filesystem": {
|
|
29
|
+
"_descripcion": "Acceso a sistema de archivos fuera del directorio de trabajo. Usar con cuidado.",
|
|
30
|
+
"_activar": "Descomentar solo si se necesita acceso a paths fuera del proyecto",
|
|
31
|
+
"command": "npx",
|
|
32
|
+
"args": [
|
|
33
|
+
"-y",
|
|
34
|
+
"@modelcontextprotocol/server-filesystem",
|
|
35
|
+
"/ruta/al/directorio/permitido"
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
"fetch": {
|
|
39
|
+
"_descripcion": "Extracción y conversión de contenido web a markdown.",
|
|
40
|
+
"_activar": "Útil cuando WebFetch nativo no basta (contenido que requiere conversión estructurada)",
|
|
41
|
+
"command": "npx",
|
|
42
|
+
"args": ["-y", "@modelcontextprotocol/server-fetch"]
|
|
43
|
+
},
|
|
44
|
+
"memory": {
|
|
45
|
+
"_descripcion": "Memoria persistente entre sesiones. Almacena entidades y relaciones en grafo.",
|
|
46
|
+
"_activar": "Útil para proyectos largos donde se quiere persistir contexto entre sesiones",
|
|
47
|
+
"command": "npx",
|
|
48
|
+
"args": ["-y", "@modelcontextprotocol/server-memory"]
|
|
49
|
+
},
|
|
50
|
+
"sequential-thinking": {
|
|
51
|
+
"_descripcion": "Herramienta de razonamiento estructurado para problemas complejos.",
|
|
52
|
+
"_activar": "Útil para arquitectura, debugging complejo, decisiones de diseño",
|
|
53
|
+
"command": "npx",
|
|
54
|
+
"args": ["-y", "@modelcontextprotocol/server-sequential-thinking"]
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: extractor-de-aprendizajes
|
|
3
3
|
description: Convertir errores y patrones descubiertos durante la implementación en nuevas habilidades o reglas. Ciclo de mejora continua del sistema SWL.
|
|
4
|
-
version: "1.0.
|
|
4
|
+
version: "1.0.6"
|
|
5
5
|
herramientasPermitidas: [Read]
|
|
6
6
|
exclusiones:
|
|
7
7
|
- "No cargar para actualizar el perfil del usuario — las correcciones explícitas del usuario van a `instintos/perfil-usuario.yaml` vía `perfilador-usuario-swl`, no a APRENDIZAJES.md."
|
|
@@ -10,10 +10,10 @@ exclusiones:
|
|
|
10
10
|
- "No cargar si el aprendizaje no tiene causa raíz identificada — documentar síntoma sin causa produce reglas que no previenen el error real."
|
|
11
11
|
evolvable: true # default para skill estandar
|
|
12
12
|
evolved: true
|
|
13
|
-
evolved-from: "1.0.
|
|
14
|
-
evolved-at: "2026-
|
|
13
|
+
evolved-from: "1.0.5"
|
|
14
|
+
evolved-at: "2026-06-11"
|
|
15
15
|
evolved-by: "aprender"
|
|
16
|
-
evolved-note: "
|
|
16
|
+
evolved-note: "Modo D del gotcha sub-agentes (CONFIRMADO x5 → x6): agentes de documentación (claude-code-guide) emiten veredictos NO-SOPORTADO por inferencia del contexto local sin consultar la doc oficial; exigir cita a doc consultada en el turno. Precedente 2026-05-15 (runtimes Cursor/Codex)"
|
|
17
17
|
---
|
|
18
18
|
# Extractor de Aprendizajes
|
|
19
19
|
|
|
@@ -296,7 +296,7 @@ Durante `/swl:aprender`, aplicar estas reglas:
|
|
|
296
296
|
- **`rating: HIGH` asignado sin verificar criterio de irreversibilidad**: el agente promueve a CLAUDE.md un aprendizaje "MEDIUM" por el entusiasmo del momento. Causa: no se aplicó el criterio de "decisión irreversible o bug crítico". Solución: antes de asignar HIGH, verificar: ¿cambiar esto en el futuro requeriría refactorizar múltiples archivos o migrar datos? Si no, mantener MEDIUM.
|
|
297
297
|
- **Regla incompleta sobre registro de hooks**: una entrada en memoria dice "registrar en modulos.json" pero omite `hooks-config.json`, y en la siguiente iteración se repite el fallo en CI porque ambos manifiestos son obligatorios. Causa: la regla de la lección anterior no cubrió todos los manifiestos afectados. Solución: al documentar una regla sobre registro en manifiestos, listar EXPLÍCITAMENTE cada manifiesto con su responsabilidad distinta (`modulos.json` = qué copiar; `hooks-config.json` = cómo registrar evento). Evidencia: tres incidentes históricos del mismo patrón incompleto (v5.7.1, v5.7.2/3, v5.11.0).
|
|
298
298
|
- **Inventario estimado a mano en vez de regenerar**: el agente cuenta "28 hooks" visualmente y propaga la cifra a 5 archivos (CLAUDE/README/package/plugin/SALUD); al regenerar con `scripts/generar-inventario.js` el número real es 30. Causa: confiar en la observación directa en vez de la fuente de verdad determinista. Solución: antes de modificar cualquier contador en documentación oficial, ejecutar el script de inventario y usar su salida como ground truth.
|
|
299
|
-
- **Sub-agentes (Explore + revisores) reportan afirmaciones factuales no verificadas
|
|
299
|
+
- **Sub-agentes (Explore + revisores + agentes de documentación) reportan afirmaciones factuales no verificadas** [CONFIRMADO x6]: aplica a `Explore`, `revisor-codigo-swl`, `revisor-seguridad-swl`, `investigador-swl`, `planificador-swl`, `claude-code-guide`, y en general a cualquier sub-agente que reporte hallazgos sobre código o capacidades de herramientas. **Cuatro modos de falla observados**:
|
|
300
300
|
|
|
301
301
|
**Modo A — papers académicos** (sesión 2026-04-25): sub-agente Explore propuso 50h+ para implementar SPRT + Lyapunov + compositionality theorem del paper Bhardwaj 2026; costo real validado fue ~5h (solo Drift Score + Recovery Catalog). Causa: el Explore evalúa portabilidad técnica sin aplicar filtro de "datos disponibles" ni "infraestructura zero-deps". Evidencia: 3 papers analizados (evolver, Bhardwaj 2026, Zhang et al. 2026) con descarte sistemático ~70-90% del contenido propuesto.
|
|
302
302
|
|
|
@@ -304,6 +304,8 @@ Durante `/swl:aprender`, aplicar estas reglas:
|
|
|
304
304
|
|
|
305
305
|
**Modo C — revisores reportan ubicaciones y severidades incorrectas en código del proyecto** (sesión 2026-05-12 SIGM): `revisor-codigo-swl` ejecutado en `/swl:verificar --until-converge` reportó dos errores factuales: (1) **ubicación incorrecta**: "deferred import en `caja/router.py:545`" cuando la línea real estaba en `caja/service.py:545` — el archivo `caja/router.py` solo tiene 157 líneas (`wc -l caja/router.py = 157`); (2) **severidad subestimada**: reportó "mismatch `CobroConsolidadoResponse` en pantalla de éxito" como MAYOR, mi auditoría manual descubrió que `CobroConsolidadoRequest` también estaba completamente desalineado (más grave, debería ser CRÍTICO bloqueante) — el revisor solo miró el Response. Causa: el revisor analiza código sin re-verificar el path/línea/extensión reportada cuando produce el reporte; sub-agentes basados en LLM hallucinan números de línea con frecuencia ≥15% en archivos grandes.
|
|
306
306
|
|
|
307
|
+
**Modo D — agentes de documentación responden por inferencia del contexto local sin consultar la fuente oficial** (sesión 2026-06-11 swl-ses Fase 09; precedente 2026-05-15 con runtimes Cursor/Codex): `claude-code-guide` emitió veredicto categórico "Claude Code NO soporta carga condicional por `paths:` en rules; el frontmatter sería inerte" basándose en que la config local del usuario no usaba ese campo (declinó el WebFetch a docs). Un WebFetch directo a `code.claude.com/docs/en/memory` demostró lo contrario: `paths:` es feature nativa documentada con sintaxis exacta, brace expansion y soporte user-level. Aceptar el veredicto habría descartado un slice completo de la fase. Causa: "ausencia de evidencia en el contexto local" tratada como "evidencia de ausencia en el producto" — mismo patrón del precedente 2026-05-15 ("Cursor no soporta hooks" — falso). Las features recientes nunca aparecen en configs existentes precisamente por ser recientes.
|
|
308
|
+
|
|
307
309
|
**Solución unificada — protocolo de verificación de afirmaciones factuales antes de aceptar propuesta de CUALQUIER sub-agente**:
|
|
308
310
|
|
|
309
311
|
*Patrón obligatorio aplicable a TODOS los modos*: extraer 2-3 afirmaciones factuales del reporte del sub-agente y verificar cada una con primitivas baratas (`Grep`/`Read`/`wc -l`/`ls`/`git log`) ANTES de aceptar el plan o acción. Tipos de afirmaciones a verificar:
|
|
@@ -317,6 +319,8 @@ Durante `/swl:aprender`, aplicar estas reglas:
|
|
|
317
319
|
*Para repos externos (Modo B)*: 4 filtros adicionales: (1) ¿qué % es teoría/código no-portable vs portable? — si >70% no-portable, recortar; (2) **¿la propuesta reescribe mecanismos existentes en el proyecto destino?** — VERIFICAR con `Grep`/`Read` 2-3 afirmaciones concretas del agente contra el código real ANTES de aceptar; (3) ¿LOC nuevas estimadas vs reutilizar lo existente? — si la propuesta supera 500 LOC para un solo patrón, hay sobre-ingeniería; (4) ¿el alcance reducido cubre 80% del valor? — Pareto.
|
|
318
320
|
|
|
319
321
|
*Para revisores de código (Modo C)*: además del patrón obligatorio, **re-clasificar severidad cuando el revisor solo miró parte del flujo**. Si el revisor marca MAYOR un bug del Response, verificar si el Request también está afectado — los happy paths típicamente involucran ambos lados.
|
|
322
|
+
|
|
323
|
+
*Para agentes de documentación (Modo D)*: todo veredicto **NO-EXISTE / NO-SOPORTADO** sobre una feature de un producto externo exige cita a la doc oficial consultada EN ese turno (URL + extracto). Si el agente "verifica" solo contra el contexto local (configs del usuario, código del repo), su veredicto es inferencia, no verificación — re-verificar con 1 WebFetch a la doc oficial antes de tomar decisiones de diseño sobre él. Regla mnemónica: *ausencia en mi config ≠ ausencia en el producto*.
|
|
320
324
|
- **Hooks de calidad pre-commit bloquean fixtures de tests como falsos positivos**: el hook `calidad-pre-commit.js` aplica regex `\b(api_key|password|token|secret)\s*[=:]\s*["'][^"'\s]{4,}["']` que matchea fixtures legítimos en archivos de test. Caso real: test que valida que la función `sanitizar()` redacta `api_key="abc12345xyz"` se bloquea. Causa: el hook no distingue contexto de test vs producción. Solución: en archivos de test, construir fixtures con concatenación de strings (`'api' + '_key'`, `'pass' + 'word'`) o agregar marcador placeholder reconocido por el hook (`fake_`, `dummy_`, `placeholder`, `example`, `os.environ`). NUNCA bypassear el hook con `--no-verify` — el detector cumple su función; ajustar el fixture es lo correcto.
|
|
321
325
|
- **Regex de path-matching `/[\\/]<dir>[\\/]/` falla con paths relativos sin slash inicial** [CONFIRMADO x4]: hooks que filtran archivos por directorio (ej: `hooks/extraccion-aprendizajes.js` con `PATRONES_ARCHIVO_SWL_EXCLUIDO`) usan patrones que requieren un separator ANTES del nombre. Caso real: path `scripts/lib/foo.js` (sin slash inicial) eludía el filtro de exclusión y generaba placeholders espurios en APRENDIZAJES.md cada vez que se hacía `Edit` o `Write` sobre archivos del sistema SWL. Causa: el regex `[\\/]` requiere un caracter slash/backslash previo; cuando el path empieza con el nombre del directorio directamente, no matchea. Solución: usar `/(?:^|[\\/])<dir>[\\/]/` para aceptar tanto el inicio del string como un separator previo. Evidencia: 4 placeholders eliminados manualmente entre v1.3.3-v1.3.5 antes de identificar la causa raíz; fix endurecido aplicado en v1.3.5 (Fix I).
|
|
322
326
|
- **`git ls-files` es preferible a `fs.readdir` recursivo para tests anti-regresión que escanean el repo**: usar `execSync('git ls-files')` limita el escaneo a archivos versionados — evita `node_modules/`, `.git/`, `_userland/`, archivos temporales y backups sin enumerar exclusiones. Caso real: `tests/scripts/no-legacy-npx-pattern.test.js` v1.3.6 escanea 1000+ archivos versionados en <200ms; el equivalente con `fs.readdir` recursivo más exclusiones manuales sería más lento y propenso a olvidar paths. Cuando el test es de "calidad del repo" (no de comportamiento), `git ls-files` es la primitiva correcta.
|
|
@@ -5,12 +5,12 @@ description: >
|
|
|
5
5
|
testing con httpx. Incluye el anti-patrón crítico MissingGreenlet (lazy loading
|
|
6
6
|
en async). Cargar cuando se implementen endpoints FastAPI, schemas Pydantic v2,
|
|
7
7
|
queries SQLAlchemy async, WebSockets, SSE o tests de integración con httpx.
|
|
8
|
-
version: "1.3.
|
|
8
|
+
version: "1.3.1"
|
|
9
9
|
evolved: true
|
|
10
|
-
evolved-from: "1.
|
|
11
|
-
evolved-at: "2026-
|
|
12
|
-
evolved-by: "
|
|
13
|
-
evolved-note: "
|
|
10
|
+
evolved-from: "1.3.0"
|
|
11
|
+
evolved-at: "2026-06-04"
|
|
12
|
+
evolved-by: "evolucionar"
|
|
13
|
+
evolved-note: "3 patrones nuevos OIC v1.5 2026-06-04: handler logging defensivo con sesión SQLAlchemy desacoplada (PE-001); tests pytest cuelgan si handler abre engine con pool_pre_ping al startup sin BD + receta conftest (PE-002); tests de endpoint sin BD con dependency_overrides[get_db]=lambda:None + monkeypatch del service (PE-008)"
|
|
14
14
|
herramientasPermitidas: [Read]
|
|
15
15
|
exclusiones:
|
|
16
16
|
- "No cargar para proyectos Django o Flask — los patrones de ORM sync, Class-Based Views y middleware difieren fundamentalmente; cargar `django-experto` o el skill del framework correspondiente."
|
|
@@ -267,6 +267,57 @@ Beneficios:
|
|
|
267
267
|
|
|
268
268
|
Regla: para cualquier whitelist usada en `setattr` ciego (PATCH endpoints, factory methods, deserializadores manuales), declarar como `ClassVar[frozenset[str]]` de la clase del service. NUNCA como variable local del método. NUNCA como módulo-level constant fuera de la clase (pierde el namespacing).
|
|
269
269
|
|
|
270
|
+
- **Handler logging que persiste en BD durante manejo de excepciones — SIEMPRE usar sesión SQLAlchemy desacoplada + silenciar fallos** (patrón portable; caso real OIC v1.5 BitacoraErrorHandler 2026-06-04): si un `logging.Handler` custom (audit trail, Sentry-style, métricas async, observabilidad) usa la sesión del request para persistir el evento, durante una excepción HTTP la sesión está en estado roto y `session.add()` falla, perdiendo la excepción original. Patrón correcto:
|
|
271
|
+
```python
|
|
272
|
+
# Engine PROPIO independiente del pool del request (pool=2 suficiente).
|
|
273
|
+
engine = create_engine(settings.DATABASE_URL, pool_pre_ping=True, pool_size=2, max_overflow=2)
|
|
274
|
+
session_factory = sessionmaker(bind=engine, autocommit=False, autoflush=False)
|
|
275
|
+
|
|
276
|
+
class MiHandler(logging.Handler):
|
|
277
|
+
def emit(self, record):
|
|
278
|
+
try:
|
|
279
|
+
self._emit_unsafe(record)
|
|
280
|
+
except Exception: # noqa: BLE001 — silencio defensivo intencional
|
|
281
|
+
# NUNCA loggear con `logging` desde aquí (riesgo de recursión infinita).
|
|
282
|
+
pass
|
|
283
|
+
|
|
284
|
+
def _emit_unsafe(self, record):
|
|
285
|
+
sess = session_factory() # sesión NUEVA, no la del request
|
|
286
|
+
try:
|
|
287
|
+
sess.add(entry); sess.commit()
|
|
288
|
+
finally:
|
|
289
|
+
sess.close()
|
|
290
|
+
```
|
|
291
|
+
Reglas clave: (a) engine propio; (b) `try/except: pass` agresivo en `emit()`; (c) NUNCA emitir a logger propio; (d) filtrar loggers ruidosos por nombre (`sqlalchemy.*`, `uvicorn.access`, `httpx`, `httpcore`, `asyncio`, `urllib3`); (e) idempotente: verificar si ya está en `root.handlers` antes de registrar. Aplicable a Sentry-style integrations, audit handlers, métricas async, alertas.
|
|
292
|
+
|
|
293
|
+
- **Tests pytest se cuelgan al importar `app.main` cuando un handler abre engine BD con `pool_pre_ping=True` al startup** (gotcha crítico OIC v1.5 2026-06-04): si un handler de logging custom se instala en `setup_logging()` y construye un engine con `pool_pre_ping=True`, sin PostgreSQL corriendo SQLAlchemy intenta una query de verificación en `socket.connect()` infinito. El test no falla — se cuelga sin output (ni siquiera el header de pytest). Causa: el bloqueo ocurre en la **importación** del módulo `app.main` (que llama `setup_logging()`), no en el test mismo. Síntoma típico: 3+ invocaciones de `pytest` en background sin output, requiere matar `python.exe` manualmente. Solución obligatoria en `backend/tests/conftest.py`:
|
|
294
|
+
```python
|
|
295
|
+
# ANTES de importar app.main
|
|
296
|
+
os.environ.setdefault("ENV", "test")
|
|
297
|
+
os.environ.setdefault("SKIP_DB_HEALTHCHECK", "true")
|
|
298
|
+
# Por CADA handler del proyecto que abre engine al startup:
|
|
299
|
+
os.environ.setdefault("SWL_BITACORA_ERRORES_ENABLED", "false")
|
|
300
|
+
# (sustituir por la env var real del proyecto)
|
|
301
|
+
```
|
|
302
|
+
Regla: cualquier handler con `pool_pre_ping=True` en su engine debe tener un kill-switch env var, y el conftest debe deshabilitarlo. Sin esto, los tests del proyecto serán inviables sin BD real.
|
|
303
|
+
|
|
304
|
+
- **Tests de endpoint sin BD con `dependency_overrides[get_db]=lambda:None` + monkeypatch del service** (patrón portable validado OIC v1.5 Slice 4 2026-06-04): para tests de endpoint que verifican contrato HTTP (auth, validación de query params, estructura de respuesta, rate-limit, headers de export CSV) sin requerir PostgreSQL. 25 tests en 0.23s.
|
|
305
|
+
```python
|
|
306
|
+
@pytest.fixture
|
|
307
|
+
def client_admin(monkeypatch: pytest.MonkeyPatch) -> TestClient:
|
|
308
|
+
app.dependency_overrides[requiere_admin] = _fake_admin # stub user
|
|
309
|
+
app.dependency_overrides[get_db] = lambda: None # type: ignore[return-value]
|
|
310
|
+
# Mock del service: el endpoint llama service.metodo(db, ...) pero `db` es None;
|
|
311
|
+
# el service no debe ejecutarse — se reemplaza con fake que devuelve schema válido.
|
|
312
|
+
from app.services import mi_service
|
|
313
|
+
monkeypatch.setattr(mi_service, "listar_paginado",
|
|
314
|
+
lambda db, filtros, page, per_page: SchemaPage(items=[], total=0, ...))
|
|
315
|
+
with TestClient(app) as c:
|
|
316
|
+
yield c
|
|
317
|
+
app.dependency_overrides.clear()
|
|
318
|
+
```
|
|
319
|
+
Aplicabilidad: cualquier endpoint que dependa de `get_db` + service mockeable. NO requiere BD real ni fixtures de datos. Tests de integración con BD viven aparte (`@pytest.mark.integration`).
|
|
320
|
+
|
|
270
321
|
## Referencias especializadas
|
|
271
322
|
|
|
272
323
|
| Tema | Archivo |
|