@mongrov/analytics 0.23.2 → 0.24.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/dist/core/migrations.d.ts.map +1 -1
- package/dist/core/migrations.js +35 -0
- package/dist/core/migrations.js.map +1 -1
- package/dist/core/schemas.d.ts.map +1 -1
- package/dist/core/schemas.js +5 -2
- package/dist/core/schemas.js.map +1 -1
- package/dist/sync/factory.d.ts +7 -0
- package/dist/sync/factory.d.ts.map +1 -1
- package/dist/sync/factory.js +31 -1
- package/dist/sync/factory.js.map +1 -1
- package/dist/sync/index.d.ts +2 -2
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/index.js +1 -1
- package/dist/sync/index.js.map +1 -1
- package/dist/sync/mapper/firmware.d.ts.map +1 -1
- package/dist/sync/mapper/firmware.js +7 -5
- package/dist/sync/mapper/firmware.js.map +1 -1
- package/dist/sync/mapper/schema.d.ts +29 -36
- package/dist/sync/mapper/schema.d.ts.map +1 -1
- package/dist/sync/mapper/schema.js +11 -12
- package/dist/sync/mapper/schema.js.map +1 -1
- package/dist/sync/mapper/sleep.d.ts +50 -43
- package/dist/sync/mapper/sleep.d.ts.map +1 -1
- package/dist/sync/mapper/sleep.js +99 -138
- package/dist/sync/mapper/sleep.js.map +1 -1
- package/dist/sync/mapper/types.d.ts +17 -18
- package/dist/sync/mapper/types.d.ts.map +1 -1
- package/dist/sync/sleep-correction/classify.d.ts +86 -0
- package/dist/sync/sleep-correction/classify.d.ts.map +1 -0
- package/dist/sync/sleep-correction/classify.js +247 -0
- package/dist/sync/sleep-correction/classify.js.map +1 -0
- package/dist/sync/sleep-correction/correct.d.ts +46 -0
- package/dist/sync/sleep-correction/correct.d.ts.map +1 -0
- package/dist/sync/sleep-correction/correct.js +60 -0
- package/dist/sync/sleep-correction/correct.js.map +1 -0
- package/dist/sync/sleep-correction/index.d.ts +8 -0
- package/dist/sync/sleep-correction/index.d.ts.map +1 -0
- package/dist/sync/sleep-correction/index.js +8 -0
- package/dist/sync/sleep-correction/index.js.map +1 -0
- package/dist/sync/sleep-correction/night.d.ts +26 -0
- package/dist/sync/sleep-correction/night.d.ts.map +1 -0
- package/dist/sync/sleep-correction/night.js +48 -0
- package/dist/sync/sleep-correction/night.js.map +1 -0
- package/dist/sync/sleep-correction/orchestrate.d.ts +50 -0
- package/dist/sync/sleep-correction/orchestrate.d.ts.map +1 -0
- package/dist/sync/sleep-correction/orchestrate.js +57 -0
- package/dist/sync/sleep-correction/orchestrate.js.map +1 -0
- package/dist/sync/sleep-correction/settle.d.ts +24 -0
- package/dist/sync/sleep-correction/settle.d.ts.map +1 -0
- package/dist/sync/sleep-correction/settle.js +59 -0
- package/dist/sync/sleep-correction/settle.js.map +1 -0
- package/dist/sync/sleep-correction/sql.d.ts +44 -0
- package/dist/sync/sleep-correction/sql.d.ts.map +1 -0
- package/dist/sync/sleep-correction/sql.js +329 -0
- package/dist/sync/sleep-correction/sql.js.map +1 -0
- package/dist/sync/sleep-correction/staging.d.ts +32 -0
- package/dist/sync/sleep-correction/staging.d.ts.map +1 -0
- package/dist/sync/sleep-correction/staging.js +51 -0
- package/dist/sync/sleep-correction/staging.js.map +1 -0
- package/dist/sync/sleep-derive.d.ts +55 -0
- package/dist/sync/sleep-derive.d.ts.map +1 -0
- package/dist/sync/sleep-derive.js +180 -0
- package/dist/sync/sleep-derive.js.map +1 -0
- package/package.json +3 -3
|
@@ -45,12 +45,12 @@ export const firmwareActivityRowSchema = z.object({
|
|
|
45
45
|
distance: z.number(),
|
|
46
46
|
arraySteps: z.array(z.number()).length(10),
|
|
47
47
|
}).strict();
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
end: firmwareTimestamp,
|
|
51
|
-
block_type: z.string(),
|
|
52
|
-
confidence: z.number(),
|
|
48
|
+
/** Raw firmware sleep sample (types 0.10.0); `quality` is the firmware code. */
|
|
49
|
+
export const firmwareSleepRawRowSchema = z.object({
|
|
53
50
|
timestamp: firmwareTimestamp,
|
|
51
|
+
quality: z.number().int(),
|
|
52
|
+
start: firmwareTimestamp,
|
|
53
|
+
unitLength: z.number().int().positive(),
|
|
54
54
|
}).strict();
|
|
55
55
|
export const firmwareBatteryRowSchema = z.object({
|
|
56
56
|
timestamp: firmwareTimestamp,
|
|
@@ -92,7 +92,7 @@ export const firmwareExportSchema = z.object({
|
|
|
92
92
|
spo2: z.array(firmwareSpO2RowSchema),
|
|
93
93
|
temperature_table: z.array(firmwareTempRowSchema),
|
|
94
94
|
activitydetails: z.array(firmwareActivityRowSchema),
|
|
95
|
-
|
|
95
|
+
sleep: z.array(firmwareSleepRawRowSchema),
|
|
96
96
|
battery_table: z.array(firmwareBatteryRowSchema),
|
|
97
97
|
ring: firmwareRingConfigSchema,
|
|
98
98
|
}).strict();
|
|
@@ -127,12 +127,11 @@ export const FIRMWARE_EXPORT_KEY_PATHS = new Set([
|
|
|
127
127
|
'activitydetails[].calories',
|
|
128
128
|
'activitydetails[].distance',
|
|
129
129
|
'activitydetails[].arraySteps',
|
|
130
|
-
'
|
|
131
|
-
'
|
|
132
|
-
'
|
|
133
|
-
'
|
|
134
|
-
'
|
|
135
|
-
'sleep_processed[].timestamp',
|
|
130
|
+
'sleep',
|
|
131
|
+
'sleep[].timestamp',
|
|
132
|
+
'sleep[].quality',
|
|
133
|
+
'sleep[].start',
|
|
134
|
+
'sleep[].unitLength',
|
|
136
135
|
'battery_table',
|
|
137
136
|
'battery_table[].timestamp',
|
|
138
137
|
'battery_table[].battery',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/sync/mapper/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,gFAAgF;AAChF,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CACxC,mDAAmD,EACnD,mDAAmD,CACpD,CAAA;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,SAAS,EAAE,iBAAiB;IAC5B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;CACrB,CAAC,CAAC,MAAM,EAAE,CAAA;AAEX,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,SAAS,EAAE,iBAAiB;IAC5B,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC1B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACjC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACrC,CAAC,CAAC,MAAM,EAAE,CAAA;AAEX,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,SAAS,EAAE,iBAAiB;IAC5B,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE;CAC9B,CAAC,CAAC,MAAM,EAAE,CAAA;AAEX,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,SAAS,EAAE,iBAAiB;IAC5B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;CACxB,CAAC,CAAC,MAAM,EAAE,CAAA;AAEX,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChD,SAAS,EAAE,iBAAiB;IAC5B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;CAC3C,CAAC,CAAC,MAAM,EAAE,CAAA;AAEX,MAAM,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/sync/mapper/schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,59 +1,66 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Sleep
|
|
2
|
+
* Sleep mapping (sleep-correction §3).
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* (session start), `end` (session end), `block_type` (primary / light / deep /
|
|
6
|
-
* rem / awake), `confidence` (0..1), and per-block `timestamp` (block instant).
|
|
7
|
-
* Multiple blocks share the same `start` when they belong to the same session.
|
|
4
|
+
* Two halves that run at different times:
|
|
8
5
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* `ts_start = parse(start)`, `ts_end = parse(end)`. `total_minutes` is
|
|
16
|
-
* their difference. Deriving the envelope from block instants would
|
|
17
|
-
* under-report any session whose first/last minutes went unclassified.
|
|
18
|
-
* - `session_id` = `fnv1a32hex(device_id | user_id | ts_session_start |
|
|
19
|
-
* ts_session_end)` (principle 25, amended 2026-08-14) — fully
|
|
20
|
-
* deterministic, so the same night mapped twice yields the same id.
|
|
21
|
-
* - `night_of` = 6pm-6pm rule applied to `ts_start` (see `time.ts`).
|
|
22
|
-
* - Stages: one row per classified block, carrying `session_id` and the
|
|
23
|
-
* DDL's integer `stage` code. `primary` is the session envelope marker,
|
|
24
|
-
* not a stage, so it produces no `sleep_stage` row — the DDL's stage
|
|
25
|
-
* enum (1=awake, 2=light, 3=deep, 5=rem) has no code for it. Unknown
|
|
26
|
-
* block types are likewise skipped; nothing is lost, because...
|
|
27
|
-
* - Raw: every input row is preserved in `sleep_raw` regardless of the
|
|
28
|
-
* primary/confidence filter, flattened onto the DDL's columns, so
|
|
29
|
-
* downstream reprocessing can revisit sessions with new heuristics.
|
|
6
|
+
* - `mapSleepRaw`, at ingest: every raw firmware sample → `sleep_raw`,
|
|
7
|
+
* verbatim. `quality` stays the FIRMWARE code (1 deep / 2 light / 3 rem /
|
|
8
|
+
* 5 awake, other codes kept). Nothing is classified here — `sleep_raw` is
|
|
9
|
+
* the reprocessing source the correction pipeline reads.
|
|
10
|
+
* - `sessionsFromCorrected`, after the batch flushes: one night's Phase 3
|
|
11
|
+
* output from `../sleep-correction` → `sleep_session` + `sleep_stage`.
|
|
30
12
|
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
13
|
+
* Until 0.24.0 the mapper built sessions straight from app-classified blocks
|
|
14
|
+
* (`sleep_processed`) — an admission filter on `primary`, a per-block `end`
|
|
15
|
+
* read as the session end, and a guessed stage map. All three were wrong on
|
|
16
|
+
* device (zivaone_app#77, and the stage swap found 2026-09-10). Sessions now
|
|
17
|
+
* come only from the validated correction pipeline.
|
|
18
|
+
*
|
|
19
|
+
* Principle 20: the firmware `quality` code is translated to the DDL's
|
|
20
|
+
* `stage` code here, and nowhere else. The two enums share integers and mean
|
|
21
|
+
* different things — `FIRMWARE_QUALITY_TO_STAGE` is the one crossing point.
|
|
33
22
|
*/
|
|
34
|
-
import type {
|
|
23
|
+
import type { ClassifiedRow } from '../sleep-correction/classify';
|
|
24
|
+
import type { FirmwareSleepRawRow, MapperContext, SleepRawRow, SleepSessionRow, SleepStageRow } from './types';
|
|
35
25
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*/
|
|
39
|
-
export declare const DEFAULT_BLOCK_MINUTES = 1;
|
|
40
|
-
/**
|
|
41
|
-
* Firmware `block_type` → `sleep_stage.stage` code (spec §Table schema:
|
|
42
|
-
* `stage SMALLINT NOT NULL -- 1=awake, 2=light, 3=deep, 5=rem`).
|
|
43
|
-
*
|
|
44
|
-
* `primary` is deliberately absent: it marks the session envelope, not a
|
|
45
|
-
* sleep stage. The enum is intentionally sparse (no 4) to match the DDL
|
|
46
|
-
* comment verbatim.
|
|
26
|
+
* `sleep_stage.stage` codes (DDL: `1=awake, 2=light, 3=deep, 5=rem`). Sparse
|
|
27
|
+
* on purpose (no 4) to match the DDL comment verbatim.
|
|
47
28
|
*/
|
|
48
29
|
export declare const SLEEP_STAGE_CODES: Readonly<Record<string, number>>;
|
|
49
30
|
/** Reverse lookup for the stage-minute accumulator + diagnostics. */
|
|
50
31
|
export declare const SLEEP_STAGE_NAMES: Readonly<Record<number, string>>;
|
|
51
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Firmware `quality` → DDL `stage`. The firmware says 1 deep / 2 light /
|
|
34
|
+
* 3 rem / 5 awake (ziva_app v3.1; the vendor header is silent); the DDL says
|
|
35
|
+
* 1 awake / 2 light / 3 deep / 5 rem. Copying a predicate across the two
|
|
36
|
+
* computes deep from awake with no error — this map is the only translation.
|
|
37
|
+
*/
|
|
38
|
+
export declare const FIRMWARE_QUALITY_TO_STAGE: Readonly<Record<number, number>>;
|
|
39
|
+
/** Raw firmware samples → `sleep_raw`, verbatim. */
|
|
40
|
+
export declare function mapSleepRaw(rows: readonly FirmwareSleepRawRow[], ctx: MapperContext): SleepRawRow[];
|
|
41
|
+
export interface SessionsFromCorrectedResult {
|
|
52
42
|
sleep_session: SleepSessionRow[];
|
|
53
43
|
sleep_stage: SleepStageRow[];
|
|
54
|
-
sleep_raw: SleepRawRow[];
|
|
55
44
|
}
|
|
56
|
-
|
|
45
|
+
/**
|
|
46
|
+
* One night's corrected rows → sessions + stages.
|
|
47
|
+
*
|
|
48
|
+
* - Only `block_type === 'primary'` rows count (R-A: every primary minute,
|
|
49
|
+
* whatever its confidence — confidence is provenance, never a gate).
|
|
50
|
+
* - Sessions are Phase 2's stitched sessions, identified by `start`. A night
|
|
51
|
+
* is normally one; a gap between 20 and 30 minutes inside the primary
|
|
52
|
+
* block leaves two.
|
|
53
|
+
* - `ts_end` is the last primary minute plus its width; `total_minutes` is
|
|
54
|
+
* the primary minutes actually present (awake minutes included).
|
|
55
|
+
* - `settle_min` belongs to the night, measured from bed, so it goes on the
|
|
56
|
+
* session that starts at bed — the first. `recovered_min` is per session.
|
|
57
|
+
* - `session_id` is principle 25's deterministic hash; the caller replaces
|
|
58
|
+
* the whole night before writing (principle 66 as amended), because a
|
|
59
|
+
* corrected END moves as later data arrives and the id moves with it.
|
|
60
|
+
*/
|
|
61
|
+
export declare function sessionsFromCorrected(rows: readonly ClassifiedRow[], ctx: MapperContext, night?: {
|
|
62
|
+
settleMin?: number | null;
|
|
63
|
+
}): SessionsFromCorrectedResult;
|
|
57
64
|
/**
|
|
58
65
|
* Session id (principle 25, as amended 2026-08-14):
|
|
59
66
|
* `fnv1a32hex(device_id | user_id | ts_session_start | ts_session_end)`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sleep.d.ts","sourceRoot":"","sources":["../../../src/sync/mapper/sleep.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"sleep.d.ts","sourceRoot":"","sources":["../../../src/sync/mapper/sleep.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAA;AACjE,OAAO,KAAK,EACV,mBAAmB,EACnB,aAAa,EACb,WAAW,EACX,eAAe,EACf,aAAa,EACd,MAAM,SAAS,CAAA;AAIhB;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAK7D,CAAA;AAEF,qEAAqE;AACrE,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAK7D,CAAA;AAEF;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAKrE,CAAA;AAEF,oDAAoD;AACpD,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,mBAAmB,EAAE,EAAE,GAAG,EAAE,aAAa,GAAG,WAAW,EAAE,CAWnG;AAED,MAAM,WAAW,2BAA2B;IAC1C,aAAa,EAAE,eAAe,EAAE,CAAA;IAChC,WAAW,EAAE,aAAa,EAAE,CAAA;CAC7B;AAKD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,SAAS,aAAa,EAAE,EAC9B,GAAG,EAAE,aAAa,EAClB,KAAK,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAO,GACxC,2BAA2B,CAkE7B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,aAAa,EAClB,cAAc,EAAE,IAAI,EACpB,YAAY,EAAE,IAAI,GACjB,MAAM,CAKR;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOhD"}
|
|
@@ -1,67 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Sleep
|
|
2
|
+
* Sleep mapping (sleep-correction §3).
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* (session start), `end` (session end), `block_type` (primary / light / deep /
|
|
6
|
-
* rem / awake), `confidence` (0..1), and per-block `timestamp` (block instant).
|
|
7
|
-
* Multiple blocks share the same `start` when they belong to the same session.
|
|
4
|
+
* Two halves that run at different times:
|
|
8
5
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* `ts_start = parse(start)`, `ts_end = parse(end)`. `total_minutes` is
|
|
16
|
-
* their difference. Deriving the envelope from block instants would
|
|
17
|
-
* under-report any session whose first/last minutes went unclassified.
|
|
18
|
-
* - `session_id` = `fnv1a32hex(device_id | user_id | ts_session_start |
|
|
19
|
-
* ts_session_end)` (principle 25, amended 2026-08-14) — fully
|
|
20
|
-
* deterministic, so the same night mapped twice yields the same id.
|
|
21
|
-
* - `night_of` = 6pm-6pm rule applied to `ts_start` (see `time.ts`).
|
|
22
|
-
* - Stages: one row per classified block, carrying `session_id` and the
|
|
23
|
-
* DDL's integer `stage` code. `primary` is the session envelope marker,
|
|
24
|
-
* not a stage, so it produces no `sleep_stage` row — the DDL's stage
|
|
25
|
-
* enum (1=awake, 2=light, 3=deep, 5=rem) has no code for it. Unknown
|
|
26
|
-
* block types are likewise skipped; nothing is lost, because...
|
|
27
|
-
* - Raw: every input row is preserved in `sleep_raw` regardless of the
|
|
28
|
-
* primary/confidence filter, flattened onto the DDL's columns, so
|
|
29
|
-
* downstream reprocessing can revisit sessions with new heuristics.
|
|
6
|
+
* - `mapSleepRaw`, at ingest: every raw firmware sample → `sleep_raw`,
|
|
7
|
+
* verbatim. `quality` stays the FIRMWARE code (1 deep / 2 light / 3 rem /
|
|
8
|
+
* 5 awake, other codes kept). Nothing is classified here — `sleep_raw` is
|
|
9
|
+
* the reprocessing source the correction pipeline reads.
|
|
10
|
+
* - `sessionsFromCorrected`, after the batch flushes: one night's Phase 3
|
|
11
|
+
* output from `../sleep-correction` → `sleep_session` + `sleep_stage`.
|
|
30
12
|
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const CONFIDENCE_FLOOR = 0.7;
|
|
37
|
-
/**
|
|
38
|
-
* Block types that mean the wearer was asleep — the admission test
|
|
39
|
-
* (zivaone_app#77).
|
|
40
|
-
*
|
|
41
|
-
* The filter used to require a `primary` block. `primary` is the session
|
|
42
|
-
* envelope marker, not a stage (see `SLEEP_STAGE_CODES`), and a correctly
|
|
43
|
-
* decoded export carries none — so every session was dropped, `sleep_raw`
|
|
44
|
-
* filled while `sleep_session` stayed empty, and every `context='asleep'`
|
|
45
|
-
* join saw nothing. An explicit asleep set rather than `!== 'awake'`, so an
|
|
46
|
-
* all-awake group is still rejected: the nap/noise intent survives.
|
|
13
|
+
* Until 0.24.0 the mapper built sessions straight from app-classified blocks
|
|
14
|
+
* (`sleep_processed`) — an admission filter on `primary`, a per-block `end`
|
|
15
|
+
* read as the session end, and a guessed stage map. All three were wrong on
|
|
16
|
+
* device (zivaone_app#77, and the stage swap found 2026-09-10). Sessions now
|
|
17
|
+
* come only from the validated correction pipeline.
|
|
47
18
|
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
19
|
+
* Principle 20: the firmware `quality` code is translated to the DDL's
|
|
20
|
+
* `stage` code here, and nowhere else. The two enums share integers and mean
|
|
21
|
+
* different things — `FIRMWARE_QUALITY_TO_STAGE` is the one crossing point.
|
|
51
22
|
*/
|
|
52
|
-
|
|
23
|
+
import { parseDateStr } from '../sleep-correction/classify';
|
|
24
|
+
import { computeNightOf, parseTimestamp } from './time';
|
|
53
25
|
/**
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*/
|
|
57
|
-
export const DEFAULT_BLOCK_MINUTES = 1;
|
|
58
|
-
/**
|
|
59
|
-
* Firmware `block_type` → `sleep_stage.stage` code (spec §Table schema:
|
|
60
|
-
* `stage SMALLINT NOT NULL -- 1=awake, 2=light, 3=deep, 5=rem`).
|
|
61
|
-
*
|
|
62
|
-
* `primary` is deliberately absent: it marks the session envelope, not a
|
|
63
|
-
* sleep stage. The enum is intentionally sparse (no 4) to match the DDL
|
|
64
|
-
* comment verbatim.
|
|
26
|
+
* `sleep_stage.stage` codes (DDL: `1=awake, 2=light, 3=deep, 5=rem`). Sparse
|
|
27
|
+
* on purpose (no 4) to match the DDL comment verbatim.
|
|
65
28
|
*/
|
|
66
29
|
export const SLEEP_STAGE_CODES = Object.freeze({
|
|
67
30
|
awake: 1,
|
|
@@ -76,93 +39,89 @@ export const SLEEP_STAGE_NAMES = Object.freeze({
|
|
|
76
39
|
3: 'deep',
|
|
77
40
|
5: 'rem',
|
|
78
41
|
});
|
|
79
|
-
/** Per-block width, honouring a firmware-supplied `unit_length`. */
|
|
80
|
-
function blockMinutes(row) {
|
|
81
|
-
return typeof row.unit_length === 'number' && row.unit_length > 0
|
|
82
|
-
? row.unit_length
|
|
83
|
-
: DEFAULT_BLOCK_MINUTES;
|
|
84
|
-
}
|
|
85
42
|
/**
|
|
86
|
-
* `
|
|
87
|
-
*
|
|
88
|
-
*
|
|
43
|
+
* Firmware `quality` → DDL `stage`. The firmware says 1 deep / 2 light /
|
|
44
|
+
* 3 rem / 5 awake (ziva_app v3.1; the vendor header is silent); the DDL says
|
|
45
|
+
* 1 awake / 2 light / 3 deep / 5 rem. Copying a predicate across the two
|
|
46
|
+
* computes deep from awake with no error — this map is the only translation.
|
|
89
47
|
*/
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
48
|
+
export const FIRMWARE_QUALITY_TO_STAGE = Object.freeze({
|
|
49
|
+
1: SLEEP_STAGE_CODES.deep,
|
|
50
|
+
2: SLEEP_STAGE_CODES.light,
|
|
51
|
+
3: SLEEP_STAGE_CODES.rem,
|
|
52
|
+
5: SLEEP_STAGE_CODES.awake,
|
|
53
|
+
});
|
|
54
|
+
/** Raw firmware samples → `sleep_raw`, verbatim. */
|
|
55
|
+
export function mapSleepRaw(rows, ctx) {
|
|
56
|
+
return rows.map(r => ({
|
|
57
|
+
ts: parseTimestamp(r.timestamp),
|
|
58
|
+
ts_session_start: parseTimestamp(r.start),
|
|
59
|
+
brand: ctx.brand,
|
|
60
|
+
family_id: ctx.familyId,
|
|
61
|
+
user_id: ctx.userId,
|
|
62
|
+
device_id: ctx.deviceId,
|
|
63
|
+
quality: r.quality,
|
|
64
|
+
unit_length: typeof r.unitLength === 'number' ? r.unitLength : null,
|
|
65
|
+
}));
|
|
94
66
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
67
|
+
/** Width of one Phase 2/3 row. v3.1 emits every row at `unitLength` 1. */
|
|
68
|
+
const ROW_SECONDS = 60;
|
|
69
|
+
/**
|
|
70
|
+
* One night's corrected rows → sessions + stages.
|
|
71
|
+
*
|
|
72
|
+
* - Only `block_type === 'primary'` rows count (R-A: every primary minute,
|
|
73
|
+
* whatever its confidence — confidence is provenance, never a gate).
|
|
74
|
+
* - Sessions are Phase 2's stitched sessions, identified by `start`. A night
|
|
75
|
+
* is normally one; a gap between 20 and 30 minutes inside the primary
|
|
76
|
+
* block leaves two.
|
|
77
|
+
* - `ts_end` is the last primary minute plus its width; `total_minutes` is
|
|
78
|
+
* the primary minutes actually present (awake minutes included).
|
|
79
|
+
* - `settle_min` belongs to the night, measured from bed, so it goes on the
|
|
80
|
+
* session that starts at bed — the first. `recovered_min` is per session.
|
|
81
|
+
* - `session_id` is principle 25's deterministic hash; the caller replaces
|
|
82
|
+
* the whole night before writing (principle 66 as amended), because a
|
|
83
|
+
* corrected END moves as later data arrives and the id moves with it.
|
|
84
|
+
*/
|
|
85
|
+
export function sessionsFromCorrected(rows, ctx, night = {}) {
|
|
114
86
|
const bySession = new Map();
|
|
115
|
-
for (const
|
|
116
|
-
|
|
87
|
+
for (const r of rows) {
|
|
88
|
+
if (r.block_type !== 'primary')
|
|
89
|
+
continue;
|
|
90
|
+
const bucket = bySession.get(r.start);
|
|
117
91
|
if (bucket)
|
|
118
|
-
bucket.push(
|
|
92
|
+
bucket.push(r);
|
|
119
93
|
else
|
|
120
|
-
bySession.set(
|
|
94
|
+
bySession.set(r.start, [r]);
|
|
121
95
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
// stamps the session end on every block gives the same answer; a producer
|
|
130
|
-
// that stamps each block's own end (zivaone_app's firmware-sync) made
|
|
131
|
-
// `blocks[0].end` the end of the first minute, so sessions came out one
|
|
132
|
-
// unit long and tripped `total_minutes: 1` alerts (zivaone_app#77).
|
|
133
|
-
const tsStart = parseTimestamp(startKey);
|
|
134
|
-
const tsEnd = blocks
|
|
135
|
-
.map(b => parseTimestamp(b.end))
|
|
136
|
-
.reduce((latest, t) => (t.getTime() > latest.getTime() ? t : latest));
|
|
137
|
-
const totalMinutes = Math.max(0, Math.round((tsEnd.getTime() - tsStart.getTime()) / MINUTE_MS));
|
|
138
|
-
const nightOf = computeNightOf(tsStart, ctx.userTimezone);
|
|
96
|
+
const groups = Array.from(bySession.values(), g => g.map(r => ({ r, e: parseDateStr(r.date) })).sort((a, b) => a.e - b.e))
|
|
97
|
+
.sort((a, b) => a[0].e - b[0].e);
|
|
98
|
+
const sleep_session = [];
|
|
99
|
+
const sleep_stage = [];
|
|
100
|
+
groups.forEach((group, index) => {
|
|
101
|
+
const tsStart = new Date(group[0].e * 1000);
|
|
102
|
+
const tsEnd = new Date((group[group.length - 1].e + ROW_SECONDS) * 1000);
|
|
139
103
|
const sessionId = makeSessionId(ctx, tsStart, tsEnd);
|
|
140
|
-
|
|
141
|
-
const stageMinutes = {
|
|
142
|
-
awake: 0,
|
|
143
|
-
light: 0,
|
|
144
|
-
deep: 0,
|
|
145
|
-
rem: 0,
|
|
146
|
-
};
|
|
104
|
+
const minutes = { awake: 0, light: 0, deep: 0, rem: 0 };
|
|
147
105
|
let confidenceSum = 0;
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
if (
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
106
|
+
let recovered = 0;
|
|
107
|
+
for (const { r, e } of group) {
|
|
108
|
+
confidenceSum += r.confidence;
|
|
109
|
+
if (r.source === 'envelope' || r.source === 'gap')
|
|
110
|
+
recovered++;
|
|
111
|
+
const stage = FIRMWARE_QUALITY_TO_STAGE[r.quality];
|
|
112
|
+
if (stage === undefined)
|
|
113
|
+
continue; // a code the pipeline passed but the DDL has no stage for
|
|
114
|
+
minutes[SLEEP_STAGE_NAMES[stage]]++;
|
|
157
115
|
sleep_stage.push({
|
|
158
|
-
ts:
|
|
116
|
+
ts: new Date(e * 1000),
|
|
159
117
|
brand: ctx.brand,
|
|
160
118
|
family_id: ctx.familyId,
|
|
161
119
|
user_id: ctx.userId,
|
|
162
120
|
device_id: ctx.deviceId,
|
|
163
121
|
session_id: sessionId,
|
|
164
|
-
stage
|
|
165
|
-
confidence:
|
|
122
|
+
stage,
|
|
123
|
+
confidence: r.confidence,
|
|
124
|
+
source: r.source,
|
|
166
125
|
});
|
|
167
126
|
}
|
|
168
127
|
sleep_session.push({
|
|
@@ -173,16 +132,18 @@ export function reconstructSleepSessions(rows, ctx) {
|
|
|
173
132
|
session_id: sessionId,
|
|
174
133
|
ts_start: tsStart,
|
|
175
134
|
ts_end: tsEnd,
|
|
176
|
-
total_minutes:
|
|
177
|
-
deep_minutes:
|
|
178
|
-
rem_minutes:
|
|
179
|
-
light_minutes:
|
|
180
|
-
awake_minutes:
|
|
181
|
-
avg_confidence:
|
|
182
|
-
night_of:
|
|
135
|
+
total_minutes: group.length,
|
|
136
|
+
deep_minutes: minutes.deep,
|
|
137
|
+
rem_minutes: minutes.rem,
|
|
138
|
+
light_minutes: minutes.light,
|
|
139
|
+
awake_minutes: minutes.awake,
|
|
140
|
+
avg_confidence: confidenceSum / group.length,
|
|
141
|
+
night_of: computeNightOf(tsStart, ctx.userTimezone),
|
|
142
|
+
settle_min: index === 0 ? (night.settleMin ?? null) : null,
|
|
143
|
+
recovered_min: recovered,
|
|
183
144
|
});
|
|
184
|
-
}
|
|
185
|
-
return { sleep_session, sleep_stage
|
|
145
|
+
});
|
|
146
|
+
return { sleep_session, sleep_stage };
|
|
186
147
|
}
|
|
187
148
|
/**
|
|
188
149
|
* Session id (principle 25, as amended 2026-08-14):
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sleep.js","sourceRoot":"","sources":["../../../src/sync/mapper/sleep.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"sleep.js","sourceRoot":"","sources":["../../../src/sync/mapper/sleep.ts"],"names":[],"mappings":"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"}
|
|
@@ -48,24 +48,17 @@ export interface FirmwareActivityRow {
|
|
|
48
48
|
distance: number;
|
|
49
49
|
arraySteps: number[];
|
|
50
50
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
/**
|
|
52
|
+
* One raw firmware sleep sample (types 0.10.0). `quality` is the FIRMWARE
|
|
53
|
+
* code (1 deep / 2 light / 3 rem / 5 awake; other codes pass through to
|
|
54
|
+
* `sleep_raw` and are filtered by the correction pipeline). Sessions and
|
|
55
|
+
* stages are no longer mapped from these directly — see `sleep-correction`.
|
|
56
|
+
*/
|
|
57
|
+
export interface FirmwareSleepRawRow {
|
|
56
58
|
timestamp: string;
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
* fall back to `round(confidence * 100)` — see `mapper/sleep.ts`.
|
|
61
|
-
*/
|
|
62
|
-
quality?: number;
|
|
63
|
-
/**
|
|
64
|
-
* Block width in minutes, when the firmware revision carries one.
|
|
65
|
-
* Passed through verbatim to `sleep_raw.unit_length`; drives stage-minute
|
|
66
|
-
* accumulation. Defaults to `DEFAULT_BLOCK_MINUTES` (1) when absent.
|
|
67
|
-
*/
|
|
68
|
-
unit_length?: number;
|
|
59
|
+
quality: number;
|
|
60
|
+
start: string;
|
|
61
|
+
unitLength: number;
|
|
69
62
|
}
|
|
70
63
|
export interface FirmwareBatteryRow {
|
|
71
64
|
timestamp: string;
|
|
@@ -121,7 +114,7 @@ export interface FirmwareExport {
|
|
|
121
114
|
spo2: FirmwareSpO2Row[];
|
|
122
115
|
temperature_table: FirmwareTempRow[];
|
|
123
116
|
activitydetails: FirmwareActivityRow[];
|
|
124
|
-
|
|
117
|
+
sleep: FirmwareSleepRawRow[];
|
|
125
118
|
battery_table: FirmwareBatteryRow[];
|
|
126
119
|
ring: FirmwareRingConfig;
|
|
127
120
|
}
|
|
@@ -186,6 +179,10 @@ export interface SleepSessionRow extends TenantRow {
|
|
|
186
179
|
awake_minutes: number | null;
|
|
187
180
|
avg_confidence: number | null;
|
|
188
181
|
night_of: Date;
|
|
182
|
+
/** Minutes from bed until HR settled; null when unknown or on the 30-min HR tier (R-C). */
|
|
183
|
+
settle_min: number | null;
|
|
184
|
+
/** Primary minutes recovered from HR (envelope/gap) rather than firmware-scored. */
|
|
185
|
+
recovered_min: number | null;
|
|
189
186
|
}
|
|
190
187
|
/**
|
|
191
188
|
* `sleep_stage` warehouse row. `stage` is the DDL's integer code
|
|
@@ -196,6 +193,8 @@ export interface SleepStageRow extends BaseRow {
|
|
|
196
193
|
session_id: string;
|
|
197
194
|
stage: number;
|
|
198
195
|
confidence: number | null;
|
|
196
|
+
/** Provenance from correction: firmware / envelope / gap / bout_consolidated. */
|
|
197
|
+
source: string | null;
|
|
199
198
|
}
|
|
200
199
|
/**
|
|
201
200
|
* `sleep_raw` warehouse row (`collected_only`). Preserves each firmware
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/sync/mapper/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,wDAAwD;IACxD,YAAY,EAAE,MAAM,CAAA;CACrB;AAID,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,iBAAiB,EAAE,MAAM,CAAA;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,EAAE,CAAA;CACrB;AAED,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/sync/mapper/types.ts"],"names":[],"mappings":"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"}
|