diff options
| author | Claude <noreply@anthropic.com> | 2026-05-26 07:12:44 +0000 |
|---|---|---|
| committer | Claude <noreply@anthropic.com> | 2026-05-26 07:12:44 +0000 |
| commit | 8c1d1605f529e32876ba4cb325a019a311c5011d (patch) | |
| tree | d983e88e63dd26a099143a5e71e6f356c7faeec5 | |
| parent | 8dbf3f883274fc0ddd16e5507f732629c85e3c91 (diff) | |
Update worklog: tack detection complete, storage complete, session prep
https://claude.ai/code/session_01YUbuZNDAoLea4cf9UGQ9qn
| -rw-r--r-- | .agent/worklog.md | 202 |
1 files changed, 65 insertions, 137 deletions
diff --git a/.agent/worklog.md b/.agent/worklog.md index 2d62bdb..6187ae5 100644 --- a/.agent/worklog.md +++ b/.agent/worklog.md @@ -1,152 +1,80 @@ # SESSION_STATE.md -## Backlog (fix later) +## Backlog -- **Pirate mode** — Re-introduce as an Easter egg / toggle, not the default voice. Long-press the trip report header (or a hidden gesture) flips the narrative into pirate dialect. Keep the seamanlike default; pirate is opt-in fun. +- **Pirate mode** — Easter egg / opt-in toggle, not the default voice. Long-press the trip report header flips the narrative into pirate dialect. Seamanlike voice stays default. +- **Race mode tack detection** — Tighter windows (T_SETTLE ~10–15 s), wider STAB_MAX (~30°), shorter MIN_GAP_MS (~20 s) for quick successive tacks at race starts and mark roundings. Current mode is CRUISING (conservative). See `TackDetector.kt` constants. +- **Persist tracks to Room** — Replace in-memory `_pastTracks` with a Room database. SAF write path is solid; the in-memory list is still the source of truth at runtime. +- **AnchorWatchHandler UI** — Re-integrate into `activity_main.xml` and wire to the Safety Dashboard. +- **Unit tests for trip generators** — `TripReportGenerator` and `PreTripReportGenerator` have no JVM tests yet. -- **Tack detection is buggy, especially at low speed** — False positives at low SOG (GPS heading noise looks like tacks). Need minimum-SOG gate (e.g. skip detection when SOG < 1.5 kt) and review the stability window / MIN_DELTA thresholds against real tracks. +--- + +## Paused Task: Instrument Sheet Visual Redesign + +**Started:** 2026-04-06 · **Status:** Tasks 1–2 done; Tasks 3–7 pending -## Current Task Goal -Logbook + Trip Report Improvements — COMPLETE (2026-05-26) +### What's being built +Full visual redesign of the instrument bottom sheet: +- `WaveView`: animated canvas divider (swell + wind waves + whitecaps), sky-blue above / ocean-blue below +- `DirectionArrowView`: 14dp inline chevron in two palettes (SKY grey / OCEAN blue) +- Direction arrows inline with all numeric values +- `°` baked into HDG/COG (no separate unit label) +- Forecast cells: value line 1, [arrow] bearing line 2 (swell adds period) +- Imperial units throughout (ft for depth, wave height, swell) +- Forecast labels: "Current" / "Waves" (no section header) +- Reports section removed; touch-through prevented -Delivered: -- **Add notes/photos to finished track** — `+ Add note` button in `TrackDetailSheet` opens a dialog with text entry, camera, and gallery. Notes are saved with `timestampMs = track.endMs` so they fall within the track window and appear in `buildLogEvents()` automatically. The map is re-built via `logEventAdapter.update()` after save. -- **Trip report single Nav voice** — Removed `NarrativeStyle` enum and the 4-style ChipGroup. `generateNarrative(summary)` now emits a concise `PASSAGE` header with date/time range, stats, conditions, and a timestamped deck log. `fragment_trip_report.xml` no longer has the style picker. -- **Speed coloring fixed** — Replaced the broken `Expression.get("color")` (reads a string feature property, silently fails for `lineColor` on `LineLayer` in MapLibre Android 11.x) with `Expression.step(Expression.get("speed"), ...)` which maps the numeric `"speed"` property directly to color literals. `speedSegments()` no longer writes the unused `"color"` string property. +### Progress +- [x] Task 1: Remove report buttons, fix touch-through — commit `2d86c0b` +- [x] Task 2: Update typography styles — commit `e79b678` +- [ ] Task 3: Create `DirectionArrowView.kt` +- [ ] Task 4: Create `WaveView.kt` +- [ ] Task 5: Restructure `layout_instruments_sheet.xml` +- [ ] Task 6: Refactor `InstrumentHandler.kt` +- [ ] Task 7: Wire new views in `MainActivity.kt`, fix units --- -## Previous Task Goal -Instrument Sheet Visual Redesign — IN PROGRESS (2026-04-06) +## Recently Completed -**Plan:** `docs/superpowers/plans/2026-04-04-instrument-sheet-visual-redesign.md` -**Spec:** `docs/superpowers/specs/2026-04-04-instrument-sheet-visual-redesign.md` +### Tack Detection Redesign — 2026-05-26 +Full rewrite of `TackDetector.kt` (both `android-app` and `test-runner` mirrors). -### Progress -- [x] Task 1: Remove report buttons + fix touch-through — **DONE** (commit `2d86c0b`) -- [x] Task 2: Update typography styles — **DONE** (commit `e79b678`) -- [ ] Task 3: Create `DirectionArrowView` — pending -- [ ] Task 4: Create `WaveView` — pending -- [ ] Task 5: Restructure `layout_instruments_sheet.xml` — pending -- [ ] Task 6: Refactor `InstrumentHandler` — pending -- [ ] Task 7: Update `MainActivity` — wire new views and fix units — pending +**Root causes fixed:** +- Point-count window (HALF_WIN=2) gave wildly different reliability at 1 Hz vs 0.2 Hz +- Only 2 points used for heading estimate — one noisy fix contaminated the result +- Single-pair spread check fired on individual noisy fixes +- No protection against GPS COG noise at low/zero SOG -### What's being built -A visual redesign of the instrument bottom sheet: -- Animated wave canvas divider (swell height/period + wind waves + whitecaps) replacing the plain divider between instruments and forecast -- Sky-blue gradient above wave, ocean blue below -- `DirectionArrowView`: 14dp inline chevron compass indicator in two palettes (SKY grey / OCEAN blue) -- Direction arrows inline with numeric values in all relevant cells -- `°` baked into HDG/COG values (not a separate unit label) -- Forecast cells: value on line 1, [arrow] bearing on line 2 (swell adds period) -- Imperial units: feet for depth, wave height, swell height (all converted from metres) -- Forecast labels: "Current" (not "Curr"), "Waves" (not "Wave"), no section header -- Touch-through prevention: clickable/focusable on root layout -- Reports section removed - -### Key files -| File | Status | -|---|---| -| `layout_instruments_sheet.xml` | Partially done (Task 1 applied; full restructure in Task 5) | -| `DirectionArrowView.kt` | Not created yet | -| `WaveView.kt` | Not created yet | -| `InstrumentHandler.kt` | Not refactored yet | -| `MainActivity.kt` | Task 1 applied; Task 7 changes pending | -| `themes.xml` / `dimens.xml` | Done | +**New algorithm (CRUISING mode — conservative):** +- Time-based 30 s settle windows before/after each candidate apex, with a 30 s guard zone +- `circularMAD` stability check: rejects any window where heading spread > 20°. Handles anchor noise (MAD ≈ 90°) without any SOG gate — the stability check is sufficient. +- `circularMean` via unit-vector averaging — correct 0°/360° wrap +- `MAX_DELTA` raised to 160° (covers deep jibes the old 140° missed) +- `START_SKIP_MS` reduced to 60 s +- De-duplication uses adjacent-candidate comparison (not group-start), so a long raw-candidate stream from one maneuver stays as one group even if it spans > MIN_GAP_MS +- Position pin refined to max instantaneous heading rate within the maneuver zone + +**Key constants:** `T_SETTLE=30s, T_MANEUVER=30s, STAB_MAX=20°, MIN_DELTA=60°, MAX_DELTA=160°, MIN_GAP_MS=60s, START_SKIP_MS=60s` + +**Tests:** 16/16 passing at 1 Hz (FULL mode). Covers: straight course, port↔stbd tack, jibe, 0/360 wrap, below/above delta limits, noisy anchor (rejected), unstable before-window (rejected), gradual course change (rejected), two tacks with sufficient gap, two tacks within MIN_GAP_MS (deduplicated), cold-start suppression, too few points. + +### GPX / Storage — completed prior session +- `AndroidManifest.xml`: fixed `application/octet-stream` VIEW filter (no `pathSuffix`); added full SEND filter set for all five MIME types +- `TrackStorage.kt`: SAF primary path (`saveViaSaf`, `loadViaSaf`, `safState`, `initSafDirectory`) with MediaStore fallback; survives reinstall with one re-auth tap +- `SavedTracksFragment.kt` + `fragment_saved_tracks.xml`: "Set up track storage" / "Restore track access" button observing `safState` flow +- `MainActivity.kt`: `safPickerLauncher` + `launchSafPicker()` via `ACTION_OPEN_DOCUMENT_TREE` + +### Logbook + Trip Report Improvements — 2026-05-26 +- **Notes/photos on finished tracks** — `+ Add note` button in `TrackDetailSheet`; dialog with text, camera, gallery. Saved with `timestampMs = track.endMs` so they fall within track window and appear in `buildLogEvents()` automatically. +- **Single Nav voice** — Removed `NarrativeStyle` enum and 4-style ChipGroup. `generateNarrative(summary)` emits a concise PASSAGE header (date/time range, stats, conditions, timestamped deck log). +- **Speed coloring fixed** — Replaced broken `Expression.get("color")` (MapLibre Android 11.x silently fails for `lineColor` on `LineLayer`) with `Expression.step(Expression.get("speed"), ...)` mapping the numeric `"speed"` property to color literals. --- -## Previous Task Goal -Section 7.4 Trip Reporting & Enhanced Tracks — COMPLETE (2026-04-04) - -## Verified (2026-04-04) -- Build Successful: `android-app/gradlew assembleDebug` passed. -- UI Layout: `activity_main.xml` refactored to LinearLayout to prevent BottomNav overlap. -- Track Differentiation: Active (solid) vs Past (dotted) tracks verified in `MapHandler.kt`. -- Pre-Trip Logic: Sail suggestions reefing logic verified in `PreTripReportGenerator.kt`. - -## Completed Items - -### [APPROVED] Trip Narrative Generator + Multi-Style AI (2026-04-04) -- `android-app/app/src/main/kotlin/org/terst/nav/tripreport/TripReportGenerator.kt`: Logic for distance, speed, and stylized narratives (Professional, Adventurous, Journal, Pirate). -- `android-app/app/src/main/kotlin/org/terst/nav/tripreport/TripReportViewModel.kt`: State management for narrative generation. -- `android-app/app/src/main/kotlin/org/terst/nav/tripreport/TripReportFragment.kt`: UI for viewing and selecting narrative styles. - -### [APPROVED] Pre-Trip Planning & Sail Suggestions (2026-04-04) -- `android-app/app/src/main/kotlin/org/terst/nav/tripreport/PreTripReportGenerator.kt`: Routing and reefing suggestions based on wind/waves. -- `android-app/app/src/main/kotlin/org/terst/nav/tripreport/PreTripModels.kt`: Domain models for boat profiles and suggestions. -- `android-app/app/src/main/kotlin/org/terst/nav/tripreport/PreTripReportFragment.kt`: UI for generating and viewing pre-trip plans. - -### [APPROVED] Enhanced Map & Track Visualization (2026-04-04) -- `android-app/app/src/main/kotlin/org/terst/nav/ui/MapHandler.kt`: `updateTrackLayer` now supports active and past tracks with distinct styles. -- `android-app/app/src/main/res/layout/activity_main.xml`: Refactored to vertical LinearLayout root to stabilize BottomNav and FAB placement. -- `android-app/app/src/main/res/layout/layout_instruments_sheet.xml`: Added "TRIP REPORTS & PLANNING" section for direct access from main view. -- `android-app/app/src/main/kotlin/org/terst/nav/MainActivity.kt`: Wired Pre-Trip and Trip Report buttons from instrument sheet; added `showReport` navigation helper. -- `android-app/app/src/main/kotlin/org/terst/nav/track/TrackRepository.kt`: Added `pastTracks` storage. -- `test-runner/src/main/kotlin/org/terst/nav/track/TrackRepository.kt`: Synchronized with main app implementation. - -### [APPROVED] GpsPosition data class (2026-03-15) -- File: `app/src/main/kotlin/org/terst/nav/gps/GpsPosition.kt` -- Fields: latitude, longitude, sog (knots), cog (degrees true), timestampMs - -### [APPROVED] DeviceGpsProvider (2026-03-15) -- Wraps `LocationManager` with `GPS_PROVIDER` -- Fix-lost timer: fires `onFixLost()` after 10s with no update - -### [APPROVED] NmeaParser — RMC parser (2026-03-15) -- Parses any `*RMC` sentence (GP, GN, etc.) -- HHMMSS + DDMMYY → Unix epoch millis UTC - -### [APPROVED] AIS Integration (2026-03-15) -- `AisVdmParser.kt`: Parses !AIVDM/!AIVDO (Types 1, 2, 3, 5). -- `AisRepository.kt`: Upserts vessels and merges static data. -- `AisHubSource.kt`: Integration with AISHub REST API. -- `MapFragment`: GeoJSON layer for AIS vessels with rotation and labels. - -### [APPROVED] Track Recording (2026-03-25) -- `MainViewModel`: TrackRepository wired; `addGpsPoint` enriches with environmental data. -- `MainActivity`: FAB for toggling recording; MapHandler for rendering. - -### [APPROVED] TrackRepository (2026-03-25) -- `android-app/app/src/main/kotlin/org/terst/nav/track/TrackRepository.kt` -- `test-runner/src/main/kotlin/org/terst/nav/track/TrackRepository.kt` -- `isRecording` flag; `startTrack()` clears + starts; `stopTrack()`; `addPoint()` guards on isRecording; `getPoints()` returns snapshot -- 8 tests — all GREEN (`TrackRepositoryTest`) - -### [APPROVED] Track ViewModel + Map overlay + Record FAB (2026-03-25) -- `MainViewModel`: TrackRepository wired in; exposes `isRecording: StateFlow<Boolean>`, `trackPoints: StateFlow<List<TrackPoint>>`; `startTrack()`, `stopTrack()`, `addGpsPoint(lat, lon, sogKnots, cogDeg)` -- `MapHandler.updateTrackLayer(style, points)`: lazy LineLayer init; red (#E53935) 3dp polyline from List<TrackPoint> -- `MainActivity`: stores `loadedStyle`; GPS flow feeds `viewModel.addGpsPoint()` (m/s→knots); observes `trackPoints` → `mapHandler.updateTrackLayer()`; observes `isRecording` → FAB icon toggle (ic_track_record / ic_close) -- `activity_main.xml`: `fab_record_track` FAB anchored top|end of bottom nav -- `drawable/ic_track_record.xml`: red dot record icon - -### [APPROVED] Vessel Registry + Crew Management (2026-04-22) -- `android-app/app/src/main/kotlin/org/terst/nav/vessel/Vessel.kt` — data class: name, MMSI, callsign, flag, homePort, hullType, LOA, beam, draft, displacement, engineHp, notes, isOwnVessel -- `android-app/app/src/main/kotlin/org/terst/nav/vessel/CrewMember.kt` — data class: name, role (SKIPPER/FIRST_MATE/WATCH_CAPTAIN/CREW/GUEST), emergencyContact, emergencyPhone, certifications, notes -- `android-app/app/src/main/kotlin/org/terst/nav/vessel/VesselRepository.kt` — in-memory CRUD for vessels and crew; addVessel, updateVessel, removeVessel, getOwnVessel, addCrewMember, updateCrewMember, removeCrewMember, getSkipper, getCrewByRole -- `android-app/app/src/main/res/layout/fragment_vessel_registry.xml` — NestedScrollView with own vessel card, crew list, and known vessels list; + ADD buttons for crew and fleet -- `android-app/app/src/main/kotlin/org/terst/nav/ui/vessel/VesselRegistryFragment.kt` — fragment with AlertDialog editors for vessels and crew; long-press to delete -- `android-app/app/src/main/res/menu/bottom_nav_menu.xml` — added `nav_vessel` 5th tab with `ic_vessel` icon -- `android-app/app/src/main/res/drawable/ic_vessel.xml` — sailboat silhouette vector icon -- `MainViewModel.kt` — added `vesselRepository` property (public, for fragment access) -- `MainActivity.kt` — `R.id.nav_vessel` case loads `VesselRegistryFragment` -- Mirror classes in `test-runner/src/main/kotlin/org/terst/nav/vessel/` -- 18 tests in `test-runner/src/test/kotlin/org/terst/nav/vessel/VesselRepositoryTest.kt` — all GREEN - -### [APPROVED] Thermal Alarm (2026-04-22) -- `android-app/app/src/main/kotlin/org/terst/nav/thermal/ThermalMonitor.kt` — `thermalFlow(context)` as Kotlin Flow using `Intent.ACTION_BATTERY_CHANGED` for battery temperature; `PowerManager.addThermalStatusListener` on API 29+ for supplemental state; emits distinct `ThermalReading` only on state change -- `ThermalState` enum: OK (<40°C), WARM (40–45°C), HOT (45–50°C), CRITICAL (>50°C) -- `MainViewModel.kt` — `thermalState: StateFlow<ThermalState>`, `thermalReading: StateFlow<ThermalReading?>`, `onThermalReading()` entry point -- `MainActivity.kt` — `startThermalMonitoring()` called from `observeDataSources()`; HOT triggers Toast + alarm sound (reuses `R.raw.mob_alarm`); CRITICAL triggers urgent Toast + alarm; OK/WARM stops alarm; alarm released in `onDestroy()` - -## Next 3 Specific Steps -1. **Unit Tests for Trip Generators** — Add JVM tests in `test-runner` for `TripReportGenerator` and `PreTripReportGenerator`. -2. **Persist track to Room** — Replace in-memory `pastTracks` with a Room database for persistence across sessions. -3. **AnchorWatchHandler UI** — Re-integrate `AnchorWatchHandler` UI into `activity_main.xml` and wire it to the Safety Dashboard. - -## Scripts Added -- `test-runner/` — standalone Kotlin/JVM Gradle project for fast test cycles. - -## Process Improvements -- Stabilized UI layout by moving navigation out of the `CoordinatorLayout`. -- Duplicated core logic into `test-runner` to bypass Android SDK requirements for logic testing. +## Infrastructure + +- **`test-runner/`** — standalone Kotlin/JVM Gradle project for logic tests without Android SDK. Run: `cd test-runner && ./gradlew test` +- **Branch policy** — all work merges to `main`. Current feature branch: `claude/optimize-nav-location-tracking-Vac5Z` +- **Build note** — `./gradlew assembleDebug` requires network access to Google plugin repo (unavailable in cloud sandbox). Use `test-runner` for logic tests; build verification requires a local dev environment. |
