@saulwade/swl-ses 2.6.1 → 2.8.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 +14 -2
- package/README.md +65 -18
- package/agentes/_intent-spec.md +73 -73
- package/agentes/_propose-step.md +90 -90
- package/bin/swl-ses.js +10 -0
- package/comandos/swl/brainstorm.md +1 -0
- package/comandos/swl/briefing.md +119 -119
- package/comandos/swl/contribuir.md +233 -233
- package/comandos/swl/deuda-codigo.md +97 -97
- package/comandos/swl/mcp-status.md +1 -0
- package/gateway/lib/event-channel.js +191 -191
- package/habilidades/agent-deep-links/SKILL.md +148 -148
- package/habilidades/backend-async-postgres-testing/SKILL.md +216 -216
- package/habilidades/backend-error-design/SKILL.md +221 -221
- package/habilidades/backend-production-resilience/SKILL.md +288 -288
- package/habilidades/calidad-anti-patrones-universales/SKILL.md +105 -1
- package/habilidades/calidad-contract-testing/SKILL.md +165 -165
- package/habilidades/calidad-mutation-testing/SKILL.md +25 -1
- package/habilidades/checklist-seguridad/recursos/stride-cobertura.md +60 -60
- package/habilidades/ci-cd-pipelines/SKILL.md +5 -1
- package/habilidades/css-moderno/SKILL.md +7 -1
- package/habilidades/diagrama-arquitectura/assets/template.html +276 -276
- package/habilidades/doubt-driven-review/recursos/EXAMPLES.md +130 -130
- package/habilidades/estructura-proyecto-claude/recursos/mcp-json-template.json +57 -57
- package/habilidades/extractor-de-aprendizajes/SKILL.md +5 -1
- package/habilidades/feynman-auditor-swl/recursos/preguntas-language-agnostic.md +108 -108
- package/habilidades/harness-claude-code/SKILL.md +3 -2
- package/habilidades/meta-skills-estandar/recursos/convencion-examples.md +93 -93
- package/habilidades/patrones-python/recursos/patrones-avanzados.md +469 -469
- package/habilidades/perfil-usuario/SKILL.md +200 -200
- package/habilidades/prevencion-sobreingenieria/recursos/EXAMPLES.md +580 -580
- package/habilidades/prevencion-sobreingenieria/recursos/soluciones-nativas.md +166 -166
- package/habilidades/prevencion-sobreingenieria/recursos/variables-residuales-post-refactor.md +85 -85
- package/habilidades/proceso-ddia-streaming/SKILL.md +231 -231
- package/habilidades/proceso-discovery-machote/SKILL.md +157 -157
- package/habilidades/proceso-dynamic-workflows/SKILL.md +60 -0
- package/habilidades/proceso-dynamic-workflows/recursos/template-adversarial-verify.js +65 -65
- package/habilidades/proceso-dynamic-workflows/recursos/template-triage.js +65 -65
- package/habilidades/proceso-intent-engineering/SKILL.md +269 -269
- package/habilidades/proceso-modular-split/SKILL.md +256 -256
- package/habilidades/state-inconsistency-auditor-swl/recursos/coupled-state-patterns.md +147 -147
- package/habilidades/swl-claudemd/recursos/contrato-aprender.md +83 -83
- package/habilidades/swl-claudemd/recursos/duplicacion-reglas-globales.md +85 -85
- package/habilidades/swl-claudemd/recursos/plantillas-init.md +94 -94
- package/habilidades/tdd-workflow/recursos/gherkin-bdd.md +111 -111
- package/hooks/calidad-pre-commit.js +159 -10
- package/hooks/ciclo-evolucion-subagente.js +26 -26
- package/hooks/ciclo-evolucion.js +26 -26
- package/hooks/contexto-subagente.js +68 -68
- package/hooks/lib/auto-consolidator.js +335 -335
- package/hooks/lib/ciclo-evolucion.js +47 -47
- package/hooks/lib/deep-links.js +185 -185
- package/hooks/lib/error-classifier.js +308 -308
- package/hooks/lib/notificacion-formato.js +45 -11
- package/hooks/lib/provenance-tracker.js +191 -191
- package/hooks/lib/raiz-proyecto.js +35 -4
- package/hooks/lib/resource-quota.js +122 -122
- package/hooks/lib/retry-jitter.js +165 -165
- package/hooks/lib/security-net.js +201 -201
- 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/notificacion-telegram.js +5 -11
- package/hooks/session-briefing.js +12 -4
- package/instintos/autonomia.yaml +27 -27
- package/instintos/prompt-appendices.yaml +57 -57
- package/llms.txt +1 -1
- package/manifiestos/agent-output-schemas.json +57 -57
- package/manifiestos/canonical-hashes.json +662 -0
- package/manifiestos/harness-ir.json +47536 -0
- package/manifiestos/hooks-config.json +469 -469
- package/manifiestos/invariantes-criticos.json +30 -30
- package/manifiestos/policy-bundle.json +2065 -0
- package/manifiestos/policy-corpus-w2.json +3926 -0
- package/manifiestos/runtime-adapters-core3.json +208 -0
- package/manifiestos/runtime-conformance.json +139 -0
- package/manifiestos/skills-lock.json +43 -43
- package/package.json +2 -2
- package/plantillas/auditor-veto-template.md +105 -105
- 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/accesibilidad.md +10 -10
- package/reglas/auditorias-documentales-estructurales.md +7 -7
- package/reglas/cloud-infra.md +8 -8
- package/reglas/consultar-vault-primero.md +195 -195
- package/reglas/git-workflow.md +1 -0
- package/reglas/hooks.md +6 -6
- package/reglas/intent-engineering.md +218 -218
- package/reglas/markitdown.md +8 -8
- package/reglas/monitor-ci.md +12 -0
- package/reglas/patrones.md +6 -6
- package/reglas/testing.md +7 -7
- package/reglas/tests-cleanup.md +224 -224
- package/schemas/agent-message.schema.json +73 -73
- package/schemas/agent-output-implementacion.schema.json +114 -114
- package/schemas/agent-output-planificacion.schema.json +150 -150
- package/schemas/agent-output-review.schema.json +98 -98
- package/schemas/diary-entry.schema.json +112 -112
- package/schemas/gate-state.schema.json +76 -0
- package/schemas/harness-ir.schema.json +369 -0
- package/schemas/hook-profiles.schema.json +54 -54
- package/schemas/hooks-config.schema.json +89 -89
- package/schemas/legacy-gates.schema.json +45 -0
- package/schemas/modulos.schema.json +38 -38
- package/schemas/perfiles.schema.json +36 -36
- package/schemas/plugin.schema.json +77 -77
- package/schemas/policy-bundle.schema.json +140 -0
- package/schemas/policy-enforcement.schema.json +117 -0
- package/schemas/policy-operation.schema.json +261 -0
- package/schemas/runtime-adapter.schema.json +176 -0
- package/schemas/runtime-build-attestation.schema.json +100 -0
- package/schemas/runtime-conformance.schema.json +239 -0
- package/schemas/runtime-diagnostic.schema.json +395 -0
- package/schemas/skill-evals.schema.json +119 -119
- package/schemas/skill-frontmatter.schema.json +245 -245
- package/schemas/w4-certification-request.schema.json +72 -0
- package/schemas/w4-certification-verdict.schema.json +224 -0
- package/schemas/w4-corpus.schema.json +172 -0
- package/schemas/w4-mutation-report.schema.json +116 -0
- package/schemas/w4-replay-result.schema.json +164 -0
- package/schemas/w4-scoring-report.schema.json +89 -0
- package/scripts/audit-tools/audit-history.js +330 -330
- package/scripts/audit-tools/bundle-tracker.js +290 -290
- package/scripts/audit-tools/canary-monitor.js +352 -352
- package/scripts/audit-tools/code-profiler.js +605 -605
- package/scripts/audit-tools/dep-doctor.js +320 -320
- package/scripts/audit-tools/env-validator.js +206 -206
- package/scripts/audit-tools/lib/fs-walk.js +48 -48
- package/scripts/audit-tools/lib/output.js +23 -23
- package/scripts/audit-tools/migration-checker.js +392 -392
- package/scripts/audit-tools/pentest-scanner.js +1436 -1436
- package/scripts/bootstrap-instintos.js +3 -0
- package/scripts/cli/aprobar-plan.js +73 -73
- package/scripts/cli/briefing.js +23 -23
- package/scripts/cli/ciclo-evolucion.js +26 -26
- package/scripts/cli/derivar-feature-list.js +25 -25
- package/scripts/cli/detectar-host.js +27 -27
- package/scripts/cli/diary-entry.js +69 -69
- package/scripts/cli/execution-state.js +18 -18
- package/scripts/cli/gateway-notify.js +41 -41
- package/scripts/cli/liberar-fase.js +42 -42
- package/scripts/cli/mark-evolved.js +56 -56
- package/scripts/cli/metricas-dora.js +26 -26
- package/scripts/cli/near-duplicate.js +55 -55
- package/scripts/cli/notificaciones.js +123 -123
- package/scripts/cli/propose-step.js +29 -29
- package/scripts/cli/schedule-parse.js +19 -19
- package/scripts/cli/sugerir-modelo.js +20 -20
- package/scripts/cli/verificar-plan.js +36 -36
- package/scripts/cli/verificar-trazabilidad.js +35 -35
- package/scripts/comandos/install-asistido.js +8 -7
- package/scripts/configurar-branch-protection.js +418 -418
- package/scripts/detectar-aprendizajes-duplicados.js +151 -151
- package/scripts/doctor.js +61 -36
- package/scripts/generar-checklists-consolidados.js +273 -273
- package/scripts/generar-claims-runtime.js +1342 -0
- package/scripts/generar-harness-ir.js +257 -0
- package/scripts/generar-inventario.js +52 -54
- package/scripts/generar-policy-bundle.js +202 -0
- package/scripts/instalador.js +26 -7
- package/scripts/lib/approval-receipts.js +190 -0
- 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/certificacion-loop-state.js +421 -0
- package/scripts/lib/ci-reader.js +193 -193
- package/scripts/lib/ciclo-autonomo/yaml-instintos.js +56 -0
- package/scripts/lib/clasificar-directorio.js +92 -0
- package/scripts/lib/contadores-inventario.js +217 -217
- package/scripts/lib/detectar-host-swl.js +175 -175
- package/scripts/lib/detectar-runtime.js +29 -20
- package/scripts/lib/detectar-stack-detallado.js +307 -307
- package/scripts/lib/detector-autoduplicacion-intra-archivo.js +234 -234
- package/scripts/lib/detector-reglas-duplicadas.js +220 -220
- 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/evidence-verifier.js +192 -0
- package/scripts/lib/evidencia-release.js +322 -322
- package/scripts/lib/frontmatter-canonico.js +509 -0
- package/scripts/lib/gate-engine.js +871 -0
- package/scripts/lib/gate-hooks-requires.js +249 -249
- package/scripts/lib/gate-licencias.js +212 -212
- package/scripts/lib/git-config-preflight.js +48 -0
- package/scripts/lib/git-metricas.js +257 -257
- package/scripts/lib/harness-ir.js +778 -0
- package/scripts/lib/harness-source-snapshot.js +309 -0
- package/scripts/lib/integrity-ledger.js +1147 -0
- package/scripts/lib/jaccard-similarity.js +98 -98
- package/scripts/lib/legacy-gate-migration.js +324 -0
- package/scripts/lib/limpiar-basura-global.js +45 -2
- package/scripts/lib/longmemeval-runner.js +125 -125
- package/scripts/lib/metricas-dora.js +204 -204
- package/scripts/lib/notificaciones-telegram.js +1 -0
- package/scripts/lib/npm-version.js +1 -0
- package/scripts/lib/paquetes-conocidos.js +50 -50
- package/scripts/lib/plan-lock.js +61 -13
- package/scripts/lib/policy-broker.js +338 -0
- package/scripts/lib/policy-bundle.js +342 -0
- package/scripts/lib/policy-context-provider.js +310 -0
- package/scripts/lib/policy-contract.js +479 -0
- package/scripts/lib/policy-verifier-utils.js +65 -0
- package/scripts/lib/pr-analyzer.js +399 -399
- package/scripts/lib/principal-verifier.js +178 -0
- package/scripts/lib/prompt-builder.js +264 -264
- package/scripts/lib/resolver-plan-fase.js +37 -37
- package/scripts/lib/rrf-fusion.js +175 -175
- package/scripts/lib/runtime-adapter-contract.js +267 -0
- package/scripts/lib/runtime-artifact-verifier.js +426 -0
- package/scripts/lib/runtime-build-attestation.js +127 -0
- package/scripts/lib/runtime-bundle-installer.js +586 -0
- package/scripts/lib/runtime-compiler.js +327 -0
- package/scripts/lib/runtime-conformance.js +202 -0
- package/scripts/lib/runtime-doctor-core3.js +567 -0
- package/scripts/lib/runtime-doctor-input.js +59 -0
- package/scripts/lib/runtime-operation-adapter.js +267 -0
- package/scripts/lib/schema-version.js +164 -164
- package/scripts/lib/semantic-search.js +252 -252
- package/scripts/lib/signed-envelope.js +545 -0
- package/scripts/lib/single-use-store.js +359 -0
- package/scripts/lib/skills-externas.js +31 -0
- package/scripts/lib/transformadores/codex.js +15 -8
- package/scripts/lib/transformadores/gemini.js +79 -5
- package/scripts/lib/w4-attestation-adapter.js +158 -0
- package/scripts/lib/w4-canario.js +337 -0
- package/scripts/lib/w4-claims.js +182 -0
- package/scripts/lib/w4-corpus-generador.js +542 -0
- package/scripts/lib/w4-gate-c5.js +115 -0
- package/scripts/lib/w4-harness-bajo-prueba.js +155 -0
- package/scripts/lib/w4-matriz-combos.js +55 -0
- package/scripts/lib/w4-motor-mutacion.js +1348 -0
- package/scripts/lib/w4-motor-replay.js +735 -0
- package/scripts/lib/w4-pin-origen.js +54 -0
- package/scripts/lib/w4-publicar-request.js +132 -0
- package/scripts/lib/w4-revocacion.js +62 -0
- package/scripts/lib/w4-runtimes-core3.js +38 -0
- package/scripts/lib/w4-scorer-certificacion.js +692 -0
- package/scripts/lib/w4-superficie-candidato.js +49 -0
- package/scripts/lib/w4-veredicto.js +452 -0
- package/scripts/lib/w4-verificar-veredicto.js +302 -0
- package/scripts/limpiar-artefactos-python.js +131 -131
- package/scripts/migrar-csv-a-array.js +168 -168
- package/scripts/migrar-fase-dominio.js +200 -200
- package/scripts/migrar-gates-legacy.js +108 -0
- package/scripts/publicar-certification-request.js +115 -0
- package/scripts/runtime-doctor.js +107 -0
- package/scripts/tui/componentes/selector-multi.js +189 -189
- package/scripts/tui/componentes/selector-unico.js +158 -158
- package/scripts/tui/ejecutores.js +375 -375
- package/scripts/tui/lib/colores.js +129 -129
- package/scripts/tui/lib/render.js +264 -264
- package/scripts/tui/lib/teclas.js +113 -113
- package/scripts/tui/pantallas/install-wizard.js +12 -7
- package/scripts/tui/pantallas/menu-principal.js +52 -52
- package/scripts/tui/pantallas/progreso.js +274 -274
- package/scripts/tui/pantallas/resumen.js +132 -132
- package/scripts/validar-userland-vacio.js +110 -110
- package/scripts/verificar-aislamiento-swl-eval.js +87 -0
- package/scripts/verificar-empaquetado-downstream.js +375 -0
- package/scripts/verificar-loop-constructor.js +215 -0
- package/scripts/verificar-trazabilidad.js +13 -6
- package/scripts/verificar-veredicto-real.js +84 -0
|
@@ -1,132 +1,132 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Pantalla Resumen final — se muestra después de Install/Update/Uninstall.
|
|
5
|
-
*
|
|
6
|
-
* Recibe un objeto con totales y muestra:
|
|
7
|
-
* - Bloque hero (éxito/error con color)
|
|
8
|
-
* - Tabla resumen: actualizados, omitidos, errores, tiempo total
|
|
9
|
-
* - Próximos pasos sugeridos según la operación
|
|
10
|
-
*
|
|
11
|
-
* Espera Enter o Esc para cerrar.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
const render = require('../lib/render');
|
|
15
|
-
const teclas = require('../lib/teclas');
|
|
16
|
-
const { colores, semantico, iconos } = require('../lib/colores');
|
|
17
|
-
|
|
18
|
-
const PROXIMOS_PASOS = {
|
|
19
|
-
install: [
|
|
20
|
-
'Verifica la salud del sistema: swl-ses doctor',
|
|
21
|
-
'Lista los skills instalados: swl-ses skills list',
|
|
22
|
-
'Ejecuta el primer comando: /swl:ayuda (dentro de tu runtime)',
|
|
23
|
-
],
|
|
24
|
-
update: [
|
|
25
|
-
'Verifica los cambios: git diff (en proyectos donde aplicaste)',
|
|
26
|
-
'Revisa el CHANGELOG: swl-ses release notes',
|
|
27
|
-
'Comprueba la salud: swl-ses doctor',
|
|
28
|
-
],
|
|
29
|
-
uninstall: [
|
|
30
|
-
'El directorio _userland/ se preservó por defecto.',
|
|
31
|
-
'Las memorias y APRENDIZAJES.md no fueron tocados.',
|
|
32
|
-
'Para reinstalar: swl-ses install',
|
|
33
|
-
],
|
|
34
|
-
inspect: [
|
|
35
|
-
'Para actualizar: swl-ses update',
|
|
36
|
-
'Para reinstalar: swl-ses install --force',
|
|
37
|
-
],
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* @param {object} datos
|
|
42
|
-
* @param {string} datos.operacion - 'install' | 'update' | 'uninstall' | 'inspect'
|
|
43
|
-
* @param {boolean} datos.ok
|
|
44
|
-
* @param {string} datos.tituloPrincipal
|
|
45
|
-
* @param {string} [datos.mensajeFinal]
|
|
46
|
-
* @param {Array<[string, string]>} [datos.tabla] - filas [clave, valor]
|
|
47
|
-
* @param {string[]} [datos.proximosPasos] - sobrescribe los defaults
|
|
48
|
-
* @returns {Promise<void>}
|
|
49
|
-
*/
|
|
50
|
-
function mostrarResumen(datos) {
|
|
51
|
-
const proximos = datos.proximosPasos || PROXIMOS_PASOS[datos.operacion] || [];
|
|
52
|
-
const tabla = datos.tabla || [];
|
|
53
|
-
|
|
54
|
-
return new Promise((resolve) => {
|
|
55
|
-
if (!render.ES_TTY || !process.stdin.isTTY) {
|
|
56
|
-
console.log('');
|
|
57
|
-
console.log(` ${datos.ok ? '[OK]' : '[ERROR]'} ${datos.tituloPrincipal}`);
|
|
58
|
-
if (datos.mensajeFinal) console.log(` ${datos.mensajeFinal}`);
|
|
59
|
-
console.log('');
|
|
60
|
-
for (const [k, v] of tabla) {
|
|
61
|
-
console.log(` ${k}: ${v}`);
|
|
62
|
-
}
|
|
63
|
-
if (proximos.length > 0) {
|
|
64
|
-
console.log('');
|
|
65
|
-
console.log(' Próximos pasos:');
|
|
66
|
-
for (const p of proximos) console.log(` - ${p}`);
|
|
67
|
-
}
|
|
68
|
-
console.log('');
|
|
69
|
-
resolve();
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function _renderizar() {
|
|
74
|
-
render.limpiarPantalla();
|
|
75
|
-
const { cols, rows } = render.obtenerDimensiones();
|
|
76
|
-
|
|
77
|
-
// Hero
|
|
78
|
-
const colorHero = datos.ok ? semantico.exito : semantico.error;
|
|
79
|
-
const ico = datos.ok ? iconos.check : iconos.cross;
|
|
80
|
-
const titulo = `${ico} ${datos.tituloPrincipal}`;
|
|
81
|
-
const colTit = Math.max(1, Math.floor((cols - render.anchoVisual(titulo)) / 2));
|
|
82
|
-
render.escribirEn(3, colTit, colores.negrita(colorHero(titulo)));
|
|
83
|
-
|
|
84
|
-
if (datos.mensajeFinal) {
|
|
85
|
-
const mensaje = colores.dim(datos.mensajeFinal);
|
|
86
|
-
const colMsg = Math.max(1, Math.floor((cols - render.anchoVisual(mensaje)) / 2));
|
|
87
|
-
render.escribirEn(5, colMsg, mensaje);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Tabla
|
|
91
|
-
const filaTabla = 7;
|
|
92
|
-
tabla.forEach(([k, v], i) => {
|
|
93
|
-
const linea = render.rellenarDer(colores.dim(k + ':'), 22) + semantico.enfasis(v);
|
|
94
|
-
const colTab = Math.max(1, Math.floor((cols - render.anchoVisual(linea)) / 2));
|
|
95
|
-
render.escribirEn(filaTabla + i, colTab, linea);
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
// Próximos pasos
|
|
99
|
-
if (proximos.length > 0) {
|
|
100
|
-
const filaPasos = filaTabla + tabla.length + 2;
|
|
101
|
-
render.escribirEn(filaPasos, 4, semantico.titulo('Próximos pasos:'));
|
|
102
|
-
proximos.forEach((p, i) => {
|
|
103
|
-
if (filaPasos + 1 + i >= rows - 3) return;
|
|
104
|
-
render.escribirEn(filaPasos + 1 + i, 6,
|
|
105
|
-
`${colores.cyan(iconos.arrow)} ${p}`);
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
render.dibujarPiePagina([
|
|
110
|
-
['Enter|Esc', 'cerrar'],
|
|
111
|
-
]);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
render.iniciarModoTui();
|
|
115
|
-
_renderizar();
|
|
116
|
-
const onResize = () => _renderizar();
|
|
117
|
-
process.stdout.on('resize', onResize);
|
|
118
|
-
|
|
119
|
-
const teclado = teclas.crearTeclado();
|
|
120
|
-
function _finalizar() {
|
|
121
|
-
teclado.desactivar();
|
|
122
|
-
process.stdout.removeListener('resize', onResize);
|
|
123
|
-
render.salirModoTui();
|
|
124
|
-
resolve();
|
|
125
|
-
}
|
|
126
|
-
teclado.on('return', _finalizar);
|
|
127
|
-
teclado.on('escape', _finalizar);
|
|
128
|
-
teclado.activar();
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
module.exports = { mostrarResumen, PROXIMOS_PASOS };
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Pantalla Resumen final — se muestra después de Install/Update/Uninstall.
|
|
5
|
+
*
|
|
6
|
+
* Recibe un objeto con totales y muestra:
|
|
7
|
+
* - Bloque hero (éxito/error con color)
|
|
8
|
+
* - Tabla resumen: actualizados, omitidos, errores, tiempo total
|
|
9
|
+
* - Próximos pasos sugeridos según la operación
|
|
10
|
+
*
|
|
11
|
+
* Espera Enter o Esc para cerrar.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const render = require('../lib/render');
|
|
15
|
+
const teclas = require('../lib/teclas');
|
|
16
|
+
const { colores, semantico, iconos } = require('../lib/colores');
|
|
17
|
+
|
|
18
|
+
const PROXIMOS_PASOS = {
|
|
19
|
+
install: [
|
|
20
|
+
'Verifica la salud del sistema: swl-ses doctor',
|
|
21
|
+
'Lista los skills instalados: swl-ses skills list',
|
|
22
|
+
'Ejecuta el primer comando: /swl:ayuda (dentro de tu runtime)',
|
|
23
|
+
],
|
|
24
|
+
update: [
|
|
25
|
+
'Verifica los cambios: git diff (en proyectos donde aplicaste)',
|
|
26
|
+
'Revisa el CHANGELOG: swl-ses release notes',
|
|
27
|
+
'Comprueba la salud: swl-ses doctor',
|
|
28
|
+
],
|
|
29
|
+
uninstall: [
|
|
30
|
+
'El directorio _userland/ se preservó por defecto.',
|
|
31
|
+
'Las memorias y APRENDIZAJES.md no fueron tocados.',
|
|
32
|
+
'Para reinstalar: swl-ses install',
|
|
33
|
+
],
|
|
34
|
+
inspect: [
|
|
35
|
+
'Para actualizar: swl-ses update',
|
|
36
|
+
'Para reinstalar: swl-ses install --force',
|
|
37
|
+
],
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @param {object} datos
|
|
42
|
+
* @param {string} datos.operacion - 'install' | 'update' | 'uninstall' | 'inspect'
|
|
43
|
+
* @param {boolean} datos.ok
|
|
44
|
+
* @param {string} datos.tituloPrincipal
|
|
45
|
+
* @param {string} [datos.mensajeFinal]
|
|
46
|
+
* @param {Array<[string, string]>} [datos.tabla] - filas [clave, valor]
|
|
47
|
+
* @param {string[]} [datos.proximosPasos] - sobrescribe los defaults
|
|
48
|
+
* @returns {Promise<void>}
|
|
49
|
+
*/
|
|
50
|
+
function mostrarResumen(datos) {
|
|
51
|
+
const proximos = datos.proximosPasos || PROXIMOS_PASOS[datos.operacion] || [];
|
|
52
|
+
const tabla = datos.tabla || [];
|
|
53
|
+
|
|
54
|
+
return new Promise((resolve) => {
|
|
55
|
+
if (!render.ES_TTY || !process.stdin.isTTY) {
|
|
56
|
+
console.log('');
|
|
57
|
+
console.log(` ${datos.ok ? '[OK]' : '[ERROR]'} ${datos.tituloPrincipal}`);
|
|
58
|
+
if (datos.mensajeFinal) console.log(` ${datos.mensajeFinal}`);
|
|
59
|
+
console.log('');
|
|
60
|
+
for (const [k, v] of tabla) {
|
|
61
|
+
console.log(` ${k}: ${v}`);
|
|
62
|
+
}
|
|
63
|
+
if (proximos.length > 0) {
|
|
64
|
+
console.log('');
|
|
65
|
+
console.log(' Próximos pasos:');
|
|
66
|
+
for (const p of proximos) console.log(` - ${p}`);
|
|
67
|
+
}
|
|
68
|
+
console.log('');
|
|
69
|
+
resolve();
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function _renderizar() {
|
|
74
|
+
render.limpiarPantalla();
|
|
75
|
+
const { cols, rows } = render.obtenerDimensiones();
|
|
76
|
+
|
|
77
|
+
// Hero
|
|
78
|
+
const colorHero = datos.ok ? semantico.exito : semantico.error;
|
|
79
|
+
const ico = datos.ok ? iconos.check : iconos.cross;
|
|
80
|
+
const titulo = `${ico} ${datos.tituloPrincipal}`;
|
|
81
|
+
const colTit = Math.max(1, Math.floor((cols - render.anchoVisual(titulo)) / 2));
|
|
82
|
+
render.escribirEn(3, colTit, colores.negrita(colorHero(titulo)));
|
|
83
|
+
|
|
84
|
+
if (datos.mensajeFinal) {
|
|
85
|
+
const mensaje = colores.dim(datos.mensajeFinal);
|
|
86
|
+
const colMsg = Math.max(1, Math.floor((cols - render.anchoVisual(mensaje)) / 2));
|
|
87
|
+
render.escribirEn(5, colMsg, mensaje);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Tabla
|
|
91
|
+
const filaTabla = 7;
|
|
92
|
+
tabla.forEach(([k, v], i) => {
|
|
93
|
+
const linea = render.rellenarDer(colores.dim(k + ':'), 22) + semantico.enfasis(v);
|
|
94
|
+
const colTab = Math.max(1, Math.floor((cols - render.anchoVisual(linea)) / 2));
|
|
95
|
+
render.escribirEn(filaTabla + i, colTab, linea);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// Próximos pasos
|
|
99
|
+
if (proximos.length > 0) {
|
|
100
|
+
const filaPasos = filaTabla + tabla.length + 2;
|
|
101
|
+
render.escribirEn(filaPasos, 4, semantico.titulo('Próximos pasos:'));
|
|
102
|
+
proximos.forEach((p, i) => {
|
|
103
|
+
if (filaPasos + 1 + i >= rows - 3) return;
|
|
104
|
+
render.escribirEn(filaPasos + 1 + i, 6,
|
|
105
|
+
`${colores.cyan(iconos.arrow)} ${p}`);
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
render.dibujarPiePagina([
|
|
110
|
+
['Enter|Esc', 'cerrar'],
|
|
111
|
+
]);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
render.iniciarModoTui();
|
|
115
|
+
_renderizar();
|
|
116
|
+
const onResize = () => _renderizar();
|
|
117
|
+
process.stdout.on('resize', onResize);
|
|
118
|
+
|
|
119
|
+
const teclado = teclas.crearTeclado();
|
|
120
|
+
function _finalizar() {
|
|
121
|
+
teclado.desactivar();
|
|
122
|
+
process.stdout.removeListener('resize', onResize);
|
|
123
|
+
render.salirModoTui();
|
|
124
|
+
resolve();
|
|
125
|
+
}
|
|
126
|
+
teclado.on('return', _finalizar);
|
|
127
|
+
teclado.on('escape', _finalizar);
|
|
128
|
+
teclado.activar();
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
module.exports = { mostrarResumen, PROXIMOS_PASOS };
|
|
@@ -1,110 +1,110 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
'use strict';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* validar-userland-vacio.js — guard pre-publish.
|
|
6
|
-
*
|
|
7
|
-
* Verifica que `_userland/` solo contenga archivos `.gitkeep` antes de
|
|
8
|
-
* empaquetar el tarball. Si algún contributor accidentalmente commiteó
|
|
9
|
-
* agentes, skills o credenciales experimentales en `_userland/`, este
|
|
10
|
-
* gate aborta el publish con exit 1 y lista los archivos extraños.
|
|
11
|
-
*
|
|
12
|
-
* Por qué existe (defensa en profundidad):
|
|
13
|
-
* `_userland/` es el directorio donde el USUARIO instala su contenido
|
|
14
|
-
* custom. En el repo del sistema debe permanecer vacío (solo
|
|
15
|
-
* `.gitkeep` para preservar la estructura). El campo `files` de
|
|
16
|
-
* package.json incluye `_userland/`, así que cualquier archivo real
|
|
17
|
-
* que se cuele entrará al tarball publicado a npm — exposición
|
|
18
|
-
* potencial de IP o secretos. Aunque `.gitignore` y `.npmignore` ya
|
|
19
|
-
* cubren los vectores típicos (.env, credenciales), este guard
|
|
20
|
-
* garantiza que la regla "_userland/ vacío en distribución" se cumpla
|
|
21
|
-
* determinísticamente.
|
|
22
|
-
*
|
|
23
|
-
* Variables de entorno:
|
|
24
|
-
* SWL_USERLAND_GUARD_ALLOW=archivo1,archivo2 — permite archivos extra
|
|
25
|
-
* (uso excepcional documentado en commit que active la variable).
|
|
26
|
-
*
|
|
27
|
-
* Exit codes:
|
|
28
|
-
* 0 — OK, _userland/ solo contiene .gitkeep
|
|
29
|
-
* 1 — hay archivos extraños; lista impresa a stderr
|
|
30
|
-
* 2 — error de invariante (cwd incorrecto, _userland/ no existe)
|
|
31
|
-
*/
|
|
32
|
-
|
|
33
|
-
const fs = require('fs');
|
|
34
|
-
const path = require('path');
|
|
35
|
-
|
|
36
|
-
const USERLAND_DIR = '_userland';
|
|
37
|
-
const PERMITIDOS_BASE = new Set(['.gitkeep', '.gitignore']);
|
|
38
|
-
|
|
39
|
-
function log(msg) { process.stdout.write(`[userland-guard] ${msg}\n`); }
|
|
40
|
-
function err(msg) { process.stderr.write(`[userland-guard] ERROR: ${msg}\n`); }
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Normaliza una ruta relativa al separador POSIX (`/`) para que la
|
|
44
|
-
* comparación contra la allowlist funcione idéntica en Windows y POSIX.
|
|
45
|
-
*/
|
|
46
|
-
function normalizar(rel) {
|
|
47
|
-
return rel.replace(/\\/g, '/');
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function obtenerExtras() {
|
|
51
|
-
const extras = process.env.SWL_USERLAND_GUARD_ALLOW;
|
|
52
|
-
if (!extras) return new Set();
|
|
53
|
-
return new Set(extras.split(',').map(s => normalizar(s.trim())).filter(Boolean));
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function listarRecursivo(dir, baseDir = dir, acumulador = []) {
|
|
57
|
-
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
58
|
-
for (const entry of entries) {
|
|
59
|
-
const full = path.join(dir, entry.name);
|
|
60
|
-
const rel = normalizar(path.relative(baseDir, full));
|
|
61
|
-
if (entry.isDirectory()) {
|
|
62
|
-
listarRecursivo(full, baseDir, acumulador);
|
|
63
|
-
} else if (entry.isFile()) {
|
|
64
|
-
acumulador.push(rel);
|
|
65
|
-
} else if (entry.isSymbolicLink()) {
|
|
66
|
-
// Symlinks dentro del paquete distribuido son anti-patrón.
|
|
67
|
-
acumulador.push(`${rel} (symlink)`);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
return acumulador;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function main() {
|
|
74
|
-
const cwd = process.cwd();
|
|
75
|
-
const userland = path.join(cwd, USERLAND_DIR);
|
|
76
|
-
|
|
77
|
-
if (!fs.existsSync(userland)) {
|
|
78
|
-
err(`${USERLAND_DIR}/ no existe en ${cwd}. ¿cwd incorrecto?`);
|
|
79
|
-
process.exit(2);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const extrasPermitidos = obtenerExtras();
|
|
83
|
-
const archivos = listarRecursivo(userland);
|
|
84
|
-
|
|
85
|
-
const noPermitidos = archivos.filter(rel => {
|
|
86
|
-
const nombre = path.basename(rel);
|
|
87
|
-
if (PERMITIDOS_BASE.has(nombre)) return false;
|
|
88
|
-
if (extrasPermitidos.has(rel)) return false;
|
|
89
|
-
return true;
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
if (noPermitidos.length > 0) {
|
|
93
|
-
err(`${USERLAND_DIR}/ contiene ${noPermitidos.length} archivo(s) que no deberían distribuirse en el tarball npm:`);
|
|
94
|
-
for (const rel of noPermitidos) {
|
|
95
|
-
err(` - ${USERLAND_DIR}/${rel}`);
|
|
96
|
-
}
|
|
97
|
-
err('');
|
|
98
|
-
err('Acciones posibles:');
|
|
99
|
-
err(` 1. Mover el contenido fuera de ${USERLAND_DIR}/ si es del sistema base`);
|
|
100
|
-
err(` 2. Borrarlo si era código experimental local`);
|
|
101
|
-
err(` 3. Permitir explícitamente con SWL_USERLAND_GUARD_ALLOW="ruta1,ruta2"`);
|
|
102
|
-
err(' (documentar la excepción en el mensaje de commit)');
|
|
103
|
-
process.exit(1);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
log(`OK: ${USERLAND_DIR}/ solo contiene ${archivos.length} archivo(s) permitido(s).`);
|
|
107
|
-
process.exit(0);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
main();
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* validar-userland-vacio.js — guard pre-publish.
|
|
6
|
+
*
|
|
7
|
+
* Verifica que `_userland/` solo contenga archivos `.gitkeep` antes de
|
|
8
|
+
* empaquetar el tarball. Si algún contributor accidentalmente commiteó
|
|
9
|
+
* agentes, skills o credenciales experimentales en `_userland/`, este
|
|
10
|
+
* gate aborta el publish con exit 1 y lista los archivos extraños.
|
|
11
|
+
*
|
|
12
|
+
* Por qué existe (defensa en profundidad):
|
|
13
|
+
* `_userland/` es el directorio donde el USUARIO instala su contenido
|
|
14
|
+
* custom. En el repo del sistema debe permanecer vacío (solo
|
|
15
|
+
* `.gitkeep` para preservar la estructura). El campo `files` de
|
|
16
|
+
* package.json incluye `_userland/`, así que cualquier archivo real
|
|
17
|
+
* que se cuele entrará al tarball publicado a npm — exposición
|
|
18
|
+
* potencial de IP o secretos. Aunque `.gitignore` y `.npmignore` ya
|
|
19
|
+
* cubren los vectores típicos (.env, credenciales), este guard
|
|
20
|
+
* garantiza que la regla "_userland/ vacío en distribución" se cumpla
|
|
21
|
+
* determinísticamente.
|
|
22
|
+
*
|
|
23
|
+
* Variables de entorno:
|
|
24
|
+
* SWL_USERLAND_GUARD_ALLOW=archivo1,archivo2 — permite archivos extra
|
|
25
|
+
* (uso excepcional documentado en commit que active la variable).
|
|
26
|
+
*
|
|
27
|
+
* Exit codes:
|
|
28
|
+
* 0 — OK, _userland/ solo contiene .gitkeep
|
|
29
|
+
* 1 — hay archivos extraños; lista impresa a stderr
|
|
30
|
+
* 2 — error de invariante (cwd incorrecto, _userland/ no existe)
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
const fs = require('fs');
|
|
34
|
+
const path = require('path');
|
|
35
|
+
|
|
36
|
+
const USERLAND_DIR = '_userland';
|
|
37
|
+
const PERMITIDOS_BASE = new Set(['.gitkeep', '.gitignore']);
|
|
38
|
+
|
|
39
|
+
function log(msg) { process.stdout.write(`[userland-guard] ${msg}\n`); }
|
|
40
|
+
function err(msg) { process.stderr.write(`[userland-guard] ERROR: ${msg}\n`); }
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Normaliza una ruta relativa al separador POSIX (`/`) para que la
|
|
44
|
+
* comparación contra la allowlist funcione idéntica en Windows y POSIX.
|
|
45
|
+
*/
|
|
46
|
+
function normalizar(rel) {
|
|
47
|
+
return rel.replace(/\\/g, '/');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function obtenerExtras() {
|
|
51
|
+
const extras = process.env.SWL_USERLAND_GUARD_ALLOW;
|
|
52
|
+
if (!extras) return new Set();
|
|
53
|
+
return new Set(extras.split(',').map(s => normalizar(s.trim())).filter(Boolean));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function listarRecursivo(dir, baseDir = dir, acumulador = []) {
|
|
57
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
58
|
+
for (const entry of entries) {
|
|
59
|
+
const full = path.join(dir, entry.name);
|
|
60
|
+
const rel = normalizar(path.relative(baseDir, full));
|
|
61
|
+
if (entry.isDirectory()) {
|
|
62
|
+
listarRecursivo(full, baseDir, acumulador);
|
|
63
|
+
} else if (entry.isFile()) {
|
|
64
|
+
acumulador.push(rel);
|
|
65
|
+
} else if (entry.isSymbolicLink()) {
|
|
66
|
+
// Symlinks dentro del paquete distribuido son anti-patrón.
|
|
67
|
+
acumulador.push(`${rel} (symlink)`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return acumulador;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function main() {
|
|
74
|
+
const cwd = process.cwd();
|
|
75
|
+
const userland = path.join(cwd, USERLAND_DIR);
|
|
76
|
+
|
|
77
|
+
if (!fs.existsSync(userland)) {
|
|
78
|
+
err(`${USERLAND_DIR}/ no existe en ${cwd}. ¿cwd incorrecto?`);
|
|
79
|
+
process.exit(2);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const extrasPermitidos = obtenerExtras();
|
|
83
|
+
const archivos = listarRecursivo(userland);
|
|
84
|
+
|
|
85
|
+
const noPermitidos = archivos.filter(rel => {
|
|
86
|
+
const nombre = path.basename(rel);
|
|
87
|
+
if (PERMITIDOS_BASE.has(nombre)) return false;
|
|
88
|
+
if (extrasPermitidos.has(rel)) return false;
|
|
89
|
+
return true;
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
if (noPermitidos.length > 0) {
|
|
93
|
+
err(`${USERLAND_DIR}/ contiene ${noPermitidos.length} archivo(s) que no deberían distribuirse en el tarball npm:`);
|
|
94
|
+
for (const rel of noPermitidos) {
|
|
95
|
+
err(` - ${USERLAND_DIR}/${rel}`);
|
|
96
|
+
}
|
|
97
|
+
err('');
|
|
98
|
+
err('Acciones posibles:');
|
|
99
|
+
err(` 1. Mover el contenido fuera de ${USERLAND_DIR}/ si es del sistema base`);
|
|
100
|
+
err(` 2. Borrarlo si era código experimental local`);
|
|
101
|
+
err(` 3. Permitir explícitamente con SWL_USERLAND_GUARD_ALLOW="ruta1,ruta2"`);
|
|
102
|
+
err(' (documentar la excepción en el mensaje de commit)');
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
log(`OK: ${USERLAND_DIR}/ solo contiene ${archivos.length} archivo(s) permitido(s).`);
|
|
107
|
+
process.exit(0);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
main();
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* CLI (wrapper de EFECTO) que PRE-CHEQUEA el gate C5 de aislamiento contra la
|
|
5
|
+
* config viva de swl-eval vía `gh api` (solo lectura) y evalúa con la lógica
|
|
6
|
+
* pura `scripts/lib/w4-gate-c5.js`. T-09, ADR-0053 pieza 3, ADR-0056.
|
|
7
|
+
*
|
|
8
|
+
* ES UN HINT LOCAL, NO EVIDENCIA CERTIFICANTE — lo corre la máquina del maker
|
|
9
|
+
* (el evaluado no produce la evidencia que lo aprueba). Fail-closed: un 403 al
|
|
10
|
+
* listar org secrets se reporta RED, nunca GREEN. Sin efectos al require;
|
|
11
|
+
* `deps.ejecutor` es inyectable.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const { execFileSync } = require('node:child_process');
|
|
15
|
+
|
|
16
|
+
const { evaluarGateC5 } = require('./lib/w4-gate-c5');
|
|
17
|
+
const { OWNER, REPO } = require('./lib/w4-pin-origen');
|
|
18
|
+
|
|
19
|
+
function ghJson(ejecutor, args) {
|
|
20
|
+
return JSON.parse(ejecutor('gh', args));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Intenta una lectura; devuelve `{ok, valor}` sin lanzar (fail-closed arriba). */
|
|
24
|
+
function intentar(fn) {
|
|
25
|
+
try {
|
|
26
|
+
return { ok: true, valor: fn() };
|
|
27
|
+
} catch {
|
|
28
|
+
return { ok: false, valor: null };
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function normalizarBranchPolicy(env) {
|
|
33
|
+
const politica = env && env.deployment_branch_policy;
|
|
34
|
+
if (!politica) return 'none';
|
|
35
|
+
if (politica.protected_branches) return 'protected';
|
|
36
|
+
if (politica.custom_branch_policies) return 'custom';
|
|
37
|
+
return 'none';
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function extraerReviewers(env) {
|
|
41
|
+
const reglas = (env && env.protection_rules) || [];
|
|
42
|
+
return reglas
|
|
43
|
+
.filter((r) => r && r.type === 'required_reviewers')
|
|
44
|
+
.flatMap((r) => (r.reviewers || []).map((x) => x.reviewer && x.reviewer.login).filter(Boolean));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function recolectarObservaciones(ejecutor) {
|
|
48
|
+
const env = intentar(() => ghJson(ejecutor, ['api', `repos/${REPO}/environments/certificacion`]));
|
|
49
|
+
const repoSecrets = intentar(() => ghJson(ejecutor, ['api', `repos/${REPO}/actions/secrets`]).total_count);
|
|
50
|
+
const orgSecrets = intentar(() => ghJson(ejecutor, ['api', `orgs/${OWNER}/actions/secrets`]).total_count);
|
|
51
|
+
const envSecrets = intentar(() => ghJson(ejecutor, ['api', `repos/${REPO}/environments/certificacion/secrets`])
|
|
52
|
+
.secrets.map((s) => s.name));
|
|
53
|
+
const perms = intentar(() => ghJson(ejecutor, ['api', `repos/${REPO}`]).permissions);
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
deploymentBranchPolicy: env.ok ? normalizarBranchPolicy(env.valor) : null,
|
|
57
|
+
canAdminsBypass: env.ok ? (env.valor.can_admins_bypass ?? null) : null,
|
|
58
|
+
repoSecretsCount: repoSecrets.ok ? repoSecrets.valor : null,
|
|
59
|
+
orgSecretsListable: orgSecrets.ok,
|
|
60
|
+
orgSecretsCount: orgSecrets.ok ? orgSecrets.valor : null,
|
|
61
|
+
envSecrets: envSecrets.ok ? envSecrets.valor : [],
|
|
62
|
+
requiredReviewers: env.ok ? extraerReviewers(env.valor) : null,
|
|
63
|
+
ejecutorPermissions: perms.ok
|
|
64
|
+
? { admin: !!perms.valor.admin, push: !!perms.valor.push, maintain: !!perms.valor.maintain }
|
|
65
|
+
: null,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function main(opciones = {}) {
|
|
70
|
+
const ejecutor = (opciones.deps && opciones.deps.ejecutor)
|
|
71
|
+
|| ((cmd, args) => execFileSync(cmd, args, { encoding: 'utf8' }));
|
|
72
|
+
const observaciones = opciones.observaciones || recolectarObservaciones(ejecutor);
|
|
73
|
+
const resultado = evaluarGateC5(observaciones);
|
|
74
|
+
return { observaciones, resultado };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
module.exports = { main, recolectarObservaciones, normalizarBranchPolicy, extraerReviewers };
|
|
78
|
+
|
|
79
|
+
if (require.main === module) {
|
|
80
|
+
const { resultado } = main();
|
|
81
|
+
process.stdout.write(`Gate C5 (HINT local, no certificante) — resumen: ${resultado.resumen}\n`);
|
|
82
|
+
for (const c of resultado.clausulas) {
|
|
83
|
+
process.stdout.write(` [${c.estado}] ${c.id} ${c.titulo}\n ${c.detalle}\n`);
|
|
84
|
+
}
|
|
85
|
+
process.stdout.write(`\n${resultado.nota}\n`);
|
|
86
|
+
process.exit(resultado.resumen === 'GREEN' ? 0 : 1);
|
|
87
|
+
}
|