<feed xmlns='http://www.w3.org/2005/Atom'>
<title>nav.git/android-app/app/src/test/kotlin, branch main</title>
<subtitle>nav — android navigation app
</subtitle>
<id>https://git.terst.org/nav.git/atom?h=main</id>
<link rel='self' href='https://git.terst.org/nav.git/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://git.terst.org/nav.git/'/>
<updated>2026-04-06T09:41:32+00:00</updated>
<entry>
<title>feat(tracks): persist tracks as GPX in Documents/Nav/ — survives uninstall</title>
<updated>2026-04-06T09:41:32+00:00</updated>
<author>
<name>Peter Stone</name>
<email>thepeterstone@gmail.com</email>
</author>
<published>2026-04-06T09:41:32+00:00</published>
<link rel='alternate' type='text/html' href='https://git.terst.org/nav.git/commit/?id=f9b8801eb52c48986eb0123e8758f7ab78736dec'/>
<id>urn:sha1:f9b8801eb52c48986eb0123e8758f7ab78736dec</id>
<content type='text'>
GpxSerializer/GpxParser: full round-trip of all TrackPoint fields via
GPX 1.1 + nav: extensions namespace. 13 unit tests.

TrackStorage: MediaStore on API 29+ (no permission needed), direct file
I/O on API 24-28 (WRITE_EXTERNAL_STORAGE maxSdkVersion=28).

TrackRepository: stopTrack() is now suspend, writes GPX and returns
TrackSummary (distance nm, duration, max/avg SOG, avg wind, avg wave).
getPastTracks() lazy-loads from Documents/Nav/ on first call.

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat(ui): wire redesigned instrument sheet — InstrumentHandler rewrite + MainActivity</title>
<updated>2026-04-06T06:49:34+00:00</updated>
<author>
<name>Peter Stone</name>
<email>thepeterstone@gmail.com</email>
</author>
<published>2026-04-06T06:49:34+00:00</published>
<link rel='alternate' type='text/html' href='https://git.terst.org/nav.git/commit/?id=c8a1e81faec6663b258898c109db1f63e57b07eb'/>
<id>urn:sha1:c8a1e81faec6663b258898c109db1f63e57b07eb</id>
<content type='text'>
InstrumentHandler: direction arrows (SKY/OCEAN palettes), WaveView state,
metres→feet conversion, bearing formatting, all helpers top-level for TDD.

MainActivity: setupHandlers wires all new view refs; observeDataSources
passes cogBearingDeg, twsBearingDeg, raw metres to handler; depth collector
wired from nmeaDepthDataFlow.

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat(ui): add DirectionArrowView and WaveView custom views</title>
<updated>2026-04-06T05:25:04+00:00</updated>
<author>
<name>Peter Stone</name>
<email>thepeterstone@gmail.com</email>
</author>
<published>2026-04-06T05:25:04+00:00</published>
<link rel='alternate' type='text/html' href='https://git.terst.org/nav.git/commit/?id=8004e7e05a68a2409ad0fdfc067936f9e2329067'/>
<id>urn:sha1:8004e7e05a68a2409ad0fdfc067936f9e2329067</id>
<content type='text'>
DirectionArrowView: rotating notched-chevron compass indicator in
SKY (grey) and OCEAN (blue) palettes, with bearing normalization.

WaveView: animated swell + wind-chop canvas divider — sky/sea
gradient fills, shimmer line, whitecap highlights; self-animates
via postInvalidateOnAnimation.

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>refactor: unify core models and finish org.terst.nav migration</title>
<updated>2026-04-04T07:45:41+00:00</updated>
<author>
<name>Peter Stone</name>
<email>thepeterstone@gmail.com</email>
</author>
<published>2026-04-04T07:45:41+00:00</published>
<link rel='alternate' type='text/html' href='https://git.terst.org/nav.git/commit/?id=97715ab4007ff3101f58edf4385cef1fc3d1615b'/>
<id>urn:sha1:97715ab4007ff3101f58edf4385cef1fc3d1615b</id>
<content type='text'>
</content>
</entry>
<entry>
<title>feat(gps): add fix-quality (accuracy) tier to GPS sensor fusion</title>
<updated>2026-03-25T04:55:58+00:00</updated>
<author>
<name>Claude Agent</name>
<email>agent@example.com</email>
</author>
<published>2026-03-25T02:19:39+00:00</published>
<link rel='alternate' type='text/html' href='https://git.terst.org/nav.git/commit/?id=75ec688eb2d2754b77ff18946412bca434eb503a'/>
<id>urn:sha1:75ec688eb2d2754b77ff18946412bca434eb503a</id>
<content type='text'>
Extend LocationService's source-selection policy with a quality-aware
"marginal staleness" zone between the primary and a new extended
staleness threshold (default 10 s):

  1. Fresh NMEA (≤ primary threshold, 5 s)  →  always prefer NMEA
  2. Marginally stale NMEA (5–10 s)         →  prefer NMEA only when
     GpsPosition.accuracyMeters is strictly better than Android's;
     fall back to Android conservatively when accuracy data is absent
  3. Very stale NMEA (&gt; 10 s)               →  always prefer Android
  4. Only one source available               →  use it regardless of age

Changes:
- GpsPosition: add nullable accuracyMeters field (default null, no
  breaking change to existing callers)
- LocationService: add nmeaExtendedThresholdMs constructor parameter;
  recomputeBestPosition() now implements three-tier logic; extract
  GpsPosition.hasStrictlyBetterAccuracyThan() helper
- LocationServiceTest: expose nmeaExtendedThresholdMs in fusionService
  helper; add posWithAccuracy helper; add 4 new test cases covering
  accuracy-based NMEA preference, worse-accuracy fallback, no-accuracy
  conservative fallback, and very-stale unconditional fallback

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat(gps): implement NMEA/Android GPS sensor fusion in LocationService</title>
<updated>2026-03-25T04:55:58+00:00</updated>
<author>
<name>Claude Agent</name>
<email>agent@example.com</email>
</author>
<published>2026-03-25T02:00:17+00:00</published>
<link rel='alternate' type='text/html' href='https://git.terst.org/nav.git/commit/?id=62c27bf28de30979bc58ef7808185ac189f71197'/>
<id>urn:sha1:62c27bf28de30979bc58ef7808185ac189f71197</id>
<content type='text'>
Adds priority-based selection between NMEA GPS (dedicated marine GPS,
higher priority) and Android system GPS (fallback) within LocationService.

Selection policy:
1. Prefer NMEA when its most recent fix is fresh (≤ nmeaStalenessThresholdMs, default 5 s)
2. Fall back to Android GPS when NMEA is stale
3. Use stale NMEA only when Android has never reported a fix
4. bestPosition is null until at least one source reports

New public API:
- GpsSource enum (NONE, NMEA, ANDROID)
- LocationService.updateNmeaGps(GpsPosition)
- LocationService.updateAndroidGps(GpsPosition)
- LocationService.bestPosition: StateFlow&lt;GpsPosition?&gt;
- LocationService.activeGpsSource: StateFlow&lt;GpsSource&gt;
- Injectable clockMs parameter for deterministic unit tests

Adds 7 unit tests covering: no-data state, fresh NMEA priority,
stale NMEA fallback, only-NMEA/only-Android scenarios, exact-threshold
edge case, and NMEA recovery after Android takeover.

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat(safety): log wind and current conditions at MOB activation (Section 4.6)</title>
<updated>2026-03-25T04:55:58+00:00</updated>
<author>
<name>Claude Agent</name>
<email>agent@claude.ai</email>
</author>
<published>2026-03-25T01:57:17+00:00</published>
<link rel='alternate' type='text/html' href='https://git.terst.org/nav.git/commit/?id=0294c6fccc5a1dac7d4fb0ac084b273683e47d32'/>
<id>urn:sha1:0294c6fccc5a1dac7d4fb0ac084b273683e47d32</id>
<content type='text'>
Per COMPONENT_DESIGN.md Section 4.6, the MOB navigation view must display
wind and current conditions at the time of the event.

- MobEvent: add nullable windSpeedKt, windDirectionDeg, currentSpeedKt,
  currentDirectionDeg fields captured at the exact moment of activation
- MobAlarmManager.activate(): accept optional wind/current params and
  forward them into MobEvent (defaults to null for backward compatibility)
- LocationService (new): aggregates live SensorData (resolves true wind via
  TrueWindCalculator) and marine-forecast current conditions; snapshot()
  provides a point-in-time EnvironmentalSnapshot for safety-critical logging
- MobAlarmManagerTest: add tests for wind/current storage and null defaults
- LocationServiceTest (new): covers snapshot, true-wind resolution,
  current-condition updates, and the latestSensor flow

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat: add AnchorWatchHandler UI with Depth/Rode Out inputs and suggested radius</title>
<updated>2026-03-25T04:55:41+00:00</updated>
<author>
<name>Agent</name>
<email>agent@example.com</email>
</author>
<published>2026-03-24T23:02:14+00:00</published>
<link rel='alternate' type='text/html' href='https://git.terst.org/nav.git/commit/?id=e5cd0ce6bf65fff1bbbb5d8e12c4076da088ebe1'/>
<id>urn:sha1:e5cd0ce6bf65fff1bbbb5d8e12c4076da088ebe1</id>
<content type='text'>
- Add AnchorWatchState with calculateRecommendedWatchCircleRadius, which
  uses ScopeCalculator.watchCircleRadius (Pythagorean scope formula) and
  falls back to rode length when geometry is invalid
- Add AnchorWatchHandler Fragment with EditText inputs for Depth (m) and
  Rode Out (m); updates suggested watch circle radius live via TextWatcher
- Add fragment_anchor_watch.xml layout
- Wire AnchorWatchHandler into bottom navigation (MainActivity + menu)
- Add AnchorWatchStateTest covering valid geometry, short-rode fallback

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat: satellite GRIB download with bandwidth optimisation (§9.1)</title>
<updated>2026-03-25T04:55:20+00:00</updated>
<author>
<name>Claudomator Agent</name>
<email>agent@claudomator</email>
</author>
<published>2026-03-16T00:45:53+00:00</published>
<link rel='alternate' type='text/html' href='https://git.terst.org/nav.git/commit/?id=31b1b3a05d2100ada78042770d62c824d47603ec'/>
<id>urn:sha1:31b1b3a05d2100ada78042770d62c824d47603ec</id>
<content type='text'>
Implements weather data download over Iridium satellite links:
- GribParameter enum with SATELLITE_MINIMAL set (wind + pressure only)
- SatelliteDownloadRequest data class (region, params, forecast hours, resolution)
- SatelliteGribDownloader: size/time estimation, abort-on-oversized, pluggable fetcher
- 8 unit tests covering estimation scaling, minimal param set, and download outcomes

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat: offline GRIB staleness checker, ViewModel integration, and UI badge</title>
<updated>2026-03-25T04:55:10+00:00</updated>
<author>
<name>Claudomator Agent</name>
<email>agent@claudomator</email>
</author>
<published>2026-03-16T00:06:33+00:00</published>
<link rel='alternate' type='text/html' href='https://git.terst.org/nav.git/commit/?id=afe94c5a2ce33c7f98d85b287ebbe07488dc181f'/>
<id>urn:sha1:afe94c5a2ce33c7f98d85b287ebbe07488dc181f</id>
<content type='text'>
- Add GribRegion, GribFile data models and GribFileManager interface
- Add InMemoryGribFileManager for testing and default use
- Add GribStalenessChecker with FreshnessResult sealed class (Fresh/Stale/NoData)
- Integrate weatherStaleness StateFlow into MainViewModel (checked after loadWeather)
- Add yellow staleness banner TextView to fragment_map.xml
- Wire staleness banner in MapFragment (shown on Stale, hidden on Fresh/NoData)
- Add GribStalenessCheckerTest (4 TDD tests)

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</content>
</entry>
</feed>
