signalk-pypilot-newui 2.11.0 → 3.0.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,358 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.0.0 — 2026-10-10 — AIS collision overlay + Freeboard-SK embedded
4
+
5
+ Rolls up Rev431 through Rev438 (8 revs). The headline feature of 3.0.0
6
+ is an AIS collision overlay on the compass rose and a Freeboard-SK
7
+ chart embedded in the rose box on double-tap. Pypilot-newui is a pure
8
+ CONSUMER of the external
9
+ [`signalk-collision-alerts`](https://github.com/dirkwa/signalk-collision-alerts)
10
+ plugin (by @dirkwa, the maintainer of @signalk/app-dock and
11
+ server-admin-ui) and of the Signal K v2 Notifications API — no
12
+ CPA/TCPA engine lives here. The decision rationale is captured in the
13
+ new memory `feedback_signalk_ecosystem_first.md`: Signal K is a
14
+ cooperative ecosystem; reinventing a well-maintained plugin is
15
+ anti-pattern. See `docs/_feature_ais_overlay.md` for the full
16
+ operator guide + install.
17
+
18
+ Carlos classified this bump as **major (3.0.0)** at the start of the
19
+ sprint: it adds a new optional external-plugin dependency, changes
20
+ double-tap-on-rose behaviour (was no-op; now opens Freeboard) and
21
+ introduces a user-facing concept — AIS alarms with ACK — that was
22
+ not present in the 2.x line.
23
+
24
+ ### Added
25
+
26
+ - **AIS collision overlay (Rev431 → Rev438)**. Subscribes to
27
+ `notifications.navigation.closestApproach.<mmsi>` emitted by
28
+ `signalk-collision-alerts`. For each active `warn` / `alarm`:
29
+ - **Red / orange triangle** painted on the compass circle at the
30
+ bearing from the self vessel to the target *as of now* (not the
31
+ CPA future projection — Rev436 fetches the target's current
32
+ position + SOG via `/signalk/v1/api/vessels/<ctx>/...` on each
33
+ delta with a 30 s cache).
34
+ - **Infobox** on top of the self boat with level badge
35
+ (`ALARM` / `WARN`), target name (or "objetivo" when the target
36
+ has no name yet — MMSI never shown or spoken), CPA · TCPA,
37
+ closing speed, ACK button, and when > 1 target is active a
38
+ `N/M` navigator with `‹` / `›`.
39
+ - **Voice**: short Spanish sentence built from the raw data, not
40
+ the plugin's English string (which TTS garbled into "ce-pe-a cero
41
+ coma cero cuatro ene eme"). Example: *"Alarma A I S, PIRATA DE
42
+ ONS, a 47 metros, ya"*.
43
+ - **ACK** button sends `POST /signalk/v2/api/notifications/<id>/acknowledge`
44
+ (so Freeboard + every SK consumer sees it) AND silences the MMSI
45
+ locally for 10 min — survives the plugin re-publishing the same
46
+ threat with a fresh UUID.
47
+ - **"Silenciadas…" modal** (Rev438) lists every locally-silenced
48
+ MMSI with remaining minutes + per-row *Reactivar* + bulk *Reactivar
49
+ todas*.
50
+ - **Stationary filter** (Rev436): targets whose cached SOG < 0.15 kn
51
+ are dropped from the UI even if the plugin keeps emitting the
52
+ alarm. Mandatory in a Ría with dozens of moored vessels.
53
+ - **Overlay-card in Setup → ROSE OVERLAYS**: master on/off, voice
54
+ sub-toggle, link to the plugin's config page, access to the
55
+ silenced modal.
56
+ - **Freeboard-SK embedded in the rose box** (Rev432 → Rev433). Double-
57
+ tap `#wind-rose` opens `/@signalk/freeboard-sk/` as an iframe
58
+ positioned inside the compass square so the side panels (mode,
59
+ nudges, AP) stay visible. Chrome row has ⤢ Maximize (full
60
+ viewport) / ⤡ Restore / × Close. Iframe `src` cleared on close so
61
+ Freeboard releases its websocket.
62
+
63
+ ### Changed
64
+
65
+ - No breaking API changes to the pypilot-newui plugin itself —
66
+ everything existing in 2.12.0 still works identically. The 3.0.0
67
+ bump reflects the new user-facing concepts (AIS alarms, Freeboard
68
+ entry point) and the optional external-plugin dependency.
69
+
70
+ ### Fixed
71
+
72
+ Bugs found and fixed during the AIS sprint, each informed by Carlos's
73
+ QA notes and the real SK bus on Tunatunes:
74
+ - **ACK button did not close the infobox** (Rev436). Was keyed by
75
+ notification UUID (Rev434); plugin cycles the id while the threat
76
+ persists → infobox resurrected on the next delta. Now keyed by
77
+ MMSI with a 10-minute TTL.
78
+ - **Triangle 180° off** (Rev436). Rev431 pointed at
79
+ `data.cpaPositions.target` which is the *projected* position at the
80
+ CPA future instant — hence "me avisa babor cuando el target me
81
+ viene por aleta estribor". Now uses the current self + target
82
+ positions fetched from the SK REST API.
83
+ - **Multiple alarms, including moored vessels** (Rev436). Added the
84
+ stationary SOG < 0.15 kn drop filter so a Ría with 30 moored boats
85
+ doesn't fire false alarms through the plugin's own thresholds.
86
+ - **TTS garble on Freeboard open** (Rev436). Removed the
87
+ `_alSpeak("abriendo carta")` that the English TTS read as "ICE
88
+ open chat".
89
+ - **Overlay-card nested checkbox hidden under the master** (Rev437).
90
+ CSS `.overlay-card input[type=checkbox]` matched every checkbox and
91
+ stacked them at top-right. Scoped to direct child so the AIS
92
+ card's "Voice alert" sub-toggle renders in-flow.
93
+
94
+ ### Known limitations / upstream work
95
+
96
+ - **Upstream `signalk-collision-alerts` issue #17** —
97
+ https://github.com/dirkwa/signalk-collision-alerts/issues/17 — the
98
+ admin UI does not render the `Alert sensitivity` / `Level`
99
+ dropdowns because the plugin's typebox schema emits `anyOf+const`
100
+ instead of `enum`. We filed the issue with a fix proposal; the
101
+ workaround is to hand-edit the plugin JSON config or patch the
102
+ built `config.js` locally. See `docs/_feature_ais_overlay.md`.
103
+ - **Needs sea-trial QA** on real moving traffic with mixed `warn` /
104
+ `alarm` targets. Default sensible config documented
105
+ (preset: `harbour`, `maxRange`: 3 NM) for a Ría-style navigation
106
+ env; switch to `coastal` / `offshore` as needed.
107
+
108
+ ---
109
+
110
+ ## 2.12.0 — 2026-10-08 — Virtual-tack audit cycle + Profile UX overhaul + safety aproado/empopado
111
+
112
+ Rolls up Rev410 through Rev430 (21 revs). Driven by two sea trials
113
+ (2026-10-03 and 2026-10-04) that exposed critical virtual-tack bugs
114
+ and a batch of UX problems around profiles and the mode selector.
115
+ Six audit MDs accompany the fixes (`docs/_audit_commit[2-6]_pre_rev*.md`
116
+ + `docs/_sea_trial_2026-10-04.md`) following the "audit before fix"
117
+ rule that paid for itself after three failed attempts at the drag/drop
118
+ bug.
119
+
120
+ ### Added
121
+
122
+ - **Virtual-tack audit cycle (Commits 2–6 of the Rev407 plan)**.
123
+ - *Commit 2 (Rev410)* — Mando trace enrichment (`ap.tack.state` and
124
+ `ap.tack.direction` deltas now log heading + AWA + mode + vtPhase),
125
+ VT `remainingDeg` on the mirror HUD (shows "N°" while turning,
126
+ "settling" during the handover phase), explicit "VT fallida: X"
127
+ toast when the backend publishes a terminal `failed` snapshot.
128
+ - *Commit 3 (Rev411)* — Writes propagate pypilot refusal through
129
+ `PUT /raw`, the SignalK v2 PUT handler and the `/ap/*` fallbacks
130
+ (503 instead of a false 200), and `dodge()` throws so KIP sees
131
+ the failure.
132
+ - *Commit 5 (Rev412)* — Empopado hot-gains that **actually apply**
133
+ (silent no-op since Rev320: the code read `catalog[path].value`
134
+ which never existed). Reads from `state.pypilotValues[path]`
135
+ now. New `data-hot={on|off|failed}` badge inside the active HUD
136
+ makes the PID state visible.
137
+ - *Commit 6 (Rev413)* — Yellow (warn) toast when settling times out
138
+ but the compass rotation finished: "Virada completada, viento sin
139
+ converger". Target is still applied; sailor sees it did not fully
140
+ confirm.
141
+ - *Commit 4 (Rev414)* — AWA settling EMA with τ ≈ 2 s applied to the
142
+ noisy raw apparent-wind sample. Fixes the "settling-timeout" seen
143
+ on light-wind sea trials. 4 unit tests cover seed / convergence /
144
+ ±π wrap-around / α = 0 identity.
145
+ - **Virtual-tack final-angle override** (Rev416, fix #12). Backend
146
+ accepts optional `finalAngleRad` on `/virtual-tack/start`; the visor
147
+ forwards whatever is set in `localStorage.pypilotnewui.tackFinalAngleDeg`.
148
+ Sailor can trim the destination AWA ±170° without having to nudge
149
+ after the tack. Backend validates (`|rad| ≤ π`) and falls back to
150
+ the AWA mirror on any invalid value.
151
+ - **EMA staleness guard** (Rev415). The settling loop now reads
152
+ `p.timestamp` from the SK path; samples older than
153
+ `STALE_SAMPLE_MS = 3000` are ignored, the dwell counter resets, and
154
+ the EMA state is cleared so a frozen value (e.g. after a WiFi
155
+ dropout) cannot sneak into the "ok" window.
156
+ - **Nudge target trace** (Rev415, fix #1 instrumentation).
157
+ `apSetTargetRad` logs the current target / heading / AWA / TWA /
158
+ mode / engaged BEFORE each PUT and the status / ok AFTER, so a
159
+ stale-UI vs. real-refusal diagnosis is trivial on the next sea trial.
160
+ - **Mode selector custom modal** (Rev425 → Rev430, fix #13 iterated).
161
+ Replaces the native `<select>` with a centered modal built lazily
162
+ under `<body>` (`.mode-select-modal-backdrop`). Contents:
163
+ - "MODO" label + list; the active mode highlighted in accent blue.
164
+ - "PERFIL" label + autowrapping button (1–2 lines so long names
165
+ like "Ceñida fondo medio viento" fit).
166
+ - Nested list opens **upward** (position: absolute; bottom: 100%)
167
+ so expanding profiles does not force the modal to scroll.
168
+ - Idempotent repaint — SK deltas never flash the open modal.
169
+ - **Doctor suggestions sorted + numbered** (Rev417, fix #8). Visor
170
+ pre-sorts by the same priority map the backend `applyAll` uses
171
+ (`bias < authority < oscillation < noise`), stamps a 1-based
172
+ ordinal prefix ("1.", "2.", "3.") on each card and gives the first
173
+ pending suggestion a `.top-priority` accent border so the sailor
174
+ can see which card the "Apply top priority" button will target.
175
+ - **Unlock prompt** (Rev421, fix #7). Flipping a group's unlock
176
+ checkbox opens a 3-choice modal ("Editar en perfil actual" /
177
+ "Cambiar a 'basic' primero" / "Cancelar") so the sailor explicitly
178
+ chooses the edit scope before touching sliders. Modal body answers
179
+ the second half of Carlos's question: "Los cambios se aplican en el
180
+ acto, no hace falta cerrar la pantalla."
181
+
182
+ ### Changed
183
+
184
+ - **Safety: aproado/empopado restoreAll default = false** (Rev415,
185
+ fix #11). Carlos: "hay que anular el restituir rumbo cuando salimos
186
+ de aproado o empopado porque es peligroso". Pre-Rev415 the finish
187
+ path unconditionally restored mode + target + disengage; now it
188
+ leaves the pilot where it is unless the caller opts in. The
189
+ "lost stern" auto-cancel in empopado passes `restoreAll:false` too.
190
+ - **Fork modal wording** (Rev418, fix #6). The "Keep in '{pilot}'"
191
+ button was filling `{pilot}` with `state.pilot` (always "basic"),
192
+ misleading when the active profile was called something else. Now
193
+ reads "Guardar en el perfil activo" + an info line showing the
194
+ actual profile + pilot pair. Cancel label clarified to
195
+ "Cancelar (deshacer último cambio)".
196
+ - **VT mirror watchdog raised 60 s → 120 s** (Rev410, fix U.2) so it
197
+ does not race the backend's own `PYPILOT_STUCK_MS = 60 s`.
198
+ - **Pypilot-silent watchdog gated on VT state** (Rev410, fix U.1).
199
+ During a VT the backend owns the authoritative stuck detection;
200
+ the legacy 40 s time-since-delta heuristic only fires on native
201
+ tack paths (no VT active) to avoid false "virada cancelada" toasts.
202
+ - **Fork modal strings fully translated** (Rev419, fix #6 follow-up).
203
+ Modal title, body and name label were English fallbacks because
204
+ `data-i18n` is not walked on dynamic `innerHTML`; now set
205
+ explicitly from `t()` after creation.
206
+
207
+ ### Fixed
208
+
209
+ - **Profile Manager drag/drop ping-pong flicker** (Rev420 after Rev418
210
+ and Rev419 attempts). The live-reorder approach was intrinsically
211
+ unstable — after each `insertBefore` the next `pointermove`
212
+ re-triggered a swap. Rewritten with the deferred-commit pattern:
213
+ only `translateY` the dragged item during the gesture, mark the
214
+ nearest drop-target with a visual line, commit one `insertBefore`
215
+ at the end. Also moved listeners to `window` + pointerId filter
216
+ (was on the handle, failed silently on tablet browsers) and gave
217
+ `.pm-item.dragging { touch-action: none }` so the gesture is not
218
+ interpreted as a scroll. Flash animation `.just-moved` on commit
219
+ confirms the move landed.
220
+ - **Tack stats HUD "dejaron de salir" + z-index + X not clickable**
221
+ (Rev416, fix #10). The HUD was only wired to the native pypilot
222
+ tack path (`_tackCountdownTick` arrived); VT (wind mode) never
223
+ triggered it. Terminal `virtualTack` snapshots now call
224
+ `_tackStatsOnTackCompleted` (completed) or
225
+ `_tackStatsOnTackCancelled` (cancelled/failed). Corner tiles had
226
+ `z-index:3` and the SVG wind-rose had no stacking context, so the
227
+ HUD painted behind corners; added a `stats-hud-up` class on
228
+ `.dash-rose` that raises `.rose-wrap` to `z-index:5` while the HUD
229
+ is open and drops corners to `z-index:1` with
230
+ `pointer-events:none`. Close × hit area widened to 34 × 34 so
231
+ off-centre taps still land.
232
+ - **Mode modal "se carga dos veces"** (Rev428). `refreshPypilotValues`
233
+ called `_rebuildModeSelect()` twice back-to-back (once when
234
+ `profiles` landed, once when `profile` landed) and each call
235
+ wiped-and-repopulated the modal's sub-select, producing a visible
236
+ double flash. Consolidated into a single `needsModeRebuild` flag
237
+ + made `_rebuildModePopupProfiles` idempotent (diffs the current
238
+ option list and skips the repaint when it matches).
239
+ - **Mode popup viewport cropping** (Rev426 before the Rev427 full
240
+ redesign). Pre-Rev427 the anchored popup overflowed the viewport
241
+ bottom on 80 %-zoom laptops and phone portrait; added
242
+ viewport-aware placement + internal scroll before deciding to
243
+ switch to a centered modal anyway.
244
+ - **Doctor "Apply top priority" button targets the right card**
245
+ (Rev417 side-effect of #8). The visor now mirrors the backend's
246
+ priority sort so the highlighted card is always the one the button
247
+ will apply.
248
+
249
+ ### Known limitations / pending real-water verification
250
+
251
+ - Rev410 U.2 / U.3 — 120 s watchdog + "VT fallida" toast on backend
252
+ `outcomeReason` need a real pypilot-dead moment to confirm.
253
+ - Rev411 J.1 / J.2 / J-1.5 — 503 propagation on `PUT /raw`, SK v2 PUT
254
+ handler and `dodge()` need pypilot genuinely offline to exercise.
255
+ - Rev412 — "aggressive PID" on empopado now ACTUALLY writes gains to
256
+ pypilot (dormant since Rev320). Validate in water that the new
257
+ P × 1.5 / D × 1.7 / servo-slew × 1.3 does not cause oscillation.
258
+ - Rev414 — AWA EMA τ = 2 s needs confirmation in light wind that the
259
+ dampened sample reaches the ±10° / 2 s dwell to produce
260
+ `completed:ok` instead of `settling-timeout`.
261
+ - Rev416 — final-angle override is exposed via `localStorage` only; a
262
+ slider UI will come in a later rev.
263
+ - Observation #2 from the 2026-10-04 sea trial (pilot behaves as if
264
+ tracking true wind in `wind` mode) is still open and awaits the
265
+ next sea trial's nav-session data with the Rev415 instrumentation
266
+ to confirm it as a real bug vs. a PID-tuning symptom.
267
+ - Observation #9 — AIS collision overlay on the rose — is planned for
268
+ the next **major (3.0.0)** bump; the design is drafted in
269
+ `docs/_audit_feature9_ais_overlay.md` but not implemented yet.
270
+
271
+ ---
272
+
273
+ ## 2.11.0 — 2026-09-30 — Sea-trial Sprint K fixes + severity override + portrait layout
274
+
275
+ Rolls up Rev324 through Rev376. Between 2.10.0 (Rev323) and 2.11.0 the
276
+ plugin went through a second sea trial (2026-09-28, 27 min on Tunatunes)
277
+ that surfaced 13 bugs. The ones not requiring open water are fixed in
278
+ this release; the remainder (aproado/empopado true-wind, mando-físico
279
+ HUD mirror) are implemented and awaiting sea-trial QA.
280
+
281
+ ### Added
282
+
283
+ - **Per-rule alarm severity override** (Rev342 backend + Rev374 frontend).
284
+ Each rule in Setup > Alarms now has an inline `🔴 Alarma / 🟡 Aviso /
285
+ 🔵 Info` dropdown. Changes are persisted via `props.alarmSeverityOverrides`
286
+ so they survive restarts. The shipped default is marked with `★` so the
287
+ sailor can see which option is the factory setting before changing it.
288
+ Endpoint: `POST /alarms/severity/:id {severity}`.
289
+ - **Mute countdown mm:ss** (Rev375). The muted-rule status pill now shows
290
+ real-time `MM:SS` (updated every second) instead of coarse `N minutes`.
291
+ - **Maneuver HUD mirror for external tacks** (Rev348 → Rev355). When a
292
+ tack is triggered from the pypilot native UI or physical remote, the
293
+ visor opens the overlay, animates the orange buttons, and emits the
294
+ post-tack stats panel — the same experience as a visor-initiated tack.
295
+ - **Tack cancellation stats** (Rev355). Cancelling mid-tack shows the HUD
296
+ immediately with `pre` + "CANCELADO" and no post window.
297
+ - **Pypilot-silence watchdog** (Rev367). If pypilot stops sending `ap.tack.state`
298
+ deltas for more than 60 s during a maneuver, the visor closes the mirror
299
+ overlay itself so the UI doesn't hang indefinitely on a lost connection.
300
+ - **Observability instrumentation** (Rev346). `maneuver-trace` now logs
301
+ stage events (`wallTs + monoTs`) for frontier debugging, plus `mtLog`
302
+ calls in `pluginRaw` and the `ap.tack.state/direction` handleDelta
303
+ branch tag the event source as `external` vs visor-local.
304
+ - **Heap diagnostics** sidecar (preserved from Rev885-equivalent work):
305
+ internal structure sizes under `/api/diagnostic.heapAudit` for
306
+ long-term RSS tracking.
307
+
308
+ ### Changed
309
+
310
+ - **Tack stats post window shortened** 60 s → 15 s (Rev371). Was 30 s
311
+ wait + 30 s measurement; now 5 s wait + 10 s measurement. 10 samples at
312
+ 1 Hz still yield a stable TWS/AWA/SOG average.
313
+ - **Rate-of-turn fallback more conservative** (Rev345). Minimum completion
314
+ threshold raised to `max(20°, total × 0.4)` so brief rotations don't
315
+ trigger a premature "tack completed" verdict.
316
+ - **Portrait tablet layout** (Rev370). `font-size` media queries at
317
+ 900 / 1200 / 1600 / 2000 px heights cascade through `em` units to
318
+ scale both the rose and the surrounding buttons on tall tablets.
319
+ Confirmed working on Opera Mobile (where `zoom` had no effect).
320
+ - **Button labels in wind mode** (Rev343). `±100°` becomes `VIRAR ← / →`
321
+ when the pilot is in `wind` or `truewind`, matching the actual
322
+ semantics.
323
+ - **Cancel labels during active maneuver** (Rev343). The orange buttons
324
+ show `CANCELAR VIRADA` or `CANCELAR TRASLUCHADA` instead of their
325
+ normal text so the sailor knows what tapping them will do.
326
+
327
+ ### Fixed
328
+
329
+ - **Diamond target stuck on external tacks** (Rev347). The
330
+ `_countdownPlannedTargetRad` variable now only masks `state.target`
331
+ when the countdown overlay is actually visible; stale values from
332
+ previously aborted visor tacks are cleared belt-and-suspenders.
333
+ - **Severity dropdown reverted to default on every poll** (Rev375,
334
+ `alarms.ts` `describe()`). Was returning `rule.severity` (the factory
335
+ default) instead of `s.severity` (the runtime value with override
336
+ applied). Fixed to return `s.severity`.
337
+ - **Visor countdown mask over authoritative state** (Rev347 lesson,
338
+ documented pattern). Any JS variable that fronts an authoritative
339
+ bus value must be gated by a visible UI signal, not by a cleanup
340
+ that may not fire on every abort path.
341
+
342
+ ### Known limitations
343
+
344
+ - Aproado / empopado true-wind flow (`apSetMode("wind")` with
345
+ `await state.mode = "wind"` before `apSetTargetRad`) is implemented
346
+ but awaits sea-trial QA.
347
+ - Physical-remote tack → HUD mirror hook (bug #7 from the 2026-09-28
348
+ trial) is implemented via `observeTackTransition` + `external` flag
349
+ but awaits sea-trial validation.
350
+ - The pypilot-core direction rewrite for short-arc wind tacks is
351
+ upstream (not our plugin) and remains open; a GitHub issue is drafted
352
+ but not yet posted to Sean D'Epagnier.
353
+
354
+ ---
355
+
3
356
  ## 2.10.0 — 2026-09-27 — Sea-trial wind-mode fixes + maneuver forensics
4
357
 
5
358
  Rolls up Rev309 through Rev323. Between 2.9.0 (Rev280) and 2.10.0 the
package/README.md CHANGED
@@ -235,6 +235,37 @@ pypilot version, restart pypilot_web).
235
235
 
236
236
  **Webapp URL**: `http://<sk-host>:3000/signalk-pypilot-newui/`
237
237
 
238
+ ## Works well with
239
+
240
+ Pypilot-newui is built as a well-behaved citizen of the Signal K
241
+ ecosystem — it consumes other mature plugins and standard APIs instead
242
+ of reinventing them. The sections below describe the plugins we
243
+ integrate with; none are hard dependencies (the autopilot visor works
244
+ on its own), but installing them unlocks the features listed.
245
+
246
+ - **[`@signalk/freeboard-sk`](https://www.npmjs.com/package/@signalk/freeboard-sk)**
247
+ — Double-tap the compass rose to open Freeboard-SK embedded inside
248
+ the rose box (side panels stay visible and usable). Lets you drop
249
+ from the autopilot view to the full chart with every AIS target in
250
+ one tap, without leaving the pypilot-newui session.
251
+ See `docs/_feature_ais_overlay.md`.
252
+
253
+ - **[`signalk-collision-alerts`](https://www.npmjs.com/package/signalk-collision-alerts)**
254
+ by @dirkwa — Provides the CPA/TCPA engine behind our AIS collision
255
+ overlay. Pypilot-newui subscribes to
256
+ `notifications.navigation.closestApproach.*` and renders a red /
257
+ orange triangle on the rose + an infobox with ACK that routes
258
+ through the Signal K v2 Notifications API, so an ACK from
259
+ pypilot-newui is also seen by Freeboard-SK and every other SK
260
+ client.
261
+ See `docs/_feature_ais_overlay.md`.
262
+
263
+ - **[`pypilot-autopilot-provider`](https://www.npmjs.com/package/pypilot-autopilot-provider)**
264
+ by Panaaj — Shares the single pypilot socket cleanly with our
265
+ autopilot provider (see next section) so KIP, Freeboard's Autopilot
266
+ Console and any other SK v2 Autopilot API client all drive the same
267
+ pilot without duplicate connections.
268
+
238
269
  ## Working alongside `pypilot-autopilot-provider`
239
270
 
240
271
  We build on top of the excellent
@@ -316,6 +347,7 @@ that isolated TinyPilot.
316
347
  | `POST` | `/plugins/signalk-pypilot-newui/alarms/ack/:id` | Acknowledge one active alarm (silences the sound, banner stays visible). |
317
348
  | `POST` | `/plugins/signalk-pypilot-newui/alarms/mute/:id` | Mute the RULE for N minutes (query `?min=15`). |
318
349
  | `POST` | `/plugins/signalk-pypilot-newui/alarms/enable/:id` | Enable / disable a rule (query `?on=1\|0`). |
350
+ | `POST` | `/plugins/signalk-pypilot-newui/alarms/severity/:id` | Override the severity of one rule. Body: `{ "severity": "info\|warn\|alarm" }`. Persists via `props.alarmSeverityOverrides` so it survives restart. |
319
351
  | `GET` | `/plugins/signalk-pypilot-newui/prechecks` | Pre-departure autopilot check verdict: `ready` / `ready-with-caveats` / `do-not-engage` + per-item detail. |
320
352
  | `POST` | `/plugins/signalk-pypilot-newui/doctor/start` | Start a diagnostic session (query `?duration=180`). Requires AP engaged. |
321
353
  | `POST` | `/plugins/signalk-pypilot-newui/doctor/cancel` | Cancel the current session. |