From f024a6a1cbcb68395fe1a15d4ac852c2be2416e6 Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Sun, 22 Mar 2026 23:48:32 +0000 Subject: chore: unify and centralize agent configuration in .agent/ --- .agent/coding_standards.md | 14 + .agent/config.md | 29 ++ .agent/design.md | 997 +++++++++++++++++++++++++++++++++++++++++++++ .agent/mission.md | 13 + .agent/narrative.md | 36 ++ .agent/preferences.md | 7 + .agent/worklog.md | 141 +++++++ 7 files changed, 1237 insertions(+) create mode 100644 .agent/coding_standards.md create mode 100644 .agent/config.md create mode 100644 .agent/design.md create mode 100644 .agent/mission.md create mode 100644 .agent/narrative.md create mode 100644 .agent/preferences.md create mode 100644 .agent/worklog.md (limited to '.agent') diff --git a/.agent/coding_standards.md b/.agent/coding_standards.md new file mode 100644 index 0000000..3d43e88 --- /dev/null +++ b/.agent/coding_standards.md @@ -0,0 +1,14 @@ +# Coding Standards + +Technical standards for the **Nav** (Sailing Companion) project. + +## 1. Android (Kotlin) +- **Architecture:** MVVM with ViewBinding/DataBinding. +- **UI:** Glanceable, high-contrast, cockpit-friendly design. +- **Persistence:** Room for local database; offline-first approach. +- **Async:** Kotlin Coroutines for non-blocking UI. + +## 2. Boating Domain +- **Safety First:** MOB and Anchor Alarm features are critical. +- **Offline Utility:** Must work without internet connectivity (using cached charts/GRIBs). +- **Integration:** Standard NMEA interface for instrument data. diff --git a/.agent/config.md b/.agent/config.md new file mode 100644 index 0000000..6094452 --- /dev/null +++ b/.agent/config.md @@ -0,0 +1,29 @@ +# Agent Configuration & Master Rulebook (.agent/config.md) + +This is the primary source of truth for all AI agents working on **Nav**. These instructions take absolute precedence over general defaults. + +## 1. Project Directory Structure (.agent/) + +| File | Purpose | +|------|---------| +| `config.md` | **Main Entry Point** — Rules, workflows, and core mandates. | +| `worklog.md` | **Session State** — Current focus, recently completed, and next steps. | +| `design.md` | **Architecture** — Component design, UI mockups, and roadmap. | +| `coding_standards.md` | **Technical Standards** — Android/Kotlin best practices, offline-first. | +| `mission.md` | **Mission & Values** — Strategic goals and agent personality. | +| `narrative.md` | **Background** — Historical context and evolution of the project. | +| `preferences.md` | **User Prefs** — Living record of user-specific likes/dislikes. | + +## 2. Core Mandates + +### ULTRA-STRICT ROOT SAFETY PROTOCOL +1. **Inquiry-Only Default:** Treat every message as research/analysis unless it is an explicit, imperative command (Directive). +2. **Zero Unsolicited Implementation:** Never modify files, directories, or processes based on assumptions. +3. **Interactive Strategy Checkpoint:** Research first, present a strategy, and **WAIT** for an explicit "GO" before any system-changing tool call. +4. **No Destructive Assumptions:** Always verify state (`ps`, `ls`, `git status`) before proposing actions. +5. **Root-Awareness:** Prioritize system integrity and user confirmation over proactiveness. + +### Living Documentation Mandate +1. **Continuous Capture:** Agents MUST proactively update the files in ".agent/" as new decisions, patterns, or user preferences are revealed. +2. **No Stale Instructions:** If a workflow or technical standard evolves, the agent is responsible for reflecting that change in the Master Rulebook immediately. +3. **Worklog Integrity:** The ".agent/worklog.md" must be updated at the start and end of EVERY session. diff --git a/.agent/design.md b/.agent/design.md new file mode 100644 index 0000000..ba82612 --- /dev/null +++ b/.agent/design.md @@ -0,0 +1,997 @@ +# Sailing Companion App — Component Design Document + +**Version:** 1.0 +**Date:** 2026-03-13 +**Status:** Draft + +--- + +## Table of Contents + +1. [Overview & Vision](#1-overview--vision) +2. [Competitive Analysis](#2-competitive-analysis) +3. [Core Technical Components](#3-core-technical-components) +4. [Technical Boating Features](#4-technical-boating-features) +5. [System Architecture](#5-system-architecture) +6. [Data Model Essentials](#6-data-model-essentials) +7. [External Integrations](#7-external-integrations) +8. [UX Principles](#8-ux-principles) +9. [Constraints & Considerations](#9-constraints--considerations) +10. [Phased Roadmap](#10-phased-roadmap) + +--- + +## 1. Overview & Vision + +### Purpose + +A sailing companion app that serves as an integrated bridge instrument, weather advisor, performance coach, and safety system — all in one offline-capable mobile application. It replaces the need to juggle multiple single-purpose apps while underway. + +### Target Users + +| Segment | Use Case | +|----------------------|-------------------------------------------------------------| +| **Daysailors** | Quick weather check, anchor alarm, basic navigation | +| **Coastal cruisers** | Route planning, tide overlays, trip logging, safety alerts | +| **Passage makers** | Offshore weather routing, polar performance, watch keeping | +| **Club racers** | VMG optimization, layline calculation, polar targets | +| **Liveaboards** | Anchor watch, weather monitoring, logbook, maintenance logs | + +### Key Differentiators + +1. **Offline-first architecture** — full charting, routing, and safety features work without connectivity. +2. **Integrated performance polars** — real-time VMG coaching tied directly to weather and routing. +3. **Single-pane-of-glass bridge** — weather, chart, instruments, and safety on one screen. +4. **NMEA integration without proprietary lock-in** — works with any standard instrument bus. +5. **Glance-able UI designed for the cockpit** — large targets, high contrast, wet-hand friendly. + +### Value Proposition + +> "One app, one screen, everything you need from dock to dock — online or off." + +Existing solutions force sailors to switch between a charting app, a weather app, a performance app, and a tide app. This product unifies all four and adds safety features (MOB, anchor alarm, watch alerts) that currently require dedicated hardware or separate apps. + +--- + +## 2. Competitive Analysis + +### Feature Comparison Matrix + +| Feature | Navily | Windy | PredictWind | OpenCPN | SailGrib | Tides (various) | Navico GoFree | **This App** | +|----------------------------------|:------:|:-----:|:-----------:|:-------:|:--------:|:----------------:|:-------------:|:------------:| +| Vector charts | - | - | - | ✓✓ | ✓ | - | ✓✓ | ✓✓ | +| Raster charts | - | - | - | ✓✓ | ✓ | - | ✓ | ✓ | +| Weather overlay (wind/pressure) | - | ✓✓ | ✓✓ | ✓ | ✓✓ | - | ✓ | ✓✓ | +| Tide/current predictions | ✓ | ✓ | ✓ | ✓ | ✓ | ✓✓ | ✓ | ✓✓ | +| Route planning | - | - | ✓✓ | ✓✓ | ✓✓ | - | ✓ | ✓✓ | +| Weather routing (isochrones) | - | - | ✓✓ | ✓* | ✓✓ | - | - | ✓✓ | +| Performance polars | - | - | ✓ | ✓* | ✓ | - | - | ✓✓ | +| NMEA instrument integration | - | - | - | ✓✓ | - | - | ✓✓ | ✓✓ | +| MOB alarm | - | - | - | ✓ | - | - | ✓ | ✓✓ | +| Anchor alarm | ✓ | - | - | ✓* | - | - | ✓ | ✓✓ | +| Offline charts/weather | - | ✓* | ✓* | ✓✓ | ✓✓ | ✓ | ✓ | ✓✓ | +| Trip logbook | ✓ | - | - | ✓* | - | - | - | ✓✓ | +| Mobile-native UI | ✓✓ | ✓✓ | ✓✓ | - | ✓ | ✓✓ | ✓ | ✓✓ | + +✓✓ = strong, ✓ = present, ✓* = via plugin/limited, - = absent + +### Gaps in Existing Solutions + +| Gap | Who suffers | Our answer | +|------------------------------------------------------|----------------------|-----------------------------------------------| +| No single app combines charting + weather + polars | Coastal/offshore | Unified bridge view | +| OpenCPN is powerful but desktop-first | Mobile-only sailors | Native mobile with full OpenCPN-class features| +| Windy/PredictWind lack real-time instrument data | Performance sailors | NMEA integration with live polar overlay | +| Navily focuses on social/anchorages, not navigation | Passage makers | Full nav suite, no social features | +| Tide apps are standalone, not integrated with charts | Coastal cruisers | Tide/current overlays on the chart | +| Anchor alarms require separate apps | All anchoring sailors| Built-in anchor watch with configurable alerts| +| No good offline weather routing on mobile | Offshore sailors | Offline GRIB processing + isochrone routing | + +--- + +## 3. Core Technical Components + +### Component Architecture Overview + +``` +┌──────────────────────────────────────────────────────────────────┐ +│ UI / Presentation │ +│ ┌──────────┐ ┌──────────┐ ┌───────────┐ ┌──────────────────┐ │ +│ │ Chart │ │Instrument│ │ Weather │ │ Safety / Alerts │ │ +│ │ View │ │ Panel │ │ Overlay │ │ Panel │ │ +│ └────┬─────┘ └────┬─────┘ └─────┬─────┘ └───────┬──────────┘ │ +│ │ │ │ │ │ +├───────┴─────────────┴─────────────┴───────────────┴──────────────┤ +│ Application Services │ +│ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌──────────────┐ │ +│ │ Navigation │ │ Weather │ │ Performance│ │ Safety │ │ +│ │ Engine │ │ Service │ │ Tracker │ │ Monitor │ │ +│ └─────┬──────┘ └─────┬──────┘ └─────┬──────┘ └──────┬───────┘ │ +│ │ │ │ │ │ +├────────┴──────────────┴──────────────┴───────────────┴───────────┤ +│ Data Layer │ +│ ┌──────────┐ ┌──────────┐ ┌───────────┐ ┌────────────────┐ │ +│ │ Chart DB │ │ Weather │ │ Logbook │ │ Settings / │ │ +│ │ (S-57/ │ │ Cache │ │ Store │ │ Boat Profile │ │ +│ │ MBTiles)│ │ (GRIB) │ │ (SQLite) │ │ (SQLite) │ │ +│ └─────┬────┘ └────┬─────┘ └─────┬─────┘ └───────┬────────┘ │ +│ │ │ │ │ │ +├────────┴───────────┴─────────────┴───────────────┴───────────────┤ +│ Platform / Hardware │ +│ ┌────────┐ ┌──────────┐ ┌───────────┐ ┌──────────────────┐ │ +│ │ GPS │ │ NMEA │ │ Compass / │ │ Cloud Sync │ │ +│ │ Module │ │ Bridge │ │ Sensors │ │ (optional) │ │ +│ └────────┘ └──────────┘ └───────────┘ └──────────────────┘ │ +└──────────────────────────────────────────────────────────────────┘ +``` + +### 3.1 Navigation & Vector Charting Module + +**Responsibility:** Render nautical charts, manage chart data, handle pan/zoom, and overlay navigation objects (waypoints, routes, tracks, AIS targets). + +| Subcomponent | Technology | Notes | +|----------------------|-----------------------------------|--------------------------------------------| +| Chart renderer | MapLibre GL Native / custom tiles | GPU-accelerated vector rendering | +| Chart data store | MBTiles (SQLite-backed) | Offline-first; predownloaded chart regions | +| S-57/S-63 parser | Custom or libosmium-based | Converts ENC data to internal tile format | +| Symbol library | INT-1 compliant symbol set | IHO S-52 presentation library | +| Overlay engine | Canvas/GL overlay layer | Routes, tracks, AIS, weather, tides | + +**Key behaviors:** +- Seamless zoom from overview to harbor-scale. +- Depth shading with configurable safety contour. +- Chart quilting (multiple chart scales blended). +- Tap-to-query chart objects (buoys, lights, depths). + +### 3.2 Real-time Weather & Environmental Data + +**Responsibility:** Ingest, cache, and visualize wind, pressure, temperature, precipitation, wave, current, and tide data. + +| Data Type | Source(s) | Update Interval | Offline Strategy | +|------------------------|-------------------------------|-----------------|----------------------------| +| Surface wind | GFS/ECMWF via GRIB2 | 6h | Pre-download GRIB files | +| Barometric pressure | GFS, device sensor | 6h / real-time | GRIB + local sensor | +| Tide height | NOAA CO-OPS, UKHO, SHOM | Static harmonic | Harmonic constants on-device| +| Tidal current | NOAA, regional models | Static harmonic | Harmonic constants on-device| +| Sea state / swell | WW3 via GRIB2 | 6h | Pre-download | +| Precipitation / clouds | GFS/ECMWF | 6h | Pre-download | +| Lightning | Blitzortung / provider API | Real-time | Not available offline | + +**GRIB processing pipeline:** + +``` + Download GRIB2 ──► Decode (eccodes) ──► Spatial index ──► Render to tile cache + │ │ + │ ┌──────────────────┐ │ + └──────────────────►│ Interpolation │◄────────────────┘ + │ (bilinear, time) │ + └────────┬─────────┘ + │ + Weather at lat/lon/time +``` + +### 3.3 Sailing Performance Tracking + +**Responsibility:** Compute and display real-time performance metrics derived from GPS, NMEA instruments, and boat polars. + +**Core metrics computed:** + +| Metric | Source(s) | Computation | +|--------|-----------|-------------| +| SOG (Speed Over Ground) | GPS | Direct from GPS fix | +| COG (Course Over Ground) | GPS | Direct from GPS fix | +| BSP (Boat Speed) | NMEA paddlewheel | Direct from instrument | +| HDG (Heading) | NMEA compass / device | Magnetic + variation = True | +| TWS/TWD (True Wind) | AWS/AWA + BSP + HDG | Vector triangle resolution | +| VMG (Velocity Made Good) | TWA + BSP | BSP × cos(TWA) | +| VMC (Velocity Made good to Course) | COG + SOG + bearing to WP | SOG × cos(bearing delta) | +| Heel angle | NMEA or device accelerometer | Direct or computed | +| Leeway | Heel + BSP + boat model | Empirical formula per hull type | +| Current set/drift | SOG/COG vs BSP/HDG | Vector difference | +| Polar % | BSP vs target BSP at TWS/TWA | (BSP / polar_target) × 100 | + +**Polar engine:** +- Stores polar tables as TWS × TWA → target BSP lookup. +- Interpolates between data points (bicubic). +- Computes optimal VMG angles (upwind/downwind) per TWS. +- Outputs target boat speed and target TWA for current conditions. + +### 3.4 Route Planning & Optimization + +**Responsibility:** Create, edit, and optimize sailing routes considering weather, currents, tides, and boat polars. + +**Route planning modes:** + +1. **Manual waypoint routing** — user taps waypoints on chart; system computes distance, bearing, ETAs. +2. **Great-circle / rhumb-line routing** — for offshore passages. +3. **Weather routing (isochrone)** — optimal route given GRIB forecast and boat polars. + +**Isochrone weather routing algorithm:** + +``` + Start ──► Generate fan of headings (5° increments) + │ + ▼ + For each heading, compute BSP from polars at + forecast wind (TWS/TWD) and current + │ + ▼ + Advance position by BSP × Δt (typically 1-3h steps) + │ + ▼ + Prune: remove dominated points (slower to same isochrone) + │ + ▼ + Repeat until isochrone reaches destination + │ + ▼ + Backtrace optimal path through isochrone tree +``` + +**Tide gate logic:** Route optimizer accounts for tidal current vectors at each waypoint leg, adjusting ETAs and optimal departure times. + +### 3.5 Safety & Alerting System + +**Responsibility:** Monitor conditions and trigger alerts for safety-critical events. + +| Alert Type | Trigger | Priority | Action | +|--------------------|------------------------------------------------------|----------|----------------------------------| +| **MOB** | User activation (hardware button / screen button) | CRITICAL | Drop MOB waypoint, start timer, show bearing/distance, sound alarm | +| **Anchor drag** | Position exceeds watch circle radius | HIGH | Audible + visual alarm, log event| +| **Depth** | Depth < user-configured minimum | HIGH | Audible alarm | +| **Off-course** | XTE > user-configured limit | MEDIUM | Visual + optional audible | +| **Weather change** | Wind shift > 30° or gust > threshold | MEDIUM | Push notification | +| **Watch alarm** | Timer expires (configurable intervals) | LOW | Audible alarm | +| **AIS CPA/TCPA** | Closest Point of Approach < threshold | HIGH | Visual + audible alarm | +| **Waypoint arrival**| Distance to active WP < arrival radius | LOW | Notification, auto-advance route | + +**MOB workflow:** +1. Single-tap large MOB button (always visible) → drops waypoint at current GPS position. +2. Screen switches to MOB view: bearing and distance to MOB point, elapsed time. +3. Compass ring shows bearing to MOB. +4. If NMEA autopilot connected: offer "Williamson Turn" or "Direct Return" course command. +5. MOB event logged with timestamp, position, conditions. +6. Cannot be silenced without explicit confirmation. + +### 3.6 Data Persistence & Cloud Sync + +**Local storage (SQLite + file system):** + +| Store | Format | Size Estimate | +|--------------------|--------------|----------------------| +| Chart tiles | MBTiles | 500 MB – 5 GB | +| GRIB weather | GRIB2 files | 50 – 500 MB | +| Tide harmonics | SQLite table | ~10 MB | +| Logbook / tracks | SQLite | ~1 MB/year | +| Boat profiles | SQLite | <1 MB | +| Routes / waypoints | SQLite | <1 MB | +| Settings | SharedPrefs / UserDefaults | <100 KB | + +**Cloud sync strategy:** +- Sync logbook, routes, waypoints, boat profiles, and settings. +- Do NOT sync charts or GRIB data (too large, user downloads per-region). +- Conflict resolution: last-write-wins with device ID tiebreaker; logbook entries are append-only (no conflicts). +- Sync protocol: RESTful API with delta payloads; background sync on connectivity. +- Optional: WebDAV or self-hosted sync for privacy-conscious users. + +### 3.7 Hardware Integration + +**GPS:** +- Primary: device GPS (CoreLocation / Android FusedLocation). +- Secondary: external GPS via NMEA over TCP/UDP, Bluetooth, or USB serial. +- Fix rate: 1 Hz minimum; 5-10 Hz preferred for racing. + +**NMEA 0183/2000 integration:** + +``` + ┌───────────────────┐ ┌──────────────────┐ + │ NMEA Instruments │ │ WiFi/BT NMEA │ + │ (wind, depth, │────────►│ Gateway │ + │ speed, compass) │ wired │ (e.g. Yacht │ + └───────────────────┘ │ Devices, iKonvert│ + │ Digital Yacht) │ + └────────┬─────────┘ + │ TCP/UDP + ▼ + ┌──────────────────────┐ + │ NMEA Parser Module │ + │ ─────────────────── │ + │ $WIMWV → Wind │ + │ $GPGGA → Position │ + │ $HCHDG → Heading │ + │ $SDDBT → Depth │ + │ $VWVHW → Speed │ + │ $GPRMB → Nav info │ + │ !AIVDM → AIS │ + └──────────┬───────────┘ + │ + ▼ + ┌──────────────────────┐ + │ Sensor Fusion │ + │ & Smoothing │ + └──────────────────────┘ +``` + +**Supported NMEA sentences (priority):** + +| Sentence | Data | Priority | +|----------|---------------------|----------| +| GGA/GLL | GPS position | P0 | +| RMC | Position + SOG/COG | P0 | +| MWV | Wind angle/speed | P0 | +| HDG/HDM | Heading | P0 | +| DBT/DPT | Depth | P1 | +| VHW | Boat speed/heading | P1 | +| VDM/VDO | AIS messages | P1 | +| XTE | Cross-track error | P2 | +| MTA/MMB | Air temp / pressure | P2 | +| RSA | Rudder angle | P3 | + +### 3.8 UI Framework & Visualization + +**Rendering stack:** +- **Charts:** MapLibre GL Native (iOS/Android) for GPU-accelerated vector tile rendering. +- **Instruments:** Custom canvas/Skia-rendered gauges (avoid DOM/layout overhead). +- **Weather overlay:** Particle animation (wind flow) + contour fill (pressure) rendered as GL overlay. +- **Performance dials:** Custom circular gauge widgets with polar target arcs. + +**Layout modes:** + +``` +┌─────────────────────────────────────────────┐ +│ NAVIGATION MODE │ +│ ┌─────────────────────────┬──────────────┐ │ +│ │ │ Wind: 15kt │ │ +│ │ │ TWA: 45° │ │ +│ │ CHART VIEW │ BSP: 6.2kt │ │ +│ │ (routes, AIS, tides) │ VMG: 4.4kt │ │ +│ │ │ Depth: 12m │ │ +│ │ │ COG: 225°T │ │ +│ ├─────────────────────────┴──────────────┤ │ +│ │ [MOB] [Anchor] [Route] [Weather] │ │ +│ └────────────────────────────────────────┘ │ +└─────────────────────────────────────────────┘ + +┌─────────────────────────────────────────────┐ +│ INSTRUMENT MODE │ +│ ┌───────────┬───────────┬────────────────┐ │ +│ │ WIND │ COMPASS │ BOAT SPEED │ │ +│ │ ◯ dial │ ◯ rose │ ◯ dial │ │ +│ │ AWS TWS │ HDG COG │ BSP SOG │ │ +│ ├───────────┼───────────┼────────────────┤ │ +│ │ VMG │ DEPTH │ POLAR % │ │ +│ │ 4.4 kt │ 12.3 m │ 94% │ │ +│ ├───────────┴───────────┴────────────────┤ │ +│ │ [MOB] [Anchor] [Route] [Weather] │ │ +│ └────────────────────────────────────────┘ │ +└─────────────────────────────────────────────┘ +``` + +### 3.9 External API Integration Layer + +**Design:** All external data access goes through an integration layer with: +- Retry logic with exponential backoff. +- Response caching with configurable TTL. +- Offline fallback to cached data with staleness indicator. +- Provider abstraction (swap weather sources without touching business logic). + +``` +┌──────────────────────────────────────────┐ +│ API Integration Layer │ +├──────────────────────────────────────────┤ +│ ┌────────────┐ ┌────────────────────┐ │ +│ │ Rate │ │ Cache Manager │ │ +│ │ Limiter │ │ (TTL, staleness) │ │ +│ └──────┬─────┘ └─────────┬──────────┘ │ +│ │ │ │ +│ ┌──────┴──────────────────┴──────────┐ │ +│ │ Provider Adapters │ │ +│ │ ┌──────┐ ┌──────┐ ┌───────────┐ │ │ +│ │ │ NOAA │ │Windy │ │OpenWeather│ │ │ +│ │ │ │ │ │ │ │ │ │ +│ │ └──────┘ └──────┘ └───────────┘ │ │ +│ └────────────────────────────────────┘ │ +└──────────────────────────────────────────┘ +``` + +--- + +## 4. Technical Boating Features + +### 4.1 Real-time Wind Visualization and Laylines + +**Wind field rendering:** +- Animated particle flow showing wind direction and relative speed across the chart. +- Color gradient encodes wind speed (Beaufort scale palette). +- Particle density increases with wind strength. + +**Layline computation:** + +``` + WIND (TWD) + │ + │ + ╱ │ ╲ + ╱ TWA │ TWA ╲ + ╱ (opt) │ (opt) ╲ + ╱ │ ╲ + Port layline │ Starboard layline + ╲ │ ╱ + ╲ │ ╱ + ╲ │ ╱ + ╲ │ ╱ + ╲ │ ╱ + ╲ │ ╱ + ╲ │ ╱ + ╲│╱ + MARK / WP +``` + +- Laylines computed from optimal VMG angles at current TWS (from polars). +- Adjusted for current set/drift. +- Displayed as semi-transparent cones on chart overlay. +- Tack/gybe point suggested where layline intersects course to waypoint. + +### 4.2 Tide/Current Predictions and Overlays + +**Tide height display:** +- Tide curve graph for selected station (24h view with current time marker). +- High/low predictions with times. +- Color-coded depth on chart adjusts for tide height relative to chart datum. + +**Tidal current overlay:** +- Animated arrows on chart showing current direction and speed. +- Arrow length/color proportional to current strength. +- Time-scrubbing: user can slide a time bar to see predicted currents at future times. +- Current vectors used in route ETA calculation and weather routing. + +**Computation:** Harmonic analysis using on-device tidal constituent databases (NOAA, UKHO). No network required after initial download. + +### 4.3 Waypoint and Route Management + +**Waypoint properties:** + +| Field | Type | Notes | +|----------------|----------|-------------------------------| +| Name | String | User-editable label | +| Position | LatLon | WGS-84 | +| Symbol | Enum | IHO-compatible icon set | +| Arrival radius | Float(m) | Triggers waypoint arrival | +| Notes | Text | Free-form | +| Created | DateTime | Auto-set | + +**Route features:** +- Ordered waypoint list with per-leg distance, bearing (true/magnetic), and ETA. +- Drag-to-reorder and drag-to-insert intermediate waypoints. +- Route statistics: total distance, estimated time (at configurable speed or from polars + weather). +- Import/export: GPX, KML. +- Reverse route (one tap). + +**Distance/bearing engine:** +- Vincenty inverse formula for accuracy on all distances. +- Rhumb line and great circle options. +- Automatic magnetic variation from WMM (World Magnetic Model) coefficients. + +### 4.4 Boat Performance Metrics + +**Instrument data flow:** + +``` + NMEA / GPS sensors + │ + ▼ + ┌──────────────┐ + │ Raw data │ + │ buffer │ ← 1-10 Hz input + └──────┬───────┘ + │ + ▼ + ┌──────────────┐ + │ Damping & │ ← Configurable: 1s, 3s, 10s, 30s + │ smoothing │ + └──────┬───────┘ + │ + ▼ + ┌──────────────┐ + │ Derived │ ← True wind, VMG, leeway, current, polar % + │ calculations│ + └──────┬───────┘ + │ + ▼ + ┌──────────────┐ + │ UI display │ ← Instruments, chart overlays, alerts + │ + logging │ + └──────────────┘ +``` + +**Damping:** Exponential moving average with user-configurable time constant. Racing mode uses shorter damping; cruising mode uses longer for stability. + +### 4.5 Polar Performance Diagrams + +**Polar diagram display:** + +``` + 0° (head to wind) + │ + │ No-sail zone + 315°──┼──045° + ╱ │ ╲ + ╱ ┌───┼───┐ ╲ + 270° │ │ │ 090° + ╲ │ │ │ ╱ + ╲ └───┼───┘ ╱ + 225°──┼──135° + │ + 180° (dead downwind) + + ── Polar curve at current TWS + -- Target BSP at each TWA + • Current boat position on polar +``` + +**Features:** +- Display polar diagram with target curve for current TWS. +- Interpolate between stored TWS values. +- Show current BSP/TWA as a dot on the polar. +- Highlight optimal VMG angles (upwind and downwind). +- Polar % shown as percentage of target at current TWA. +- Support user-editable polar tables or import from ORC/manufacturer data. + +### 4.6 MOB (Man Overboard) Quick Activation + +- **Activation:** Single tap on persistent on-screen MOB button (minimum 60×60pt touch target, high-contrast red). +- **Immediate actions:** + 1. Record GPS position at moment of activation. + 2. Sound continuous alarm. + 3. Switch display to MOB navigation view. + 4. Start elapsed timer. + 5. Log event to logbook. +- **MOB navigation view:** + - Large bearing arrow pointing to MOB position. + - Distance in meters/feet (auto-scales). + - Elapsed time since MOB. + - Current position and MOB position on chart. + - Wind and current conditions at time of event. +- **Recovery:** Explicit "Recovered" confirmation required to exit MOB mode. + +### 4.7 Anchor Alarm and Watch Circle + +**Configuration:** +- Drop anchor position: auto (GPS at time of set) or manual (tap on chart). +- Watch circle radius: user-configurable (default: calculated from scope × depth + freeboard). +- Alert threshold: distance from anchor position exceeding radius. + +**Monitoring:** +- Continuous GPS monitoring at configurable interval (default: 10s, high-accuracy mode: 1s). +- Displays current swing radius on chart as a circle overlay. +- Historical track shows boat movement around anchor. +- Alert escalation: visual → audible → persistent notification (survives app background/screen lock). + +**Anchor scope calculator:** + +``` + Scope = Chain/Rode Out ÷ (Depth + Freeboard) + + Input: Depth (from sounder or manual), Freeboard (from boat profile) + Recommended: 5:1 chain, 7:1 mixed rode + Watch circle radius = Rode Out × cos(asin((Depth + Freeboard) / Rode Out)) +``` + +### 4.8 Trip Logging and Electronic Logbook + +**Automatic entries (system-generated):** +- Track recording: continuous GPS track at configurable interval (5s – 60s). +- Hourly log: position, SOG, COG, wind, barometer, depth (if available). +- Event log: route activation, waypoint arrival, anchor set/weigh, MOB, alarms. + +**Manual entries:** +- Sail changes, engine on/off, weather observations, crew notes. +- Photo attachment (geo-tagged). + +**Log format:** + +| Time (UTC) | Position | SOG | COG | Wind | Baro | Depth | Event / Notes | +|------------|-----------------|-----|-----|----------|-------|-------|------------------------| +| 08:00 | 41°23.4N 71°12.1W | 6.2 | 225 | 15kt SW | 1018 | 14m | Departed slip | +| 09:00 | 41°18.7N 71°08.3W | 5.8 | 210 | 18kt SW | 1017 | 22m | Full main + jib | +| 09:15 | 41°17.2N 71°07.1W | 6.5 | 195 | 20kt SW | 1016 | 28m | Reef #1 main | + +**Export:** CSV, GPX (track), PDF (formatted logbook page). + +### 4.9 True/Magnetic Heading Conversion + +- World Magnetic Model (WMM) coefficients stored on-device (updated annually). +- Auto-compute magnetic variation for any position and date. +- All headings displayed with user preference: True (°T), Magnetic (°M), or both. +- Compass rose on chart rotates to show magnetic north offset. +- All NMEA headings tagged as magnetic are auto-converted using local variation. + +### 4.10 Night Vision Mode + +- Single-tap toggle from any screen. +- Color scheme: red-on-black (preserves night adaptation). +- All chart colors remapped to red spectrum. +- Screen brightness reduced (app-controlled dimming below OS minimum). +- Instrument displays switch to red numerals on black background. +- No white flashes from notifications or overlays. +- Chart light symbols (Fl, Iso, Oc, etc.) rendered with visible flash patterns on dark background. + +--- + +## 5. System Architecture + +### 5.1 Platform Stack + +| Layer | Technology | +|---------------|------------------------------------------------------| +| Mobile UI | Kotlin Multiplatform (Android) + Swift (iOS) | +| Chart engine | MapLibre GL Native (shared C++ core) | +| Local DB | SQLite (via SQLDelight / GRDB) | +| Chart storage | MBTiles (SQLite-backed tile packages) | +| Weather | Custom GRIB2 decoder (Rust/C FFI for performance) | +| Networking | Ktor (KMP) / URLSession (iOS) | +| Background | WorkManager (Android) / BGTaskScheduler (iOS) | +| Web (future) | Kotlin/JS or separate PWA consuming same API layer | + +**Rationale:** Native per-platform for performance-critical operations (chart rendering, GRIB decoding, GPS). Shared business logic via Kotlin Multiplatform where feasible. + +### 5.2 Backend Services + +``` +┌──────────────────────────────────────────────┐ +│ Cloud Backend │ +│ ┌──────────────┐ ┌──────────────────────┐ │ +│ │ Auth / User │ │ Sync API │ │ +│ │ Service │ │ (routes, logs, prefs)│ │ +│ └──────────────┘ └──────────────────────┘ │ +│ ┌──────────────┐ ┌──────────────────────┐ │ +│ │ Chart Index │ │ Weather Proxy / │ │ +│ │ & Download │ │ GRIB Distribution │ │ +│ └──────────────┘ └──────────────────────┘ │ +│ ┌──────────────────────────────────────┐ │ +│ │ Push Notification Service │ │ +│ └──────────────────────────────────────┘ │ +└──────────────────────────────────────────────┘ +``` + +- **Auth:** OAuth 2.0 / email+password. Optional — app is fully functional without account. +- **Sync API:** REST with JSON delta payloads. Supports offline queue with conflict resolution. +- **Chart index:** Catalog of available chart regions with version metadata. Client downloads tiles directly (CDN-backed). +- **Weather proxy:** Aggregates GRIB data from multiple sources; serves cropped/subsetted GRIB files for requested regions to minimize bandwidth. +- **Push notifications:** Weather alerts, anchor drag (if device loses connectivity, companion device can alert). + +### 5.3 Offline-First Data Model + +**Principle:** Every core feature works without connectivity. Online access enhances but never gates functionality. + +| Feature | Offline capability | Online enhancement | +|----------------------|--------------------------------------------------------|-------------------------------------| +| Chart display | Pre-downloaded chart tiles | On-demand tile streaming | +| Navigation | Full waypoint/route with GPS | — | +| Weather | Last downloaded GRIB (with staleness warning) | Fresh GRIB download | +| Tides | Full harmonic prediction (no network needed) | — | +| Performance | Full (all computation is local) | — | +| Safety (MOB, anchor) | Full (GPS-only) | — | +| Logbook | Full recording; sync queued for later | Real-time cloud backup | +| AIS | Via NMEA hardware receiver | Internet AIS feed | + +### 5.4 Hardware Sensor Integration Strategy + +**Abstraction layer:** `SensorProvider` interface with implementations for: +1. Device GPS (built-in). +2. Device compass/accelerometer (built-in). +3. NMEA TCP/UDP (WiFi multiplexer — e.g., Yacht Devices, Vesper, Digital Yacht). +4. NMEA Bluetooth (Bluetooth serial adapters). +5. Signal K (JSON-based open marine data protocol over WebSocket). + +**Priority / fallback chain:** +``` +NMEA instrument data (highest precision) + └─► Signal K server + └─► Device built-in sensors (GPS, compass, barometer) + └─► Manual entry / last known (lowest priority) +``` + +**Sensor fusion:** When multiple sources provide the same data (e.g., GPS from device + NMEA), use highest-priority source with automatic fallback on signal loss. + +### 5.5 Cloud Synchronization Approach + +``` + Device A (phone) Cloud Device B (tablet) + ┌──────────────┐ ┌──────────┐ ┌──────────────┐ + │ Local SQLite │──── push ──────►│ Sync API │◄─── push ───│ Local SQLite │ + │ │◄─── pull ───────│ │──── pull ───►│ │ + └──────────────┘ └──────────┘ └──────────────┘ +``` + +- **Sync granularity:** Per-entity (route, waypoint, log entry, setting). +- **Conflict strategy:** Last-write-wins using monotonic device clocks + server timestamp. +- **Append-only entities:** Logbook entries, track points — no conflicts possible. +- **Queue:** Offline changes queued in local `sync_outbox` table; drained on connectivity. +- **Bandwidth budget:** Sync payloads are JSON deltas — typically < 10 KB per sync cycle. + +--- + +## 6. Data Model Essentials + +### 6.1 Key Entities + +``` +┌─────────────┐ ┌──────────────┐ ┌───────────────┐ +│ Route │1────*│ Waypoint │ │ BoatProfile │ +├─────────────┤ ├──────────────┤ ├───────────────┤ +│ id │ │ id │ │ id │ +│ name │ │ route_id(FK) │ │ name │ +│ created_at │ │ seq_order │ │ hull_type │ +│ updated_at │ │ lat │ │ loa │ +│ total_dist │ │ lon │ │ beam │ +│ notes │ │ name │ │ draft │ +└─────────────┘ │ arrival_rad │ │ displacement │ + │ symbol │ │ freeboard │ + │ notes │ │ polar_data │ + └──────────────┘ └───────────────┘ + +┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ +│ BoatPosition │ │ WeatherData │ │ PerformanceLog │ +├──────────────────┤ ├──────────────────┤ ├──────────────────┤ +│ id │ │ id │ │ id │ +│ timestamp │ │ timestamp │ │ timestamp │ +│ lat │ │ lat │ │ position_id(FK) │ +│ lon │ │ lon │ │ bsp │ +│ sog │ │ tws │ │ vmg │ +│ cog │ │ twd │ │ polar_pct │ +│ hdg_true │ │ pressure_hpa │ │ heel_deg │ +│ hdg_mag │ │ wave_height_m │ │ leeway_deg │ +│ depth_m │ │ wave_period_s │ │ current_set │ +│ source (enum) │ │ wave_dir │ │ current_drift │ +│ fix_quality │ │ temp_c │ │ twa │ +└──────────────────┘ │ source (enum) │ │ tws │ + │ model_run │ │ aws │ + └──────────────────┘ │ awa │ + └──────────────────┘ + +┌──────────────────┐ ┌──────────────────┐ +│ LogEntry │ │ AnchorWatch │ +├──────────────────┤ ├──────────────────┤ +│ id │ │ id │ +│ trip_id(FK) │ │ anchor_lat │ +│ timestamp │ │ anchor_lon │ +│ position_id(FK) │ │ radius_m │ +│ type (enum) │ │ set_time │ +│ text │ │ depth_at_set │ +│ auto_generated │ │ rode_out_m │ +│ photo_path │ │ active │ +└──────────────────┘ └──────────────────┘ +``` + +### 6.2 Real-time Streaming vs Historical Storage + +| Data Class | Real-time Buffer | Historical Storage | +|-------------------|-------------------------------------|-------------------------------------------| +| GPS position | Ring buffer, last 60s at full rate | Downsampled to 5s–60s intervals in SQLite | +| Instrument data | Ring buffer, last 60s | Hourly averages in PerformanceLog | +| Weather grid | In-memory GRIB slice for current t | Full GRIB files on disk (last 3 downloads)| +| AIS targets | In-memory map (MMSI → last report) | Not stored (ephemeral) | +| Tide predictions | Computed on-demand | Harmonic constants are static reference | + +### 6.3 Data Freshness and Caching Strategy + +| Data | TTL / Freshness Rule | Staleness Indicator | +|--------------------|--------------------------------------------------------|----------------------------------| +| GRIB weather | Valid until model run + forecast hour; stale after | Yellow "outdated" badge on chart | +| Tide harmonics | Valid for calendar year (annual coefficient update) | — | +| Chart tiles | Valid until chart edition update (check weekly) | "Update available" on chart menu | +| AIS positions | Stale after 5 min (class A) / 30 min (class B) | Target fades on chart | +| GPS fix | Stale after 10s (lost fix) | Red "No GPS" warning bar | +| NMEA instruments | Stale after 5s (no data) | Dashes (--) replace values | + +--- + +## 7. External Integrations + +### 7.1 Weather APIs + +| Provider | Data | Format | Cost Model | Notes | +|----------------|-------------------------|--------|--------------------|---------------------------------| +| NOAA (GFS) | Global wind, pressure | GRIB2 | Free | 0.25° resolution, 6h updates | +| ECMWF (open) | Global wind, pressure | GRIB2 | Free (open data) | 0.1° resolution, 6h updates | +| Windy API | Multi-model access | JSON | Paid (per request) | Good fallback, easy integration| +| OpenWeather | Point forecasts | JSON | Freemium | Useful for simple point lookups| +| NOAA NDBC | Buoy observations | Text | Free | Real-time buoy data | + +**Strategy:** Primary: NOAA GFS (free, GRIB2). Secondary: ECMWF open data. Fallback: Windy API for regions with poor GFS coverage. + +### 7.2 Chart Data Sources + +| Source | Coverage | Format | License | +|---------------------|-----------------|--------------|------------------| +| NOAA ENC | US waters | S-57 | Public domain | +| OpenSeaMap | Global | Vector tiles | ODbL | +| Navionics (license) | Global | Proprietary | Commercial | +| LINZ | New Zealand | S-57 | CC BY 4.0 | +| BSH | Germany | S-57 | Government | + +**Strategy:** Ship with NOAA ENC + OpenSeaMap. Offer Navionics integration as premium add-on. + +### 7.3 AIS Feeds + +- **Hardware:** NMEA-connected AIS receiver (preferred — works offline). +- **Internet:** AIS APIs (MarineTraffic, AISHub) for supplemental coverage when online. +- **Display:** AIS targets rendered on chart with MMSI, vessel name, SOG/COG vector, CPA/TCPA. + +### 7.4 GPS / NMEA Protocols + +| Protocol | Transport | Use Case | +|--------------|------------------|-------------------------------------------| +| NMEA 0183 | TCP/UDP/serial | Legacy instruments (most common) | +| NMEA 2000 | CAN bus → gateway| Modern instrument buses | +| Signal K | WebSocket (JSON) | Open-source boat data server | +| GPX import | File | Route/waypoint exchange | + +--- + +## 8. UX Principles + +### 8.1 Glance-able Critical Information + +- **Primary data** (SOG, COG, depth, wind) visible without any interaction. +- **Font sizing:** minimum 24pt for primary values; 18pt for secondary. +- **Color coding:** depth alarm = red, normal = green/white, stale data = yellow. +- **No modals during navigation** — all alerts are non-blocking banners (except MOB). + +### 8.2 Minimal Taps While Underway + +| Action | Max taps | Notes | +|----------------------------|----------|--------------------------------------| +| View current conditions | 0 | Always visible | +| Activate MOB | 1 | Persistent button | +| Set anchor alarm | 2 | Long-press position → set radius | +| Check next waypoint | 0 | Shown in nav bar | +| Switch day/night mode | 1 | Toggle button | +| View tide at current pos | 1 | Tap tide icon | +| Log a note | 2 | Quick-entry with voice option | + +### 8.3 High-Contrast Readability + +- **Day mode:** Dark text on light background; chart uses standard ECDIS color scheme. +- **Dusk mode:** Reduced brightness, muted colors. +- **Night mode:** Red on black, no blue/white light sources. +- **Sunlight testing:** All UI elements must pass WCAG AAA contrast ratio (7:1) in day mode. + +### 8.4 Touch Optimization for Wet/Gloved Hands + +- Minimum touch target: 60×60pt (larger than standard 44pt). +- Generous spacing between interactive elements (minimum 16pt gap). +- No swipe-only gestures for critical functions — always provide tap alternative. +- Support for hardware buttons (volume keys) as configurable shortcuts (e.g., MOB, mark waypoint). +- Edge gestures disabled in navigation mode to prevent accidental OS navigation. + +--- + +## 9. Constraints & Considerations + +### 9.1 Bandwidth & Connectivity + +| Scenario | Expected bandwidth | Strategy | +|-------------------|--------------------|-----------------------------------------------| +| Harbor WiFi | 1-10 Mbps | Bulk download charts, GRIB, updates | +| Coastal cellular | 100 Kbps – 5 Mbps | Incremental GRIB, sync, AIS feed | +| Offshore (none) | 0 | Full offline; queue sync for later | +| Satellite (Iridium)| 2.4 Kbps | Text-only weather (GRIB subset), position reports| + +**GRIB bandwidth optimization:** +- Request only needed parameters (wind, pressure — skip temperature, clouds if not needed). +- Crop to planned route corridor + 200nm buffer. +- Typical offshore GRIB: 200 KB – 2 MB (manageable on satellite with patience). + +### 9.2 Battery Life + +**Target:** 24+ hours of continuous navigation on a full charge (modern smartphone). + +| Optimization | Impact | +|-------------------------------------------|-----------| +| GPS polling rate: 1 Hz normal, 5 Hz race | High | +| Screen brightness: user-controlled dimming| High | +| Chart rendering: cache rendered tiles | Medium | +| GRIB decode: on-demand, not continuous | Medium | +| Network: batch requests, no polling | Medium | +| Background: limit to anchor alarm + track | Low-Med | + +**Power modes:** +- **Full:** All features active. ~6-8h screen-on. +- **Economy:** Reduced GPS rate (0.2 Hz), no weather animation, dimmed screen. ~16-24h. +- **Anchor watch:** Screen off, GPS at 0.1 Hz, wake on alarm. ~48-72h. + +### 9.3 Screen Visibility + +- Support for both OLED and LCD displays. +- Day mode uses maximum contrast; no subtle gradients. +- Night mode: pure black background (#000000) on OLED saves power and reduces glare. +- Anti-glare: avoid white backgrounds that reflect sunlight; prefer dark/medium chart backgrounds. +- User-adjustable brightness independent of OS brightness. + +### 9.4 Reliability & Safety-Critical Fail-Safes + +- **No single point of failure for position:** Device GPS + optional external GPS. +- **MOB button always accessible:** Rendered above all other UI layers; not dismissible. +- **Anchor alarm survives:** app background, screen lock, low-battery mode, OS memory pressure. +- **Watchdog:** Background process monitors GPS feed; alerts if fix lost for > 30s while underway. +- **Data integrity:** SQLite WAL mode; logbook writes are atomic. +- **Disclaimer:** App is an aid to navigation, not a replacement for proper seamanship, paper charts, and official publications. Displayed prominently at first launch and in About screen. + +### 9.5 Data Privacy & Local Storage + +- **Default local:** All data stored on device. Cloud sync is opt-in. +- **No telemetry of position data** without explicit consent. +- **Track data:** Stays on device unless user explicitly exports or syncs. +- **Account optional:** App is fully functional without creating an account. +- **Self-host option:** Publish sync server specification so users can run their own. +- **Data export:** Users can export all their data (routes, logs, tracks) at any time in open formats (GPX, CSV, JSON). + +--- + +## 10. Phased Roadmap + +### Phase 1 — Foundation (Months 1–4) + +| Deliverable | Priority | +|------------------------------------|----------| +| Chart display (NOAA ENC + OpenSeaMap) | P0 | +| GPS navigation (position, SOG, COG) | P0 | +| Waypoint & route management | P0 | +| Basic instrument display | P0 | +| MOB alarm | P0 | +| Anchor alarm | P0 | +| Day/night mode | P1 | +| GPX import/export | P1 | + +### Phase 2 — Weather & Tides (Months 5–7) + +| Deliverable | Priority | +|--------------------------------------|----------| +| GRIB weather download & display | P0 | +| Wind overlay on chart | P0 | +| Tide predictions (harmonic) | P0 | +| Tidal current overlay | P1 | +| Barometric pressure trend | P1 | +| Offline GRIB storage & staleness | P0 | + +### Phase 3 — Performance & Routing (Months 8–10) + +| Deliverable | Priority | +|--------------------------------------|----------| +| NMEA 0183 integration (TCP/UDP) | P0 | +| True wind calculation | P0 | +| Polar diagram display | P0 | +| VMG / polar % instruments | P0 | +| Layline rendering | P1 | +| Isochrone weather routing | P1 | +| Signal K integration | P2 | + +### Phase 4 — Logbook & Polish (Months 11–13) + +| Deliverable | Priority | +|--------------------------------------|----------| +| Trip logbook (auto + manual) | P0 | +| Track recording & playback | P0 | +| Cloud sync (opt-in) | P1 | +| AIS display (hardware + internet) | P1 | +| CPA/TCPA alerts | P1 | +| PDF logbook export | P2 | +| Compass/heading instrument | P0 | + +### Phase 5 — Advanced & Optimization (Months 14+) + +| Deliverable | Priority | +|--------------------------------------|----------| +| NMEA 2000 via gateway | P1 | +| Navionics chart integration | P2 | +| Satellite weather (Iridium GRIB) | P2 | +| Apple Watch / Wear OS companion | P2 | +| Web dashboard (trip review) | P3 | +| Voice commands for logbook entries | P3 | +| Battery economy mode | P1 | + +--- + +*This document focuses exclusively on sailing/navigation technical features. Social features (crew networking, race communities, marina reviews) are explicitly out of scope.* diff --git a/.agent/mission.md b/.agent/mission.md new file mode 100644 index 0000000..dc89364 --- /dev/null +++ b/.agent/mission.md @@ -0,0 +1,13 @@ +# Project Mission & Strategic Values + +## 1. Core Mission +**One Screen, Dock to Dock.** A unified bridge instrument, weather advisor, and safety system for sailors. + +## 2. Strategic Values +- **No Social:** Purely technical boating features; no community or social components. +- **Offline Integrity:** Full charting and routing must work offshore. +- **Single Pane of Glass:** Weather, charts, and instruments on one unified view. + +## 3. Agent Personality & Role +- **Proactive Navigator:** Anticipate technical needs (weather updates, safety checks). +- **Precision & Clarity:** Scientific/technical accuracy in boating data. diff --git a/.agent/narrative.md b/.agent/narrative.md new file mode 100644 index 0000000..567c343 --- /dev/null +++ b/.agent/narrative.md @@ -0,0 +1,36 @@ + +--- 2026-03-12T08:04:16Z --- +Write a high level component design doc for a full featured sailing companion app. Include comparisons to existing apps, focusing on technical boating features with no social components + +--- 2026-03-13T07:09:49Z --- +Create a task for each deliverable in docs/COMPONENT_DESIGN.md + +--- 2026-03-13T07:10:09Z --- +Create a claudomator task for each deliverable in docs/COMPONENT_DESIGN.md + +--- 2026-03-13T07:10:36Z --- +Create a claudomator task for each deliverable in docs/COMPONENT_DESIGN.md + +--- 2026-03-13T23:55:54Z --- +request necessary android permissions + +--- 2026-03-13T23:56:25Z --- +request necessary android permissions + +--- 2026-03-13T23:56:30Z --- +request necessary android permissions + +--- 2026-03-14T00:04:22Z --- +Request necessary android permissions + +--- 2026-03-14T00:06:44Z --- +Request necessary android permissions + +--- 2026-03-15T07:42:37Z --- +warning: Kapt support in Moshi Kotlin Code Gen is deprecated and will be removed in 2.0. Please migrate to KSP. https://github.com/square/moshi#codegen + +--- 2026-03-15T07:43:23Z --- +warning: Kapt support in Moshi Kotlin Code Gen is deprecated and will be removed in 2.0. Please migrate to KSP. https://github.com/square/moshi#codegen + +--- 2026-03-15T09:10:59Z --- +warning: Kapt support in Moshi Kotlin Code Gen is deprecated and will be removed in 2.0. Please migrate to KSP. https://github.com/square/moshi#codegen diff --git a/.agent/preferences.md b/.agent/preferences.md new file mode 100644 index 0000000..7ca21d6 --- /dev/null +++ b/.agent/preferences.md @@ -0,0 +1,7 @@ +# User Preferences & Workflow Quirks + +Living record of user preferences for the Nav project. + +## 1. Interaction & Workflow +- **Safety First:** Cautious and deliberate action. +- **Checkpoint Model:** Research -> Strategy -> GO. diff --git a/.agent/worklog.md b/.agent/worklog.md new file mode 100644 index 0000000..e17781b --- /dev/null +++ b/.agent/worklog.md @@ -0,0 +1,141 @@ +# SESSION_STATE.md + +## Current Task Goal +Section 7.3 AIS display — COMPLETE (2026-03-15): AIS integrated into ViewModel, MapFragment, and MainActivity + +## Verified (2026-03-15) +- All 41 tests GREEN: 22 GPS/NMEA + 16 AIS + 3 ViewModel AIS (via /tmp/ais-vm-test-runner/) +- NmeaParser extended with MWV (wind), DBT (depth), HDG/HDM (heading) parsers +- Sensor data classes added: WindData, DepthData, HeadingData +- NmeaStreamManager added for TCP stream management + +## Completed Items + +### [APPROVED] GpsPosition data class +- File: `app/src/main/kotlin/org/terst/nav/gps/GpsPosition.kt` +- Package: `org.terst.nav.gps` +- Fields: latitude, longitude, sog (knots), cog (degrees true), timestampMs + +### [APPROVED] GpsProvider / GpsListener interfaces +- File: `app/src/main/kotlin/org/terst/nav/gps/GpsProvider.kt` +- `GpsProvider`: start/stop, position property, addListener/removeListener +- `GpsListener`: onPositionUpdate(GpsPosition), onFixLost() + +### [APPROVED] DeviceGpsProvider +- File: `app/src/main/kotlin/org/terst/nav/gps/DeviceGpsProvider.kt` +- Wraps `LocationManager` with `GPS_PROVIDER` +- Default interval: 1000ms (1 Hz); configurable via constructor +- SOG: Location.speed (m/s) × 1.94384 → knots +- COG: Location.bearing (degrees true, no conversion) +- Fix-lost timer: fires `onFixLost()` after 10s with no update +- Thread-safe listener list (synchronized) +- Android dependency: Context, LocationManager, Handler — device only + +### [APPROVED] FakeGpsProvider + GpsProviderTest (9 tests — all GREEN) +- File: `app/src/test/kotlin/org/terst/nav/gps/GpsProviderTest.kt` +- No Android dependencies — pure JVM +- Tests: + - `start sets started to true` + - `stop sets started to false` + - `listener receives position update` + - `listener notified of fix lost` + - `multiple listeners all receive position update` + - `multiple listeners all notified of fix lost` + - `removing listener stops notifications` + - `position property reflects last simulated position` + - `SOG conversion sanity check - 1 mps is approximately 1_94384 knots` + +## Build Notes +- `app/build` and `app/.kotlin/sessions` are root-owned from a prior run. + Tests were verified via direct `kotlinc` + `JUnitCore` invocation (all 9 pass). + Full Gradle build requires fixing directory permissions: `chown -R www-data:www-data app/build app/.kotlin` +- Pre-existing XML layout error in `activity_main.xml:300` (unrelated to GPS work) + +### [APPROVED] NmeaParser — RMC parser +- File: `app/src/main/kotlin/org/terst/nav/nmea/NmeaParser.kt` +- Parses any `*RMC` sentence (GP, GN, etc.) +- Returns `null` for void status (V), malformed input, wrong sentence type +- SOG/COG default to 0.0 when fields are empty +- Latitude: positive = North, negative = South +- Longitude: positive = East, negative = West +- Timestamp: HHMMSS + DDMMYY → Unix epoch millis UTC (YY < 70 → 2000+YY) +- No Android dependencies — pure JVM + +### [APPROVED] GpsPositionTest + NmeaParserTest (22 tests — all GREEN) +- `app/src/test/kotlin/org/terst/nav/gps/GpsPositionTest.kt` (2 tests) +- `app/src/test/kotlin/org/terst/nav/nmea/NmeaParserTest.kt` (11 tests) +- `app/src/test/kotlin/org/terst/nav/gps/GpsProviderTest.kt` (9 tests, pre-existing) +- All verified via direct `kotlinc` (1.9.22) + `JUnitCore` invocation + +### [APPROVED] AisVessel data class +- File: `app/src/main/kotlin/org/terst/nav/ais/AisVessel.kt` +- Package: `org.terst.nav.ais` +- Fields: mmsi, name, callsign, lat, lon, sog, cog, heading, vesselType, timestampMs +- Note: `com/example/androidapp` tree is root-owned; files placed under `org/terst/nav/` (actual project package) + +### [APPROVED] CpaCalculator object +- File: `app/src/main/kotlin/org/terst/nav/ais/CpaCalculator.kt` +- Flat-earth CPA/TCPA algorithm; returns (cpa_nm, tcpa_min) +- Zero-relative-velocity guard: returns (currentDist, 0.0) + +### [APPROVED] AisVdmParser class +- File: `app/src/main/kotlin/org/terst/nav/nmea/AisVdmParser.kt` +- Parses !AIVDM/!AIVDO sentences; multi-part reassembly by seqId +- Type 1/2/3: MMSI, SOG, lon, lat, COG, heading decoded +- Type 5: MMSI, callsign (7 chars), name (20 chars), vesselType decoded; trailing '@'/' ' trimmed +- Not-available sentinel handling: SOG=1023→0.0, COG=3600→0.0, lon=0x6791AC0→0.0, lat=0x3412140→0.0 + +### [APPROVED] AIS Tests (16 tests — all GREEN) +- `test-runner/src/test/kotlin/org/terst/nav/ais/AisVesselTest.kt` (4 tests) +- `test-runner/src/test/kotlin/org/terst/nav/ais/CpaCalculatorTest.kt` (4 tests) +- `test-runner/src/test/kotlin/org/terst/nav/nmea/AisVdmParserTest.kt` (8 tests) +- Verification harness: `/tmp/ais-test-runner/` (JUnit5, com.example.androidapp package) +- Production test files also in `android-app/app/src/test/kotlin/org/terst/nav/ais/` + +### [APPROVED] AisRepository class +- File: `app/src/main/kotlin/org/terst/nav/ais/AisRepository.kt` +- Upserts position targets by MMSI; merges type-5 static data (name/callsign/vesselType) +- Pending static map: holds type-5 data until position arrives for same MMSI +- `evictStale(nowMs)`: removes vessels older than `staleTimeoutMs` (default 10 min) +- `AisDataSource` interface (with Flow) defined in same file + +### [APPROVED] AisHubApiService + AisHubVessel +- File: `app/src/main/kotlin/org/terst/nav/ais/AisHubApiService.kt` +- Note: placed in `ais/` directory (writable) with package `org.terst.nav.data.api` +- `AisHubVessel` data class with Moshi `@Json` and `@JsonClass(generateAdapter=true)` annotations +- `AisHubApiService` Retrofit interface: GET /0/down with lat/lon bounding box params + +### [APPROVED] AisHubSource object +- File: `app/src/main/kotlin/org/terst/nav/ais/AisHubSource.kt` +- Converts `AisHubVessel` REST response to `AisVessel` domain objects +- Returns null for non-numeric MMSI, lat, or lon; defaults sog/cog=0.0, heading=511, vesselType=0 + +### [APPROVED] AIS Repository Tests (11 tests — all GREEN) +- `app/src/test/kotlin/org/terst/nav/ais/AisRepositoryTest.kt` (7 tests) +- `app/src/test/kotlin/org/terst/nav/ais/AisHubSourceTest.kt` (4 tests) +- Harness: `/tmp/ais-repo-test-runner/` (JUnit5, org.terst.nav package, stub annotations for offline build) + +### [APPROVED] Section 7.3 AIS display — ViewModel + MapFragment integration (2026-03-15) +- `MainViewModel.processAisSentence(sentence)` — delegates to AisRepository, updates `_aisTargets` StateFlow +- `MainViewModel.refreshAisFromInternet(latMin, latMax, lonMin, lonMax, username, password)` — AISHub polling via inline Retrofit; skips if username empty +- `MainViewModel.aisTargets: StateFlow>` — exposed to observers +- `AisRepository.ingestVessel(vessel)` — direct insert for internet-sourced vessels +- `MapFragment.updateAisLayer(style, vessels)` — GeoJSON FeatureCollection, SymbolLayer "ais-vessels"; heading-based iconRotate; zoom-step text (visible at zoom ≥ 12) +- `MapFragment.addShipArrowImage(style)` — rasterises ic_ship_arrow.xml into style +- `ic_ship_arrow.xml` — pink arrow vector drawable for AIS icons +- `MainActivity.startAisHardwareFeed(host, port)` — TCP stub reads !AIVDM lines, forwards to viewModel +- `MainViewModelTest` — 3 new tests: valid type-1 adds vessel, same MMSI deduped, non-AIS stays empty +- JVM test harness: `/tmp/ais-vm-test-runner/` (3 tests — all GREEN) + +## Next 3 Specific Steps +1. **CPA/TCPA alarms** — use CpaCalculator in ViewModel to emit alarm when CPA < threshold; add UI indicator in MapFragment +2. **AISHub periodic polling** — call refreshAisFromInternet() on a timer (e.g. every 60s) when GPS position is known +3. **AIS TCP full implementation** — replace stub socket reader with NmeaStreamManager integration + +## Scripts Added +- `test-runner/` — standalone Kotlin/JVM Gradle project; runs all 22 GPS/NMEA tests without Android SDK + - Command: `cd /workspace/nav/test-runner && GRADLE_USER_HOME=/tmp/gradle-home ./gradlew test` + +## Process Improvements +- Gradle builds blocked by Android SDK requirement; added `test-runner/` JVM-only subproject as reliable test runner +- All 22 tests verified GREEN via `test-runner/` JVM project (2026-03-14) \ No newline at end of file -- cgit v1.2.3