<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Open Waters: Releases</title>
    <link>https://openwaters.io/updates/releases/</link>
    <atom:link href="https://openwaters.io/updates/releases/rss.xml" rel="self" type="application/rss+xml" />
    <description>New releases from Open Waters.</description>
    <language>en</language>
    <item>
      <title>Earth perihelion and aphelion (Almanac 0.11.0)</title>
      <link>https://openwaters.io/updates/almanac-0-11-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/almanac-0-11-0/</guid>
      <pubDate>Sun, 18 Oct 2026 13:05:46 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Almanac 0.11.0 adds Earth perihelion and aphelion events in TypeScript, Swift, and Kotlin.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;earthApsides(startUtc, endUtc)&lt;/code&gt; / &lt;code&gt;earthApsides(from:to:)&lt;/code&gt; returns the sorted perihelion and aphelion events in a half-open window. Each carries its time, its kind (&lt;code&gt;perihelion&lt;/code&gt; or &lt;code&gt;aphelion&lt;/code&gt;; &lt;code&gt;EarthApsisKind&lt;/code&gt; in Swift and Kotlin), and &lt;code&gt;distanceKm&lt;/code&gt;, the geometric Sun–Earth centre distance at that instant.&lt;/li&gt;
&lt;li&gt;The search brackets each root in fixed cells anchored at J2000, as the season and lunar apsis searches do, so every window containing an event reports the same millisecond.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://github.com/openwatersio/almanac/blob/v0.11.0/docs/CONTRACT.md&quot;&gt;contract&lt;/a&gt; defines the model and tolerances, and the README shows the call in each language.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The search translates Astronomy Engine&amp;#39;s &lt;code&gt;SearchPlanetApsis&lt;/code&gt; for Earth. A pinned, independently compiled Astronomy Engine run is committed as an implementation oracle for all 302 events from 1950 through 2100. Every event matches, with a worst timing difference of 1.525 seconds and a distance difference below a millimeter, against tolerances of 2 seconds and 1 meter. This verifies the translation; it makes no separate physical-accuracy claim. Cross-port parity checks the new events in all three ports, and the release workflow verifies all three suites, Kotlin coverage and source consumption, and independent SwiftPM and packed npm consumers before publishing with provenance.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install @openwaters/almanac@0.11.0
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;import { earthApsides } from &amp;#39;@openwaters/almanac&amp;#39;;
for (const { kind, time, distanceKm } of earthApsides(start, end)) console.log(kind, time.toISOString(), distanceKm);
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;.package(url: &amp;quot;https://github.com/openwatersio/almanac.git&amp;quot;, exact: &amp;quot;0.11.0&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Kotlin consumers can pin the &lt;code&gt;v0.11.0&lt;/code&gt; source checkout using the &lt;a href=&quot;https://github.com/openwatersio/almanac/blob/v0.11.0/kotlin/README.md&quot;&gt;installation guide&lt;/a&gt;. No Maven artifact is published.&lt;/p&gt;
&lt;p&gt;Earth apsides: #82. CI Node versions from mise: #80. Release preparation: #83.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/compare/v0.10.0...v0.11.0&quot;&gt;Full changelog&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Depth bands and isobaths from zoom 4 (Seascape style 0.4.0)</title>
      <link>https://openwaters.io/updates/seascape-style-0-4-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/seascape-style-0-4-0/</guid>
      <pubDate>Fri, 16 Oct 2026 13:28:24 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;The style for the &lt;code&gt;v2026.10.16&lt;/code&gt; tiles.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Bands mode and isobaths start at z4 instead of z6 (#214).&lt;/li&gt;
&lt;li&gt;The coarse depth ladders carry the 10 and 20 m contours, so shallow seas split into bands at low zoom (#214).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;BANDS_MIN_ZOOM&lt;/code&gt; is exported for apps that switch between Bands and Relief.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    <item>
      <title>Shallow seas split into depth bands at low zoom (Seascape 2026.10.16)</title>
      <link>https://openwaters.io/updates/seascape-2026-10-16/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/seascape-2026-10-16/</guid>
      <pubDate>Fri, 16 Oct 2026 13:06:27 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Shallow seas no longer turn into one solid blue band at low zoom, and Bands mode is a compiled chart partition from z4 up.&lt;/p&gt;
&lt;h2&gt;Chart fixes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Shallow seas split at 10, 20 and 50 m at low zoom&lt;/strong&gt; (#214). The coarse tiers carried no isobath shallower than 50 m (z7 to 8) or 200 m (z6), so a shallow sea like the Kattegat or the North Sea painted one band in the darkest tint. Each tier now follows NOAA&amp;#39;s ENC Design Handbook contour set for its scale, plus the 10 and 20 m contours wherever that set lacks them.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bands mode and isobaths start at z4&lt;/strong&gt; (#214). A new z4 tier with the Overview contour set replaces the raster handoff at z5, so the shelf no longer changes tint between z5 and z6.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Isobaths follow the seabed at z7 to z10&lt;/strong&gt; (#214). Each tier is cut one zoom finer than before and keeps a vertex per pixel at the last zoom it serves. At z8 over the Kuril arc the median segment went from 6.4 to 3.9 px.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Depth bands below 4,000 m and in the deepest trenches&lt;/strong&gt; (#214). Water deeper than a tier&amp;#39;s deepest contour got no band at all: the deep ocean at z4 to z6, and trenches past 10,000 m or 5,000 fathoms at every zoom. A floor below the deepest ocean closes it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Shoal soundings show with their ring&lt;/strong&gt; (#214). A least depth inside a 10 to 100 m contour now shows from the zoom that contour draws at.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Pipeline&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Coarse tiers reuse the native tier&amp;#39;s tidal-water union, the cost that dominated the slowest stems: the Arctic stem 4-3-3-8 went from 316 to 101 minutes (#214).&lt;/li&gt;
&lt;li&gt;The low-zoom vector bundle writes below its top zoom at detail 11, so the Philippines z4 tile fits under tippecanoe&amp;#39;s size ceiling (#215).&lt;/li&gt;
&lt;li&gt;Every commit that touches the style or viewer gets a viewer preview, and the style package now releases from &lt;code&gt;style-v*&lt;/code&gt; tags once the live tiles carry its pipeline (#213).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Seascape is not an official Electronic Navigational Chart and is never a replacement for one. Not for navigational use.&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Soundings placed at the transducer, none lost or sent twice; requires Node 24 (Crowd depth 1.3.0)</title>
      <link>https://openwaters.io/updates/crowd-depth-1-3-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/crowd-depth-1-3-0/</guid>
      <pubDate>Thu, 15 Oct 2026 19:55:06 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;More accurate soundings, and none lost or sent twice.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Requires Node 24.&lt;/strong&gt; Signal K servers running an older Node need to upgrade before installing this version (#115).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Positions at the transducer&lt;/strong&gt;: each sounding&amp;#39;s position is moved from the GPS antenna to the transducer using your heading, or your course over ground while you are moving faster than about 1 knot. A sounding that can&amp;#39;t be placed this way is no longer uploaded with the antenna&amp;#39;s position (#134)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Correct depth reference&lt;/strong&gt;: reports say what depths are measured from: the waterline, the transducer, or unknown. Depths read through the History API now get the same transducer depth or draft correction as live data, and the transducer depth below the waterline is optional (#128)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sensor offsets in the standard frame&lt;/strong&gt;: report metadata gives sensor positions from the transducer, as forward, starboard and down (#129)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Late history providers&lt;/strong&gt;: after a restart, the plugin waits up to 10 minutes for a history provider such as signalk-to-influxdb2 to come up, recording meanwhile, before it settles on its own storage (#132)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No lost or duplicate soundings&lt;/strong&gt;: each report stops 5 minutes short of the current time, so soundings a history provider is still writing go out in the next report instead of being skipped. A sounding stamped exactly on a report boundary is sent once, not twice. &lt;code&gt;BATHY_REPORT_DELAY&lt;/code&gt; changes the delay (#136)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;End-to-end tests&lt;/strong&gt;: CI now uploads soundings through a real Signal K server and checks them against the CSB schema, and runs on pull requests from forks (#131)&lt;/li&gt;
&lt;li&gt;Dependency updates (#114)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thanks to @dirkwa for most of this release.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Depth areas, isobaths, and soundings compiled per zoom level (Seascape 2026.10.15)</title>
      <link>https://openwaters.io/updates/seascape-2026-10-15/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/seascape-2026-10-15/</guid>
      <pubDate>Thu, 15 Oct 2026 18:01:52 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Depth areas and isobaths are now compiled per zoom tier, the way an ENC is compiled per usage band, and the soundings follow chart practice for selection and rounding.&lt;/p&gt;
&lt;h2&gt;Chart fixes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Depth areas and isobaths compiled per zoom&lt;/strong&gt; (#195). Each zoom tier (z6, z7 to 8, z9 to 10, z11 to 12, z13 and up) is its own complete partition, cut from the bathymetry at that tier&amp;#39;s resolution with the isobath ladder a chart draws at that scale. Zooming out can only shoal, never deepen, and bands too small to read at a tier&amp;#39;s scale merge into their shallower neighbour. A coarse source viewed closely shows its own content rather than 2 m bands interpolated from kilometre cells. The emphasized safety contour follows the ladder drawn at each zoom.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Low-zoom isobaths keep their shape&lt;/strong&gt; (#210). At z6 to z9 the lines had been thinned to long straight segments across shelves and island arcs; they now keep a vertex per pixel and draw with round joins.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No more false shallow water along ditches and small canals&lt;/strong&gt; (#196). Under coarse sources, polder ditches and canals narrower than the source&amp;#39;s own cell had read as 0 to 2 m depth bands with soundings on them (the Haarlemmermeer). Water narrower than the source cell now stays land in that source and shows as unknown depth.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Exact datum is unknown water, never foreshore&lt;/strong&gt; (#195). A depth of exactly 0 is the land sentinel and the fill for water a source holds no depth for; it no longer draws as drying.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Unknown-depth water fills no longer compound&lt;/strong&gt; (#195). Abutting water polygons inside a lake had overlapped into a dark lattice along every outline; the fills now dissolve per tile.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Soundings in line with chart standards&lt;/strong&gt; (#180). The selection keeps the least depths a chart ranks first (the 1 m floor that discarded real shoals is gone), rounds toward the shoal side, and thins by the chart&amp;#39;s spacing rules.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No more horizontal stripes across the map at fixed latitudes&lt;/strong&gt; (#192). Unknown-water rows on the easternmost tiles had wrapped around the antimeridian.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Pipeline&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Depth-area tier files declare their full read sets, so a bbox smoke and a planet build heal the same stems (#195); the vector archive&amp;#39;s census measures each feature at its own tier&amp;#39;s zoom (#195); a bundle whose tiles overflowed fails instead of merging bands (#210).&lt;/li&gt;
&lt;li&gt;Depth-area contouring uses upstream GDAL&amp;#39;s fast polygon mode (#193); the planet build aborts early when the box&amp;#39;s disk can&amp;#39;t hold the run (#178) and stops a doomed build sooner (#194); a GEOS overlay failure on one stem no longer stops the planet (#208).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Seascape is not an official Electronic Navigational Chart and is never a replacement for one. Not for navigational use.&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Is available on the App Store (Slackwater for iOS 1.14.0)</title>
      <link>https://openwaters.io/updates/slackwater-for-ios-1-14-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/slackwater-for-ios-1-14-0/</guid>
      <pubDate>Wed, 14 Oct 2026 19:48:18 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Welcome to the first release of Slackwater, the tides &amp;amp; currents app that works offline where you need it — on the water, at the beach, in the anchorage. View past, present, and future predictions at thousands of stations worldwide, already on your phone.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tide and current predictions on a timeline you can scrub, with sun, Moon, and eclipse events alongside.&lt;/li&gt;
&lt;li&gt;A station map and search, and nearby tide and current stations on every station page.&lt;/li&gt;
&lt;li&gt;Canadian tides and currents from CHS, downloaded for offline use.&lt;/li&gt;
&lt;li&gt;Home-screen widgets for the next event and today&amp;#39;s tide curve.&lt;/li&gt;
&lt;li&gt;An Apple Watch app with tide and current complications, scrubbed with the Digital Crown.&lt;/li&gt;
&lt;li&gt;Calendar and notification alerts for slack windows, tides, and eclipses.&lt;/li&gt;
&lt;li&gt;Ask Siri for the next high tide, low tide, or slack window.&lt;/li&gt;
&lt;li&gt;Available in 14 languages.&lt;/li&gt;
&lt;li&gt;Slackwater Premium is an optional purchase; the offline core is free and stays free.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/app/id6813654837&quot;&gt;Slackwater on the App Store&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Requires Swift 6 (Almanac 0.10.0)</title>
      <link>https://openwaters.io/updates/almanac-0-10-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/almanac-0-10-0/</guid>
      <pubDate>Tue, 13 Oct 2026 08:34:39 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Almanac 0.10.0 uses Swift 6 language mode and requires a Swift 6 or newer toolchain.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Swift&amp;#39;s compiler checks the package and its tests under Swift 6 concurrency rules. Immutable event specifications have a checked Sendable conformance.&lt;/li&gt;
&lt;li&gt;The public astronomy API and calculations are unchanged. TypeScript and Kotlin consumers use the same API as 0.9.0.&lt;/li&gt;
&lt;li&gt;Slackwater&amp;#39;s iOS consumer validation passed Debug and unsigned Release builds for the phone, watch, and both widget extensions, including watch hardware&amp;#39;s arm64_32 architecture. All 170 selected sun, moon, eclipse, alert, and timeline integration tests passed.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install @openwaters/almanac@0.10.0
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;.package(url: &amp;quot;https://github.com/openwatersio/almanac.git&amp;quot;, exact: &amp;quot;0.10.0&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Kotlin consumers can pin the &lt;code&gt;v0.10.0&lt;/code&gt; source checkout using the &lt;a href=&quot;https://github.com/openwatersio/almanac/blob/v0.10.0/kotlin/README.md&quot;&gt;installation guide&lt;/a&gt;. No Maven artifact is published.&lt;/p&gt;
&lt;p&gt;Swift 6 migration: #78. Release preparation: #79.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/compare/v0.9.0...v0.10.0&quot;&gt;Full changelog&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Check whether the Sun is up (Almanac 0.9.0)</title>
      <link>https://openwaters.io/updates/almanac-0-9-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/almanac-0-9-0/</guid>
      <pubDate>Mon, 12 Oct 2026 21:45:17 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Almanac 0.9.0 provides an instantaneous sunrise-based day/night decision in TypeScript, Swift, and Kotlin.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sunIsUp(time, observer, heightAboveGroundM = 0)&lt;/code&gt; returns whether the Sun’s upper limb clears the modeled horizon. It uses the same changing solar radius, standard refraction convention, topocentric geometry, and optional horizon dip as &lt;code&gt;sunEvents&lt;/code&gt; sunrise and sunset.&lt;/li&gt;
&lt;li&gt;Polar day and night work without an event search or a calendar-day choice. The helper preserves the existing date, observer, and eye-height validation. Exact equality with the horizon target returns &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://github.com/openwatersio/almanac/blob/v0.9.0/docs/cookbook.md&quot;&gt;cookbook&lt;/a&gt; shows display-mode recipes in all three languages, explains eye height versus elevation, and leaves refresh timing and missing-position handling to the application. The astronomical model does not account for terrain, clouds, or eclipses.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tests cover independent USNO sunrise/set evidence, midnight sun, polar night, raised horizons, and a grazing polar sunrise where a fixed threshold on refracted altitude reports night. Cross-port parity checks the boolean exactly. The release workflow verifies all three suites, Kotlin coverage and source consumption, and independent SwiftPM and packed npm consumers before publishing with provenance.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install @openwaters/almanac@0.9.0
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;import { sunIsUp } from &amp;#39;@openwaters/almanac&amp;#39;;
const mode = sunIsUp(new Date(), observer) ? &amp;#39;day&amp;#39; : &amp;#39;night&amp;#39;;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;.package(url: &amp;quot;https://github.com/openwatersio/almanac.git&amp;quot;, exact: &amp;quot;0.9.0&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Kotlin consumers can pin the &lt;code&gt;v0.9.0&lt;/code&gt; source checkout using the &lt;a href=&quot;https://github.com/openwatersio/almanac/blob/v0.9.0/kotlin/README.md&quot;&gt;installation guide&lt;/a&gt;. No Maven artifact is published.&lt;/p&gt;
&lt;p&gt;Day/night helper and cookbook: #75. Release preparation: #76.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/compare/v0.8.1...v0.9.0&quot;&gt;Full changelog&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Kotlin port, angle helpers, and tested migration guides (Almanac 0.8.1)</title>
      <link>https://openwaters.io/updates/almanac-0-8-1/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/almanac-0-8-1/</guid>
      <pubDate>Mon, 12 Oct 2026 14:51:19 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Almanac 0.8.1 provides shared angle conversion helpers and tested migration guides, with the public astronomy API available in TypeScript, Swift, and Kotlin.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;degreesToRadians&lt;/code&gt; and &lt;code&gt;radiansToDegrees&lt;/code&gt; preserve signed angles and full turns without wrapping. Non-finite inputs and conversion overflow raise validation errors.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://github.com/openwatersio/almanac/blob/v0.8.1/docs/migrating-from-suncalc.md&quot;&gt;SunCalc guide&lt;/a&gt; and &lt;a href=&quot;https://github.com/openwatersio/almanac/blob/v0.8.1/docs/migrating-from-astronomy-engine.md&quot;&gt;Astronomy Engine guide&lt;/a&gt; cover event windows, polar crossings, refraction, phase conventions, and supported-range boundaries, with tested examples.&lt;/li&gt;
&lt;li&gt;The native Kotlin/JVM port shares the public contract and fixture corpus with TypeScript and Swift. It supports Java 8 bytecode and Android API 26+, and is consumed through a &lt;a href=&quot;https://github.com/openwatersio/almanac/blob/v0.8.1/kotlin/README.md&quot;&gt;pinned source checkout&lt;/a&gt;; no Maven artifact is published.&lt;/li&gt;
&lt;li&gt;Equinox and solstice searches, lunar perigee and apogee searches, and the equation of time are available in all three ports. The &lt;a href=&quot;https://github.com/openwatersio/almanac/blob/v0.8.1/docs/CONTRACT.md&quot;&gt;accuracy contract&lt;/a&gt; records their evidence and limits: measured worst errors are 79 seconds for seasons through 2050, 14.8 minutes and 54 kilometers for lunar apsides, and 1.0 second for the equation of time.&lt;/li&gt;
&lt;li&gt;The packed npm package is checked with static ESM imports, dynamic imports, and synchronous CommonJS loading on Node 22.12 and 24.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Local validation for the conversion helpers and guides passed 245 TypeScript tests, 204 Swift release tests, and 79 Kotlin tests, with 100% handwritten Kotlin line coverage. The release workflow runs all three suites, fixture checks, and independent npm and SwiftPM consumers before publishing.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install @openwaters/almanac@0.8.1
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;.package(url: &amp;quot;https://github.com/openwatersio/almanac.git&amp;quot;, exact: &amp;quot;0.8.1&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Angle helpers and migration guides: #73. Kotlin port: #70. Seasons, apsides, and equation of time: #68. Benchmarks: #69. Release preparation: #74.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/compare/v0.8.0...v0.8.1&quot;&gt;Full changelog&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Uranus and Neptune, plus guides for moving from SunCalc and Solar (Almanac 0.8.0)</title>
      <link>https://openwaters.io/updates/almanac-0-8-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/almanac-0-8-0/</guid>
      <pubDate>Sun, 11 Oct 2026 03:43:06 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Almanac 0.8.0 adds Uranus and Neptune, the Sun and Moon events apps need to move off SunCalc, and migration guides for SunCalc and Solar, in TypeScript and Swift.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sunAltitudeEvents(startUtc, endUtc, observer, altitudeDeg)&lt;/code&gt; finds the Sun crossing any altitude, rising and falling: golden hour at +6°, blue hour, or SunCalc&amp;#39;s &lt;code&gt;addTime&lt;/code&gt; angles, which mean the same thing here. At −6° it returns the same instants as civil twilight.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sunTransits&lt;/code&gt; and &lt;code&gt;moonTransits&lt;/code&gt; find upper and lower transits, so solar midnight and the Moon&amp;#39;s highest and lowest points are available alongside rise and set.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;moonOrientation(time, observer)&lt;/code&gt; gives the position angle of the Moon&amp;#39;s bright limb and its parallactic angle; subtracting one from the other gives the bright limb&amp;#39;s angle from the zenith, which is what drawing the Moon as it looks needs.&lt;/li&gt;
&lt;li&gt;Uranus and Neptune support every planetary API: Sun-centered vectors, apparent positions, altitude and azimuth, illumination, approximate magnitude, solar elongation, and rise and set.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/blob/v0.8.0/docs/migrating-from-suncalc.md&quot;&gt;Migrating from SunCalc&lt;/a&gt; and &lt;a href=&quot;https://github.com/openwatersio/almanac/blob/v0.8.0/docs/migrating-from-solar.md&quot;&gt;Migrating from Solar&lt;/a&gt; map every export of those libraries to an Almanac call and give drop-in adapters; both test suites run the guides&amp;#39; code verbatim against output recorded from SunCalc 2.1.1 and Solar 4.0.1. &lt;a href=&quot;https://github.com/openwatersio/almanac/blob/v0.8.0/docs/comparison.md&quot;&gt;How Almanac compares&lt;/a&gt; sets it beside SunCalc, Astronomy Engine, astronomia, Solar, SwiftAA, and EDSunriseSet, including where they are the better choice.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Existing functions return the same results, and no existing enum gains a case.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;New quantity&lt;/th&gt;
&lt;th&gt;Evidence&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Worst&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Limit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Sun altitude crossings at +6°, −0.3°, −4°, −8°&lt;/td&gt;
&lt;td&gt;124 crossings on Horizons one-minute grids, 20°N to 70.5°N&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;5.6 s&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;60 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Upper and lower transits, Sun and Moon&lt;/td&gt;
&lt;td&gt;Horizons hour-angle grids&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.1 s&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;60 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Moon upper transit, Sun and Moon lower transit&lt;/td&gt;
&lt;td&gt;54 USNO rows&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;27.5 s&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;60 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Parallactic angle&lt;/td&gt;
&lt;td&gt;Horizons azimuth, elevation, and declination&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.18′&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1′&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bright limb, elongation 20°–160°&lt;/td&gt;
&lt;td&gt;Meeus 48.5 on Horizons apparent positions&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.42′&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1′&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Uranus, Neptune Sun-centered position&lt;/td&gt;
&lt;td&gt;Horizons, 1950–2100&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.00035 AU&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.001 AU&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Against SunCalc 2.1.1 the migration adapters agree within 7 seconds on Sun times and 4 seconds on moonrise and moonset. Against Solar 4.0.1 they agree within 59 seconds from 34°S to 49°N; at 78°N, where the Sun grazes the twilight altitudes, the worst is 449 seconds.&lt;/p&gt;
&lt;p&gt;Validation includes 216 TypeScript tests, 178 Swift release tests, offline fixture regeneration, cross-port parity, and Apple Watch compilation. Every existing benchmark workload stays inside the 20% regression limit. A year of Sun altitude events takes about 21 ms in TypeScript and 12 ms in Swift, and a year of Sun or Moon transits about 7 ms and 4 ms; timings vary by machine.&lt;/p&gt;
&lt;p&gt;Fixture metadata records each Horizons request&amp;#39;s own retrieval date, checked against the raw response headers.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install @openwaters/almanac@0.8.0
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;.package(url: &amp;quot;https://github.com/openwatersio/almanac.git&amp;quot;, exact: &amp;quot;0.8.0&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Uranus and Neptune: #59. SunCalc parity and migration guide: #62. Solar migration guide: #65. Library comparison: #64. CI lockfile checks: #60, #66. Release preparation: #67.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/compare/v0.7.0...v0.8.0&quot;&gt;Full changelog&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>App Store screenshots in Navionics and Aqua Map (Signal K AIS plugin 0.6.3)</title>
      <link>https://openwaters.io/updates/signal-k-ais-plugin-0-6-3/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/signal-k-ais-plugin-0-6-3/</guid>
      <pubDate>Fri, 09 Oct 2026 19:38:47 GMT</pubDate>
      <category>Release</category>
      <description>&lt;ul&gt;
&lt;li&gt;The plugin&amp;#39;s App Store page has screenshots of aiscast traffic in Navionics and Aqua Map, which receive it from the Signal K server as NMEA 0183 over Wi-Fi.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    <item>
      <title>Accurate course, heading, and turn rate from NMEA 2000 receivers (Signal K AIS plugin 0.6.2)</title>
      <link>https://openwaters.io/updates/signal-k-ais-plugin-0-6-2/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/signal-k-ais-plugin-0-6-2/</guid>
      <pubDate>Fri, 09 Oct 2026 12:56:55 GMT</pubDate>
      <category>Release</category>
      <description>&lt;ul&gt;
&lt;li&gt;Traffic your NMEA 2000 AIS receiver hears reaches Open Waters AIS more faithfully. A vessel steering just west of north no longer has its course and heading sent as not available, a turn&amp;#39;s rate is no longer rounded down, and a position report that leaves out the navigation status or rate of turn now says so, where it used to claim the vessel was under way using its engine and not turning.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    <item>
      <title>Renamed to Open Waters AIS (Signal K AIS plugin 0.6.1)</title>
      <link>https://openwaters.io/updates/signal-k-ais-plugin-0-6-1/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/signal-k-ais-plugin-0-6-1/</guid>
      <pubDate>Fri, 09 Oct 2026 11:40:56 GMT</pubDate>
      <category>Release</category>
      <description>&lt;ul&gt;
&lt;li&gt;The plugin is now called Open Waters AIS, in Plugin Config and in the App Store, where it was AIScast. It is the same plugin: the package is still &lt;code&gt;signalk-aiscast&lt;/code&gt;, your settings and station carry over, and nothing about how it shares or receives traffic has changed.&lt;/li&gt;
&lt;li&gt;The plugin has an icon in the App Store, and its page there suggests &lt;a href=&quot;https://github.com/sbender9/signalk-buddylist-plugin&quot;&gt;signalk-buddylist-plugin&lt;/a&gt;, which lets you follow buddy boats on Open Waters AIS far beyond VHF range.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    <item>
      <title>Horizon dip and planetary motion (Almanac 0.7.0)</title>
      <link>https://openwaters.io/updates/almanac-0-7-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/almanac-0-7-0/</guid>
      <pubDate>Tue, 06 Oct 2026 17:57:02 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Almanac 0.7.0 provides apparent horizon dip and native planetary motion in TypeScript and Swift, with Earth included for solar-system views.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;horizonDip(observer, heightAboveGroundM)&lt;/code&gt; gives the apparent altitude of an unobstructed horizon, accounting for Earth shape and terrestrial refraction. Eye height above the surface is separate from elevation above sea level; body altitudes remain relative to the horizontal plane.&lt;/li&gt;
&lt;li&gt;Sun and Moon rise/set, local solar eclipse searches, and lunar eclipse visibility accept optional eye height. The default of zero preserves existing calls and results. Twilight and transit retain their definitions.&lt;/li&gt;
&lt;li&gt;Mercury, Venus, Mars, Jupiter, and Saturn have apparent positions, refracted altitude/azimuth, point-center rise/set, illumination, approximate airless visual magnitude, and solar elongation through &lt;code&gt;planetPosition&lt;/code&gt;, &lt;code&gt;planetAltAz&lt;/code&gt;, &lt;code&gt;planetEvents&lt;/code&gt;, and &lt;code&gt;planetIllumination&lt;/code&gt;. Viewing windows combine these quantities with the consumer&amp;#39;s twilight and observing policy.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;planetHeliocentricPosition&lt;/code&gt; accepts those five planets and Earth. It returns geometric Sun-centered &lt;code&gt;xAu&lt;/code&gt;, &lt;code&gt;yAu&lt;/code&gt;, and &lt;code&gt;zAu&lt;/code&gt; in fixed J2000 equatorial coordinates. Earth-based planetary queries reject Earth.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Planetary geometry is checked against JPL Horizons across 1950 through 2100, including both supported boundaries, conjunctions, near-zenith tracks, and polar grazing rise/set pairs. Angular limits remain one arcminute, physical range and heliocentric vector limits are 0.001 AU, and event limits are 60 seconds. Magnitudes are approximate: the pinned model differs from Horizons by up to 0.75 magnitudes for extreme Venus crescents in the retained evidence. Saturn&amp;#39;s magnitude includes its rings.&lt;/p&gt;
&lt;p&gt;Validation includes 193 TypeScript tests, 155 Swift release tests, offline fixture regeneration, cross-port reproduction within 5 scaled units / 100 ms, and Apple Watch hardware and simulator compilation. All 30 benchmark workloads pass the 20% regression limit in both ports. On the local machine, the five-planet 228-hour sky track takes about 17.2 ms in TypeScript and 6.5 ms in Swift; timings vary by machine.&lt;/p&gt;
&lt;p&gt;The library retains zero runtime dependencies and zero runtime data files. Plans and specs live in #51; the repository contains the maintained API contract and scope.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install @openwaters/almanac@0.7.0
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;.package(url: &amp;quot;https://github.com/openwatersio/almanac.git&amp;quot;, exact: &amp;quot;0.7.0&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Documentation scope: #50. Apparent horizon: #52. Planetary motion: #53. Release preparation: #55.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/compare/v0.6.0...v0.7.0&quot;&gt;Full changelog&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Tide widget for chart plotters (Signal K tides plugin 2.2.0)</title>
      <link>https://openwaters.io/updates/signal-k-tides-plugin-2-2-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/signal-k-tides-plugin-2-2-0/</guid>
      <pubDate>Fri, 02 Oct 2026 17:34:17 GMT</pubDate>
      <category>Release</category>
      <description>&lt;h2&gt;New Features&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;feat: offer a tide widget to chart plotters (&lt;a href=&quot;https://github.com/openwatersio/signalk-tides/pull/139&quot;&gt;#139&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Maintenance&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Group vitest and @vitest/* Dependabot updates (&lt;a href=&quot;https://github.com/openwatersio/signalk-tides/pull/137&quot;&gt;#137&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    <item>
      <title>Tiles at half the size, with land areas (Maritime zones 0.2.0)</title>
      <link>https://openwaters.io/updates/maritime-zones-0-2-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/maritime-zones-0-2-0/</guid>
      <pubDate>Thu, 01 Oct 2026 20:11:45 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Maritime zone tiles for @openwaters/maritime-zones 0.2.0. The package downloads the tiles it needs from this release and checks each against the sha256 in &lt;code&gt;tiles.json&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;636 seekable zstd tiles (256 KiB frames, level 19), 142 MB in total. Sizes and SHA-256 cover the compressed downloads.&lt;/p&gt;
&lt;p&gt;Zone and boundary features: Marine Regions Maritime Boundaries Geodatabase (Flanders Marine Institute), CC-BY 4.0. Land features: Flanders Marine Institute (2020). &lt;a href=&quot;https://marineinfo.org/doc/dataset/8873&quot;&gt;World Countries Geodatabase&lt;/a&gt;, CC-BY 4.0, adapted from ESRI World Countries 2014 with DeLorme (2014) source data. Country polygon rings come from MarineRegions:worldcountries_esri_2014 and include inland borders and holes. The source hashes are recorded in upstream.lock.json. Marine Regions land_v9 is not used.&lt;/p&gt;
&lt;p&gt;VLIZ has approved derived-tile redistribution and the monthly upstream-check load. Maintainers monitor Marine Regions updates to avoid distributing deprecated versions. World Countries supplies a proxy for normal baselines, not a complete legal-baseline model. The v0.1.0 release uses OpenStreetMap coastlines and retains its own NOTICE and ODbL 1.0 terms. npm publication is authorized and follows the matching tile release; see CONTRIBUTING.md for publishing instructions.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Internal Waters (v4, world, 2023): 113 features&lt;/li&gt;
&lt;li&gt;Archipelagic Waters (v4, world, 2023): 23 features&lt;/li&gt;
&lt;li&gt;Territorial Seas (12 NM) (v4, world, 2023): 230 features&lt;/li&gt;
&lt;li&gt;Contiguous Zones (24 NM) (v4, world, 2023): 220 features&lt;/li&gt;
&lt;li&gt;Exclusive Economic Zones (200 NM) (v12, world, 2023): 285 features&lt;/li&gt;
&lt;li&gt;High Seas (v2, world, 2024): 1 feature&lt;/li&gt;
&lt;li&gt;World countries (ESRI, 2014): 294 features&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Not for navigation.&lt;/strong&gt; Marine Regions data &amp;quot;is not meant to be used for legal, economical … or navigational purposes&amp;quot; and &amp;quot;has no legal value whatsoever&amp;quot;. See the attached NOTICE for the citation and licence of each layer.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Stations named after your boat, and signed token requests (Signal K AIS plugin 0.6.0)</title>
      <link>https://openwaters.io/updates/signal-k-ais-plugin-0-6-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/signal-k-ais-plugin-0-6-0/</guid>
      <pubDate>Thu, 01 Oct 2026 14:00:50 GMT</pubDate>
      <category>Release</category>
      <description>&lt;ul&gt;
&lt;li&gt;Your station on aiscast takes your boat&amp;#39;s name, the vessel name set in Signal K, while &lt;em&gt;Share my own ship&lt;/em&gt; is on. Turning that switch off removes the name, so the station never says where the boat is. There is nothing to set up.&lt;/li&gt;
&lt;li&gt;The plugin signs its token requests with the boat&amp;#39;s key, so nobody else can get a token for your station. After the upgrade it requests a new token once.&lt;/li&gt;
&lt;li&gt;Plugin Config shows the address of this boat&amp;#39;s station page on openwaters.io under Advanced → Access token, to copy into a browser, so you can see what your receiver is contributing.&lt;/li&gt;
&lt;li&gt;A pasted token that aiscast refuses now says how to fix it: clear Advanced → Access token and the plugin goes back to its own token. Tokens from openwaters.io/ais/token that are bound to a network address stop working when that address changes, as it does on Starlink and cellular. The plugin&amp;#39;s own token works from any address.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    <item>
      <title>First maritime zone tiles (Maritime zones 0.1.0)</title>
      <link>https://openwaters.io/updates/maritime-zones-0-1-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/maritime-zones-0-1-0/</guid>
      <pubDate>Thu, 01 Oct 2026 02:59:09 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Maritime zone tiles for @openwaters/maritime-zones 0.1.0. The package downloads the tiles it needs from this release and checks each against the sha256 in &lt;code&gt;tiles.json&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;586 seekable zstd tiles (256 KiB frames, level 19), 282 MB in total. Sizes and SHA-256 cover the compressed downloads.&lt;/p&gt;
&lt;p&gt;Zone and boundary features: Marine Regions Maritime Boundaries Geodatabase (Flanders Marine Institute), CC-BY 4.0. Coastline features: © OpenStreetMap contributors, &lt;a href=&quot;https://opendatacommons.org/licenses/odbl/1-0/&quot;&gt;ODbL 1.0&lt;/a&gt;. The source archive is recorded in upstream.lock.json. Marine Regions land_v9 is not used.&lt;/p&gt;
&lt;p&gt;This is an experimental release while VLIZ&amp;#39;s confirmation of derived-tile redistribution is pending. The release and Pages mirror may be removed. The package remains private and is not published to npm.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Internal Waters (v4, world, 2023): 113 features&lt;/li&gt;
&lt;li&gt;Archipelagic Waters (v4, world, 2023): 23 features&lt;/li&gt;
&lt;li&gt;Territorial Seas (12 NM) (v4, world, 2023): 230 features&lt;/li&gt;
&lt;li&gt;Contiguous Zones (24 NM) (v4, world, 2023): 220 features&lt;/li&gt;
&lt;li&gt;Exclusive Economic Zones (200 NM) (v12, world, 2023): 285 features&lt;/li&gt;
&lt;li&gt;High Seas (v2, world, 2024): 1 feature&lt;/li&gt;
&lt;li&gt;OpenStreetMap coastlines (WGS84), ODbL 1.0: 879204 features&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Not for navigation.&lt;/strong&gt; Marine Regions data &amp;quot;is not meant to be used for legal, economical … or navigational purposes&amp;quot; and &amp;quot;has no legal value whatsoever&amp;quot;. See the attached NOTICE for the citation and licence of each layer.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Where each solar eclipse is greatest (Almanac 0.6.0)</title>
      <link>https://openwaters.io/updates/almanac-0-6-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/almanac-0-6-0/</guid>
      <pubDate>Sun, 27 Sep 2026 22:12:39 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Almanac 0.6.0 reports where greatest eclipse falls for every solar eclipse on Earth, including partial eclipses, in TypeScript and Swift.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GlobalSolarEclipse&lt;/code&gt; gains &lt;code&gt;greatestLatitudeDeg&lt;/code&gt;, &lt;code&gt;greatestLongitudeDeg&lt;/code&gt;, and &lt;code&gt;greatestObscuration&lt;/code&gt;, present for every eclipse. For a total or annular eclipse they equal the ground point. When the Moon&amp;#39;s shadow axis misses the Earth, as it does for every partial eclipse and a few non-central annular and total ones, they give the point on the Earth&amp;#39;s limb nearest the axis, where the Sun&amp;#39;s center is on the geometric horizon, and the fraction of the Sun covered there. &lt;code&gt;latitudeDeg&lt;/code&gt;, &lt;code&gt;longitudeDeg&lt;/code&gt;, and &lt;code&gt;obscuration&lt;/code&gt; keep their meaning and are still &lt;code&gt;null&lt;/code&gt; for a partial eclipse.&lt;/li&gt;
&lt;li&gt;Swift&amp;#39;s &lt;code&gt;GlobalSolarEclipse&lt;/code&gt; public initializer takes the three new values as required arguments, so code that constructs the struct by hand needs updating.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The point is checked against the Espenak Five Millennium Catalog for all 122 eclipses from 1950 through 2100 whose axis misses the Earth, 115 partial and 7 non-central:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Quantity&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Worst residual&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Tolerance&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Point against the catalog&amp;#39;s whole-degree coordinates&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.63°&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1°&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Geometric Sun altitude there&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.0011°&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.01°&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Local search placed there: peak against greatest eclipse&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.95 s&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Local search placed there: obscuration&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;about 1e-9&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1e-6&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The local search placed at the point also reports the catalog&amp;#39;s kind for all 122. The performance comparison showed no regression in either port. Validation includes 178 TypeScript tests, 137 Swift release tests, and the shared fixture and parity checks.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install @openwaters/almanac@0.6.0
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;.package(url: &amp;quot;https://github.com/openwatersio/almanac.git&amp;quot;, exact: &amp;quot;0.6.0&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Greatest eclipse for partial solar eclipses: #43, #44, #45.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/compare/v0.5.0...v0.6.0&quot;&gt;Full changelog&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Solar eclipses anywhere on Earth, with central lines (Almanac 0.5.0)</title>
      <link>https://openwaters.io/updates/almanac-0-5-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/almanac-0-5-0/</guid>
      <pubDate>Sun, 27 Sep 2026 18:21:24 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Almanac 0.5.0 adds solar eclipses anywhere on Earth, and the central line of each total or annular eclipse, in TypeScript and Swift.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;nextGlobalSolarEclipse(after:)&lt;/code&gt; / &lt;code&gt;nextGlobalSolarEclipse(after)&lt;/code&gt;, &lt;code&gt;previousGlobalSolarEclipse(before:)&lt;/code&gt; / &lt;code&gt;previousGlobalSolarEclipse(before)&lt;/code&gt;, and &lt;code&gt;globalSolarEclipses(from:to:)&lt;/code&gt; / &lt;code&gt;globalSolarEclipses(from, to)&lt;/code&gt; find solar eclipses with no observer. Each result carries the time of greatest eclipse, the shadow axis&amp;#39;s distance from the Earth&amp;#39;s center, and where the axis meets the ground, with the kind (partial, annular, or total) and obscuration seen from there. When the axis misses the Earth, the eclipse is partial, with no ground point.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;solarEclipseAxisPoint(at:)&lt;/code&gt; / &lt;code&gt;solarEclipseAxisPoint(time)&lt;/code&gt; gives where the shadow axis meets the ground at any instant, or nothing when it misses.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;solarEclipseCentralLine(peak:stepSeconds:)&lt;/code&gt; / &lt;code&gt;solarEclipseCentralLine(peak, stepSeconds)&lt;/code&gt; traces the central line from where the axis first touches the Earth to where it leaves. Interior points fall on whole multiples of the step since the Unix epoch, which defaults to 60 seconds, so a line at a step that is a whole multiple of another samples a subset of its instants.&lt;/li&gt;
&lt;li&gt;The shared performance harness gains five global workloads. &lt;code&gt;benchmarks/run.mjs --skip &amp;#39;^global/&amp;#39;&lt;/code&gt; leaves them out when the comparison base predates 0.5.0.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The global search finds all 337 solar eclipses from 1950 through 2100 in the Espenak Five Millennium Catalog, with no extras, and every kind matches. The central line is checked against NASA&amp;#39;s path tables for six central eclipses, at the same dynamical time:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Quantity&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Worst residual&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Tolerance&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Greatest eclipse, 337 eclipses&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;8.2 s&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;60 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Axis distance against catalog gamma&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;4.1 km&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;5 km&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ground point, 202 eclipses with the axis under 6,100 km&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.66°&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1°&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Central line against NASA path tables&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;3.1 km, 4.9 s&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;5 km, 60 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Central line of the grazing 2044-08-23 eclipse&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;9.4 km, 8.1 s&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;15 km, 60 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Annular obscuration against the diameter ratio squared&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.0010&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.002&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Local search at 953 central-line points: peak&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.40 s&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2 s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/openwatersio/almanac/actions/runs/36339002754&quot;&gt;hosted CI comparison&lt;/a&gt; measured these median query times, in milliseconds:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Workload&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;TypeScript&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Swift&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Next global solar eclipse&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.22&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.16&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Previous global solar eclipse&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.18&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Global solar eclipses / 228 hours, no new moon&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.006&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.005&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Global solar eclipses / 1950–2100&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;149&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;111&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Central line of 2024-04-08, 60 s step&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.3&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Both revisions used the same harness and toolchain within each port, with seven interleaved process pairs and 300 ms warmup. No existing workload moved by more than 2.6% in either port. Validation includes 174 TypeScript tests, 133 Swift release tests, and the shared fixture and parity checks.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install @openwaters/almanac@0.5.0
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;.package(url: &amp;quot;https://github.com/openwatersio/almanac.git&amp;quot;, exact: &amp;quot;0.5.0&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Global solar eclipses: #39, #40, #42. Development and toolchain: #36. Dependency updates: #37.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/compare/v0.4.2...v0.5.0&quot;&gt;Full changelog&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Works with the new contributor station names (Signal K AIS plugin 0.5.2)</title>
      <link>https://openwaters.io/updates/signal-k-ais-plugin-0-5-2/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/signal-k-ais-plugin-0-5-2/</guid>
      <pubDate>Sat, 26 Sep 2026 14:36:00 GMT</pubDate>
      <category>Release</category>
      <description>&lt;ul&gt;
&lt;li&gt;Works with aiscast&amp;#39;s new names for contributing stations. aiscast now files every contribution as &lt;code&gt;station:&amp;lt;key&amp;gt;&lt;/code&gt;, which 0.5.1 does not recognize, so it took its own reports coming back from the server for traffic from another station. The loop guard then held back the boat&amp;#39;s receiver when it heard an identical report again, such as a nearby vessel&amp;#39;s unchanged static data, and that report never reached aiscast. The plugin recognizes its own reports under the old and new names, and with an operator-issued token as well as one it minted itself.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    <item>
      <title>Permanent station slugs, Alaska panhandle gauges, and Dutch tide fits (Slackwater database 0.10.20260924)</title>
      <link>https://openwaters.io/updates/slackwater-database-0-10-20260924/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/slackwater-database-0-10-20260924/</guid>
      <pubDate>Thu, 24 Sep 2026 15:48:44 GMT</pubDate>
      <category>Release</category>
      <description>&lt;ul&gt;
&lt;li&gt;Publish the Alaska panhandle&amp;#39;s NOAA gauges in Alaska (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/177&quot;&gt;#177&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Re-import NOAA stations after the state fix (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/178&quot;&gt;#178&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Exit non-zero when the NOAA importer or LAT/HAT scripts crash (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/180&quot;&gt;#180&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Fit Rijkswaterstaat tide heights with harmonics (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/182&quot;&gt;#182&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Remove numeric subdivision codes from station locations (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/183&quot;&gt;#183&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Distinguish nearby stations that share a name (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/186&quot;&gt;#186&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Keep a published slug for good, record every move as a redirect, and merge the ten BC pairs (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/189&quot;&gt;#189&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Keep a published bare slug through a name collision (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/190&quot;&gt;#190&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Publish the database rewrite as 0.10 (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/193&quot;&gt;#193&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    <item>
      <title>Swift package by URL and cleaner station names (Slackwater database 0.9.20260923)</title>
      <link>https://openwaters.io/updates/slackwater-database-0-9-20260923/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/slackwater-database-0-9-20260923/</guid>
      <pubDate>Wed, 23 Sep 2026 05:25:54 GMT</pubDate>
      <category>Release</category>
      <description>&lt;ul&gt;
&lt;li&gt;Let Swift apps depend on the tide database by URL (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/162&quot;&gt;#162&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Evaluate Kartverket tide-height coverage for Norway (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/163&quot;&gt;#163&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Refresh UHSLC research-quality datums from live RQD (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/140&quot;&gt;#140&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Stop station name cleanup damaging brackets, possessives and Mc names (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/166&quot;&gt;#166&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Read a subordinate station&amp;#39;s tidal range without resolving its reference yourself (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/169&quot;&gt;#169&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Fix capitalized station names and repeated state codes (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/171&quot;&gt;#171&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Label cross-border gauges by location instead of publisher (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/173&quot;&gt;#173&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Prototype Rijkswaterstaat tide prediction data (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/172&quot;&gt;#172&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Move NOAA current ingestion into the tide database (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/175&quot;&gt;#175&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    <item>
      <title>Water body names and boat rentals (Seamap 0.3.1)</title>
      <link>https://openwaters.io/updates/seamap-0-3-1/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/seamap-0-3-1/</guid>
      <pubDate>Tue, 22 Sep 2026 23:05:08 GMT</pubDate>
      <category>Release</category>
      <description>&lt;ul&gt;
&lt;li&gt;Name islands, bays, straits, and other water bodies (&lt;a href=&quot;https://github.com/openwatersio/seamap/pull/71&quot;&gt;#71&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Quieter restricted-area fills and paper-style boundaries (&lt;a href=&quot;https://github.com/openwatersio/seamap/pull/70&quot;&gt;#70&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Show boat rentals on the chart (&lt;a href=&quot;https://github.com/openwatersio/seamap/pull/75&quot;&gt;#75&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Serve label glyphs from the Open Waters font stack (&lt;a href=&quot;https://github.com/openwatersio/seamap/pull/77&quot;&gt;#77&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Fix seamarks not showing on the chart (&lt;a href=&quot;https://github.com/openwatersio/seamap/pull/85&quot;&gt;#85&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    <item>
      <title>One-file database with a Swift reader and current stations (Slackwater database 0.9.20260921)</title>
      <link>https://openwaters.io/updates/slackwater-database-0-9-20260921/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/slackwater-database-0-9-20260921/</guid>
      <pubDate>Mon, 21 Sep 2026 18:35:48 GMT</pubDate>
      <category>Release</category>
      <description>&lt;ul&gt;
&lt;li&gt;Stop loading baltic-sea.geo.json as a phantom station (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/128&quot;&gt;#128&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Package the database as a single FlatBuffers file (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/123&quot;&gt;#123&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Fix mise npm version for installs (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/137&quot;&gt;#137&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Reorganize the repo into workspace packages (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/130&quot;&gt;#130&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Swift package for reading the database (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/129&quot;&gt;#129&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Unify tide and current station metadata (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/131&quot;&gt;#131&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Include current stations in the XTide tide database (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/143&quot;&gt;#143&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Place stations by the bay or strait they sit in (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/145&quot;&gt;#145&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Credit TICON-4&amp;#39;s authors and state what we change (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/158&quot;&gt;#158&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Document Rijkswaterstaat tide coverage and offline format (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/156&quot;&gt;#156&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Give every station a ready-to-display attribution (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/159&quot;&gt;#159&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Ship a single tide file instead of separate metric and imperial ones (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/147&quot;&gt;#147&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    <item>
      <title>Names, call signs, and dimensions on chartplotters (Signal K AIS plugin 0.5.1)</title>
      <link>https://openwaters.io/updates/signal-k-ais-plugin-0-5-1/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/signal-k-ais-plugin-0-5-1/</guid>
      <pubDate>Mon, 21 Sep 2026 16:53:13 GMT</pubDate>
      <category>Release</category>
      <description>&lt;ul&gt;
&lt;li&gt;Chartplotters now show names, call signs, and dimensions for aiscast targets. aiscast sends a vessel&amp;#39;s static data only when it changes, so for most aggregated targets the only copy arrives in the snapshot on connect, which the NMEA 0183 relay held back. The plugin now keeps the latest static data for each target, sends it right after the target&amp;#39;s first live position, and repeats it with a position every 6 minutes while the target stays live.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    <item>
      <title>Open Waters AIS traffic on NMEA 0183 chartplotters (Signal K AIS plugin 0.5.0)</title>
      <link>https://openwaters.io/updates/signal-k-ais-plugin-0-5-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/signal-k-ais-plugin-0-5-0/</guid>
      <pubDate>Mon, 21 Sep 2026 13:25:27 GMT</pubDate>
      <category>Release</category>
      <description>&lt;ul&gt;
&lt;li&gt;New Receive setting, on by default: &lt;em&gt;Send aiscast traffic to NMEA 0183 output&lt;/em&gt;. Targets injected from aiscast are re-emitted as &lt;code&gt;!AIVDM&lt;/code&gt; on the &lt;code&gt;nmea0183out&lt;/code&gt; event, so chartplotters and tablet apps reading the server&amp;#39;s NMEA 0183 connections see over-the-horizon traffic, not only the Signal K apps. Only aiscast-sourced targets are relayed, and in &lt;code&gt;Always&lt;/code&gt; mode a target the local receiver already covers is left out, so nothing is duplicated. Turn it off if &lt;code&gt;signalk-vessels-to-ais&lt;/code&gt; is doing the same conversion.&lt;/li&gt;
&lt;li&gt;Position events older than 2 minutes are discarded before they reach Signal K or NMEA 0183. Static data is always injected into Signal K, but reaches NMEA 0183 only after that vessel has sent a live position, keeping the snapshot replay burst off slow serial connections. Remote &lt;code&gt;!AIVDO&lt;/code&gt; is converted to &lt;code&gt;!AIVDM&lt;/code&gt; before relay so it cannot replace the chartplotter&amp;#39;s own-ship state.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    <item>
      <title>Faster sunrise, sunset, and twilight searches (Almanac 0.4.2)</title>
      <link>https://openwaters.io/updates/almanac-0-4-2/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/almanac-0-4-2/</guid>
      <pubDate>Sun, 20 Sep 2026 04:53:21 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Almanac 0.4.2 speeds up Sun and Moon rise, set, and twilight searches in TypeScript and Swift, and the Sun&amp;#39;s position in TypeScript. The public API is unchanged.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Event searches find altitude extrema with Brent&amp;#39;s method instead of a fixed 22-sample golden section, and find altitude crossings with a cosine-seeded secant solver. Every crossing is still proven inside a half-second bracket, and anything that stalls or leaves the segment falls back to the bracketed search. Sampler calls for a year at Victoria drop from 40,681 to 15,400 for Sun events and from 24,437 to 10,173 for Moon events.&lt;/li&gt;
&lt;li&gt;The TypeScript Sun series evaluates its 51 VSOP87 terms as straight-line arithmetic rather than iterating the coefficient table, for bit-for-bit identical results. Swift already evaluated the series efficiently and mirrors the structure for the twin-port contract.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The focused year benchmark returns the same 3,255 Sun events:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;v0.4.1&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;v0.4.2&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Change&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;TypeScript&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;136.267 ms&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;36.268 ms&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;73.4% faster&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Swift&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;56.322 ms&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;20.963 ms&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;62.8% faster&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Moon events over the same year are 57.6% faster in TypeScript and 57.4% faster in Swift. Sun positions, the sky track, Moon phases, and every lunar and solar eclipse workload are 21% to 36% faster in TypeScript; Swift&amp;#39;s remaining workloads are within 2%.&lt;/p&gt;
&lt;p&gt;Each search now reports the root inside its verified bracket rather than the bracket&amp;#39;s midpoint, so event times move by at most a third of a second. Across 1950 through 2100 at Victoria, 60°N, the equator, and 70.5°S, every event count, kind, and order is identical, and the parity corpus still holds 9,449 Sun events and 2,115 Moon events.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install @openwaters/almanac@0.4.2
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;.package(url: &amp;quot;https://github.com/openwatersio/almanac.git&amp;quot;, exact: &amp;quot;0.4.2&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sun series: #32. Event searches: #34.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/compare/v0.4.1...v0.4.2&quot;&gt;Full changelog&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Fewer SD card writes while offline (Signal K AIS plugin 0.4.0)</title>
      <link>https://openwaters.io/updates/signal-k-ais-plugin-0-4-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/signal-k-ais-plugin-0-4-0/</guid>
      <pubDate>Thu, 17 Sep 2026 13:54:00 GMT</pubDate>
      <category>Release</category>
      <description>&lt;ul&gt;
&lt;li&gt;The offline queue writes far less to the SD card. Each queue file used to be rewritten from scratch every fifteen seconds as sentences were added to it, so a boat at anchor hearing a slow trickle of traffic wrote the same data to the card a dozen times over. Sentences are now appended to the end of a file and nothing is rewritten, which on a quiet anchorage cuts the writing to a fraction of what it was.&lt;/li&gt;
&lt;li&gt;A replay the server only partly accepts no longer rewrites anything on disk, and a queue file damaged by a power cut costs one sentence instead of the five hundred it was sharing a file with.&lt;/li&gt;
&lt;li&gt;The queue keeps working when the plugin cannot delete a file, as happens when an SD card turns read-only. A queue file that could neither be read nor removed used to stop the replay where it stood until the next reconnect, and files the server had already taken could be left behind in a way that made the 100 MB cap discard data that had not been sent yet. Files that will not delete are now set aside, retried in the background, and never replayed.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    <item>
      <title>Offline backlog uploads in full after reconnecting (Signal K AIS plugin 0.3.1)</title>
      <link>https://openwaters.io/updates/signal-k-ais-plugin-0-3-1/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/signal-k-ais-plugin-0-3-1/</guid>
      <pubDate>Thu, 17 Sep 2026 11:45:58 GMT</pubDate>
      <category>Release</category>
      <description>&lt;ul&gt;
&lt;li&gt;Fixes a queue that never emptied. While the plugin was replaying a backlog to aiscast it wrote every sentence its receiver heard to a new queue file, so it traded one file for another and the replay never reached the end. On a boat that had been offline a while, the queue directory stayed at tens of thousands of files no matter how long the connection was up. A replay now carries up to a thousand sentences from as many files in one frame, and sentences heard mid-replay go out from memory.&lt;/li&gt;
&lt;li&gt;The queue keeps far fewer files. Time offline used to leave one behind every fifteen seconds; the plugin now fills each file to 500 sentences before starting another, so the count follows how much is owed rather than how long the boat was out of range.&lt;/li&gt;
&lt;li&gt;Sentences past the server&amp;#39;s publish limit are no longer lost. aiscast accepts 6000 sentences a minute and quietly drops the rest, so a large replay used to arrive mostly empty while the plugin counted it as delivered. The plugin now paces a replay under the limit and keeps anything the server did not take. A boat with a big backlog takes about a minute for every 5400 sentences owed to catch up, with live sending held back until it is done.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    <item>
      <title>Faster Moon positions and Moon events (Almanac 0.4.1)</title>
      <link>https://openwaters.io/updates/almanac-0-4-1/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/almanac-0-4-1/</guid>
      <pubDate>Tue, 15 Sep 2026 15:01:51 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Almanac 0.4.1 speeds up Moon positions and the searches built on them in TypeScript and Swift. The public API is unchanged.&lt;/p&gt;
&lt;p&gt;The focused year benchmark returns the same 705 Moon events:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;v0.4.0&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;v0.4.1&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Change&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;TypeScript&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;127.918 ms&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;53.918 ms&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;57.8% faster&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Swift&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;127.762 ms&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;42.581 ms&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;66.7% faster&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Representative Moon-dependent workloads are 35% to 62% faster in TypeScript and 51% to 69% faster in Swift.&lt;/p&gt;
&lt;p&gt;This release also makes the tag workflow create a GitHub release for every published version.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install @openwaters/almanac@0.4.1
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;.package(url: &amp;quot;https://github.com/openwatersio/almanac.git&amp;quot;, exact: &amp;quot;0.4.1&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Moon performance: #29. Release automation: #28.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/compare/v0.4.0...v0.4.1&quot;&gt;Full changelog&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Positions of fixed stars (Almanac 0.3.0)</title>
      <link>https://openwaters.io/updates/almanac-0-3-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/almanac-0-3-0/</guid>
      <pubDate>Tue, 15 Sep 2026 14:58:48 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Almanac 0.3.0 adds the altitude and azimuth of any fixed star in TypeScript and Swift.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;starAltAz(raDeg:decDeg:at:observer:)&lt;/code&gt; / &lt;code&gt;starAltAz(raDeg, decDeg, time, observer)&lt;/code&gt; takes a star&amp;#39;s J2000 catalog right ascension and declination and returns its refracted topocentric altitude and azimuth. It precesses and nutates the position to date and uses the same sidereal time and refraction as &lt;code&gt;sunAltAz&lt;/code&gt; and &lt;code&gt;moonAltAz&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Annual aberration, proper motion, and stellar parallax are not applied. Aberration is at most 20.5″, and all but a few fast-moving stars shift by only arcseconds per decade.&lt;/li&gt;
&lt;li&gt;An out-of-range right ascension or declination is a validation error, like an invalid observer.&lt;/li&gt;
&lt;li&gt;The library ships no star catalog; callers pass the coordinates they already carry.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The star positions are checked against the USNO celestial-navigation almanac for the navigational stars at Victoria and at 35°S, on the 2026 equinoxes and solstices, 1999-01-17, and 2050-06-21, with J2000 positions from SIMBAD. The tests compare every star above 10° altitude and leave out the twelve stars whose proper motion would exceed the tolerance by 2050.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;right&quot;&gt;Positions checked&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Worst altitude error&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Worst azimuth error&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Tolerance&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;197&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.45′&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.51′&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1′&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Validation includes 88 TypeScript tests, 93 Swift release tests, and the shared fixture and parity checks.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install @openwaters/almanac@0.3.0
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;.package(url: &amp;quot;https://github.com/openwatersio/almanac.git&amp;quot;, exact: &amp;quot;0.3.0&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Requested in #12. Changes: #13, #14.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/compare/v0.2.1...v0.3.0&quot;&gt;Full changelog&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Offline Sun and Moon astronomy for TypeScript and Swift (Almanac 0.1.0)</title>
      <link>https://openwaters.io/updates/almanac-0-1-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/almanac-0-1-0/</guid>
      <pubDate>Tue, 15 Sep 2026 14:58:40 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Almanac 0.1.0 is the first release: offline Sun and Moon astronomy for TypeScript and Swift, with one behavior in both ports and no network access or runtime data files.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sunPosition&lt;/code&gt; and &lt;code&gt;moonPosition&lt;/code&gt; give geocentric apparent right ascension, declination, and distance. &lt;code&gt;sunAltAz&lt;/code&gt; and &lt;code&gt;moonAltAz&lt;/code&gt; give refracted topocentric altitude and azimuth.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sunEvents&lt;/code&gt; finds sunrise, sunset, civil, nautical, and astronomical twilight, and transit within a window. &lt;code&gt;moonEvents&lt;/code&gt; finds moonrise and moonset from the Moon&amp;#39;s upper limb.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;moonIllumination&lt;/code&gt; reports the illuminated fraction, phase angle, phase, and waxing state, and &lt;code&gt;searchMoonPhases&lt;/code&gt; finds new, first-quarter, full, and last-quarter moons.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nextLunarEclipse&lt;/code&gt; returns the kind, peak, magnitudes, and contact times of the next lunar eclipse, and &lt;code&gt;lunarEclipseVisibility&lt;/code&gt; reports which contacts an observer can see.&lt;/li&gt;
&lt;li&gt;Every function covers 1950 through 2100 and raises a typed out-of-range error outside that interval. The functions share names across both ports, with Swift argument labels. The algorithms are translated from Astronomy Engine by Don Cross.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Both ports are tested against the same external fixtures and a cross-port parity corpus, with these tolerances:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Quantity&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Tolerance&lt;/th&gt;
&lt;th&gt;Evidence&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Sun and Moon position&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1′&lt;/td&gt;
&lt;td&gt;JPL Horizons, 1,839 samples each across 1950–2100&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sun distance&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1e-4 AU&lt;/td&gt;
&lt;td&gt;JPL Horizons&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Moon distance&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;70 km&lt;/td&gt;
&lt;td&gt;JPL Horizons&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rise, set, twilight, and phase times&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;60 s&lt;/td&gt;
&lt;td&gt;USNO rise and set grid, 693 USNO moon phases&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lunar eclipse peaks and magnitudes&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;60 s, 0.03&lt;/td&gt;
&lt;td&gt;All 344 eclipses in the Espenak catalog, 1950–2100&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lunar eclipse contacts&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;60 s&lt;/td&gt;
&lt;td&gt;NASA contact tables for four eclipses&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Event searches scale with window length: a full 151-year window takes about 68 s in TypeScript and 44 s in a Swift release build, so run long searches off the main thread. Validation includes 80 TypeScript tests, 84 Swift release tests, and the shared fixture and parity checks.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install @openwaters/almanac@0.1.0
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;.package(url: &amp;quot;https://github.com/openwatersio/almanac.git&amp;quot;, exact: &amp;quot;0.1.0&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Changes: #1.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/commits/v0.1.0&quot;&gt;Full history&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Solar eclipses visible from a location (Almanac 0.4.0)</title>
      <link>https://openwaters.io/updates/almanac-0-4-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/almanac-0-4-0/</guid>
      <pubDate>Mon, 14 Sep 2026 18:39:11 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Almanac 0.4.0 adds solar eclipses for an observer in TypeScript and Swift.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;nextSolarEclipse(after:observer:)&lt;/code&gt; / &lt;code&gt;nextSolarEclipse(after, observer)&lt;/code&gt;, &lt;code&gt;previousSolarEclipse(before:observer:)&lt;/code&gt; / &lt;code&gt;previousSolarEclipse(before, observer)&lt;/code&gt;, and &lt;code&gt;solarEclipses(from:to:observer:)&lt;/code&gt; / &lt;code&gt;solarEclipses(from, to, observer)&lt;/code&gt; find the solar eclipses a place can see. Each result carries the kind (partial, annular, or total), the obscuration at peak, contacts C1 through C4, and the Sun&amp;#39;s altitude at each contact. C2 and C3 are present only for annular and total eclipses.&lt;/li&gt;
&lt;li&gt;An eclipse whose Sun is below the horizon at C1, the peak, and C4 is not returned. Next and previous searches walk to the edge of the supported interval, because a place can go years without a visible solar eclipse.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;solarObscuration(at:observer:)&lt;/code&gt; / &lt;code&gt;solarObscuration(time, observer)&lt;/code&gt; gives the fraction of the Sun&amp;#39;s disc the Moon covers at any instant, for drawing an eclipse as it happens.&lt;/li&gt;
&lt;li&gt;The shared performance harness gains seven solar workloads. &lt;code&gt;benchmarks/run.mjs --skip &amp;lt;regex&amp;gt;&lt;/code&gt; leaves them out when the comparison base predates 0.4.0.&lt;/li&gt;
&lt;li&gt;Swift CI runs on Linux with Swift 6.3.3, and the TypeScript package builds with TypeScript 7.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The searches are checked against USNO local circumstances for eight places and against all 337 solar eclipses from 1950 through 2100 in the Espenak Five Millennium Catalog. The worst residuals sit well inside the contract&amp;#39;s tolerances:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Quantity&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Worst residual&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Tolerance&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;USNO contacts C1 through C4&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;7.2 s&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;60 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;USNO peak&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;7.0 s&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;300 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Catalog peak, 215 central eclipses&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;123 s&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;300 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;USNO obscuration&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.001&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;USNO Sun altitude at a contact&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.06°&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.5°&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/openwatersio/almanac/actions/runs/34825453137&quot;&gt;hosted CI comparison&lt;/a&gt; measured these median query times, in milliseconds:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Workload&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;TypeScript&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Swift&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Next solar eclipse&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;8.1&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;6.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Previous solar eclipse&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;6.9&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;5.1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Solar eclipses / 228 hours, one visible&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.72&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.51&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Solar eclipses / 228 hours, new moon not visible&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.48&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.35&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Solar eclipses / 228 hours, no new moon&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.012&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.009&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Solar eclipses / 1950–2100&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;391&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;295&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Obscuration / 228 hours&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2.8&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2.0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Both revisions used the same harness and toolchain within each port, with seven interleaved process pairs and 300 ms warmup. No existing workload moved by more than 2.1% in either port. Validation includes 127 TypeScript tests, 109 Swift release tests, and the shared fixture and parity checks.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install @openwaters/almanac@0.4.0
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;.package(url: &amp;quot;https://github.com/openwatersio/almanac.git&amp;quot;, exact: &amp;quot;0.4.0&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Solar eclipses: #24, #27. Development and toolchain: #15, #22, #23, #25, #26. Dependency updates: #16, #17, #18, #19, #20, #21.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/compare/v0.3.0...v0.4.0&quot;&gt;Full changelog&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Nearby stations on every station page, and how the Moon shapes tides (Slackwater for iOS 1.13.0)</title>
      <link>https://openwaters.io/updates/slackwater-for-ios-1-13-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/slackwater-for-ios-1-13-0/</guid>
      <pubDate>Mon, 14 Sep 2026 04:06:28 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Find nearby places from any detail page, and see how the Moon can shape the tides.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Each station page now lists nearby tide and current stations with a map, so you can move between places without returning to search.&lt;/li&gt;
&lt;li&gt;The Moon sheet explains spring and neap tides and how the Moon&amp;#39;s distance can affect tidal range. Phase shortcuts take you to the relevant night sky.&lt;/li&gt;
&lt;li&gt;Search shows where same-name stations are and remembers the place you selected. Results use more space on iPad.&lt;/li&gt;
&lt;li&gt;First launch offers ready Chesapeake Bay stations and a clearer location choice.&lt;/li&gt;
&lt;li&gt;Canadian tide and current downloads recover better from slow or interrupted connections, and downloaded currents appear in widgets.&lt;/li&gt;
&lt;li&gt;The Now button returns the schedule to the current week. Current pages show station details consistently.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    <item>
      <title>Nearest tide and current stations, an endless timeline, and sharing (Slackwater for iOS 1.12.0)</title>
      <link>https://openwaters.io/updates/slackwater-for-ios-1-12-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/slackwater-for-ios-1-12-0/</guid>
      <pubDate>Sat, 12 Sep 2026 04:11:00 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Finding the right station, a timeline that doesn&amp;#39;t end, and sharing the moment you&amp;#39;re looking at.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;My Location shows two cards — the nearest tide station and the nearest current station — and Near Me and search share All/Tides/Currents filter chips. Every tide detail links to the nearest current station and back again, with the distance in the label.&lt;/li&gt;
&lt;li&gt;The detail timeline scrolls without end in both directions. Tapping anywhere on it brings that moment to the centerline; a sunrise or sunset scrubs to itself, and the date opens the week picker.&lt;/li&gt;
&lt;li&gt;A share button sits beside the star on every detail page. It sends a slackwater.xyz link, carrying the instant you scrubbed to rather than making the receiver find it again.&lt;/li&gt;
&lt;li&gt;The commentary pill names sunrise or sunset whenever it comes before the next high, low or slack — and taps through to it like any other stop.&lt;/li&gt;
&lt;li&gt;The Moon sheet is drawn instead of tabulated: rise and set on a horizon, next full and next new as the discs they name, the orbit under the distance readout, and each eclipse row drawing its own eclipse.&lt;/li&gt;
&lt;li&gt;Shape-only gates such as Malibu Rapids now use the same curve language as measured currents without implying a speed, slack windows read cleanly against the curve, and the card and widget direction arrows match the detail page.&lt;/li&gt;
&lt;li&gt;The schedule collapses to one day at a time, Recents use the same cards as the rest of the list, day labels sit at the middle of daylight rather than clock noon, and the lead readout carries the date while you scrub through the night.&lt;/li&gt;
&lt;li&gt;The station list renders before the catalogs finish decoding, so the first frame arrives sooner.&lt;/li&gt;
&lt;li&gt;Fixes: a My Location card opens the station you tapped, not its neighbour; the location refreshes when the app comes back from the background instead of only on a cold launch.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    <item>
      <title>LAT and HAT for NOAA stations that don't publish them (Slackwater database 0.9.20260907)</title>
      <link>https://openwaters.io/updates/slackwater-database-0-9-20260907/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/slackwater-database-0-9-20260907/</guid>
      <pubDate>Mon, 07 Sep 2026 23:07:51 GMT</pubDate>
      <category>Release</category>
      <description>&lt;ul&gt;
&lt;li&gt;Synthesize LAT and HAT where NOAA publishes neither (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/126&quot;&gt;#126&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    <item>
      <title>Faster Moon, Sun, and eclipse calculations (Almanac 0.2.1)</title>
      <link>https://openwaters.io/updates/almanac-0-2-1/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/almanac-0-2-1/</guid>
      <pubDate>Mon, 07 Sep 2026 12:36:42 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Almanac 0.2.1 reduces repeated astronomy work in TypeScript and Swift, with the same public API and fixture tolerances.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reuse Moon geometry for illumination and flatten the Moon model&amp;#39;s scratch arrays.&lt;/li&gt;
&lt;li&gt;Share solar crossing probes, skip crossings before the requested window, and accelerate altitude refinement with a verified bracket and bisection fallback.&lt;/li&gt;
&lt;li&gt;Reuse peak shadow geometry when calculating eclipse contacts.&lt;/li&gt;
&lt;li&gt;Expand the shared performance harness to 15 workloads, including an empty eclipse window that exercises latitude pruning, and document how to reproduce comparisons in the README.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/openwatersio/almanac/actions/runs/34119038860&quot;&gt;hosted CI comparison&lt;/a&gt; measured these reductions in median query time versus the 0.2.0 astronomy code:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Workload&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;TypeScript&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Swift&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Sky track / 228 hours&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;40.0%&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;42.4%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sun events / 228 hours&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;39.3%&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;40.2%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Moon events / 228 hours&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;39.1%&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;35.1%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Previous lunar eclipse&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;26.0%&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;36.6%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lunar eclipses / 1950–2100&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;26.4%&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;23.4%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Both revisions used the same harness and toolchain within each port, with seven interleaved process pairs and 300 ms warmup. Build/startup time is excluded; timings vary by machine. All 15 workloads pass the 20% regression gate in both ports.&lt;/p&gt;
&lt;p&gt;Refined rise/set and twilight times can shift by up to 600 ms after quantization; event counts and kinds are unchanged, and existing accuracy and parity tolerances are preserved. Validation includes 86 TypeScript tests, 91 Swift release tests, and the shared fixture checks.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install @openwaters/almanac@0.2.1
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;.package(url: &amp;quot;https://github.com/openwatersio/almanac.git&amp;quot;, exact: &amp;quot;0.2.1&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Performance changes: #10.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/compare/v0.2.0...v0.2.1&quot;&gt;Full changelog&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Search past lunar eclipses and date ranges (Almanac 0.2.0)</title>
      <link>https://openwaters.io/updates/almanac-0-2-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/almanac-0-2-0/</guid>
      <pubDate>Mon, 07 Sep 2026 11:22:10 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Almanac 0.2.0 adds backward and range lunar eclipse searches in TypeScript and Swift.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;previousLunarEclipse(before:)&lt;/code&gt; / &lt;code&gt;previousLunarEclipse(before)&lt;/code&gt; finds the previous eclipse directly, retaining the 100 ms same-eclipse band used by next searches.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lunarEclipses(from:to:)&lt;/code&gt; / &lt;code&gt;lunarEclipses(from, to)&lt;/code&gt; returns eclipse peaks in a sorted, half-open &lt;code&gt;[from, to)&lt;/code&gt; window. Visibility remains a separate observer query.&lt;/li&gt;
&lt;li&gt;Stable peak calculations and Swift date normalization allow adjacent windows to split at a returned peak. The root solver also rejects narrow intervals without a crossing.&lt;/li&gt;
&lt;li&gt;A shared performance harness compares both ports against the base revision in CI, with macOS benchmarks gated on the cheaper TypeScript job.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Compared with the previous consumer loops, CI measured previous searches about 86% faster and 228-hour range searches 65–99% faster. Stable boundary handling adds about 0.1 ms to next searches (8–11%); all workloads pass the 20% regression gate.&lt;/p&gt;
&lt;p&gt;Validated against all 344 catalog eclipses, with 86 TypeScript tests, 91 Swift tests, and unchanged fixture/parity tolerances.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install @openwaters/almanac@0.2.0
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;.package(url: &amp;quot;https://github.com/openwatersio/almanac.git&amp;quot;, exact: &amp;quot;0.2.0&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Changes: #7, #8.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/compare/v0.1.0...v0.2.0&quot;&gt;Full changelog&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>CHS constituents 0.3.1</title>
      <link>https://openwaters.io/updates/chs-constituents-0-3-1/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/chs-constituents-0-3-1/</guid>
      <pubDate>Sun, 06 Sep 2026 15:03:41 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;No behavior change.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;0.3.0&lt;/code&gt; was published by hand to bootstrap &lt;code&gt;@openwaters/chs-constituents&lt;/code&gt;, since npm cannot configure a trusted publisher for a package that does not exist yet. This release is the first to go out through &lt;code&gt;publish.yml&lt;/code&gt; over OIDC, with provenance attached.&lt;/p&gt;
&lt;p&gt;The package moved from &lt;code&gt;@sailingnaturali/chs-constituents&lt;/code&gt; in #13, along with its shared registry dependency, now &lt;code&gt;@openwaters/station-metadata&lt;/code&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Follow buddy boats beyond VHF range (Signal K AIS plugin 0.3.0)</title>
      <link>https://openwaters.io/updates/signal-k-ais-plugin-0-3-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/signal-k-ais-plugin-0-3-0/</guid>
      <pubDate>Tue, 01 Sep 2026 19:29:23 GMT</pubDate>
      <category>Release</category>
      <description>&lt;ul&gt;
&lt;li&gt;Buddy boats: vessels on &lt;a href=&quot;https://github.com/sbender9/signalk-buddylist-plugin&quot;&gt;signalk-buddylist-plugin&lt;/a&gt;&amp;#39;s list are followed on aiscast wherever they are, far beyond VHF range, in every receive mode. The buddylist plugin keeps raising its buddy flag and proximity alerts, so Freeboard-SK&amp;#39;s buddy icon and phone notifications work at any distance. The status line shows how many buddies have been heard from.&lt;/li&gt;
&lt;li&gt;Subscriptions request a snapshot, so targets appear from the server&amp;#39;s cache at connect instead of one by one as they next transmit.&lt;/li&gt;
&lt;li&gt;Own-ship reports from NMEA 2000 are recognized by the boat&amp;#39;s MMSI, not only by the transceiver-information field, so transmitting transponders like the B&amp;amp;G V60-B publish as &lt;code&gt;!AIVDO&lt;/code&gt; and pause self-reported position synthesis.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    <item>
      <title>Slackwater database 0.9.20260901</title>
      <link>https://openwaters.io/updates/slackwater-database-0-9-20260901/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/slackwater-database-0-9-20260901/</guid>
      <pubDate>Tue, 01 Sep 2026 11:22:06 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Chores:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ci: cache GeoNames data to avoid re-downloading in tests (&lt;a href=&quot;https://github.com/openwatersio/tide-database/pull/117&quot;&gt;#117&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    <item>
      <title>New icon and App Store listing (Crowd depth 1.2.6)</title>
      <link>https://openwaters.io/updates/crowd-depth-1-2-6/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/crowd-depth-1-2-6/</guid>
      <pubDate>Mon, 31 Aug 2026 14:07:27 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Polish for the Signal K AppStore listing — no behavior changes.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;New icon&lt;/strong&gt;: sonar pings from a sailboat down to the seabed, in the Open Waters palette (#113)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AppStore metadata&lt;/strong&gt;: display name &amp;quot;Crowd Depth&amp;quot;, a fuller description, and expanded keywords (#113)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MIT license&lt;/strong&gt;, now bundled with the npm package (#113)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;README rewrite&lt;/strong&gt;: leads with why crowdsourced bathymetry matters and how reports flow through Open Waters as an IHO trusted node to the IHO DCDB (#113)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;New CONTRIBUTING.md&lt;/strong&gt;: repo layout, dev/test workflows, and the release process (#112)&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    <item>
      <title>Readable device names in the source menus (Crowd depth 1.2.5)</title>
      <link>https://openwaters.io/updates/crowd-depth-1-2-5/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/crowd-depth-1-2-5/</guid>
      <pubDate>Mon, 31 Aug 2026 01:24:36 GMT</pubDate>
      <category>Release</category>
      <description>&lt;ul&gt;
&lt;li&gt;Fixed friendly device names in the Position/Depth source dropdowns (#111, first half of #93). The config UI now shows e.g. &amp;quot;Furuno SCX-20 (IPG100.c0788c00e7e04312)&amp;quot; instead of the raw sourceRef, including for canName-form refs (&lt;code&gt;useCanName&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    <item>
      <title>CHS constituents 0.2.2</title>
      <link>https://openwaters.io/updates/chs-constituents-0-2-2/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/chs-constituents-0-2-2/</guid>
      <pubDate>Sat, 29 Aug 2026 03:26:58 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Move repository ownership to Open Waters while retaining the &lt;code&gt;@sailingnaturali/chs-constituents&lt;/code&gt; package identity. Add automated checks that keep CHS-derived output and provider station IDs out of Git and npm packages.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Share your position from GPS when there's no AIS transponder (Signal K AIS plugin 0.2.0)</title>
      <link>https://openwaters.io/updates/signal-k-ais-plugin-0-2-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/signal-k-ais-plugin-0-2-0/</guid>
      <pubDate>Mon, 24 Aug 2026 16:41:07 GMT</pubDate>
      <category>Release</category>
      <description>&lt;ul&gt;
&lt;li&gt;New Share setting: &lt;em&gt;Fallback to self-reported AIS position&lt;/em&gt;. When an AIS transponder is not available, the plugin builds class B position and static reports from Signal K (like &lt;code&gt;@signalk/aisreporter&lt;/code&gt;) and publishes them as &lt;code&gt;!AIVDO&lt;/code&gt; tagged &lt;code&gt;s:self&lt;/code&gt;, so a boat with only a GPS shows up on aiscast as self-reported. Synthesis pauses while a real &lt;code&gt;!AIVDO&lt;/code&gt; is heard. Checked by default when the config form is saved; configs saved before this setting existed stay off until re-saved. The checkbox is disabled until an MMSI is set in Vessel settings.&lt;/li&gt;
&lt;li&gt;Each Share setting explains itself below its label, and Receive mode renders as radio buttons instead of a dropdown.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    <item>
      <title>Tokens no longer expire (Signal K AIS plugin 0.1.4)</title>
      <link>https://openwaters.io/updates/signal-k-ais-plugin-0-1-4/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/signal-k-ais-plugin-0-1-4/</guid>
      <pubDate>Fri, 21 Aug 2026 22:15:46 GMT</pubDate>
      <category>Release</category>
      <description>&lt;ul&gt;
&lt;li&gt;Personal tokens minted by aiscast no longer expire; the plugin keeps a cached token with no expiry instead of minting a new one every start.&lt;/li&gt;
&lt;li&gt;The npm package includes a CHANGELOG.md.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    <item>
      <title>Connects over Starlink, satellite, and slow cellular links (Signal K AIS plugin 0.1.3)</title>
      <link>https://openwaters.io/updates/signal-k-ais-plugin-0-1-3/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/signal-k-ais-plugin-0-1-3/</guid>
      <pubDate>Fri, 21 Aug 2026 11:22:13 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Fixes the plugin never connecting on high-latency links (Starlink in remote regions, satellite, some cellular): the status line stuck on &lt;code&gt;reconnecting&lt;/code&gt; while &lt;code&gt;curl&lt;/code&gt; to the server worked. Node gave up on the IPv4 connection after 250 ms and fell back to an unroutable IPv6 address; the plugin now allows 3 s per attempt.&lt;/p&gt;
&lt;p&gt;The debug log now shows the real reason a socket failed (for example &lt;code&gt;socket error: ETIMEDOUT (connect ETIMEDOUT 2.29.0.215:443; …)&lt;/code&gt;) instead of an empty &lt;code&gt;socket error:&lt;/code&gt; line.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Dashboard clears the &quot;No token&quot; error once connected (Signal K AIS plugin 0.1.2)</title>
      <link>https://openwaters.io/updates/signal-k-ais-plugin-0-1-2/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/signal-k-ais-plugin-0-1-2/</guid>
      <pubDate>Fri, 21 Aug 2026 02:17:31 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Clears the red &amp;#39;No token&amp;#39; line on the Dashboard once the token is obtained (the server keeps a plugin&amp;#39;s last error until the status entry is reset).&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Starts sharing once the network comes up (Signal K AIS plugin 0.1.1)</title>
      <link>https://openwaters.io/updates/signal-k-ais-plugin-0-1-1/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/signal-k-ais-plugin-0-1-1/</guid>
      <pubDate>Fri, 21 Aug 2026 02:09:51 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Retries token minting with backoff (1 to 30 min) instead of waiting six hours after a failed start, so a Pi that boots before its network is up starts sharing as soon as it can. Token errors now include the underlying cause (DNS, TLS, connection refused).&lt;/p&gt;
</description>
    </item>
  </channel>
</rss>
