theus-cli-linux-arm64 0.2.84
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/LICENSE +42 -0
- package/README.md +295 -0
- package/RELEASE.json +18 -0
- package/assets/brand-official/v1.0/logo/theus-lockup-negative-official.png +0 -0
- package/assets/brand-official/v1.0/logo/theus-lockup-primary-dark-official.png +0 -0
- package/assets/fonts/satoshi/satoshi-300.woff2 +0 -0
- package/assets/fonts/satoshi/satoshi-400.woff2 +0 -0
- package/assets/fonts/satoshi/satoshi-500.woff2 +0 -0
- package/assets/fonts/satoshi/satoshi-700.woff2 +0 -0
- package/assets/fonts/satoshi/satoshi-900.woff2 +0 -0
- package/assets/windows-store/Square150x150Logo.png +0 -0
- package/assets/windows-store/Square44x44Logo.png +0 -0
- package/assets/windows-store/StoreLogo.png +0 -0
- package/assets/windows-store/theus-store-icon-master.png +0 -0
- package/bin/theus +0 -0
- package/package.json +18 -0
- package/vendor/theus-arsenal/.arsenal-nombres-ola2.json +6 -0
- package/vendor/theus-arsenal/.arsenal-nombres-ola3.json +72 -0
- package/vendor/theus-arsenal/.mailmap +2 -0
- package/vendor/theus-arsenal/.theus-plugin/marketplace.json +25 -0
- package/vendor/theus-arsenal/.theus-plugin/plugin.json +20 -0
- package/vendor/theus-arsenal/AUTHORS.md +8 -0
- package/vendor/theus-arsenal/CLEANROOM_REPLACEMENT_PLAN.md +11 -0
- package/vendor/theus-arsenal/LICENSE +26 -0
- package/vendor/theus-arsenal/PROVENANCE.md +9 -0
- package/vendor/theus-arsenal/README.md +41 -0
- package/vendor/theus-arsenal/THIRD_PARTY.md +80 -0
- package/vendor/theus-arsenal/agents/actualizador-docs.md +123 -0
- package/vendor/theus-arsenal/agents/analista-comentarios.md +53 -0
- package/vendor/theus-arsenal/agents/analista-conversaciones.md +60 -0
- package/vendor/theus-arsenal/agents/analista-tests-pr.md +53 -0
- package/vendor/theus-arsenal/agents/analista-tipos.md +49 -0
- package/vendor/theus-arsenal/agents/arquitecto-accesibilidad.md +148 -0
- package/vendor/theus-arsenal/agents/arquitecto-codigo.md +79 -0
- package/vendor/theus-arsenal/agents/arquitecto-homelab.md +90 -0
- package/vendor/theus-arsenal/agents/arquitecto-redes.md +116 -0
- package/vendor/theus-arsenal/agents/arquitecto-sistemas.md +219 -0
- package/vendor/theus-arsenal/agents/bifurcador-opensource.md +206 -0
- package/vendor/theus-arsenal/agents/cazador-fallos-silenciosos.md +58 -0
- package/vendor/theus-arsenal/agents/consultor-documentacion.md +76 -0
- package/vendor/theus-arsenal/agents/diagnosticador-redes.md +135 -0
- package/vendor/theus-arsenal/agents/ejecutor-e2e.md +96 -0
- package/vendor/theus-arsenal/agents/empaquetador-opensource.md +257 -0
- package/vendor/theus-arsenal/agents/escaner-secretos.md +196 -0
- package/vendor/theus-arsenal/agents/especialista-seo.md +70 -0
- package/vendor/theus-arsenal/agents/estratega-marketing.md +158 -0
- package/vendor/theus-arsenal/agents/evaluador-agentes.md +214 -0
- package/vendor/theus-arsenal/agents/evaluador-harness.md +217 -0
- package/vendor/theus-arsenal/agents/explorador-codigo.md +79 -0
- package/vendor/theus-arsenal/agents/extractor-specs.md +214 -0
- package/vendor/theus-arsenal/agents/generador-harness.md +139 -0
- package/vendor/theus-arsenal/agents/guia-tdd.md +99 -0
- package/vendor/theus-arsenal/agents/jefe-de-gabinete.md +162 -0
- package/vendor/theus-arsenal/agents/limpiador-refactors.md +93 -0
- package/vendor/theus-arsenal/agents/optimizador-rendimiento.md +454 -0
- package/vendor/theus-arsenal/agents/planificador-harness.md +107 -0
- package/vendor/theus-arsenal/agents/planificador.md +221 -0
- package/vendor/theus-arsenal/agents/resolutor-apps-harmonyos.md +181 -0
- package/vendor/theus-arsenal/agents/resolutor-builds-cpp.md +98 -0
- package/vendor/theus-arsenal/agents/resolutor-builds-dart.md +209 -0
- package/vendor/theus-arsenal/agents/resolutor-builds-django.md +253 -0
- package/vendor/theus-arsenal/agents/resolutor-builds-go.md +102 -0
- package/vendor/theus-arsenal/agents/resolutor-builds-java.md +274 -0
- package/vendor/theus-arsenal/agents/resolutor-builds-kotlin.md +128 -0
- package/vendor/theus-arsenal/agents/resolutor-builds-pytorch.md +128 -0
- package/vendor/theus-arsenal/agents/resolutor-builds-react.md +214 -0
- package/vendor/theus-arsenal/agents/resolutor-builds-rust.md +156 -0
- package/vendor/theus-arsenal/agents/resolutor-builds-swift.md +169 -0
- package/vendor/theus-arsenal/agents/resolutor-builds.md +122 -0
- package/vendor/theus-arsenal/agents/revisor-bd.md +97 -0
- package/vendor/theus-arsenal/agents/revisor-codigo.md +291 -0
- package/vendor/theus-arsenal/agents/revisor-config-red.md +116 -0
- package/vendor/theus-arsenal/agents/revisor-cpp.md +80 -0
- package/vendor/theus-arsenal/agents/revisor-csharp.md +109 -0
- package/vendor/theus-arsenal/agents/revisor-django.md +168 -0
- package/vendor/theus-arsenal/agents/revisor-fastapi.md +82 -0
- package/vendor/theus-arsenal/agents/revisor-flutter.md +251 -0
- package/vendor/theus-arsenal/agents/revisor-go.md +84 -0
- package/vendor/theus-arsenal/agents/revisor-java.md +192 -0
- package/vendor/theus-arsenal/agents/revisor-kotlin.md +171 -0
- package/vendor/theus-arsenal/agents/revisor-ml.md +159 -0
- package/vendor/theus-arsenal/agents/revisor-php.md +108 -0
- package/vendor/theus-arsenal/agents/revisor-python.md +106 -0
- package/vendor/theus-arsenal/agents/revisor-react.md +166 -0
- package/vendor/theus-arsenal/agents/revisor-rust.md +102 -0
- package/vendor/theus-arsenal/agents/revisor-seguridad.md +116 -0
- package/vendor/theus-arsenal/agents/revisor-software-clinico.md +95 -0
- package/vendor/theus-arsenal/agents/revisor-swift.md +115 -0
- package/vendor/theus-arsenal/agents/revisor-typescript.md +123 -0
- package/vendor/theus-arsenal/agents/revisor-vue.md +205 -0
- package/vendor/theus-arsenal/agents/simplificador-codigo.md +55 -0
- package/vendor/theus-arsenal/commands/actualizar-docs.md +88 -0
- package/vendor/theus-arsenal/commands/actualizar-mapas-codigo.md +78 -0
- package/vendor/theus-arsenal/commands/aprender-evaluar.md +109 -0
- package/vendor/theus-arsenal/commands/aprender.md +74 -0
- package/vendor/theus-arsenal/commands/arreglar-build.md +66 -0
- package/vendor/theus-arsenal/commands/bucle-multiperspectiva.md +153 -0
- package/vendor/theus-arsenal/commands/build-cpp.md +173 -0
- package/vendor/theus-arsenal/commands/build-flutter.md +164 -0
- package/vendor/theus-arsenal/commands/build-go.md +183 -0
- package/vendor/theus-arsenal/commands/build-gradle.md +75 -0
- package/vendor/theus-arsenal/commands/build-kotlin.md +176 -0
- package/vendor/theus-arsenal/commands/build-react.md +187 -0
- package/vendor/theus-arsenal/commands/build-rust.md +187 -0
- package/vendor/theus-arsenal/commands/campana-marketing.md +125 -0
- package/vendor/theus-arsenal/commands/checkpoint.md +78 -0
- package/vendor/theus-arsenal/commands/cobertura-tests.md +73 -0
- package/vendor/theus-arsenal/commands/configurar-gestor-paquetes.md +86 -0
- package/vendor/theus-arsenal/commands/consulta.md +164 -0
- package/vendor/theus-arsenal/commands/control-calidad.md +50 -0
- package/vendor/theus-arsenal/commands/crear-skill.md +77 -0
- package/vendor/theus-arsenal/commands/enrutar-modelo.md +30 -0
- package/vendor/theus-arsenal/commands/epica-desbloquear.md +17 -0
- package/vendor/theus-arsenal/commands/epica-descomponer.md +22 -0
- package/vendor/theus-arsenal/commands/epica-publicar.md +21 -0
- package/vendor/theus-arsenal/commands/epica-reclamar.md +25 -0
- package/vendor/theus-arsenal/commands/epica-revisar.md +22 -0
- package/vendor/theus-arsenal/commands/epica-sincronizar.md +21 -0
- package/vendor/theus-arsenal/commands/epica-validar.md +21 -0
- package/vendor/theus-arsenal/commands/evolucionar.md +176 -0
- package/vendor/theus-arsenal/commands/funcionalidad.md +49 -0
- package/vendor/theus-arsenal/commands/guardar-sesion.md +278 -0
- package/vendor/theus-arsenal/commands/harness-build.md +111 -0
- package/vendor/theus-arsenal/commands/harness-diseno.md +46 -0
- package/vendor/theus-arsenal/commands/informe-costos.md +90 -0
- package/vendor/theus-arsenal/commands/iniciar-bucle.md +36 -0
- package/vendor/theus-arsenal/commands/instintos-estado.md +53 -0
- package/vendor/theus-arsenal/commands/instintos-exportar.md +69 -0
- package/vendor/theus-arsenal/commands/instintos-importar.md +120 -0
- package/vendor/theus-arsenal/commands/lienzo-planes.md +48 -0
- package/vendor/theus-arsenal/commands/limpiar-refactor.md +84 -0
- package/vendor/theus-arsenal/commands/modo-seguro.md +96 -0
- package/vendor/theus-arsenal/commands/orq-agregar-funcionalidad.md +36 -0
- package/vendor/theus-arsenal/commands/orq-cambiar-funcionalidad.md +38 -0
- package/vendor/theus-arsenal/commands/orq-construir-mvp.md +36 -0
- package/vendor/theus-arsenal/commands/orq-corregir-defecto.md +40 -0
- package/vendor/theus-arsenal/commands/orq-refinar-codigo.md +44 -0
- package/vendor/theus-arsenal/commands/orq-revisar.md +135 -0
- package/vendor/theus-arsenal/commands/plan-prd.md +160 -0
- package/vendor/theus-arsenal/commands/plan.md +198 -0
- package/vendor/theus-arsenal/commands/podar.md +31 -0
- package/vendor/theus-arsenal/commands/pr.md +181 -0
- package/vendor/theus-arsenal/commands/promover.md +41 -0
- package/vendor/theus-arsenal/commands/proyectos.md +33 -0
- package/vendor/theus-arsenal/commands/prp-commit.md +112 -0
- package/vendor/theus-arsenal/commands/prp-implementar.md +385 -0
- package/vendor/theus-arsenal/commands/prp-planificar.md +501 -0
- package/vendor/theus-arsenal/commands/reanudar-sesion.md +160 -0
- package/vendor/theus-arsenal/commands/revisar-codigo.md +289 -0
- package/vendor/theus-arsenal/commands/revisar-cpp.md +132 -0
- package/vendor/theus-arsenal/commands/revisar-fastapi.md +39 -0
- package/vendor/theus-arsenal/commands/revisar-flutter.md +115 -0
- package/vendor/theus-arsenal/commands/revisar-go.md +148 -0
- package/vendor/theus-arsenal/commands/revisar-kotlin.md +140 -0
- package/vendor/theus-arsenal/commands/revisar-pr.md +37 -0
- package/vendor/theus-arsenal/commands/revisar-python.md +297 -0
- package/vendor/theus-arsenal/commands/revisar-react.md +170 -0
- package/vendor/theus-arsenal/commands/revisar-rust.md +142 -0
- package/vendor/theus-arsenal/commands/revisar-vue.md +174 -0
- package/vendor/theus-arsenal/commands/salud-skills.md +52 -0
- package/vendor/theus-arsenal/commands/sesiones.md +345 -0
- package/vendor/theus-arsenal/commands/test-cpp.md +252 -0
- package/vendor/theus-arsenal/commands/test-flutter.md +143 -0
- package/vendor/theus-arsenal/commands/test-go.md +268 -0
- package/vendor/theus-arsenal/commands/test-kotlin.md +312 -0
- package/vendor/theus-arsenal/commands/test-react.md +265 -0
- package/vendor/theus-arsenal/commands/test-rust.md +309 -0
- package/vendor/theus-arsenal/commands/vigilancia-canary.md +43 -0
- package/vendor/theus-arsenal/hooks/hooks.json +274 -0
- package/vendor/theus-arsenal/package.json +6 -0
- package/vendor/theus-arsenal/rules/angular/coding-style.md +182 -0
- package/vendor/theus-arsenal/rules/angular/hooks.md +25 -0
- package/vendor/theus-arsenal/rules/angular/patterns.md +249 -0
- package/vendor/theus-arsenal/rules/angular/security.md +87 -0
- package/vendor/theus-arsenal/rules/angular/testing.md +164 -0
- package/vendor/theus-arsenal/rules/arkts/coding-style.md +153 -0
- package/vendor/theus-arsenal/rules/arkts/hooks.md +80 -0
- package/vendor/theus-arsenal/rules/arkts/patterns.md +236 -0
- package/vendor/theus-arsenal/rules/arkts/security.md +141 -0
- package/vendor/theus-arsenal/rules/arkts/testing.md +126 -0
- package/vendor/theus-arsenal/rules/common/agents.md +49 -0
- package/vendor/theus-arsenal/rules/common/code-review.md +123 -0
- package/vendor/theus-arsenal/rules/common/coding-style.md +90 -0
- package/vendor/theus-arsenal/rules/common/development-workflow.md +44 -0
- package/vendor/theus-arsenal/rules/common/git-workflow.md +24 -0
- package/vendor/theus-arsenal/rules/common/hooks.md +32 -0
- package/vendor/theus-arsenal/rules/common/patterns.md +31 -0
- package/vendor/theus-arsenal/rules/common/performance.md +53 -0
- package/vendor/theus-arsenal/rules/common/security.md +29 -0
- package/vendor/theus-arsenal/rules/common/testing.md +57 -0
- package/vendor/theus-arsenal/rules/cpp/coding-style.md +44 -0
- package/vendor/theus-arsenal/rules/cpp/hooks.md +39 -0
- package/vendor/theus-arsenal/rules/cpp/patterns.md +51 -0
- package/vendor/theus-arsenal/rules/cpp/security.md +51 -0
- package/vendor/theus-arsenal/rules/cpp/testing.md +44 -0
- package/vendor/theus-arsenal/rules/csharp/coding-style.md +72 -0
- package/vendor/theus-arsenal/rules/csharp/hooks.md +25 -0
- package/vendor/theus-arsenal/rules/csharp/patterns.md +50 -0
- package/vendor/theus-arsenal/rules/csharp/security.md +58 -0
- package/vendor/theus-arsenal/rules/csharp/testing.md +50 -0
- package/vendor/theus-arsenal/rules/dart/coding-style.md +159 -0
- package/vendor/theus-arsenal/rules/dart/hooks.md +68 -0
- package/vendor/theus-arsenal/rules/dart/patterns.md +261 -0
- package/vendor/theus-arsenal/rules/dart/security.md +135 -0
- package/vendor/theus-arsenal/rules/dart/testing.md +215 -0
- package/vendor/theus-arsenal/rules/fsharp/coding-style.md +112 -0
- package/vendor/theus-arsenal/rules/fsharp/hooks.md +26 -0
- package/vendor/theus-arsenal/rules/fsharp/patterns.md +111 -0
- package/vendor/theus-arsenal/rules/fsharp/security.md +76 -0
- package/vendor/theus-arsenal/rules/fsharp/testing.md +62 -0
- package/vendor/theus-arsenal/rules/golang/coding-style.md +32 -0
- package/vendor/theus-arsenal/rules/golang/hooks.md +17 -0
- package/vendor/theus-arsenal/rules/golang/patterns.md +45 -0
- package/vendor/theus-arsenal/rules/golang/security.md +34 -0
- package/vendor/theus-arsenal/rules/golang/testing.md +31 -0
- package/vendor/theus-arsenal/rules/java/coding-style.md +114 -0
- package/vendor/theus-arsenal/rules/java/hooks.md +18 -0
- package/vendor/theus-arsenal/rules/java/patterns.md +147 -0
- package/vendor/theus-arsenal/rules/java/security.md +101 -0
- package/vendor/theus-arsenal/rules/java/testing.md +133 -0
- package/vendor/theus-arsenal/rules/kotlin/coding-style.md +86 -0
- package/vendor/theus-arsenal/rules/kotlin/hooks.md +17 -0
- package/vendor/theus-arsenal/rules/kotlin/patterns.md +146 -0
- package/vendor/theus-arsenal/rules/kotlin/security.md +82 -0
- package/vendor/theus-arsenal/rules/kotlin/testing.md +128 -0
- package/vendor/theus-arsenal/rules/nuxt/coding-style.md +47 -0
- package/vendor/theus-arsenal/rules/nuxt/hooks.md +39 -0
- package/vendor/theus-arsenal/rules/nuxt/patterns.md +54 -0
- package/vendor/theus-arsenal/rules/nuxt/security.md +48 -0
- package/vendor/theus-arsenal/rules/nuxt/testing.md +49 -0
- package/vendor/theus-arsenal/rules/php/coding-style.md +40 -0
- package/vendor/theus-arsenal/rules/php/hooks.md +24 -0
- package/vendor/theus-arsenal/rules/php/patterns.md +33 -0
- package/vendor/theus-arsenal/rules/php/security.md +37 -0
- package/vendor/theus-arsenal/rules/php/testing.md +38 -0
- package/vendor/theus-arsenal/rules/python/coding-style.md +42 -0
- package/vendor/theus-arsenal/rules/python/fastapi.md +58 -0
- package/vendor/theus-arsenal/rules/python/hooks.md +19 -0
- package/vendor/theus-arsenal/rules/python/patterns.md +39 -0
- package/vendor/theus-arsenal/rules/python/security.md +30 -0
- package/vendor/theus-arsenal/rules/python/testing.md +38 -0
- package/vendor/theus-arsenal/rules/react/coding-style.md +109 -0
- package/vendor/theus-arsenal/rules/react/hooks.md +187 -0
- package/vendor/theus-arsenal/rules/react/patterns.md +194 -0
- package/vendor/theus-arsenal/rules/react/security.md +180 -0
- package/vendor/theus-arsenal/rules/react/testing.md +208 -0
- package/vendor/theus-arsenal/rules/react-native/accessibility.md +55 -0
- package/vendor/theus-arsenal/rules/react-native/coding-style.md +71 -0
- package/vendor/theus-arsenal/rules/react-native/hooks.md +28 -0
- package/vendor/theus-arsenal/rules/react-native/patterns.md +88 -0
- package/vendor/theus-arsenal/rules/react-native/performance.md +45 -0
- package/vendor/theus-arsenal/rules/react-native/production-readiness.md +51 -0
- package/vendor/theus-arsenal/rules/react-native/security.md +43 -0
- package/vendor/theus-arsenal/rules/react-native/testing.md +52 -0
- package/vendor/theus-arsenal/rules/ruby/coding-style.md +46 -0
- package/vendor/theus-arsenal/rules/ruby/hooks.md +37 -0
- package/vendor/theus-arsenal/rules/ruby/patterns.md +44 -0
- package/vendor/theus-arsenal/rules/ruby/security.md +51 -0
- package/vendor/theus-arsenal/rules/ruby/testing.md +51 -0
- package/vendor/theus-arsenal/rules/rust/coding-style.md +151 -0
- package/vendor/theus-arsenal/rules/rust/hooks.md +16 -0
- package/vendor/theus-arsenal/rules/rust/patterns.md +168 -0
- package/vendor/theus-arsenal/rules/rust/security.md +141 -0
- package/vendor/theus-arsenal/rules/rust/testing.md +154 -0
- package/vendor/theus-arsenal/rules/swift/coding-style.md +47 -0
- package/vendor/theus-arsenal/rules/swift/hooks.md +20 -0
- package/vendor/theus-arsenal/rules/swift/patterns.md +66 -0
- package/vendor/theus-arsenal/rules/swift/security.md +33 -0
- package/vendor/theus-arsenal/rules/swift/testing.md +45 -0
- package/vendor/theus-arsenal/rules/typescript/coding-style.md +199 -0
- package/vendor/theus-arsenal/rules/typescript/hooks.md +22 -0
- package/vendor/theus-arsenal/rules/typescript/patterns.md +52 -0
- package/vendor/theus-arsenal/rules/typescript/security.md +28 -0
- package/vendor/theus-arsenal/rules/typescript/testing.md +18 -0
- package/vendor/theus-arsenal/rules/vue/coding-style.md +54 -0
- package/vendor/theus-arsenal/rules/vue/hooks.md +45 -0
- package/vendor/theus-arsenal/rules/vue/patterns.md +56 -0
- package/vendor/theus-arsenal/rules/vue/security.md +46 -0
- package/vendor/theus-arsenal/rules/vue/testing.md +53 -0
- package/vendor/theus-arsenal/rules/web/coding-style.md +108 -0
- package/vendor/theus-arsenal/rules/web/design-quality.md +75 -0
- package/vendor/theus-arsenal/rules/web/hooks.md +141 -0
- package/vendor/theus-arsenal/rules/web/patterns.md +91 -0
- package/vendor/theus-arsenal/rules/web/performance.md +76 -0
- package/vendor/theus-arsenal/rules/web/security.md +69 -0
- package/vendor/theus-arsenal/rules/web/testing.md +67 -0
- package/vendor/theus-arsenal/scripts/hooks/bash-hook-dispatcher.js +192 -0
- package/vendor/theus-arsenal/scripts/hooks/block-no-verify.js +556 -0
- package/vendor/theus-arsenal/scripts/hooks/check-console-log.js +92 -0
- package/vendor/theus-arsenal/scripts/hooks/check-hook-enabled.js +16 -0
- package/vendor/theus-arsenal/scripts/hooks/config-protection.js +171 -0
- package/vendor/theus-arsenal/scripts/hooks/design-quality-check.js +132 -0
- package/vendor/theus-arsenal/scripts/hooks/doc-file-warning.js +110 -0
- package/vendor/theus-arsenal/scripts/hooks/modo-seguro.js +158 -0
- package/vendor/theus-arsenal/scripts/hooks/notificacion-escritorio.js +208 -0
- package/vendor/theus-arsenal/scripts/hooks/plugin-hook-bootstrap.js +280 -0
- package/vendor/theus-arsenal/scripts/hooks/post-bash-command-log.js +87 -0
- package/vendor/theus-arsenal/scripts/hooks/post-bash-dispatcher.js +24 -0
- package/vendor/theus-arsenal/scripts/hooks/post-bash-pr-created.js +60 -0
- package/vendor/theus-arsenal/scripts/hooks/post-edit-accumulator.js +94 -0
- package/vendor/theus-arsenal/scripts/hooks/post-edit-console-warn.js +54 -0
- package/vendor/theus-arsenal/scripts/hooks/post-edit-format.js +110 -0
- package/vendor/theus-arsenal/scripts/hooks/post-edit-typecheck.js +98 -0
- package/vendor/theus-arsenal/scripts/hooks/pre-bash-commit-quality.js +447 -0
- package/vendor/theus-arsenal/scripts/hooks/pre-bash-dev-server-block.js +232 -0
- package/vendor/theus-arsenal/scripts/hooks/pre-bash-dispatcher.js +27 -0
- package/vendor/theus-arsenal/scripts/hooks/pre-compact.js +101 -0
- package/vendor/theus-arsenal/scripts/hooks/pretooluse-visible-output.js +49 -0
- package/vendor/theus-arsenal/scripts/hooks/quality-gate.js +168 -0
- package/vendor/theus-arsenal/scripts/hooks/run-with-flags.js +271 -0
- package/vendor/theus-arsenal/scripts/hooks/salud-mcp.js +749 -0
- package/vendor/theus-arsenal/scripts/hooks/seguimiento-costos.js +161 -0
- package/vendor/theus-arsenal/scripts/hooks/session-end.js +340 -0
- package/vendor/theus-arsenal/scripts/hooks/session-start.js +906 -0
- package/vendor/theus-arsenal/scripts/hooks/stop-format-typecheck.js +263 -0
- package/vendor/theus-arsenal/scripts/hooks/suggest-compact.js +286 -0
- package/vendor/theus-arsenal/scripts/hooks/theus-context-monitor.js +289 -0
- package/vendor/theus-arsenal/scripts/hooks/verificacion-factual.js +1278 -0
- package/vendor/theus-arsenal/scripts/lib/agent-data-home.js +96 -0
- package/vendor/theus-arsenal/scripts/lib/cost-estimate.js +66 -0
- package/vendor/theus-arsenal/scripts/lib/hook-flags.js +79 -0
- package/vendor/theus-arsenal/scripts/lib/llm-summary.js +185 -0
- package/vendor/theus-arsenal/scripts/lib/loopback-guard.js +54 -0
- package/vendor/theus-arsenal/scripts/lib/observer-sessions.js +237 -0
- package/vendor/theus-arsenal/scripts/lib/package-manager.d.ts +120 -0
- package/vendor/theus-arsenal/scripts/lib/package-manager.js +434 -0
- package/vendor/theus-arsenal/scripts/lib/path-safety.js +86 -0
- package/vendor/theus-arsenal/scripts/lib/plan-canvas/markdown.js +285 -0
- package/vendor/theus-arsenal/scripts/lib/plan-canvas/sdk.js +238 -0
- package/vendor/theus-arsenal/scripts/lib/plan-canvas/server.js +534 -0
- package/vendor/theus-arsenal/scripts/lib/plan-canvas/sessions.js +274 -0
- package/vendor/theus-arsenal/scripts/lib/plan-canvas/ui.js +546 -0
- package/vendor/theus-arsenal/scripts/lib/project-detect.js +451 -0
- package/vendor/theus-arsenal/scripts/lib/resolve-formatter.js +193 -0
- package/vendor/theus-arsenal/scripts/lib/resolve-theus-root.js +101 -0
- package/vendor/theus-arsenal/scripts/lib/session-aliases.d.ts +138 -0
- package/vendor/theus-arsenal/scripts/lib/session-aliases.js +483 -0
- package/vendor/theus-arsenal/scripts/lib/session-bridge.js +155 -0
- package/vendor/theus-arsenal/scripts/lib/session-manager.d.ts +137 -0
- package/vendor/theus-arsenal/scripts/lib/session-manager.js +555 -0
- package/vendor/theus-arsenal/scripts/lib/shell-split.js +86 -0
- package/vendor/theus-arsenal/scripts/lib/shell-substitution.js +501 -0
- package/vendor/theus-arsenal/scripts/lib/skill-evolution/dashboard.js +414 -0
- package/vendor/theus-arsenal/scripts/lib/skill-evolution/health.js +285 -0
- package/vendor/theus-arsenal/scripts/lib/skill-evolution/index.js +22 -0
- package/vendor/theus-arsenal/scripts/lib/skill-evolution/provenance.js +200 -0
- package/vendor/theus-arsenal/scripts/lib/skill-evolution/tracker.js +157 -0
- package/vendor/theus-arsenal/scripts/lib/skill-evolution/versioning.js +246 -0
- package/vendor/theus-arsenal/scripts/lib/transcript-context.js +232 -0
- package/vendor/theus-arsenal/scripts/lib/utils.d.ts +205 -0
- package/vendor/theus-arsenal/scripts/lib/utils.js +658 -0
- package/vendor/theus-arsenal/scripts/plan-canvas.js +341 -0
- package/vendor/theus-arsenal/scripts/setup-package-manager.js +46 -0
- package/vendor/theus-arsenal/scripts/skills-health.js +143 -0
- package/vendor/theus-arsenal/skills/a11y-frontend/SKILL.md +444 -0
- package/vendor/theus-arsenal/skills/accesibilidad/SKILL.md +144 -0
- package/vendor/theus-arsenal/skills/acelerador-throughput-datos/SKILL.md +72 -0
- package/vendor/theus-arsenal/skills/agente-scraper-datos/SKILL.md +771 -0
- package/vendor/theus-arsenal/skills/analisis-plataformas-competencia/SKILL.md +137 -0
- package/vendor/theus-arsenal/skills/api-x/SKILL.md +233 -0
- package/vendor/theus-arsenal/skills/aprendizaje-continuo-v2/SKILL.md +335 -0
- package/vendor/theus-arsenal/skills/aprendizaje-continuo-v2/agents/observer-loop.sh +374 -0
- package/vendor/theus-arsenal/skills/aprendizaje-continuo-v2/agents/observer.md +188 -0
- package/vendor/theus-arsenal/skills/aprendizaje-continuo-v2/agents/session-guardian.sh +153 -0
- package/vendor/theus-arsenal/skills/aprendizaje-continuo-v2/agents/start-observer.sh +253 -0
- package/vendor/theus-arsenal/skills/aprendizaje-continuo-v2/config.json +8 -0
- package/vendor/theus-arsenal/skills/aprendizaje-continuo-v2/hooks/observe.sh +594 -0
- package/vendor/theus-arsenal/skills/aprendizaje-continuo-v2/scripts/detect-project.sh +325 -0
- package/vendor/theus-arsenal/skills/aprendizaje-continuo-v2/scripts/instinct-cli.py +1918 -0
- package/vendor/theus-arsenal/skills/aprendizaje-continuo-v2/scripts/lib/arsenal-dir.sh +23 -0
- package/vendor/theus-arsenal/skills/aprendizaje-continuo-v2/scripts/test_parse_instinct.py +1420 -0
- package/vendor/theus-arsenal/skills/arquitectura-hexagonal/SKILL.md +275 -0
- package/vendor/theus-arsenal/skills/arquitectura-limpia-android/SKILL.md +340 -0
- package/vendor/theus-arsenal/skills/arquitectura-pipelines-recomendacion/SKILL.md +112 -0
- package/vendor/theus-arsenal/skills/atlas-datos-prediccion/SKILL.md +53 -0
- package/vendor/theus-arsenal/skills/auditoria-arquitectura-agentes/SKILL.md +257 -0
- package/vendor/theus-arsenal/skills/auditoria-produccion/SKILL.md +180 -0
- package/vendor/theus-arsenal/skills/auditoria-rutas-clic/SKILL.md +243 -0
- package/vendor/theus-arsenal/skills/autoevaluacion-agente/SKILL.md +180 -0
- package/vendor/theus-arsenal/skills/autoevaluacion-agente/examples/high-score-example.md +89 -0
- package/vendor/theus-arsenal/skills/autoevaluacion-agente/examples/low-score-example.md +87 -0
- package/vendor/theus-arsenal/skills/autoevaluacion-agente/references/evaluation-criteria.md +71 -0
- package/vendor/theus-arsenal/skills/autoevaluacion-agente/references/hook-integration.md +90 -0
- package/vendor/theus-arsenal/skills/autoevaluacion-agente/scripts/evaluate.py +409 -0
- package/vendor/theus-arsenal/skills/autoevaluacion-agente/templates/evaluation-report.md +86 -0
- package/vendor/theus-arsenal/skills/automatizacion-ssh-netmiko/SKILL.md +176 -0
- package/vendor/theus-arsenal/skills/base-datos-pubmed/SKILL.md +174 -0
- package/vendor/theus-arsenal/skills/base-datos-uspto/SKILL.md +173 -0
- package/vendor/theus-arsenal/skills/benchmark/SKILL.md +92 -0
- package/vendor/theus-arsenal/skills/bitacora-crecimiento/SKILL.md +120 -0
- package/vendor/theus-arsenal/skills/bucle-verificacion/SKILL.md +125 -0
- package/vendor/theus-arsenal/skills/buscar-primero/SKILL.md +184 -0
- package/vendor/theus-arsenal/skills/busqueda-exa/SKILL.md +111 -0
- package/vendor/theus-arsenal/skills/cache-por-hash/SKILL.md +160 -0
- package/vendor/theus-arsenal/skills/campana-marketing/SKILL.md +118 -0
- package/vendor/theus-arsenal/skills/capacidad-producto/SKILL.md +138 -0
- package/vendor/theus-arsenal/skills/cazador-vulnerabilidades/SKILL.md +104 -0
- package/vendor/theus-arsenal/skills/compactacion-estrategica/SKILL.md +115 -0
- package/vendor/theus-arsenal/skills/comparador-baskets-prediccion/SKILL.md +69 -0
- package/vendor/theus-arsenal/skills/compras-energia/SKILL.md +206 -0
- package/vendor/theus-arsenal/skills/concurrencia-swift-6-2/SKILL.md +224 -0
- package/vendor/theus-arsenal/skills/consejo/SKILL.md +201 -0
- package/vendor/theus-arsenal/skills/construccion-harness-agentes/SKILL.md +78 -0
- package/vendor/theus-arsenal/skills/constructor-conectores/SKILL.md +119 -0
- package/vendor/theus-arsenal/skills/constructor-equipos/SKILL.md +169 -0
- package/vendor/theus-arsenal/skills/consulta-documentacion/SKILL.md +92 -0
- package/vendor/theus-arsenal/skills/consultas-genomicas-gget/SKILL.md +170 -0
- package/vendor/theus-arsenal/skills/contacto-inversores/SKILL.md +95 -0
- package/vendor/theus-arsenal/skills/corrutinas-flows-kotlin/SKILL.md +284 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/SKILL.md +46 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/3d.md +86 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/animations.md +29 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/assets/charts-bar-chart.tsx +173 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/assets/text-animations-typewriter.tsx +100 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/assets/text-animations-word-highlight.tsx +108 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/assets.md +78 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/audio.md +172 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/calculate-metadata.md +104 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/can-decode.md +75 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/charts.md +58 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/compositions.md +146 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/display-captions.md +126 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/extract-frames.md +229 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/fonts.md +152 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/get-audio-duration.md +58 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/get-video-dimensions.md +68 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/get-video-duration.md +58 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/gifs.md +138 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/images.md +130 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/import-srt-captions.md +67 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/lottie.md +67 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/measuring-dom-nodes.md +34 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/measuring-text.md +143 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/sequencing.md +106 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/tailwind.md +11 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/text-animations.md +20 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/timing.md +179 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/transcribe-captions.md +19 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/transitions.md +122 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/trimming.md +52 -0
- package/vendor/theus-arsenal/skills/creacion-video-remotion/rules/videos.md +171 -0
- package/vendor/theus-arsenal/skills/cumplimiento-aduanero/SKILL.md +270 -0
- package/vendor/theus-arsenal/skills/cumplimiento-hipaa/SKILL.md +78 -0
- package/vendor/theus-arsenal/skills/datos-sensibles-salud/SKILL.md +149 -0
- package/vendor/theus-arsenal/skills/decimales-tokens-evm/SKILL.md +128 -0
- package/vendor/theus-arsenal/skills/decisiones-arquitectura/SKILL.md +206 -0
- package/vendor/theus-arsenal/skills/demos-ui/SKILL.md +469 -0
- package/vendor/theus-arsenal/skills/desarrollo-por-intencion/SKILL.md +369 -0
- package/vendor/theus-arsenal/skills/descubrimiento-marca/SKILL.md +149 -0
- package/vendor/theus-arsenal/skills/descubrimiento-marca/references/10_proposito-porque.md +42 -0
- package/vendor/theus-arsenal/skills/descubrimiento-marca/references/20_posicionamiento.md +47 -0
- package/vendor/theus-arsenal/skills/descubrimiento-marca/references/30_audiencia-nicho.md +53 -0
- package/vendor/theus-arsenal/skills/descubrimiento-marca/references/40_personalidad-arquetipo.md +61 -0
- package/vendor/theus-arsenal/skills/descubrimiento-marca/references/50_voz-tono.md +62 -0
- package/vendor/theus-arsenal/skills/descubrimiento-marca/references/60_narrativa-historia.md +54 -0
- package/vendor/theus-arsenal/skills/descubrimiento-marca/references/70_tension-fundador.md +50 -0
- package/vendor/theus-arsenal/skills/descubrimiento-marca/references/90_SINTESIS.md +133 -0
- package/vendor/theus-arsenal/skills/descubrimiento-plugins-laravel/SKILL.md +230 -0
- package/vendor/theus-arsenal/skills/destilado-reglas/SKILL.md +263 -0
- package/vendor/theus-arsenal/skills/destilado-reglas/scripts/scan-rules.sh +58 -0
- package/vendor/theus-arsenal/skills/destilado-reglas/scripts/scan-skills.sh +129 -0
- package/vendor/theus-arsenal/skills/diagnostico-bgp/SKILL.md +170 -0
- package/vendor/theus-arsenal/skills/direccion-estetica/SKILL.md +220 -0
- package/vendor/theus-arsenal/skills/direccion-estetica/references/taxonomia-generos.md +89 -0
- package/vendor/theus-arsenal/skills/diseno-api/SKILL.md +522 -0
- package/vendor/theus-arsenal/skills/diseno-liquid-glass/SKILL.md +282 -0
- package/vendor/theus-arsenal/skills/e2e-escritorio-windows/SKILL.md +879 -0
- package/vendor/theus-arsenal/skills/edicion-video/SKILL.md +289 -0
- package/vendor/theus-arsenal/skills/enfoque-producto/SKILL.md +91 -0
- package/vendor/theus-arsenal/skills/entornos-flox/SKILL.md +493 -0
- package/vendor/theus-arsenal/skills/estandares-codigo/SKILL.md +548 -0
- package/vendor/theus-arsenal/skills/estandares-cpp/SKILL.md +727 -0
- package/vendor/theus-arsenal/skills/estandares-java/SKILL.md +389 -0
- package/vendor/theus-arsenal/skills/estilo-legado/SKILL.md +149 -0
- package/vendor/theus-arsenal/skills/estructura-informes-competencia/SKILL.md +95 -0
- package/vendor/theus-arsenal/skills/evaluacion-academica/SKILL.md +165 -0
- package/vendor/theus-arsenal/skills/explorador-skills/SKILL.md +129 -0
- package/vendor/theus-arsenal/skills/flujo-git/SKILL.md +714 -0
- package/vendor/theus-arsenal/skills/flujo-ingenieria-ml/SKILL.md +343 -0
- package/vendor/theus-arsenal/skills/flujo-tdd/SKILL.md +584 -0
- package/vendor/theus-arsenal/skills/forja-personas/SKILL.md +298 -0
- package/vendor/theus-arsenal/skills/forja-personas/gacha.py +224 -0
- package/vendor/theus-arsenal/skills/forja-personas/gacha.sh +5 -0
- package/vendor/theus-arsenal/skills/forja-personas/references/avatar-style.md +123 -0
- package/vendor/theus-arsenal/skills/forja-personas/references/boundary-rules.md +53 -0
- package/vendor/theus-arsenal/skills/forja-personas/references/error-handling.md +53 -0
- package/vendor/theus-arsenal/skills/forja-personas/references/identity-tension.md +48 -0
- package/vendor/theus-arsenal/skills/forja-personas/references/naming-system.md +39 -0
- package/vendor/theus-arsenal/skills/forja-personas/references/output-template.md +166 -0
- package/vendor/theus-arsenal/skills/fundamentos-animacion/SKILL.md +296 -0
- package/vendor/theus-arsenal/skills/generacion-iconos-ios/SKILL.md +156 -0
- package/vendor/theus-arsenal/skills/generacion-iconos-ios/scripts/generate_icons.swift +258 -0
- package/vendor/theus-arsenal/skills/generacion-iconos-ios/scripts/iconify_gen.sh +235 -0
- package/vendor/theus-arsenal/skills/gestion-excepciones-logisticas/SKILL.md +208 -0
- package/vendor/theus-arsenal/skills/gestion-transportistas/SKILL.md +204 -0
- package/vendor/theus-arsenal/skills/guia-adopcion-ml/SKILL.md +64 -0
- package/vendor/theus-arsenal/skills/harness-agente-autonomo/SKILL.md +252 -0
- package/vendor/theus-arsenal/skills/harness-eval-clinico/SKILL.md +212 -0
- package/vendor/theus-arsenal/skills/harness-evaluacion/SKILL.md +296 -0
- package/vendor/theus-arsenal/skills/harness-generador-evaluador/SKILL.md +254 -0
- package/vendor/theus-arsenal/skills/homelab-diseno-red/SKILL.md +120 -0
- package/vendor/theus-arsenal/skills/homelab-dns-pihole/SKILL.md +264 -0
- package/vendor/theus-arsenal/skills/homelab-preparacion-red/SKILL.md +144 -0
- package/vendor/theus-arsenal/skills/homelab-segmentacion-vlan/SKILL.md +307 -0
- package/vendor/theus-arsenal/skills/homelab-vpn-wireguard/SKILL.md +299 -0
- package/vendor/theus-arsenal/skills/ingenieria-agentica/SKILL.md +96 -0
- package/vendor/theus-arsenal/skills/inspeccion-animaciones-blender/SKILL.md +164 -0
- package/vendor/theus-arsenal/skills/instaladores-python/SKILL.md +820 -0
- package/vendor/theus-arsenal/skills/integracion-jira/SKILL.md +307 -0
- package/vendor/theus-arsenal/skills/inteligencia-leads/SKILL.md +312 -0
- package/vendor/theus-arsenal/skills/inteligencia-leads/agents/agente-enriquecimiento.md +87 -0
- package/vendor/theus-arsenal/skills/inteligencia-leads/agents/mapeador-mutuos.md +76 -0
- package/vendor/theus-arsenal/skills/inteligencia-leads/agents/puntuador-senales.md +60 -0
- package/vendor/theus-arsenal/skills/inteligencia-leads/agents/redactor-outreach.md +102 -0
- package/vendor/theus-arsenal/skills/inteligencia-mercados-prediccion/SKILL.md +53 -0
- package/vendor/theus-arsenal/skills/introspeccion-agente/SKILL.md +150 -0
- package/vendor/theus-arsenal/skills/inventario-skills/SKILL.md +194 -0
- package/vendor/theus-arsenal/skills/inventario-skills/scripts/quick-diff.sh +87 -0
- package/vendor/theus-arsenal/skills/inventario-skills/scripts/save-results.sh +57 -0
- package/vendor/theus-arsenal/skills/inventario-skills/scripts/scan.sh +170 -0
- package/vendor/theus-arsenal/skills/investigacion-mercado/SKILL.md +87 -0
- package/vendor/theus-arsenal/skills/investigacion-oraculos-prediccion/SKILL.md +59 -0
- package/vendor/theus-arsenal/skills/investigacion-profunda/SKILL.md +161 -0
- package/vendor/theus-arsenal/skills/keccak256-nodejs/SKILL.md +100 -0
- package/vendor/theus-arsenal/skills/libro-decisiones-recursivo/SKILL.md +82 -0
- package/vendor/theus-arsenal/skills/lienzo-planes/SKILL.md +111 -0
- package/vendor/theus-arsenal/skills/limpieza-configuracion/SKILL.md +116 -0
- package/vendor/theus-arsenal/skills/logistica-inversa-devoluciones/SKILL.md +241 -0
- package/vendor/theus-arsenal/skills/manejo-errores/SKILL.md +375 -0
- package/vendor/theus-arsenal/skills/materiales-inversores/SKILL.md +101 -0
- package/vendor/theus-arsenal/skills/memoria-por-proyecto/SKILL.md +170 -0
- package/vendor/theus-arsenal/skills/memoria-por-proyecto/commands/forget.mjs +44 -0
- package/vendor/theus-arsenal/skills/memoria-por-proyecto/commands/info.mjs +24 -0
- package/vendor/theus-arsenal/skills/memoria-por-proyecto/commands/init.mjs +152 -0
- package/vendor/theus-arsenal/skills/memoria-por-proyecto/commands/list.mjs +40 -0
- package/vendor/theus-arsenal/skills/memoria-por-proyecto/commands/migrate.mjs +214 -0
- package/vendor/theus-arsenal/skills/memoria-por-proyecto/commands/resume.mjs +36 -0
- package/vendor/theus-arsenal/skills/memoria-por-proyecto/commands/save.mjs +210 -0
- package/vendor/theus-arsenal/skills/memoria-por-proyecto/commands/shared.mjs +402 -0
- package/vendor/theus-arsenal/skills/memoria-por-proyecto/hooks/session-start.mjs +238 -0
- package/vendor/theus-arsenal/skills/metodologia-benchmarks/SKILL.md +131 -0
- package/vendor/theus-arsenal/skills/migraciones-bd/SKILL.md +430 -0
- package/vendor/theus-arsenal/skills/modelos-fundacionales-en-dispositivo/SKILL.md +244 -0
- package/vendor/theus-arsenal/skills/modo-seguro/SKILL.md +86 -0
- package/vendor/theus-arsenal/skills/motion-avanzado/SKILL.md +592 -0
- package/vendor/theus-arsenal/skills/motor-de-contenido/SKILL.md +136 -0
- package/vendor/theus-arsenal/skills/no-conformidades-calidad/SKILL.md +249 -0
- package/vendor/theus-arsenal/skills/onboarding-codigo/SKILL.md +244 -0
- package/vendor/theus-arsenal/skills/operaciones-agentes-empresariales/SKILL.md +51 -0
- package/vendor/theus-arsenal/skills/operaciones-conocimiento/SKILL.md +159 -0
- package/vendor/theus-arsenal/skills/operaciones-correo/SKILL.md +123 -0
- package/vendor/theus-arsenal/skills/operaciones-facturacion/SKILL.md +142 -0
- package/vendor/theus-arsenal/skills/operaciones-flujo-proyectos/SKILL.md +110 -0
- package/vendor/theus-arsenal/skills/operaciones-github/SKILL.md +143 -0
- package/vendor/theus-arsenal/skills/operaciones-google-workspace/SKILL.md +100 -0
- package/vendor/theus-arsenal/skills/operaciones-investigacion/SKILL.md +124 -0
- package/vendor/theus-arsenal/skills/operaciones-mensajes/SKILL.md +103 -0
- package/vendor/theus-arsenal/skills/operaciones-terminal/SKILL.md +110 -0
- package/vendor/theus-arsenal/skills/optimizacion-benchmark/SKILL.md +70 -0
- package/vendor/theus-arsenal/skills/optimizacion-costos-llm/SKILL.md +182 -0
- package/vendor/theus-arsenal/skills/optimizador-conexiones/SKILL.md +191 -0
- package/vendor/theus-arsenal/skills/optimizador-paralelismo/SKILL.md +75 -0
- package/vendor/theus-arsenal/skills/optimizador-prompts/SKILL.md +374 -0
- package/vendor/theus-arsenal/skills/orq-agregar-funcionalidad/SKILL.md +37 -0
- package/vendor/theus-arsenal/skills/orq-cambiar-funcionalidad/SKILL.md +36 -0
- package/vendor/theus-arsenal/skills/orq-construir-mvp/SKILL.md +38 -0
- package/vendor/theus-arsenal/skills/orq-corregir-defecto/SKILL.md +36 -0
- package/vendor/theus-arsenal/skills/orq-pipeline/SKILL.md +134 -0
- package/vendor/theus-arsenal/skills/orq-refinar-codigo/SKILL.md +49 -0
- package/vendor/theus-arsenal/skills/orquestacion-equipos-agentes/SKILL.md +117 -0
- package/vendor/theus-arsenal/skills/pagos-agentes-x402/SKILL.md +237 -0
- package/vendor/theus-arsenal/skills/patrones-angular/SKILL.md +153 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/angular-animations.md +160 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/angular-aria.md +410 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/cli.md +86 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/component-harnesses.md +59 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/component-styling.md +91 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/components.md +117 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/creating-services.md +97 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/data-resolvers.md +69 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/define-routes.md +67 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/defining-providers.md +72 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/di-fundamentals.md +120 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/e2e-testing.md +56 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/effects.md +83 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/hierarchical-injectors.md +43 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/host-elements.md +80 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/injection-context.md +63 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/inputs.md +101 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/linked-signal.md +59 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/loading-strategies.md +61 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/mcp.md +67 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/navigate-to-routes.md +69 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/outputs.md +86 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/reactive-forms.md +122 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/rendering-strategies.md +44 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/resource.md +77 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/route-animations.md +56 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/route-guards.md +52 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/router-lifecycle.md +45 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/router-testing.md +87 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/show-routes-with-outlets.md +68 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/signal-forms.md +795 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/signals-overview.md +94 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/tailwind-css.md +69 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/template-driven-forms.md +114 -0
- package/vendor/theus-arsenal/skills/patrones-angular/references/testing-fundamentals.md +65 -0
- package/vendor/theus-arsenal/skills/patrones-animacion/SKILL.md +432 -0
- package/vendor/theus-arsenal/skills/patrones-backend/SKILL.md +560 -0
- package/vendor/theus-arsenal/skills/patrones-cdss-clinico/SKILL.md +249 -0
- package/vendor/theus-arsenal/skills/patrones-cisco-ios/SKILL.md +148 -0
- package/vendor/theus-arsenal/skills/patrones-clickhouse/SKILL.md +443 -0
- package/vendor/theus-arsenal/skills/patrones-compose-multiplatform/SKILL.md +298 -0
- package/vendor/theus-arsenal/skills/patrones-dart-flutter/SKILL.md +566 -0
- package/vendor/theus-arsenal/skills/patrones-despliegue/SKILL.md +426 -0
- package/vendor/theus-arsenal/skills/patrones-django/SKILL.md +739 -0
- package/vendor/theus-arsenal/skills/patrones-django-celery/SKILL.md +456 -0
- package/vendor/theus-arsenal/skills/patrones-docker/SKILL.md +363 -0
- package/vendor/theus-arsenal/skills/patrones-dotnet/SKILL.md +321 -0
- package/vendor/theus-arsenal/skills/patrones-emr-clinico/SKILL.md +168 -0
- package/vendor/theus-arsenal/skills/patrones-fastapi/SKILL.md +513 -0
- package/vendor/theus-arsenal/skills/patrones-frontend/SKILL.md +655 -0
- package/vendor/theus-arsenal/skills/patrones-go/SKILL.md +674 -0
- package/vendor/theus-arsenal/skills/patrones-jpa/SKILL.md +156 -0
- package/vendor/theus-arsenal/skills/patrones-kotlin/SKILL.md +717 -0
- package/vendor/theus-arsenal/skills/patrones-kotlin-exposed/SKILL.md +724 -0
- package/vendor/theus-arsenal/skills/patrones-kotlin-ktor/SKILL.md +694 -0
- package/vendor/theus-arsenal/skills/patrones-kubernetes/SKILL.md +754 -0
- package/vendor/theus-arsenal/skills/patrones-laravel/SKILL.md +414 -0
- package/vendor/theus-arsenal/skills/patrones-mcp/SKILL.md +66 -0
- package/vendor/theus-arsenal/skills/patrones-mysql/SKILL.md +420 -0
- package/vendor/theus-arsenal/skills/patrones-nestjs/SKILL.md +229 -0
- package/vendor/theus-arsenal/skills/patrones-nextjs/SKILL.md +56 -0
- package/vendor/theus-arsenal/skills/patrones-nuxt4/SKILL.md +99 -0
- package/vendor/theus-arsenal/skills/patrones-perl/SKILL.md +508 -0
- package/vendor/theus-arsenal/skills/patrones-postgres/SKILL.md +141 -0
- package/vendor/theus-arsenal/skills/patrones-prisma/SKILL.md +399 -0
- package/vendor/theus-arsenal/skills/patrones-python/SKILL.md +750 -0
- package/vendor/theus-arsenal/skills/patrones-pytorch/SKILL.md +400 -0
- package/vendor/theus-arsenal/skills/patrones-quarkus/SKILL.md +729 -0
- package/vendor/theus-arsenal/skills/patrones-react/SKILL.md +339 -0
- package/vendor/theus-arsenal/skills/patrones-react-native/SKILL.md +325 -0
- package/vendor/theus-arsenal/skills/patrones-redis/SKILL.md +401 -0
- package/vendor/theus-arsenal/skills/patrones-rust/SKILL.md +504 -0
- package/vendor/theus-arsenal/skills/patrones-springboot/SKILL.md +314 -0
- package/vendor/theus-arsenal/skills/patrones-swiftui/SKILL.md +261 -0
- package/vendor/theus-arsenal/skills/patrones-tinystruct/SKILL.md +281 -0
- package/vendor/theus-arsenal/skills/patrones-tinystruct/references/architecture.md +90 -0
- package/vendor/theus-arsenal/skills/patrones-tinystruct/references/data-handling.md +60 -0
- package/vendor/theus-arsenal/skills/patrones-tinystruct/references/database.md +99 -0
- package/vendor/theus-arsenal/skills/patrones-tinystruct/references/routing.md +64 -0
- package/vendor/theus-arsenal/skills/patrones-tinystruct/references/system-usage.md +97 -0
- package/vendor/theus-arsenal/skills/patrones-tinystruct/references/testing.md +72 -0
- package/vendor/theus-arsenal/skills/patrones-vite/SKILL.md +449 -0
- package/vendor/theus-arsenal/skills/patrones-vue/SKILL.md +469 -0
- package/vendor/theus-arsenal/skills/persistencia-actores-swift/SKILL.md +148 -0
- package/vendor/theus-arsenal/skills/pipeline-opensource/SKILL.md +254 -0
- package/vendor/theus-arsenal/skills/planificacion-demanda-inventario/SKILL.md +236 -0
- package/vendor/theus-arsenal/skills/planificador-trades-prediccion/SKILL.md +60 -0
- package/vendor/theus-arsenal/skills/plano-tecnico/SKILL.md +102 -0
- package/vendor/theus-arsenal/skills/presentaciones-html/SKILL.md +189 -0
- package/vendor/theus-arsenal/skills/presentaciones-html/STYLE_PRESETS.md +330 -0
- package/vendor/theus-arsenal/skills/presentaciones-html/animation-patterns.md +122 -0
- package/vendor/theus-arsenal/skills/presentaciones-html/html-template.md +419 -0
- package/vendor/theus-arsenal/skills/presentaciones-html/scripts/export-pdf.sh +418 -0
- package/vendor/theus-arsenal/skills/presentaciones-html/scripts/extract-pptx.py +96 -0
- package/vendor/theus-arsenal/skills/presentaciones-html/viewport-base.css +153 -0
- package/vendor/theus-arsenal/skills/presupuesto-contexto/SKILL.md +263 -0
- package/vendor/theus-arsenal/skills/procesamiento-documentos-nutrient/SKILL.md +168 -0
- package/vendor/theus-arsenal/skills/programacion-produccion/SKILL.md +220 -0
- package/vendor/theus-arsenal/skills/publicacion-cruzada/SKILL.md +117 -0
- package/vendor/theus-arsenal/skills/publicador-social/SKILL.md +121 -0
- package/vendor/theus-arsenal/skills/puerta-de-entrega/SKILL.md +164 -0
- package/vendor/theus-arsenal/skills/puerta-de-entrega/hooks/puerta-entrega.py +242 -0
- package/vendor/theus-arsenal/skills/pulir-interfaces/SKILL.md +126 -0
- package/vendor/theus-arsenal/skills/qa-navegador/SKILL.md +103 -0
- package/vendor/theus-arsenal/skills/ranking-grafo-social/SKILL.md +153 -0
- package/vendor/theus-arsenal/skills/recuperacion-iterativa/SKILL.md +236 -0
- package/vendor/theus-arsenal/skills/redaccion-articulos/SKILL.md +81 -0
- package/vendor/theus-arsenal/skills/regex-vs-llm/SKILL.md +221 -0
- package/vendor/theus-arsenal/skills/regresion-codigo-ia/SKILL.md +388 -0
- package/vendor/theus-arsenal/skills/rendimiento-react/SKILL.md +567 -0
- package/vendor/theus-arsenal/skills/revision-codigo-flutter-dart/SKILL.md +442 -0
- package/vendor/theus-arsenal/skills/revision-literatura-cientifica/SKILL.md +191 -0
- package/vendor/theus-arsenal/skills/revision-multiperspectiva/SKILL.md +302 -0
- package/vendor/theus-arsenal/skills/revision-riesgo-prediccion/SKILL.md +56 -0
- package/vendor/theus-arsenal/skills/revision-seguridad/SKILL.md +505 -0
- package/vendor/theus-arsenal/skills/revision-seguridad/cloud-infrastructure-security.md +361 -0
- package/vendor/theus-arsenal/skills/runtime-bun/SKILL.md +83 -0
- package/vendor/theus-arsenal/skills/salud-codigo-codescene/SKILL.md +163 -0
- package/vendor/theus-arsenal/skills/salud-interfaces-red/SKILL.md +143 -0
- package/vendor/theus-arsenal/skills/seguimiento-costos/SKILL.md +122 -0
- package/vendor/theus-arsenal/skills/seguridad-agentes-trading/SKILL.md +145 -0
- package/vendor/theus-arsenal/skills/seguridad-amm-defi/SKILL.md +166 -0
- package/vendor/theus-arsenal/skills/seguridad-django/SKILL.md +648 -0
- package/vendor/theus-arsenal/skills/seguridad-laravel/SKILL.md +945 -0
- package/vendor/theus-arsenal/skills/seguridad-perl/SKILL.md +507 -0
- package/vendor/theus-arsenal/skills/seguridad-quarkus/SKILL.md +474 -0
- package/vendor/theus-arsenal/skills/seguridad-springboot/SKILL.md +279 -0
- package/vendor/theus-arsenal/skills/seo/SKILL.md +166 -0
- package/vendor/theus-arsenal/skills/sistema-diseno/SKILL.md +81 -0
- package/vendor/theus-arsenal/skills/sistema-operativo-agentico/SKILL.md +375 -0
- package/vendor/theus-arsenal/skills/sistemas-latencia-critica/SKILL.md +65 -0
- package/vendor/theus-arsenal/skills/tdd-django/SKILL.md +735 -0
- package/vendor/theus-arsenal/skills/tdd-laravel/SKILL.md +673 -0
- package/vendor/theus-arsenal/skills/tdd-quarkus/SKILL.md +817 -0
- package/vendor/theus-arsenal/skills/tdd-springboot/SKILL.md +165 -0
- package/vendor/theus-arsenal/skills/testing-cpp/SKILL.md +328 -0
- package/vendor/theus-arsenal/skills/testing-csharp/SKILL.md +321 -0
- package/vendor/theus-arsenal/skills/testing-e2e/SKILL.md +325 -0
- package/vendor/theus-arsenal/skills/testing-go/SKILL.md +719 -0
- package/vendor/theus-arsenal/skills/testing-kotlin/SKILL.md +829 -0
- package/vendor/theus-arsenal/skills/testing-perl/SKILL.md +479 -0
- package/vendor/theus-arsenal/skills/testing-protocolos-di-swift/SKILL.md +196 -0
- package/vendor/theus-arsenal/skills/testing-python/SKILL.md +815 -0
- package/vendor/theus-arsenal/skills/testing-react/SKILL.md +421 -0
- package/vendor/theus-arsenal/skills/testing-rust/SKILL.md +506 -0
- package/vendor/theus-arsenal/skills/tours-de-codigo/SKILL.md +252 -0
- package/vendor/theus-arsenal/skills/traduccion-documentos-visado/SKILL.md +121 -0
- package/vendor/theus-arsenal/skills/ui-a-vue/SKILL.md +141 -0
- package/vendor/theus-arsenal/skills/validacion-config-red/SKILL.md +211 -0
- package/vendor/theus-arsenal/skills/verificacion-django/SKILL.md +470 -0
- package/vendor/theus-arsenal/skills/verificacion-factual/SKILL.md +142 -0
- package/vendor/theus-arsenal/skills/verificacion-laravel/SKILL.md +184 -0
- package/vendor/theus-arsenal/skills/verificacion-quarkus/SKILL.md +485 -0
- package/vendor/theus-arsenal/skills/verificacion-springboot/SKILL.md +237 -0
- package/vendor/theus-arsenal/skills/videodb/SKILL.md +374 -0
- package/vendor/theus-arsenal/skills/videodb/reference/api-reference.md +550 -0
- package/vendor/theus-arsenal/skills/videodb/reference/capture-reference.md +407 -0
- package/vendor/theus-arsenal/skills/videodb/reference/capture.md +101 -0
- package/vendor/theus-arsenal/skills/videodb/reference/editor.md +443 -0
- package/vendor/theus-arsenal/skills/videodb/reference/generative.md +331 -0
- package/vendor/theus-arsenal/skills/videodb/reference/rtstream-reference.md +564 -0
- package/vendor/theus-arsenal/skills/videodb/reference/rtstream.md +65 -0
- package/vendor/theus-arsenal/skills/videodb/reference/search.md +230 -0
- package/vendor/theus-arsenal/skills/videodb/reference/streaming.md +406 -0
- package/vendor/theus-arsenal/skills/videodb/reference/use-cases.md +118 -0
- package/vendor/theus-arsenal/skills/videodb/scripts/ws_listener.py +279 -0
- package/vendor/theus-arsenal/skills/videos-manim/SKILL.md +91 -0
- package/vendor/theus-arsenal/skills/videos-manim/assets/network_graph_scene.py +52 -0
- package/vendor/theus-arsenal/skills/vigilancia-canary/SKILL.md +108 -0
- package/vendor/theus-arsenal/skills/voz-de-marca/SKILL.md +106 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: patrones-emr-clinico
|
|
3
|
+
description: Patrones de desarrollo de sistemas EMR/EHR para aplicaciones de salud. Seguridad clínica, flujos de consulta, generación de recetas, integración de soporte a la decisión clínica (CDSS) y UI accesible para captura de datos médicos.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Patrones de desarrollo EMR/EHR
|
|
7
|
+
|
|
8
|
+
Patrones para construir sistemas de Historia Clínica Electrónica (EMR/EHR). Prioriza la seguridad del paciente, la exactitud clínica y la eficiencia del personal sanitario.
|
|
9
|
+
|
|
10
|
+
> **Aviso:** este material es una guía de ingeniería. No sustituye la asesoría de profesionales clínicos, regulatorios ni legales; cualquier sistema clínico real debe validarse con especialistas cualificados y la normativa aplicable.
|
|
11
|
+
|
|
12
|
+
## Cuándo usarla
|
|
13
|
+
|
|
14
|
+
- Al construir flujos de consulta de pacientes (motivo, exploración, diagnóstico, receta).
|
|
15
|
+
- Al implementar notas clínicas (estructuradas + texto libre + dictado por voz).
|
|
16
|
+
- Al diseñar módulos de recetas/medicación con verificación de interacciones farmacológicas.
|
|
17
|
+
- Al integrar sistemas de soporte a la decisión clínica (CDSS).
|
|
18
|
+
- Al construir visualizaciones de resultados de laboratorio con resaltado de rangos de referencia.
|
|
19
|
+
- Al implementar trazas de auditoría para datos clínicos.
|
|
20
|
+
- Al diseñar interfaces accesibles para captura de datos clínicos.
|
|
21
|
+
|
|
22
|
+
## Cómo funciona
|
|
23
|
+
|
|
24
|
+
### La seguridad del paciente primero
|
|
25
|
+
|
|
26
|
+
Toda decisión de diseño debe evaluarse contra la pregunta: "¿Podría esto dañar a un paciente?"
|
|
27
|
+
|
|
28
|
+
- Las interacciones farmacológicas DEBEN alertar, nunca pasar en silencio.
|
|
29
|
+
- Los valores de laboratorio anormales DEBEN señalarse visualmente.
|
|
30
|
+
- Las constantes vitales críticas DEBEN disparar flujos de escalamiento.
|
|
31
|
+
- Ninguna modificación de datos clínicos sin traza de auditoría.
|
|
32
|
+
|
|
33
|
+
### Flujo de consulta en una sola página
|
|
34
|
+
|
|
35
|
+
Las consultas clínicas deben fluir verticalmente en una sola página — sin cambiar de pestaña:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
Cabecera del paciente (fija — siempre visible)
|
|
39
|
+
├── Datos demográficos, alergias, medicación activa
|
|
40
|
+
│
|
|
41
|
+
Flujo de la consulta (scroll vertical)
|
|
42
|
+
├── 1. Motivo de consulta (plantillas estructuradas + texto libre)
|
|
43
|
+
├── 2. Historia de la enfermedad actual
|
|
44
|
+
├── 3. Exploración física (por sistemas)
|
|
45
|
+
├── 4. Constantes vitales (dispara scoring clínico automático)
|
|
46
|
+
├── 5. Diagnóstico (búsqueda ICD-10/SNOMED)
|
|
47
|
+
├── 6. Medicación (base de fármacos + verificación de interacciones)
|
|
48
|
+
├── 7. Pruebas complementarias (órdenes de laboratorio/radiología)
|
|
49
|
+
├── 8. Plan y seguimiento
|
|
50
|
+
└── 9. Firmar / Bloquear / Imprimir
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Sistema de plantillas inteligentes
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
interface ClinicalTemplate {
|
|
57
|
+
id: string;
|
|
58
|
+
name: string; // p. ej., "Dolor torácico"
|
|
59
|
+
chips: string[]; // chips de síntomas clicables
|
|
60
|
+
requiredFields: string[]; // datos obligatorios
|
|
61
|
+
redFlags: string[]; // dispara una alerta no descartable
|
|
62
|
+
icdSuggestions: string[]; // códigos de diagnóstico pre-mapeados
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Los red flags de cualquier plantilla deben disparar una alerta visible y no descartable — NUNCA una notificación tipo toast.
|
|
67
|
+
|
|
68
|
+
### Patrón de seguridad en medicación
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
El usuario selecciona un fármaco
|
|
72
|
+
→ Verificar interacciones con la medicación actual
|
|
73
|
+
→ Verificar interacciones con la medicación de esta consulta
|
|
74
|
+
→ Verificar alergias del paciente
|
|
75
|
+
→ Validar dosis según peso/edad/función renal
|
|
76
|
+
→ Si la interacción es CRÍTICA: BLOQUEAR la prescripción por completo
|
|
77
|
+
→ El clínico debe documentar el motivo de la anulación para superar un bloqueo
|
|
78
|
+
→ Si la interacción es MAYOR: mostrar advertencia y exigir confirmación explícita
|
|
79
|
+
→ Registrar todas las alertas y motivos de anulación en la traza de auditoría
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Las interacciones críticas **bloquean la prescripción por defecto**. El clínico debe anular explícitamente con un motivo documentado que queda en la traza de auditoría. El sistema nunca permite en silencio una interacción crítica.
|
|
83
|
+
|
|
84
|
+
### Patrón de consulta bloqueada
|
|
85
|
+
|
|
86
|
+
Una vez firmada una consulta clínica:
|
|
87
|
+
|
|
88
|
+
- No se permiten ediciones — solo una adenda (un registro separado y vinculado).
|
|
89
|
+
- Tanto el original como la adenda aparecen en la línea de tiempo del paciente.
|
|
90
|
+
- La traza de auditoría captura quién firmó, cuándo, y cualquier adenda posterior.
|
|
91
|
+
|
|
92
|
+
### Patrones de UI para datos clínicos
|
|
93
|
+
|
|
94
|
+
**Constantes vitales:** valores actuales con resaltado de rango normal (verde/amarillo/rojo), flechas de tendencia respecto a la medición anterior, scoring clínico auto-calculado (NEWS2, qSOFA), guía de escalamiento en línea.
|
|
95
|
+
|
|
96
|
+
**Resultados de laboratorio:** resaltado de rango normal, comparación con el valor previo, valores críticos con alerta no descartable, marcas de tiempo de toma de muestra y análisis, órdenes pendientes con tiempo de respuesta esperado.
|
|
97
|
+
|
|
98
|
+
**PDF de receta:** generación en un clic con datos demográficos del paciente, alergias, diagnóstico, detalle del fármaco (genérico + marca, dosis, vía, frecuencia, duración) y bloque de firma del clínico.
|
|
99
|
+
|
|
100
|
+
### Accesibilidad en salud
|
|
101
|
+
|
|
102
|
+
Las interfaces sanitarias tienen requisitos más estrictos que una web típica:
|
|
103
|
+
|
|
104
|
+
- Contraste mínimo de 4.5:1 (WCAG AA) — el personal clínico trabaja con iluminación variable.
|
|
105
|
+
- Objetivos táctiles grandes (mínimo 44x44 px) — para interacción con guantes o con prisa.
|
|
106
|
+
- Navegación completa por teclado — para usuarios avanzados que capturan datos a gran velocidad.
|
|
107
|
+
- Nunca indicar solo por color — acompañar siempre con texto/icono (clínicos con daltonismo).
|
|
108
|
+
- Etiquetas de lector de pantalla en todos los campos de formulario.
|
|
109
|
+
- Nada de toasts que se auto-descartan para alertas clínicas — el clínico debe confirmar activamente.
|
|
110
|
+
|
|
111
|
+
### Antipatrones
|
|
112
|
+
|
|
113
|
+
- Almacenar datos clínicos en el localStorage del navegador.
|
|
114
|
+
- Fallos silenciosos en la verificación de interacciones farmacológicas.
|
|
115
|
+
- Toasts descartables para alertas clínicas críticas.
|
|
116
|
+
- Interfaces de consulta por pestañas que fragmentan el flujo clínico.
|
|
117
|
+
- Permitir ediciones a consultas firmadas/bloqueadas.
|
|
118
|
+
- Mostrar datos clínicos sin traza de auditoría.
|
|
119
|
+
- Usar el tipo `any` en estructuras de datos clínicos.
|
|
120
|
+
|
|
121
|
+
## Ejemplos
|
|
122
|
+
|
|
123
|
+
### Ejemplo 1: flujo de consulta de paciente
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
El médico abre la consulta del paciente #4521
|
|
127
|
+
→ La cabecera fija muestra: "Rajesh M, 58H, Alergias: Penicilina, Medicación activa: Metformina 500mg"
|
|
128
|
+
→ Motivo de consulta: selecciona la plantilla "Dolor torácico"
|
|
129
|
+
→ Clica los chips: "retroesternal", "irradiado a brazo izquierdo", "opresivo"
|
|
130
|
+
→ El red flag "dolor torácico opresivo retroesternal" dispara una alerta no descartable
|
|
131
|
+
→ Exploración: sistema cardiovascular — "R1 R2 normales, sin soplos"
|
|
132
|
+
→ Constantes: FC 110, TA 90/60, SpO2 94%
|
|
133
|
+
→ NEWS2 se auto-calcula: puntuación 8, riesgo ALTO, se muestra alerta de escalamiento
|
|
134
|
+
→ Diagnóstico: busca "SCA" → selecciona ICD-10 I21.9
|
|
135
|
+
→ Medicación: selecciona Aspirina 300mg
|
|
136
|
+
→ El CDSS verifica contra Metformina: sin interacción
|
|
137
|
+
→ Firma la consulta → bloqueada, a partir de aquí solo adendas
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Ejemplo 2: flujo de seguridad en medicación
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
El médico prescribe Warfarina al paciente #4521
|
|
144
|
+
→ El CDSS detecta: Warfarina + Aspirina = interacción CRÍTICA
|
|
145
|
+
→ UI: un modal rojo no descartable bloquea la prescripción
|
|
146
|
+
→ El médico pulsa "Anular con motivo"
|
|
147
|
+
→ Escribe: "El beneficio supera el riesgo — protocolo de INR monitorizado"
|
|
148
|
+
→ El motivo de anulación + la alerta quedan en la traza de auditoría
|
|
149
|
+
→ La prescripción continúa con la anulación documentada
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Ejemplo 3: consulta bloqueada + adenda
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
Consulta #E-2024-0891 firmada por la Dra. Shah a las 14:30
|
|
156
|
+
→ Todos los campos bloqueados — sin botones de edición visibles
|
|
157
|
+
→ El botón "Añadir adenda" sigue disponible
|
|
158
|
+
→ La Dra. Shah añade la adenda: "Resultados de laboratorio recibidos — Troponina elevada"
|
|
159
|
+
→ Se crea el registro E-2024-0891-A1 vinculado al original
|
|
160
|
+
→ La línea de tiempo muestra ambos: consulta original + adenda con sus marcas de tiempo
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Skills relacionadas
|
|
164
|
+
|
|
165
|
+
- `datos-sensibles-salud`
|
|
166
|
+
- `cumplimiento-hipaa`
|
|
167
|
+
- `harness-eval-clinico`
|
|
168
|
+
- `accesibilidad`
|
|
@@ -0,0 +1,513 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: patrones-fastapi
|
|
3
|
+
description: Buenas prácticas de FastAPI que cubren estructura de proyecto, esquemas Pydantic v2, inyección de dependencias, handlers async, autenticación, autorización, capas de servicio transaccionales y testing con httpx y pytest.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Patrones de FastAPI
|
|
7
|
+
|
|
8
|
+
Desarrollo moderno de FastAPI con calidad de producción: estructura de proyecto, esquemas Pydantic v2, inyección de dependencias, patrones async, autenticación, métodos de servicio transaccionales y testing.
|
|
9
|
+
|
|
10
|
+
## Estructura del proyecto
|
|
11
|
+
|
|
12
|
+
```text
|
|
13
|
+
my_app/
|
|
14
|
+
|-- app/
|
|
15
|
+
| |-- main.py # Fábrica de la app, lifespan, middleware
|
|
16
|
+
| |-- config.py # Configuración vía pydantic-settings
|
|
17
|
+
| |-- dependencies.py # Dependencias compartidas de FastAPI
|
|
18
|
+
| |-- database.py # Engine + sesión de SQLAlchemy
|
|
19
|
+
| |-- routers/
|
|
20
|
+
| | `-- users.py
|
|
21
|
+
| |-- models/ # Modelos ORM de SQLAlchemy
|
|
22
|
+
| | `-- user.py
|
|
23
|
+
| |-- schemas/ # Esquemas Pydantic de request/response
|
|
24
|
+
| | `-- user.py
|
|
25
|
+
| `-- services/ # Capa de lógica de negocio
|
|
26
|
+
| `-- user_service.py
|
|
27
|
+
|-- tests/
|
|
28
|
+
| |-- conftest.py
|
|
29
|
+
| `-- test_users.py
|
|
30
|
+
|-- pyproject.toml
|
|
31
|
+
`-- .env
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Fábrica de la app y lifespan
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
# app/main.py
|
|
40
|
+
from contextlib import asynccontextmanager
|
|
41
|
+
from fastapi import FastAPI
|
|
42
|
+
from fastapi.middleware.cors import CORSMiddleware
|
|
43
|
+
|
|
44
|
+
from app.config import settings
|
|
45
|
+
from app.database import engine, Base
|
|
46
|
+
from app.routers import users
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@asynccontextmanager
|
|
50
|
+
async def lifespan(app: FastAPI):
|
|
51
|
+
# Crear las tablas automáticamente al arrancar, por comodidad en entornos de dev/demo.
|
|
52
|
+
# Para aplicaciones de producción estrictas, gestiona los esquemas con migraciones de Alembic.
|
|
53
|
+
async with engine.begin() as conn:
|
|
54
|
+
await conn.run_sync(Base.metadata.create_all)
|
|
55
|
+
yield
|
|
56
|
+
# Apagado: cerrar los recursos del pool.
|
|
57
|
+
await engine.dispose()
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def create_app() -> FastAPI:
|
|
61
|
+
app = FastAPI(
|
|
62
|
+
title=settings.app_name,
|
|
63
|
+
version=settings.app_version,
|
|
64
|
+
lifespan=lifespan,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
app.add_middleware(
|
|
68
|
+
CORSMiddleware,
|
|
69
|
+
allow_origins=settings.allowed_origins,
|
|
70
|
+
allow_credentials=settings.allow_credentials,
|
|
71
|
+
allow_methods=settings.allowed_methods,
|
|
72
|
+
allow_headers=settings.allowed_headers,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
app.include_router(users.router, prefix="/users", tags=["users"])
|
|
76
|
+
|
|
77
|
+
return app
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
app = create_app()
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Configuración con pydantic-settings
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
# app/config.py
|
|
89
|
+
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class Settings(BaseSettings):
|
|
93
|
+
model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8")
|
|
94
|
+
|
|
95
|
+
app_name: str = "My App"
|
|
96
|
+
app_version: str = "0.1.0"
|
|
97
|
+
debug: bool = False
|
|
98
|
+
|
|
99
|
+
database_url: str
|
|
100
|
+
secret_key: str
|
|
101
|
+
algorithm: str = "HS256"
|
|
102
|
+
access_token_expire_minutes: int = 30
|
|
103
|
+
|
|
104
|
+
# pydantic-settings v2 evalúa de forma segura los literales de lista mutables
|
|
105
|
+
allowed_origins: list[str] = ["http://localhost:3000"]
|
|
106
|
+
allowed_methods: list[str] = ["GET", "POST", "PATCH", "DELETE", "OPTIONS"]
|
|
107
|
+
allowed_headers: list[str] = ["Authorization", "Content-Type"]
|
|
108
|
+
allow_credentials: bool = True
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
settings = Settings()
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Esquemas Pydantic (v2)
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
# app/schemas/user.py
|
|
120
|
+
from datetime import datetime
|
|
121
|
+
from pydantic import BaseModel, EmailStr, Field, model_validator
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class UserBase(BaseModel):
|
|
125
|
+
email: EmailStr
|
|
126
|
+
username: str = Field(min_length=3, max_length=50)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class UserCreate(UserBase):
|
|
130
|
+
password: str = Field(min_length=8)
|
|
131
|
+
password_confirm: str
|
|
132
|
+
|
|
133
|
+
@model_validator(mode="after")
|
|
134
|
+
def passwords_match(self) -> "UserCreate":
|
|
135
|
+
if self.password != self.password_confirm:
|
|
136
|
+
raise ValueError("Las contraseñas no coinciden")
|
|
137
|
+
return self
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class UserUpdate(BaseModel):
|
|
141
|
+
username: str | None = Field(default=None, min_length=3, max_length=50)
|
|
142
|
+
email: EmailStr | None = None
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class UserResponse(UserBase):
|
|
146
|
+
id: int
|
|
147
|
+
is_active: bool
|
|
148
|
+
created_at: datetime
|
|
149
|
+
|
|
150
|
+
model_config = {"from_attributes": True}
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class UserListResponse(BaseModel):
|
|
154
|
+
total: int
|
|
155
|
+
items: list[UserResponse]
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Inyección de dependencias
|
|
161
|
+
|
|
162
|
+
```python
|
|
163
|
+
# app/dependencies.py
|
|
164
|
+
from typing import Annotated, AsyncGenerator
|
|
165
|
+
from fastapi import Depends, HTTPException, status
|
|
166
|
+
from fastapi.security import OAuth2PasswordBearer
|
|
167
|
+
from jose import JWTError, jwt
|
|
168
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
169
|
+
|
|
170
|
+
from app.config import settings
|
|
171
|
+
from app.database import AsyncSessionLocal
|
|
172
|
+
from app.models.user import User
|
|
173
|
+
|
|
174
|
+
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/users/token")
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
async def get_db() -> AsyncGenerator[AsyncSession, None]:
|
|
178
|
+
async with AsyncSessionLocal() as session:
|
|
179
|
+
try:
|
|
180
|
+
yield session
|
|
181
|
+
except Exception:
|
|
182
|
+
await session.rollback()
|
|
183
|
+
raise
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
async def get_current_user(
|
|
187
|
+
token: Annotated[str, Depends(oauth2_scheme)],
|
|
188
|
+
db: Annotated[AsyncSession, Depends(get_db)],
|
|
189
|
+
) -> User:
|
|
190
|
+
credentials_exception = HTTPException(
|
|
191
|
+
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
192
|
+
detail="No se pudieron validar las credenciales",
|
|
193
|
+
headers={"WWW-Authenticate": "Bearer"},
|
|
194
|
+
)
|
|
195
|
+
try:
|
|
196
|
+
payload = jwt.decode(token, settings.secret_key, algorithms=[settings.algorithm])
|
|
197
|
+
subject = payload.get("sub")
|
|
198
|
+
if subject is None:
|
|
199
|
+
raise credentials_exception
|
|
200
|
+
user_id = int(subject)
|
|
201
|
+
except (JWTError, TypeError, ValueError):
|
|
202
|
+
raise credentials_exception
|
|
203
|
+
|
|
204
|
+
user = await db.get(User, user_id)
|
|
205
|
+
if user is None:
|
|
206
|
+
raise credentials_exception
|
|
207
|
+
return user
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
async def get_current_active_user(
|
|
211
|
+
current_user: Annotated[User, Depends(get_current_user)],
|
|
212
|
+
) -> User:
|
|
213
|
+
if not current_user.is_active:
|
|
214
|
+
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Usuario inactivo")
|
|
215
|
+
return current_user
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
DbDep = Annotated[AsyncSession, Depends(get_db)]
|
|
219
|
+
CurrentUserDep = Annotated[User, Depends(get_current_user)]
|
|
220
|
+
ActiveUserDep = Annotated[User, Depends(get_current_active_user)]
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## Diseño de routers y endpoints
|
|
226
|
+
|
|
227
|
+
```python
|
|
228
|
+
# app/routers/users.py
|
|
229
|
+
from typing import Annotated
|
|
230
|
+
from fastapi import APIRouter, HTTPException, Query, status
|
|
231
|
+
from fastapi.security import OAuth2PasswordRequestForm
|
|
232
|
+
|
|
233
|
+
from app.dependencies import ActiveUserDep, DbDep
|
|
234
|
+
from app.schemas.user import UserCreate, UserResponse, UserUpdate, UserListResponse
|
|
235
|
+
from app.services.user_service import DuplicateUserError, UserService
|
|
236
|
+
|
|
237
|
+
router = APIRouter()
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
@router.post("/", response_model=UserResponse, status_code=status.HTTP_201_CREATED)
|
|
241
|
+
async def create_user(payload: UserCreate, db: DbDep) -> UserResponse:
|
|
242
|
+
service = UserService(db)
|
|
243
|
+
try:
|
|
244
|
+
return await service.create(payload)
|
|
245
|
+
except DuplicateUserError:
|
|
246
|
+
raise HTTPException(status_code=400, detail="El email ya está registrado")
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
@router.get("/me", response_model=UserResponse)
|
|
250
|
+
async def get_me(current_user: ActiveUserDep) -> UserResponse:
|
|
251
|
+
return current_user
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
@router.get("/", response_model=UserListResponse)
|
|
255
|
+
async def list_users(
|
|
256
|
+
db: DbDep,
|
|
257
|
+
current_user: ActiveUserDep,
|
|
258
|
+
skip: Annotated[int, Query(ge=0)] = 0,
|
|
259
|
+
limit: Annotated[int, Query(ge=1, le=100)] = 20,
|
|
260
|
+
) -> UserListResponse:
|
|
261
|
+
service = UserService(db)
|
|
262
|
+
users, total = await service.list(skip=skip, limit=limit)
|
|
263
|
+
return UserListResponse(total=total, items=users)
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
@router.patch("/{user_id}", response_model=UserResponse)
|
|
267
|
+
async def update_user(
|
|
268
|
+
user_id: int,
|
|
269
|
+
payload: UserUpdate,
|
|
270
|
+
db: DbDep,
|
|
271
|
+
current_user: ActiveUserDep,
|
|
272
|
+
) -> UserResponse:
|
|
273
|
+
if current_user.id != user_id:
|
|
274
|
+
raise HTTPException(status_code=403, detail="No autorizado")
|
|
275
|
+
service = UserService(db)
|
|
276
|
+
try:
|
|
277
|
+
user = await service.update(user_id, payload)
|
|
278
|
+
except DuplicateUserError:
|
|
279
|
+
raise HTTPException(status_code=400, detail="El email ya está registrado")
|
|
280
|
+
if user is None:
|
|
281
|
+
raise HTTPException(status_code=404, detail="Usuario no encontrado")
|
|
282
|
+
return user
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
@router.post("/token")
|
|
286
|
+
async def login(
|
|
287
|
+
form_data: Annotated[OAuth2PasswordRequestForm, Depends()],
|
|
288
|
+
db: DbDep,
|
|
289
|
+
) -> dict[str, str]:
|
|
290
|
+
service = UserService(db)
|
|
291
|
+
token = await service.authenticate(form_data.username, form_data.password)
|
|
292
|
+
if token is None:
|
|
293
|
+
raise HTTPException(
|
|
294
|
+
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
295
|
+
detail="Usuario o contraseña incorrectos",
|
|
296
|
+
headers={"WWW-Authenticate": "Bearer"},
|
|
297
|
+
)
|
|
298
|
+
return {"access_token": token, "token_type": "bearer"}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## Capa de servicio
|
|
304
|
+
|
|
305
|
+
```python
|
|
306
|
+
# app/services/user_service.py
|
|
307
|
+
from datetime import datetime, timedelta, timezone
|
|
308
|
+
|
|
309
|
+
from jose import jwt
|
|
310
|
+
from passlib.context import CryptContext
|
|
311
|
+
from sqlalchemy import func, select
|
|
312
|
+
from sqlalchemy.exc import IntegrityError
|
|
313
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
314
|
+
|
|
315
|
+
from app.config import settings
|
|
316
|
+
from app.models.user import User
|
|
317
|
+
from app.schemas.user import UserCreate, UserUpdate
|
|
318
|
+
|
|
319
|
+
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
class DuplicateUserError(Exception):
|
|
323
|
+
"""Se lanza cuando un campo único del usuario colisiona con una fila existente."""
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
class UserService:
|
|
327
|
+
def __init__(self, db: AsyncSession) -> None:
|
|
328
|
+
self.db = db
|
|
329
|
+
|
|
330
|
+
async def get_by_email(self, email: str) -> User | None:
|
|
331
|
+
result = await self.db.execute(select(User).where(User.email == email))
|
|
332
|
+
return result.scalar_one_or_none()
|
|
333
|
+
|
|
334
|
+
async def create(self, payload: UserCreate) -> User:
|
|
335
|
+
user = User(
|
|
336
|
+
email=payload.email,
|
|
337
|
+
username=payload.username,
|
|
338
|
+
hashed_password=pwd_context.hash(payload.password),
|
|
339
|
+
)
|
|
340
|
+
self.db.add(user)
|
|
341
|
+
try:
|
|
342
|
+
# Confiar en las restricciones atómicas de la BD en lugar de
|
|
343
|
+
# prechequeos a nivel de aplicación propensos a condiciones de carrera
|
|
344
|
+
await self.db.commit()
|
|
345
|
+
except IntegrityError as exc:
|
|
346
|
+
await self.db.rollback()
|
|
347
|
+
raise DuplicateUserError from exc
|
|
348
|
+
await self.db.refresh(user)
|
|
349
|
+
return user
|
|
350
|
+
|
|
351
|
+
async def list(self, skip: int = 0, limit: int = 20) -> tuple[list[User], int]:
|
|
352
|
+
total_result = await self.db.execute(select(func.count(User.id)))
|
|
353
|
+
total = total_result.scalar_one()
|
|
354
|
+
# Forzar un orden determinista explícito para garantizar una paginación fiable
|
|
355
|
+
result = await self.db.execute(
|
|
356
|
+
select(User).order_by(User.id).offset(skip).limit(limit)
|
|
357
|
+
)
|
|
358
|
+
return list(result.scalars()), total
|
|
359
|
+
|
|
360
|
+
async def update(self, user_id: int, payload: UserUpdate) -> User | None:
|
|
361
|
+
user = await self.db.get(User, user_id)
|
|
362
|
+
if user is None:
|
|
363
|
+
return None
|
|
364
|
+
for field, value in payload.model_dump(exclude_unset=True).items():
|
|
365
|
+
setattr(user, field, value)
|
|
366
|
+
try:
|
|
367
|
+
await self.db.commit()
|
|
368
|
+
except IntegrityError as exc:
|
|
369
|
+
await self.db.rollback()
|
|
370
|
+
raise DuplicateUserError from exc
|
|
371
|
+
await self.db.refresh(user)
|
|
372
|
+
return user
|
|
373
|
+
|
|
374
|
+
async def authenticate(self, email: str, password: str) -> str | None:
|
|
375
|
+
user = await self.get_by_email(email)
|
|
376
|
+
if user is None or not pwd_context.verify(password, user.hashed_password):
|
|
377
|
+
return None
|
|
378
|
+
expire = datetime.now(timezone.utc) + timedelta(
|
|
379
|
+
minutes=settings.access_token_expire_minutes
|
|
380
|
+
)
|
|
381
|
+
return jwt.encode(
|
|
382
|
+
{"sub": str(user.id), "exp": expire},
|
|
383
|
+
settings.secret_key,
|
|
384
|
+
algorithm=settings.algorithm,
|
|
385
|
+
)
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
> **Nota sobre diseño de base de datos:** El manejo de unicidad a nivel de aplicación requiere un índice único subyacente en la base de datos (p. ej., `unique=True` en los atributos mapeados de SQLAlchemy). Sin restricciones subyacentes, capturar errores en la capa de aplicación no puede prevenir con seguridad las condiciones de carrera concurrentes.
|
|
389
|
+
|
|
390
|
+
---
|
|
391
|
+
|
|
392
|
+
## Testing con httpx y pytest
|
|
393
|
+
|
|
394
|
+
```python
|
|
395
|
+
# tests/conftest.py
|
|
396
|
+
import pytest_asyncio
|
|
397
|
+
from httpx import ASGITransport, AsyncClient
|
|
398
|
+
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine
|
|
399
|
+
|
|
400
|
+
from app.database import Base
|
|
401
|
+
from app.dependencies import get_db
|
|
402
|
+
from app.main import create_app
|
|
403
|
+
|
|
404
|
+
TEST_DATABASE_URL = "sqlite+aiosqlite:///:memory:"
|
|
405
|
+
|
|
406
|
+
engine = create_async_engine(TEST_DATABASE_URL)
|
|
407
|
+
TestingSessionLocal = async_sessionmaker(engine, expire_on_commit=False)
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
@pytest_asyncio.fixture(autouse=True)
|
|
411
|
+
async def setup_db():
|
|
412
|
+
async with engine.begin() as conn:
|
|
413
|
+
await conn.run_sync(Base.metadata.create_all)
|
|
414
|
+
yield
|
|
415
|
+
async with engine.begin() as conn:
|
|
416
|
+
await conn.run_sync(Base.metadata.drop_all)
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
@pytest_asyncio.fixture
|
|
420
|
+
async def db_session():
|
|
421
|
+
async with TestingSessionLocal() as session:
|
|
422
|
+
yield session
|
|
423
|
+
await session.rollback()
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
@pytest_asyncio.fixture
|
|
427
|
+
async def client(db_session: AsyncSession):
|
|
428
|
+
app = create_app()
|
|
429
|
+
|
|
430
|
+
async def override_get_db():
|
|
431
|
+
yield db_session
|
|
432
|
+
|
|
433
|
+
app.dependency_overrides[get_db] = override_get_db
|
|
434
|
+
|
|
435
|
+
async with AsyncClient(
|
|
436
|
+
transport=ASGITransport(app=app), base_url="http://test"
|
|
437
|
+
) as ac:
|
|
438
|
+
yield ac
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
@pytest_asyncio.fixture
|
|
442
|
+
async def registered_user(client: AsyncClient) -> dict:
|
|
443
|
+
resp = await client.post("/users/", json={
|
|
444
|
+
"email": "test@example.com",
|
|
445
|
+
"username": "testuser",
|
|
446
|
+
"password": "securepass1",
|
|
447
|
+
"password_confirm": "securepass1",
|
|
448
|
+
})
|
|
449
|
+
assert resp.status_code == 201
|
|
450
|
+
return resp.json()
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
@pytest_asyncio.fixture
|
|
454
|
+
async def auth_token(client: AsyncClient, registered_user: dict) -> str:
|
|
455
|
+
resp = await client.post("/users/token", data={
|
|
456
|
+
"username": "test@example.com",
|
|
457
|
+
"password": "securepass1",
|
|
458
|
+
})
|
|
459
|
+
assert resp.status_code == 200
|
|
460
|
+
return resp.json()["access_token"]
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
@pytest_asyncio.fixture
|
|
464
|
+
async def auth_client(client: AsyncClient, auth_token: str) -> AsyncClient:
|
|
465
|
+
client.headers.update({"Authorization": f"Bearer {auth_token}"})
|
|
466
|
+
return client
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
---
|
|
470
|
+
|
|
471
|
+
## Antipatrones
|
|
472
|
+
|
|
473
|
+
```python
|
|
474
|
+
# Mal: lógica de negocio dentro de los handlers de ruta.
|
|
475
|
+
@router.post("/users/")
|
|
476
|
+
async def create_user(payload: UserCreate, db: DbDep):
|
|
477
|
+
hashed = bcrypt.hash(payload.password)
|
|
478
|
+
user = User(email=payload.email, hashed_password=hashed)
|
|
479
|
+
db.add(user)
|
|
480
|
+
await db.commit()
|
|
481
|
+
return user
|
|
482
|
+
|
|
483
|
+
# Bien: ruta delgada, manejo transaccional en el servicio.
|
|
484
|
+
@router.post("/users/", response_model=UserResponse, status_code=201)
|
|
485
|
+
async def create_user(payload: UserCreate, db: DbDep):
|
|
486
|
+
try:
|
|
487
|
+
return await UserService(db).create(payload)
|
|
488
|
+
except DuplicateUserError:
|
|
489
|
+
raise HTTPException(status_code=400, detail="El email ya está registrado")
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
# Mal: llamadas síncronas a la BD en rutas async bloquean el event loop.
|
|
493
|
+
@router.get("/items/")
|
|
494
|
+
async def list_items(db: Session = Depends(get_db)):
|
|
495
|
+
return db.query(Item).all()
|
|
496
|
+
|
|
497
|
+
# Bien: usar ejecuciones async de SQLAlchemy.
|
|
498
|
+
@router.get("/items/")
|
|
499
|
+
async def list_items(db: AsyncSession = Depends(get_db)):
|
|
500
|
+
result = await db.execute(select(Item))
|
|
501
|
+
return result.scalars().all()
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
---
|
|
505
|
+
|
|
506
|
+
## Buenas prácticas
|
|
507
|
+
|
|
508
|
+
- Declara siempre un `response_model` tipado para prevenir fugas accidentales de PII/datos y producir esquemas OpenAPI limpios.
|
|
509
|
+
- Consolida las inyecciones de dependencias estándar mediante alias de tipo: `DbDep = Annotated[AsyncSession, Depends(get_db)]`.
|
|
510
|
+
- Envuelve los límites de mutación de la base de datos en transacciones dentro de tu capa de servicio, capturando directamente los errores estructurales de la BD.
|
|
511
|
+
- Parsea los parámetros del JWT de forma defensiva, anticipando posibles desajustes de casteo string/entero en variaciones modernas de payload.
|
|
512
|
+
- Fuerza un ordenamiento determinista (p. ej., `.order_by(Model.id)`) en todos los endpoints paginados con offset/limit para evitar saltos de datos.
|
|
513
|
+
- Aísla las comprobaciones de autorización de las dependencias centrales de autenticación para dar señales REST precisas (`401` vs `403`).
|