@camstack/addon-matter-broker 0.2.14 → 0.2.16

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 (3) hide show
  1. package/dist/addon.js +731 -76
  2. package/dist/addon.mjs +731 -76
  3. package/package.json +1 -1
package/dist/addon.mjs CHANGED
@@ -10832,7 +10832,14 @@ var cameraStreamsCapability = {
10832
10832
  low: string$2().optional()
10833
10833
  }),
10834
10834
  lastChangedAt: number()
10835
- })
10835
+ }),
10836
+ /**
10837
+ * Runtime-state durability: **session** — a restored `slotStatuses: streaming` for a camera that has been dark for two hours is a lie the UI renders as truth.
10838
+ *
10839
+ * See `RuntimeStateDurability`. Enforced by
10840
+ * `scripts/check-runtime-state-durability.ts`.
10841
+ */
10842
+ durability: "session"
10836
10843
  };
10837
10844
  /** Where a block runs. The operator chooses — a block driving a device on an
10838
10845
  * agent is the reason placement is not fixed to the hub. */
@@ -11393,6 +11400,13 @@ var deviceDiscoveryCapability = {
11393
11400
  kind: "poll"
11394
11401
  },
11395
11402
  runtimeState: DeviceDiscoveryStatusSchema.extend({ lastFetchedAt: number().int().nonnegative() }),
11403
+ /**
11404
+ * Runtime-state durability: **session** — 5.7 KB of scan output on the largest device, fully re-derivable by re-scanning.
11405
+ *
11406
+ * See `RuntimeStateDurability`. Enforced by
11407
+ * `scripts/check-runtime-state-durability.ts`.
11408
+ */
11409
+ durability: "session",
11396
11410
  methods: {
11397
11411
  /**
11398
11412
  * Snapshot of the current `discovered` list. Returns the
@@ -13279,11 +13293,33 @@ var NotificationFormatSchema = _enum([
13279
13293
  * Named by INTENT, never by glyph. "check" would tie the vocabulary to one
13280
13294
  * renderer's icon set; "acknowledge" survives an adapter that draws it
13281
13295
  * differently.
13296
+ *
13297
+ * ── A TOKEN IS NOT A WIRE VALUE ─────────────────────────────────────
13298
+ *
13299
+ * These names are for US. **No adapter may forward one verbatim.** Each maps
13300
+ * the whole set onto its own renderer's vocabulary through a
13301
+ * `Record<NotificationActionIcon, string>` — a Record, never a lookup with a
13302
+ * fallback, so adding a member here fails every adapter's build until someone
13303
+ * decides its glyph, which is the only place that decision can be made
13304
+ * honestly.
13305
+ *
13306
+ * This paragraph is the bug. Zentik declared `actionIcons: true` and passed
13307
+ * `disarm` straight through; iOS feeds that string to
13308
+ * `UNNotificationActionIcon(systemImageName:)`, `disarm` is not an SF Symbol,
13309
+ * and every snooze and alarm button arrived BLANK. A pass-through is not a
13310
+ * mapping, and "the field is documented" is not "the value renders".
13311
+ *
13312
+ * Adding a member is TRAIN-BOUND. The enum lives in the published
13313
+ * `@camstack/server` closure and the cap seam validates against the HUB's copy,
13314
+ * so an addon that emits a token the running hub does not know does not lose an
13315
+ * icon — its whole `send` fails Zod validation and the notification never
13316
+ * arrives. Never emit a new token from an addon before the train carrying it.
13282
13317
  */
13283
13318
  var NotificationActionIconSchema = _enum([
13284
13319
  "acknowledge",
13285
13320
  "dismiss",
13286
13321
  "silence",
13322
+ "snooze",
13287
13323
  "view",
13288
13324
  "play",
13289
13325
  "open",
@@ -13291,9 +13327,13 @@ var NotificationActionIconSchema = _enum([
13291
13327
  "lock",
13292
13328
  "unlock",
13293
13329
  "arm",
13330
+ "arm-home",
13331
+ "arm-away",
13332
+ "arm-night",
13294
13333
  "disarm",
13295
13334
  "light",
13296
- "alert"
13335
+ "alert",
13336
+ "camera"
13297
13337
  ]);
13298
13338
  /** A single tap-through action button. */
13299
13339
  var NotificationActionSchema = object({
@@ -13309,7 +13349,23 @@ var NotificationActionSchema = object({
13309
13349
  * else — see `notification-center/action-token.ts` for what that does and
13310
13350
  * does not buy.
13311
13351
  */
13312
- destructive: boolean().optional()
13352
+ destructive: boolean().optional(),
13353
+ /**
13354
+ * How the tap should REACH the url.
13355
+ *
13356
+ * `navigate` (absent, and every button authored before this field) opens it:
13357
+ * the phone leaves the notification and shows whatever the callback returns.
13358
+ * That is right for a button whose answer the operator wants to read.
13359
+ *
13360
+ * `background` fires it as a POST and stays put. It exists for the buttons
13361
+ * whose whole point is not to interrupt — "silence this for 30 minutes" is
13362
+ * an answer to the notification, and being thrown into a browser tab to
13363
+ * confirm it costs more attention than the notification did. A backend that
13364
+ * cannot do a background call renders it as an ordinary link (the adapters
13365
+ * fall back rather than dropping the button), so this is a preference, never
13366
+ * a requirement.
13367
+ */
13368
+ mode: _enum(["navigate", "background"]).optional()
13313
13369
  });
13314
13370
  /**
13315
13371
  * The canonical notification. `body` is the only hard field (Apprise model).
@@ -13477,6 +13533,24 @@ method(object({}), array(TargetKindSchema)), method(object({}), array(TargetSche
13477
13533
  targetId: string$2(),
13478
13534
  enabled: boolean()
13479
13535
  }), _void(), { kind: "mutation" });
13536
+ new Set([
13537
+ {
13538
+ id: "person",
13539
+ name: "Person"
13540
+ },
13541
+ {
13542
+ id: "vehicle",
13543
+ name: "Vehicle"
13544
+ },
13545
+ {
13546
+ id: "animal",
13547
+ name: "Animal"
13548
+ },
13549
+ {
13550
+ id: "package",
13551
+ name: "Package"
13552
+ }
13553
+ ].map((l) => l.id));
13480
13554
  var COCO_TO_MACRO = {
13481
13555
  mapping: {
13482
13556
  person: "person",
@@ -14161,7 +14235,17 @@ var alarmPanelCapability = {
14161
14235
  * full slice; renders an arm button per `availableModes` entry and
14162
14236
  * a PIN field iff `requiresCode === true`.
14163
14237
  */
14164
- runtimeState: AlarmPanelStatusSchema
14238
+ runtimeState: AlarmPanelStatusSchema,
14239
+ /**
14240
+ * Runtime-state durability: **restored** — armed state is the one thing a panel must not lose across a restart.
14241
+ *
14242
+ * See `RuntimeStateDurability`. Enforced by
14243
+ * `scripts/check-runtime-state-durability.ts`.
14244
+ */
14245
+ durability: "restored",
14246
+ /** Clock fields: written, but excluded from the compare that decides
14247
+ * whether persisting is worth a SQLite commit. */
14248
+ volatileStateFields: ["lastChangedAt"]
14165
14249
  };
14166
14250
  /**
14167
14251
  * Shared geometry vocabulary for on-frame shape caps — privacy-mask,
@@ -14302,6 +14386,8 @@ var NcSystemEventKindSchema = _enum([
14302
14386
  "alarm-triggered",
14303
14387
  "alarm-armed",
14304
14388
  "alarm-disarmed",
14389
+ "alarm-arming",
14390
+ "alarm-arm-refused",
14305
14391
  "camera-online",
14306
14392
  "camera-offline",
14307
14393
  "camera-disabled",
@@ -14338,6 +14424,9 @@ var NcSystemEventConditionSchema = object({
14338
14424
  nodeIds: array(string$2().min(1)).min(1).optional(),
14339
14425
  packageNames: array(string$2().min(1)).min(1).optional()
14340
14426
  });
14427
+ /** Hard ceiling on a window (24h). A snooze that could not expire would be an
14428
+ * outage the operator asked for once and forgot. */
14429
+ var NC_SNOOZE_MAX_MINUTES = 1440;
14341
14430
  /** Weekly schedule — OR of windows; absence on the rule = always active. */
14342
14431
  var NcScheduleSchema = object({
14343
14432
  windows: array(object({
@@ -14714,15 +14803,15 @@ var NcConditionsSchema = object({
14714
14803
  * (an `immediate` rule naming an `audio-*` class, one notification per
14715
14804
  * classified sample) stays exactly as it was for rules that already use it.
14716
14805
  *
14717
- * NOT in {@link NC_CONDITION_CATALOG} yet, and that is the sequencing rule
14718
- * rather than an oversight: the viewer mirrors the descriptor enums BY HAND
14719
- * (`camstack/src/data/notification-center.ts`, guarded by
14720
- * `scripts/check-viewer-condition-mirror.ts`) and its rule editor STRIPS the
14806
+ * In {@link NC_CONDITION_CATALOG} since P2, and the ORDER it got there is the
14807
+ * rule rather than an accident: the viewer mirrors the descriptor enums BY
14808
+ * HAND (`camstack/src/data/notification-center.ts`, guarded by
14809
+ * `scripts/check-viewer-condition-mirror.ts`) and its rule editor strips the
14721
14810
  * condition fields it does not know when a rule is saved from the phone.
14722
14811
  * Publishing an editor for a condition the app cannot round-trip is how an
14723
- * operator loses a rule's conditions by opening it — so the descriptor, the
14724
- * admin widget and the viewer mirror land together (P2 + P3), and only then
14725
- * does an audio rule become authorable.
14812
+ * operator loses a rule's conditions by opening it — so the viewer mirror
14813
+ * (P3, shipped) went FIRST, and the descriptor an editor renders from
14814
+ * follows here.
14726
14815
  */
14727
14816
  audio: NcAudioConditionSchema.optional()
14728
14817
  });
@@ -14958,6 +15047,30 @@ var NcRuleInputSchema = object({
14958
15047
  */
14959
15048
  snoozeAllowGlobal: boolean().optional(),
14960
15049
  /**
15050
+ * The snooze durations THIS rule's notification offers as buttons, in
15051
+ * minutes.
15052
+ *
15053
+ * Three states, and all three are distinct — which is exactly why this is
15054
+ * `.optional()` and never `.default()`. A Zod default does not run on the
15055
+ * addon cap path (three production failures in one day), so a schema default
15056
+ * would collapse the first two:
15057
+ *
15058
+ * | value | meaning |
15059
+ * | --- | --- |
15060
+ * | absent | the operator never said ⇒ {@link NC_DEFAULT_SNOOZE_MINUTES} |
15061
+ * | `[]` | **no snooze buttons on this rule** — the explicit override |
15062
+ * | a list | these choices, de-duplicated and sorted, at most four |
15063
+ *
15064
+ * `.max(4)` because the notifier's own action budget is small (ntfy allows
15065
+ * three buttons in total) and a rule that spent it all on snooze choices
15066
+ * would push its own tap-through actions off the notification.
15067
+ *
15068
+ * An empty list is NOT an alarm exemption: a rule the alarm is about, or
15069
+ * that arms the panel, is exempt automatically and cannot be silenced by a
15070
+ * window from anywhere (D133).
15071
+ */
15072
+ snoozeOptions: array(number().int().min(1).max(NC_SNOOZE_MAX_MINUTES)).max(4).optional(),
15073
+ /**
14961
15074
  * Devices this rule ACTUATES — arm the alarm, open a gate, turn on a light.
14962
15075
  *
14963
15076
  * This is what makes the rule set the alarm's trigger set without the alarm
@@ -15057,6 +15170,7 @@ var NcConditionDescriptorSchema = object({
15057
15170
  "device",
15058
15171
  "package",
15059
15172
  "occupancy",
15173
+ "audio",
15060
15174
  "system"
15061
15175
  ]),
15062
15176
  label: string$2(),
@@ -15075,6 +15189,7 @@ var NcConditionDescriptorSchema = object({
15075
15189
  "crossingSelect",
15076
15190
  "polygonDraw",
15077
15191
  "occupancy",
15192
+ "audio",
15078
15193
  "deviceState",
15079
15194
  "systemEvent"
15080
15195
  ]),
@@ -15226,7 +15341,20 @@ var NcSnoozeInputSchema = object({
15226
15341
  ruleId: string$2().optional(),
15227
15342
  /** Required when `scope: 'device'`. */
15228
15343
  deviceId: number().int().optional(),
15229
- durationMinutes: number().int().min(1).max(1440),
15344
+ /**
15345
+ * Narrow the window to these subject classes — "the cat, not the person".
15346
+ *
15347
+ * ORTHOGONAL to `scope`, deliberately, and absent means EVERY class: that is
15348
+ * what every window authored before this field meant, so no persisted row
15349
+ * changes meaning and no client has to learn anything to keep working.
15350
+ *
15351
+ * It is what makes the window's real key `(deviceId, classes[])` and lets it
15352
+ * cross rules (D133): the operator points at a camera and a kind of thing,
15353
+ * not at whichever of their four rules happened to produce the notification
15354
+ * they are dismissing.
15355
+ */
15356
+ classes: array(string$2().min(1)).min(1).optional(),
15357
+ durationMinutes: number().int().min(1).max(NC_SNOOZE_MAX_MINUTES),
15230
15358
  /**
15231
15359
  * Silence this for EVERY recipient, not just the caller. Permission is
15232
15360
  * checked server-side (the rule's `snoozeAllowGlobal`, or admin for the
@@ -15251,6 +15379,10 @@ var NcSnoozeSchema = object({
15251
15379
  scope: NcSnoozeScopeSchema,
15252
15380
  ruleId: string$2().optional(),
15253
15381
  deviceId: number().int().optional(),
15382
+ /** Subject classes this window covers. ABSENT = every class — see
15383
+ * {@link NcSnoozeInputSchema.shape.classes}. Lives in the JSON blob and has
15384
+ * no SQLite column: nothing queries a window by class. */
15385
+ classes: array(string$2().min(1)).min(1).optional(),
15254
15386
  startedAt: number(),
15255
15387
  /** Exclusive: at exactly this instant the snooze is over. Expiry is a
15256
15388
  * COMPARISON, not a job — no sweeper can leave the operator silenced. */
@@ -17351,7 +17483,14 @@ var zonesCapability = {
17351
17483
  * handle. Slice shape is `{ zones: Zone[] }` so future extensions
17352
17484
  * (e.g. zone groupings) can sit alongside the polygon list.
17353
17485
  */
17354
- runtimeState: object({ zones: array(ZoneSchema).readonly() })
17486
+ runtimeState: object({ zones: array(ZoneSchema).readonly() }),
17487
+ /**
17488
+ * Runtime-state durability: **restored** — written only on operator mutation, so a camera that never had one has nothing to re-derive from. This is the slice `zone-mirror-hydration.ts` exists to paper over.
17489
+ *
17490
+ * See `RuntimeStateDurability`. Enforced by
17491
+ * `scripts/check-runtime-state-durability.ts`.
17492
+ */
17493
+ durability: "restored"
17355
17494
  };
17356
17495
  /**
17357
17496
  * A bounding box in NORMALIZED [0,1] frame coordinates for `getNativeCrop`. The
@@ -17521,6 +17660,22 @@ var detectionFpsField = {
17521
17660
  default: 10,
17522
17661
  step: 1
17523
17662
  };
17663
+ /**
17664
+ * The occupancy re-check interval. DEFAULT 300 s (2026-08-13 — was 30 s).
17665
+ *
17666
+ * The recheck is now on by default (a parked car is invisible to occupancy
17667
+ * rules until the stationary registry has been rebuilt by motion, which after a
17668
+ * restart may be never on a quiet camera). Each cycle re-subscribes a detection
17669
+ * session — an RTSP re-dial — so the switch is only affordable at a WIDE
17670
+ * interval: 300 s is ~12 re-dials an hour per camera, against 120 at the old
17671
+ * 30 s. A parked car is therefore counted within 5 minutes of a restart.
17672
+ *
17673
+ * Why not wider: `max` is 300 and raising it is TRAIN-BOUND, not addon-bound —
17674
+ * the host validates `attachCamera` against ITS copy of this schema, so a
17675
+ * runner asked for 600 would be rejected by the hub until a `@camstack/server`
17676
+ * carrying the wider bound is installed everywhere. 300 is the widest value
17677
+ * that ships with an addon deploy.
17678
+ */
17524
17679
  var occupancyRecheckSecField = {
17525
17680
  min: 0,
17526
17681
  max: 300,
@@ -17722,15 +17877,21 @@ var RunnerCameraConfigSchema = object({
17722
17877
  */
17723
17878
  onboardMotionDrivesAnalyzer: boolean().default(true),
17724
17879
  /**
17725
- * Master toggle for the occupancy re-check. When `false` (DEFAULT) the runner
17726
- * never arms the periodic recheck timer, regardless of `occupancyRecheckSec` —
17727
- * this is off by default because the recheck re-subscribes a detection session
17728
- * every N seconds while `watching`, a major source of pull-decoder re-dial
17729
- * churn (each cycle creates+tears a session → RTSP re-dial → latency). The
17880
+ * Master toggle for the occupancy re-check. When `false` the runner never arms
17881
+ * the periodic recheck timer, regardless of `occupancyRecheckSec`; the
17730
17882
  * `occupancyRecheckSec` / `occupancyRecheckFrames` sliders only take effect
17731
17883
  * (and only render) when this is enabled.
17884
+ *
17885
+ * DEFAULT `true` since 2026-08-13 (was `false`). It was off because the
17886
+ * recheck re-subscribes a detection session every N seconds while `watching`
17887
+ * — each cycle creates+tears a session ⇒ an RTSP re-dial ⇒ latency, a major
17888
+ * pull-decoder churn source. What that bought was a blind spot: a STATIONARY
17889
+ * object is counted only while the stationary registry holds it, and the
17890
+ * registry rebuilds from motion, so after a restart a parked car was invisible
17891
+ * to every occupancy rule until something moved in front of it. The churn is
17892
+ * now paid on the interval instead — see `occupancyRecheckSecField`.
17732
17893
  */
17733
- occupancyRecheckEnabled: boolean().default(false),
17894
+ occupancyRecheckEnabled: boolean().default(true),
17734
17895
  occupancyRecheckSec: number().min(occupancyRecheckSecField.min).max(occupancyRecheckSecField.max).default(occupancyRecheckSecField.default),
17735
17896
  occupancyRecheckFrames: number().min(occupancyRecheckFramesField.min).max(occupancyRecheckFramesField.max).default(occupancyRecheckFramesField.default),
17736
17897
  /**
@@ -20150,7 +20311,17 @@ var airQualitySensorCapability = {
20150
20311
  schema: AirQualitySensorStatusSchema,
20151
20312
  kind: "push"
20152
20313
  },
20153
- runtimeState: AirQualitySensorStatusSchema
20314
+ runtimeState: AirQualitySensorStatusSchema,
20315
+ /**
20316
+ * Runtime-state durability: **restored** — as `numeric-sensor`.
20317
+ *
20318
+ * See `RuntimeStateDurability`. Enforced by
20319
+ * `scripts/check-runtime-state-durability.ts`.
20320
+ */
20321
+ durability: "restored",
20322
+ /** Clock fields: written, but excluded from the compare that decides
20323
+ * whether persisting is worth a SQLite commit. */
20324
+ volatileStateFields: ["lastFetchedAt"]
20154
20325
  };
20155
20326
  /**
20156
20327
  * Ambient illuminance reading in lux. Drives Home Assistant `sensor`
@@ -20182,7 +20353,17 @@ var ambientLightSensorCapability = {
20182
20353
  schema: AmbientLightSensorStatusSchema,
20183
20354
  kind: "push"
20184
20355
  },
20185
- runtimeState: AmbientLightSensorStatusSchema
20356
+ runtimeState: AmbientLightSensorStatusSchema,
20357
+ /**
20358
+ * Runtime-state durability: **restored** — as `numeric-sensor`.
20359
+ *
20360
+ * See `RuntimeStateDurability`. Enforced by
20361
+ * `scripts/check-runtime-state-durability.ts`.
20362
+ */
20363
+ durability: "restored",
20364
+ /** Clock fields: written, but excluded from the compare that decides
20365
+ * whether persisting is worth a SQLite commit. */
20366
+ volatileStateFields: ["lastFetchedAt"]
20186
20367
  };
20187
20368
  /**
20188
20369
  * Per-class audio metrics aggregated over a sliding window.
@@ -20300,7 +20481,14 @@ var audioMetricsCapability = {
20300
20481
  }), AudioMetricsHistorySchema)
20301
20482
  },
20302
20483
  /** Reactive runtime-state mirror — live `device.state.audioMetrics.value`. */
20303
- runtimeState: AudioMetricsSnapshotSchema
20484
+ runtimeState: AudioMetricsSnapshotSchema,
20485
+ /**
20486
+ * Runtime-state durability: **session** — 1 Hz per camera at the mirror and ~63 % of the fleet's whole runtime-state write rate. `avgDbfs` is a rolling 60 s mean that genuinely moves every second, so no equality fix reclaims it — and a two-hour-old dB reading rendered as current is worse than no reading.
20487
+ *
20488
+ * See `RuntimeStateDurability`. Enforced by
20489
+ * `scripts/check-runtime-state-durability.ts`.
20490
+ */
20491
+ durability: "session"
20304
20492
  };
20305
20493
  /**
20306
20494
  * Automation-control cap. Models HA `automation.*` entities on
@@ -20362,7 +20550,14 @@ var automationControlCapability = {
20362
20550
  * reads `enabled` (toggle) + `isRunning` (spinner) + `lastError`
20363
20551
  * (badge) directly.
20364
20552
  */
20365
- runtimeState: AutomationControlStatusSchema
20553
+ runtimeState: AutomationControlStatusSchema,
20554
+ /**
20555
+ * Runtime-state durability: **session** — the authority for an automation being enabled is the automation store; a restored `isRunning` would be a lie. D62: one authority per switch.
20556
+ *
20557
+ * See `RuntimeStateDurability`. Enforced by
20558
+ * `scripts/check-runtime-state-durability.ts`.
20559
+ */
20560
+ durability: "session"
20366
20561
  };
20367
20562
  /**
20368
20563
  * Battery status snapshot. Emitted by providers whose device is
@@ -20468,7 +20663,17 @@ onStatusChanged: { data: object({
20468
20663
  * via `device.runtimeState.getCapState('battery')` regardless of
20469
20664
  * the underlying driver.
20470
20665
  */
20471
- runtimeState: BatteryStatusSchema
20666
+ runtimeState: BatteryStatusSchema,
20667
+ /**
20668
+ * Runtime-state durability: **restored** — a sleeping battery camera may not report for hours; the restored percentage is the only thing the UI and the sleep gate have. Zero churn once `lastUpdated` is excluded — 526 writes, 0 value changes, in 25 minutes.
20669
+ *
20670
+ * See `RuntimeStateDurability`. Enforced by
20671
+ * `scripts/check-runtime-state-durability.ts`.
20672
+ */
20673
+ durability: "restored",
20674
+ /** Clock fields: written, but excluded from the compare that decides
20675
+ * whether persisting is worth a SQLite commit. */
20676
+ volatileStateFields: ["lastUpdated"]
20472
20677
  };
20473
20678
  /**
20474
20679
  * Generic boolean sensor — last-resort fallback when no domain-
@@ -20497,7 +20702,17 @@ var binaryCapability = {
20497
20702
  schema: BinaryStatusSchema,
20498
20703
  kind: "push"
20499
20704
  },
20500
- runtimeState: BinaryStatusSchema
20705
+ runtimeState: BinaryStatusSchema,
20706
+ /**
20707
+ * Runtime-state durability: **restored** — transition-driven sensor state; the restored value gives the boot comparison.
20708
+ *
20709
+ * See `RuntimeStateDurability`. Enforced by
20710
+ * `scripts/check-runtime-state-durability.ts`.
20711
+ */
20712
+ durability: "restored",
20713
+ /** Clock fields: written, but excluded from the compare that decides
20714
+ * whether persisting is worth a SQLite commit. */
20715
+ volatileStateFields: ["lastChangedAt"]
20501
20716
  };
20502
20717
  /**
20503
20718
  * Dimmable-light brightness control. Co-exists with `switch` on the
@@ -20550,7 +20765,14 @@ onBrightnessChanged: { data: object({
20550
20765
  * by the kernel. Read via `device.state.brightness.value` so UI
20551
20766
  * sliders surface the current level without polling the provider.
20552
20767
  */
20553
- runtimeState: BrightnessStatusSchema
20768
+ runtimeState: BrightnessStatusSchema,
20769
+ /**
20770
+ * Runtime-state durability: **session** — live lamp state, re-published by the provider on connect.
20771
+ *
20772
+ * See `RuntimeStateDurability`. Enforced by
20773
+ * `scripts/check-runtime-state-durability.ts`.
20774
+ */
20775
+ durability: "session"
20554
20776
  };
20555
20777
  /**
20556
20778
  * button — device-scoped capability for HA `button.*` / `input_button.*`
@@ -20655,7 +20877,17 @@ var carbonMonoxideCapability = {
20655
20877
  schema: CarbonMonoxideStatusSchema,
20656
20878
  kind: "push"
20657
20879
  },
20658
- runtimeState: CarbonMonoxideStatusSchema
20880
+ runtimeState: CarbonMonoxideStatusSchema,
20881
+ /**
20882
+ * Runtime-state durability: **restored** — as `smoke`.
20883
+ *
20884
+ * See `RuntimeStateDurability`. Enforced by
20885
+ * `scripts/check-runtime-state-durability.ts`.
20886
+ */
20887
+ durability: "restored",
20888
+ /** Clock fields: written, but excluded from the compare that decides
20889
+ * whether persisting is worth a SQLite commit. */
20890
+ volatileStateFields: ["lastChangedAt"]
20659
20891
  };
20660
20892
  /**
20661
20893
  * HVAC / climate control cap. Models the full surface of a HA
@@ -20815,7 +21047,14 @@ var climateControlCapability = {
20815
21047
  * the full slice via `device.state.climate-control.value` and refresh
20816
21048
  * on every push without re-querying the provider.
20817
21049
  */
20818
- runtimeState: ClimateControlStatusSchema
21050
+ runtimeState: ClimateControlStatusSchema,
21051
+ /**
21052
+ * Runtime-state durability: **session** — as `brightness`; `currentTemp` moves continuously and is re-published on connect.
21053
+ *
21054
+ * See `RuntimeStateDurability`. Enforced by
21055
+ * `scripts/check-runtime-state-durability.ts`.
21056
+ */
21057
+ durability: "session"
20819
21058
  };
20820
21059
  /**
20821
21060
  * Color-light cap. Coexists with `switch` (on/off) and `brightness`
@@ -20925,7 +21164,14 @@ onColorChanged: { data: object({
20925
21164
  * kernel. Read via `device.state.color.value` so UI pickers surface
20926
21165
  * the current chromaticity without polling the provider.
20927
21166
  */
20928
- runtimeState: ColorStatusSchema
21167
+ runtimeState: ColorStatusSchema,
21168
+ /**
21169
+ * Runtime-state durability: **session** — as `brightness`.
21170
+ *
21171
+ * See `RuntimeStateDurability`. Enforced by
21172
+ * `scripts/check-runtime-state-durability.ts`.
21173
+ */
21174
+ durability: "session"
20929
21175
  };
20930
21176
  var ConnectionTestOutcomeSchema = discriminatedUnion("outcome", [
20931
21177
  object({
@@ -20983,7 +21229,17 @@ var connectivityCapability = {
20983
21229
  schema: ConnectivityStatusSchema,
20984
21230
  kind: "push"
20985
21231
  },
20986
- runtimeState: ConnectivityStatusSchema
21232
+ runtimeState: ConnectivityStatusSchema,
21233
+ /**
21234
+ * Runtime-state durability: **restored** — same shape and same argument as `device-status`, for links rather than devices.
21235
+ *
21236
+ * See `RuntimeStateDurability`. Enforced by
21237
+ * `scripts/check-runtime-state-durability.ts`.
21238
+ */
21239
+ durability: "restored",
21240
+ /** Clock fields: written, but excluded from the compare that decides
21241
+ * whether persisting is worth a SQLite commit. */
21242
+ volatileStateFields: ["lastChangedAt"]
20987
21243
  };
20988
21244
  /**
20989
21245
  * Generic device-consumables capability — surfaces a device's
@@ -21065,7 +21321,14 @@ reset: method(object({
21065
21321
  }
21066
21322
  }
21067
21323
  },
21068
- runtimeState: ConsumablesStatusSchema.extend({ lastFetchedAt: number() })
21324
+ runtimeState: ConsumablesStatusSchema.extend({ lastFetchedAt: number() }),
21325
+ /**
21326
+ * Runtime-state durability: **session** — the authority is the appliance; the provider re-reads the whole item array on connect.
21327
+ *
21328
+ * See `RuntimeStateDurability`. Enforced by
21329
+ * `scripts/check-runtime-state-durability.ts`.
21330
+ */
21331
+ durability: "session"
21069
21332
  };
21070
21333
  /**
21071
21334
  * Door / window / opening / garage / valve contact sensor. Boolean
@@ -21096,7 +21359,17 @@ var contactCapability = {
21096
21359
  schema: ContactStatusSchema,
21097
21360
  kind: "push"
21098
21361
  },
21099
- runtimeState: ContactStatusSchema
21362
+ runtimeState: ContactStatusSchema,
21363
+ /**
21364
+ * Runtime-state durability: **restored** — a door left open across a restart must still read open.
21365
+ *
21366
+ * See `RuntimeStateDurability`. Enforced by
21367
+ * `scripts/check-runtime-state-durability.ts`.
21368
+ */
21369
+ durability: "restored",
21370
+ /** Clock fields: written, but excluded from the compare that decides
21371
+ * whether persisting is worth a SQLite commit. */
21372
+ volatileStateFields: ["lastChangedAt"]
21100
21373
  };
21101
21374
  /**
21102
21375
  * Status slice — flat object (the framework's `runtimeState` contract
@@ -21202,7 +21475,14 @@ var controlCapability = {
21202
21475
  * dropdown / text field / date picker) read the slice's discriminant
21203
21476
  * and value directly without polling the provider.
21204
21477
  */
21205
- runtimeState: ControlStatusSchema
21478
+ runtimeState: ControlStatusSchema,
21479
+ /**
21480
+ * Runtime-state durability: **session** — a generic control mirrors an external entity that re-publishes on connect; the options array is re-derived with it.
21481
+ *
21482
+ * See `RuntimeStateDurability`. Enforced by
21483
+ * `scripts/check-runtime-state-durability.ts`.
21484
+ */
21485
+ durability: "session"
21206
21486
  };
21207
21487
  var CoverStatusSchema = object({
21208
21488
  /** Lifecycle state of the cover. */
@@ -21263,7 +21543,17 @@ var coverCapability = {
21263
21543
  * Runtime-state slice — mirrored by the kernel. UI controls watch
21264
21544
  * the slice for live position changes during a move.
21265
21545
  */
21266
- runtimeState: CoverStatusSchema
21546
+ runtimeState: CoverStatusSchema,
21547
+ /**
21548
+ * Runtime-state durability: **restored** — position survives a restart on the device; the mirror should agree at boot rather than read blank.
21549
+ *
21550
+ * See `RuntimeStateDurability`. Enforced by
21551
+ * `scripts/check-runtime-state-durability.ts`.
21552
+ */
21553
+ durability: "restored",
21554
+ /** Clock fields: written, but excluded from the compare that decides
21555
+ * whether persisting is worth a SQLite commit. */
21556
+ volatileStateFields: ["lastChangedAt"]
21267
21557
  };
21268
21558
  /**
21269
21559
  * Vendor-neutral day/night (IR-cut) control — the per-camera config cap
@@ -21357,7 +21647,17 @@ var dayNightCapability = {
21357
21647
  schema: DayNightStatusSchema,
21358
21648
  kind: "poll"
21359
21649
  },
21360
- runtimeState: DayNightStatusSchema
21650
+ runtimeState: DayNightStatusSchema,
21651
+ /**
21652
+ * Runtime-state durability: **restored** — operator-set IR-cut behaviour; mutation-driven.
21653
+ *
21654
+ * See `RuntimeStateDurability`. Enforced by
21655
+ * `scripts/check-runtime-state-durability.ts`.
21656
+ */
21657
+ durability: "restored",
21658
+ /** Clock fields: written, but excluded from the compare that decides
21659
+ * whether persisting is worth a SQLite commit. */
21660
+ volatileStateFields: ["lastFetchedAt"]
21361
21661
  };
21362
21662
  /**
21363
21663
  * Generic device-level status snapshot. Auto-registered by `BaseDevice`
@@ -21404,7 +21704,17 @@ onStatusChanged: { data: object({
21404
21704
  schema: DeviceStatusSchema,
21405
21705
  kind: "push"
21406
21706
  },
21407
- runtimeState: DeviceStatusSchema
21707
+ runtimeState: DeviceStatusSchema,
21708
+ /**
21709
+ * Runtime-state durability: **restored** — the previous observation is what makes the first reading after a restart a COMPARISON instead of a phantom transition (D130). 32 real flips across 16 devices in 25 min — the busiest slice in the cold half.
21710
+ *
21711
+ * See `RuntimeStateDurability`. Enforced by
21712
+ * `scripts/check-runtime-state-durability.ts`.
21713
+ */
21714
+ durability: "restored",
21715
+ /** Clock fields: written, but excluded from the compare that decides
21716
+ * whether persisting is worth a SQLite commit. */
21717
+ volatileStateFields: ["lastChangedAt"]
21408
21718
  };
21409
21719
  /**
21410
21720
  * Doorbell button cap. Two kinds of providers coexist behind this cap
@@ -21466,7 +21776,14 @@ onPressed: { data: DoorbellPressEventSchema } },
21466
21776
  * `device.state.doorbell.value`. UIs can show "last ring 5m ago"
21467
21777
  * without subscribing.
21468
21778
  */
21469
- runtimeState: DoorbellStatusSchema
21779
+ runtimeState: DoorbellStatusSchema,
21780
+ /**
21781
+ * Runtime-state durability: **restored** — a monotonic accumulator: the slice IS the record. `lastPressedAt` is content here, not a clock, so it is deliberately NOT volatile.
21782
+ *
21783
+ * See `RuntimeStateDurability`. Enforced by
21784
+ * `scripts/check-runtime-state-durability.ts`.
21785
+ */
21786
+ durability: "restored"
21470
21787
  };
21471
21788
  /**
21472
21789
  * Enum-state sensor — a string value picked from a finite option set.
@@ -21506,7 +21823,17 @@ var enumSensorCapability = {
21506
21823
  schema: EnumSensorStatusSchema,
21507
21824
  kind: "push"
21508
21825
  },
21509
- runtimeState: EnumSensorStatusSchema
21826
+ runtimeState: EnumSensorStatusSchema,
21827
+ /**
21828
+ * Runtime-state durability: **restored** — as `numeric-sensor`; 80 devices.
21829
+ *
21830
+ * See `RuntimeStateDurability`. Enforced by
21831
+ * `scripts/check-runtime-state-durability.ts`.
21832
+ */
21833
+ durability: "restored",
21834
+ /** Clock fields: written, but excluded from the compare that decides
21835
+ * whether persisting is worth a SQLite commit. */
21836
+ volatileStateFields: ["lastFetchedAt"]
21510
21837
  };
21511
21838
  /**
21512
21839
  * Generic stateless event emitter. Installed on a `DeviceType.EventEmitter`
@@ -21542,7 +21869,14 @@ var eventEmitterCapability = {
21542
21869
  schema: EventEmitterStatusSchema,
21543
21870
  kind: "push"
21544
21871
  },
21545
- runtimeState: EventEmitterStatusSchema
21872
+ runtimeState: EventEmitterStatusSchema,
21873
+ /**
21874
+ * Runtime-state durability: **session** — `eventCountSinceStart` names its own scope.
21875
+ *
21876
+ * See `RuntimeStateDurability`. Enforced by
21877
+ * `scripts/check-runtime-state-durability.ts`.
21878
+ */
21879
+ durability: "session"
21546
21880
  };
21547
21881
  var EventItemSchema = object({
21548
21882
  id: string$2(),
@@ -21823,7 +22157,14 @@ var fanControlCapability = {
21823
22157
  * Runtime-state slice — mirrored by the kernel. UI fan speed
21824
22158
  * sliders read `percentage` for live updates.
21825
22159
  */
21826
- runtimeState: FanControlStatusSchema
22160
+ runtimeState: FanControlStatusSchema,
22161
+ /**
22162
+ * Runtime-state durability: **session** — as `brightness`.
22163
+ *
22164
+ * See `RuntimeStateDurability`. Enforced by
22165
+ * `scripts/check-runtime-state-durability.ts`.
22166
+ */
22167
+ durability: "session"
21827
22168
  };
21828
22169
  /**
21829
22170
  * Per-device feature/identity probe slice. Holds the runtime-resolved
@@ -21899,7 +22240,14 @@ onProbeChanged: { data: object({
21899
22240
  schema: FeatureProbeStatusSchema,
21900
22241
  kind: "push"
21901
22242
  },
21902
- runtimeState: FeatureProbeStatusSchema
22243
+ runtimeState: FeatureProbeStatusSchema,
22244
+ /**
22245
+ * Runtime-state durability: **session** — per-session by definition — `lastProbedAt` means "this worker completed a probe THIS session", which is why the mirror seed already blanks it. Persisting it only creates something to blank.
22246
+ *
22247
+ * See `RuntimeStateDurability`. Enforced by
22248
+ * `scripts/check-runtime-state-durability.ts`.
22249
+ */
22250
+ durability: "session"
21903
22251
  };
21904
22252
  /**
21905
22253
  * Water leak / moisture sensor. Boolean "is liquid currently
@@ -21926,7 +22274,17 @@ var floodCapability = {
21926
22274
  schema: FloodStatusSchema,
21927
22275
  kind: "push"
21928
22276
  },
21929
- runtimeState: FloodStatusSchema
22277
+ runtimeState: FloodStatusSchema,
22278
+ /**
22279
+ * Runtime-state durability: **restored** — as `smoke`.
22280
+ *
22281
+ * See `RuntimeStateDurability`. Enforced by
22282
+ * `scripts/check-runtime-state-durability.ts`.
22283
+ */
22284
+ durability: "restored",
22285
+ /** Clock fields: written, but excluded from the compare that decides
22286
+ * whether persisting is worth a SQLite commit. */
22287
+ volatileStateFields: ["lastChangedAt"]
21930
22288
  };
21931
22289
  /**
21932
22290
  * Combustible-gas (LPG / methane / hydrogen) alarm sensor. Drives
@@ -21949,7 +22307,17 @@ var gasCapability = {
21949
22307
  schema: GasStatusSchema,
21950
22308
  kind: "push"
21951
22309
  },
21952
- runtimeState: GasStatusSchema
22310
+ runtimeState: GasStatusSchema,
22311
+ /**
22312
+ * Runtime-state durability: **restored** — as `smoke`.
22313
+ *
22314
+ * See `RuntimeStateDurability`. Enforced by
22315
+ * `scripts/check-runtime-state-durability.ts`.
22316
+ */
22317
+ durability: "restored",
22318
+ /** Clock fields: written, but excluded from the compare that decides
22319
+ * whether persisting is worth a SQLite commit. */
22320
+ volatileStateFields: ["lastChangedAt"]
21953
22321
  };
21954
22322
  /**
21955
22323
  * Humidifier / dehumidifier cap. Models HA `humidifier.*` entities —
@@ -22025,7 +22393,14 @@ var humidifierCapability = {
22025
22393
  * Runtime-state slice — mirrored by the kernel. UI controls watch the
22026
22394
  * slice for live humidity / mode changes.
22027
22395
  */
22028
- runtimeState: HumidifierStatusSchema
22396
+ runtimeState: HumidifierStatusSchema,
22397
+ /**
22398
+ * Runtime-state durability: **session** — as `climate-control`.
22399
+ *
22400
+ * See `RuntimeStateDurability`. Enforced by
22401
+ * `scripts/check-runtime-state-durability.ts`.
22402
+ */
22403
+ durability: "session"
22029
22404
  };
22030
22405
  /**
22031
22406
  * Single-metric humidity reading. Drives Home Assistant `sensor`
@@ -22061,7 +22436,17 @@ var humiditySensorCapability = {
22061
22436
  schema: HumiditySensorStatusSchema,
22062
22437
  kind: "push"
22063
22438
  },
22064
- runtimeState: HumiditySensorStatusSchema
22439
+ runtimeState: HumiditySensorStatusSchema,
22440
+ /**
22441
+ * Runtime-state durability: **restored** — as `numeric-sensor` (67 of 75 writes were the clock alone).
22442
+ *
22443
+ * See `RuntimeStateDurability`. Enforced by
22444
+ * `scripts/check-runtime-state-durability.ts`.
22445
+ */
22446
+ durability: "restored",
22447
+ /** Clock fields: written, but excluded from the compare that decides
22448
+ * whether persisting is worth a SQLite commit. */
22449
+ volatileStateFields: ["lastFetchedAt"]
22065
22450
  };
22066
22451
  /**
22067
22452
  * Image display cap. Models a single still image exposed by an integration —
@@ -22099,7 +22484,14 @@ var imageCapability = {
22099
22484
  * Runtime-state slice — mirrored by the kernel. The UI reads `url`
22100
22485
  * directly and renders the still image.
22101
22486
  */
22102
- runtimeState: ImageStatusSchema
22487
+ runtimeState: ImageStatusSchema,
22488
+ /**
22489
+ * Runtime-state durability: **session** — a snapshot URL is a session-scoped handle; a restored one points at nothing.
22490
+ *
22491
+ * See `RuntimeStateDurability`. Enforced by
22492
+ * `scripts/check-runtime-state-durability.ts`.
22493
+ */
22494
+ durability: "session"
22103
22495
  };
22104
22496
  /**
22105
22497
  * Vendor-neutral image / picture-adjustment cap — the per-camera config
@@ -22248,7 +22640,17 @@ var imageSettingsCapability = {
22248
22640
  schema: ImageSettingsStatusSchema,
22249
22641
  kind: "poll"
22250
22642
  },
22251
- runtimeState: ImageSettingsStatusSchema
22643
+ runtimeState: ImageSettingsStatusSchema,
22644
+ /**
22645
+ * Runtime-state durability: **restored** — operator-set camera imaging; mutation-driven.
22646
+ *
22647
+ * See `RuntimeStateDurability`. Enforced by
22648
+ * `scripts/check-runtime-state-durability.ts`.
22649
+ */
22650
+ durability: "restored",
22651
+ /** Clock fields: written, but excluded from the compare that decides
22652
+ * whether persisting is worth a SQLite commit. */
22653
+ volatileStateFields: ["lastFetchedAt"]
22252
22654
  };
22253
22655
  /**
22254
22656
  * integrations — system-scoped singleton capability for integration
@@ -22588,7 +22990,14 @@ var lawnMowerControlCapability = {
22588
22990
  * Runtime-state slice — mirrored by the kernel. UI controls watch the
22589
22991
  * slice for live activity + battery changes.
22590
22992
  */
22591
- runtimeState: LawnMowerControlStatusSchema
22993
+ runtimeState: LawnMowerControlStatusSchema,
22994
+ /**
22995
+ * Runtime-state durability: **session** — as `vacuum-control`.
22996
+ *
22997
+ * See `RuntimeStateDurability`. Enforced by
22998
+ * `scripts/check-runtime-state-durability.ts`.
22999
+ */
23000
+ durability: "session"
22592
23001
  };
22593
23002
  /**
22594
23003
  * local-network — hub-only singleton.
@@ -22794,7 +23203,17 @@ var lockControlCapability = {
22794
23203
  * read `state` and disable themselves during `locking`/`unlocking`
22795
23204
  * transitions.
22796
23205
  */
22797
- runtimeState: LockControlStatusSchema
23206
+ runtimeState: LockControlStatusSchema,
23207
+ /**
23208
+ * Runtime-state durability: **restored** — a lock left locked must still read locked.
23209
+ *
23210
+ * See `RuntimeStateDurability`. Enforced by
23211
+ * `scripts/check-runtime-state-durability.ts`.
23212
+ */
23213
+ durability: "restored",
23214
+ /** Clock fields: written, but excluded from the compare that decides
23215
+ * whether persisting is worth a SQLite commit. */
23216
+ volatileStateFields: ["lastChangedAt"]
22798
23217
  };
22799
23218
  /**
22800
23219
  * Media-player cap. Models HA `media_player.*` (Sonos, Chromecast,
@@ -22956,7 +23375,14 @@ var mediaPlayerCapability = {
22956
23375
  * full slice for live now-playing, volume, and progress updates
22957
23376
  * without polling.
22958
23377
  */
22959
- runtimeState: MediaPlayerStatusSchema
23378
+ runtimeState: MediaPlayerStatusSchema,
23379
+ /**
23380
+ * Runtime-state durability: **session** — a restored transport position describes a playback that stopped when the hub did.
23381
+ *
23382
+ * See `RuntimeStateDurability`. Enforced by
23383
+ * `scripts/check-runtime-state-durability.ts`.
23384
+ */
23385
+ durability: "session"
22960
23386
  };
22961
23387
  /**
22962
23388
  * mesh-network — collection cap for mesh-VPN providers.
@@ -23220,7 +23646,14 @@ onMotionChanged: { data: MotionOnMotionChangedDataSchema } },
23220
23646
  * `device.state.motion.value`. Reads never invoke the provider, so
23221
23647
  * UIs and other addons can poll the cached state safely.
23222
23648
  */
23223
- runtimeState: MotionStatusSchema
23649
+ runtimeState: MotionStatusSchema,
23650
+ /**
23651
+ * Runtime-state durability: **session** — self-clearing by construction (`autoClearAfterMs`); a restored `detected: true` is a frozen event, and the next frame re-publishes the real one.
23652
+ *
23653
+ * See `RuntimeStateDurability`. Enforced by
23654
+ * `scripts/check-runtime-state-durability.ts`.
23655
+ */
23656
+ durability: "session"
23224
23657
  };
23225
23658
  /**
23226
23659
  * Motion-trigger toggle for accessory devices.
@@ -23285,7 +23718,14 @@ var motionTriggerCapability = {
23285
23718
  schema: MotionTriggerStatusSchema,
23286
23719
  kind: "command-driven"
23287
23720
  },
23288
- runtimeState: MotionTriggerRuntimeStateSchema
23721
+ runtimeState: MotionTriggerRuntimeStateSchema,
23722
+ /**
23723
+ * Runtime-state durability: **session** — the authority for motion-trigger enablement is the provider's own config; the slice is a mirror of it, re-published on connect.
23724
+ *
23725
+ * See `RuntimeStateDurability`. Enforced by
23726
+ * `scripts/check-runtime-state-durability.ts`.
23727
+ */
23728
+ durability: "session"
23289
23729
  };
23290
23730
  /**
23291
23731
  * Motion-zones share the same MaskShape vocabulary as privacy-mask — the
@@ -23352,7 +23792,17 @@ var motionZonesCapability = {
23352
23792
  schema: MotionZoneStatusSchema,
23353
23793
  kind: "poll"
23354
23794
  },
23355
- runtimeState: MotionZoneStatusSchema
23795
+ runtimeState: MotionZoneStatusSchema,
23796
+ /**
23797
+ * Runtime-state durability: **restored** — the 14 KB polygon list is the single largest slice on the fleet and has not changed since the operator drew it. Highest value per byte in the table.
23798
+ *
23799
+ * See `RuntimeStateDurability`. Enforced by
23800
+ * `scripts/check-runtime-state-durability.ts`.
23801
+ */
23802
+ durability: "restored",
23803
+ /** Clock fields: written, but excluded from the compare that decides
23804
+ * whether persisting is worth a SQLite commit. */
23805
+ volatileStateFields: ["lastFetchedAt"]
23356
23806
  };
23357
23807
  /**
23358
23808
  * On-camera AI object detection cap. Surfaces per-device the classes
@@ -23426,7 +23876,17 @@ var nativeObjectDetectionCapability = {
23426
23876
  schema: NativeObjectDetectionStatusSchema,
23427
23877
  kind: "push"
23428
23878
  },
23429
- runtimeState: NativeObjectDetectionRuntimeStateSchema
23879
+ runtimeState: NativeObjectDetectionRuntimeStateSchema,
23880
+ /**
23881
+ * Runtime-state durability: **restored** — `enabled` is an operator toggle on a camera whose refresh is a no-op and whose staleMs is Infinity. There is no hardware value to re-read — losing it loses the setting.
23882
+ *
23883
+ * See `RuntimeStateDurability`. Enforced by
23884
+ * `scripts/check-runtime-state-durability.ts`.
23885
+ */
23886
+ durability: "restored",
23887
+ /** Clock fields: written, but excluded from the compare that decides
23888
+ * whether persisting is worth a SQLite commit. */
23889
+ volatileStateFields: ["lastFetchedAt"]
23430
23890
  };
23431
23891
  /**
23432
23892
  * network-quality — system-scoped singleton capability tracking RTT,
@@ -23760,7 +24220,14 @@ onSent: { data: object({
23760
24220
  * form reads `supports` to gate optional fields; history pane reads
23761
24221
  * `lastSentAt` / `lastError` / `queueDepth`.
23762
24222
  */
23763
- runtimeState: NotifierStatusSchema
24223
+ runtimeState: NotifierStatusSchema,
24224
+ /**
24225
+ * Runtime-state durability: **session** — live queue depth and last-send state; a restored queue depth describes a queue that no longer exists.
24226
+ *
24227
+ * See `RuntimeStateDurability`. Enforced by
24228
+ * `scripts/check-runtime-state-durability.ts`.
24229
+ */
24230
+ durability: "session"
23764
24231
  };
23765
24232
  /**
23766
24233
  * Generic numeric sensor — last-resort fallback when no typed numeric
@@ -23803,7 +24270,17 @@ var numericSensorCapability = {
23803
24270
  schema: NumericSensorStatusSchema,
23804
24271
  kind: "push"
23805
24272
  },
23806
- runtimeState: NumericSensorStatusSchema
24273
+ runtimeState: NumericSensorStatusSchema,
24274
+ /**
24275
+ * Runtime-state durability: **restored** — polled value, low churn once the clock is excluded (251 of 669 writes were the clock alone); restoring it removes the cold window before the first poll.
24276
+ *
24277
+ * See `RuntimeStateDurability`. Enforced by
24278
+ * `scripts/check-runtime-state-durability.ts`.
24279
+ */
24280
+ durability: "restored",
24281
+ /** Clock fields: written, but excluded from the compare that decides
24282
+ * whether persisting is worth a SQLite commit. */
24283
+ volatileStateFields: ["lastFetchedAt"]
23807
24284
  };
23808
24285
  /**
23809
24286
  * Generic on-screen-display (video overlay) cap. Each camera exposes
@@ -24188,7 +24665,14 @@ var petFeederCapability = {
24188
24665
  * the full slice via `device.state.petFeeder.value` and refresh on
24189
24666
  * every poll without re-querying the provider.
24190
24667
  */
24191
- runtimeState: PetFeederStatusSchema
24668
+ runtimeState: PetFeederStatusSchema,
24669
+ /**
24670
+ * Runtime-state durability: **session** — live appliance state re-published on connect.
24671
+ *
24672
+ * See `RuntimeStateDurability`. Enforced by
24673
+ * `scripts/check-runtime-state-durability.ts`.
24674
+ */
24675
+ durability: "session"
24192
24676
  };
24193
24677
  var VehicleSchema = object({
24194
24678
  id: string$2(),
@@ -24500,7 +24984,17 @@ var powerMeterCapability = {
24500
24984
  schema: PowerMeterStatusSchema,
24501
24985
  kind: "push"
24502
24986
  },
24503
- runtimeState: PowerMeterStatusSchema
24987
+ runtimeState: PowerMeterStatusSchema,
24988
+ /**
24989
+ * Runtime-state durability: **restored** — as `numeric-sensor`; `kwhTotal` is an accumulator whose restored value is the baseline.
24990
+ *
24991
+ * See `RuntimeStateDurability`. Enforced by
24992
+ * `scripts/check-runtime-state-durability.ts`.
24993
+ */
24994
+ durability: "restored",
24995
+ /** Clock fields: written, but excluded from the compare that decides
24996
+ * whether persisting is worth a SQLite commit. */
24997
+ volatileStateFields: ["lastFetchedAt"]
24504
24998
  };
24505
24999
  /**
24506
25000
  * Presence cap. Models HA `person.*` and `device_tracker.*` entities
@@ -24557,7 +25051,17 @@ var presenceCapability = {
24557
25051
  * the map pin is rendered (use `DeviceFeature.PresenceGps` for the
24558
25052
  * pre-fetch fast-path check).
24559
25053
  */
24560
- runtimeState: PresenceStatusSchema
25054
+ runtimeState: PresenceStatusSchema,
25055
+ /**
25056
+ * Runtime-state durability: **restored** — occupancy-relevant: the restored state is what an occupancy rule compares the first post-restart observation against.
25057
+ *
25058
+ * See `RuntimeStateDurability`. Enforced by
25059
+ * `scripts/check-runtime-state-durability.ts`.
25060
+ */
25061
+ durability: "restored",
25062
+ /** Clock fields: written, but excluded from the compare that decides
25063
+ * whether persisting is worth a SQLite commit. */
25064
+ volatileStateFields: ["lastChangedAt"]
24561
25065
  };
24562
25066
  /**
24563
25067
  * Atmospheric pressure reading in hectopascals. Drives Home Assistant
@@ -24593,7 +25097,17 @@ var pressureSensorCapability = {
24593
25097
  schema: PressureSensorStatusSchema,
24594
25098
  kind: "push"
24595
25099
  },
24596
- runtimeState: PressureSensorStatusSchema
25100
+ runtimeState: PressureSensorStatusSchema,
25101
+ /**
25102
+ * Runtime-state durability: **restored** — as `numeric-sensor`.
25103
+ *
25104
+ * See `RuntimeStateDurability`. Enforced by
25105
+ * `scripts/check-runtime-state-durability.ts`.
25106
+ */
25107
+ durability: "restored",
25108
+ /** Clock fields: written, but excluded from the compare that decides
25109
+ * whether persisting is worth a SQLite commit. */
25110
+ volatileStateFields: ["lastFetchedAt"]
24597
25111
  };
24598
25112
  /**
24599
25113
  * PRIVACY — what the camera deliberately does not capture. Two planes:
@@ -24723,7 +25237,17 @@ var privacyMaskCapability = {
24723
25237
  schema: PrivacyMaskStatusSchema,
24724
25238
  kind: "poll"
24725
25239
  },
24726
- runtimeState: PrivacyMaskStatusSchema
25240
+ runtimeState: PrivacyMaskStatusSchema,
25241
+ /**
25242
+ * Runtime-state durability: **restored** — operator-drawn regions, zero real churn — 22 writes in 25 minutes, every one of them the clock.
25243
+ *
25244
+ * See `RuntimeStateDurability`. Enforced by
25245
+ * `scripts/check-runtime-state-durability.ts`.
25246
+ */
25247
+ durability: "restored",
25248
+ /** Clock fields: written, but excluded from the compare that decides
25249
+ * whether persisting is worth a SQLite commit. */
25250
+ volatileStateFields: ["lastFetchedAt"]
24727
25251
  };
24728
25252
  var PtzPresetSchema = object({
24729
25253
  id: string$2(),
@@ -24889,7 +25413,14 @@ var ptzAutotrackCapability = {
24889
25413
  * fetch / cache / fallback logic out of the four cap methods —
24890
25414
  * they become trampolines over `runtimeState`.
24891
25415
  */
24892
- runtimeState: PtzAutotrackRuntimeStateSchema
25416
+ runtimeState: PtzAutotrackRuntimeStateSchema,
25417
+ /**
25418
+ * Runtime-state durability: **session** — mirrors the camera's own autotrack config, re-read on connect.
25419
+ *
25420
+ * See `RuntimeStateDurability`. Enforced by
25421
+ * `scripts/check-runtime-state-durability.ts`.
25422
+ */
25423
+ durability: "session"
24893
25424
  };
24894
25425
  DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceId: number().int().nonnegative() }), object({ success: literal(true) }), {
24895
25426
  kind: "mutation",
@@ -25539,7 +26070,14 @@ var sceneMonitorCapability = {
25539
26070
  schema: SceneMonitorStatusSchema,
25540
26071
  kind: "push"
25541
26072
  },
25542
- runtimeState: SceneMonitorStatusSchema
26073
+ runtimeState: SceneMonitorStatusSchema,
26074
+ /**
26075
+ * Runtime-state durability: **session** — re-derived from the current scene on the next evaluation.
26076
+ *
26077
+ * See `RuntimeStateDurability`. Enforced by
26078
+ * `scripts/check-runtime-state-durability.ts`.
26079
+ */
26080
+ durability: "session"
25543
26081
  };
25544
26082
  /**
25545
26083
  * Per-stage gating mode applied to the zones a rule references.
@@ -25683,7 +26221,14 @@ var scriptRunnerCapability = {
25683
26221
  * `isRunning` to render a spinner during execution and surfaces
25684
26222
  * `lastError` / `lastRunSuccess` in the recent-runs panel.
25685
26223
  */
25686
- runtimeState: ScriptRunnerStatusSchema
26224
+ runtimeState: ScriptRunnerStatusSchema,
26225
+ /**
26226
+ * Runtime-state durability: **session** — a restored `isRunning: true` describes a process that died with the previous hub.
26227
+ *
26228
+ * See `RuntimeStateDurability`. Enforced by
26229
+ * `scripts/check-runtime-state-durability.ts`.
26230
+ */
26231
+ durability: "session"
25687
26232
  };
25688
26233
  /**
25689
26234
  * Smoke alarm sensor — boolean "is smoke currently detected" with
@@ -25710,7 +26255,17 @@ var smokeCapability = {
25710
26255
  schema: SmokeStatusSchema,
25711
26256
  kind: "push"
25712
26257
  },
25713
- runtimeState: SmokeStatusSchema
26258
+ runtimeState: SmokeStatusSchema,
26259
+ /**
26260
+ * Runtime-state durability: **restored** — a safety sensor must not read "clear" merely because the hub restarted.
26261
+ *
26262
+ * See `RuntimeStateDurability`. Enforced by
26263
+ * `scripts/check-runtime-state-durability.ts`.
26264
+ */
26265
+ durability: "restored",
26266
+ /** Clock fields: written, but excluded from the compare that decides
26267
+ * whether persisting is worth a SQLite commit. */
26268
+ volatileStateFields: ["lastChangedAt"]
25714
26269
  };
25715
26270
  /**
25716
26271
  * One publishable camera stream as its OWNING PROVIDER describes it — the same
@@ -25883,7 +26438,17 @@ var streamParamsCapability = {
25883
26438
  schema: StreamParamsStatusSchema,
25884
26439
  kind: "poll"
25885
26440
  },
25886
- runtimeState: StreamParamsStatusSchema
26441
+ runtimeState: StreamParamsStatusSchema,
26442
+ /**
26443
+ * Runtime-state durability: **restored** — operator-set encoder profile; mutation-driven.
26444
+ *
26445
+ * See `RuntimeStateDurability`. Enforced by
26446
+ * `scripts/check-runtime-state-durability.ts`.
26447
+ */
26448
+ durability: "restored",
26449
+ /** Clock fields: written, but excluded from the compare that decides
26450
+ * whether persisting is worth a SQLite commit. */
26451
+ volatileStateFields: ["lastFetchedAt"]
25887
26452
  };
25888
26453
  /**
25889
26454
  * Generic on/off switch cap for accessory children (siren, floodlight,
@@ -25929,6 +26494,16 @@ var switchCapability = {
25929
26494
  * not need to re-query the provider after a setState mutation.
25930
26495
  */
25931
26496
  runtimeState: SwitchStatusSchema,
26497
+ /**
26498
+ * Runtime-state durability: **restored** — device state an operator reads as authoritative; 55 devices, transition-driven.
26499
+ *
26500
+ * See `RuntimeStateDurability`. Enforced by
26501
+ * `scripts/check-runtime-state-durability.ts`.
26502
+ */
26503
+ durability: "restored",
26504
+ /** Clock fields: written, but excluded from the compare that decides
26505
+ * whether persisting is worth a SQLite commit. */
26506
+ volatileStateFields: ["lastChangedAt"],
25932
26507
  settings: { bindings: [{
25933
26508
  kind: "scalar",
25934
26509
  statusPath: "on",
@@ -26008,7 +26583,17 @@ var tamperCapability = {
26008
26583
  schema: TamperStatusSchema,
26009
26584
  kind: "push"
26010
26585
  },
26011
- runtimeState: TamperStatusSchema
26586
+ runtimeState: TamperStatusSchema,
26587
+ /**
26588
+ * Runtime-state durability: **restored** — as `smoke`.
26589
+ *
26590
+ * See `RuntimeStateDurability`. Enforced by
26591
+ * `scripts/check-runtime-state-durability.ts`.
26592
+ */
26593
+ durability: "restored",
26594
+ /** Clock fields: written, but excluded from the compare that decides
26595
+ * whether persisting is worth a SQLite commit. */
26596
+ volatileStateFields: ["lastChangedAt"]
26012
26597
  };
26013
26598
  /**
26014
26599
  * Single-metric temperature reading. Drives Home Assistant `sensor`
@@ -26053,7 +26638,17 @@ var temperatureSensorCapability = {
26053
26638
  schema: TemperatureSensorStatusSchema,
26054
26639
  kind: "push"
26055
26640
  },
26056
- runtimeState: TemperatureSensorStatusSchema
26641
+ runtimeState: TemperatureSensorStatusSchema,
26642
+ /**
26643
+ * Runtime-state durability: **restored** — as `numeric-sensor` (69 of 125 writes were the clock alone).
26644
+ *
26645
+ * See `RuntimeStateDurability`. Enforced by
26646
+ * `scripts/check-runtime-state-durability.ts`.
26647
+ */
26648
+ durability: "restored",
26649
+ /** Clock fields: written, but excluded from the compare that decides
26650
+ * whether persisting is worth a SQLite commit. */
26651
+ volatileStateFields: ["lastFetchedAt"]
26057
26652
  };
26058
26653
  /**
26059
26654
  * toast — system-scoped singleton capability that streams toast
@@ -26122,7 +26717,14 @@ var updateCapability = {
26122
26717
  schema: UpdateStatusSchema,
26123
26718
  kind: "poll"
26124
26719
  },
26125
- runtimeState: UpdateStatusSchema
26720
+ runtimeState: UpdateStatusSchema,
26721
+ /**
26722
+ * Runtime-state durability: **session** — a restored `inProgress: true` describes an update that is no longer running; versions are re-probed at boot.
26723
+ *
26724
+ * See `RuntimeStateDurability`. Enforced by
26725
+ * `scripts/check-runtime-state-durability.ts`.
26726
+ */
26727
+ durability: "session"
26126
26728
  };
26127
26729
  var UserSummarySchema = object({
26128
26730
  id: string$2(),
@@ -26456,7 +27058,14 @@ var vacuumControlCapability = {
26456
27058
  * Runtime-state slice — mirrored by the kernel. UI controls watch the
26457
27059
  * slice for live state + battery + fan-speed changes.
26458
27060
  */
26459
- runtimeState: VacuumControlStatusSchema
27061
+ runtimeState: VacuumControlStatusSchema,
27062
+ /**
27063
+ * Runtime-state durability: **session** — as `media-player` — a restored `state: cleaning` is a robot that is not cleaning.
27064
+ *
27065
+ * See `RuntimeStateDurability`. Enforced by
27066
+ * `scripts/check-runtime-state-durability.ts`.
27067
+ */
27068
+ durability: "session"
26460
27069
  };
26461
27070
  var ValveStatusSchema = object({
26462
27071
  /** Lifecycle state of the valve. */
@@ -26508,7 +27117,14 @@ var valveCapability = {
26508
27117
  * Runtime-state slice — mirrored by the kernel. UI controls watch the
26509
27118
  * slice for live position changes during a move.
26510
27119
  */
26511
- runtimeState: ValveStatusSchema
27120
+ runtimeState: ValveStatusSchema,
27121
+ /**
27122
+ * Runtime-state durability: **session** — as `brightness`.
27123
+ *
27124
+ * See `RuntimeStateDurability`. Enforced by
27125
+ * `scripts/check-runtime-state-durability.ts`.
27126
+ */
27127
+ durability: "session"
26512
27128
  };
26513
27129
  /**
26514
27130
  * Vibration / shake / impact sensor. Drives Home Assistant
@@ -26530,7 +27146,17 @@ var vibrationCapability = {
26530
27146
  schema: VibrationStatusSchema,
26531
27147
  kind: "push"
26532
27148
  },
26533
- runtimeState: VibrationStatusSchema
27149
+ runtimeState: VibrationStatusSchema,
27150
+ /**
27151
+ * Runtime-state durability: **restored** — as `smoke`.
27152
+ *
27153
+ * See `RuntimeStateDurability`. Enforced by
27154
+ * `scripts/check-runtime-state-durability.ts`.
27155
+ */
27156
+ durability: "restored",
27157
+ /** Clock fields: written, but excluded from the compare that decides
27158
+ * whether persisting is worth a SQLite commit. */
27159
+ volatileStateFields: ["lastChangedAt"]
26534
27160
  };
26535
27161
  /**
26536
27162
  * Water heater / boiler cap. Models HA `water_heater.*` entities — a
@@ -26604,7 +27230,14 @@ var waterHeaterCapability = {
26604
27230
  * Runtime-state slice — mirrored by the kernel. UI controls watch the
26605
27231
  * slice for live temperature / mode / away changes.
26606
27232
  */
26607
- runtimeState: WaterHeaterStatusSchema
27233
+ runtimeState: WaterHeaterStatusSchema,
27234
+ /**
27235
+ * Runtime-state durability: **session** — as `climate-control`.
27236
+ *
27237
+ * See `RuntimeStateDurability`. Enforced by
27238
+ * `scripts/check-runtime-state-durability.ts`.
27239
+ */
27240
+ durability: "session"
26608
27241
  };
26609
27242
  /**
26610
27243
  * Weather provider cap. Models HA `weather.*` entities — a read-only
@@ -26663,7 +27296,14 @@ var weatherCapability = {
26663
27296
  * Runtime-state slice — mirrored by the kernel. The UI reads the
26664
27297
  * current conditions directly from the slice on each weather push.
26665
27298
  */
26666
- runtimeState: WeatherStatusSchema
27299
+ runtimeState: WeatherStatusSchema,
27300
+ /**
27301
+ * Runtime-state durability: **session** — a forecast is stale the moment the hub is down; the provider re-fetches on connect.
27302
+ *
27303
+ * See `RuntimeStateDurability`. Enforced by
27304
+ * `scripts/check-runtime-state-durability.ts`.
27305
+ */
27306
+ durability: "session"
26667
27307
  };
26668
27308
  /**
26669
27309
  * Per-zone occupancy aggregation produced by the analytics frame
@@ -26825,7 +27465,14 @@ var zoneAnalyticsCapability = {
26825
27465
  * automatically; the explicit `getCurrentSnapshot` cap method is
26826
27466
  * still useful for one-off polls without a subscription.
26827
27467
  */
26828
- runtimeState: CameraOccupancySnapshotSchema
27468
+ runtimeState: CameraOccupancySnapshotSchema,
27469
+ /**
27470
+ * Runtime-state durability: **session** — per-frame analytics; with `audio-metrics` it is ~90 % of the offered write rate. Re-derived on the next frame.
27471
+ *
27472
+ * See `RuntimeStateDurability`. Enforced by
27473
+ * `scripts/check-runtime-state-durability.ts`.
27474
+ */
27475
+ durability: "session"
26829
27476
  };
26830
27477
  /**
26831
27478
  * Stages a {@link ZoneRule} can apply to. Discriminator on the rules
@@ -26903,7 +27550,14 @@ var zoneRulesCapability = {
26903
27550
  motion: array(ZoneRuleSchema).readonly(),
26904
27551
  detection: array(ZoneRuleSchema).readonly(),
26905
27552
  package: array(ZoneRuleSchema).readonly()
26906
- })
27553
+ }),
27554
+ /**
27555
+ * Runtime-state durability: **restored** — operator intent, mutation-only, same argument as `zones`.
27556
+ *
27557
+ * See `RuntimeStateDurability`. Enforced by
27558
+ * `scripts/check-runtime-state-durability.ts`.
27559
+ */
27560
+ durability: "restored"
26907
27561
  };
26908
27562
  /**
26909
27563
  * Accessory device helpers — shared across drivers.
@@ -33590,6 +34244,7 @@ Object.freeze({
33590
34244
  "network-access": "ingress",
33591
34245
  "smtp-provider": "email"
33592
34246
  });
34247
+ new Map(AUDIO_MACRO_LABELS.flatMap((macro) => macro.icon === void 0 ? [] : [[macro.id, macro.icon]]));
33593
34248
  new Set(["devices", "classes"]);
33594
34249
  /**
33595
34250
  * TimelapseRule — the STANDALONE scheduled timelapse producer's rule model.