@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
|
@@ -1,139 +1,139 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* guard-convivencia.js — Guard de convivencia con una sesión interactiva de
|
|
5
|
-
* Claude Code en la misma máquina (Fase 22, T-03, REQ-22-02).
|
|
6
|
-
*
|
|
7
|
-
* El runner headless de Fase B (`runner-fase-b.js`, T-05) NUNCA debe competir
|
|
8
|
-
* por recursos/rate-limit con un usuario trabajando en una sesión interactiva.
|
|
9
|
-
* Este módulo detecta si hay un proceso con imagen `claude` corriendo:
|
|
10
|
-
* `tasklist /FO CSV /NH` en win32, `ps -eo comm=` en POSIX.
|
|
11
|
-
*
|
|
12
|
-
* El `detector` es INYECTABLE — una función sin argumentos que devuelve la
|
|
13
|
-
* salida cruda del listado de procesos (string) o lanza. Los tests SIEMPRE
|
|
14
|
-
* inyectan el detector; nunca se spawnea un proceso real en la suite. El
|
|
15
|
-
* detector por defecto usa `child_process.spawnSync` con un timeout corto
|
|
16
|
-
* (2s) para que un binario colgado nunca bloquee el runner.
|
|
17
|
-
*
|
|
18
|
-
* Semántica CONSERVADORA (dictamen adversarial, supuesto 2 del CONTEXTO):
|
|
19
|
-
* proceso `claude` presente → diferir; ausente → no diferir; CUALQUIER fallo
|
|
20
|
-
* de detección (spawn falla, binario ausente, timeout, salida ilegible) →
|
|
21
|
-
* diferir también. Un falso positivo (diferir de más) es aceptable; competir
|
|
22
|
-
* con un usuario interactivo no lo es. El guard NUNCA lanza hacia el caller.
|
|
23
|
-
*
|
|
24
|
-
* LIMITACIÓN DOCUMENTADA (fase dry-run, F22 no la resuelve): el detector
|
|
25
|
-
* matchea por NOMBRE de imagen de proceso, no por árbol de PIDs. Si el propio
|
|
26
|
-
* runner (headless, `node`) fuese lanzado como hijo de un proceso `claude`
|
|
27
|
-
* padre (p. ej. invocado manualmente desde dentro de una sesión interactiva),
|
|
28
|
-
* este guard lo tomaría como sesión interactiva activa y diferiría — no hay
|
|
29
|
-
* forma de distinguir "mi propio ancestro" de "otra sesión del usuario" sin
|
|
30
|
-
* caminar el árbol de procesos por PID/PPID, algo que el CONTEXTO de esta fase
|
|
31
|
-
* no exige y el plan no especifica. El proceso `node` del propio runner NUNCA
|
|
32
|
-
* cuenta como match (solo se busca la imagen `claude`), pero un ancestro
|
|
33
|
-
* `claude` sí produce el mismo diferir que una sesión ajena. F24 (ciclo con
|
|
34
|
-
* mutaciones reales) es quien debe afinar esta distinción si el patrón de
|
|
35
|
-
* disparo cambia (p. ej. invocación manual desde dentro de una sesión).
|
|
36
|
-
*
|
|
37
|
-
* Zero-deps, CommonJS.
|
|
38
|
-
*
|
|
39
|
-
* @module scripts/lib/ciclo-autonomo/guard-convivencia
|
|
40
|
-
*/
|
|
41
|
-
|
|
42
|
-
const { spawnSync } = require('child_process');
|
|
43
|
-
|
|
44
|
-
/** Timeout del spawn de detección — nunca debe colgar el runner headless. */
|
|
45
|
-
const TIMEOUT_MS = 2000;
|
|
46
|
-
|
|
47
|
-
/** Nombre de imagen de proceso que identifica una sesión interactiva. */
|
|
48
|
-
const NOMBRE_PROCESO = 'claude';
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Resuelve el comando de listado de procesos según la plataforma. Puro y
|
|
52
|
-
* exportado para poder verificar la selección win32/POSIX en tests sin
|
|
53
|
-
* spawnear nada real.
|
|
54
|
-
*
|
|
55
|
-
* @param {string} plataforma - Típicamente `process.platform`.
|
|
56
|
-
* @returns {{cmd: string, args: string[]}}
|
|
57
|
-
*/
|
|
58
|
-
function resolverComando(plataforma) {
|
|
59
|
-
if (plataforma === 'win32') {
|
|
60
|
-
return { cmd: 'tasklist', args: ['/FO', 'CSV', '/NH'] };
|
|
61
|
-
}
|
|
62
|
-
return { cmd: 'ps', args: ['-eo', 'comm='] };
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Detector por defecto: spawnSync del listado de procesos de la plataforma.
|
|
67
|
-
* Lanza si el spawn falla, sale con código distinto de 0, o no produce una
|
|
68
|
-
* salida de texto utilizable — el caller (`evaluar`) trata cualquier lanzamiento
|
|
69
|
-
* como fallo de detección conservador.
|
|
70
|
-
*
|
|
71
|
-
* @param {string} plataforma
|
|
72
|
-
* @returns {string} Salida cruda del comando.
|
|
73
|
-
*/
|
|
74
|
-
function detectorPorDefecto(plataforma) {
|
|
75
|
-
const { cmd, args } = resolverComando(plataforma);
|
|
76
|
-
const resultado = spawnSync(cmd, args, { timeout: TIMEOUT_MS, encoding: 'utf8' });
|
|
77
|
-
|
|
78
|
-
if (!resultado || resultado.error || resultado.status !== 0 || typeof resultado.stdout !== 'string') {
|
|
79
|
-
throw new Error(`guard-convivencia: "${cmd}" no produjo salida utilizable`);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return resultado.stdout;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* `true` si la salida cruda del listado de procesos contiene una imagen
|
|
87
|
-
* `claude` (case-insensitive; matchea tanto `claude` como `claude.exe` en
|
|
88
|
-
* una línea CSV de tasklist o en la salida de `ps -eo comm=`).
|
|
89
|
-
*
|
|
90
|
-
* @param {string} salidaCruda
|
|
91
|
-
* @returns {boolean}
|
|
92
|
-
*/
|
|
93
|
-
function contieneProcesoClaude(salidaCruda) {
|
|
94
|
-
return salidaCruda
|
|
95
|
-
.split(/\r?\n/)
|
|
96
|
-
.some((linea) => linea.toLowerCase().includes(NOMBRE_PROCESO));
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* `true` si hay una sesión interactiva de Claude Code corriendo, según el
|
|
101
|
-
* detector inyectado (o el detector por defecto para la plataforma dada).
|
|
102
|
-
* Lanza si la detección falla — `evaluar` es quien decide el fallback
|
|
103
|
-
* conservador; esta función expone el booleano crudo.
|
|
104
|
-
*
|
|
105
|
-
* @param {{detector?: () => string, plataforma?: string}} [opciones]
|
|
106
|
-
* @returns {boolean}
|
|
107
|
-
*/
|
|
108
|
-
function haySesionInteractiva({ detector, plataforma = process.platform } = {}) {
|
|
109
|
-
const salidaCruda = detector ? detector() : detectorPorDefecto(plataforma);
|
|
110
|
-
if (typeof salidaCruda !== 'string') {
|
|
111
|
-
throw new Error('guard-convivencia: el detector no devolvió una salida de texto');
|
|
112
|
-
}
|
|
113
|
-
return contieneProcesoClaude(salidaCruda);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Evalúa si el runner de Fase B debe diferirse por convivencia con una
|
|
118
|
-
* sesión interactiva. NUNCA lanza — cualquier error de detección se
|
|
119
|
-
* convierte en `{diferir:true, razon:'deteccion-fallida'}` (conservador).
|
|
120
|
-
*
|
|
121
|
-
* @param {{detector?: () => string, plataforma?: string}} [opciones]
|
|
122
|
-
* @returns {{diferir: boolean, razon?: string}}
|
|
123
|
-
*/
|
|
124
|
-
function evaluar({ detector, plataforma } = {}) {
|
|
125
|
-
let activa;
|
|
126
|
-
try {
|
|
127
|
-
activa = haySesionInteractiva({ detector, plataforma });
|
|
128
|
-
} catch (_) {
|
|
129
|
-
return { diferir: true, razon: 'deteccion-fallida' };
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (activa) {
|
|
133
|
-
return { diferir: true, razon: 'sesion-interactiva' };
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
return { diferir: false };
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
module.exports = { evaluar, haySesionInteractiva, resolverComando };
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* guard-convivencia.js — Guard de convivencia con una sesión interactiva de
|
|
5
|
+
* Claude Code en la misma máquina (Fase 22, T-03, REQ-22-02).
|
|
6
|
+
*
|
|
7
|
+
* El runner headless de Fase B (`runner-fase-b.js`, T-05) NUNCA debe competir
|
|
8
|
+
* por recursos/rate-limit con un usuario trabajando en una sesión interactiva.
|
|
9
|
+
* Este módulo detecta si hay un proceso con imagen `claude` corriendo:
|
|
10
|
+
* `tasklist /FO CSV /NH` en win32, `ps -eo comm=` en POSIX.
|
|
11
|
+
*
|
|
12
|
+
* El `detector` es INYECTABLE — una función sin argumentos que devuelve la
|
|
13
|
+
* salida cruda del listado de procesos (string) o lanza. Los tests SIEMPRE
|
|
14
|
+
* inyectan el detector; nunca se spawnea un proceso real en la suite. El
|
|
15
|
+
* detector por defecto usa `child_process.spawnSync` con un timeout corto
|
|
16
|
+
* (2s) para que un binario colgado nunca bloquee el runner.
|
|
17
|
+
*
|
|
18
|
+
* Semántica CONSERVADORA (dictamen adversarial, supuesto 2 del CONTEXTO):
|
|
19
|
+
* proceso `claude` presente → diferir; ausente → no diferir; CUALQUIER fallo
|
|
20
|
+
* de detección (spawn falla, binario ausente, timeout, salida ilegible) →
|
|
21
|
+
* diferir también. Un falso positivo (diferir de más) es aceptable; competir
|
|
22
|
+
* con un usuario interactivo no lo es. El guard NUNCA lanza hacia el caller.
|
|
23
|
+
*
|
|
24
|
+
* LIMITACIÓN DOCUMENTADA (fase dry-run, F22 no la resuelve): el detector
|
|
25
|
+
* matchea por NOMBRE de imagen de proceso, no por árbol de PIDs. Si el propio
|
|
26
|
+
* runner (headless, `node`) fuese lanzado como hijo de un proceso `claude`
|
|
27
|
+
* padre (p. ej. invocado manualmente desde dentro de una sesión interactiva),
|
|
28
|
+
* este guard lo tomaría como sesión interactiva activa y diferiría — no hay
|
|
29
|
+
* forma de distinguir "mi propio ancestro" de "otra sesión del usuario" sin
|
|
30
|
+
* caminar el árbol de procesos por PID/PPID, algo que el CONTEXTO de esta fase
|
|
31
|
+
* no exige y el plan no especifica. El proceso `node` del propio runner NUNCA
|
|
32
|
+
* cuenta como match (solo se busca la imagen `claude`), pero un ancestro
|
|
33
|
+
* `claude` sí produce el mismo diferir que una sesión ajena. F24 (ciclo con
|
|
34
|
+
* mutaciones reales) es quien debe afinar esta distinción si el patrón de
|
|
35
|
+
* disparo cambia (p. ej. invocación manual desde dentro de una sesión).
|
|
36
|
+
*
|
|
37
|
+
* Zero-deps, CommonJS.
|
|
38
|
+
*
|
|
39
|
+
* @module scripts/lib/ciclo-autonomo/guard-convivencia
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
const { spawnSync } = require('child_process');
|
|
43
|
+
|
|
44
|
+
/** Timeout del spawn de detección — nunca debe colgar el runner headless. */
|
|
45
|
+
const TIMEOUT_MS = 2000;
|
|
46
|
+
|
|
47
|
+
/** Nombre de imagen de proceso que identifica una sesión interactiva. */
|
|
48
|
+
const NOMBRE_PROCESO = 'claude';
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Resuelve el comando de listado de procesos según la plataforma. Puro y
|
|
52
|
+
* exportado para poder verificar la selección win32/POSIX en tests sin
|
|
53
|
+
* spawnear nada real.
|
|
54
|
+
*
|
|
55
|
+
* @param {string} plataforma - Típicamente `process.platform`.
|
|
56
|
+
* @returns {{cmd: string, args: string[]}}
|
|
57
|
+
*/
|
|
58
|
+
function resolverComando(plataforma) {
|
|
59
|
+
if (plataforma === 'win32') {
|
|
60
|
+
return { cmd: 'tasklist', args: ['/FO', 'CSV', '/NH'] };
|
|
61
|
+
}
|
|
62
|
+
return { cmd: 'ps', args: ['-eo', 'comm='] };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Detector por defecto: spawnSync del listado de procesos de la plataforma.
|
|
67
|
+
* Lanza si el spawn falla, sale con código distinto de 0, o no produce una
|
|
68
|
+
* salida de texto utilizable — el caller (`evaluar`) trata cualquier lanzamiento
|
|
69
|
+
* como fallo de detección conservador.
|
|
70
|
+
*
|
|
71
|
+
* @param {string} plataforma
|
|
72
|
+
* @returns {string} Salida cruda del comando.
|
|
73
|
+
*/
|
|
74
|
+
function detectorPorDefecto(plataforma) {
|
|
75
|
+
const { cmd, args } = resolverComando(plataforma);
|
|
76
|
+
const resultado = spawnSync(cmd, args, { timeout: TIMEOUT_MS, encoding: 'utf8' });
|
|
77
|
+
|
|
78
|
+
if (!resultado || resultado.error || resultado.status !== 0 || typeof resultado.stdout !== 'string') {
|
|
79
|
+
throw new Error(`guard-convivencia: "${cmd}" no produjo salida utilizable`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return resultado.stdout;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* `true` si la salida cruda del listado de procesos contiene una imagen
|
|
87
|
+
* `claude` (case-insensitive; matchea tanto `claude` como `claude.exe` en
|
|
88
|
+
* una línea CSV de tasklist o en la salida de `ps -eo comm=`).
|
|
89
|
+
*
|
|
90
|
+
* @param {string} salidaCruda
|
|
91
|
+
* @returns {boolean}
|
|
92
|
+
*/
|
|
93
|
+
function contieneProcesoClaude(salidaCruda) {
|
|
94
|
+
return salidaCruda
|
|
95
|
+
.split(/\r?\n/)
|
|
96
|
+
.some((linea) => linea.toLowerCase().includes(NOMBRE_PROCESO));
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* `true` si hay una sesión interactiva de Claude Code corriendo, según el
|
|
101
|
+
* detector inyectado (o el detector por defecto para la plataforma dada).
|
|
102
|
+
* Lanza si la detección falla — `evaluar` es quien decide el fallback
|
|
103
|
+
* conservador; esta función expone el booleano crudo.
|
|
104
|
+
*
|
|
105
|
+
* @param {{detector?: () => string, plataforma?: string}} [opciones]
|
|
106
|
+
* @returns {boolean}
|
|
107
|
+
*/
|
|
108
|
+
function haySesionInteractiva({ detector, plataforma = process.platform } = {}) {
|
|
109
|
+
const salidaCruda = detector ? detector() : detectorPorDefecto(plataforma);
|
|
110
|
+
if (typeof salidaCruda !== 'string') {
|
|
111
|
+
throw new Error('guard-convivencia: el detector no devolvió una salida de texto');
|
|
112
|
+
}
|
|
113
|
+
return contieneProcesoClaude(salidaCruda);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Evalúa si el runner de Fase B debe diferirse por convivencia con una
|
|
118
|
+
* sesión interactiva. NUNCA lanza — cualquier error de detección se
|
|
119
|
+
* convierte en `{diferir:true, razon:'deteccion-fallida'}` (conservador).
|
|
120
|
+
*
|
|
121
|
+
* @param {{detector?: () => string, plataforma?: string}} [opciones]
|
|
122
|
+
* @returns {{diferir: boolean, razon?: string}}
|
|
123
|
+
*/
|
|
124
|
+
function evaluar({ detector, plataforma } = {}) {
|
|
125
|
+
let activa;
|
|
126
|
+
try {
|
|
127
|
+
activa = haySesionInteractiva({ detector, plataforma });
|
|
128
|
+
} catch (_) {
|
|
129
|
+
return { diferir: true, razon: 'deteccion-fallida' };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (activa) {
|
|
133
|
+
return { diferir: true, razon: 'sesion-interactiva' };
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return { diferir: false };
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
module.exports = { evaluar, haySesionInteractiva, resolverComando };
|
|
@@ -1,112 +1,112 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Higiene del ciclo de nudges (T-09, Fase 21 — ADR-0041).
|
|
5
|
-
*
|
|
6
|
-
* Opera sobre `.planning/evolution/nudges.jsonl` con formato compatible con
|
|
7
|
-
* `hooks/lib/nudge-tracker.js` ({id, kind, target, ts, accionado,
|
|
8
|
-
* accionado_ts, accionado_por}), pero con `baseDir` inyectable — el tracker
|
|
9
|
-
* fija sus rutas al cwd del require y no sirve para el motor ni para tests
|
|
10
|
-
* en sandbox.
|
|
11
|
-
*
|
|
12
|
-
* - marcarAccionado(baseDir, {id | kinds, por, ahora}) → {marcados}
|
|
13
|
-
* - archivarViejos(baseDir, {ahora, dias=90}) → {archivados}
|
|
14
|
-
*
|
|
15
|
-
* Zero-deps. Reescritura completa vía atomic-write; líneas con schema viejo
|
|
16
|
-
* o corruptas se conservan intactas (nunca se pierden por higiene).
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
const fs = require('fs');
|
|
20
|
-
const path = require('path');
|
|
21
|
-
const { atomicWriteSync } = require('../../../hooks/lib/atomic-write');
|
|
22
|
-
|
|
23
|
-
const DIAS_VENTANA_DEFAULT = 90;
|
|
24
|
-
|
|
25
|
-
function rutaNudges(baseDir) {
|
|
26
|
-
return path.join(baseDir, '.planning', 'evolution', 'nudges.jsonl');
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function rutaArchive(baseDir) {
|
|
30
|
-
return path.join(baseDir, '.planning', 'evolution', 'nudges.archive.jsonl');
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Lee el JSONL preservando las líneas crudas: las que no parsean se devuelven
|
|
34
|
-
// con `nudge: null` para reescribirlas tal cual (tolerancia sin pérdida).
|
|
35
|
-
function leerLineas(baseDir) {
|
|
36
|
-
const ruta = rutaNudges(baseDir);
|
|
37
|
-
if (!fs.existsSync(ruta)) return null;
|
|
38
|
-
return fs
|
|
39
|
-
.readFileSync(ruta, 'utf8')
|
|
40
|
-
.split('\n')
|
|
41
|
-
.filter((l) => l.trim() !== '')
|
|
42
|
-
.map((cruda) => {
|
|
43
|
-
try {
|
|
44
|
-
return { cruda, nudge: JSON.parse(cruda) };
|
|
45
|
-
} catch {
|
|
46
|
-
return { cruda, nudge: null };
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function escribirLineas(baseDir, lineas) {
|
|
52
|
-
const contenido = lineas.map((l) => l.cruda).join('\n') + (lineas.length ? '\n' : '');
|
|
53
|
-
atomicWriteSync(rutaNudges(baseDir), contenido, 'utf8');
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Marca nudges como accionados, por `id` exacto o por lista de `kinds`
|
|
58
|
-
* (solo los aún no accionados). Nunca pisa un `accionado_por` previo.
|
|
59
|
-
*/
|
|
60
|
-
function marcarAccionado(baseDir, { id, kinds, por = 'desconocido', ahora = new Date() } = {}) {
|
|
61
|
-
const lineas = leerLineas(baseDir);
|
|
62
|
-
if (!lineas) return { marcados: 0 };
|
|
63
|
-
|
|
64
|
-
let marcados = 0;
|
|
65
|
-
for (const linea of lineas) {
|
|
66
|
-
const n = linea.nudge;
|
|
67
|
-
if (!n || n.accionado === true) continue;
|
|
68
|
-
const porId = id != null && n.id === id;
|
|
69
|
-
const porKind = Array.isArray(kinds) && kinds.includes(n.kind);
|
|
70
|
-
if (!porId && !porKind) continue;
|
|
71
|
-
|
|
72
|
-
n.accionado = true;
|
|
73
|
-
n.accionado_ts = ahora.toISOString();
|
|
74
|
-
n.accionado_por = por;
|
|
75
|
-
linea.cruda = JSON.stringify(n);
|
|
76
|
-
marcados++;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if (marcados > 0) escribirLineas(baseDir, lineas);
|
|
80
|
-
return { marcados };
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Mueve al archive los nudges SIN accionar con `ts` más viejo que la ventana.
|
|
85
|
-
* Los nudges sin `ts` parseable y las líneas corruptas se conservan activos
|
|
86
|
-
* (mejor conservar de más que archivar señal viva).
|
|
87
|
-
*/
|
|
88
|
-
function archivarViejos(baseDir, { ahora = new Date(), dias = DIAS_VENTANA_DEFAULT } = {}) {
|
|
89
|
-
const lineas = leerLineas(baseDir);
|
|
90
|
-
if (!lineas) return { archivados: 0 };
|
|
91
|
-
|
|
92
|
-
const limiteMs = ahora.getTime() - dias * 24 * 3600 * 1000;
|
|
93
|
-
const activos = [];
|
|
94
|
-
const archivados = [];
|
|
95
|
-
|
|
96
|
-
for (const linea of lineas) {
|
|
97
|
-
const n = linea.nudge;
|
|
98
|
-
const tsMs = n && n.ts ? Date.parse(n.ts) : NaN;
|
|
99
|
-
const esViejoSinAccionar = n && n.accionado !== true && Number.isFinite(tsMs) && tsMs < limiteMs;
|
|
100
|
-
(esViejoSinAccionar ? archivados : activos).push(linea);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
if (archivados.length > 0) {
|
|
104
|
-
const bloque = archivados.map((l) => l.cruda).join('\n') + '\n';
|
|
105
|
-
fs.appendFileSync(rutaArchive(baseDir), bloque, 'utf8');
|
|
106
|
-
escribirLineas(baseDir, activos);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
return { archivados: archivados.length };
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
module.exports = { marcarAccionado, archivarViejos, DIAS_VENTANA_DEFAULT };
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Higiene del ciclo de nudges (T-09, Fase 21 — ADR-0041).
|
|
5
|
+
*
|
|
6
|
+
* Opera sobre `.planning/evolution/nudges.jsonl` con formato compatible con
|
|
7
|
+
* `hooks/lib/nudge-tracker.js` ({id, kind, target, ts, accionado,
|
|
8
|
+
* accionado_ts, accionado_por}), pero con `baseDir` inyectable — el tracker
|
|
9
|
+
* fija sus rutas al cwd del require y no sirve para el motor ni para tests
|
|
10
|
+
* en sandbox.
|
|
11
|
+
*
|
|
12
|
+
* - marcarAccionado(baseDir, {id | kinds, por, ahora}) → {marcados}
|
|
13
|
+
* - archivarViejos(baseDir, {ahora, dias=90}) → {archivados}
|
|
14
|
+
*
|
|
15
|
+
* Zero-deps. Reescritura completa vía atomic-write; líneas con schema viejo
|
|
16
|
+
* o corruptas se conservan intactas (nunca se pierden por higiene).
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const fs = require('fs');
|
|
20
|
+
const path = require('path');
|
|
21
|
+
const { atomicWriteSync } = require('../../../hooks/lib/atomic-write');
|
|
22
|
+
|
|
23
|
+
const DIAS_VENTANA_DEFAULT = 90;
|
|
24
|
+
|
|
25
|
+
function rutaNudges(baseDir) {
|
|
26
|
+
return path.join(baseDir, '.planning', 'evolution', 'nudges.jsonl');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function rutaArchive(baseDir) {
|
|
30
|
+
return path.join(baseDir, '.planning', 'evolution', 'nudges.archive.jsonl');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Lee el JSONL preservando las líneas crudas: las que no parsean se devuelven
|
|
34
|
+
// con `nudge: null` para reescribirlas tal cual (tolerancia sin pérdida).
|
|
35
|
+
function leerLineas(baseDir) {
|
|
36
|
+
const ruta = rutaNudges(baseDir);
|
|
37
|
+
if (!fs.existsSync(ruta)) return null;
|
|
38
|
+
return fs
|
|
39
|
+
.readFileSync(ruta, 'utf8')
|
|
40
|
+
.split('\n')
|
|
41
|
+
.filter((l) => l.trim() !== '')
|
|
42
|
+
.map((cruda) => {
|
|
43
|
+
try {
|
|
44
|
+
return { cruda, nudge: JSON.parse(cruda) };
|
|
45
|
+
} catch {
|
|
46
|
+
return { cruda, nudge: null };
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function escribirLineas(baseDir, lineas) {
|
|
52
|
+
const contenido = lineas.map((l) => l.cruda).join('\n') + (lineas.length ? '\n' : '');
|
|
53
|
+
atomicWriteSync(rutaNudges(baseDir), contenido, 'utf8');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Marca nudges como accionados, por `id` exacto o por lista de `kinds`
|
|
58
|
+
* (solo los aún no accionados). Nunca pisa un `accionado_por` previo.
|
|
59
|
+
*/
|
|
60
|
+
function marcarAccionado(baseDir, { id, kinds, por = 'desconocido', ahora = new Date() } = {}) {
|
|
61
|
+
const lineas = leerLineas(baseDir);
|
|
62
|
+
if (!lineas) return { marcados: 0 };
|
|
63
|
+
|
|
64
|
+
let marcados = 0;
|
|
65
|
+
for (const linea of lineas) {
|
|
66
|
+
const n = linea.nudge;
|
|
67
|
+
if (!n || n.accionado === true) continue;
|
|
68
|
+
const porId = id != null && n.id === id;
|
|
69
|
+
const porKind = Array.isArray(kinds) && kinds.includes(n.kind);
|
|
70
|
+
if (!porId && !porKind) continue;
|
|
71
|
+
|
|
72
|
+
n.accionado = true;
|
|
73
|
+
n.accionado_ts = ahora.toISOString();
|
|
74
|
+
n.accionado_por = por;
|
|
75
|
+
linea.cruda = JSON.stringify(n);
|
|
76
|
+
marcados++;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (marcados > 0) escribirLineas(baseDir, lineas);
|
|
80
|
+
return { marcados };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Mueve al archive los nudges SIN accionar con `ts` más viejo que la ventana.
|
|
85
|
+
* Los nudges sin `ts` parseable y las líneas corruptas se conservan activos
|
|
86
|
+
* (mejor conservar de más que archivar señal viva).
|
|
87
|
+
*/
|
|
88
|
+
function archivarViejos(baseDir, { ahora = new Date(), dias = DIAS_VENTANA_DEFAULT } = {}) {
|
|
89
|
+
const lineas = leerLineas(baseDir);
|
|
90
|
+
if (!lineas) return { archivados: 0 };
|
|
91
|
+
|
|
92
|
+
const limiteMs = ahora.getTime() - dias * 24 * 3600 * 1000;
|
|
93
|
+
const activos = [];
|
|
94
|
+
const archivados = [];
|
|
95
|
+
|
|
96
|
+
for (const linea of lineas) {
|
|
97
|
+
const n = linea.nudge;
|
|
98
|
+
const tsMs = n && n.ts ? Date.parse(n.ts) : NaN;
|
|
99
|
+
const esViejoSinAccionar = n && n.accionado !== true && Number.isFinite(tsMs) && tsMs < limiteMs;
|
|
100
|
+
(esViejoSinAccionar ? archivados : activos).push(linea);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (archivados.length > 0) {
|
|
104
|
+
const bloque = archivados.map((l) => l.cruda).join('\n') + '\n';
|
|
105
|
+
fs.appendFileSync(rutaArchive(baseDir), bloque, 'utf8');
|
|
106
|
+
escribirLineas(baseDir, activos);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return { archivados: archivados.length };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
module.exports = { marcarAccionado, archivarViejos, DIAS_VENTANA_DEFAULT };
|