trading-platform/orchestration/analisis/integracion/CHECKPOINTS.yml
Adrian Flores Cortes 090fe5d278 feat: Add Trading Agents types for frontend
Create comprehensive TypeScript type definitions for Trading Agents (Atlas, Orion, Nova) in the frontend.

- Align with backend trading-agents.client.ts interfaces
- Export AgentType, AgentStatus, BotStatus types
- Define TradingBot, AgentMetrics, AgentPosition, AgentTrade interfaces
- Include utility functions for status mapping and display names
- Full JSDoc documentation for all types
- Export from main types/index.ts

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 15:40:04 -06:00

909 lines
25 KiB
YAML

# CHECKPOINTS.yml - Trading Platform
# Criterios de validación y gates de calidad para el proyecto
# Fecha: 2026-01-27
# Sistema: SIMCO v4.0.0
metadata:
proyecto: trading-platform
fecha_creacion: 2026-01-27
version: 1.0.0
owner: Claude Opus 4.5
estado_actual: "Desarrollo Activo - Post MVP"
completitud_global: 60%
coherencia_global_actual: 81.25%
coherencia_global_target: 95%
# ==============================================================================
# VALIDATION GATES - Checkpoints GO/NO-GO
# ==============================================================================
validation_gates:
# ---------------------------------------------------------------------------
# CHECKPOINT 01: Resolución de Gaps Bloqueantes (P0)
# ---------------------------------------------------------------------------
- gate: CP-01
nombre: "Post Gaps P0 - Bloqueantes Resueltos"
descripcion: "Todos los gaps bloqueantes (P0) deben estar resueltos"
fase: "Post-MVP - Bloqueantes"
status: NO_GO
fecha_target: "2026-02-03"
duracion_estimada: "1.5 semanas (54h)"
criterios:
- criterio: "0 gaps bloqueantes abiertos"
metrica: gaps_p0_count
umbral: 0
actual: 3
estado: FAIL
detalles:
- "GAP-P0-001: Password Recovery sin UI (8h)"
- "GAP-P0-002: User Profile sin servicio (6h)"
- "GAP-P0-003: Trading Agents sin UI (40h)"
- criterio: "Password Recovery funcional"
tipo: functional_test
metrica: password_recovery_implemented
umbral: true
actual: false
estado: FAIL
tests_requeridos:
- "E2E: Flujo completo forgot password -> email -> reset"
- "Unit: PasswordRecoveryService funcionando"
- "Integration: Email service conectado"
- criterio: "User Profile servicio implementado"
tipo: functional_test
metrica: user_profile_service_exists
umbral: true
actual: false
estado: FAIL
tests_requeridos:
- "GET /users/profile funcional"
- "PUT /users/profile actualiza datos"
- "Avatar upload funcionando"
- criterio: "Trading Agents UI al menos parcial (50%)"
tipo: functional_test
metrica: trading_agents_ui_coverage
umbral: 50
actual: 0
estado: FAIL
tests_requeridos:
- "Lista de agentes (Atlas, Orion, Nova) visible"
- "Configuración básica de agente funcional"
- "Status de agente en tiempo real"
riesgos:
- "Sin CP-01: NO se puede lanzar a producción"
- "Password recovery es requerimiento legal/seguridad"
- "User profile es feature core de plataforma"
# ---------------------------------------------------------------------------
# CHECKPOINT 02: Coherencia DDL-Backend >= 95%
# ---------------------------------------------------------------------------
- gate: CP-02
nombre: "Coherencia DDL-Backend >= 95%"
descripcion: "Cobertura de servicios backend para tablas DDL"
fase: "Consolidación Backend"
status: NO_GO
fecha_target: "2026-02-10"
duracion_estimada: "1 semana (40h)"
criterios:
- criterio: "Cobertura servicios >= 95%"
metrica: ddl_backend_coverage
umbral: 95
actual: 85
estado: FAIL
formula: "(tablas_con_servicio / total_tablas) * 100"
detalles:
- "89 tablas DDL totales"
- "76 tablas con servicio (85%)"
- "13 tablas faltantes (15%)"
- criterio: "Servicios backend críticos implementados"
tipo: functional_test
metrica: critical_services_coverage
umbral: 100
actual: 85
estado: FAIL
servicios_faltantes:
- "marketData.service.ts (GAP-P1-001) - 16h"
- "notifications.service.ts completo (GAP-P1-002) - 20h"
- "audit.service.ts (GAP-P2-001) - 32h"
- "currencyExchange.service.ts (GAP-P2-002) - 16h"
- "riskAssessment.service.ts (GAP-P2-003) - 12h"
- criterio: "Endpoints documentados en Swagger"
tipo: documentation
metrica: swagger_coverage
umbral: 100
actual: 70
estado: FAIL
riesgos:
- "Sin servicios backend: frontend no puede conectarse"
- "Market data crítico para charts"
- "Notifications core para UX"
# ---------------------------------------------------------------------------
# CHECKPOINT 03: Coherencia Backend-Frontend >= 90%
# ---------------------------------------------------------------------------
- gate: CP-03
nombre: "Coherencia Backend-Frontend >= 90%"
descripcion: "Frontend consume endpoints backend correctamente"
fase: "Consolidación Frontend"
status: NO_GO
fecha_target: "2026-02-17"
duracion_estimada: "1 semana (40h)"
criterios:
- criterio: "Cobertura consumo endpoints >= 90%"
metrica: backend_frontend_coverage
umbral: 90
actual: 77.5
estado: FAIL
formula: "(endpoints_consumidos / total_endpoints) * 100"
detalles:
- "187 endpoints totales"
- "145 endpoints consumidos (77.5%)"
- "42 endpoints sin consumir (22.5%)"
- criterio: "ML Chart Overlays implementados"
tipo: functional_test
metrica: ml_chart_overlays_implemented
umbral: true
actual: false
estado: FAIL
esfuerzo: "24h (GAP-P1-003)"
- criterio: "Frontend services usando apiClient"
tipo: architectural
metrica: services_using_apiclient
umbral: 100
actual: 64
estado: FAIL
servicios_sin_apiclient:
- "portfolio.service.ts"
- "adminService.ts"
- "mlService.ts"
- "llmAgentService.ts"
- "backtestService.ts"
riesgo: "Sin auto-refresh tokens, sin retry logic, sin manejo errores consistente"
- criterio: "2FA flujo completo"
tipo: functional_test
metrica: two_factor_auth_complete
umbral: true
actual: false
estado: FAIL
esfuerzo: "16h (GAP-P1-004)"
riesgos:
- "UX inconsistente sin apiClient"
- "Security risk sin 2FA completo"
- "ML features no visibles sin overlays"
# ---------------------------------------------------------------------------
# CHECKPOINT 04: Consolidación Arquitectural
# ---------------------------------------------------------------------------
- gate: CP-04
nombre: "Consolidación Arquitectural"
descripcion: "Acceso consistente a servicios backend y Python"
fase: "Refactoring Arquitectural"
status: NO_GO
fecha_target: "2026-02-24"
duracion_estimada: "1 semana (40h)"
criterios:
- criterio: "Acceso Python centralizado vía Express"
tipo: architectural
metrica: python_access_via_express
umbral: 100
actual: 0
estado: FAIL
problema: "Frontend accede directamente a servicios Python sin gateway"
servicios_afectados:
- "mlService.ts -> ML Engine (3083)"
- "llmAgentService.ts -> LLM Agent (3085)"
- "backtestService.ts -> ML Engine (3083)"
riesgos:
- "Sin autenticación centralizada"
- "CORS issues potenciales"
- "Sin rate limiting consistente"
solucion: "Migrar todo acceso via Express backend como gateway"
- criterio: "100% servicios usando apiClient"
tipo: architectural
metrica: services_using_apiclient_percentage
umbral: 100
actual: 64
estado: FAIL
trabajo_requerido: "Migrar 5 servicios a apiClient"
- criterio: "Consistencia manejo tokens"
tipo: security
metrica: token_handling_consistent
umbral: true
actual: false
estado: FAIL
problema: "Inconsistencia auth_token vs token (B-004)"
status_blocker: "RESUELTO (P1)"
riesgos:
- "Security vulnerabilities sin gateway centralizado"
- "Mantenibilidad baja con acceso directo"
# ---------------------------------------------------------------------------
# CHECKPOINT 05: Testing y Calidad
# ---------------------------------------------------------------------------
- gate: CP-05
nombre: "Testing y Calidad"
descripcion: "Coverage y tests de integración completos"
fase: "Quality Assurance"
status: NO_GO
fecha_target: "2026-03-03"
duracion_estimada: "1 semana (40h)"
criterios:
- criterio: "Code coverage >= 80%"
tipo: quality
metrica: code_coverage
umbral: 80
actual: 15
estado: FAIL
nota: "Actualmente solo 153 E2E tests (video upload)"
- criterio: "0 errores lint"
tipo: quality
metrica: lint_errors
umbral: 0
actual: "unknown"
estado: UNKNOWN
- criterio: "0 errores TypeScript"
tipo: quality
metrica: type_errors
umbral: 0
actual: "unknown"
estado: UNKNOWN
- criterio: "Tests E2E críticos implementados"
tipo: functional_test
metrica: e2e_critical_tests_count
umbral: 20
actual: 5
estado: FAIL
tests_requeridos:
- "Login flow completo (email + password + 2FA)"
- "Password recovery E2E"
- "Trading order placement"
- "Payment flow Stripe"
- "ML signal generation"
- "LLM chat interaction"
- "Portfolio creation"
- "Investment account wizard"
- "Course enrollment + video playback"
- "Notification delivery (push + email)"
riesgos:
- "Bajo coverage = bugs en producción"
- "Sin E2E tests = regresiones no detectadas"
# ==============================================================================
# MÉTRICAS A MONITOREAR
# ==============================================================================
metricas_monitorear:
coherencia_global:
descripcion: "Promedio coherencia DDL-Backend-Frontend"
actual: 81.25
target: 95
gap: -13.75
formula: "(ddl_backend_coverage + backend_frontend_coverage) / 2"
frecuencia_medicion: "Semanal"
gaps_por_prioridad:
p0_bloqueantes:
actual: 3
target: 0
esfuerzo_total: "54h"
items:
- "GAP-P0-001: Password Recovery (8h)"
- "GAP-P0-002: User Profile (6h)"
- "GAP-P0-003: Trading Agents UI (40h)"
p1_criticos:
actual: 4
target: 0
esfuerzo_total: "76h"
items:
- "GAP-P1-001: Market Data OHLCV (16h)"
- "GAP-P1-002: Notifications API (20h)"
- "GAP-P1-003: ML Chart Overlays (24h)"
- "GAP-P1-004: 2FA completo (16h)"
p2_importantes:
actual: 5
target: 0
esfuerzo_total: "78h"
items:
- "GAP-P2-001: Audit system (32h)"
- "GAP-P2-002: Currency Exchange (16h)"
- "GAP-P2-003: Risk Assessment (12h)"
- "GAP-P2-004: Course Reviews (6h)"
- "GAP-P2-005: OAuth flows (12h)"
coherencia_por_capa:
ddl_backend:
actual: 85
target: 95
gap: -10
tablas_totales: 89
tablas_con_servicio: 76
tablas_faltantes: 13
backend_frontend:
actual: 77.5
target: 90
gap: -12.5
endpoints_totales: 187
endpoints_consumidos: 145
endpoints_faltantes: 42
coherencia_por_epica:
oqi_001_auth:
ddl: 100
backend: 95
frontend: 85
global: 93
estado: EXCELENTE
oqi_002_education:
ddl: 100
backend: 90
frontend: 96
global: 95
estado: EXCELENTE
oqi_003_trading:
ddl: 100
backend: 100
frontend: 95
global: 98
estado: EXCELENTE
oqi_004_investment:
ddl: 100
backend: 90
frontend: 100
global: 97
estado: EXCELENTE
oqi_005_payments:
ddl: 100
backend: 85
frontend: 92
global: 92
estado: EXCELENTE
oqi_006_ml_signals:
ddl: 100
backend: 100
frontend: 47
global: 82
estado: BUENO
nota: "Frontend gap en ML overlays"
oqi_007_llm_agent:
ddl: 100
backend: 100
frontend: 67
global: 89
estado: BUENO
nota: "Frontend gap en panels"
oqi_008_portfolio:
ddl: 100
backend: 100
frontend: 92
global: 97
estado: EXCELENTE
oqi_009_mt4:
ddl: 0
backend: 0
frontend: 0
global: 0
estado: NO_INICIADO
nota: "Feature completa sin implementar"
servicios_apiclient:
actual: 64
target: 100
gap: -36
servicios_totales: 14
servicios_con_apiclient: 9
servicios_sin_apiclient: 5
acceso_python_directo:
actual: 3
target: 0
servicios_con_acceso_directo:
- mlService.ts
- llmAgentService.ts
- backtestService.ts
# ==============================================================================
# TESTS DE ACEPTACIÓN
# ==============================================================================
tests_aceptacion:
# E2E Tests Críticos
e2e_tests:
- test: "Login flow E2E"
id: E2E-001
tipo: e2e
automatizado: false
target: true
prioridad: P0
escenario: "Usuario ingresa email + password -> recibe token -> accede a dashboard"
criterio_exito: "Login exitoso en < 2s"
dependencias: ["GAP-P0-002 resuelto"]
- test: "Password recovery E2E"
id: E2E-002
tipo: e2e
automatizado: false
target: true
prioridad: P0
escenario: "Usuario forgot password -> email -> reset -> login exitoso"
criterio_exito: "Email recibido en < 30s, reset exitoso"
dependencias: ["GAP-P0-001 resuelto"]
- test: "2FA flow E2E"
id: E2E-003
tipo: e2e
automatizado: false
target: true
prioridad: P1
escenario: "Usuario enable 2FA -> QR code -> verify TOTP -> login con 2FA"
criterio_exito: "2FA funcionando correctamente"
dependencias: ["GAP-P1-004 resuelto"]
- test: "Trading order placement E2E"
id: E2E-004
tipo: e2e
automatizado: false
target: true
prioridad: P0
escenario: "Usuario selecciona symbol -> ingresa order -> confirma -> ejecuta"
criterio_exito: "Order aparece en historial, balance actualizado"
dependencias: ["GAP-P0-003 parcialmente resuelto"]
- test: "ML signal visualization E2E"
id: E2E-005
tipo: e2e
automatizado: false
target: true
prioridad: P1
escenario: "Usuario abre chart -> ML overlay visible -> señales actualizadas"
criterio_exito: "Overlays renderizados, latencia < 1s"
dependencias: ["GAP-P1-003 resuelto"]
- test: "Payment flow Stripe E2E"
id: E2E-006
tipo: e2e
automatizado: false
target: true
prioridad: P1
escenario: "Usuario selecciona plan -> Stripe checkout -> payment success"
criterio_exito: "Payment confirmado, subscription activada"
dependencias: ["OQI-005 completo"]
- test: "Course enrollment + video playback E2E"
id: E2E-007
tipo: e2e
automatizado: true
target: true
prioridad: P2
escenario: "Usuario enrolls en curso -> ve video -> progreso guardado"
criterio_exito: "Video reproduce, progreso persiste"
dependencias: ["OQI-002 completo"]
nota: "153 E2E tests existentes para video upload"
- test: "LLM chat interaction E2E"
id: E2E-008
tipo: e2e
automatizado: false
target: true
prioridad: P2
escenario: "Usuario abre chat -> envía mensaje -> recibe respuesta LLM"
criterio_exito: "Respuesta en < 5s, context mantenido"
dependencias: ["OQI-007 completado al 70%"]
- test: "Portfolio creation E2E"
id: E2E-009
tipo: e2e
automatizado: false
target: true
prioridad: P2
escenario: "Usuario crea portfolio -> agrega assets -> ve balance"
criterio_exito: "Portfolio creado, balance calculado correctamente"
dependencias: ["OQI-008 completado"]
- test: "Notification delivery E2E"
id: E2E-010
tipo: e2e
automatizado: false
target: true
prioridad: P1
escenario: "Sistema genera notificación -> usuario recibe push + email"
criterio_exito: "Notificación recibida en < 10s"
dependencias: ["GAP-P1-002 resuelto"]
# Integration Tests
integration_tests:
- test: "Backend API health check"
id: INT-001
tipo: integration
automatizado: true
target: true
prioridad: P0
endpoint: "GET /health"
criterio_exito: "Status 200, servicios conectados"
- test: "PostgreSQL connection pool"
id: INT-002
tipo: integration
automatizado: true
target: true
prioridad: P0
criterio_exito: "Pool activo, queries < 100ms"
- test: "Redis cache funcionando"
id: INT-003
tipo: integration
automatizado: true
target: true
prioridad: P0
criterio_exito: "Set/Get funcionando, TTL respetado"
- test: "ML Engine connection"
id: INT-004
tipo: integration
automatizado: true
target: true
prioridad: P1
criterio_exito: "FastAPI responde, modelos cargados"
- test: "LLM Agent connection"
id: INT-005
tipo: integration
automatizado: true
target: true
prioridad: P2
criterio_exito: "FastAPI responde, Ollama conectado"
- test: "Trading Agents connection"
id: INT-006
tipo: integration
automatizado: true
target: true
prioridad: P1
criterio_exito: "FastAPI responde, agentes disponibles"
# Unit Tests
unit_tests:
- test: "Auth service unit tests"
id: UNIT-001
tipo: unit
automatizado: true
target: true
prioridad: P0
coverage_target: 90
criterio_exito: "Login, register, logout, refresh testeados"
- test: "Trading service unit tests"
id: UNIT-002
tipo: unit
automatizado: true
target: true
prioridad: P0
coverage_target: 85
criterio_exito: "Order placement, cancellation, history testeados"
- test: "Payment service unit tests"
id: UNIT-003
tipo: unit
automatizado: true
target: true
prioridad: P1
coverage_target: 80
criterio_exito: "Stripe integration testeado"
# ==============================================================================
# UMBRALES DE CALIDAD
# ==============================================================================
umbrales_calidad:
codigo:
code_coverage:
actual: 15
target: 80
umbral_minimo: 70
gap: -65
bloqueante: true
nota: "Bloqueante para producción"
lint_errors:
actual: unknown
target: 0
umbral_minimo: 0
bloqueante: true
type_errors:
actual: unknown
target: 0
umbral_minimo: 0
bloqueante: true
complexity:
cyclomatic_max: 10
cognitive_max: 15
nota: "Refactorizar funciones que excedan"
rendimiento:
api_response_time:
p50: "< 200ms"
p95: "< 500ms"
p99: "< 1s"
frontend_load_time:
inicial: "< 2s"
interactivo: "< 3s"
database_query_time:
simple: "< 50ms"
complex: "< 200ms"
seguridad:
vulnerabilities:
critical: 0
high: 0
medium: "< 5"
dependencies_outdated:
critical: 0
all: "< 20%"
arquitectura:
services_using_apiclient: 100
python_access_via_express: 100
swagger_coverage: 100
endpoints_documented: 100
# ==============================================================================
# RUTA CRÍTICA Y DEPENDENCIAS
# ==============================================================================
ruta_critica:
semana_1_2:
fecha_inicio: "2026-01-27"
fecha_fin: "2026-02-03"
objetivo: "Resolver Gaps P0 (Bloqueantes)"
checkpoint: CP-01
esfuerzo: "54h"
tareas:
- tarea: "Implementar Password Recovery UI"
id: TASK-P0-001
esfuerzo: "8h"
owner: TBD
bloqueante: true
- tarea: "Crear userService.ts + endpoints"
id: TASK-P0-002
esfuerzo: "6h"
owner: TBD
bloqueante: true
- tarea: "Iniciar Trading Agents UI (50%)"
id: TASK-P0-003
esfuerzo: "20h"
owner: TBD
bloqueante: true
nota: "40h total, pero 50% suficiente para CP-01"
semana_3_4:
fecha_inicio: "2026-02-03"
fecha_fin: "2026-02-10"
objetivo: "Resolver Gaps P1 (Críticos) + Coherencia DDL-Backend"
checkpoint: CP-02
esfuerzo: "76h"
dependencias: ["CP-01 PASSED"]
tareas:
- tarea: "Crear marketData.service.ts"
id: TASK-P1-001
esfuerzo: "16h"
owner: TBD
- tarea: "Completar Notifications API"
id: TASK-P1-002
esfuerzo: "20h"
owner: TBD
- tarea: "ML Chart Overlays frontend"
id: TASK-P1-003
esfuerzo: "24h"
owner: TBD
- tarea: "2FA flujo completo"
id: TASK-P1-004
esfuerzo: "16h"
owner: TBD
semana_5_6:
fecha_inicio: "2026-02-10"
fecha_fin: "2026-02-17"
objetivo: "Resolver Gaps P2 + Coherencia Backend-Frontend"
checkpoint: CP-03
esfuerzo: "78h"
dependencias: ["CP-02 PASSED"]
tareas:
- tarea: "Audit system servicios"
id: TASK-P2-001
esfuerzo: "32h"
owner: TBD
- tarea: "Currency Exchange service"
id: TASK-P2-002
esfuerzo: "16h"
owner: TBD
- tarea: "Risk Assessment service"
id: TASK-P2-003
esfuerzo: "12h"
owner: TBD
- tarea: "Course Reviews + OAuth flows"
id: TASK-P2-004
esfuerzo: "18h"
owner: TBD
semana_7_8:
fecha_inicio: "2026-02-17"
fecha_fin: "2026-02-24"
objetivo: "Consolidación Arquitectural"
checkpoint: CP-04
esfuerzo: "40h"
dependencias: ["CP-03 PASSED"]
tareas:
- tarea: "Migrar acceso Python via Express"
id: TASK-ARCH-001
esfuerzo: "16h"
owner: TBD
impacto: "Security + Consistency"
- tarea: "Migrar servicios a apiClient"
id: TASK-ARCH-002
esfuerzo: "16h"
owner: TBD
impacto: "UX + Error handling"
- tarea: "Tests de integración"
id: TASK-ARCH-003
esfuerzo: "8h"
owner: TBD
semana_9_10:
fecha_inicio: "2026-02-24"
fecha_fin: "2026-03-03"
objetivo: "Testing y Calidad"
checkpoint: CP-05
esfuerzo: "40h"
dependencias: ["CP-04 PASSED"]
tareas:
- tarea: "Implementar E2E tests críticos"
id: TASK-QA-001
esfuerzo: "24h"
owner: TBD
tests: 10
- tarea: "Aumentar code coverage a 80%"
id: TASK-QA-002
esfuerzo: "16h"
owner: TBD
# ==============================================================================
# CONDICIONES GO/NO-GO PARA PRODUCCIÓN
# ==============================================================================
condiciones_produccion:
bloqueantes_absolutos:
- condicion: "CP-01 PASSED"
descripcion: "0 gaps P0 abiertos"
estado: FAIL
- condicion: "CP-02 PASSED"
descripcion: "Coherencia DDL-Backend >= 95%"
estado: FAIL
- condicion: "Code coverage >= 70%"
descripcion: "Coverage mínimo para producción"
estado: FAIL
- condicion: "0 vulnerabilidades críticas"
descripcion: "Security audit passed"
estado: UNKNOWN
- condicion: "E2E tests críticos passed"
descripcion: "Login, trading, payment funcionando"
estado: FAIL
recomendados:
- condicion: "CP-03 PASSED"
descripcion: "Coherencia Backend-Frontend >= 90%"
estado: FAIL
- condicion: "CP-04 PASSED"
descripcion: "Arquitectura consolidada"
estado: FAIL
- condicion: "Code coverage >= 80%"
descripcion: "Coverage recomendado"
estado: FAIL
nice_to_have:
- condicion: "CP-05 PASSED"
descripcion: "QA completo"
estado: FAIL
- condicion: "OQI-009 implementado"
descripcion: "MT4 Gateway funcional"
estado: FAIL
# ==============================================================================
# TRACKING Y REPORTES
# ==============================================================================
tracking:
frecuencia_revision: "Semanal"
responsable: "Project Lead"
formato_reporte: "YAML update + Executive summary"
metricas_semanales:
- coherencia_global
- gaps_p0_count
- gaps_p1_count
- gaps_p2_count
- code_coverage
- tests_passed
- checkpoints_status
escalacion:
- trigger: "CP-01 no resuelto en fecha target"
accion: "Escalar a PM, re-priorizar recursos"
- trigger: "Code coverage < 50% a 1 semana de release"
accion: "Postponer release, focus en testing"
- trigger: "Gaps P0 nuevos descubiertos"
accion: "Freeze features, resolver bloqueantes"
# ==============================================================================
# HISTORIAL DE CAMBIOS
# ==============================================================================
historial:
- fecha: "2026-01-27"
version: "1.0.0"
cambios: "Creación inicial del archivo de checkpoints"
autor: "Claude Opus 4.5"
base: "COHERENCE-MASTER-REPORT.md + PROJECT-STATUS.md"