@saulwade/swl-ses 1.3.8 → 1.4.1
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 +15 -6
- package/README.md +15 -14
- package/agentes/nemesis-auditor-swl.md +161 -0
- package/bin/swl-mcp-server.js +187 -187
- package/bin/swl-webhook-server.js +198 -0
- package/comandos/swl/.evolved.json +22 -22
- package/comandos/swl/adoptar-proyecto.md +21 -1
- package/comandos/swl/claudemd.md +14 -1
- package/comandos/swl/contribuir.md +233 -233
- package/comandos/swl/exportar-vault.md +108 -0
- package/comandos/swl/nemesis.md +122 -0
- package/comandos/swl/nuevo-proyecto.md +24 -2
- package/comandos/swl/salud.md +34 -0
- package/comandos/swl/verificar.md +45 -0
- package/gateway/adapters/base.js +109 -0
- package/gateway/adapters/discord.js +167 -0
- package/gateway/adapters/email.js +221 -0
- package/gateway/adapters/slack.js +192 -0
- package/gateway/adapters/telegram.js +183 -0
- package/gateway/adapters/webhook.js +113 -0
- package/gateway/adapters/whatsapp.js +214 -0
- package/gateway/agent-executor.js +322 -0
- package/gateway/command-relay.js +271 -0
- package/gateway/cron/jobs.js +263 -0
- package/gateway/cron/scheduler.js +322 -0
- package/gateway/cron/store.js +335 -0
- package/gateway/index.js +320 -0
- package/gateway/lib/event-channel.js +191 -0
- package/gateway/session.js +131 -0
- package/gateway/webhook-server.js +324 -0
- package/habilidades/backend-production-resilience/SKILL.md +288 -288
- package/habilidades/benchmark-memoria/SKILL.md +186 -186
- package/habilidades/build-errors-nextjs/SKILL.md +55 -1
- package/habilidades/diagrama-arquitectura/assets/template.html +276 -276
- package/habilidades/doubt-driven-review/SKILL.md +171 -171
- package/habilidades/doubt-driven-review/recursos/EXAMPLES.md +130 -130
- package/habilidades/eval-framework/SKILL.md +212 -212
- package/habilidades/extractor-de-aprendizajes/SKILL.md +20 -10
- package/habilidades/feynman-auditor-swl/SKILL.md +123 -0
- package/habilidades/feynman-auditor-swl/recursos/preguntas-language-agnostic.md +108 -0
- package/habilidades/harness-claude-code/SKILL.md +299 -299
- package/habilidades/infra-github-actions/SKILL.md +166 -166
- package/habilidades/legacy-code-rescue/SKILL.md +267 -267
- package/habilidades/manejo-errores/.evolved.json +8 -8
- package/habilidades/meta-skills-estandar/recursos/convencion-examples.md +93 -93
- package/habilidades/meta-skills-estandar/recursos/skills-as-agents.md +163 -163
- package/habilidades/nextjs-testing/SKILL.md +89 -5
- package/habilidades/node-experto/SKILL.md +37 -1
- package/habilidades/patrones-python/SKILL.md +229 -229
- package/habilidades/patrones-python/recursos/patrones-avanzados.md +469 -469
- package/habilidades/planear-fase/SKILL.md +319 -319
- package/habilidades/react-experto/SKILL.md +45 -4
- package/habilidades/release-semver/.evolved.json +8 -8
- package/habilidades/state-inconsistency-auditor-swl/SKILL.md +166 -0
- package/habilidades/state-inconsistency-auditor-swl/recursos/coupled-state-patterns.md +147 -0
- package/habilidades/tdd-workflow/SKILL.md +36 -4
- package/habilidades/testing-python/SKILL.md +340 -340
- package/habilidades/web-fetcher-routing/SKILL.md +75 -0
- package/hooks/claudemd-bloat-detector.js +161 -161
- package/hooks/inyeccion-contexto.js +8 -3
- package/hooks/lib/agent-routing.js +107 -107
- package/hooks/lib/auto-consolidator.js +335 -335
- package/hooks/lib/error-classifier.js +308 -308
- package/hooks/lib/merkle-audit.js +96 -96
- package/hooks/lib/provenance-tracker.js +191 -191
- package/hooks/lib/rate-limit-ip.js +177 -0
- package/hooks/lib/rate-limit-tracker.js +253 -253
- package/hooks/lib/resource-quota.js +122 -122
- package/hooks/lib/retry-jitter.js +165 -165
- package/hooks/lib/security-net.js +201 -0
- package/hooks/lib/skill-auditor.js +588 -588
- package/hooks/lib/sync-status.js +228 -228
- package/hooks/lib/taint-tracker.js +107 -107
- package/hooks/lib/text-similarity.js +241 -241
- package/hooks/lib/toon-compressor.js +245 -245
- package/hooks/lib/webhook-dedup.js +184 -0
- package/hooks/lib/webhook-verify.js +123 -0
- package/hooks/proteccion-rutas.js +120 -15
- package/hooks/registro-turnos.js +209 -209
- package/hooks/sugerir-regenerar-inventario.js +170 -170
- package/hooks/validar-formato-post-subagente.js +140 -140
- package/hooks/validar-memoria-hook.js +218 -218
- package/instintos/prompt-appendices.yaml +57 -57
- package/manifiestos/agent-output-schemas.json +57 -57
- package/manifiestos/modulos.json +31 -0
- package/manifiestos/skills-lock.json +1114 -1093
- package/package.json +6 -4
- package/plantillas/auditor-veto-template.md +105 -105
- package/plantillas/github-workflows/README.md +47 -47
- package/plantillas/github-workflows/release-please.yml +44 -44
- package/plantillas/github-workflows/swl-ci.yml +107 -107
- package/plantillas/github-workflows/swl-security.yml +51 -51
- package/plugin.json +2 -2
- package/reglas/analisis-previo-tareas-grandes.md +172 -172
- package/reglas/arreglar-al-detectar.md +147 -147
- package/reglas/fragmentos-compartidos.md +152 -152
- package/reglas/harness-claude-code.md +213 -213
- package/reglas/usar-context7.md +226 -226
- package/reglas/usar-sistema-swl.md +251 -0
- package/schemas/diary-entry.schema.json +80 -80
- package/scripts/audit-tools/audit-history.js +330 -0
- package/scripts/audit-tools/bundle-tracker.js +290 -0
- package/scripts/audit-tools/canary-monitor.js +352 -0
- package/scripts/audit-tools/code-profiler.js +605 -0
- package/scripts/audit-tools/dep-doctor.js +320 -0
- package/scripts/audit-tools/env-validator.js +206 -0
- package/scripts/audit-tools/lib/fs-walk.js +48 -0
- package/scripts/audit-tools/lib/output.js +23 -0
- package/scripts/audit-tools/migration-checker.js +392 -0
- package/scripts/audit-tools/pentest-scanner.js +1436 -0
- package/scripts/benchmark-memoria.js +167 -167
- package/scripts/comandos/skills.js +251 -2
- package/scripts/configurar-branch-protection.js +418 -418
- package/scripts/detectar-aprendizajes-duplicados.js +151 -151
- package/scripts/field-report.js +199 -199
- package/scripts/generar-checklists-consolidados.js +273 -273
- package/scripts/generar-inventario.js +420 -420
- package/scripts/generar-matriz-lenguajes.js +271 -271
- package/scripts/lib/artefactos-python.js +43 -43
- package/scripts/lib/benchmark-metrics.js +160 -160
- package/scripts/lib/budget-enforcer.js +252 -252
- package/scripts/lib/configurar-ci.js +380 -380
- package/scripts/lib/contadores-inventario.js +217 -217
- package/scripts/lib/detectar-stack-detallado.js +307 -307
- package/scripts/lib/diary-entry.js +234 -234
- package/scripts/lib/eval-metrics-store.js +218 -218
- package/scripts/lib/eval-quality.js +171 -171
- package/scripts/lib/eval-schemas.js +144 -144
- package/scripts/lib/eval-self-correct.js +106 -106
- package/scripts/lib/eval-validator.js +185 -185
- package/scripts/lib/jaccard-similarity.js +98 -98
- package/scripts/lib/longmemeval-runner.js +125 -125
- package/scripts/lib/npm-version.js +261 -261
- package/scripts/lib/paquetes-conocidos.js +50 -50
- package/scripts/lib/prompt-builder.js +264 -264
- package/scripts/lib/rrf-fusion.js +175 -175
- package/scripts/lib/scoring-instintos.js +277 -277
- package/scripts/lib/semantic-search.js +252 -252
- package/scripts/limpiar-artefactos-python.js +131 -131
- package/scripts/mcp-server/README.md +128 -128
- package/scripts/mcp-server/handlers.js +206 -206
- package/scripts/migrar-csv-a-array.js +168 -168
- package/scripts/migrar-fase-dominio.js +201 -201
- package/scripts/publicar.js +511 -511
- package/scripts/run-eval.js +141 -141
- package/scripts/validar-manifest.js +195 -195
- package/scripts/validar-userland-vacio.js +110 -110
- package/scripts/verificar-release.js +110 -0
package/comandos/swl/claudemd.md
CHANGED
|
@@ -117,6 +117,17 @@ Si ya existe, NO lo sobreescribe — sugiere añadir secciones faltantes.
|
|
|
117
117
|
Detecta el stack del proyecto actual con `scripts/lib/detectar-stack-detallado.js`
|
|
118
118
|
y genera `./CLAUDE.md` mínimo con:
|
|
119
119
|
|
|
120
|
+
- Sección **Reglas obligatorias** que **DEBE** incluir como primera línea
|
|
121
|
+
bajo el encabezado:
|
|
122
|
+
```markdown
|
|
123
|
+
## Reglas obligatorias
|
|
124
|
+
|
|
125
|
+
@reglas/usar-sistema-swl.md
|
|
126
|
+
```
|
|
127
|
+
Esta referencia es obligatoria — fuerza que el agente cargue la matriz
|
|
128
|
+
operacional de uso del sistema SWL al inicio de cada sesión. Si el proyecto
|
|
129
|
+
tiene otras reglas locales (`@reglas/seguridad.md`, `@reglas/arquitectura.md`,
|
|
130
|
+
etc.), agregarlas debajo.
|
|
120
131
|
- Sección **Stack** poblada (lenguaje, framework, ORM, package manager)
|
|
121
132
|
- Sección **Comandos** poblada (npm scripts detectados o comandos típicos)
|
|
122
133
|
- Sección **Code style** vacía con placeholders
|
|
@@ -125,7 +136,9 @@ y genera `./CLAUDE.md` mínimo con:
|
|
|
125
136
|
`README.md`, etc. si existen
|
|
126
137
|
|
|
127
138
|
Si CLAUDE.md ya existe, **NO lo sobreescribe**. Sugiere correr
|
|
128
|
-
`/swl:claudemd refactor` para mejorar el actual.
|
|
139
|
+
`/swl:claudemd refactor` para mejorar el actual. Si detecta que el CLAUDE.md
|
|
140
|
+
existente NO incluye `@reglas/usar-sistema-swl.md`, emitir hallazgo WARN
|
|
141
|
+
recomendando agregarlo manualmente.
|
|
129
142
|
|
|
130
143
|
## Variables de entorno
|
|
131
144
|
|
|
@@ -1,233 +1,233 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: swl:contribuir
|
|
3
|
-
description: Contribuye evoluciones de _userland/ al core de swl-ses creando un PR en GitHub. Filtra por dominio (solo ingeniería de software general), evalúa calidad con PluginEval (score ≥80 requerido) y crea el PR vía gh CLI. Flags: --skill=[nombre], --agente=[nombre], --dry-run.
|
|
4
|
-
allowed_tools: ["Read", "Write", "Edit", "Bash", "Glob", "Grep", "Agent"]
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# /swl:contribuir — Contribuir evoluciones al core de swl-ses
|
|
8
|
-
|
|
9
|
-
Eres el facilitador de contribuciones del sistema SWL. Tu responsabilidad es tomar evoluciones que un usuario creó en `_userland/` y, si pasan los filtros de calidad y dominio, crear un Pull Request contra el repositorio oficial de swl-ses.
|
|
10
|
-
|
|
11
|
-
**Principio**: las evoluciones específicas de un proyecto se quedan en `_userland/` — solo evoluciones de dominio general pasan al core. Un skill de "configuración de Stripe para mi SaaS" no sube; un skill de "patrones de testing de APIs de pago" sí.
|
|
12
|
-
|
|
13
|
-
## Cuándo usar este comando
|
|
14
|
-
|
|
15
|
-
- Cuando el usuario evolucionó un agente o skill en `_userland/` y quiere compartirlo con la comunidad
|
|
16
|
-
- Después de `/swl:evolucionar` cuando el cambio aplica a cualquier proyecto de software
|
|
17
|
-
- Cuando se creó un skill nuevo con `/swl:crear-skill` que resuelve un problema general de ingeniería
|
|
18
|
-
|
|
19
|
-
## Prerrequisitos
|
|
20
|
-
|
|
21
|
-
1. **GitHub CLI (`gh`) autenticado** — verificar con `gh auth status`
|
|
22
|
-
2. **Evolución marcada** — el artefacto debe tener `evolved: true` en frontmatter o existir en `_userland/`
|
|
23
|
-
3. **Repositorio swl-ses accesible** — se necesita permiso de fork/PR
|
|
24
|
-
|
|
25
|
-
## Flags soportados
|
|
26
|
-
|
|
27
|
-
```
|
|
28
|
-
--skill=[nombre] Contribuir solo el skill indicado de _userland/habilidades/
|
|
29
|
-
--agente=[nombre] Contribuir solo el agente indicado de _userland/agentes/
|
|
30
|
-
--dry-run Ejecutar validaciones y evaluación sin crear PR
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
Si no se pasa flag, escanea todo `_userland/` buscando candidatos.
|
|
34
|
-
|
|
35
|
-
## Paso 0 — Verificar prerrequisitos
|
|
36
|
-
|
|
37
|
-
Verificar que `gh` está instalado y autenticado:
|
|
38
|
-
|
|
39
|
-
```bash
|
|
40
|
-
gh auth status
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
Si falla:
|
|
44
|
-
- **No instalado**: indicar al usuario que instale GitHub CLI (ver MANUAL_USO.md § Dependencias externas)
|
|
45
|
-
- **No autenticado**: indicar al usuario que ejecute `! gh auth login` desde el prompt de Claude Code
|
|
46
|
-
|
|
47
|
-
DETENER si `gh auth status` no reporta una cuenta autenticada.
|
|
48
|
-
|
|
49
|
-
## Paso 1 — Escanear candidatos en _userland/
|
|
50
|
-
|
|
51
|
-
Buscar artefactos en `_userland/habilidades/` y `_userland/agentes/`:
|
|
52
|
-
|
|
53
|
-
```bash
|
|
54
|
-
# Skills con SKILL.md
|
|
55
|
-
for dir in _userland/habilidades/*/; do
|
|
56
|
-
[ -f "$dir/SKILL.md" ] && echo "skill: $(basename $dir)"
|
|
57
|
-
done
|
|
58
|
-
|
|
59
|
-
# Agentes con .md
|
|
60
|
-
for f in _userland/agentes/*.md; do
|
|
61
|
-
[ -f "$f" ] && echo "agente: $(basename $f .md)"
|
|
62
|
-
done
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
Si se pasó `--skill` o `--agente`, filtrar a solo ese candidato.
|
|
66
|
-
|
|
67
|
-
Si no hay candidatos, informar:
|
|
68
|
-
```
|
|
69
|
-
No se encontraron evoluciones en _userland/ para contribuir.
|
|
70
|
-
Usa /swl:evolucionar o /swl:crear-skill para generar evoluciones primero.
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
## Paso 2 — Filtro de dominio
|
|
74
|
-
|
|
75
|
-
Para cada candidato, leer su contenido y evaluar compatibilidad de dominio.
|
|
76
|
-
|
|
77
|
-
**Pregunta de filtro**: *¿Le sirve esto a un ingeniero de software en cualquier proyecto de software?*
|
|
78
|
-
|
|
79
|
-
**Dominios aceptados** (ingeniería de software general):
|
|
80
|
-
- SDLC, backend, frontend, QA, DevOps, seguridad, arquitectura
|
|
81
|
-
- Testing, CI/CD, monitoreo, observabilidad
|
|
82
|
-
- Patrones de diseño, refactoring, revisión de código
|
|
83
|
-
- APIs, bases de datos, infraestructura cloud
|
|
84
|
-
|
|
85
|
-
**Dominios rechazados** (verticales específicos):
|
|
86
|
-
- ML/AI productivo, ciencia de datos, bioinformática
|
|
87
|
-
- Finanzas, contabilidad, legal
|
|
88
|
-
- Dominio de negocio específico del proyecto
|
|
89
|
-
|
|
90
|
-
Para cada candidato rechazado, explicar por qué:
|
|
91
|
-
```
|
|
92
|
-
RECHAZADO: [nombre] — dominio "[dominio detectado]" no es ingeniería de software general.
|
|
93
|
-
Las evoluciones específicas de dominio se mantienen en _userland/ del proyecto.
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
## Paso 3 — Evaluación PluginEval
|
|
97
|
-
|
|
98
|
-
Para cada candidato que pasó el filtro de dominio, ejecutar evaluación de calidad.
|
|
99
|
-
|
|
100
|
-
Cargar:
|
|
101
|
-
```
|
|
102
|
-
Skill("evaluacion-agentes")
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
Ejecutar evaluación completa (2 capas). El score mínimo para contribuir es **80/100** (badge Oro).
|
|
106
|
-
|
|
107
|
-
- **Score ≥ 80**: APROBADO — continuar al siguiente paso
|
|
108
|
-
- **Score 60-79**: RECHAZADO con recomendaciones de mejora
|
|
109
|
-
- **Score < 60**: RECHAZADO — necesita trabajo significativo
|
|
110
|
-
|
|
111
|
-
```
|
|
112
|
-
EVALUACIÓN: [nombre]
|
|
113
|
-
Capa 1 (estática): [N] errores, [N] advertencias
|
|
114
|
-
Capa 2 (semántica): [score]/100 — badge [badge]
|
|
115
|
-
Veredicto: [APROBADO | RECHAZADO]
|
|
116
|
-
[Si rechazado: top 3 mejoras recomendadas]
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
Si `--dry-run`: presentar resultados de evaluación y TERMINAR.
|
|
120
|
-
|
|
121
|
-
## Paso 4 — Preparar contribución
|
|
122
|
-
|
|
123
|
-
Para cada candidato aprobado:
|
|
124
|
-
|
|
125
|
-
1. **Guardar ruta del workspace original** antes de cambiar de directorio:
|
|
126
|
-
```bash
|
|
127
|
-
WORKSPACE_DIR=$(pwd)
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
2. **Crear fork** (si no existe) del repo oficial de swl-ses y obtener el nombre del fork:
|
|
131
|
-
```bash
|
|
132
|
-
gh repo fork saul-wade/swl-ses --clone=false
|
|
133
|
-
FORK_REPO=$(gh api user --jq '.login')/swl-ses
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
3. **Clonar el fork** y crear branch descriptivo:
|
|
137
|
-
```bash
|
|
138
|
-
gh repo clone "$FORK_REPO" /tmp/swl-ses-contrib
|
|
139
|
-
cd /tmp/swl-ses-contrib
|
|
140
|
-
git checkout -b contrib/[tipo]-[nombre]
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
4. **Copiar artefacto** desde el workspace original al clon del fork:
|
|
144
|
-
- Skills: `$WORKSPACE_DIR/_userland/habilidades/[nombre]/` → `habilidades/[nombre]/`
|
|
145
|
-
- Agentes: `$WORKSPACE_DIR/_userland/agentes/[nombre].md` → `agentes/[nombre].md`
|
|
146
|
-
|
|
147
|
-
4. **Ajustar frontmatter** — agregar campos de contribución:
|
|
148
|
-
```yaml
|
|
149
|
-
contributed: true
|
|
150
|
-
contributed-from: "_userland"
|
|
151
|
-
contributed-at: "[fecha YYYY-MM-DD]"
|
|
152
|
-
contributed-by: "[usuario gh]"
|
|
153
|
-
plugineval-score: [score]
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
5. **Registrar en plugin.json** si es necesario
|
|
157
|
-
|
|
158
|
-
## Paso 5 — Crear Pull Request
|
|
159
|
-
|
|
160
|
-
Crear el PR con template estructurado:
|
|
161
|
-
|
|
162
|
-
```bash
|
|
163
|
-
git add .
|
|
164
|
-
git commit -m "contrib([tipo]): agrega [nombre] desde _userland
|
|
165
|
-
|
|
166
|
-
Evaluado con PluginEval: [score]/100 (badge [badge]).
|
|
167
|
-
Dominio: ingeniería de software general.
|
|
168
|
-
|
|
169
|
-
Co-Authored-By: swl-ses <noreply@swl-ses>"
|
|
170
|
-
|
|
171
|
-
git push origin contrib/[tipo]-[nombre]
|
|
172
|
-
|
|
173
|
-
gh pr create \
|
|
174
|
-
--repo saul-wade/swl-ses \
|
|
175
|
-
--title "contrib([tipo]): [nombre]" \
|
|
176
|
-
--body "$(cat <<'EOF'
|
|
177
|
-
## Contribución desde _userland
|
|
178
|
-
|
|
179
|
-
**Tipo**: [skill | agente]
|
|
180
|
-
**Nombre**: [nombre]
|
|
181
|
-
**Dominio**: [dominio detectado]
|
|
182
|
-
**PluginEval**: [score]/100 — badge [badge]
|
|
183
|
-
|
|
184
|
-
## Descripción
|
|
185
|
-
|
|
186
|
-
[Descripción extraída del artefacto]
|
|
187
|
-
|
|
188
|
-
## Evidencia de calidad
|
|
189
|
-
|
|
190
|
-
- Capa 1 (estática): [N] errores, [N] advertencias
|
|
191
|
-
- Capa 2 (semántica): [score]/100
|
|
192
|
-
- Filtro de dominio: APROBADO (ingeniería de software general)
|
|
193
|
-
|
|
194
|
-
## Checklist
|
|
195
|
-
|
|
196
|
-
- [ ] Score PluginEval ≥ 80
|
|
197
|
-
- [ ] Dominio: ingeniería de software general
|
|
198
|
-
- [ ] Sin credenciales hardcodeadas
|
|
199
|
-
- [ ] Frontmatter válido
|
|
200
|
-
- [ ] No duplica skill/agente existente
|
|
201
|
-
|
|
202
|
-
---
|
|
203
|
-
Generado por `/swl:contribuir` — swl-ses v[versión]
|
|
204
|
-
EOF
|
|
205
|
-
)"
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
## Paso 6 — Reporte final
|
|
209
|
-
|
|
210
|
-
```
|
|
211
|
-
=== Contribución completada ===
|
|
212
|
-
|
|
213
|
-
Candidatos escaneados: [N]
|
|
214
|
-
Filtro de dominio: [N] aprobados, [N] rechazados
|
|
215
|
-
Evaluación PluginEval: [N] aprobados (≥80), [N] rechazados
|
|
216
|
-
PRs creados: [N]
|
|
217
|
-
|
|
218
|
-
[Para cada PR creado:]
|
|
219
|
-
→ [nombre]: [URL del PR]
|
|
220
|
-
|
|
221
|
-
Los PRs serán revisados por los mantenedores de swl-ses.
|
|
222
|
-
```
|
|
223
|
-
|
|
224
|
-
## Reglas de comportamiento
|
|
225
|
-
|
|
226
|
-
- NUNCA crear un PR sin que el candidato haya pasado AMBOS filtros (dominio + PluginEval ≥ 80).
|
|
227
|
-
- NUNCA contribuir artefactos que contengan credenciales, tokens o datos del proyecto del usuario.
|
|
228
|
-
- NUNCA modificar artefactos del core existente — solo agregar nuevos.
|
|
229
|
-
- Si el artefacto duplica funcionalidad de uno existente en el core, RECHAZAR y sugerir `/swl:evolucionar` en su lugar.
|
|
230
|
-
- Si `gh auth status` falla, DETENER inmediatamente — no intentar autenticación automática.
|
|
231
|
-
- En `--dry-run`, el reporte debe ser completo y accionable sin crear ningún PR.
|
|
232
|
-
- Los artefactos contribuidos mantienen su autoría original (campo `contributed-by`).
|
|
233
|
-
- SIEMPRE verificar que el nombre del artefacto no colisione con uno existente en el core antes de crear el PR.
|
|
1
|
+
---
|
|
2
|
+
name: swl:contribuir
|
|
3
|
+
description: Contribuye evoluciones de _userland/ al core de swl-ses creando un PR en GitHub. Filtra por dominio (solo ingeniería de software general), evalúa calidad con PluginEval (score ≥80 requerido) y crea el PR vía gh CLI. Flags: --skill=[nombre], --agente=[nombre], --dry-run.
|
|
4
|
+
allowed_tools: ["Read", "Write", "Edit", "Bash", "Glob", "Grep", "Agent"]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# /swl:contribuir — Contribuir evoluciones al core de swl-ses
|
|
8
|
+
|
|
9
|
+
Eres el facilitador de contribuciones del sistema SWL. Tu responsabilidad es tomar evoluciones que un usuario creó en `_userland/` y, si pasan los filtros de calidad y dominio, crear un Pull Request contra el repositorio oficial de swl-ses.
|
|
10
|
+
|
|
11
|
+
**Principio**: las evoluciones específicas de un proyecto se quedan en `_userland/` — solo evoluciones de dominio general pasan al core. Un skill de "configuración de Stripe para mi SaaS" no sube; un skill de "patrones de testing de APIs de pago" sí.
|
|
12
|
+
|
|
13
|
+
## Cuándo usar este comando
|
|
14
|
+
|
|
15
|
+
- Cuando el usuario evolucionó un agente o skill en `_userland/` y quiere compartirlo con la comunidad
|
|
16
|
+
- Después de `/swl:evolucionar` cuando el cambio aplica a cualquier proyecto de software
|
|
17
|
+
- Cuando se creó un skill nuevo con `/swl:crear-skill` que resuelve un problema general de ingeniería
|
|
18
|
+
|
|
19
|
+
## Prerrequisitos
|
|
20
|
+
|
|
21
|
+
1. **GitHub CLI (`gh`) autenticado** — verificar con `gh auth status`
|
|
22
|
+
2. **Evolución marcada** — el artefacto debe tener `evolved: true` en frontmatter o existir en `_userland/`
|
|
23
|
+
3. **Repositorio swl-ses accesible** — se necesita permiso de fork/PR
|
|
24
|
+
|
|
25
|
+
## Flags soportados
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
--skill=[nombre] Contribuir solo el skill indicado de _userland/habilidades/
|
|
29
|
+
--agente=[nombre] Contribuir solo el agente indicado de _userland/agentes/
|
|
30
|
+
--dry-run Ejecutar validaciones y evaluación sin crear PR
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Si no se pasa flag, escanea todo `_userland/` buscando candidatos.
|
|
34
|
+
|
|
35
|
+
## Paso 0 — Verificar prerrequisitos
|
|
36
|
+
|
|
37
|
+
Verificar que `gh` está instalado y autenticado:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
gh auth status
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Si falla:
|
|
44
|
+
- **No instalado**: indicar al usuario que instale GitHub CLI (ver MANUAL_USO.md § Dependencias externas)
|
|
45
|
+
- **No autenticado**: indicar al usuario que ejecute `! gh auth login` desde el prompt de Claude Code
|
|
46
|
+
|
|
47
|
+
DETENER si `gh auth status` no reporta una cuenta autenticada.
|
|
48
|
+
|
|
49
|
+
## Paso 1 — Escanear candidatos en _userland/
|
|
50
|
+
|
|
51
|
+
Buscar artefactos en `_userland/habilidades/` y `_userland/agentes/`:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# Skills con SKILL.md
|
|
55
|
+
for dir in _userland/habilidades/*/; do
|
|
56
|
+
[ -f "$dir/SKILL.md" ] && echo "skill: $(basename $dir)"
|
|
57
|
+
done
|
|
58
|
+
|
|
59
|
+
# Agentes con .md
|
|
60
|
+
for f in _userland/agentes/*.md; do
|
|
61
|
+
[ -f "$f" ] && echo "agente: $(basename $f .md)"
|
|
62
|
+
done
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Si se pasó `--skill` o `--agente`, filtrar a solo ese candidato.
|
|
66
|
+
|
|
67
|
+
Si no hay candidatos, informar:
|
|
68
|
+
```
|
|
69
|
+
No se encontraron evoluciones en _userland/ para contribuir.
|
|
70
|
+
Usa /swl:evolucionar o /swl:crear-skill para generar evoluciones primero.
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Paso 2 — Filtro de dominio
|
|
74
|
+
|
|
75
|
+
Para cada candidato, leer su contenido y evaluar compatibilidad de dominio.
|
|
76
|
+
|
|
77
|
+
**Pregunta de filtro**: *¿Le sirve esto a un ingeniero de software en cualquier proyecto de software?*
|
|
78
|
+
|
|
79
|
+
**Dominios aceptados** (ingeniería de software general):
|
|
80
|
+
- SDLC, backend, frontend, QA, DevOps, seguridad, arquitectura
|
|
81
|
+
- Testing, CI/CD, monitoreo, observabilidad
|
|
82
|
+
- Patrones de diseño, refactoring, revisión de código
|
|
83
|
+
- APIs, bases de datos, infraestructura cloud
|
|
84
|
+
|
|
85
|
+
**Dominios rechazados** (verticales específicos):
|
|
86
|
+
- ML/AI productivo, ciencia de datos, bioinformática
|
|
87
|
+
- Finanzas, contabilidad, legal
|
|
88
|
+
- Dominio de negocio específico del proyecto
|
|
89
|
+
|
|
90
|
+
Para cada candidato rechazado, explicar por qué:
|
|
91
|
+
```
|
|
92
|
+
RECHAZADO: [nombre] — dominio "[dominio detectado]" no es ingeniería de software general.
|
|
93
|
+
Las evoluciones específicas de dominio se mantienen en _userland/ del proyecto.
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Paso 3 — Evaluación PluginEval
|
|
97
|
+
|
|
98
|
+
Para cada candidato que pasó el filtro de dominio, ejecutar evaluación de calidad.
|
|
99
|
+
|
|
100
|
+
Cargar:
|
|
101
|
+
```
|
|
102
|
+
Skill("evaluacion-agentes")
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Ejecutar evaluación completa (2 capas). El score mínimo para contribuir es **80/100** (badge Oro).
|
|
106
|
+
|
|
107
|
+
- **Score ≥ 80**: APROBADO — continuar al siguiente paso
|
|
108
|
+
- **Score 60-79**: RECHAZADO con recomendaciones de mejora
|
|
109
|
+
- **Score < 60**: RECHAZADO — necesita trabajo significativo
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
EVALUACIÓN: [nombre]
|
|
113
|
+
Capa 1 (estática): [N] errores, [N] advertencias
|
|
114
|
+
Capa 2 (semántica): [score]/100 — badge [badge]
|
|
115
|
+
Veredicto: [APROBADO | RECHAZADO]
|
|
116
|
+
[Si rechazado: top 3 mejoras recomendadas]
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Si `--dry-run`: presentar resultados de evaluación y TERMINAR.
|
|
120
|
+
|
|
121
|
+
## Paso 4 — Preparar contribución
|
|
122
|
+
|
|
123
|
+
Para cada candidato aprobado:
|
|
124
|
+
|
|
125
|
+
1. **Guardar ruta del workspace original** antes de cambiar de directorio:
|
|
126
|
+
```bash
|
|
127
|
+
WORKSPACE_DIR=$(pwd)
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
2. **Crear fork** (si no existe) del repo oficial de swl-ses y obtener el nombre del fork:
|
|
131
|
+
```bash
|
|
132
|
+
gh repo fork saul-wade/swl-ses --clone=false
|
|
133
|
+
FORK_REPO=$(gh api user --jq '.login')/swl-ses
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
3. **Clonar el fork** y crear branch descriptivo:
|
|
137
|
+
```bash
|
|
138
|
+
gh repo clone "$FORK_REPO" /tmp/swl-ses-contrib
|
|
139
|
+
cd /tmp/swl-ses-contrib
|
|
140
|
+
git checkout -b contrib/[tipo]-[nombre]
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
4. **Copiar artefacto** desde el workspace original al clon del fork:
|
|
144
|
+
- Skills: `$WORKSPACE_DIR/_userland/habilidades/[nombre]/` → `habilidades/[nombre]/`
|
|
145
|
+
- Agentes: `$WORKSPACE_DIR/_userland/agentes/[nombre].md` → `agentes/[nombre].md`
|
|
146
|
+
|
|
147
|
+
4. **Ajustar frontmatter** — agregar campos de contribución:
|
|
148
|
+
```yaml
|
|
149
|
+
contributed: true
|
|
150
|
+
contributed-from: "_userland"
|
|
151
|
+
contributed-at: "[fecha YYYY-MM-DD]"
|
|
152
|
+
contributed-by: "[usuario gh]"
|
|
153
|
+
plugineval-score: [score]
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
5. **Registrar en plugin.json** si es necesario
|
|
157
|
+
|
|
158
|
+
## Paso 5 — Crear Pull Request
|
|
159
|
+
|
|
160
|
+
Crear el PR con template estructurado:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
git add .
|
|
164
|
+
git commit -m "contrib([tipo]): agrega [nombre] desde _userland
|
|
165
|
+
|
|
166
|
+
Evaluado con PluginEval: [score]/100 (badge [badge]).
|
|
167
|
+
Dominio: ingeniería de software general.
|
|
168
|
+
|
|
169
|
+
Co-Authored-By: swl-ses <noreply@swl-ses>"
|
|
170
|
+
|
|
171
|
+
git push origin contrib/[tipo]-[nombre]
|
|
172
|
+
|
|
173
|
+
gh pr create \
|
|
174
|
+
--repo saul-wade/swl-ses \
|
|
175
|
+
--title "contrib([tipo]): [nombre]" \
|
|
176
|
+
--body "$(cat <<'EOF'
|
|
177
|
+
## Contribución desde _userland
|
|
178
|
+
|
|
179
|
+
**Tipo**: [skill | agente]
|
|
180
|
+
**Nombre**: [nombre]
|
|
181
|
+
**Dominio**: [dominio detectado]
|
|
182
|
+
**PluginEval**: [score]/100 — badge [badge]
|
|
183
|
+
|
|
184
|
+
## Descripción
|
|
185
|
+
|
|
186
|
+
[Descripción extraída del artefacto]
|
|
187
|
+
|
|
188
|
+
## Evidencia de calidad
|
|
189
|
+
|
|
190
|
+
- Capa 1 (estática): [N] errores, [N] advertencias
|
|
191
|
+
- Capa 2 (semántica): [score]/100
|
|
192
|
+
- Filtro de dominio: APROBADO (ingeniería de software general)
|
|
193
|
+
|
|
194
|
+
## Checklist
|
|
195
|
+
|
|
196
|
+
- [ ] Score PluginEval ≥ 80
|
|
197
|
+
- [ ] Dominio: ingeniería de software general
|
|
198
|
+
- [ ] Sin credenciales hardcodeadas
|
|
199
|
+
- [ ] Frontmatter válido
|
|
200
|
+
- [ ] No duplica skill/agente existente
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
Generado por `/swl:contribuir` — swl-ses v[versión]
|
|
204
|
+
EOF
|
|
205
|
+
)"
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Paso 6 — Reporte final
|
|
209
|
+
|
|
210
|
+
```
|
|
211
|
+
=== Contribución completada ===
|
|
212
|
+
|
|
213
|
+
Candidatos escaneados: [N]
|
|
214
|
+
Filtro de dominio: [N] aprobados, [N] rechazados
|
|
215
|
+
Evaluación PluginEval: [N] aprobados (≥80), [N] rechazados
|
|
216
|
+
PRs creados: [N]
|
|
217
|
+
|
|
218
|
+
[Para cada PR creado:]
|
|
219
|
+
→ [nombre]: [URL del PR]
|
|
220
|
+
|
|
221
|
+
Los PRs serán revisados por los mantenedores de swl-ses.
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Reglas de comportamiento
|
|
225
|
+
|
|
226
|
+
- NUNCA crear un PR sin que el candidato haya pasado AMBOS filtros (dominio + PluginEval ≥ 80).
|
|
227
|
+
- NUNCA contribuir artefactos que contengan credenciales, tokens o datos del proyecto del usuario.
|
|
228
|
+
- NUNCA modificar artefactos del core existente — solo agregar nuevos.
|
|
229
|
+
- Si el artefacto duplica funcionalidad de uno existente en el core, RECHAZAR y sugerir `/swl:evolucionar` en su lugar.
|
|
230
|
+
- Si `gh auth status` falla, DETENER inmediatamente — no intentar autenticación automática.
|
|
231
|
+
- En `--dry-run`, el reporte debe ser completo y accionable sin crear ningún PR.
|
|
232
|
+
- Los artefactos contribuidos mantienen su autoría original (campo `contributed-by`).
|
|
233
|
+
- SIEMPRE verificar que el nombre del artefacto no colisione con uno existente en el core antes de crear el PR.
|
|
@@ -55,6 +55,66 @@ documentado en `reglas/consultar-vault-primero.md § Workflow forzoso para
|
|
|
55
55
|
escritura al vault`. El bloqueo por `proteccion-rutas.js` no es una falla a
|
|
56
56
|
esquivar — es una señal de que el canal correcto es el MCP.
|
|
57
57
|
|
|
58
|
+
### 0c — Verificar que el vault activo de Obsidian apunta a `Vault\SWL\` (CRÍTICO)
|
|
59
|
+
|
|
60
|
+
> Origen del paso: sesión 2026-05-13 v1.4.0. El MCP de Obsidian resuelve paths
|
|
61
|
+
> relativos contra el **vault que Obsidian tiene abierto**, no contra una
|
|
62
|
+
> ruta hardcodeada en el plugin. Si Obsidian abrió un vault distinto del
|
|
63
|
+
> esperado (ej. `F:\Google Drive\Developer\Obsidian\Vault\` raíz en lugar
|
|
64
|
+
> de `Vault\SWL\`), todas las escrituras del MCP irán al vault equivocado.
|
|
65
|
+
> El plugin **crea carpetas inexistentes** sobre la marcha, así que ni
|
|
66
|
+
> siquiera obtendrás error — los archivos terminan en una ubicación huérfana.
|
|
67
|
+
|
|
68
|
+
Verifica antes de cualquier llamada MCP:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# Path canónico de la config global de Obsidian en Windows
|
|
72
|
+
APP="$APPDATA/obsidian/obsidian.json"
|
|
73
|
+
node -e "
|
|
74
|
+
const fs = require('fs');
|
|
75
|
+
const data = JSON.parse(fs.readFileSync(process.argv[1], 'utf8'));
|
|
76
|
+
const abierto = Object.values(data.vaults).find(v => v.open === true);
|
|
77
|
+
console.log('Vault abierto:', abierto ? abierto.path : 'NINGUNO');
|
|
78
|
+
console.log('Esperado: F:\\\\Google Drive\\\\Developer\\\\Obsidian\\\\Vault\\\\SWL');
|
|
79
|
+
console.log('OK:', abierto && abierto.path.endsWith('SWL') ? 'sí' : 'NO');
|
|
80
|
+
" "$APP"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Resultado esperado:
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
Vault abierto: F:\Google Drive\Developer\Obsidian\Vault\SWL
|
|
87
|
+
Esperado: F:\Google Drive\Developer\Obsidian\Vault\SWL
|
|
88
|
+
OK: sí
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Si `OK: NO` o `Vault abierto: NINGUNO`, **NO usar MCP** — caer al filesystem
|
|
92
|
+
para esta sesión y reportar al usuario que debe abrir el vault `SWL` en
|
|
93
|
+
Obsidian (File → Open vault → seleccionar `F:\Google Drive\Developer\Obsidian\Vault\SWL`).
|
|
94
|
+
|
|
95
|
+
### 0d — Verificar que la apiKey del MCP coincide con la del plugin activo
|
|
96
|
+
|
|
97
|
+
> Origen: cuando el vault activo cambia, la apiKey del plugin Local REST API
|
|
98
|
+
> cambia (cada vault tiene su propio `.obsidian/plugins/obsidian-local-rest-api/data.json`
|
|
99
|
+
> con apiKey, cert y privateKey distintos). El MCP server registrado en
|
|
100
|
+
> Claude.ai tiene una apiKey hardcodeada — si no se actualiza tras cambiar de
|
|
101
|
+
> vault, todas las llamadas retornan `40101 Authorization required`.
|
|
102
|
+
|
|
103
|
+
Si tras `ToolSearch` el MCP carga sus tools pero la primera llamada (ej.
|
|
104
|
+
`obsidian_list_files_in_dir`) retorna `Error 40101: Authorization required`,
|
|
105
|
+
el síntoma es claro: apiKey desincronizada.
|
|
106
|
+
|
|
107
|
+
Acción:
|
|
108
|
+
1. Leer la apiKey actual del plugin con
|
|
109
|
+
`grep '"apiKey"' "F:/Google Drive/Developer/Obsidian/Vault/SWL/.obsidian/plugins/obsidian-local-rest-api/data.json"`
|
|
110
|
+
2. Reportar al usuario que actualice en **claude.ai → Settings → Connectors
|
|
111
|
+
→ Obsidian → API Key**. Disconnect + Reconnect tras pegar el valor.
|
|
112
|
+
3. Mientras tanto, usar filesystem como fallback para escribir al Inbox.
|
|
113
|
+
|
|
114
|
+
Si hay procesos zombie de Obsidian o `mcp-obsidian` cliente con apiKey
|
|
115
|
+
cacheada, requieren terminación + reinicio de Claude Code para tomar la
|
|
116
|
+
nueva apiKey.
|
|
117
|
+
|
|
58
118
|
## Paso 1 — Identificación del proyecto actual
|
|
59
119
|
|
|
60
120
|
Detecta qué proyecto eres leyendo:
|
|
@@ -296,6 +356,40 @@ escribe a `_userland/staging/<timestamp>.md` dentro del CWD, luego mueve con
|
|
|
296
356
|
Reportar al usuario qué canal se usó:
|
|
297
357
|
- Canal A → `[OK] Vía: MCP Obsidian (puerto 27124)`
|
|
298
358
|
- Canal B → `[OK] Vía: filesystem directo (MCP no disponible)`
|
|
359
|
+
- Canal Híbrido → `[OK] Vía: filesystem para Inbox, MCP para promociones`
|
|
360
|
+
|
|
361
|
+
### Modo HÍBRIDO (validado en sesión 2026-05-13)
|
|
362
|
+
|
|
363
|
+
Cuando la sesión incluye **autorización ampliada para promover documentos**
|
|
364
|
+
a `02-Projects/`, `07-Decisions/` y `04-Resources/`, el flujo óptimo combina
|
|
365
|
+
ambos canales:
|
|
366
|
+
|
|
367
|
+
1. **Inbox** (`00-Inbox/YYYY-MM-DD_HHMM_export-{slug}.md`): usar siempre
|
|
368
|
+
**filesystem directo via Bash heredoc con ruta absoluta** (canal B). Razón:
|
|
369
|
+
el Bash heredoc bypassa cualquier desalineación del vault activo de
|
|
370
|
+
Obsidian — escribe directamente al disco en la ruta exacta.
|
|
371
|
+
|
|
372
|
+
2. **Promociones** (a `02-Projects/`, `07-Decisions/`, `04-Resources/`):
|
|
373
|
+
usar **MCP append_content** (canal A) tras validar Pasos 0c y 0d. Razón:
|
|
374
|
+
las promociones requieren enlaces bidireccionales con `[[...]]` que el
|
|
375
|
+
plugin de Obsidian indexa al detectar la escritura. El filesystem directo
|
|
376
|
+
crea el archivo pero no dispara la reindexación hasta que Obsidian
|
|
377
|
+
detecte el cambio.
|
|
378
|
+
|
|
379
|
+
3. **Aprobación de revisiones** (cambiar `status: pending-review` → `reviewed`
|
|
380
|
+
en frontmatter): si el archivo está en `00-Inbox/`, usar `sed` via Bash;
|
|
381
|
+
si está en `02-Projects/` etc., usar `mcp__obsidian__obsidian_patch_content`
|
|
382
|
+
con `target_type: "frontmatter"`. Validado que `patch_content` puede
|
|
383
|
+
responder 404 en algunos archivos pre-existentes — caer al filesystem si
|
|
384
|
+
falla.
|
|
385
|
+
|
|
386
|
+
Reportar al usuario el desglose final del modo híbrido:
|
|
387
|
+
|
|
388
|
+
```
|
|
389
|
+
[OK] Inbox creado via filesystem: F:\...\00-Inbox\...md
|
|
390
|
+
[OK] 3 promociones via MCP: 02-Projects, 07-Decisions, 04-Resources
|
|
391
|
+
[OK] Revisión aprobada (reviewed: true) en el Inbox
|
|
392
|
+
```
|
|
299
393
|
|
|
300
394
|
## Paso 5 — Confirmación
|
|
301
395
|
|
|
@@ -373,6 +467,20 @@ Próximo paso: al abrir el vault, ejecuta:
|
|
|
373
467
|
|
|
374
468
|
## Historial de cambios del comando
|
|
375
469
|
|
|
470
|
+
- **v1.4.0** (2026-05-13) — Agregados Pasos 0c y 0d con verificación previa
|
|
471
|
+
del vault activo de Obsidian y de la apiKey del MCP. Origen: sesión
|
|
472
|
+
2026-05-13 con autorización ampliada del usuario para promover docs;
|
|
473
|
+
el MCP escribió `02-Projects/DEV - swl-ses.md` en `Vault\` raíz en lugar
|
|
474
|
+
de `Vault\SWL\` porque Obsidian tenía abierto el vault un nivel arriba
|
|
475
|
+
del esperado. Hallazgo crítico: el plugin Local REST API resuelve paths
|
|
476
|
+
relativos contra el vault que Obsidian tiene abierto en `obsidian.json`
|
|
477
|
+
global, no contra una ruta hardcodeada. Si el vault activo está mal,
|
|
478
|
+
el MCP escribe a la ubicación equivocada sin error (el plugin crea
|
|
479
|
+
carpetas inexistentes). Agregado también Paso 0d para apiKey
|
|
480
|
+
desincronizada (síntoma `40101 Authorization required`). Y nuevo
|
|
481
|
+
modo HÍBRIDO en Paso 4: filesystem directo para Inbox + MCP para
|
|
482
|
+
promociones, validado en la misma sesión.
|
|
483
|
+
|
|
376
484
|
- **v1.3.8** (2026-05-11) — Agregado flujo MCP-first en Paso 4 con detección
|
|
377
485
|
en Paso 0b. Origen: en la sesión v1.3.4 → v1.3.8 el comando defaultó a
|
|
378
486
|
`Write` directo al filesystem que fue bloqueado por `proteccion-rutas.js`.
|