@saulwade/swl-ses 2.3.1 → 2.4.2
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 +242 -240
- package/README.md +597 -597
- package/agentes/_intent-spec.md +73 -73
- package/agentes/_propose-step.md +90 -90
- package/agentes/accesibilidad-wcag-swl.md +690 -690
- package/agentes/arquitecto-swl.md +267 -267
- package/agentes/auto-evolucion-swl.md +908 -908
- package/agentes/backend-api-swl.md +472 -472
- package/agentes/backend-csharp-swl.md +420 -420
- package/agentes/backend-go-swl.md +390 -390
- package/agentes/backend-java-swl.md +281 -281
- package/agentes/backend-node-swl.md +479 -479
- package/agentes/backend-python-swl.md +605 -605
- package/agentes/backend-rust-swl.md +364 -364
- package/agentes/backend-workers-swl.md +482 -482
- package/agentes/cloud-infra-swl.md +509 -509
- package/agentes/consolidador-swl.md +541 -541
- package/agentes/datos-swl.md +605 -605
- package/agentes/depurador-swl.md +352 -352
- package/agentes/devops-ci-swl.md +400 -400
- package/agentes/disenador-ui-swl.md +569 -569
- package/agentes/documentador-swl.md +345 -345
- package/agentes/frontend-angular-swl.md +621 -621
- package/agentes/frontend-css-swl.md +716 -716
- package/agentes/frontend-react-swl.md +692 -692
- package/agentes/frontend-swl.md +496 -496
- package/agentes/frontend-tailwind-swl.md +826 -826
- package/agentes/gh-fix-ci-swl.md +275 -275
- package/agentes/implementador-swl.md +328 -328
- package/agentes/investigador-swl.md +432 -432
- package/agentes/investigador-ux-swl.md +505 -505
- package/agentes/llm-apps-swl.md +278 -278
- package/agentes/migrador-swl.md +442 -442
- package/agentes/mobile-android-swl.md +511 -511
- package/agentes/mobile-cross-swl.md +541 -541
- package/agentes/mobile-ios-swl.md +502 -502
- package/agentes/mobile-testing-swl.md +302 -302
- package/agentes/nemesis-auditor-swl.md +285 -285
- package/agentes/notificador-swl.md +918 -918
- package/agentes/observabilidad-swl.md +438 -438
- package/agentes/orquestador-swl.md +1053 -1026
- package/agentes/pagos-swl.md +310 -310
- package/agentes/perfilador-usuario-swl.md +321 -321
- package/agentes/planificador-swl.md +399 -399
- package/agentes/producto-prd-swl.md +589 -589
- package/agentes/red-team-swl.md +218 -218
- package/agentes/release-manager-swl.md +590 -590
- package/agentes/rendimiento-swl.md +713 -713
- package/agentes/resolutor-build-swl.md +245 -245
- package/agentes/revisor-angular-swl.md +278 -278
- package/agentes/revisor-codigo-swl.md +538 -505
- package/agentes/revisor-csharp-swl.md +264 -264
- package/agentes/revisor-go-swl.md +259 -259
- package/agentes/revisor-java-swl.md +257 -257
- package/agentes/revisor-kotlin-swl.md +273 -273
- package/agentes/revisor-nextjs-swl.md +281 -281
- package/agentes/revisor-php-swl.md +271 -271
- package/agentes/revisor-react-swl.md +278 -278
- package/agentes/revisor-rust-swl.md +346 -346
- package/agentes/revisor-seguridad-swl.md +399 -399
- package/agentes/revisor-swift-swl.md +268 -268
- package/agentes/revisor-typescript-swl.md +346 -346
- package/agentes/sre-swl.md +291 -291
- package/agentes/tdd-qa-swl.md +393 -393
- package/comandos/swl/contexto.md +0 -2
- package/comandos/swl/deuda-codigo.md +97 -0
- package/habilidades/angular-moderno/SKILL.md +5 -1
- package/habilidades/contenedores-docker/SKILL.md +3 -1
- package/habilidades/ejecutar-task-iterativo/SKILL.md +278 -278
- package/habilidades/harness-claude-code/SKILL.md +5 -4
- package/habilidades/harness-claude-code/recursos/disciplina-harness-regla.md +6 -5
- package/habilidades/legacy-code-rescue/SKILL.md +2 -1
- package/habilidades/meta-skills-estandar/SKILL.md +1 -1
- package/habilidades/meta-skills-estandar/recursos/skills-as-agents.md +2 -2
- package/habilidades/postgresql-experto/SKILL.md +3 -1
- package/habilidades/prevencion-sobreingenieria/SKILL.md +70 -92
- package/habilidades/prevencion-sobreingenieria/recursos/soluciones-nativas.md +166 -0
- package/habilidades/prevencion-sobreingenieria/recursos/variables-residuales-post-refactor.md +85 -0
- package/habilidades/tdd-workflow/SKILL.md +3 -1
- package/hooks/audit-trail.js +4 -4
- package/hooks/calidad-pre-commit.js +15 -11
- package/hooks/captura-acciones-post.js +3 -2
- package/hooks/captura-acciones-session.js +3 -2
- package/hooks/contexto-iteracion.js +2 -1
- package/hooks/contexto-subagente.js +68 -0
- package/hooks/guardrail-modelo.js +13 -3
- package/hooks/inyeccion-contexto.js +12 -12
- package/hooks/registro-turnos.js +5 -4
- package/hooks/spec-gate.js +2 -1
- package/hooks/sugerir-contribuir.js +2 -1
- package/hooks/sugerir-regenerar-inventario.js +3 -2
- package/hooks/tdd-gate.js +2 -1
- package/llms.txt +3 -3
- package/manifiestos/canonical-hashes.json +995 -10
- package/manifiestos/hook-profiles.json +0 -2
- package/manifiestos/hooks-config.json +469 -477
- package/manifiestos/invariantes-criticos.json +30 -0
- package/manifiestos/modulos.json +1390 -1390
- package/manifiestos/skills-lock.json +24 -24
- package/package.json +93 -93
- package/plugin.json +369 -371
- package/reglas/arreglar-al-detectar.md +16 -0
- package/reglas/pruebas.md +7 -3
- package/schemas/agent-frontmatter.schema.json +3 -1
- package/scripts/actualizar.js +253 -254
- package/scripts/doctor.js +25 -17
- package/scripts/instalador.js +4 -1
- package/scripts/lib/detectar-runtime.js +58 -0
- package/scripts/lib/expandir-targets.js +71 -71
- package/scripts/lib/hooks-settings.js +40 -3
- package/scripts/lib/preservar-usuario.js +39 -5
- package/scripts/lib/toml-merge.js +204 -204
- package/scripts/mcp-server/auth.js +105 -105
- package/scripts/mcp-server/cache.js +106 -106
- package/scripts/tui/pantallas/inspect.js +175 -173
- package/scripts/tui/pantallas/uninstall-wizard.js +210 -208
- package/scripts/tui/pantallas/update-wizard.js +234 -232
- package/scripts/tui/pantallas/welcome.js +189 -187
- package/scripts/validar.js +1 -1
- package/scripts/verificar-release.js +51 -0
- package/hooks/lib/context-compressor.js +0 -657
- package/hooks/linea-estado.js +0 -328
- package/hooks/monitor-contexto.js +0 -373
|
@@ -1,187 +1,189 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Pantalla Welcome de la TUI de swl-ses.
|
|
5
|
-
*
|
|
6
|
-
* Diseño:
|
|
7
|
-
* - Logo ASCII centrado en la parte superior
|
|
8
|
-
* - Tabla de runtimes detectados (nombre, scope, versión instalada, estado)
|
|
9
|
-
* - Pie con atajos: Enter continuar / Esc salir
|
|
10
|
-
*
|
|
11
|
-
* No-TTY: imprime versión texto plano y retorna { continuar: true } inmediatamente.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
const path = require('path');
|
|
15
|
-
|
|
16
|
-
const render = require('../lib/render');
|
|
17
|
-
const teclas = require('../lib/teclas');
|
|
18
|
-
const { colores, semantico, iconos } = require('../lib/colores');
|
|
19
|
-
|
|
20
|
-
// Logo en caracteres ASCII art compactos (5 líneas)
|
|
21
|
-
const LOGO = [
|
|
22
|
-
' ███████ ██ ██ ██ ███████ ███████ ███████ ',
|
|
23
|
-
' ██ ██ ██ ██ ██ ██ ██ ',
|
|
24
|
-
' ███████ ██ █ ██ ██ ███████ █████ ███████ ',
|
|
25
|
-
' ██ ██ ███ ██ ██ ██ ██ ██ ',
|
|
26
|
-
' ███████ ███ ███ ███████ ███████ ███████ ███████ ',
|
|
27
|
-
];
|
|
28
|
-
|
|
29
|
-
const SUBTITULO = 'Sistema de ingeniería de software auto-evolutivo multi-runtime';
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Detecta runtimes instalados leyendo desde scripts/lib/detectar-runtime.
|
|
33
|
-
* No falla si la lib no está disponible — devuelve array vacío.
|
|
34
|
-
*/
|
|
35
|
-
function detectarInstalaciones() {
|
|
36
|
-
let detectarRuntimes;
|
|
37
|
-
let cargarEstado;
|
|
38
|
-
try {
|
|
39
|
-
({ detectarRuntimes } = require('../../lib/detectar-runtime'));
|
|
40
|
-
({ cargarEstado } = require('../../lib/estado'));
|
|
41
|
-
} catch (_) {
|
|
42
|
-
return [];
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const runtimes = detectarRuntimes();
|
|
46
|
-
const filas = [];
|
|
47
|
-
for (const runtime of runtimes) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
render.escribirEn(filaTabla
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
render.rellenarDer(colores.dim('
|
|
105
|
-
render.rellenarDer(colores.dim('
|
|
106
|
-
colores.dim('
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
render.rellenarDer(
|
|
117
|
-
render.rellenarDer(f.
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
*
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
console.log(
|
|
151
|
-
console.log(
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
teclado.
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Pantalla Welcome de la TUI de swl-ses.
|
|
5
|
+
*
|
|
6
|
+
* Diseño:
|
|
7
|
+
* - Logo ASCII centrado en la parte superior
|
|
8
|
+
* - Tabla de runtimes detectados (nombre, scope, versión instalada, estado)
|
|
9
|
+
* - Pie con atajos: Enter continuar / Esc salir
|
|
10
|
+
*
|
|
11
|
+
* No-TTY: imprime versión texto plano y retorna { continuar: true } inmediatamente.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const path = require('path');
|
|
15
|
+
|
|
16
|
+
const render = require('../lib/render');
|
|
17
|
+
const teclas = require('../lib/teclas');
|
|
18
|
+
const { colores, semantico, iconos } = require('../lib/colores');
|
|
19
|
+
|
|
20
|
+
// Logo en caracteres ASCII art compactos (5 líneas)
|
|
21
|
+
const LOGO = [
|
|
22
|
+
' ███████ ██ ██ ██ ███████ ███████ ███████ ',
|
|
23
|
+
' ██ ██ ██ ██ ██ ██ ██ ',
|
|
24
|
+
' ███████ ██ █ ██ ██ ███████ █████ ███████ ',
|
|
25
|
+
' ██ ██ ███ ██ ██ ██ ██ ██ ',
|
|
26
|
+
' ███████ ███ ███ ███████ ███████ ███████ ███████ ',
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
const SUBTITULO = 'Sistema de ingeniería de software auto-evolutivo multi-runtime';
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Detecta runtimes instalados leyendo desde scripts/lib/detectar-runtime.
|
|
33
|
+
* No falla si la lib no está disponible — devuelve array vacío.
|
|
34
|
+
*/
|
|
35
|
+
function detectarInstalaciones() {
|
|
36
|
+
let detectarRuntimes;
|
|
37
|
+
let cargarEstado;
|
|
38
|
+
try {
|
|
39
|
+
({ detectarRuntimes, scopesReales } = require('../../lib/detectar-runtime'));
|
|
40
|
+
({ cargarEstado } = require('../../lib/estado'));
|
|
41
|
+
} catch (_) {
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const runtimes = detectarRuntimes();
|
|
46
|
+
const filas = [];
|
|
47
|
+
for (const runtime of runtimes) {
|
|
48
|
+
// Dedup + guard anti-fantasma: desde HOME, el local relativo resuelve al
|
|
49
|
+
// global propio (duplicado) o al de OTRO runtime (p.ej. .claude de
|
|
50
|
+
// OpenClaude = global de Claude Code) — ver scopesReales().
|
|
51
|
+
const dirs = scopesReales(runtime).map(({ dir, esGlobal }) => (
|
|
52
|
+
{ ruta: dir, scope: esGlobal ? 'global' : 'proyecto' }
|
|
53
|
+
));
|
|
54
|
+
for (const { ruta, scope } of dirs) {
|
|
55
|
+
try {
|
|
56
|
+
const estado = cargarEstado(ruta);
|
|
57
|
+
if (!estado) continue;
|
|
58
|
+
filas.push({
|
|
59
|
+
runtime: runtime.nombre,
|
|
60
|
+
scope,
|
|
61
|
+
version: estado.versionSistema || 'desconocida',
|
|
62
|
+
perfil: estado.perfil || '-',
|
|
63
|
+
componentes: estado.componentesInstalados?.length || 0,
|
|
64
|
+
});
|
|
65
|
+
} catch (_) {
|
|
66
|
+
// ignorar errores de lectura
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return filas;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Pinta el contenido completo de la pantalla. Idempotente — se puede invocar
|
|
75
|
+
* múltiples veces (resize, re-render).
|
|
76
|
+
*/
|
|
77
|
+
function _renderizar(filas, version) {
|
|
78
|
+
render.limpiarPantalla();
|
|
79
|
+
const { cols, rows } = render.obtenerDimensiones();
|
|
80
|
+
|
|
81
|
+
// Logo centrado
|
|
82
|
+
const filaLogo = 2;
|
|
83
|
+
for (let i = 0; i < LOGO.length; i++) {
|
|
84
|
+
const linea = LOGO[i];
|
|
85
|
+
const colLogo = Math.max(1, Math.floor((cols - linea.length) / 2));
|
|
86
|
+
render.escribirEn(filaLogo + i, colLogo, semantico.titulo(linea));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Subtítulo + versión
|
|
90
|
+
const filaSub = filaLogo + LOGO.length + 1;
|
|
91
|
+
const subFinal = `${SUBTITULO} ${colores.dim('v' + version)}`;
|
|
92
|
+
const colSub = Math.max(1, Math.floor((cols - render.anchoVisual(subFinal)) / 2));
|
|
93
|
+
render.escribirEn(filaSub, colSub, subFinal);
|
|
94
|
+
|
|
95
|
+
// Tabla de runtimes detectados
|
|
96
|
+
const filaTabla = filaSub + 3;
|
|
97
|
+
if (filas.length === 0) {
|
|
98
|
+
const mensaje = colores.dim('No se detectaron instalaciones SWL en este equipo.');
|
|
99
|
+
const colMsg = Math.max(1, Math.floor((cols - render.anchoVisual(mensaje)) / 2));
|
|
100
|
+
render.escribirEn(filaTabla, colMsg, mensaje);
|
|
101
|
+
} else {
|
|
102
|
+
render.escribirEn(filaTabla - 1, 4, semantico.enfasis('Instalaciones detectadas:'));
|
|
103
|
+
const cabecera =
|
|
104
|
+
render.rellenarDer(colores.dim('Runtime'), 14) +
|
|
105
|
+
render.rellenarDer(colores.dim('Scope'), 10) +
|
|
106
|
+
render.rellenarDer(colores.dim('Versión'), 12) +
|
|
107
|
+
render.rellenarDer(colores.dim('Perfil'), 18) +
|
|
108
|
+
colores.dim('Componentes');
|
|
109
|
+
render.escribirEn(filaTabla, 4, cabecera);
|
|
110
|
+
|
|
111
|
+
filas.slice(0, rows - filaTabla - 4).forEach((f, i) => {
|
|
112
|
+
const estado = f.version === version
|
|
113
|
+
? semantico.exito(iconos.check)
|
|
114
|
+
: semantico.warn(iconos.warn);
|
|
115
|
+
const linea =
|
|
116
|
+
render.rellenarDer(`${estado} ${f.runtime}`, 14) +
|
|
117
|
+
render.rellenarDer(f.scope, 10) +
|
|
118
|
+
render.rellenarDer('v' + f.version, 12) +
|
|
119
|
+
render.rellenarDer(f.perfil, 18) +
|
|
120
|
+
colores.cyan(String(f.componentes));
|
|
121
|
+
render.escribirEn(filaTabla + 1 + i, 4, linea);
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Mensaje central de continuación
|
|
126
|
+
const filaCont = rows - 4;
|
|
127
|
+
const mensaje = `Presiona ${semantico.cursor('Enter')} para continuar al menú principal o ${semantico.cursor('Esc')} para salir.`;
|
|
128
|
+
const colCont = Math.max(1, Math.floor((cols - render.anchoVisual(mensaje)) / 2));
|
|
129
|
+
render.escribirEn(filaCont, colCont, mensaje);
|
|
130
|
+
|
|
131
|
+
// Pie con atajos
|
|
132
|
+
render.dibujarPiePagina([
|
|
133
|
+
['Enter', 'continuar'],
|
|
134
|
+
['Esc', 'salir'],
|
|
135
|
+
]);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Muestra la pantalla Welcome y espera input del usuario.
|
|
140
|
+
*
|
|
141
|
+
* @returns {Promise<{ continuar: boolean, instalaciones: Array }>}
|
|
142
|
+
*/
|
|
143
|
+
function mostrarWelcome() {
|
|
144
|
+
const version = require('../../../package.json').version;
|
|
145
|
+
const filas = detectarInstalaciones();
|
|
146
|
+
|
|
147
|
+
return new Promise((resolve) => {
|
|
148
|
+
// Modo no-TTY: salida texto plano sin esperar input
|
|
149
|
+
if (!render.ES_TTY || !process.stdin.isTTY) {
|
|
150
|
+
console.log('');
|
|
151
|
+
console.log(` swl-ses v${version}`);
|
|
152
|
+
console.log(` ${SUBTITULO}`);
|
|
153
|
+
console.log('');
|
|
154
|
+
if (filas.length > 0) {
|
|
155
|
+
console.log(' Instalaciones detectadas:');
|
|
156
|
+
for (const f of filas) {
|
|
157
|
+
console.log(` ${f.runtime} (${f.scope}): v${f.version}, perfil ${f.perfil}`);
|
|
158
|
+
}
|
|
159
|
+
} else {
|
|
160
|
+
console.log(' No se detectaron instalaciones SWL.');
|
|
161
|
+
}
|
|
162
|
+
console.log('');
|
|
163
|
+
resolve({ continuar: true, instalaciones: filas });
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
render.iniciarModoTui();
|
|
168
|
+
_renderizar(filas, version);
|
|
169
|
+
|
|
170
|
+
// Re-renderizar en resize
|
|
171
|
+
const onResize = () => _renderizar(filas, version);
|
|
172
|
+
process.stdout.on('resize', onResize);
|
|
173
|
+
|
|
174
|
+
const teclado = teclas.crearTeclado();
|
|
175
|
+
|
|
176
|
+
function finalizar(continuar) {
|
|
177
|
+
teclado.desactivar();
|
|
178
|
+
process.stdout.removeListener('resize', onResize);
|
|
179
|
+
render.salirModoTui();
|
|
180
|
+
resolve({ continuar, instalaciones: filas });
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
teclado.on('return', () => finalizar(true));
|
|
184
|
+
teclado.on('escape', () => finalizar(false));
|
|
185
|
+
teclado.activar();
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
module.exports = { mostrarWelcome, detectarInstalaciones, LOGO, SUBTITULO };
|
package/scripts/validar.js
CHANGED
|
@@ -55,7 +55,7 @@ if (fs.existsSync(hooksConfigPath)) {
|
|
|
55
55
|
verificar(hooksEnConfig.length >= 4, `hooks-config.json: ${hooksEnConfig.length} hooks definidos (mínimo 4)`);
|
|
56
56
|
for (const hookName of hooksEnConfig) {
|
|
57
57
|
const hc = hooksConfig.hooks[hookName];
|
|
58
|
-
const eventosValidos = ['PreToolUse', 'PostToolUse', 'Stop', 'Notification', 'SubagentStop', 'UserPromptSubmit', 'PreCompact', 'SessionStart'];
|
|
58
|
+
const eventosValidos = ['PreToolUse', 'PostToolUse', 'Stop', 'Notification', 'SubagentStart', 'SubagentStop', 'UserPromptSubmit', 'PreCompact', 'SessionStart'];
|
|
59
59
|
verificar(
|
|
60
60
|
eventosValidos.includes(hc.event),
|
|
61
61
|
`hooks-config.json: ${hookName} tiene event válido (${hc.event})`
|
|
@@ -329,6 +329,17 @@ function main() {
|
|
|
329
329
|
? ' [OK] Gate evolución: manifiesto al día + fuente sin evolved espurio'
|
|
330
330
|
: ` [FALLA] Gate evolución: ${gateEvolved.problemas.join('; ')}`);
|
|
331
331
|
|
|
332
|
+
// Gate de invariantes: frases load-bearing de manifiestos/invariantes-criticos.json
|
|
333
|
+
// presentes verbatim en sus componentes. Blocking — perder una frase en un
|
|
334
|
+
// reword rompe el contrato cross-componente en silencio.
|
|
335
|
+
const gateInvariantes = ejecutarGateInvariantes();
|
|
336
|
+
if (!gateInvariantes.ok) {
|
|
337
|
+
fallasObligatorias++;
|
|
338
|
+
}
|
|
339
|
+
console.log(gateInvariantes.ok
|
|
340
|
+
? ` [OK] Gate invariantes: ${gateInvariantes.frasesVerificadas} frase(s) load-bearing presentes`
|
|
341
|
+
: ` [FALLA] Gate invariantes: ${gateInvariantes.problemas.join('; ')}`);
|
|
342
|
+
|
|
332
343
|
if (jsonOut) {
|
|
333
344
|
process.stdout.write(JSON.stringify({
|
|
334
345
|
version,
|
|
@@ -343,6 +354,7 @@ function main() {
|
|
|
343
354
|
aiisms_gate: aiismsGate,
|
|
344
355
|
gate_licencias: gateLicencias,
|
|
345
356
|
gate_evolved: gateEvolved,
|
|
357
|
+
gate_invariantes: gateInvariantes,
|
|
346
358
|
resultados: resultados.map(({ entrada, resultado }) => ({
|
|
347
359
|
archivo: entrada.archivo,
|
|
348
360
|
obligatorio: entrada.obligatorio,
|
|
@@ -928,6 +940,44 @@ function ejecutarGateLicencias(baseDir = CWD) {
|
|
|
928
940
|
}
|
|
929
941
|
}
|
|
930
942
|
|
|
943
|
+
/**
|
|
944
|
+
* Gate de invariantes: frases load-bearing declaradas en
|
|
945
|
+
* manifiestos/invariantes-criticos.json deben existir verbatim en sus
|
|
946
|
+
* archivos. Complementa a canonical-hashes (que detecta QUE un archivo
|
|
947
|
+
* cambió) detectando si un reword perdió UNA regla puntual del contrato
|
|
948
|
+
* cross-componente. Blocking: la fricción de actualizar el manifiesto en
|
|
949
|
+
* un reword intencional es el recordatorio de propagar el cambio.
|
|
950
|
+
*
|
|
951
|
+
* @param {string} [baseDir=CWD] - Raíz del repo (inyectable para tests).
|
|
952
|
+
* @returns {{ ok: boolean, disponible: boolean, problemas: string[], frasesVerificadas: number }}
|
|
953
|
+
*/
|
|
954
|
+
function ejecutarGateInvariantes(baseDir = CWD) {
|
|
955
|
+
const manifiestoPath = path.join(baseDir, 'manifiestos', 'invariantes-criticos.json');
|
|
956
|
+
let manifiesto;
|
|
957
|
+
try {
|
|
958
|
+
manifiesto = JSON.parse(fs.readFileSync(manifiestoPath, 'utf8'));
|
|
959
|
+
} catch (err) {
|
|
960
|
+
return { ok: false, disponible: false, problemas: [`manifiesto ilegible: ${err.message}`], frasesVerificadas: 0 };
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
const problemas = [];
|
|
964
|
+
let frasesVerificadas = 0;
|
|
965
|
+
for (const [archivo, frases] of Object.entries(manifiesto.invariantes || {})) {
|
|
966
|
+
const contenido = leerArchivoSeguro(path.join(baseDir, archivo));
|
|
967
|
+
if (contenido === null) {
|
|
968
|
+
problemas.push(`${archivo}: archivo no existe`);
|
|
969
|
+
continue;
|
|
970
|
+
}
|
|
971
|
+
for (const frase of frases) {
|
|
972
|
+
frasesVerificadas++;
|
|
973
|
+
if (!contenido.includes(frase)) {
|
|
974
|
+
problemas.push(`${archivo}: perdió la frase invariante "${frase}"`);
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
return { ok: problemas.length === 0, disponible: true, problemas, frasesVerificadas };
|
|
979
|
+
}
|
|
980
|
+
|
|
931
981
|
if (require.main === module) main();
|
|
932
982
|
|
|
933
983
|
module.exports = {
|
|
@@ -938,4 +988,5 @@ module.exports = {
|
|
|
938
988
|
ejecutarGateDescription,
|
|
939
989
|
ejecutarGateLicencias,
|
|
940
990
|
ejecutarGateEvolved,
|
|
991
|
+
ejecutarGateInvariantes,
|
|
941
992
|
};
|