sprint-0: fundaciones VMS-Sailor

Sprint 0 completo del producto VMS-Sailor (Vessel Management System
integrado para buques 30-40m). Brief de referencia en
VMS_Sailor_v2_Parte_*.md (intacto).

Core (vmssailor.core, 95.17% coverage, 99 tests verde):
- ShipCoord: sistema naval x_pp/y_cl/z_bl frozen
- Vessel, Deck, Bulkhead
- Equipment, EquipmentModel, Sensor, EquipmentSpec
- Tag, AlarmConfig, TagBinding, Scaling
- CardInstance, Bus, Topology con validacion 21 puntos I/O AR-NMEA-IO-v1.0
- Alarm, PermissiveRule, Condition
- Project agregado raiz con validacion cross-entity
- Persistencia portable .vmsproj (SQLite) con roundtrip verificable

Biblioteca curada seed (vmssailor.library):
- systems_catalog.json completo (catalogo maestro Parte 1 sec 7)
- 2 vessels: Sunseeker 76, Ferretti 850
- 2 motores: MTU 12V 2000 M96, Volvo D13-900
- 1 genset: Northern Lights M65C13
- yacht_motor_planeo.yaml (reglas heuristicas)
- TODO marcado data_source=seed_estimate - requiere validacion datasheets

Tools:
- vms-validate-library: CLI valida biblioteca completa
- vms-generate-test-project: CLI demo + verificacion roundtrip persistencia

Design System + 8 mockups HTML estaticos:
- docs/design_system.md (paleta Deep Ocean, gradientes, typography, motion)
- docs/brand/ (logo + variantes SVG)
- docs/mockups/splash, studio_main, runtime_overview,
  runtime_mimic_fuel (P&ID animado), runtime_alarms, runtime_trim (panel
  estrella con horizonte artificial), mobile_overview, mobile_trim
- docs/mockups/index.html (galeria)

Firmware (Sprint 12+ implementacion):
- firmware/ar_nmea_io_v1/src/config/pinout.h con macros GPIO

Decisiones autonomas documentadas en docs/decisions_sprint0.md.

Stack: Python 3.11 + uv + Pydantic v2 + SQLite stdlib + hatchling +
pytest 9 + ruff + mypy. Sin PySide6, FastAPI, Flutter ni firmware
funcional (entran en sprints siguientes).

Criterio de aceptacion Sprint 0: cumplido.
- uv sync: OK
- pytest: 99/99 verde
- cov vmssailor.core: 95.17% (objetivo >=80%)
- ruff: clean
- vms-validate-library: OK
- vms-generate-test-project: INTEGRIDAD OK

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-17 07:26:06 -04:00
commit deb04c9315
96 changed files with 15335 additions and 0 deletions
+483
View File
@@ -0,0 +1,483 @@
# VMS-Sailor · Brief para Claude Code · Parte 6 de 6
## Plan de sprints completo, modelo de datos core, reglas de oro
> Esta es la última parte. Asume que ya leíste Partes 1-5.
---
## 1. Ubicación del proyecto
**Todo va en `D:/Proyectos Software/VMS-Sailor/`.**
- Si la carpeta no existe, créala.
- Si existe vacía, úsala.
- Si tiene contenido previo, pregúntame antes de tocar nada.
- Git desde el primer commit. Cada sprint termina con commit etiquetado (`sprint-0`, `sprint-1`, etc.).
`.gitignore` debe incluir:
```
__pycache__/
*.pyc
.venv/
dist/
build/
*.egg-info/
.idea/
.vscode/
logs/
*.vmspack
*.vmsdelta
licenses/local/
mobile/build/
firmware/.pio/
firmware/.vscode/
*.bin
historian.duckdb
secrets/
```
---
## 2. Estructura raíz del repositorio
```
D:/Proyectos Software/VMS-Sailor/
├── README.md
├── LICENSE.txt
├── CHANGELOG.md
├── pyproject.toml
├── requirements.txt
├── requirements-dev.txt
├── .gitignore
├── studio_main.py # Entry point del Studio
├── runtime_server_main.py # Entry point del servicio Windows
├── runtime_client_main.py # Entry point del cliente desktop
├── vmssailor/ # Código Python compartido
│ ├── __init__.py
│ ├── version.py
│ ├── core/ # Modelo de datos compartido (CRÍTICO)
│ ├── library/ # Biblioteca curada (solo Studio)
│ ├── studio/ # App Studio (Parte 2)
│ ├── runtime/ # App Runtime (Parte 3)
│ ├── shared/ # Utilidades compartidas
│ └── tests/ # Tests Python
├── firmware/ # Firmware ESP32 (Parte 4)
│ └── ar_nmea_io_v1/
├── mobile/ # App Flutter (Parte 5)
│ └── lib/
├── docs/ # Documentación técnica
├── installer/ # WiX MSI scripts
├── tools/ # Scripts auxiliares
└── projects/ # Proyectos de buques específicos (git-ignored excepto seed)
```
---
## 3. Modelo de datos core (Sprint 0)
Este es el corazón del sistema. Lo construimos en Sprint 0 antes de cualquier UI.
### Coordenadas navales
```python
from dataclasses import dataclass
@dataclass(frozen=True)
class ShipCoord:
"""Coordenadas en el marco del buque.
x_pp : metros desde Perpendicular de Popa (Pp), positivo hacia proa.
y_cl : metros desde Línea de Crujía (CL), positivo a estribor, negativo a babor.
z_bl : metros desde Línea Base (BL), positivo hacia arriba.
"""
x_pp: float
y_cl: float
z_bl: float
```
### Entidades principales
```
Vessel
└── Deck[] Cubiertas con polígono 2D vista planta + altura
Project (instancia de un buque específico para un cliente)
├── vessel_ref referencia a Vessel de biblioteca o importado
├── name "M/Y Aurora"
├── customer
├── systems_enabled List[SystemId]
├── equipment List[Equipment]
├── tags List[Tag]
├── cards List[CardInstance]
└── topology Topology
Equipment
├── id
├── model_ref referencia a EquipmentModel
├── tag_prefix "ME_PORT", "GEN_1"
├── location: ShipCoord
├── deck_id
└── system_id
EquipmentModel (en biblioteca)
├── id "mtu_12v_2000_m96"
├── manufacturer "MTU"
├── model_name "12V 2000 M96"
├── category ENGINE_MAIN | GENSET | PUMP | ...
├── specs potencia, RPM nominales, peso, dimensiones
└── default_sensors List[Sensor]
Sensor
├── id
├── name "Oil Pressure"
├── type TEMPERATURE | PRESSURE | LEVEL | RPM | VOLTAGE | ...
├── unit_si "bar", "C", "rpm"
├── range_normal (min, max)
├── alarm_low (value, priority)
├── alarm_high (value, priority)
└── default_signal_type RTD_PT100 | 4-20MA | 0-10V | PULSE | ...
Tag (punto I/O concreto)
├── id autogenerado "ME_PORT.OIL_PRESS"
├── description
├── value float | bool | str
├── quality GOOD | BAD | UNCERTAIN
├── timestamp
├── unit_si
├── range_normal
├── alarms List[AlarmConfig]
├── controllable bool
├── control_mode MONITOR | MANUAL | AUTO | FUTURE
├── authority_required BRIDGE | ENGINE | EITHER
├── protocol MODBUS_RTU | MODBUS_TCP | NMEA2000 | J1939
├── address dirección Modbus o ID CAN
├── scaling raw → engineering
└── physical_binding TagBinding
TagBinding (cómo un tag se mapea a un canal físico)
├── card_id
├── channel_type AI | DI | DO | RPM
├── channel_number 1-10 (o 1-5 para DI, 1-4 para AI)
├── signal_type 4-20MA | 0-10V | RTD_PT100 | RELAY_NO | ...
├── scaling raw_min, raw_max, eng_min, eng_max
├── filter NONE | MOVING_AVG | MEDIAN | DEADBAND | RATE_LIMIT
└── update_rate_ms
CardInstance (una tarjeta AR-NMEA-IO en un proyecto concreto)
├── id "card_001"
├── serial_number "ARC-2026-00153"
├── slot_number 1-16 (dipswitch físico)
├── physical_location "Sala máquinas, panel principal"
├── ship_coord ShipCoord aproximada
├── bus_role MODBUS_SLAVE | MODBUS_MASTER | NMEA2000_NODE | DUAL | BRIDGE
├── modbus_address 1-247 si esclava
├── bus_segment "bus_main"
└── firmware_version
Topology (la red completa del proyecto)
├── buses List[Bus]
└── cards List[CardInstance]
Bus
├── id "bus_main"
├── protocol MODBUS_RTU | NMEA2000
├── physical_port "COM3" | "USB-CAN0"
├── baud_rate
├── parity, stop_bits (Modbus RTU)
└── termination
Alarm (instancia activa)
├── id
├── tag_id
├── priority EMERGENCY | HIGH | LOW | INFO
├── state ACTIVE | ACK | CLEARED
├── timestamp_active
├── timestamp_ack
├── timestamp_cleared
├── acknowledged_by
└── message
PermissiveRule
├── action_id "START_ME_PORT"
├── conditions List[Condition]
└── on_fail_message
Condition
├── tag_ref
├── operator EQ | NEQ | GT | LT | BETWEEN | IS_TRUE | IS_FALSE
├── threshold
├── severity FAIL | WARNING
└── message_on_fail
```
### Persistencia
- **Biblioteca curada**: archivos JSON/YAML versionados en git
- **Proyecto en Studio**: archivo único `.vmsproj` (SQLite portable)
- **Paquete distribuible**: `.vmspack` = ZIP firmado con `manifest.json` + `project.db` + mímicos + firmware + assets
- **Runtime a bordo**: descomprime `.vmspack` en `%PROGRAMDATA%/VMS-Sailor/project/`
- **Capas**: cada capa es un `.vmsdelta` separado en `%PROGRAMDATA%/VMS-Sailor/layers/`
- **Historian**: DuckDB en `%PROGRAMDATA%/VMS-Sailor/historian.duckdb`
- **Auditoría**: SQLite append-only en `%PROGRAMDATA%/VMS-Sailor/audit.db`
---
## 4. Plan completo de sprints
### Sprint 0 — Fundaciones (2-3 semanas)
**Objetivo**: estructura completa del proyecto + modelo de datos + biblioteca seed mínima.
**Entregables:**
- Repositorio Git inicializado con la estructura completa (stubs creados)
- `pyproject.toml`, `requirements.txt`, `.gitignore`
- Módulo `vmssailor.core` completo con tests (cobertura ≥80%)
- Persistencia: serialización/deserialización a `.vmsproj`
- Biblioteca seed mínima:
- 2 yates motor (Sunseeker 76, Ferretti 850)
- 2 motores principales (MTU 12V 2000 M96, Volvo D13 900hp)
- 1 genset (Northern Lights M65C13)
- 1 archivo de reglas (yacht_motor_planeo.yaml)
- `systems_catalog.json` completo (todos los sistemas de la Parte 1)
- Validador de biblioteca: `tools/validate_library.py`
- Tests unitarios para `core` (cobertura ≥80%)
- README con setup
- Pinout inicial del firmware en `firmware/ar_nmea_io_v1/src/config/pinout.h` (sin firmware funcional aún)
**Criterio de aceptación**: `pytest` pasa todo, `validate_library.py` pasa todo, se puede crear/guardar/leer un Project programáticamente desde script.
### Sprint 1 — Studio shell + wizard básico (3-4 semanas)
- QApplication del Studio con ventana principal y menú
- Wizard pasos 1-4 funcional (tipo, plantilla, dimensiones, sistemas)
- Visualización de silueta en QGraphicsView con sistema de coordenadas naval (rejilla en metros desde Pp)
- Sin paso 5-8 aún (mocked)
- Se puede crear proyecto desde wizard y guardarlo como `.vmsproj`
### Sprint 2 — Wizard completo + editor de equipos (3-4 semanas)
- Pasos 5-8 del wizard: motor de reglas YAML, propuesta de equipos, refinamiento manual con drag-and-drop, paso 7 de topología
- Editor de equipos: CRUD, vista planta, vista lista
- Más buques en biblioteca: 5-7 yates motor + 2 pesqueros + 1 patrullero
- Más equipos en biblioteca: 10+ motores, 6+ gensets, bombas básicas
### Sprint 3 — Editor de mímicos + tags + alarmas (3-4 semanas)
- Editor visual de mímicos por sistema (QGraphicsView con símbolos arrastrables)
- Editor de tags: tabla con filtros, edición de direcciones, escalado, control_mode
- Editor de alarmas: límites, prioridades, histéresis, mensajes
- Símbolos básicos: motor, bomba, válvula, tanque, sensor, indicador, línea
### Sprint 4 — Runtime servidor base (4-5 semanas)
- Servicio Windows operativo (pywin32) arrancando al boot
- Driver Modbus TCP funcional (pymodbus)
- Driver Modbus RTU funcional
- `tag_store` en memoria con pub/sub
- Historian básico DuckDB con retención configurable
- Alarm engine con evaluación de límites, prioridades, ack
- API REST/WebSocket básica
- Simulador del Studio que inyecta valores en servidor de pruebas
### Sprint 5 — NMEA 2000 + Log Book básico (3-4 semanas)
- Driver NMEA 2000 (CAN) suscribiendo a PGNs configurados
- Log Book básico:
- Auto-detección arranque/parada motores
- Snapshots periódicos cada 15 min
- Registro de alarmas con ack
- Entradas manuales
- Firma digital inmutable
- Cliente desktop básico (login + overview + lista de sistemas)
### Sprint 6 — Cliente desktop completo (3-4 semanas)
- Renderizado completo de mímicos desde `.vmspack`
- Panel de alarmas viviente con ack
- Trends básicos (gráficas tiempo real con fl_chart Python equivalente: pyqtgraph)
- Login con tres perfiles
- Permisos por rol
- Vista de logbook
- Vista de soporte y auditoría (Admin solo)
### Sprint 7 — Empaquetador + activación + MSI (3 semanas)
- `package_builder` genera `.vmspack` desde proyecto del Studio
- `delta_builder` genera `.vmsdelta`
- `hwid_binder` liga paquete a HWID destino
- Activación online inicial del Runtime
- WiX scripts para generar instalador MSI Windows con servicio
- Activación del Studio (protegerlo a mi PC)
### Sprint 8 — Permissive + Authority + Stability (3-4 semanas)
- Permissive engine completo con todas las pre-condiciones
- Editor de permissives en Studio
- Authority manager: transferencia bilateral puente↔máquinas
- Override de emergencia (E-stop)
- Stability monitor con los 3 niveles + envelope + modo manual owner
- UI de autoridad y stability en clientes desktop
### Sprint 9 — Layer Config Engine (3 semanas)
- Carga de capas en orden al boot
- Aplicación de deltas firmados con verificación criptográfica
- Snapshots automáticos antes de aplicar
- Rollback granular accesible al owner
- Schema validation entre versiones
- UI de gestión de actualizaciones en cliente desktop (orden de trabajo + disponibilidad)
### Sprint 10 — Telemetría + VPN + auditoría (2-3 semanas)
- Telemetría de salud transparente (visible al owner, pausable)
- Soporte WireGuard externo (cliente VPN en Runtime)
- Endpoints administrativos solo desde IP del túnel
- Auditoría completa de sesiones VPN
- Vista de "Soporte y Auditoría" en cliente
### Sprint 11 — VMS-Sailor Mobile (Flutter) (4-5 semanas)
- Setup proyecto Flutter
- Enrollment flow con QR
- Login + TOTP + biométrico
- Cliente WebSocket + REST
- Pantallas: Overview, Lista sistemas, Mímico, Alarmas con notificaciones
- Panel Trim y Maniobra destacado
- Build iOS + Android
### Sprint 12 — Firmware ESP32 base (4 semanas)
- Setup PlatformIO o ESP-IDF
- Modbus RTU esclava funcional
- Discovery broadcast + config push desde VMS
- Lectura de 5 DI + 4 AI con oversampling
- Comando de 10 DO
- Lectura de RPM
- Filtros locales (moving average, median, deadband)
- Tests con simulador y banco de pruebas
### Sprint 13 — Firmware NMEA 2000 + J1939 (3 semanas)
- Stack NMEA 2000 funcional
- Publicación de PGNs estándar (127488, 127489, 127505, 127508)
- Listener J1939 para motores que hablan ese protocolo
- Modo dual (Modbus + NMEA 2000 simultáneo)
### Sprint 14 — OTA + permissives locales + alarmas locales (3 semanas)
- Cliente OTA seguro con verificación de firma
- Rollback automático si firmware nuevo falla
- Permissives locales críticos (E-stop) ejecutándose en la tarjeta
- Alarmas locales con umbrales
- Health reporter cada 60s
### Sprint 15 — Pruebas integradas + hardening (3 semanas)
- Pruebas de integración VMS + tarjetas reales
- Pruebas de stress (alta carga de tags, alarmas masivas)
- Pruebas de fallo (cable cortado, tarjeta sin energía, bus colgado)
- Watchdog y recovery automático
- Documentación de operador y mantenimiento
### Sprint 16+ — Refinamientos y extensiones
- Log Book regulatorio completo (MARPOL, IMO)
- Integración Seakeeper, Quick MC², CMC stabilizers
- Cotizador de expansiones
- Generador paramétrico de silueta
- Plantillas adicionales (offshore support, ferries más grandes)
- Edge cases y polishing
- Manuales de usuario completos
---
## 5. Reglas de oro (recordatorio)
1. **Antes de cada sprint**, me presentas plan detallado de lo que vas a hacer y esperas mi OK. No improvises features.
2. **Cada cambio importante** se discute primero en chat. Yo decido alcance.
3. **Tests obligatorios** para todo lo que toca `core` y `runtime/server`. UI más relajada pero `pytest-qt` en flujos críticos. Firmware: `Unity` + PlatformIO test runner. Mobile: tests de widget Flutter.
4. **No agregues dependencias** sin preguntarme primero.
5. **Mantén consistencia** con mis otras apps (AR ShipDesign, AR-ElecArrangement, AR-StabCol): misma filosofía UX, mismo idioma por defecto (español), mismo manejo de coordenadas navales.
6. **Documenta normativa** cuando implementes algo regulado:
- IEC 60092-504 (electrical installations in ships - automation)
- IACS UR E22 (computer-based systems)
- ABYC E-11 (electrical)
- NMEA 2000 (protocolo, PGNs)
- SAE J1939 (CAN motores)
- IMO MARPOL/SOLAS (log book — sprint 16+)
7. **Sin red de salida en Runtime** salvo:
- Activación inicial de licencia (Studio → mi servidor)
- Túnel VPN administrativa (cliente WireGuard externo)
- Telemetría técnica solo si el owner la habilita
Sin telemetría implícita NUNCA.
8. **La biblioteca curada es ORO**. Cualquier cambio en formato de archivos de biblioteca requiere migración para los proyectos existentes.
9. **El Runtime debe ser inmutable para el cliente**. El cliente no puede editar tags, alarmas, mímicos, topología. Solo opera lo que el Studio le entregó vía paquetes y deltas firmados.
10. **Auditoría siempre activa** en Runtime:
- Cada ack de alarma
- Cada solicitud de autoridad
- Cada override de permissive
- Cada conexión VPN mía con timestamps y endpoints accedidos
- Cada aplicación de delta
- Cada rollback
- Cada enrolamiento/revocación de dispositivo móvil
11. **Coordenadas navales consistentes** en TODO el código: ShipCoord siempre, conversión a pantalla solo en renderers.
12. **Unidades SI internas siempre**: m, kg, Pa, °C, s. Conversión a imperial solo en UI cuando el usuario lo pida.
13. **Idioma**: español por defecto, inglés como segundo. Strings en `vmssailor/i18n/`.
14. **AR-ECDIS es producto separado**, no se desarrolla en este repositorio. Solo se asume que publica al backbone NMEA 2000 datos de navegación y actitud (PGN 127257) que el VMS-Sailor consume.
15. **Firmware y software van juntos**. El mismo `.vmspack` que configura el Runtime incluye los binarios de firmware para las tarjetas del proyecto. Versionados consistentemente.
---
## 6. Cómo proceder ahora
**Paso 1.** Confirma que entendiste el alcance global de las 6 partes. Pregunta cualquier duda ANTES de tocar código.
**Paso 2.** Verifica si existe `D:/Proyectos Software/VMS-Sailor/`. Si está vacía, OK. Si tiene contenido, pregúntame.
**Paso 3.** Presenta tu plan detallado del **Sprint 0**: lista de archivos que vas a crear, librerías que vas a usar, tests que vas a escribir. Espera mi OK.
**Paso 4.** Cuando dé OK, ejecutas el Sprint 0 completo. Al final me presentas:
- Repositorio completo con commit `sprint-0`
- Resultado de `pytest` (todo en verde)
- Resultado de `validate_library.py` (todo en verde)
- Script de demo `tools/generate_test_project.py` que crea proyecto de prueba, lo guarda como `.vmsproj` y lo lee de vuelta para verificar integridad
**Paso 5.** Yo reviso, doy feedback, y cuando apruebo, taggeas `sprint-0-approved` y pasamos al Sprint 1.
---
## 7. Información adicional
- Mi código LiveCode original de VMS-Sailor: **NO TENGO**. Construimos desde cero.
- Capturas de pantalla de mímicos comerciales (Kongsberg K-Chief, Praxis Mega-Guard, Wärtsilä NACOS) como referencia visual: te los pasaré en mensajes posteriores si hace falta.
- El servidor de licencias para activación es proyecto APARTE que no se construye aquí; solo el cliente de activación dentro del Runtime y dentro del Studio.
- WireGuard se gestiona externamente; solo helpers en Runtime, no embebido.
- Cualquier feature que se te ocurra que NO esté en estas 6 partes, lo discutes conmigo antes.
- El hardware AR-NMEA-IO-v1.0 ya está diseñado (PCB esquemático en archivos del proyecto), no se modifica en este desarrollo. El firmware sí lo escribimos desde cero.
---
**Fin del brief completo (Partes 1-6).**
Comienza confirmando que entendiste el alcance global, y luego preséntame tu plan del Sprint 0.