signalk-pypilot-newui 2.7.5 → 2.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,191 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.9.0 — 2026-09-23 — Relicensed to AGPL-3.0-or-later
4
+
5
+ ### License change (see NOTICE for details)
6
+
7
+ Starting with this release the plugin is distributed under the
8
+ **GNU Affero General Public License 3.0 or later** instead of Apache
9
+ 2.0. The move is intended to keep downstream forks open under the
10
+ same license — including forks offered as a network service — while
11
+ still allowing personal and commercial USE without any fee, permission
12
+ or contract.
13
+
14
+ What this means in practice:
15
+
16
+ - **Personal or commercial use is unchanged.** A cruiser, charter
17
+ fleet, sailing school or workshop can install and use the plugin
18
+ without paying anything or asking anyone.
19
+ - **Fork for your own use or to contribute back — same as before.**
20
+ Anyone can clone the repo, modify the code, test it on their boat,
21
+ or open a pull request. The AGPL only kicks in the moment you
22
+ *distribute* your modified version (as a package or as a network
23
+ service).
24
+ - **Distributing a modified version obliges you to publish the source
25
+ code under AGPL-3.0-or-later too.** Closing a fork behind a
26
+ commercial product without releasing the source is no longer
27
+ permitted.
28
+
29
+ Previous releases (up to 2.8.0) remain available under the Apache 2.0
30
+ terms that were granted at the time — those rights are perpetual for
31
+ those specific versions.
32
+
33
+ ### Also in this release
34
+
35
+ - Ship the `LICENSE` file that was declared in `package.json` but
36
+ missing from the tarball in all prior releases. The file now
37
+ carries the full AGPL-3.0 text (previously an implicit Apache-2.0
38
+ reference in `NOTICE`).
39
+ - `NOTICE` updated with licensing history + reaffirmation that
40
+ Panaaj's Apache-2.0 code fragment (autopilot-provider adapter)
41
+ is compatible with an AGPL-3.0 combined work.
42
+
43
+ ## 2.8.0 — 2026-09-23 — Sea-trial critical fixes + intelligence layer
44
+
45
+ ### Fixed (critical, from real sea trial)
46
+
47
+ - **pypilot-disconnected alarm no longer panics on a 1 s hiccup.**
48
+ The banner used to fire after just 1 second of socket silence at
49
+ "alarm" severity (audio channel forced). In a marine environment
50
+ where a 4G router routinely blips for a few seconds on the SIM,
51
+ this generated constant false positives with unavoidable sound.
52
+ New default: **15 s sustain, "warn" severity** (silent banner). The
53
+ window is now runtime-configurable via
54
+ `POST /supervisor/config` field `alarmPypilotDiscSec` (range
55
+ 3..300 s). Applies to `notifications.autopilot.pypilot-disconnected`.
56
+
57
+ - **Wind-mode nudge buttons now steer the bow to the labelled side,
58
+ independent of AWA sign.** Before, `modeSign = -Math.sign(AWA)`
59
+ meant a `+10` on port-side ceñida (AWA=-45°) inverted the sign and
60
+ moved the target the wrong way, so the bow swung to the opposite
61
+ side of the button label. Fixed to `modeSign = -1` always in wind
62
+ mode; the four cases (AWA±45 × button±10) now all match the
63
+ physical expectation of "swing the bow to the labelled side".
64
+
65
+ - **Mode change compass↔wind no longer strands `heading_command` in
66
+ the previous space.** pypilot's `ap.heading_command` lives in
67
+ different value spaces per mode (compass=heading, wind=AWA,
68
+ true wind=TWA). Before, changing modes left the target number
69
+ unchanged, so a `heading_command=90°` in compass became a 90° AWA
70
+ target in wind mode and the pilot swung hard to reach it. The
71
+ provider now **re-anchors** `heading_command` to the current
72
+ measurement in the destination space (`wind.direction` /
73
+ `wind.true_direction` / `ap.heading`) right after the mode delta
74
+ is confirmed. Same-space transitions (compass↔gps↔nav,
75
+ wind↔true wind) skip the re-anchor. Decision extracted to
76
+ `src/mode-reanchor.ts` with 24 unit tests.
77
+
78
+ - **Profile selection cannot be overwritten to "default" when opening
79
+ the visor on a fresh device.** The `<select id="profile-select">`
80
+ starts with the DOM-default first option ("default") until the
81
+ authoritative delta lands. A stray change event fired during that
82
+ gap could write "default" to pypilot, overriding the sailor's
83
+ active profile. The visor now refuses to send profile changes
84
+ until it has received at least one authoritative `profile` delta
85
+ from the backend, and skips identity writes.
86
+
87
+ - **Gust temp-heavy strategy respects manual profile changes.** If
88
+ the sailor picks a different profile during the 30 s temp-heavy
89
+ window, the automatic restore no longer overwrites that choice.
90
+ It fires an advisory notification instead.
91
+
92
+ - **Runaway pilot defence.** `adjustTarget` clamp tightened from
93
+ 573° to 90°. A single adjustTarget above 90° is either a caller
94
+ bug or a corrupt payload; refused at the boundary before it
95
+ becomes an untraceable pypilot sweep. Nudges (max 100° per press)
96
+ and tacks (go through `setTarget` absolute) are unaffected.
97
+
98
+ ### New — Doctor rule set
99
+
100
+ - **Rule 5: step-response episode analysis.** When ≥3 correction
101
+ episodes closed during the Doctor session's window, high average
102
+ overshoot suggests raising D (+15% or +25% if overshoot > 35%),
103
+ and repeated timeouts flag "AP cannot reach the target — hardware
104
+ authority".
105
+ - **Rule 6: downwind roll advisory.** With Roll FF disabled and a
106
+ heel RMS > 5° on downwind engaged samples, Doctor suggests
107
+ activating the Roll feed-forward slider.
108
+
109
+ ### New — Tuning & profiles
110
+
111
+ - **Three-slider tuning panel (backend).** New endpoints
112
+ `GET/POST /tuning/knobs` map Aggressivity + Understeer/Oversteer +
113
+ Balance-Heading/Rate onto raw P/I/D/DD via `src/tuning-knobs.ts`.
114
+ Identity at (50, 0, 0); all factors clamped to [0.3×, 3.0×]
115
+ baseline. 26 unit tests.
116
+ - **Profile metadata.** `GET /profiles/metadata` + `PUT/DELETE
117
+ /profiles/metadata/:name` for tagging each pypilot profile with a
118
+ condition (light/medium/heavy/motor/custom) and free-text notes.
119
+ Persisted via `savePluginOptions`.
120
+ - **Profile advisor.** Watches the 1 min KPI window and notifies
121
+ when the boat has been tracking sustainedly badly ("consider a
122
+ more aggressive profile") or over-tightly with high servo duty
123
+ ("consider a less aggressive profile"). Never applies anything;
124
+ emits a `notifications.autopilot.pypilot.profileAdvisor` visual
125
+ banner with 5 min cooldown.
126
+ - **Profile change audit log.** New endpoint
127
+ `GET /profile-change-log` shows the last 50 profile transitions
128
+ with attributed source (user / auto-profile / gust-heavy /
129
+ gust-heavy-restore / doctor / external). Answers "who changed my
130
+ profile?" for surprise switches.
131
+
132
+ ### New — Correction episodes + config backup
133
+
134
+ - **Correction episode metrics.** `src/episodes.ts` detects each
135
+ target-step correction and records step-response metrics
136
+ (rise time, overshoot %, settling time, steady-state error).
137
+ Exposed at `GET /episodes` with a good/acceptable/poor quality
138
+ band. Feeds Rule 5 of the Doctor.
139
+ - **Config backup / restore.** `GET /config/export` downloads a
140
+ JSON bundle of plugin options + persistent pypilot settings
141
+ (P/I/D/DD, tack params, servo max_current, etc.). `POST
142
+ /config/import` accepts a bundle and applies it, filtering runtime
143
+ telemetry keys defensively.
144
+
145
+ ### New — Physical control terms
146
+
147
+ - **Roll feed-forward (off by default).** `src/roll-ff.ts` filters
148
+ the dynamic component of `navigation.attitude.roll` and computes a
149
+ small pre-emptive shift of the commanded heading, gated to
150
+ |TWA|>90°. Currently PUBLISHED at
151
+ `steering.autopilot.pypilot.tuning.rollFf.*` for observation; not
152
+ applied to the pilot yet — a later Rev flips that switch after sea
153
+ trial validates the term. Slider lives at `POST
154
+ /supervisor/config` field `rollFfGain` (0..2).
155
+ - **Gust heel-confirmation gate.** The Rev167 gust supervisor now
156
+ cross-checks the AWS jump against a >2° heel change during the
157
+ same 5 s window. A sensor spike that did not physically load the
158
+ boat is suppressed. Falls open when heel data is absent.
159
+
160
+ ### New — Alarms & telemetry
161
+
162
+ - **Persistent servo error log.** JSONL under the plugin dataDir
163
+ records every servo-* alarm transition with a 30 s peak summary
164
+ of pre-fault telemetry (max A, max °C, min V, max heading error).
165
+ Exposed at `GET /servo-error-log`.
166
+ - **Pre-fault trim warnings.** New "info"-severity rules
167
+ `servo-current-trim` (>75% of overcurrent limit) and
168
+ `rudder-range-trim` (>40° absolute) fire *before* the fault-severity
169
+ rules to give the sailor time to trim.
170
+ - **Configurable alarm thresholds.** `alarmLowVoltageV` (8..14 V),
171
+ `alarmServoTempC` (40..85 °C), `alarmServoMotorTempC` (40..90 °C)
172
+ now exposed via `/supervisor/config` and threaded through the
173
+ alarm rules per install.
174
+
175
+ ### New — NAV mode observability
176
+
177
+ - **APB source preview.** `GET /nav/apb-preview` shows the current
178
+ active-waypoint bearing computed both ways — direct `bearingTrue`
179
+ and plotter-provided `steerTo` — plus their divergence. Read-only
180
+ for now; a later Rev may switch to plugin-side NAV mode after sea
181
+ trial validates the preference.
182
+
183
+ ### Under the hood
184
+
185
+ - 8 new source modules with 177 unit tests (up from 5). All
186
+ additive — no existing endpoint or SK path changed contract.
187
+ - Rev sequence 281..297 on branch `feat/blind-batch-sep16`.
188
+
3
189
  ## 2.7.5 — 2026-09-15 — Hotfix on 2.7.4 (visor did not load)
4
190
 
5
191
  **Deprecates 2.7.4.** The restore verdict fix that landed in 2.7.4