@saulwade/swl-ses 2.0.0 → 2.1.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 +196 -196
- package/README.md +579 -579
- package/agentes/_propose-step.md +90 -0
- package/agentes/implementador-swl.md +2 -0
- package/agentes/orquestador-swl.md +2 -0
- package/agentes/perfilador-usuario-swl.md +14 -1
- package/bin/swl-ses.js +1 -1
- package/comandos/swl/aprobar-plan.md +3 -2
- package/comandos/swl/briefing.md +122 -0
- package/comandos/swl/compactar.md +29 -2
- package/comandos/swl/discutir-fase.md +8 -5
- package/comandos/swl/ejecutar-fase.md +6 -0
- package/comandos/swl/planear-fase.md +5 -3
- package/comandos/swl/release.md +46 -0
- package/comandos/swl/status.md +69 -0
- package/comandos/swl/verificar.md +3 -2
- package/habilidades/changelog-generator/scripts/parse-commits.js +6 -4
- package/habilidades/ejecutar-fase/SKILL.md +541 -518
- package/habilidades/planear-fase/SKILL.md +3 -2
- package/habilidades/tdd-workflow/SKILL.md +715 -713
- package/habilidades/validacion-ci-sistema/SKILL.md +17 -1
- package/hooks/calidad-pre-commit.js +5 -1
- package/hooks/check-update.js +39 -1
- package/hooks/lib/autonomia.js +208 -0
- package/hooks/lib/briefing.js +474 -0
- package/hooks/lib/propose-step.js +357 -0
- package/hooks/session-briefing.js +98 -0
- package/hooks/telemetria-skill-routing.js +100 -0
- package/instintos/autonomia.yaml +27 -0
- package/llms.txt +4 -4
- package/manifiestos/hooks-config.json +18 -0
- package/manifiestos/modulos.json +25 -3
- package/manifiestos/skills-lock.json +14 -14
- package/package.json +93 -93
- package/plugin.json +371 -371
- package/reglas/analizar-directorios-antes-de-escribir.md +228 -0
- package/reglas/consultar-vault-primero.md +195 -0
- package/reglas/debatir-antes-de-aceptar.md +158 -0
- package/reglas/git-coauthor.md +100 -0
- package/reglas/monitor-ci.md +309 -0
- package/reglas/registro-componentes-nuevos.md +38 -10
- package/reglas/sesiones-paralelas.md +180 -0
- package/reglas/usar-code-review-graph.md +155 -0
- package/reglas/verificar-citas-normativas.md +548 -0
- package/scripts/instalador.js +52 -6
- package/scripts/lib/ci-reader.js +193 -0
- package/scripts/lib/detectar-host-swl.js +175 -0
- package/scripts/lib/evidencia-release.js +322 -0
- package/scripts/lib/gate-hooks-requires.js +249 -0
- package/scripts/lib/gate-licencias.js +212 -0
- package/scripts/lib/git-metricas.js +257 -0
- package/scripts/lib/metricas-dora.js +204 -0
- package/scripts/tui/ejecutores.js +1 -1
- package/scripts/validar-manifest.js +92 -1
- package/scripts/verificar-evolucion.js +54 -4
- package/scripts/verificar-release.js +102 -0
- package/scripts/verificar-trazabilidad.js +11 -5
- package/reglas/arquitectura.evolved.json +0 -7
- package/reglas/seguridad.evolved.json +0 -7
|
@@ -32,6 +32,10 @@
|
|
|
32
32
|
const fs = require('fs');
|
|
33
33
|
const path = require('path');
|
|
34
34
|
const contadoresLib = require('./lib/contadores-inventario');
|
|
35
|
+
// Gate de licencias (Fase 14, ADR-0038) — WARN-ONLY: reporta copyleft pero
|
|
36
|
+
// NUNCA bloquea el release en v1 (D-14-02). Cargado como módulo, no subproceso.
|
|
37
|
+
const { evaluarLicencias } = require('./lib/gate-licencias');
|
|
38
|
+
const { evaluarHooksRequires } = require('./lib/gate-hooks-requires');
|
|
35
39
|
|
|
36
40
|
const CWD = process.cwd();
|
|
37
41
|
|
|
@@ -272,6 +276,18 @@ function main() {
|
|
|
272
276
|
fallasObligatorias++;
|
|
273
277
|
}
|
|
274
278
|
|
|
279
|
+
// Gate de requires hooks→scripts: valida que toda lib de scripts/ requerida
|
|
280
|
+
// por un hook DISTRIBUIDO (incluidas dependencias transitivas) esté registrada
|
|
281
|
+
// en modulos.json y cubierta en todos los perfiles que instalan el hook.
|
|
282
|
+
// Bloqueante: sin esto el hook muere con MODULE_NOT_FOUND en el destino y el
|
|
283
|
+
// wrapper de settings.json lo traga en silencio. Origen: bug check-update —
|
|
284
|
+
// el aviso de nuevas versiones nunca llegó a instalaciones destino (2026-06-12,
|
|
285
|
+
// commit 12b2a31). Misma familia que el gate de bin-imports, eje instalador→destino.
|
|
286
|
+
const gateHooksRequires = ejecutarGateHooksRequires();
|
|
287
|
+
if (gateHooksRequires.disponible && gateHooksRequires.hallazgos.length > 0) {
|
|
288
|
+
fallasObligatorias++;
|
|
289
|
+
}
|
|
290
|
+
|
|
275
291
|
// Gate de consistencia cross-manifest del campo description:
|
|
276
292
|
// valida que package.json#description y plugin.json#description tengan
|
|
277
293
|
// las mismas cifras (60 agentes / N habilidades / M comandos / K reglas / L hooks)
|
|
@@ -295,6 +311,12 @@ function main() {
|
|
|
295
311
|
}
|
|
296
312
|
}
|
|
297
313
|
|
|
314
|
+
// Gate de licencias (Fase 14, ADR-0038) — WARN-ONLY por diseño (D-14-02):
|
|
315
|
+
// clasifica el árbol prod (copyleft fuerte/débil, desconocida) pero NUNCA
|
|
316
|
+
// suma a fallasObligatorias. Solo informa; la promoción a blocking exigiría
|
|
317
|
+
// calibración + ADR posterior (mismo patrón que G0/G2/G3).
|
|
318
|
+
const gateLicencias = ejecutarGateLicencias();
|
|
319
|
+
|
|
298
320
|
if (jsonOut) {
|
|
299
321
|
process.stdout.write(JSON.stringify({
|
|
300
322
|
version,
|
|
@@ -304,8 +326,10 @@ function main() {
|
|
|
304
326
|
warnings_opcionales: warningsOpcionales,
|
|
305
327
|
contadores_gate: gateContadores,
|
|
306
328
|
bin_imports_gate: gateBinImports,
|
|
329
|
+
hooks_requires_gate: gateHooksRequires,
|
|
307
330
|
description_gate: gateDescription,
|
|
308
331
|
aiisms_gate: aiismsGate,
|
|
332
|
+
gate_licencias: gateLicencias,
|
|
309
333
|
resultados: resultados.map(({ entrada, resultado }) => ({
|
|
310
334
|
archivo: entrada.archivo,
|
|
311
335
|
obligatorio: entrada.obligatorio,
|
|
@@ -378,6 +402,28 @@ function main() {
|
|
|
378
402
|
process.stdout.write('\n');
|
|
379
403
|
process.stdout.write('Gate de bin-imports: no disponible — ' + gateBinImports.error + '\n');
|
|
380
404
|
}
|
|
405
|
+
if (gateHooksRequires.disponible) {
|
|
406
|
+
process.stdout.write('\n');
|
|
407
|
+
process.stdout.write('Gate de requires hooks→scripts (vs modulos.json + perfiles.json):\n');
|
|
408
|
+
process.stdout.write(
|
|
409
|
+
' Hooks distribuidos analizados: ' + gateHooksRequires.hooksDistribuidos +
|
|
410
|
+
' | dependencias hooks→scripts: ' + gateHooksRequires.dependencias.length + '\n'
|
|
411
|
+
);
|
|
412
|
+
if (gateHooksRequires.hallazgos.length === 0) {
|
|
413
|
+
process.stdout.write(' [OK] Toda lib de scripts/ requerida por hooks distribuidos está registrada y cubierta\n');
|
|
414
|
+
} else {
|
|
415
|
+
for (const h of gateHooksRequires.hallazgos) {
|
|
416
|
+
process.stdout.write(' [FALLA] [' + h.tipo + '] ' + h.detalle + '\n');
|
|
417
|
+
}
|
|
418
|
+
process.stdout.write(
|
|
419
|
+
' Bloqueo: registra la lib (y sus transitivas) en el módulo del hook en modulos.json. ' +
|
|
420
|
+
'Sin esto el hook muere en silencio en el destino (wrapper traga MODULE_NOT_FOUND).\n'
|
|
421
|
+
);
|
|
422
|
+
}
|
|
423
|
+
} else if (gateHooksRequires.error) {
|
|
424
|
+
process.stdout.write('\n');
|
|
425
|
+
process.stdout.write('Gate de hooks-requires: no disponible — ' + gateHooksRequires.error + '\n');
|
|
426
|
+
}
|
|
381
427
|
if (gateDescription.disponible) {
|
|
382
428
|
process.stdout.write('\n');
|
|
383
429
|
process.stdout.write('Gate de description (package.json vs plugin.json vs INVENTARIO.md):\n');
|
|
@@ -420,6 +466,29 @@ function main() {
|
|
|
420
466
|
);
|
|
421
467
|
}
|
|
422
468
|
}
|
|
469
|
+
if (gateLicencias.disponible) {
|
|
470
|
+
process.stdout.write('\n');
|
|
471
|
+
process.stdout.write('Gate de licencias (árbol prod — WARN-ONLY, no bloquea):\n');
|
|
472
|
+
const r = gateLicencias.resumen;
|
|
473
|
+
process.stdout.write(
|
|
474
|
+
' permisiva: ' + r.permisiva + ' | débil: ' + r.debil +
|
|
475
|
+
' | fuerte: ' + r.fuerte + ' | desconocida: ' + r.desconocida + '\n'
|
|
476
|
+
);
|
|
477
|
+
const alertas = gateLicencias.hallazgos.filter((h) => h.clasificacion !== 'permisiva');
|
|
478
|
+
if (alertas.length > 0) {
|
|
479
|
+
for (const h of alertas) {
|
|
480
|
+
process.stdout.write(
|
|
481
|
+
' [WARN ' + h.clasificacion + '] ' + h.paquete + '@' + h.version + ' — ' + h.licencia + '\n'
|
|
482
|
+
);
|
|
483
|
+
}
|
|
484
|
+
process.stdout.write(' Aviso: licencias no permisivas detectadas (informativo, no bloquea el release).\n');
|
|
485
|
+
} else {
|
|
486
|
+
process.stdout.write(' [OK] Todas las dependencias de producción son permisivas.\n');
|
|
487
|
+
}
|
|
488
|
+
} else if (gateLicencias.error) {
|
|
489
|
+
process.stdout.write('\n');
|
|
490
|
+
process.stdout.write('Gate de licencias: no disponible — ' + gateLicencias.error + '\n');
|
|
491
|
+
}
|
|
423
492
|
if (fallasObligatorias > 0) {
|
|
424
493
|
process.stdout.write('\n');
|
|
425
494
|
process.stdout.write('Corrige los archivos marcados como FALLA antes de hacer push o publicar.\n');
|
|
@@ -583,6 +652,18 @@ function ejecutarGateBinImports() {
|
|
|
583
652
|
}
|
|
584
653
|
}
|
|
585
654
|
|
|
655
|
+
/**
|
|
656
|
+
* Gate de requires hooks→scripts (lib: scripts/lib/gate-hooks-requires.js).
|
|
657
|
+
* Bloqueante. Ver comentario en el flujo principal.
|
|
658
|
+
*/
|
|
659
|
+
function ejecutarGateHooksRequires() {
|
|
660
|
+
try {
|
|
661
|
+
return evaluarHooksRequires(CWD);
|
|
662
|
+
} catch (err) {
|
|
663
|
+
return { disponible: false, error: err.message };
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
|
|
586
667
|
function ejecutarGateAiisms() {
|
|
587
668
|
const { spawnSync } = require('child_process');
|
|
588
669
|
const detector = path.join(CWD, 'habilidades', 'estilo-sin-ai-isms', 'scripts', 'detectar_aiisms.py');
|
|
@@ -795,6 +876,26 @@ function ejecutarGateDescription(contadoresReales) {
|
|
|
795
876
|
};
|
|
796
877
|
}
|
|
797
878
|
|
|
879
|
+
/**
|
|
880
|
+
* Gate de licencias (Fase 14, ADR-0038) — WARN-ONLY.
|
|
881
|
+
*
|
|
882
|
+
* Clasifica las licencias del árbol de producción (vía scripts/lib/gate-licencias)
|
|
883
|
+
* y devuelve el resumen para impresión. NO bloquea el release: el caller NUNCA
|
|
884
|
+
* suma este resultado a fallasObligatorias (D-14-02, calibración primero).
|
|
885
|
+
*
|
|
886
|
+
* @param {string} [baseDir=CWD] raíz del proyecto a evaluar (parametrizable
|
|
887
|
+
* para tests; en producción usa el CWD del proceso).
|
|
888
|
+
* @returns {{disponible: boolean, hallazgos?: Array, resumen?: object, error?: string}}
|
|
889
|
+
*/
|
|
890
|
+
function ejecutarGateLicencias(baseDir = CWD) {
|
|
891
|
+
try {
|
|
892
|
+
const { hallazgos, resumen } = evaluarLicencias(baseDir);
|
|
893
|
+
return { disponible: true, hallazgos, resumen };
|
|
894
|
+
} catch (err) {
|
|
895
|
+
return { disponible: false, error: err.message };
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
|
|
798
899
|
if (require.main === module) main();
|
|
799
900
|
|
|
800
901
|
module.exports = {
|
|
@@ -803,4 +904,5 @@ module.exports = {
|
|
|
803
904
|
versionObjetivo,
|
|
804
905
|
extraerCifrasDescription,
|
|
805
906
|
ejecutarGateDescription,
|
|
907
|
+
ejecutarGateLicencias,
|
|
806
908
|
};
|
|
@@ -51,7 +51,10 @@ function extraerReqs(contextoTexto) {
|
|
|
51
51
|
// Definición: línea con `**REQ-NN**:` o `REQ-NN:` (con bullet opcional).
|
|
52
52
|
// El criterio puede continuar en líneas siguientes indentadas — se capturan
|
|
53
53
|
// hasta la próxima definición para detectar la anotación de método.
|
|
54
|
-
|
|
54
|
+
// REQ-NN (legacy) o REQ-NN-MM (namespaceado por fase, DT-IDS-NAMESPACE).
|
|
55
|
+
// El grupo `(?:-\d{1,3})?` es greedy: en `REQ-12-01` captura el ID completo,
|
|
56
|
+
// nunca el prefijo `REQ-12` truncado.
|
|
57
|
+
const re = /^\s*(?:[-*]\s*)?\*{0,2}(REQ-\d{1,3}(?:-\d{1,3})?)\*{0,2}\s*:([\s\S]*?)(?=^\s*(?:[-*]\s*)?\*{0,2}REQ-\d|^#|\n\n|$(?![\s\S]))/gm;
|
|
55
58
|
let m;
|
|
56
59
|
while ((m = re.exec(contextoTexto)) !== null) {
|
|
57
60
|
const cuerpo = m[2];
|
|
@@ -76,8 +79,11 @@ function extraerMatrizPlan(planTexto) {
|
|
|
76
79
|
if (!tareas.has(tareaActual)) tareas.set(tareaActual, []);
|
|
77
80
|
continue;
|
|
78
81
|
}
|
|
79
|
-
|
|
80
|
-
|
|
82
|
+
// Solo la línea-campo cuenta (`- **Verifica REQ**: ...` al inicio, bullet
|
|
83
|
+
// opcional). Una descripción que cite `**Verifica REQ**:` en prosa NO debe
|
|
84
|
+
// contaminar la matriz ni ocultar huérfanos (ancla `^` obligatoria).
|
|
85
|
+
if (tareaActual && /^\s*(?:[-*]\s*)?\*\*Verifica REQ\*\*\s*:/i.test(linea)) {
|
|
86
|
+
const reqs = linea.match(/REQ-\d{1,3}(?:-\d{1,3})?/g) || [];
|
|
81
87
|
tareas.get(tareaActual).push(...reqs);
|
|
82
88
|
}
|
|
83
89
|
}
|
|
@@ -102,7 +108,7 @@ function extraerCommitsConRefs(cwd) {
|
|
|
102
108
|
if (!hash || !cuerpo) continue;
|
|
103
109
|
const refs = cuerpo.match(/^Refs:\s*(.+)$/m);
|
|
104
110
|
if (!refs) continue;
|
|
105
|
-
for (const req of refs[1].match(/REQ-\d{1,3}
|
|
111
|
+
for (const req of refs[1].match(/REQ-\d{1,3}(?:-\d{1,3})?/g) || []) {
|
|
106
112
|
if (!porReq.has(req)) porReq.set(req, []);
|
|
107
113
|
porReq.get(req).push(hash.trim());
|
|
108
114
|
}
|
|
@@ -138,7 +144,7 @@ function extraerTestsConMarker(cwd) {
|
|
|
138
144
|
} catch (_) {
|
|
139
145
|
continue;
|
|
140
146
|
}
|
|
141
|
-
for (const m of contenido.matchAll(/verifica:\s*(REQ-\d{1,3})/g)) {
|
|
147
|
+
for (const m of contenido.matchAll(/verifica:\s*(REQ-\d{1,3}(?:-\d{1,3})?)/g)) {
|
|
142
148
|
const req = m[1];
|
|
143
149
|
if (!porReq.has(req)) porReq.set(req, []);
|
|
144
150
|
if (!porReq.get(req).includes(archivo)) porReq.get(req).push(archivo);
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"evolved": true,
|
|
3
|
-
"evolved-from": "1.8.0",
|
|
4
|
-
"evolved-at": "2026-06-04",
|
|
5
|
-
"evolved-by": "evolucionar",
|
|
6
|
-
"evolved-note": "PE-010 sección nueva 'Tablas append-only — excepción documentada a audit columns nullable=False'. Patrón portable a logs estructurados, audit trails, event sourcing, telemetría. Origen: OIC v1.5 Slice 1 2026-06-04 (BitacoraError)."
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"evolved": true,
|
|
3
|
-
"evolved-from": "1.8.0",
|
|
4
|
-
"evolved-at": "2026-06-04",
|
|
5
|
-
"evolved-by": "evolucionar",
|
|
6
|
-
"evolved-note": "PE-003 (verificación de flags antes de asumir servicios externos LDAP/Redis/S3) + PE-004 (sanitización PII centralizada en handlers) + PE-007 (generación de passwords legibles sin chars ambiguos). Origen: OIC v1.5 2026-06-04, bug histórico manuel.monteagudo + Slice 2 v1.5 Observabilidad."
|
|
7
|
-
}
|