signalk-wakelogger 0.2.0-beta.10 → 0.2.0-beta.11

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.
Files changed (48) hide show
  1. package/CHANGELOG.md +28 -6
  2. package/README.md +6 -6
  3. package/dist/config/schema.d.ts +2 -2
  4. package/dist/config/schema.js +2 -2
  5. package/dist/config/schema.js.map +1 -1
  6. package/dist/courses/course-store.d.ts +13 -0
  7. package/dist/courses/course-store.js +45 -4
  8. package/dist/courses/course-store.js.map +1 -1
  9. package/dist/index.js +51 -11
  10. package/dist/index.js.map +1 -1
  11. package/docs/evidence/course-progress-source.md +88 -0
  12. package/docs/evidence/eta-correction-independent-review.md +67 -0
  13. package/docs/evidence/eta-independent-recheck.md +161 -0
  14. package/docs/evidence/eta-independent-review.md +82 -0
  15. package/docs/evidence/eta-native-source-availability.md +120 -0
  16. package/docs/evidence/eta-order-recheck.mjs +20 -0
  17. package/docs/evidence/eta-order-repro.mjs +11 -0
  18. package/docs/evidence/eta-print-recheck.mjs +33 -0
  19. package/docs/evidence/eta-production-independent.md +25 -0
  20. package/docs/evidence/eta-production-investigation.md +140 -0
  21. package/docs/evidence/eta-production-reconstruction.json +64 -0
  22. package/docs/evidence/eta-production-repro.py +53 -0
  23. package/docs/evidence/eta-source.md +206 -0
  24. package/docs/evidence/finish-trip-controls.md +76 -0
  25. package/docs/evidence/finish-trip-independent-review.md +64 -0
  26. package/docs/evidence/leg-average-boundary-independent-recheck.md +67 -0
  27. package/docs/evidence/leg-average-eta.md +255 -0
  28. package/docs/evidence/leg-average-independent-check.mjs +37 -0
  29. package/docs/evidence/leg-average-independent-review.md +80 -0
  30. package/docs/evidence/live-tracking-confirmation.md +112 -0
  31. package/docs/evidence/live-tracking-independent-verification.md +66 -0
  32. package/docs/evidence/overlays/direct-ground-gybe-1280.png +0 -0
  33. package/docs/evidence/overlays/direct-ground-gybe-390.png +0 -0
  34. package/docs/evidence/overlays-source.md +102 -0
  35. package/docs/evidence/the903/frontend-lint-final-independent.md +75 -0
  36. package/docs/evidence/true-wind-source.md +174 -0
  37. package/docs/evidence/vmg-independent.md +77 -0
  38. package/docs/evidence/vmg-source.md +111 -0
  39. package/docs/releases/0.2.0-beta.11.md +27 -0
  40. package/package.json +5 -5
  41. package/public/app.mjs +47 -28
  42. package/public/course-progress.mjs +56 -18
  43. package/public/index.html +4 -4
  44. package/public/instruments.mjs +64 -23
  45. package/public/leg-eta.mjs +49 -0
  46. package/public/style.css +2 -0
  47. package/public/tracking-controls.mjs +31 -0
  48. package/public/vessel-guides.mjs +26 -9
package/CHANGELOG.md CHANGED
@@ -2,6 +2,34 @@
2
2
 
3
3
  Updates for boat owners and crew: what's new, what's improved, and anything you need to do.
4
4
 
5
+ ## [0.2.0-beta.11] - 2026-10-17
6
+
7
+ ### Live tracking asks before it changes
8
+
9
+ - Turning **Live tracking** on or off now asks you to confirm the change and names its effect. The new setting is only reported once it has been saved onboard, and if the setting changed somewhere else the app re-reads it instead of overwriting it.
10
+ - Live transmission can only be switched on by the confirmed control in the onboard app. The Signal K plugin settings page no longer turns uploads on by itself.
11
+
12
+ ### An ETA that follows the leg you are sailing
13
+
14
+ - The Race tab's ETA and VMG are based on your net progress along the current leg — the leg-average speed actually being made good — instead of native time-to-go or a single speed sample. The value is labelled **Leg-average VMG (ground)**. During the first minute of a leg, a matching Wake Logger leg plan may provide a clearly labelled provisional estimate **(plan)**.
15
+ - If the position, speed or course data needed for the estimate is missing, stale or out of sync, the ETA is withheld and the reason is shown instead. Estimates outside normal sailing speeds or more than a day away are not displayed.
16
+
17
+ ### Wind values labelled by their source
18
+
19
+ - True wind angle is derived relative to the bow, never the boat's course, and is worked out separately for each velocity reference, so a ground-based result can no longer stand in for water wind.
20
+ - Wind VMG is computed and labelled per reference (ground or water). A value that would mix references, or that is stale, is shown as unavailable instead of being displayed.
21
+
22
+ ### A clearer map, progress and finish
23
+
24
+ - Course progress now shows the distance sailed along the active leg, so it advances smoothly between waypoints instead of jumping at each mark.
25
+ - **Finish trip** is always a local save: cloud connection, upload queue and race readiness never block it, and a failed attempt explains the exact cause with a safe retry path.
26
+ - The heading and tack/gybe guide label now names the current tack and stays visible, and the map frames the boat even before a course or track exists. Guides still take no tide or leeway into account.
27
+
28
+ ### Updating
29
+
30
+ - Update Wake Logger in the Signal K App Store and restart Signal K if prompted. Your settings, pairing and recorded trips are retained.
31
+ - After this update, **confirm Live tracking ON in the onboard app** to resume uploading new trips. Until you confirm, the plugin keeps recording locally and live transmission stays off — a saved setting or the plugin configuration page can no longer start transmitting by itself.
32
+
5
33
  ## [0.2.0-beta.10] - 2026-10-11
6
34
 
7
35
  ### Race-day navigation survives course activation failures
@@ -69,8 +97,6 @@ Updates for boat owners and crew: what's new, what's improved, and anything you
69
97
  - A source time more than 30 days before the delta was delivered is treated as a broken clock and replaced by receipt time, instead of being queued and later rejected by Wake Logger as outside the vessel's entitled capture window (for example a GPS reporting a stale 2014 default date).
70
98
  - The database outbox now declares sequences skipped by a seed or reset as dropped when it opens, matching the file outbox, so the cloud's contiguous acknowledgement can advance and later trips are not left waiting for history.
71
99
 
72
- ## [Unreleased] - 2026-09-27
73
-
74
100
  ### Offline race readiness you can trust
75
101
 
76
102
  - One clear **Offline race ready** status now checks that the selected course is applied, the expected Signal K route is active, and a Race Pack that matches the course (id, race plan and course definition) is prepared with supported rules and a current forecast. Changing the course immediately invalidates readiness for the old pack, even though that pack is kept for history.
@@ -80,10 +106,6 @@ Updates for boat owners and crew: what's new, what's improved, and anything you
80
106
 
81
107
  - Failed Signal K requests now keep the operation, method, path, HTTP status and a bounded, credential-safe reason. Advancing, setting or activating a course shows a human-readable message such as "Could not advance to the next course point to Mark 3 — Signal K rejected the active route update: <reason>", and the bounded detail is written to the plugin log. Tokens and passwords are never logged or displayed.
82
108
 
83
- ### A track that survives reload
84
-
85
- - The onboard map now rebuilds the current recording's track from an independent durable onboard archive on open or reload, rather than starting at page-open time and rather than depending on whether telemetry has already been uploaded. New fixes append incrementally; long trips are decimated for display without changing the recording; and the complete geometry survives browser reload, page-resume and plugin restart with no Wake Logger/cloud connection. A tail-only cloud trip is marked "Reconstructing trip · N% history received" until its history converges.
86
-
87
109
  ### Standalone vessel instruments
88
110
 
89
111
  - A new **Instruments** tab is the default when no course is selected. It reads position, speed and course over ground, heading (true or magnetic), speed through water, depth (with its reference), and apparent and true wind directly from the local Signal K server.
package/README.md CHANGED
@@ -29,7 +29,7 @@ The plugin requires Node.js 20 or newer on the Signal K server. Your boat does n
29
29
  1. In Signal K's **App Store**, install **Wake Logger** (`signalk-wakelogger`).
30
30
  2. In Wake Logger, open your vessel's settings and generate a Signal K pairing code.
31
31
  3. Open **Wake Logger** in Signal K's plugin configuration, enter the code and save. Enable the plugin if it is disabled.
32
- 4. Check the connection status. When your boat supplies a position and the connection is online, it will appear in the vessel's **Signal K Live** view in Wake Logger.
32
+ 4. Open the onboard **Wake Logger webapp** and confirm **Live tracking** on when you are ready to upload. Check the connection status. When your boat supplies a position and the connection is online, it will appear in the vessel's **Signal K Live** view in Wake Logger.
33
33
 
34
34
  Pairing codes are single-use. If a code expires or is rejected, generate a new one. You do not need to pair again after an ordinary internet outage or plugin update.
35
35
 
@@ -37,13 +37,13 @@ Pairing codes are single-use. If a code expires or is rejected, generate a new o
37
37
 
38
38
  Recording and uploading are separate. Keep Signal K and the Wake Logger plugin running, with your boat's navigation data available, for the trip to be recorded.
39
39
 
40
- **For normal use:** Leave **Upload mode** set to **Automatic upload**. If internet access drops, the plugin stores readings onboard and uploads them when the connection returns.
40
+ **For normal use:** Confirm **Live tracking** on in the onboard Wake Logger app. If internet access drops, the plugin stores readings onboard and resumes uploads when the connection returns, provided your confirmed choice is still on.
41
41
 
42
- **To deliberately defer uploading:** Pair first, then turn **Live tracking** off on the onboard Wake Logger map. The plugin keeps recording locally, up to your storage and age limits. Turn it on when you are ready to send your live position and upload stored history. Changing the switch does not end a trip or restart recording, and the setting survives restarts.
42
+ **To deliberately defer uploading:** Pair first, then confirm **Live tracking** off on the onboard Wake Logger map. The plugin keeps recording locally, up to your storage and age limits. Confirm it on when you are ready to send your live position and upload stored history. Changing the switch does not end a trip or restart recording, and the confirmed setting survives restarts and configuration updates. Both directions require confirmation. New installations and upgrades without a readable confirmed choice start with live tracking off; confirm it on in the onboard app when ready. Saving the legacy upload mode in plugin settings cannot enable live tracking.
43
43
 
44
- You can also choose **Record locally** or **Automatic upload** in the plugin's **Upload mode** setting. These controls change the same setting.
44
+ The plugin configuration still shows the legacy **Upload mode** setting. Saving **Record locally** or **Automatic upload** there does not change your confirmed live-tracking choice. Use the onboard **Live tracking** switch to change it.
45
45
 
46
- On reconnecting, the latest position is sent promptly while stored history uploads in the background. With the supporting Wake Logger service update, your vessel view shows the percentage of stored history uploaded and an estimated time remaining once there is enough upload progress to measure. Estimates pause when the connection is lost. Detailed recording updates are available under **Upload details**. Wake Logger uses the recorded movement and times to identify trips; switching live tracking does not itself create a new trip. Missing or rejected readings are flagged rather than presented as a complete trip.
46
+ On reconnecting with **Live tracking** on, the latest position is sent promptly while stored history uploads in the background. Reconnecting with it off keeps recording local and does not enable uploads. With the supporting Wake Logger service update, your vessel view shows the percentage of stored history uploaded and an estimated time remaining once there is enough upload progress to measure. Estimates pause when the connection is lost. Detailed recording updates are available under **Upload details**. Wake Logger uses the recorded movement and times to identify trips; switching live tracking does not itself create a new trip. Missing or rejected readings are flagged rather than presented as a complete trip.
47
47
 
48
48
  **When you dock:** Tap **Finish trip** before switching off boat power. The plugin saves the trip’s actual final recorded sequence and capture time immediately, including offline and with Live tracking off. **Saved onboard · upload pending** is local success, not cloud confirmation. Keep power and Live tracking on until **Trip confirmed ready by cloud** appears if you need confirmation now; the same connection checks receipt coverage and processing. Otherwise the pending finish survives restart and uploads later. The automatic 15-minute stationary stop remains the fallback. Finish trip does not change the active Signal K route, and fresh movement can start a new recording.
49
49
 
@@ -93,7 +93,7 @@ Vessel roles and sharing settings in Wake Logger control who can see your data.
93
93
  ## If something is not working
94
94
 
95
95
  - **Not paired:** Generate a pairing code in Wake Logger and enter it in the plugin settings.
96
- - **Offline or waiting to upload:** Check **Upload mode**, your internet connection and the plugin's queue status. Leave the plugin running so it can record and retry.
96
+ - **Offline or waiting to upload:** Check **Live tracking** in the onboard app, your internet connection and the plugin's queue status. Confirm Live tracking on when you want uploads to resume. Leave the plugin running so it can record and retry while tracking is on; saving the legacy **Upload mode** setting cannot enable uploads.
97
97
  - **No vessel position:** Check that Signal K itself is receiving a valid position from your boat.
98
98
  - **Course not active:** Check whether another app selected a route. Reactivate the Wake Logger course when appropriate.
99
99
  - **Blank basemap:** Check your selected chart source and local coverage. Course and vessel information can still be displayed.
@@ -7,8 +7,8 @@ export declare const configSchema: {
7
7
  readonly title: "Upload mode";
8
8
  readonly enum: readonly ["automatic", "local_only"];
9
9
  readonly enumNames: readonly ["Automatic upload", "Record locally"];
10
- readonly default: "automatic";
11
- readonly description: "local_only records on this boat without any Wake Logger network traffic. Pair first. Save automatic when ready to upload the queue.";
10
+ readonly default: "local_only";
11
+ readonly description: "Legacy upload setting. Live tracking is controlled only by the confirmed switch in the onboard Wake Logger app; saving this setting cannot enable uploads.";
12
12
  };
13
13
  readonly pairingCode: {
14
14
  readonly type: "string";
@@ -10,8 +10,8 @@ exports.configSchema = {
10
10
  title: 'Upload mode',
11
11
  enum: ['automatic', 'local_only'],
12
12
  enumNames: ['Automatic upload', 'Record locally'],
13
- default: 'automatic',
14
- description: 'local_only records on this boat without any Wake Logger network traffic. Pair first. Save automatic when ready to upload the queue.'
13
+ default: 'local_only',
14
+ description: 'Legacy upload setting. Live tracking is controlled only by the confirmed switch in the onboard Wake Logger app; saving this setting cannot enable uploads.'
15
15
  },
16
16
  pairingCode: {
17
17
  type: 'string',
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":";;;AAAa,QAAA,YAAY,GAAG;IAC1B,IAAI,EAAE,QAAQ;IACd,oBAAoB,EAAE,KAAK;IAC3B,UAAU,EAAE;QACV,UAAU,EAAE;YACV,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,aAAa;YACpB,IAAI,EAAE,CAAC,WAAW,EAAE,YAAY,CAAC;YACjC,SAAS,EAAE,CAAC,kBAAkB,EAAE,gBAAgB,CAAC;YACjD,OAAO,EAAE,WAAW;YACpB,WAAW,EAAE,qIAAqI;SACnJ;QACD,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,0BAA0B;YACjC,WAAW,EAAE,qFAAqF;SACnG;QACD,aAAa,EAAE;YACb,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,iBAAiB;YACxB,OAAO,EAAE,gDAAgD;YACzD,OAAO,EAAE,WAAW;SACrB;QACD,cAAc,EAAE;YACd,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,gCAAgC;YACvC,OAAO,EAAE,GAAG;YACZ,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,IAAI;SACd;QACD,WAAW,EAAE;YACX,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,iCAAiC;YACxC,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,GAAG;SACb;QACD,aAAa,EAAE;YACb,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,kCAAkC;YACzC,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,CAAC;SACX;QACD,cAAc,EAAE;YACd,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,gCAAgC;YACvC,OAAO,EAAE,KAAK;SACf;QACD,mBAAmB,EAAE;YACnB,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,qBAAqB;YAC5B,IAAI,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC;YAChC,SAAS,EAAE,CAAC,WAAW,EAAE,SAAS,EAAE,KAAK,CAAC;YAC1C,OAAO,EAAE,MAAM;YACf,WAAW,EAAE,wMAAwM;SACtN;KACF;CACO,CAAA"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":";;;AAAa,QAAA,YAAY,GAAG;IAC1B,IAAI,EAAE,QAAQ;IACd,oBAAoB,EAAE,KAAK;IAC3B,UAAU,EAAE;QACV,UAAU,EAAE;YACV,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,aAAa;YACpB,IAAI,EAAE,CAAC,WAAW,EAAE,YAAY,CAAC;YACjC,SAAS,EAAE,CAAC,kBAAkB,EAAE,gBAAgB,CAAC;YACjD,OAAO,EAAE,YAAY;YACrB,WAAW,EAAE,4JAA4J;SAC1K;QACD,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,0BAA0B;YACjC,WAAW,EAAE,qFAAqF;SACnG;QACD,aAAa,EAAE;YACb,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,iBAAiB;YACxB,OAAO,EAAE,gDAAgD;YACzD,OAAO,EAAE,WAAW;SACrB;QACD,cAAc,EAAE;YACd,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,gCAAgC;YACvC,OAAO,EAAE,GAAG;YACZ,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,IAAI;SACd;QACD,WAAW,EAAE;YACX,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,iCAAiC;YACxC,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,GAAG;SACb;QACD,aAAa,EAAE;YACb,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,kCAAkC;YACzC,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,CAAC;SACX;QACD,cAAc,EAAE;YACd,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,gCAAgC;YACvC,OAAO,EAAE,KAAK;SACf;QACD,mBAAmB,EAAE;YACnB,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,qBAAqB;YAC5B,IAAI,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC;YAChC,SAAS,EAAE,CAAC,WAAW,EAAE,SAAS,EAAE,KAAK,CAAC;YAC1C,OAAO,EAAE,MAAM;YACf,WAAW,EAAE,wMAAwM;SACtN;KACF;CACO,CAAA"}
@@ -1,13 +1,26 @@
1
1
  import { NativeCourseService } from './native-course';
2
2
  import { type CourseAcknowledgement } from './protocol';
3
+ export interface LegStart {
4
+ identity: string;
5
+ observedAt: number;
6
+ startedAt: number | null;
7
+ position: {
8
+ latitude: number;
9
+ longitude: number;
10
+ } | null;
11
+ positionTimestamp: number | null;
12
+ }
3
13
  export declare class CourseStore {
4
14
  private readonly target;
5
15
  private readonly native;
6
16
  private snapshot;
7
17
  private operation;
18
+ private latestLegPosition;
8
19
  constructor(target: string, native: NativeCourseService);
9
20
  open(): Promise<void>;
10
21
  acknowledgement(): Promise<CourseAcknowledgement | undefined>;
22
+ observeLeg(now?: number, activation?: boolean): Promise<void>;
23
+ observeLegPosition(position: unknown, timestamp: unknown, now?: number): Promise<void>;
11
24
  status(): Promise<object>;
12
25
  receive(payload: Buffer): Promise<CourseAcknowledgement>;
13
26
  activate(): Promise<void>;
@@ -13,6 +13,7 @@ class CourseStore {
13
13
  native;
14
14
  snapshot = { version: 1 };
15
15
  operation = Promise.resolve();
16
+ latestLegPosition = null;
16
17
  constructor(target, native) {
17
18
  this.target = target;
18
19
  this.native = native;
@@ -64,13 +65,50 @@ class CourseStore {
64
65
  return undefined;
65
66
  return { ...acknowledgement, activation: await this.activation(), mapReadiness: this.snapshot.mapReadiness?.revision === this.snapshot.desired?.revision ? this.snapshot.mapReadiness?.status ?? 'unknown' : 'unknown' };
66
67
  }
68
+ // One durable marker for every observed activation/advance. Never use page
69
+ // load time, a packet receipt time, or an old race-plan timestamp as leg start.
70
+ async observeLeg(now = Date.now(), activation = false) {
71
+ await this.exclusive(async () => {
72
+ const desired = this.snapshot.desired;
73
+ const native = await this.native.current();
74
+ const matches = desired?.action === 'activate' && await this.native.matches(desired);
75
+ const points = desired?.action === 'activate' ? (0, protocol_1.coursePoints)(desired) : [];
76
+ const index = matches ? native?.activeRoute?.pointIndex : desired?.action === 'activate' ? desired.activeWaypointIndex ?? 1 : null;
77
+ const identity = desired?.action === 'activate' && Number.isInteger(index) && index >= 0 && index < points.length
78
+ ? JSON.stringify([desired.courseId, desired.revision, desired.updatedAt, index, matches ? native?.activeRoute?.href : 'cached', matches && native?.activeRoute?.reverse === true, points]) : null;
79
+ if (!activation && (identity === this.snapshot.legStart?.identity || (!identity && !this.snapshot.legStart)))
80
+ return;
81
+ // A first attachment to an already active route cannot reconstruct its
82
+ // activation. Controlled activation or an observed transition is required.
83
+ const knownEvent = activation || !!this.snapshot.legStart;
84
+ const fix = this.latestLegPosition;
85
+ const baseline = knownEvent && fix && fix.at <= now && now - fix.at <= 30000 ? fix : null;
86
+ const next = { ...this.snapshot, legStart: identity ? { identity, observedAt: now, startedAt: knownEvent ? now : null,
87
+ position: baseline?.position ?? null, positionTimestamp: baseline?.at ?? null } : undefined };
88
+ await this.persist(next);
89
+ this.snapshot = next;
90
+ });
91
+ }
92
+ observeLegPosition(position, timestamp, now = Date.now()) {
93
+ return this.exclusive(async () => {
94
+ const p = position;
95
+ const at = typeof timestamp === 'string' ? Date.parse(timestamp) : NaN;
96
+ if (!p || typeof p.latitude !== 'number' || typeof p.longitude !== 'number'
97
+ || !Number.isFinite(p.latitude) || !Number.isFinite(p.longitude) || Math.abs(p.latitude) > 90 || Math.abs(p.longitude) > 180
98
+ || !Number.isFinite(at) || at > now || now - at > 30000 || (this.latestLegPosition && at <= this.latestLegPosition.at))
99
+ return;
100
+ this.latestLegPosition = { position: { latitude: p.latitude, longitude: p.longitude }, at };
101
+ });
102
+ }
67
103
  async status() {
104
+ await this.observeLeg();
68
105
  const course = this.snapshot.cachedCourse;
69
106
  const native = await this.native.current();
70
107
  const activation = await this.activation();
71
108
  const activeMatchesDesired = !!course && this.snapshot.desired?.action === 'activate' && await this.native.matches(course);
72
109
  return {
73
110
  desired: this.snapshot.desired ?? null, cachedCourse: course ?? null,
111
+ legStart: this.snapshot.legStart ?? null,
74
112
  acknowledgement: await this.acknowledgement() ?? null,
75
113
  routePoints: course ? (0, protocol_1.coursePoints)(course) : [],
76
114
  native: {
@@ -83,6 +121,7 @@ class CourseStore {
83
121
  };
84
122
  }
85
123
  receive(payload) {
124
+ let activated = false;
86
125
  return this.exclusive(async () => {
87
126
  let document;
88
127
  try {
@@ -102,8 +141,10 @@ class CourseStore {
102
141
  await this.native.clearOwned(previousCourse);
103
142
  else {
104
143
  await this.native.ensureResource(document);
105
- if (!duplicate)
106
- await this.native.activate(document, false, previousCourse);
144
+ if (!duplicate) {
145
+ const result = await this.native.activate(document, false, previousCourse);
146
+ activated = result === 'active' || previous?.revision !== document.revision;
147
+ }
107
148
  }
108
149
  const activation = await this.activation();
109
150
  const blocker = activation === 'conflict' && document.action === 'activate'
@@ -127,7 +168,7 @@ class CourseStore {
127
168
  this.snapshot.acknowledgement = acknowledgement;
128
169
  return acknowledgement;
129
170
  }
130
- });
171
+ }).then(async (acknowledgement) => { await this.observeLeg(Date.now(), activated); return acknowledgement; });
131
172
  }
132
173
  activate() {
133
174
  return this.exclusive(async () => {
@@ -142,7 +183,7 @@ class CourseStore {
142
183
  const acknowledgement = { v: 1, revision: course.revision, status: 'applied', activation: 'active' };
143
184
  await this.persist({ ...this.snapshot, acknowledgement });
144
185
  this.snapshot.acknowledgement = acknowledgement;
145
- });
186
+ }).then(async () => { await this.observeLeg(Date.now(), true); });
146
187
  }
147
188
  setMapReadiness(revision, status) {
148
189
  return this.exclusive(async () => {
@@ -1 +1 @@
1
- {"version":3,"file":"course-store.js","sourceRoot":"","sources":["../../src/courses/course-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"course-store.js","sourceRoot":"","sources":["../../src/courses/course-store.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -59,8 +59,8 @@ const constructor = (app) => {
59
59
  // Explicit, leased, generation-stamped navigation-control ownership. Only the
60
60
  // owning onboard client may apply a detected rounding; other pages are viewers.
61
61
  const navigationLease = new navigation_control_1.NavigationControlLease();
62
- let activeUploadMode = 'automatic';
63
- let persistedUploadMode = 'automatic';
62
+ let activeUploadMode = 'local_only';
63
+ let persistedUploadMode = 'local_only';
64
64
  let persistenceError;
65
65
  let rawConfiguration = {};
66
66
  let trackingOperation = Promise.resolve();
@@ -85,6 +85,8 @@ const constructor = (app) => {
85
85
  schema: schema_1.configSchema,
86
86
  start(configuration) {
87
87
  ready = false;
88
+ activeUploadMode = 'local_only';
89
+ persistedUploadMode = 'local_only';
88
90
  trackingRevision += 1;
89
91
  rawConfiguration = structuredClone(configuration);
90
92
  pairingAbortController?.abort();
@@ -101,9 +103,10 @@ const constructor = (app) => {
101
103
  await initialise((0, defaults_1.parseConfig)(configuration), thisGeneration);
102
104
  ready = thisGeneration === generation;
103
105
  }
104
- })().catch((error) => {
106
+ })().catch(async (error) => {
105
107
  if (thisGeneration !== generation)
106
108
  return;
109
+ await pauseTransmission();
107
110
  const message = safeError(error);
108
111
  app.setPluginError(`Wake Logger initialization failed: ${message}`);
109
112
  app.error(`Wake Logger initialization failed: ${message}`);
@@ -140,7 +143,8 @@ const constructor = (app) => {
140
143
  }
141
144
  });
142
145
  writeRouter.post('/tracking', async (request, response, next) => {
143
- const mode = request.body?.uploadMode;
146
+ const body = request.body;
147
+ const mode = body?.uploadMode;
144
148
  if (mode !== 'automatic' && mode !== 'local_only') {
145
149
  response.status(400).json({ error: 'invalid_upload_mode' });
146
150
  return;
@@ -149,6 +153,14 @@ const constructor = (app) => {
149
153
  response.status(409).json({ error: 'tracking_unavailable', ...await trackingStatus() });
150
154
  return;
151
155
  }
156
+ if (body?.confirmed !== true) {
157
+ response.status(400).json({ error: 'tracking_confirmation_required', ...await trackingStatus() });
158
+ return;
159
+ }
160
+ if (body.expectedUploadMode !== activeUploadMode) {
161
+ response.status(409).json({ error: 'tracking_changed', ...await trackingStatus() });
162
+ return;
163
+ }
152
164
  const revision = ++trackingRevision;
153
165
  const thisGeneration = generation;
154
166
  // Off wins immediately, even while an earlier options save is pending.
@@ -854,9 +866,20 @@ const constructor = (app) => {
854
866
  associationCheck = undefined;
855
867
  }
856
868
  async function initialise(config, thisGeneration) {
857
- persistedUploadMode = config.uploadMode;
869
+ // Configuration/defaults are never authority for live transmission. Only a
870
+ // versioned choice written by the confirmed control route may restore ON.
871
+ persistedUploadMode = 'local_only';
872
+ activeUploadMode = 'local_only';
858
873
  persistenceError = undefined;
859
- activeUploadMode = config.uploadMode;
874
+ try {
875
+ const choice = JSON.parse(await node_fs_1.promises.readFile(node_path_1.default.join(app.getDataDirPath(), 'tracking-choice.json'), 'utf8'));
876
+ if (choice.version !== 1 || choice.confirmed !== true || !['automatic', 'local_only'].includes(choice.uploadMode))
877
+ throw new Error('Invalid tracking choice');
878
+ persistedUploadMode = activeUploadMode = choice.uploadMode;
879
+ }
880
+ catch {
881
+ persistenceError = 'No readable confirmed tracking choice; live tracking remains off. Confirm a choice in the onboard app.';
882
+ }
860
883
  try {
861
884
  await node_fs_1.promises.access(node_path_1.default.join(app.getDataDirPath(), 'tracking-pause.json'));
862
885
  activeUploadMode = 'local_only';
@@ -873,7 +896,7 @@ const constructor = (app) => {
873
896
  const credentialStore = new credentials_1.CredentialStore(node_path_1.default.join(dataDirectory, 'identity'));
874
897
  let credentials = await credentialStore.load();
875
898
  const lastPairingCodeFingerprint = await credentialStore.lastPairingCodeFingerprint();
876
- if (config.uploadMode === 'automatic' && (0, credentials_1.shouldExchangePairingCode)(credentials, config.pairingCode, lastPairingCodeFingerprint)) {
899
+ if ((config.uploadMode === 'automatic' || !credentials) && (0, credentials_1.shouldExchangePairingCode)(credentials, config.pairingCode, lastPairingCodeFingerprint)) {
877
900
  const controller = new AbortController();
878
901
  pairingAbortController = controller;
879
902
  try {
@@ -917,7 +940,7 @@ const constructor = (app) => {
917
940
  }
918
941
  if (!credentials) {
919
942
  connectionState = 'unpaired';
920
- app.setPluginStatus(config.uploadMode === 'local_only' ? 'Wake Logger: Not paired — switch to automatic and pair before recording locally' : 'Wake Logger: Not paired');
943
+ app.setPluginStatus('Wake Logger: Not paired');
921
944
  return;
922
945
  }
923
946
  if (generation !== thisGeneration)
@@ -1083,6 +1106,11 @@ const constructor = (app) => {
1083
1106
  stopSubscription = (0, subscriber_1.subscribeToTelemetry)(app, (delta) => {
1084
1107
  normaliser.ingest(delta);
1085
1108
  observations?.ingest(delta);
1109
+ for (const update of delta.updates ?? [])
1110
+ for (const entry of ('values' in update ? update.values : []) ?? []) {
1111
+ if (entry.path === 'navigation.position')
1112
+ void courses?.observeLegPosition(entry.value, update.timestamp).catch(() => app.error('Wake Logger leg marker checkpoint failed'));
1113
+ }
1086
1114
  if (!progression)
1087
1115
  return;
1088
1116
  const fix = normaliser.latestFix();
@@ -1252,10 +1280,22 @@ const constructor = (app) => {
1252
1280
  app.savePluginOptions(configuration, (error) => error ? reject(error) : resolve());
1253
1281
  });
1254
1282
  rawConfiguration = configuration;
1283
+ if (revision !== trackingRevision || generation !== thisGeneration)
1284
+ return;
1285
+ await (0, history_1.durableJson)(node_path_1.default.join(app.getDataDirPath(), 'tracking-choice.json'), { version: 1, confirmed: true, uploadMode: mode });
1286
+ if (generation !== thisGeneration) {
1287
+ await (0, history_1.durableJson)(guard, { paused: true, at: Date.now() });
1288
+ throw new Error('tracking_restarted');
1289
+ }
1290
+ if (revision !== trackingRevision)
1291
+ return;
1292
+ await node_fs_1.promises.unlink(guard).catch((error) => { if (error.code !== 'ENOENT')
1293
+ throw error; });
1294
+ if (generation !== thisGeneration || revision !== trackingRevision) {
1295
+ await (0, history_1.durableJson)(guard, { paused: true, at: Date.now() });
1296
+ throw new Error('tracking_restarted');
1297
+ }
1255
1298
  persistedUploadMode = mode;
1256
- if (revision === trackingRevision && generation === thisGeneration)
1257
- await node_fs_1.promises.unlink(guard).catch((error) => { if (error.code !== 'ENOENT')
1258
- throw error; });
1259
1299
  persistenceError = undefined;
1260
1300
  }
1261
1301
  catch (error) {