summaryrefslogtreecommitdiff
path: root/.agent/worklog.md
blob: 1ca8a7c272288f152884280208921897d97e2864 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# SESSION_STATE.md

## Backlog

- **Additional map sources** — NOAA chart tiles, ATON vector layer, TSS overlay. Plan: `docs/superpowers/plans/2026-06-30-additional-map-sources.md` (5 tasks).

---

## Recently Completed

### Bug Fixes (pre-fishing-mode release) — 2026-06-30

1. **Restore dark mode** — removed `MODE_NIGHT_NO` from `NavApplication`; system dark mode now works. NightVision (red-on-black FAB) is separate and unaffected.
2. **Depth tile source** — swapped empty `OpenSeaMap/depth` URL for NOAA CoastWatch ETOPO180 WMS; full Pacific/Hawaii coverage.
3. **FADs visible by default** — changed `fadsEnabled` default from `false` to `true`.

### Code Map Update — 2026-06-30

Updated `code-map.md` to reflect all changes since 2026-06-03: `ui/fishing/` package, `FadData.kt`, updated `MapLayerManager`/`MapHandler`/`LayerPickerSheet` entries, `SafetyFragment` collapsible sections, `PreTripReportFragment` auto-generate, `TrackRepository` reverse sort, `LogEntry.trackId` field, `VoiceLogViewModel` standalone filtering, new invariants (night vision vs dark mode, idle timer, trackId filter), `LocationService` notification behavior, fishing mode gotchas.

### Fishing Mode Feature — 2026-06-30

Implemented all 7 tasks for the fishing mode feature:

1. **FishingTarget + RigAdvisor** — `FishingTarget.kt`, `RigAdvisor.kt`, `RigAdvisorTest.kt` (2 tests PASSED). Species recommendation logic: Ono for warm/fast current, Mahi for moderate, BOTH otherwise.
2. **SST raster layer** — Added NOAA CoastWatch SST source/layer to `MapLayerManager`, SST toggle switch to `layout_layer_picker_sheet.xml`, `onSstChanged` callback to `LayerPickerSheet`, and updated `MainActivity.buildLayerPickerSheet()`.
3. **FishingModeManager** — `FishingModeManager.kt` + `FishingModeManagerTest.kt` (1 test PASSED). Computes fishing target zone cross-current bearing from marine conditions.
4. **FishingOverlayView** — `view_fishing_overlay.xml` card layout + `FishingOverlayView.kt` custom view. Displays species, bearing, zone description, rig, trolling speed, and approach note.
5. **MainActivity wiring** — Added `fishing_overlay` + `fab_fishing` to `activity_main.xml` (ConstraintLayout); fishing fields + `setupFishingMode()` + `updateFishingOverlay()` to `MainActivity`. SST layer auto-toggles on fishing mode activation.
6. **Fish icon** — `ic_fish.xml` vector drawable.
7. **Steering line on map** — `setupFishingLayer()` + `updateFishingBearing()` + `destinationPoint()` haversine helper in `MapHandler.kt`. Renders dashed orange line from boat toward fishing target bearing (10 nm).

Also fixed pre-existing test compile errors: `metresToFeet`/`formatFt` added to `InstrumentHandler.kt`, nullable `!!` access in `WeatherApiServiceTest.kt`.

APK build: `assembleDebug` passed. Pushed to github + local.

### Code Map & Context Tips — 2026-06-03

Created `.agent/code-map.md`: full package topology, key class table per domain, architectural invariants, testing guide, CI/merge workflow, and a "gotchas" section covering known tricky spots (MapLibre lineColor expression, TackDetector symlink, Room as read-cache, VoiceLogFragment adapter signature, etc.). Updated `config.md` directory table to reference the new file.

### Tech Debt + Trip Report Redesign — 2026-06-03

Six tech debt items closed and trip report rebuilt:

1. **Ghost package deletion** — deleted all 18 `com/example/androidapp/` source files and 9 test files; fixed package declarations in the three tide model files that were in the right directory but had wrong package headers; migrated `HarmonicTideCalculatorTest` to `org.terst.nav.tide`.
2. **TackDetector dual-mirror** — replaced test-runner copy with a filesystem symlink to the android-app canonical source (`../../../../../../../../android-app/.../TackDetector.kt`).
3. **Forecast current-hour slot** — `addGpsPoint()` now matches current UTC hour prefix against `timeIso` instead of always taking `firstOrNull()`.
4. **Room list fast-path** — `TrackEntity.toShallowSavedTrack()` + `getSavedTracksFromRoom()` serve the saved-tracks list immediately from Room before GPX parsing completes.
5. **Delete AnchorWatchHandler orphan** — removed `AnchorWatchHandler.kt` and `fragment_anchor_watch.xml` (dead code, functionality already embedded in SafetyFragment).
6. **LogbookRepository thread safety** — `@Synchronized` on `save()`, `getAll()`, `reload()`; `onSafDirectorySelected` calls `logbookRepository.reload()`.
7. **CI fix** — `VoiceLogFragment` was passing only `onSelect` to `SavedTrackAdapter`; fixed to pass both `onSelect` and `onReport`.
8. **Remove "GENERATE TRIP REPORT" button** — button and click handler removed from Log tab (`VoiceLogFragment` + layout); report auto-generates on open, RETRY appears only on error.
9. **Trip report redesign** — replaced monospace text block with: full-bleed 260dp MapLibre track map, structured stats row, conditions row (seas/temp), log entries with full-width 220dp photo thumbnails, pirate mode Easter egg via long-press title. All speeds/temps/depths use `UnitPrefs`.

### Backlog Sweep — 2026-05-27
All five backlog items closed:
1. **Pirate mode** (trip report Easter egg) — long-press title toggles dialect; done in prior session.
2. **Race mode tack detection** — `TackMode.RACE` with tight windows (T_SETTLE=12s, MIN_GAP=20s, STAB_MAX=30°); 18/18 tests pass including two race-mode-specific tests.
3. **Unit tests for PreTripReportGenerator** — 18 JVM tests in `android-app/.../tripreport/PreTripReportGeneratorTest.kt`; covers `estimatedSogKt`, condition window, sail plan, watch items, similar trips.
4. **AnchorWatchHandler UI re-integration** — depth + rode EditTexts and live radius display embedded directly in `card_anchor` inside `fragment_safety.xml`; removed `button_anchor_config` and `SafetyListener.onConfigureAnchor()`.
5. **Room persistence** — `TrackEntity`, `TrackDao`, `NavDatabase` (Room 2.6.1, KSP); write-through on `stopTrack()`/`importTrack()`; one-time GPX backfill on cold start if Room is empty. GPX/SAF remains source-of-truth.

### Tack Detection Redesign — 2026-05-26
Full rewrite of `TackDetector.kt` (both `android-app` and `test-runner` mirrors).

**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

**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=75°, no MAX_DELTA, 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.

---

## 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`.
- **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.