@saulwade/swl-ses 2.6.0 → 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 +209 -197
- package/README.md +647 -600
- package/agentes/accesibilidad-wcag-swl.md +690 -690
- package/agentes/arquitecto-swl.md +267 -267
- package/agentes/auto-evolucion-swl.md +932 -932
- 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-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/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/investigador-swl.md +432 -432
- package/agentes/investigador-ux-swl.md +505 -505
- 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/observabilidad-swl.md +438 -438
- 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/revisor-angular-swl.md +278 -278
- 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/tdd-qa-swl.md +393 -393
- package/bin/swl-ses.js +10 -0
- package/comandos/swl/actualizar.md +174 -174
- package/comandos/swl/adoptar-proyecto.md +265 -265
- package/comandos/swl/aprender.md +836 -836
- package/comandos/swl/aprobar-plan.md +146 -146
- package/comandos/swl/auditar-deps.md +134 -134
- package/comandos/swl/autoresearch.md +264 -264
- package/comandos/swl/ayuda.md +224 -224
- package/comandos/swl/brainstorm.md +52 -51
- package/comandos/swl/checkpoint.md +325 -325
- package/comandos/swl/claudemd.md +234 -234
- package/comandos/swl/compactar.md +310 -310
- package/comandos/swl/configurar-ci.md +235 -235
- package/comandos/swl/contexto.md +110 -110
- package/comandos/swl/crear-skill.md +292 -292
- package/comandos/swl/cron.md +194 -194
- package/comandos/swl/deuda-codigo.md +97 -97
- package/comandos/swl/discutir-fase.md +169 -169
- package/comandos/swl/ejecutar-fase.md +233 -233
- package/comandos/swl/evaluar-skill.md +520 -520
- package/comandos/swl/evolucion-continua.md +73 -73
- package/comandos/swl/evolucionar.md +267 -267
- package/comandos/swl/exportar-vault.md +583 -583
- package/comandos/swl/fix.md +118 -118
- package/comandos/swl/gateway.md +158 -158
- package/comandos/swl/inbox.md +116 -116
- package/comandos/swl/instalar.md +220 -220
- package/comandos/swl/instintos.md +86 -86
- package/comandos/swl/mapear-codebase.md +312 -312
- package/comandos/swl/mcp-status.md +176 -175
- package/comandos/swl/modelo.md +100 -100
- package/comandos/swl/nemesis.md +433 -433
- package/comandos/swl/notificaciones.md +299 -299
- package/comandos/swl/nuevo-proyecto.md +251 -251
- package/comandos/swl/planear-fase.md +263 -263
- package/comandos/swl/plugins.md +256 -256
- package/comandos/swl/predecir.md +169 -169
- package/comandos/swl/reflect-skills.md +125 -125
- package/comandos/swl/release.md +450 -450
- package/comandos/swl/revisar-impacto.md +201 -201
- package/comandos/swl/revisar.md +330 -330
- package/comandos/swl/seguridad.md +189 -189
- package/comandos/swl/sesiones.md +200 -200
- package/comandos/swl/skill-search.md +113 -113
- package/comandos/swl/status.md +345 -345
- package/comandos/swl/verificar.md +817 -817
- package/comandos/swl/wiki.md +620 -620
- package/gateway/cron/jobs.example.json +12 -12
- package/gateway/lib/event-channel.js +191 -191
- package/habilidades/agent-deep-links/SKILL.md +148 -148
- package/habilidades/auto-evolucion-protocolo/SKILL.md +294 -294
- package/habilidades/backend-async-postgres-testing/SKILL.md +216 -215
- 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/changelog-generator/SKILL.md +174 -174
- package/habilidades/checklist-seguridad/recursos/stride-cobertura.md +60 -60
- package/habilidades/ci-cd-pipelines/SKILL.md +5 -1
- package/habilidades/compactacion-contexto/SKILL.md +2 -1
- package/habilidades/contenedores-docker/SKILL.md +4 -2
- package/habilidades/css-moderno/SKILL.md +7 -1
- package/habilidades/diagrama-arquitectura/assets/template.html +276 -276
- package/habilidades/doubt-driven-review/SKILL.md +207 -207
- package/habilidades/doubt-driven-review/recursos/EXAMPLES.md +130 -130
- package/habilidades/drift-detection/SKILL.md +1 -1
- package/habilidades/ejecutar-task-iterativo/SKILL.md +278 -278
- package/habilidades/estructura-proyecto-claude/recursos/mcp-json-template.json +57 -57
- package/habilidades/extractor-de-aprendizajes/SKILL.md +12 -2
- package/habilidades/feynman-auditor-swl/recursos/preguntas-language-agnostic.md +108 -108
- package/habilidades/git-worktrees-paralelo/SKILL.md +19 -1
- package/habilidades/harness-claude-code/SKILL.md +315 -314
- package/habilidades/instalar-sistema/SKILL.md +227 -227
- 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/planear-fase/SKILL.md +358 -358
- package/habilidades/prevencion-sobreingenieria/recursos/EXAMPLES.md +580 -580
- 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-ingenieria-requerimientos/SKILL.md +147 -147
- package/habilidades/proceso-intent-engineering/SKILL.md +269 -269
- package/habilidades/proceso-modular-split/SKILL.md +256 -256
- package/habilidades/release-semver/SKILL.md +2 -2
- 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/SKILL.md +749 -749
- package/habilidades/tdd-workflow/recursos/gherkin-bdd.md +111 -111
- package/hooks/agente-lifecycle.js +1 -1
- package/hooks/audit-trail.js +1 -1
- package/hooks/auto-consolidacion.js +1 -1
- package/hooks/calidad-pre-commit.js +159 -10
- package/hooks/captura-acciones-post.js +1 -1
- package/hooks/captura-acciones-session.js +1 -1
- package/hooks/captura-feedback-usuario.js +1 -1
- package/hooks/ciclo-evolucion-subagente.js +26 -26
- package/hooks/ciclo-evolucion.js +26 -26
- package/hooks/contexto-iteracion.js +1 -1
- package/hooks/degradacion-instintos.js +1 -1
- package/hooks/grafo-contexto.js +1 -1
- package/hooks/guardrail-modelo.js +1 -1
- package/hooks/inbox-aviso.js +1 -1
- package/hooks/inyeccion-contexto.js +1 -1
- package/hooks/lib/agent-matcher.js +1 -1
- package/hooks/lib/agent-routing.js +1 -1
- package/hooks/lib/auto-consolidator.js +335 -335
- package/hooks/lib/captura-acciones.js +1 -1
- 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/etapa-metricas.js +1 -1
- package/hooks/lib/evolution-tracker.js +1 -1
- package/hooks/lib/gateway-notify.js +193 -193
- package/hooks/lib/mcp-health.js +1 -1
- package/hooks/lib/notificacion-formato.js +92 -0
- package/hooks/lib/nudge-tracker.js +1 -1
- package/hooks/lib/otlp-exporter.js +1 -1
- package/hooks/lib/propose-step.js +1 -1
- package/hooks/lib/provenance-tracker.js +191 -191
- package/hooks/lib/raiz-proyecto.js +158 -102
- package/hooks/lib/resource-quota.js +122 -122
- package/hooks/lib/retry-jitter.js +165 -165
- package/hooks/lib/run-log.js +1 -1
- package/hooks/lib/security-net.js +201 -201
- package/hooks/lib/singleton-guard.js +20 -13
- 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/telegram-cliente.js +11 -3
- package/hooks/lib/text-similarity.js +241 -241
- package/hooks/lib/toon-compressor.js +245 -245
- package/hooks/notificacion-telegram.js +17 -13
- package/hooks/preservar-estado-pre-compact.js +1 -1
- package/hooks/registro-turnos.js +1 -1
- package/hooks/resumen-sesion.js +1 -1
- package/hooks/risk-scoring.js +1 -1
- package/hooks/session-briefing.js +13 -5
- package/hooks/spec-gate.js +1 -1
- package/hooks/sugerir-regenerar-inventario.js +1 -1
- package/hooks/tdd-gate.js +1 -1
- package/hooks/telemetria-agentes.js +1 -1
- package/hooks/telemetria-skill-routing.js +1 -1
- package/hooks/tracking-costos.js +1 -1
- package/hooks/validar-formato-post-subagente.js +1 -1
- package/hooks/validar-intent-spec.js +1 -1
- package/hooks/validar-planning-paths.js +1 -1
- package/instintos/autonomia.yaml +27 -27
- package/instintos/prompt-appendices.yaml +57 -57
- package/llms.txt +29 -29
- package/manifiestos/agent-output-schemas.json +57 -57
- package/manifiestos/canonical-hashes.json +6250 -5257
- package/manifiestos/harness-ir.json +47536 -0
- package/manifiestos/modulos.json +1429 -1428
- 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 +1275 -1275
- package/package.json +94 -94
- 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 +369 -369
- 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/auditar-clases-conocidas.js +134 -134
- package/scripts/bootstrap-instintos.js +88 -14
- package/scripts/canario-hooks.js +166 -166
- package/scripts/cli/aprobar-plan.js +73 -73
- package/scripts/cli/autonomia.js +23 -23
- package/scripts/cli/benchmark-memoria.js +37 -37
- package/scripts/cli/briefing.js +23 -23
- package/scripts/cli/ciclo-autonomo.js +73 -73
- package/scripts/cli/ciclo-evolucion.js +26 -26
- package/scripts/cli/ciclo-fase-b.js +102 -102
- 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/guardrail-metrics.js +39 -39
- package/scripts/cli/liberar-fase.js +42 -42
- package/scripts/cli/mark-evolved.js +56 -56
- package/scripts/cli/memoria-search.js +69 -69
- 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/nudge-accionar.js +39 -39
- package/scripts/cli/propose-step.js +29 -29
- package/scripts/cli/run-eval.js +38 -38
- 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 -13
- package/scripts/evidencia-valor.js +101 -101
- package/scripts/field-report.js +16 -16
- 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 +39 -7
- package/scripts/lib/activar-hooks-proyecto.js +116 -116
- 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/candidatos.js +174 -174
- package/scripts/lib/ciclo-autonomo/config.js +165 -165
- package/scripts/lib/ciclo-autonomo/drenador-feedback.js +174 -174
- package/scripts/lib/ciclo-autonomo/fallback.js +77 -77
- package/scripts/lib/ciclo-autonomo/guard-convivencia.js +139 -139
- package/scripts/lib/ciclo-autonomo/higiene-nudges.js +112 -112
- package/scripts/lib/ciclo-autonomo/index.js +301 -301
- package/scripts/lib/ciclo-autonomo/lock.js +124 -124
- package/scripts/lib/ciclo-autonomo/presupuesto.js +122 -122
- package/scripts/lib/ciclo-autonomo/puente-degradacion.js +240 -240
- package/scripts/lib/ciclo-autonomo/runner-fase-b.js +248 -248
- package/scripts/lib/ciclo-autonomo/writer-instintos.js +190 -190
- package/scripts/lib/ciclo-autonomo/yaml-instintos.js +591 -535
- 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/evidencia-valor.js +228 -228
- package/scripts/lib/expandir-targets.js +71 -71
- 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 +204 -0
- 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/toml-merge.js +204 -204
- 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/mcp-server/auth.js +105 -105
- package/scripts/mcp-server/cache.js +106 -106
- 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 +408 -403
- 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
- package/instintos/.backups/perfil-usuario.yaml.2026-07-10-165128.bak +0 -53
- package/instintos/.backups/proyecto.yaml.2026-07-10-165128.bak +0 -372
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Ciclo aislado pack -> install -> doctor -> update -> uninstall sobre el
|
|
6
|
+
* TARBALL real que `npm pack` produciría — no el árbol fuente. Detecta la
|
|
7
|
+
* clase de bug histórica "declarado en package.json#files pero el contenido
|
|
8
|
+
* empaquetado está roto/incompleto" (gateway/ ausente antes de v1.4.0,
|
|
9
|
+
* ver CLAUDE.md § package.json#files) que ni los tests unitarios ni el
|
|
10
|
+
* gate de sincronización de manifiestos pueden atrapar, porque ambos leen
|
|
11
|
+
* el árbol fuente, no lo que realmente viaja en el tarball.
|
|
12
|
+
*
|
|
13
|
+
* Fase "update": el subcomando `update` real compara la versión local
|
|
14
|
+
* contra el registro npm (`npm view`) y, si el paquete local difiere del
|
|
15
|
+
* publicado, se salta el reinstalo ANTES de evaluar `--force`
|
|
16
|
+
* (scripts/actualizar.js) — no determinista en desarrollo local con una
|
|
17
|
+
* versión sin publicar (local 3.0.0 vs. remoto real 2.6.1 al momento de
|
|
18
|
+
* escribir este script). Ejercitar el subcomando `update` real produciría
|
|
19
|
+
* un no-op silencioso que fingiría cobertura sin probar nada. Esta fase en
|
|
20
|
+
* su lugar corre `update --check` (solo lectura, tolerante a falta de red)
|
|
21
|
+
* MÁS un reinstall en sitio con los mismos flags del install inicial — el
|
|
22
|
+
* mecanismo real que `update()` invoca internamente (`instalador()` con
|
|
23
|
+
* `force:true`) cuando SÍ decide actualizar — probando así el camino de
|
|
24
|
+
* re-aplicación idempotente sin depender del estado del registro npm.
|
|
25
|
+
*
|
|
26
|
+
* Exit codes: 0 OK, 1 si cualquier fase falla.
|
|
27
|
+
*
|
|
28
|
+
* Uso: node scripts/verificar-empaquetado-downstream.js [--keep-tmp]
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
const { spawnSync } = require('node:child_process');
|
|
32
|
+
const fs = require('node:fs');
|
|
33
|
+
const path = require('node:path');
|
|
34
|
+
const os = require('node:os');
|
|
35
|
+
|
|
36
|
+
const { comandoNpm } = require('./lib/npm-version');
|
|
37
|
+
|
|
38
|
+
const RAIZ = path.resolve(__dirname, '..');
|
|
39
|
+
const KEEP_TMP = process.argv.includes('--keep-tmp');
|
|
40
|
+
|
|
41
|
+
function log(msg) {
|
|
42
|
+
console.log(msg);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Invoca `npm <args>` vía `node npm-cli.js` (nunca `npm.cmd` con
|
|
47
|
+
* `shell:true`): en Windows, `spawnSync('npm.cmd', ...)` sin shell lanza
|
|
48
|
+
* EINVAL, y `shell:true` reintroduce DEP0190 — mismo problema ya resuelto
|
|
49
|
+
* en scripts/lib/npm-version.js § comandoNpm.
|
|
50
|
+
*/
|
|
51
|
+
function spawnNpm(args, opts) {
|
|
52
|
+
const { bin, argsList } = comandoNpm(args);
|
|
53
|
+
return spawnSync(bin, argsList, opts);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
// Fase 0: inspección del tarball (dry-run, sin escribir en disco).
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
|
|
60
|
+
const RUTAS_REQUERIDAS = [
|
|
61
|
+
'bin/', 'manifiestos/', 'schemas/', 'agentes/', 'habilidades/',
|
|
62
|
+
'comandos/', 'hooks/', 'reglas/', 'package.json', 'plugin.json', 'CLAUDE.md',
|
|
63
|
+
];
|
|
64
|
+
// Nombres de ARCHIVO que delatan credenciales reales, no menciones al tema
|
|
65
|
+
// (el paquete incluye legítimamente hooks/skills de escaneo de secretos —
|
|
66
|
+
// "escaneo-secretos.js", "habilidades/iam-secretos/" — que hablan DE
|
|
67
|
+
// seguridad sin filtrar ninguna).
|
|
68
|
+
const PATRONES_PROHIBIDOS = [
|
|
69
|
+
/^tests\//, /^\.planning\//, /(^|\/)\.env(\.|$)/, /\.pem$/, /\.key$/,
|
|
70
|
+
/(^|\/)\.npmrc$/, /(^|\/)\.netrc$/,
|
|
71
|
+
/(^|\/)credentials\.json$/, /(^|\/)secrets\.(json|ya?ml)$/,
|
|
72
|
+
/^\.git\//, /^temp\//, /^respositorios-git\//,
|
|
73
|
+
];
|
|
74
|
+
|
|
75
|
+
function faseInspeccion() {
|
|
76
|
+
log('\n[FASE 0/5] inspección del tarball (npm pack --dry-run --json --ignore-scripts)');
|
|
77
|
+
const r = spawnNpm(['pack', '--dry-run', '--json', '--ignore-scripts'], {
|
|
78
|
+
cwd: RAIZ, encoding: 'utf-8',
|
|
79
|
+
});
|
|
80
|
+
if (r.status !== 0) {
|
|
81
|
+
log(` [FALLA] npm pack --dry-run exit=${r.status}`);
|
|
82
|
+
log(r.stderr || '');
|
|
83
|
+
return { ok: false };
|
|
84
|
+
}
|
|
85
|
+
let parseado;
|
|
86
|
+
try {
|
|
87
|
+
parseado = JSON.parse(r.stdout);
|
|
88
|
+
} catch (error) {
|
|
89
|
+
log(` [FALLA] salida de npm pack --dry-run no es JSON válido: ${error.message}`);
|
|
90
|
+
return { ok: false };
|
|
91
|
+
}
|
|
92
|
+
const entrada = parseado[0];
|
|
93
|
+
const archivos = (entrada.files || []).map((f) => f.path);
|
|
94
|
+
|
|
95
|
+
const faltantes = RUTAS_REQUERIDAS.filter(
|
|
96
|
+
(req) => !archivos.some((a) => a === req || a.startsWith(req))
|
|
97
|
+
);
|
|
98
|
+
if (faltantes.length > 0) {
|
|
99
|
+
log(` [FALLA] rutas requeridas ausentes del tarball: ${faltantes.join(', ')}`);
|
|
100
|
+
return { ok: false };
|
|
101
|
+
}
|
|
102
|
+
log(` [OK] ${RUTAS_REQUERIDAS.length}/${RUTAS_REQUERIDAS.length} rutas requeridas presentes`);
|
|
103
|
+
|
|
104
|
+
const prohibidos = archivos.filter((a) => PATRONES_PROHIBIDOS.some((pat) => pat.test(a)));
|
|
105
|
+
if (prohibidos.length > 0) {
|
|
106
|
+
log(` [FALLA] rutas prohibidas presentes en el tarball: ${prohibidos.slice(0, 10).join(', ')}`);
|
|
107
|
+
return { ok: false };
|
|
108
|
+
}
|
|
109
|
+
log(` [OK] sin fixtures/tests/secretos/evidencia privada (${archivos.length} archivos totales)`);
|
|
110
|
+
return { ok: true };
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// ---------------------------------------------------------------------------
|
|
114
|
+
// Fase 1: pack real + install aislado del tarball vía npm (igual que un
|
|
115
|
+
// consumidor downstream real: `npm install @saulwade/swl-ses`).
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
|
|
118
|
+
function fasePackEInstalarPaquete(tmpBase) {
|
|
119
|
+
log('\n[FASE 1/5] npm pack real + instalación del tarball en prefix aislado');
|
|
120
|
+
const packDest = path.join(tmpBase, 'pack-dest');
|
|
121
|
+
const installDest = path.join(tmpBase, 'consumer');
|
|
122
|
+
fs.mkdirSync(packDest, { recursive: true });
|
|
123
|
+
fs.mkdirSync(installDest, { recursive: true });
|
|
124
|
+
|
|
125
|
+
const pack = spawnNpm(['pack', '--pack-destination', packDest, '--ignore-scripts'], {
|
|
126
|
+
cwd: RAIZ, encoding: 'utf-8',
|
|
127
|
+
});
|
|
128
|
+
if (pack.status !== 0) {
|
|
129
|
+
log(` [FALLA] npm pack exit=${pack.status}`);
|
|
130
|
+
log(pack.stderr || '');
|
|
131
|
+
return { ok: false };
|
|
132
|
+
}
|
|
133
|
+
const tgz = fs.readdirSync(packDest).find((f) => f.endsWith('.tgz'));
|
|
134
|
+
if (!tgz) {
|
|
135
|
+
log(' [FALLA] npm pack no produjo ningún .tgz');
|
|
136
|
+
return { ok: false };
|
|
137
|
+
}
|
|
138
|
+
log(` [OK] tarball producido: ${tgz}`);
|
|
139
|
+
|
|
140
|
+
const install = spawnNpm(
|
|
141
|
+
['install', '--prefix', installDest, '--no-save', '--ignore-scripts', path.join(packDest, tgz)],
|
|
142
|
+
{ cwd: installDest, encoding: 'utf-8' }
|
|
143
|
+
);
|
|
144
|
+
if (install.status !== 0) {
|
|
145
|
+
log(` [FALLA] npm install del tarball exit=${install.status}`);
|
|
146
|
+
log(install.stderr || '');
|
|
147
|
+
return { ok: false };
|
|
148
|
+
}
|
|
149
|
+
const paqueteDir = path.join(installDest, 'node_modules', '@saulwade', 'swl-ses');
|
|
150
|
+
const cli = path.join(paqueteDir, 'bin', 'swl-ses.js');
|
|
151
|
+
if (!fs.existsSync(cli)) {
|
|
152
|
+
log(` [FALLA] el tarball instalado no contiene ${path.relative(installDest, cli)}`);
|
|
153
|
+
return { ok: false };
|
|
154
|
+
}
|
|
155
|
+
log(' [OK] tarball instalado en prefix aislado; bin/swl-ses.js presente');
|
|
156
|
+
return { ok: true, cli, paqueteDir };
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// ---------------------------------------------------------------------------
|
|
160
|
+
// Fases 2-4: install -> doctor -> update -> uninstall, ejecutando el CLI
|
|
161
|
+
// EMPACADO (no el árbol fuente) contra un HOME aislado.
|
|
162
|
+
// ---------------------------------------------------------------------------
|
|
163
|
+
|
|
164
|
+
function correrCliEmpacado(cli, args, cwd, env) {
|
|
165
|
+
const r = spawnSync(process.execPath, [cli, ...args], {
|
|
166
|
+
cwd, env: { ...process.env, ...env }, encoding: 'utf-8', timeout: 120000,
|
|
167
|
+
});
|
|
168
|
+
return {
|
|
169
|
+
code: r.status, stdout: r.stdout || '', stderr: r.stderr || '',
|
|
170
|
+
error: r.error ? (r.error.code || r.error.message) : null,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function faseInstalarDesdeEmpacado(cli, cwd, home) {
|
|
175
|
+
log('\n[FASE 2/5] install (desde el tarball) --profile completo --global --all-langs');
|
|
176
|
+
const r = correrCliEmpacado(
|
|
177
|
+
cli,
|
|
178
|
+
['install', '--target', 'claude', '--profile', 'completo', '--global', '--force', '--all-langs'],
|
|
179
|
+
cwd, { HOME: home, USERPROFILE: home }
|
|
180
|
+
);
|
|
181
|
+
if (r.code !== 0) {
|
|
182
|
+
log(` [FALLA] install exit=${r.code} spawnError=${r.error || '-'}`);
|
|
183
|
+
if (r.stderr.trim()) log(r.stderr.split('\n').slice(0, 10).map((l) => ` ${l}`).join('\n'));
|
|
184
|
+
return { ok: false };
|
|
185
|
+
}
|
|
186
|
+
const destino = path.join(home, '.claude');
|
|
187
|
+
const marcadores = [
|
|
188
|
+
path.join(destino, 'agents'), path.join(destino, 'skills'),
|
|
189
|
+
path.join(destino, 'commands'), path.join(destino, 'hooks'),
|
|
190
|
+
path.join(destino, 'rules'),
|
|
191
|
+
];
|
|
192
|
+
const ausentes = marcadores.filter((m) => !fs.existsSync(m));
|
|
193
|
+
if (ausentes.length > 0) {
|
|
194
|
+
log(` [FALLA] rutas esperadas ausentes tras install: ${ausentes.map((m) => path.relative(destino, m)).join(', ')}`);
|
|
195
|
+
return { ok: false };
|
|
196
|
+
}
|
|
197
|
+
log(' [OK] install terminó sin errores; estructura esperada presente');
|
|
198
|
+
return { ok: true };
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function faseDoctorDesdeEmpacado(cli, cwd, home) {
|
|
202
|
+
log('\n[FASE 3/5] doctor (desde el tarball)');
|
|
203
|
+
const r = correrCliEmpacado(cli, ['doctor'], cwd, { HOME: home, USERPROFILE: home });
|
|
204
|
+
if (r.code !== 0) {
|
|
205
|
+
log(` [FALLA] doctor exit=${r.code}`);
|
|
206
|
+
log(r.stdout.split('\n').slice(-15).map((l) => ` ${l}`).join('\n'));
|
|
207
|
+
return { ok: false };
|
|
208
|
+
}
|
|
209
|
+
const m = r.stdout.match(/(\d+)\s*errores/);
|
|
210
|
+
if (!m || parseInt(m[1], 10) !== 0) {
|
|
211
|
+
log(' [FALLA] doctor no reportó "0 errores" en su resumen');
|
|
212
|
+
log(r.stdout.split('\n').slice(-15).map((l) => ` ${l}`).join('\n'));
|
|
213
|
+
return { ok: false };
|
|
214
|
+
}
|
|
215
|
+
log(' [OK] doctor pasó sin errores');
|
|
216
|
+
return { ok: true };
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function faseActualizarDesdeEmpacado(cli, cwd, home) {
|
|
220
|
+
log('\n[FASE 4/5] update --check (solo lectura) + reinstall en sitio (mecanismo real de update)');
|
|
221
|
+
const check = correrCliEmpacado(cli, ['update', '--check'], cwd, { HOME: home, USERPROFILE: home });
|
|
222
|
+
if (check.code !== 0) {
|
|
223
|
+
log(` [FALLA] update --check exit=${check.code}`);
|
|
224
|
+
log(check.stderr.split('\n').slice(0, 10).map((l) => ` ${l}`).join('\n'));
|
|
225
|
+
return { ok: false };
|
|
226
|
+
}
|
|
227
|
+
log(' [OK] update --check terminó sin errores');
|
|
228
|
+
|
|
229
|
+
// Reinstall en sitio con los MISMOS flags del install inicial: el
|
|
230
|
+
// mecanismo idempotente que update() invoca internamente vía
|
|
231
|
+
// instalador({..., force:true}) cuando decide actualizar. Prueba que
|
|
232
|
+
// re-aplicar el mismo perfil sobre una instalación existente no rompe
|
|
233
|
+
// ni deja archivos a medias — sin depender del registro npm.
|
|
234
|
+
const reinstall = correrCliEmpacado(
|
|
235
|
+
cli,
|
|
236
|
+
['install', '--target', 'claude', '--profile', 'completo', '--global', '--force', '--all-langs'],
|
|
237
|
+
cwd, { HOME: home, USERPROFILE: home }
|
|
238
|
+
);
|
|
239
|
+
if (reinstall.code !== 0) {
|
|
240
|
+
log(` [FALLA] reinstall en sitio exit=${reinstall.code}`);
|
|
241
|
+
log(reinstall.stderr.split('\n').slice(0, 10).map((l) => ` ${l}`).join('\n'));
|
|
242
|
+
return { ok: false };
|
|
243
|
+
}
|
|
244
|
+
const destino = path.join(home, '.claude');
|
|
245
|
+
if (!fs.existsSync(path.join(destino, 'agents')) || !fs.existsSync(path.join(destino, 'skills'))) {
|
|
246
|
+
log(' [FALLA] tras el reinstall en sitio, agents/ o skills/ ya no están presentes');
|
|
247
|
+
return { ok: false };
|
|
248
|
+
}
|
|
249
|
+
log(' [OK] reinstall en sitio (mecanismo de update) terminó sin errores');
|
|
250
|
+
return { ok: true };
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function faseDesinstalarDesdeEmpacado(cli, cwd, home) {
|
|
254
|
+
log('\n[FASE 5/5] uninstall (desde el tarball)');
|
|
255
|
+
const r = correrCliEmpacado(cli, ['uninstall', '--target', 'claude', '--global', '--force'], cwd, {
|
|
256
|
+
HOME: home, USERPROFILE: home,
|
|
257
|
+
});
|
|
258
|
+
if (r.code !== 0) {
|
|
259
|
+
log(` [FALLA] uninstall exit=${r.code}`);
|
|
260
|
+
log(r.stderr.split('\n').slice(0, 10).map((l) => ` ${l}`).join('\n'));
|
|
261
|
+
return { ok: false };
|
|
262
|
+
}
|
|
263
|
+
log(' [OK] uninstall terminó sin errores');
|
|
264
|
+
return { ok: true };
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// ---------------------------------------------------------------------------
|
|
268
|
+
// Invariantes que ninguna fase debe romper: los siete claims públicos
|
|
269
|
+
// permanecen unverified y las tres ubicaciones de versión no cambian.
|
|
270
|
+
// ---------------------------------------------------------------------------
|
|
271
|
+
|
|
272
|
+
function verificarInvariantesDelRepoFuente(snapshotPrevio) {
|
|
273
|
+
const conformancePath = path.join(RAIZ, 'manifiestos', 'runtime-conformance.json');
|
|
274
|
+
const conformance = JSON.parse(fs.readFileSync(conformancePath, 'utf8'));
|
|
275
|
+
const estados = Object.values(conformance.runtimes).map((r) => r.certificationStatus);
|
|
276
|
+
const noUnverified = estados.filter((e) => e !== 'unverified');
|
|
277
|
+
if (noUnverified.length > 0) {
|
|
278
|
+
return { ok: false, motivo: `runtime-conformance.json tiene estados fuera de unverified: ${noUnverified.join(', ')}` };
|
|
279
|
+
}
|
|
280
|
+
if (estados.length !== 7) {
|
|
281
|
+
return { ok: false, motivo: `runtime-conformance.json declara ${estados.length} runtimes, se esperaban 7` };
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(RAIZ, 'package.json'), 'utf8'));
|
|
285
|
+
const plugin = JSON.parse(fs.readFileSync(path.join(RAIZ, 'plugin.json'), 'utf8'));
|
|
286
|
+
const salud = fs.readFileSync(path.join(RAIZ, 'SALUD.md'), 'utf8');
|
|
287
|
+
if (pkg.version !== snapshotPrevio.pkgVersion) {
|
|
288
|
+
return { ok: false, motivo: `package.json#version cambió: ${snapshotPrevio.pkgVersion} -> ${pkg.version}` };
|
|
289
|
+
}
|
|
290
|
+
if (plugin.version !== snapshotPrevio.pluginVersion) {
|
|
291
|
+
return { ok: false, motivo: `plugin.json#version cambió: ${snapshotPrevio.pluginVersion} -> ${plugin.version}` };
|
|
292
|
+
}
|
|
293
|
+
if (!salud.includes(snapshotPrevio.pkgVersion)) {
|
|
294
|
+
return { ok: false, motivo: `SALUD.md ya no menciona la versión ${snapshotPrevio.pkgVersion}` };
|
|
295
|
+
}
|
|
296
|
+
return { ok: true };
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function snapshotVersiones() {
|
|
300
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(RAIZ, 'package.json'), 'utf8'));
|
|
301
|
+
const plugin = JSON.parse(fs.readFileSync(path.join(RAIZ, 'plugin.json'), 'utf8'));
|
|
302
|
+
return { pkgVersion: pkg.version, pluginVersion: plugin.version };
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function main() {
|
|
306
|
+
log('Ciclo aislado de empaquetado downstream (pack -> install -> doctor -> update -> uninstall)');
|
|
307
|
+
log('═══════════════════════════════════════════\n');
|
|
308
|
+
|
|
309
|
+
const snapshotPrevio = snapshotVersiones();
|
|
310
|
+
|
|
311
|
+
const inspeccion = faseInspeccion();
|
|
312
|
+
if (!inspeccion.ok) {
|
|
313
|
+
log('\n✗ FALLÓ en la fase de inspección — abortando sin tocar disco');
|
|
314
|
+
process.exit(1);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
const tmpBase = fs.mkdtempSync(path.join(os.tmpdir(), 'swl-pack-cycle-'));
|
|
318
|
+
const home = path.join(tmpBase, 'home');
|
|
319
|
+
const cwd = path.join(tmpBase, 'workspace');
|
|
320
|
+
fs.mkdirSync(home, { recursive: true });
|
|
321
|
+
fs.mkdirSync(cwd, { recursive: true });
|
|
322
|
+
log(`TMP: ${tmpBase}`);
|
|
323
|
+
|
|
324
|
+
let todoOk = true;
|
|
325
|
+
try {
|
|
326
|
+
const paquete = fasePackEInstalarPaquete(tmpBase);
|
|
327
|
+
if (!paquete.ok) {
|
|
328
|
+
todoOk = false;
|
|
329
|
+
} else {
|
|
330
|
+
const install = faseInstalarDesdeEmpacado(paquete.cli, cwd, home);
|
|
331
|
+
if (!install.ok) todoOk = false;
|
|
332
|
+
|
|
333
|
+
if (install.ok) {
|
|
334
|
+
const doctor = faseDoctorDesdeEmpacado(paquete.cli, cwd, home);
|
|
335
|
+
if (!doctor.ok) todoOk = false;
|
|
336
|
+
|
|
337
|
+
const update = faseActualizarDesdeEmpacado(paquete.cli, cwd, home);
|
|
338
|
+
if (!update.ok) todoOk = false;
|
|
339
|
+
|
|
340
|
+
const uninstall = faseDesinstalarDesdeEmpacado(paquete.cli, cwd, home);
|
|
341
|
+
if (!uninstall.ok) todoOk = false;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
} finally {
|
|
345
|
+
if (!KEEP_TMP) {
|
|
346
|
+
try {
|
|
347
|
+
fs.rmSync(tmpBase, { recursive: true, force: true });
|
|
348
|
+
} catch {
|
|
349
|
+
/* best-effort: no bloquear el resultado del gate por un residuo de limpieza */
|
|
350
|
+
}
|
|
351
|
+
} else {
|
|
352
|
+
log(`\n(--keep-tmp) directorio preservado en ${tmpBase}`);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
log('\n[INVARIANTES] runtime-conformance unverified + versiones sin cambio en el repo fuente');
|
|
357
|
+
const invariantes = verificarInvariantesDelRepoFuente(snapshotPrevio);
|
|
358
|
+
if (!invariantes.ok) {
|
|
359
|
+
log(` [FALLA] ${invariantes.motivo}`);
|
|
360
|
+
todoOk = false;
|
|
361
|
+
} else {
|
|
362
|
+
log(' [OK] los siete claims siguen unverified; package.json/plugin.json/SALUD.md sin cambio');
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
log('\n═══════════════════════════════════════════');
|
|
366
|
+
if (todoOk) {
|
|
367
|
+
log('✓ Ciclo de empaquetado downstream OK');
|
|
368
|
+
process.exit(0);
|
|
369
|
+
} else {
|
|
370
|
+
log('✗ Ciclo de empaquetado downstream FALLÓ — revisar fases arriba');
|
|
371
|
+
process.exit(1);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
main();
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Verifica, en modo de sólo lectura, un loop con el gate estructural de un
|
|
6
|
+
* checkout exacto de constructor-loops.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const { execFileSync } = require('node:child_process');
|
|
10
|
+
const fs = require('node:fs');
|
|
11
|
+
const path = require('node:path');
|
|
12
|
+
|
|
13
|
+
const ARGUMENTOS = new Set(['constructor-dir', 'expected-commit', 'loop']);
|
|
14
|
+
const CAMPOS_GATE = new Set(['pass', 'summary', 'findings', 'matchedRules']);
|
|
15
|
+
const SCRIPT_GATE = [
|
|
16
|
+
"import fs from 'node:fs';",
|
|
17
|
+
"import { pathToFileURL } from 'node:url';",
|
|
18
|
+
'const [builderPath, loopPath] = process.argv.slice(1);',
|
|
19
|
+
'const modulo = await import(pathToFileURL(builderPath).href);',
|
|
20
|
+
"if (typeof modulo.runStructuralGate !== 'function') {",
|
|
21
|
+
" throw new TypeError('runStructuralGate no está exportado');",
|
|
22
|
+
'}',
|
|
23
|
+
"const markdown = fs.readFileSync(loopPath, 'utf8');",
|
|
24
|
+
'const resultado = modulo.runStructuralGate(markdown);',
|
|
25
|
+
'process.stdout.write(JSON.stringify(resultado));',
|
|
26
|
+
].join('\n');
|
|
27
|
+
|
|
28
|
+
function parsearArgs(argv) {
|
|
29
|
+
const opciones = {};
|
|
30
|
+
for (const argumento of argv) {
|
|
31
|
+
const separador = argumento.indexOf('=');
|
|
32
|
+
const clave = separador > 2 ? argumento.slice(2, separador) : '';
|
|
33
|
+
const valor = separador >= 0 ? argumento.slice(separador + 1) : '';
|
|
34
|
+
if (!argumento.startsWith('--') || !ARGUMENTOS.has(clave) || !valor) {
|
|
35
|
+
throw new TypeError(`argumento inválido: ${argumento}`);
|
|
36
|
+
}
|
|
37
|
+
if (Object.hasOwn(opciones, clave)) throw new TypeError(`argumento duplicado: --${clave}`);
|
|
38
|
+
opciones[clave] = valor;
|
|
39
|
+
}
|
|
40
|
+
const faltantes = [...ARGUMENTOS].filter((clave) => !Object.hasOwn(opciones, clave));
|
|
41
|
+
if (faltantes.length > 0) throw new TypeError(`argumentos requeridos: ${faltantes.join(', ')}`);
|
|
42
|
+
return opciones;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function resolverEntradas(opciones) {
|
|
46
|
+
const constructorDir = path.resolve(opciones.constructorDir);
|
|
47
|
+
const loopPath = path.resolve(opciones.loopPath);
|
|
48
|
+
if (!fs.existsSync(constructorDir) || !fs.statSync(constructorDir).isDirectory()) {
|
|
49
|
+
throw new Error(`constructor-dir no existe o no es directorio: ${constructorDir}`);
|
|
50
|
+
}
|
|
51
|
+
if (!fs.existsSync(loopPath) || !fs.statSync(loopPath).isFile()) {
|
|
52
|
+
throw new Error(`loop no existe o no es archivo: ${loopPath}`);
|
|
53
|
+
}
|
|
54
|
+
const constructorReal = fs.realpathSync(constructorDir);
|
|
55
|
+
const builderPath = path.join(constructorReal, 'app', 'lib', 'loop-builder.ts');
|
|
56
|
+
if (!fs.existsSync(builderPath) || !fs.statSync(builderPath).isFile()) {
|
|
57
|
+
throw new Error(`loop-builder.ts no existe: ${builderPath}`);
|
|
58
|
+
}
|
|
59
|
+
if (fs.lstatSync(builderPath).isSymbolicLink()) {
|
|
60
|
+
throw new Error(`loop-builder.ts no puede ser enlace simbólico: ${builderPath}`);
|
|
61
|
+
}
|
|
62
|
+
return { builderPath, constructorDir: constructorReal, loopPath: fs.realpathSync(loopPath) };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function construirEntornoGit(entorno = process.env) {
|
|
66
|
+
const limpio = Object.fromEntries(Object.entries(entorno).filter(
|
|
67
|
+
([clave]) => clave.toUpperCase() !== 'GIT_OPTIONAL_LOCKS'
|
|
68
|
+
));
|
|
69
|
+
return { ...limpio, GIT_OPTIONAL_LOCKS: '0' };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function ejecutarGit(constructorDir, args, descripcion) {
|
|
73
|
+
try {
|
|
74
|
+
return execFileSync('git', args, {
|
|
75
|
+
cwd: constructorDir,
|
|
76
|
+
encoding: 'utf8',
|
|
77
|
+
env: construirEntornoGit(),
|
|
78
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
79
|
+
}).trim().toLowerCase();
|
|
80
|
+
} catch (error) {
|
|
81
|
+
const detalle = String(error.stderr || error.message).trim();
|
|
82
|
+
throw new Error(`${descripcion}: ${detalle}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function verificarCommit(constructorDir, expectedCommit) {
|
|
87
|
+
if (!/^[a-f0-9]{7,40}$/i.test(expectedCommit)) {
|
|
88
|
+
throw new TypeError('expected-commit debe ser un SHA hexadecimal de 7 a 40 caracteres');
|
|
89
|
+
}
|
|
90
|
+
const revision = `${expectedCommit}^{commit}`;
|
|
91
|
+
const esperado = ejecutarGit(
|
|
92
|
+
constructorDir,
|
|
93
|
+
['rev-parse', '--verify', '--end-of-options', revision],
|
|
94
|
+
'expected-commit no resoluble'
|
|
95
|
+
);
|
|
96
|
+
const head = ejecutarGit(constructorDir, ['rev-parse', 'HEAD'], 'HEAD no resoluble');
|
|
97
|
+
if (esperado !== head) {
|
|
98
|
+
throw new Error(`commit distinto: esperado ${esperado}; HEAD ${head}`);
|
|
99
|
+
}
|
|
100
|
+
const blobEsperado = ejecutarGit(
|
|
101
|
+
constructorDir,
|
|
102
|
+
['rev-parse', 'HEAD:app/lib/loop-builder.ts'],
|
|
103
|
+
'loop-builder.ts no existe en HEAD'
|
|
104
|
+
);
|
|
105
|
+
const blobActual = ejecutarGit(
|
|
106
|
+
constructorDir,
|
|
107
|
+
['hash-object', '--', 'app/lib/loop-builder.ts'],
|
|
108
|
+
'no se pudo calcular el blob actual de loop-builder.ts'
|
|
109
|
+
);
|
|
110
|
+
if (blobEsperado !== blobActual) {
|
|
111
|
+
throw new Error(`loop-builder.ts tiene cambios fuera de HEAD: ${blobEsperado} != ${blobActual}`);
|
|
112
|
+
}
|
|
113
|
+
const estadoCheckout = ejecutarGit(
|
|
114
|
+
constructorDir,
|
|
115
|
+
['status', '--porcelain=v1', '--untracked-files=all'],
|
|
116
|
+
'no se pudo verificar el checkout completo'
|
|
117
|
+
);
|
|
118
|
+
if (estadoCheckout) throw new Error(`checkout tiene cambios fuera de HEAD: ${estadoCheckout}`);
|
|
119
|
+
return { expectedCommit: esperado, headCommit: head };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function ejecutarGate(builderPath, loopPath) {
|
|
123
|
+
try {
|
|
124
|
+
const salida = execFileSync(process.execPath, [
|
|
125
|
+
'--experimental-strip-types',
|
|
126
|
+
'--input-type=module',
|
|
127
|
+
'-e',
|
|
128
|
+
SCRIPT_GATE,
|
|
129
|
+
builderPath,
|
|
130
|
+
loopPath,
|
|
131
|
+
], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'], maxBuffer: 1024 * 1024 });
|
|
132
|
+
return JSON.parse(salida);
|
|
133
|
+
} catch (error) {
|
|
134
|
+
const detalle = String(error.stderr || error.stdout || error.message).trim();
|
|
135
|
+
throw new Error(`falló el gate de constructor-loops: ${detalle}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function validarResultado(resultado) {
|
|
140
|
+
if (!resultado || typeof resultado !== 'object' || Array.isArray(resultado)) {
|
|
141
|
+
throw new TypeError('resultado estructural inválido');
|
|
142
|
+
}
|
|
143
|
+
const desconocidos = Object.keys(resultado).filter((campo) => !CAMPOS_GATE.has(campo));
|
|
144
|
+
if (desconocidos.length > 0) {
|
|
145
|
+
throw new TypeError(`resultado estructural contiene campo desconocido: ${desconocidos[0]}`);
|
|
146
|
+
}
|
|
147
|
+
const reglas = resultado.matchedRules;
|
|
148
|
+
if (resultado.pass !== true) {
|
|
149
|
+
const hallazgos = Array.isArray(resultado.findings) ? resultado.findings.join('; ') : 'sin detalle';
|
|
150
|
+
throw new Error(`gate estructural rechazó el loop: ${hallazgos}`);
|
|
151
|
+
}
|
|
152
|
+
if (!Array.isArray(resultado.findings) || resultado.findings.length > 0) {
|
|
153
|
+
throw new Error('gate PASS contiene findings y se rechaza por inconsistencia');
|
|
154
|
+
}
|
|
155
|
+
if (typeof resultado.summary !== 'string' || !resultado.summary.trim()) {
|
|
156
|
+
throw new TypeError('gate PASS no contiene summary válido');
|
|
157
|
+
}
|
|
158
|
+
if (!Array.isArray(reglas) || reglas.length !== 10 || new Set(reglas).size !== 10) {
|
|
159
|
+
throw new Error('gate estructural no devolvió exactamente diez reglas PASS únicas');
|
|
160
|
+
}
|
|
161
|
+
if (!reglas.every((regla) => typeof regla === 'string' && regla.trim())) {
|
|
162
|
+
throw new TypeError('matchedRules contiene una regla inválida');
|
|
163
|
+
}
|
|
164
|
+
return resultado;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function verificarLoopConstructor(opciones) {
|
|
168
|
+
const entradas = resolverEntradas(opciones);
|
|
169
|
+
const commits = verificarCommit(entradas.constructorDir, opciones.expectedCommit);
|
|
170
|
+
const gate = validarResultado(ejecutarGate(entradas.builderPath, entradas.loopPath));
|
|
171
|
+
return {
|
|
172
|
+
pass: true,
|
|
173
|
+
expectedCommit: commits.expectedCommit,
|
|
174
|
+
headCommit: commits.headCommit,
|
|
175
|
+
summary: gate.summary,
|
|
176
|
+
findings: gate.findings,
|
|
177
|
+
matchedRules: gate.matchedRules,
|
|
178
|
+
...entradas,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function imprimirResultado(resultado) {
|
|
183
|
+
console.log(`[constructor-loop] commit PASS: ${resultado.headCommit}`);
|
|
184
|
+
for (const regla of resultado.matchedRules) {
|
|
185
|
+
console.log(`[constructor-loop] regla PASS: ${regla}`);
|
|
186
|
+
}
|
|
187
|
+
console.log(`[constructor-loop] resultado PASS: ${resultado.summary}`);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function main(argv = process.argv.slice(2)) {
|
|
191
|
+
const args = parsearArgs(argv);
|
|
192
|
+
const resultado = verificarLoopConstructor({
|
|
193
|
+
constructorDir: args['constructor-dir'],
|
|
194
|
+
expectedCommit: args['expected-commit'],
|
|
195
|
+
loopPath: args.loop,
|
|
196
|
+
});
|
|
197
|
+
imprimirResultado(resultado);
|
|
198
|
+
return resultado;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (require.main === module) {
|
|
202
|
+
try {
|
|
203
|
+
main();
|
|
204
|
+
} catch (error) {
|
|
205
|
+
console.error(`[constructor-loop] ERROR: ${error.message}`);
|
|
206
|
+
process.exitCode = 1;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
module.exports = {
|
|
211
|
+
construirEntornoGit,
|
|
212
|
+
main,
|
|
213
|
+
parsearArgs,
|
|
214
|
+
verificarLoopConstructor,
|
|
215
|
+
};
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* calidad-pre-commit) con marker `verifica: REQ-NN`
|
|
19
19
|
*
|
|
20
20
|
* Exit codes:
|
|
21
|
-
* 0 — cadena completa
|
|
21
|
+
* 0 — cadena completa
|
|
22
22
|
* 1 — huérfanos detectados (REQ sin tarea / sin commit / sin test)
|
|
23
23
|
* 2 — error de invocación o parseo (fase inexistente, args inválidos)
|
|
24
24
|
*
|
|
@@ -189,9 +189,16 @@ function validarFase({ cwd, fase, soloPlan }) {
|
|
|
189
189
|
if (activos.length === 0) {
|
|
190
190
|
return {
|
|
191
191
|
fase: nn,
|
|
192
|
-
legacy:
|
|
193
|
-
|
|
194
|
-
|
|
192
|
+
legacy: false,
|
|
193
|
+
reqs: [],
|
|
194
|
+
retirados,
|
|
195
|
+
trazabilidad: {},
|
|
196
|
+
validaciones: {
|
|
197
|
+
contexto_sin_req: true,
|
|
198
|
+
req_sin_tarea: [], req_sin_commit: [], req_sin_test: [],
|
|
199
|
+
tarea_sin_req: [], headers_malformados: [],
|
|
200
|
+
},
|
|
201
|
+
exit: 1,
|
|
195
202
|
};
|
|
196
203
|
}
|
|
197
204
|
|
|
@@ -256,8 +263,8 @@ function imprimirReporte(r) {
|
|
|
256
263
|
console.error(`ERROR: ${r.error}`);
|
|
257
264
|
return;
|
|
258
265
|
}
|
|
259
|
-
if (r.
|
|
260
|
-
console.log(`Fase ${r.fase}:
|
|
266
|
+
if (r.validaciones.contexto_sin_req) {
|
|
267
|
+
console.log(`Fase ${r.fase}: CONTEXTO sin REQ explícitos — migración o inferencia legacy no satisface G4.`);
|
|
261
268
|
return;
|
|
262
269
|
}
|
|
263
270
|
console.log(`Trazabilidad REQ→T→commit→test — Fase ${r.fase}${r.soloPlan ? ' (--solo-plan: matriz REQ×T)' : ''}`);
|