camstack 1.2.23 → 1.2.25

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.
@@ -14522,7 +14522,7 @@ function date4(params) {
14522
14522
  // ../../node_modules/zod/v4/classic/external.js
14523
14523
  config(en_default());
14524
14524
 
14525
- // ../types/dist/sleep-BxjBLp3L.mjs
14525
+ // ../types/dist/sleep-CSgK0rNX.mjs
14526
14526
  var WELL_KNOWN_TABS = [
14527
14527
  {
14528
14528
  id: "overview",
@@ -18749,7 +18749,14 @@ var cameraStreamsCapability = {
18749
18749
  low: external_exports.string().optional()
18750
18750
  }),
18751
18751
  lastChangedAt: external_exports.number()
18752
- })
18752
+ }),
18753
+ /**
18754
+ * 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.
18755
+ *
18756
+ * See `RuntimeStateDurability`. Enforced by
18757
+ * `scripts/check-runtime-state-durability.ts`.
18758
+ */
18759
+ durability: "session"
18753
18760
  };
18754
18761
  var CoreBlockPlacementSchema = external_exports.union([external_exports.literal("hub"), external_exports.string().min(1)]);
18755
18762
  var CoreBlockStatusSchema = external_exports.enum([
@@ -19323,6 +19330,13 @@ var deviceDiscoveryCapability = {
19323
19330
  kind: "poll"
19324
19331
  },
19325
19332
  runtimeState: DeviceDiscoveryStatusSchema.extend({ lastFetchedAt: external_exports.number().int().nonnegative() }),
19333
+ /**
19334
+ * Runtime-state durability: **session** — 5.7 KB of scan output on the largest device, fully re-derivable by re-scanning.
19335
+ *
19336
+ * See `RuntimeStateDurability`. Enforced by
19337
+ * `scripts/check-runtime-state-durability.ts`.
19338
+ */
19339
+ durability: "session",
19326
19340
  methods: {
19327
19341
  /**
19328
19342
  * Snapshot of the current `discovered` list. Returns the
@@ -21527,6 +21541,7 @@ var NotificationActionIconSchema = external_exports.enum([
21527
21541
  "acknowledge",
21528
21542
  "dismiss",
21529
21543
  "silence",
21544
+ "snooze",
21530
21545
  "view",
21531
21546
  "play",
21532
21547
  "open",
@@ -21534,9 +21549,13 @@ var NotificationActionIconSchema = external_exports.enum([
21534
21549
  "lock",
21535
21550
  "unlock",
21536
21551
  "arm",
21552
+ "arm-home",
21553
+ "arm-away",
21554
+ "arm-night",
21537
21555
  "disarm",
21538
21556
  "light",
21539
- "alert"
21557
+ "alert",
21558
+ "camera"
21540
21559
  ]);
21541
21560
  var NotificationActionSchema = external_exports.object({
21542
21561
  id: external_exports.string(),
@@ -21551,7 +21570,23 @@ var NotificationActionSchema = external_exports.object({
21551
21570
  * else — see `notification-center/action-token.ts` for what that does and
21552
21571
  * does not buy.
21553
21572
  */
21554
- destructive: external_exports.boolean().optional()
21573
+ destructive: external_exports.boolean().optional(),
21574
+ /**
21575
+ * How the tap should REACH the url.
21576
+ *
21577
+ * `navigate` (absent, and every button authored before this field) opens it:
21578
+ * the phone leaves the notification and shows whatever the callback returns.
21579
+ * That is right for a button whose answer the operator wants to read.
21580
+ *
21581
+ * `background` fires it as a POST and stays put. It exists for the buttons
21582
+ * whose whole point is not to interrupt — "silence this for 30 minutes" is
21583
+ * an answer to the notification, and being thrown into a browser tab to
21584
+ * confirm it costs more attention than the notification did. A backend that
21585
+ * cannot do a background call renders it as an ordinary link (the adapters
21586
+ * fall back rather than dropping the button), so this is a preference, never
21587
+ * a requirement.
21588
+ */
21589
+ mode: external_exports.enum(["navigate", "background"]).optional()
21555
21590
  });
21556
21591
  var NotificationSchema = external_exports.object({
21557
21592
  body: external_exports.string(),
@@ -21709,6 +21744,25 @@ var notificationOutputCapability = {
21709
21744
  }), external_exports.void(), { kind: "mutation" })
21710
21745
  }
21711
21746
  };
21747
+ var MACRO_LABELS = [
21748
+ {
21749
+ id: "person",
21750
+ name: "Person"
21751
+ },
21752
+ {
21753
+ id: "vehicle",
21754
+ name: "Vehicle"
21755
+ },
21756
+ {
21757
+ id: "animal",
21758
+ name: "Animal"
21759
+ },
21760
+ {
21761
+ id: "package",
21762
+ name: "Package"
21763
+ }
21764
+ ];
21765
+ var DETECTION_MACRO_CLASSES = new Set(MACRO_LABELS.map((l) => l.id));
21712
21766
  var COCO_TO_MACRO = {
21713
21767
  mapping: {
21714
21768
  person: "person",
@@ -22329,7 +22383,17 @@ var alarmPanelCapability = {
22329
22383
  * full slice; renders an arm button per `availableModes` entry and
22330
22384
  * a PIN field iff `requiresCode === true`.
22331
22385
  */
22332
- runtimeState: AlarmPanelStatusSchema
22386
+ runtimeState: AlarmPanelStatusSchema,
22387
+ /**
22388
+ * Runtime-state durability: **restored** — armed state is the one thing a panel must not lose across a restart.
22389
+ *
22390
+ * See `RuntimeStateDurability`. Enforced by
22391
+ * `scripts/check-runtime-state-durability.ts`.
22392
+ */
22393
+ durability: "restored",
22394
+ /** Clock fields: written, but excluded from the compare that decides
22395
+ * whether persisting is worth a SQLite commit. */
22396
+ volatileStateFields: ["lastChangedAt"]
22333
22397
  };
22334
22398
  var MaskPointSchema = external_exports.object({
22335
22399
  x: external_exports.number(),
@@ -22397,6 +22461,8 @@ var NcSystemEventKindSchema = external_exports.enum([
22397
22461
  "alarm-triggered",
22398
22462
  "alarm-armed",
22399
22463
  "alarm-disarmed",
22464
+ "alarm-arming",
22465
+ "alarm-arm-refused",
22400
22466
  "camera-online",
22401
22467
  "camera-offline",
22402
22468
  "camera-disabled",
@@ -22427,6 +22493,7 @@ var NcSystemEventConditionSchema = external_exports.object({
22427
22493
  nodeIds: external_exports.array(external_exports.string().min(1)).min(1).optional(),
22428
22494
  packageNames: external_exports.array(external_exports.string().min(1)).min(1).optional()
22429
22495
  });
22496
+ var NC_SNOOZE_MAX_MINUTES = 1440;
22430
22497
  var NcScheduleWindowSchema = external_exports.object({
22431
22498
  /** Days of week the window STARTS on (0 = Sunday … 6 = Saturday). */
22432
22499
  days: external_exports.array(external_exports.number().int().min(0).max(6)).min(1),
@@ -22683,15 +22750,15 @@ var NcConditionsSchema = external_exports.object({
22683
22750
  * (an `immediate` rule naming an `audio-*` class, one notification per
22684
22751
  * classified sample) stays exactly as it was for rules that already use it.
22685
22752
  *
22686
- * NOT in {@link NC_CONDITION_CATALOG} yet, and that is the sequencing rule
22687
- * rather than an oversight: the viewer mirrors the descriptor enums BY HAND
22688
- * (`camstack/src/data/notification-center.ts`, guarded by
22689
- * `scripts/check-viewer-condition-mirror.ts`) and its rule editor STRIPS the
22753
+ * In {@link NC_CONDITION_CATALOG} since P2, and the ORDER it got there is the
22754
+ * rule rather than an accident: the viewer mirrors the descriptor enums BY
22755
+ * HAND (`camstack/src/data/notification-center.ts`, guarded by
22756
+ * `scripts/check-viewer-condition-mirror.ts`) and its rule editor strips the
22690
22757
  * condition fields it does not know when a rule is saved from the phone.
22691
22758
  * Publishing an editor for a condition the app cannot round-trip is how an
22692
- * operator loses a rule's conditions by opening it — so the descriptor, the
22693
- * admin widget and the viewer mirror land together (P2 + P3), and only then
22694
- * does an audio rule become authorable.
22759
+ * operator loses a rule's conditions by opening it — so the viewer mirror
22760
+ * (P3, shipped) went FIRST, and the descriptor an editor renders from
22761
+ * follows here.
22695
22762
  */
22696
22763
  audio: NcAudioConditionSchema.optional()
22697
22764
  });
@@ -22860,6 +22927,30 @@ var NcRuleInputSchema = external_exports.object({
22860
22927
  */
22861
22928
  snoozeAllowGlobal: external_exports.boolean().optional(),
22862
22929
  /**
22930
+ * The snooze durations THIS rule's notification offers as buttons, in
22931
+ * minutes.
22932
+ *
22933
+ * Three states, and all three are distinct — which is exactly why this is
22934
+ * `.optional()` and never `.default()`. A Zod default does not run on the
22935
+ * addon cap path (three production failures in one day), so a schema default
22936
+ * would collapse the first two:
22937
+ *
22938
+ * | value | meaning |
22939
+ * | --- | --- |
22940
+ * | absent | the operator never said ⇒ {@link NC_DEFAULT_SNOOZE_MINUTES} |
22941
+ * | `[]` | **no snooze buttons on this rule** — the explicit override |
22942
+ * | a list | these choices, de-duplicated and sorted, at most four |
22943
+ *
22944
+ * `.max(4)` because the notifier's own action budget is small (ntfy allows
22945
+ * three buttons in total) and a rule that spent it all on snooze choices
22946
+ * would push its own tap-through actions off the notification.
22947
+ *
22948
+ * An empty list is NOT an alarm exemption: a rule the alarm is about, or
22949
+ * that arms the panel, is exempt automatically and cannot be silenced by a
22950
+ * window from anywhere (D133).
22951
+ */
22952
+ snoozeOptions: external_exports.array(external_exports.number().int().min(1).max(NC_SNOOZE_MAX_MINUTES)).max(4).optional(),
22953
+ /**
22863
22954
  * Devices this rule ACTUATES — arm the alarm, open a gate, turn on a light.
22864
22955
  *
22865
22956
  * This is what makes the rule set the alarm's trigger set without the alarm
@@ -22949,6 +23040,7 @@ var NcConditionDescriptorSchema = external_exports.object({
22949
23040
  "device",
22950
23041
  "package",
22951
23042
  "occupancy",
23043
+ "audio",
22952
23044
  "system"
22953
23045
  ]),
22954
23046
  label: external_exports.string(),
@@ -22967,6 +23059,7 @@ var NcConditionDescriptorSchema = external_exports.object({
22967
23059
  "crossingSelect",
22968
23060
  "polygonDraw",
22969
23061
  "occupancy",
23062
+ "audio",
22970
23063
  "deviceState",
22971
23064
  "systemEvent"
22972
23065
  ]),
@@ -23070,7 +23163,6 @@ var NcSnoozeScopeSchema = external_exports.enum([
23070
23163
  "device",
23071
23164
  "all"
23072
23165
  ]);
23073
- var NC_SNOOZE_MAX_MINUTES = 1440;
23074
23166
  var NcSnoozeInputSchema = external_exports.object({
23075
23167
  scope: NcSnoozeScopeSchema,
23076
23168
  /** Required when `scope: 'rule'` — a scoped snooze with no id matches
@@ -23078,6 +23170,19 @@ var NcSnoozeInputSchema = external_exports.object({
23078
23170
  ruleId: external_exports.string().optional(),
23079
23171
  /** Required when `scope: 'device'`. */
23080
23172
  deviceId: external_exports.number().int().optional(),
23173
+ /**
23174
+ * Narrow the window to these subject classes — "the cat, not the person".
23175
+ *
23176
+ * ORTHOGONAL to `scope`, deliberately, and absent means EVERY class: that is
23177
+ * what every window authored before this field meant, so no persisted row
23178
+ * changes meaning and no client has to learn anything to keep working.
23179
+ *
23180
+ * It is what makes the window's real key `(deviceId, classes[])` and lets it
23181
+ * cross rules (D133): the operator points at a camera and a kind of thing,
23182
+ * not at whichever of their four rules happened to produce the notification
23183
+ * they are dismissing.
23184
+ */
23185
+ classes: external_exports.array(external_exports.string().min(1)).min(1).optional(),
23081
23186
  durationMinutes: external_exports.number().int().min(1).max(NC_SNOOZE_MAX_MINUTES),
23082
23187
  /**
23083
23188
  * Silence this for EVERY recipient, not just the caller. Permission is
@@ -23102,6 +23207,10 @@ var NcSnoozeSchema = external_exports.object({
23102
23207
  scope: NcSnoozeScopeSchema,
23103
23208
  ruleId: external_exports.string().optional(),
23104
23209
  deviceId: external_exports.number().int().optional(),
23210
+ /** Subject classes this window covers. ABSENT = every class — see
23211
+ * {@link NcSnoozeInputSchema.shape.classes}. Lives in the JSON blob and has
23212
+ * no SQLite column: nothing queries a window by class. */
23213
+ classes: external_exports.array(external_exports.string().min(1)).min(1).optional(),
23105
23214
  startedAt: external_exports.number(),
23106
23215
  /** Exclusive: at exactly this instant the snooze is over. Expiry is a
23107
23216
  * COMPARISON, not a job — no sweeper can leave the operator silenced. */
@@ -25374,7 +25483,14 @@ var zonesCapability = {
25374
25483
  * handle. Slice shape is `{ zones: Zone[] }` so future extensions
25375
25484
  * (e.g. zone groupings) can sit alongside the polygon list.
25376
25485
  */
25377
- runtimeState: external_exports.object({ zones: external_exports.array(ZoneSchema).readonly() })
25486
+ runtimeState: external_exports.object({ zones: external_exports.array(ZoneSchema).readonly() }),
25487
+ /**
25488
+ * 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.
25489
+ *
25490
+ * See `RuntimeStateDurability`. Enforced by
25491
+ * `scripts/check-runtime-state-durability.ts`.
25492
+ */
25493
+ durability: "restored"
25378
25494
  };
25379
25495
  var NativeCropBboxSchema = external_exports.object({
25380
25496
  x: external_exports.number(),
@@ -25638,15 +25754,21 @@ var RunnerCameraConfigSchema = external_exports.object({
25638
25754
  */
25639
25755
  onboardMotionDrivesAnalyzer: external_exports.boolean().default(true),
25640
25756
  /**
25641
- * Master toggle for the occupancy re-check. When `false` (DEFAULT) the runner
25642
- * never arms the periodic recheck timer, regardless of `occupancyRecheckSec`
25643
- * this is off by default because the recheck re-subscribes a detection session
25644
- * every N seconds while `watching`, a major source of pull-decoder re-dial
25645
- * churn (each cycle creates+tears a session → RTSP re-dial → latency). The
25757
+ * Master toggle for the occupancy re-check. When `false` the runner never arms
25758
+ * the periodic recheck timer, regardless of `occupancyRecheckSec`; the
25646
25759
  * `occupancyRecheckSec` / `occupancyRecheckFrames` sliders only take effect
25647
25760
  * (and only render) when this is enabled.
25648
- */
25649
- occupancyRecheckEnabled: external_exports.boolean().default(false),
25761
+ *
25762
+ * DEFAULT `true` since 2026-08-13 (was `false`). It was off because the
25763
+ * recheck re-subscribes a detection session every N seconds while `watching`
25764
+ * — each cycle creates+tears a session ⇒ an RTSP re-dial ⇒ latency, a major
25765
+ * pull-decoder churn source. What that bought was a blind spot: a STATIONARY
25766
+ * object is counted only while the stationary registry holds it, and the
25767
+ * registry rebuilds from motion, so after a restart a parked car was invisible
25768
+ * to every occupancy rule until something moved in front of it. The churn is
25769
+ * now paid on the interval instead — see `occupancyRecheckSecField`.
25770
+ */
25771
+ occupancyRecheckEnabled: external_exports.boolean().default(true),
25650
25772
  occupancyRecheckSec: external_exports.number().min(occupancyRecheckSecField.min).max(occupancyRecheckSecField.max).default(occupancyRecheckSecField.default),
25651
25773
  occupancyRecheckFrames: external_exports.number().min(occupancyRecheckFramesField.min).max(occupancyRecheckFramesField.max).default(occupancyRecheckFramesField.default),
25652
25774
  /**
@@ -25764,8 +25886,8 @@ var RunnerCameraDeviceUIFields = [
25764
25886
  type: "boolean",
25765
25887
  style: "checkbox",
25766
25888
  label: "Occupancy re-check",
25767
- description: "Periodically re-sample a few frames during the watching phase to confirm the scene is truly empty (catches stationary objects motion-gating would miss). Off by default \u2014 it adds decoder re-dial churn.",
25768
- default: false
25889
+ description: "Periodically re-sample a few frames during the watching phase, so objects that are simply parked are still counted (motion gating alone loses them after a restart). On by default at a wide interval; turn it off on cameras where the extra decoder re-dial is expensive.",
25890
+ default: true
25769
25891
  },
25770
25892
  {
25771
25893
  key: "occupancyRecheckSec",
@@ -28802,7 +28924,17 @@ var airQualitySensorCapability = {
28802
28924
  schema: AirQualitySensorStatusSchema,
28803
28925
  kind: "push"
28804
28926
  },
28805
- runtimeState: AirQualitySensorStatusSchema
28927
+ runtimeState: AirQualitySensorStatusSchema,
28928
+ /**
28929
+ * Runtime-state durability: **restored** — as `numeric-sensor`.
28930
+ *
28931
+ * See `RuntimeStateDurability`. Enforced by
28932
+ * `scripts/check-runtime-state-durability.ts`.
28933
+ */
28934
+ durability: "restored",
28935
+ /** Clock fields: written, but excluded from the compare that decides
28936
+ * whether persisting is worth a SQLite commit. */
28937
+ volatileStateFields: ["lastFetchedAt"]
28806
28938
  };
28807
28939
  var AmbientLightSensorStatusSchema = external_exports.object({
28808
28940
  /** Current illuminance in lux (lx). */
@@ -28830,7 +28962,17 @@ var ambientLightSensorCapability = {
28830
28962
  schema: AmbientLightSensorStatusSchema,
28831
28963
  kind: "push"
28832
28964
  },
28833
- runtimeState: AmbientLightSensorStatusSchema
28965
+ runtimeState: AmbientLightSensorStatusSchema,
28966
+ /**
28967
+ * Runtime-state durability: **restored** — as `numeric-sensor`.
28968
+ *
28969
+ * See `RuntimeStateDurability`. Enforced by
28970
+ * `scripts/check-runtime-state-durability.ts`.
28971
+ */
28972
+ durability: "restored",
28973
+ /** Clock fields: written, but excluded from the compare that decides
28974
+ * whether persisting is worth a SQLite commit. */
28975
+ volatileStateFields: ["lastFetchedAt"]
28834
28976
  };
28835
28977
  var AudioClassSummarySchema = external_exports.object({
28836
28978
  className: external_exports.string(),
@@ -28920,7 +29062,14 @@ var audioMetricsCapability = {
28920
29062
  }), AudioMetricsHistorySchema)
28921
29063
  },
28922
29064
  /** Reactive runtime-state mirror — live `device.state.audioMetrics.value`. */
28923
- runtimeState: AudioMetricsSnapshotSchema
29065
+ runtimeState: AudioMetricsSnapshotSchema,
29066
+ /**
29067
+ * 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.
29068
+ *
29069
+ * See `RuntimeStateDurability`. Enforced by
29070
+ * `scripts/check-runtime-state-durability.ts`.
29071
+ */
29072
+ durability: "session"
28924
29073
  };
28925
29074
  var AutomationControlStatusSchema = external_exports.object({
28926
29075
  /** Whether the automation is currently enabled. Disabled automations
@@ -28971,7 +29120,14 @@ var automationControlCapability = {
28971
29120
  * reads `enabled` (toggle) + `isRunning` (spinner) + `lastError`
28972
29121
  * (badge) directly.
28973
29122
  */
28974
- runtimeState: AutomationControlStatusSchema
29123
+ runtimeState: AutomationControlStatusSchema,
29124
+ /**
29125
+ * 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.
29126
+ *
29127
+ * See `RuntimeStateDurability`. Enforced by
29128
+ * `scripts/check-runtime-state-durability.ts`.
29129
+ */
29130
+ durability: "session"
28975
29131
  };
28976
29132
  var BatteryStatusSchema = external_exports.object({
28977
29133
  /** 0..100 inclusive. Firmware-reported. */
@@ -29072,7 +29228,17 @@ var batteryCapability = {
29072
29228
  * via `device.runtimeState.getCapState('battery')` regardless of
29073
29229
  * the underlying driver.
29074
29230
  */
29075
- runtimeState: BatteryStatusSchema
29231
+ runtimeState: BatteryStatusSchema,
29232
+ /**
29233
+ * 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.
29234
+ *
29235
+ * See `RuntimeStateDurability`. Enforced by
29236
+ * `scripts/check-runtime-state-durability.ts`.
29237
+ */
29238
+ durability: "restored",
29239
+ /** Clock fields: written, but excluded from the compare that decides
29240
+ * whether persisting is worth a SQLite commit. */
29241
+ volatileStateFields: ["lastUpdated"]
29076
29242
  };
29077
29243
  var BinaryStatusSchema = external_exports.object({
29078
29244
  on: external_exports.boolean(),
@@ -29090,7 +29256,17 @@ var binaryCapability = {
29090
29256
  schema: BinaryStatusSchema,
29091
29257
  kind: "push"
29092
29258
  },
29093
- runtimeState: BinaryStatusSchema
29259
+ runtimeState: BinaryStatusSchema,
29260
+ /**
29261
+ * Runtime-state durability: **restored** — transition-driven sensor state; the restored value gives the boot comparison.
29262
+ *
29263
+ * See `RuntimeStateDurability`. Enforced by
29264
+ * `scripts/check-runtime-state-durability.ts`.
29265
+ */
29266
+ durability: "restored",
29267
+ /** Clock fields: written, but excluded from the compare that decides
29268
+ * whether persisting is worth a SQLite commit. */
29269
+ volatileStateFields: ["lastChangedAt"]
29094
29270
  };
29095
29271
  var BrightnessStatusSchema = external_exports.object({
29096
29272
  /** Current level as 0..100 inclusive. Firmware-reported. */
@@ -29132,7 +29308,14 @@ var brightnessCapability = {
29132
29308
  * by the kernel. Read via `device.state.brightness.value` so UI
29133
29309
  * sliders surface the current level without polling the provider.
29134
29310
  */
29135
- runtimeState: BrightnessStatusSchema
29311
+ runtimeState: BrightnessStatusSchema,
29312
+ /**
29313
+ * Runtime-state durability: **session** — live lamp state, re-published by the provider on connect.
29314
+ *
29315
+ * See `RuntimeStateDurability`. Enforced by
29316
+ * `scripts/check-runtime-state-durability.ts`.
29317
+ */
29318
+ durability: "session"
29136
29319
  };
29137
29320
  var buttonCapability = {
29138
29321
  name: "button",
@@ -29212,7 +29395,17 @@ var carbonMonoxideCapability = {
29212
29395
  schema: CarbonMonoxideStatusSchema,
29213
29396
  kind: "push"
29214
29397
  },
29215
- runtimeState: CarbonMonoxideStatusSchema
29398
+ runtimeState: CarbonMonoxideStatusSchema,
29399
+ /**
29400
+ * Runtime-state durability: **restored** — as `smoke`.
29401
+ *
29402
+ * See `RuntimeStateDurability`. Enforced by
29403
+ * `scripts/check-runtime-state-durability.ts`.
29404
+ */
29405
+ durability: "restored",
29406
+ /** Clock fields: written, but excluded from the compare that decides
29407
+ * whether persisting is worth a SQLite commit. */
29408
+ volatileStateFields: ["lastChangedAt"]
29216
29409
  };
29217
29410
  var HvacModeSchema = external_exports.enum([
29218
29411
  "off",
@@ -29341,7 +29534,14 @@ var climateControlCapability = {
29341
29534
  * the full slice via `device.state.climate-control.value` and refresh
29342
29535
  * on every push without re-querying the provider.
29343
29536
  */
29344
- runtimeState: ClimateControlStatusSchema
29537
+ runtimeState: ClimateControlStatusSchema,
29538
+ /**
29539
+ * Runtime-state durability: **session** — as `brightness`; `currentTemp` moves continuously and is re-published on connect.
29540
+ *
29541
+ * See `RuntimeStateDurability`. Enforced by
29542
+ * `scripts/check-runtime-state-durability.ts`.
29543
+ */
29544
+ durability: "session"
29345
29545
  };
29346
29546
  var RgbTripletSchema = external_exports.object({
29347
29547
  r: external_exports.number().int().min(0).max(255),
@@ -29428,7 +29628,14 @@ var colorCapability = {
29428
29628
  * kernel. Read via `device.state.color.value` so UI pickers surface
29429
29629
  * the current chromaticity without polling the provider.
29430
29630
  */
29431
- runtimeState: ColorStatusSchema
29631
+ runtimeState: ColorStatusSchema,
29632
+ /**
29633
+ * Runtime-state durability: **session** — as `brightness`.
29634
+ *
29635
+ * See `RuntimeStateDurability`. Enforced by
29636
+ * `scripts/check-runtime-state-durability.ts`.
29637
+ */
29638
+ durability: "session"
29432
29639
  };
29433
29640
  var ConnectionTestOutcomeSchema = external_exports.discriminatedUnion("outcome", [
29434
29641
  external_exports.object({
@@ -29482,7 +29689,17 @@ var connectivityCapability = {
29482
29689
  schema: ConnectivityStatusSchema,
29483
29690
  kind: "push"
29484
29691
  },
29485
- runtimeState: ConnectivityStatusSchema
29692
+ runtimeState: ConnectivityStatusSchema,
29693
+ /**
29694
+ * Runtime-state durability: **restored** — same shape and same argument as `device-status`, for links rather than devices.
29695
+ *
29696
+ * See `RuntimeStateDurability`. Enforced by
29697
+ * `scripts/check-runtime-state-durability.ts`.
29698
+ */
29699
+ durability: "restored",
29700
+ /** Clock fields: written, but excluded from the compare that decides
29701
+ * whether persisting is worth a SQLite commit. */
29702
+ volatileStateFields: ["lastChangedAt"]
29486
29703
  };
29487
29704
  var ConsumableItemSchema = external_exports.object({
29488
29705
  /** Stable id, e.g. 'main-brush'. */
@@ -29549,7 +29766,14 @@ var consumablesCapability = {
29549
29766
  }
29550
29767
  }
29551
29768
  },
29552
- runtimeState: ConsumablesStatusSchema.extend({ lastFetchedAt: external_exports.number() })
29769
+ runtimeState: ConsumablesStatusSchema.extend({ lastFetchedAt: external_exports.number() }),
29770
+ /**
29771
+ * Runtime-state durability: **session** — the authority is the appliance; the provider re-reads the whole item array on connect.
29772
+ *
29773
+ * See `RuntimeStateDurability`. Enforced by
29774
+ * `scripts/check-runtime-state-durability.ts`.
29775
+ */
29776
+ durability: "session"
29553
29777
  };
29554
29778
  var ContactStatusSchema = external_exports.object({
29555
29779
  /** True when the entry is open; false when closed. */
@@ -29568,7 +29792,17 @@ var contactCapability = {
29568
29792
  schema: ContactStatusSchema,
29569
29793
  kind: "push"
29570
29794
  },
29571
- runtimeState: ContactStatusSchema
29795
+ runtimeState: ContactStatusSchema,
29796
+ /**
29797
+ * Runtime-state durability: **restored** — a door left open across a restart must still read open.
29798
+ *
29799
+ * See `RuntimeStateDurability`. Enforced by
29800
+ * `scripts/check-runtime-state-durability.ts`.
29801
+ */
29802
+ durability: "restored",
29803
+ /** Clock fields: written, but excluded from the compare that decides
29804
+ * whether persisting is worth a SQLite commit. */
29805
+ volatileStateFields: ["lastChangedAt"]
29572
29806
  };
29573
29807
  var ControlKindSchema = external_exports.enum([
29574
29808
  "numeric",
@@ -29655,7 +29889,14 @@ var controlCapability = {
29655
29889
  * dropdown / text field / date picker) read the slice's discriminant
29656
29890
  * and value directly without polling the provider.
29657
29891
  */
29658
- runtimeState: ControlStatusSchema
29892
+ runtimeState: ControlStatusSchema,
29893
+ /**
29894
+ * Runtime-state durability: **session** — a generic control mirrors an external entity that re-publishes on connect; the options array is re-derived with it.
29895
+ *
29896
+ * See `RuntimeStateDurability`. Enforced by
29897
+ * `scripts/check-runtime-state-durability.ts`.
29898
+ */
29899
+ durability: "session"
29659
29900
  };
29660
29901
  var CoverStateSchema = external_exports.enum([
29661
29902
  "open",
@@ -29717,7 +29958,17 @@ var coverCapability = {
29717
29958
  * Runtime-state slice — mirrored by the kernel. UI controls watch
29718
29959
  * the slice for live position changes during a move.
29719
29960
  */
29720
- runtimeState: CoverStatusSchema
29961
+ runtimeState: CoverStatusSchema,
29962
+ /**
29963
+ * Runtime-state durability: **restored** — position survives a restart on the device; the mirror should agree at boot rather than read blank.
29964
+ *
29965
+ * See `RuntimeStateDurability`. Enforced by
29966
+ * `scripts/check-runtime-state-durability.ts`.
29967
+ */
29968
+ durability: "restored",
29969
+ /** Clock fields: written, but excluded from the compare that decides
29970
+ * whether persisting is worth a SQLite commit. */
29971
+ volatileStateFields: ["lastChangedAt"]
29721
29972
  };
29722
29973
  var DayNightModeSchema = external_exports.enum([
29723
29974
  "auto",
@@ -29778,7 +30029,17 @@ var dayNightCapability = {
29778
30029
  schema: DayNightStatusSchema,
29779
30030
  kind: "poll"
29780
30031
  },
29781
- runtimeState: DayNightStatusSchema
30032
+ runtimeState: DayNightStatusSchema,
30033
+ /**
30034
+ * Runtime-state durability: **restored** — operator-set IR-cut behaviour; mutation-driven.
30035
+ *
30036
+ * See `RuntimeStateDurability`. Enforced by
30037
+ * `scripts/check-runtime-state-durability.ts`.
30038
+ */
30039
+ durability: "restored",
30040
+ /** Clock fields: written, but excluded from the compare that decides
30041
+ * whether persisting is worth a SQLite commit. */
30042
+ volatileStateFields: ["lastFetchedAt"]
29782
30043
  };
29783
30044
  var DeviceStatusSchema = external_exports.object({
29784
30045
  /**
@@ -29811,7 +30072,17 @@ var deviceStatusCapability = {
29811
30072
  schema: DeviceStatusSchema,
29812
30073
  kind: "push"
29813
30074
  },
29814
- runtimeState: DeviceStatusSchema
30075
+ runtimeState: DeviceStatusSchema,
30076
+ /**
30077
+ * 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.
30078
+ *
30079
+ * See `RuntimeStateDurability`. Enforced by
30080
+ * `scripts/check-runtime-state-durability.ts`.
30081
+ */
30082
+ durability: "restored",
30083
+ /** Clock fields: written, but excluded from the compare that decides
30084
+ * whether persisting is worth a SQLite commit. */
30085
+ volatileStateFields: ["lastChangedAt"]
29815
30086
  };
29816
30087
  var DoorbellStatusSchema = external_exports.object({
29817
30088
  /** Ms epoch of the last press. null = never observed since this provider started. */
@@ -29851,7 +30122,14 @@ var doorbellCapability = {
29851
30122
  * `device.state.doorbell.value`. UIs can show "last ring 5m ago"
29852
30123
  * without subscribing.
29853
30124
  */
29854
- runtimeState: DoorbellStatusSchema
30125
+ runtimeState: DoorbellStatusSchema,
30126
+ /**
30127
+ * 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.
30128
+ *
30129
+ * See `RuntimeStateDurability`. Enforced by
30130
+ * `scripts/check-runtime-state-durability.ts`.
30131
+ */
30132
+ durability: "restored"
29855
30133
  };
29856
30134
  var EnumSensorDateTimeFormatSchema = external_exports.enum([
29857
30135
  "date",
@@ -29881,7 +30159,17 @@ var enumSensorCapability = {
29881
30159
  schema: EnumSensorStatusSchema,
29882
30160
  kind: "push"
29883
30161
  },
29884
- runtimeState: EnumSensorStatusSchema
30162
+ runtimeState: EnumSensorStatusSchema,
30163
+ /**
30164
+ * Runtime-state durability: **restored** — as `numeric-sensor`; 80 devices.
30165
+ *
30166
+ * See `RuntimeStateDurability`. Enforced by
30167
+ * `scripts/check-runtime-state-durability.ts`.
30168
+ */
30169
+ durability: "restored",
30170
+ /** Clock fields: written, but excluded from the compare that decides
30171
+ * whether persisting is worth a SQLite commit. */
30172
+ volatileStateFields: ["lastFetchedAt"]
29885
30173
  };
29886
30174
  var EventFireSchema = external_exports.object({
29887
30175
  deviceId: external_exports.number(),
@@ -29907,7 +30195,14 @@ var eventEmitterCapability = {
29907
30195
  schema: EventEmitterStatusSchema,
29908
30196
  kind: "push"
29909
30197
  },
29910
- runtimeState: EventEmitterStatusSchema
30198
+ runtimeState: EventEmitterStatusSchema,
30199
+ /**
30200
+ * Runtime-state durability: **session** — `eventCountSinceStart` names its own scope.
30201
+ *
30202
+ * See `RuntimeStateDurability`. Enforced by
30203
+ * `scripts/check-runtime-state-durability.ts`.
30204
+ */
30205
+ durability: "session"
29911
30206
  };
29912
30207
  var EventItemSchema = external_exports.object({
29913
30208
  id: external_exports.string(),
@@ -30206,7 +30501,14 @@ var fanControlCapability = {
30206
30501
  * Runtime-state slice — mirrored by the kernel. UI fan speed
30207
30502
  * sliders read `percentage` for live updates.
30208
30503
  */
30209
- runtimeState: FanControlStatusSchema
30504
+ runtimeState: FanControlStatusSchema,
30505
+ /**
30506
+ * Runtime-state durability: **session** — as `brightness`.
30507
+ *
30508
+ * See `RuntimeStateDurability`. Enforced by
30509
+ * `scripts/check-runtime-state-durability.ts`.
30510
+ */
30511
+ durability: "session"
30210
30512
  };
30211
30513
  var FeatureProbeStatusSchema = external_exports.object({
30212
30514
  /**
@@ -30259,7 +30561,14 @@ var featureProbeCapability = {
30259
30561
  schema: FeatureProbeStatusSchema,
30260
30562
  kind: "push"
30261
30563
  },
30262
- runtimeState: FeatureProbeStatusSchema
30564
+ runtimeState: FeatureProbeStatusSchema,
30565
+ /**
30566
+ * 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.
30567
+ *
30568
+ * See `RuntimeStateDurability`. Enforced by
30569
+ * `scripts/check-runtime-state-durability.ts`.
30570
+ */
30571
+ durability: "session"
30263
30572
  };
30264
30573
  var FloodStatusSchema = external_exports.object({
30265
30574
  /** True when leak is currently detected. */
@@ -30278,7 +30587,17 @@ var floodCapability = {
30278
30587
  schema: FloodStatusSchema,
30279
30588
  kind: "push"
30280
30589
  },
30281
- runtimeState: FloodStatusSchema
30590
+ runtimeState: FloodStatusSchema,
30591
+ /**
30592
+ * Runtime-state durability: **restored** — as `smoke`.
30593
+ *
30594
+ * See `RuntimeStateDurability`. Enforced by
30595
+ * `scripts/check-runtime-state-durability.ts`.
30596
+ */
30597
+ durability: "restored",
30598
+ /** Clock fields: written, but excluded from the compare that decides
30599
+ * whether persisting is worth a SQLite commit. */
30600
+ volatileStateFields: ["lastChangedAt"]
30282
30601
  };
30283
30602
  var GasStatusSchema = external_exports.object({
30284
30603
  detected: external_exports.boolean(),
@@ -30296,7 +30615,17 @@ var gasCapability = {
30296
30615
  schema: GasStatusSchema,
30297
30616
  kind: "push"
30298
30617
  },
30299
- runtimeState: GasStatusSchema
30618
+ runtimeState: GasStatusSchema,
30619
+ /**
30620
+ * Runtime-state durability: **restored** — as `smoke`.
30621
+ *
30622
+ * See `RuntimeStateDurability`. Enforced by
30623
+ * `scripts/check-runtime-state-durability.ts`.
30624
+ */
30625
+ durability: "restored",
30626
+ /** Clock fields: written, but excluded from the compare that decides
30627
+ * whether persisting is worth a SQLite commit. */
30628
+ volatileStateFields: ["lastChangedAt"]
30300
30629
  };
30301
30630
  var HumidifierStatusSchema = external_exports.object({
30302
30631
  /** Whether the humidifier is currently on. */
@@ -30357,7 +30686,14 @@ var humidifierCapability = {
30357
30686
  * Runtime-state slice — mirrored by the kernel. UI controls watch the
30358
30687
  * slice for live humidity / mode changes.
30359
30688
  */
30360
- runtimeState: HumidifierStatusSchema
30689
+ runtimeState: HumidifierStatusSchema,
30690
+ /**
30691
+ * Runtime-state durability: **session** — as `climate-control`.
30692
+ *
30693
+ * See `RuntimeStateDurability`. Enforced by
30694
+ * `scripts/check-runtime-state-durability.ts`.
30695
+ */
30696
+ durability: "session"
30361
30697
  };
30362
30698
  var HumiditySensorStatusSchema = external_exports.object({
30363
30699
  /** Current relative humidity, 0..100. */
@@ -30385,7 +30721,17 @@ var humiditySensorCapability = {
30385
30721
  schema: HumiditySensorStatusSchema,
30386
30722
  kind: "push"
30387
30723
  },
30388
- runtimeState: HumiditySensorStatusSchema
30724
+ runtimeState: HumiditySensorStatusSchema,
30725
+ /**
30726
+ * Runtime-state durability: **restored** — as `numeric-sensor` (67 of 75 writes were the clock alone).
30727
+ *
30728
+ * See `RuntimeStateDurability`. Enforced by
30729
+ * `scripts/check-runtime-state-durability.ts`.
30730
+ */
30731
+ durability: "restored",
30732
+ /** Clock fields: written, but excluded from the compare that decides
30733
+ * whether persisting is worth a SQLite commit. */
30734
+ volatileStateFields: ["lastFetchedAt"]
30389
30735
  };
30390
30736
  var ImageStatusSchema = external_exports.object({
30391
30737
  /** Absolute signed URL the browser loads directly. Null when the
@@ -30409,7 +30755,14 @@ var imageCapability = {
30409
30755
  * Runtime-state slice — mirrored by the kernel. The UI reads `url`
30410
30756
  * directly and renders the still image.
30411
30757
  */
30412
- runtimeState: ImageStatusSchema
30758
+ runtimeState: ImageStatusSchema,
30759
+ /**
30760
+ * Runtime-state durability: **session** — a snapshot URL is a session-scoped handle; a restored one points at nothing.
30761
+ *
30762
+ * See `RuntimeStateDurability`. Enforced by
30763
+ * `scripts/check-runtime-state-durability.ts`.
30764
+ */
30765
+ durability: "session"
30413
30766
  };
30414
30767
  var ImageRotateSchema = external_exports.enum([
30415
30768
  "0",
@@ -30510,7 +30863,17 @@ var imageSettingsCapability = {
30510
30863
  schema: ImageSettingsStatusSchema,
30511
30864
  kind: "poll"
30512
30865
  },
30513
- runtimeState: ImageSettingsStatusSchema
30866
+ runtimeState: ImageSettingsStatusSchema,
30867
+ /**
30868
+ * Runtime-state durability: **restored** — operator-set camera imaging; mutation-driven.
30869
+ *
30870
+ * See `RuntimeStateDurability`. Enforced by
30871
+ * `scripts/check-runtime-state-durability.ts`.
30872
+ */
30873
+ durability: "restored",
30874
+ /** Clock fields: written, but excluded from the compare that decides
30875
+ * whether persisting is worth a SQLite commit. */
30876
+ volatileStateFields: ["lastFetchedAt"]
30514
30877
  };
30515
30878
  var IntegrationWithStateSchema = external_exports.object({
30516
30879
  id: external_exports.string(),
@@ -30841,7 +31204,14 @@ var lawnMowerControlCapability = {
30841
31204
  * Runtime-state slice — mirrored by the kernel. UI controls watch the
30842
31205
  * slice for live activity + battery changes.
30843
31206
  */
30844
- runtimeState: LawnMowerControlStatusSchema
31207
+ runtimeState: LawnMowerControlStatusSchema,
31208
+ /**
31209
+ * Runtime-state durability: **session** — as `vacuum-control`.
31210
+ *
31211
+ * See `RuntimeStateDurability`. Enforced by
31212
+ * `scripts/check-runtime-state-durability.ts`.
31213
+ */
31214
+ durability: "session"
30845
31215
  };
30846
31216
  var InterfaceKindEnum = external_exports.enum([
30847
31217
  "lan",
@@ -31090,7 +31460,17 @@ var lockControlCapability = {
31090
31460
  * read `state` and disable themselves during `locking`/`unlocking`
31091
31461
  * transitions.
31092
31462
  */
31093
- runtimeState: LockControlStatusSchema
31463
+ runtimeState: LockControlStatusSchema,
31464
+ /**
31465
+ * Runtime-state durability: **restored** — a lock left locked must still read locked.
31466
+ *
31467
+ * See `RuntimeStateDurability`. Enforced by
31468
+ * `scripts/check-runtime-state-durability.ts`.
31469
+ */
31470
+ durability: "restored",
31471
+ /** Clock fields: written, but excluded from the compare that decides
31472
+ * whether persisting is worth a SQLite commit. */
31473
+ volatileStateFields: ["lastChangedAt"]
31094
31474
  };
31095
31475
  var MediaPlayerStateSchema = external_exports.enum([
31096
31476
  "off",
@@ -31240,7 +31620,14 @@ var mediaPlayerCapability = {
31240
31620
  * full slice for live now-playing, volume, and progress updates
31241
31621
  * without polling.
31242
31622
  */
31243
- runtimeState: MediaPlayerStatusSchema
31623
+ runtimeState: MediaPlayerStatusSchema,
31624
+ /**
31625
+ * Runtime-state durability: **session** — a restored transport position describes a playback that stopped when the hub did.
31626
+ *
31627
+ * See `RuntimeStateDurability`. Enforced by
31628
+ * `scripts/check-runtime-state-durability.ts`.
31629
+ */
31630
+ durability: "session"
31244
31631
  };
31245
31632
  var MeshEndpointSchema = external_exports.object({
31246
31633
  /** Stable identifier within the provider (e.g. `mesh-ipv4`, `magicdns`, `funnel`). */
@@ -31524,7 +31911,14 @@ var motionCapability = {
31524
31911
  * `device.state.motion.value`. Reads never invoke the provider, so
31525
31912
  * UIs and other addons can poll the cached state safely.
31526
31913
  */
31527
- runtimeState: MotionStatusSchema
31914
+ runtimeState: MotionStatusSchema,
31915
+ /**
31916
+ * 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.
31917
+ *
31918
+ * See `RuntimeStateDurability`. Enforced by
31919
+ * `scripts/check-runtime-state-durability.ts`.
31920
+ */
31921
+ durability: "session"
31528
31922
  };
31529
31923
  var MotionTriggerStatusSchema = external_exports.object({
31530
31924
  enabled: external_exports.boolean(),
@@ -31561,7 +31955,14 @@ var motionTriggerCapability = {
31561
31955
  schema: MotionTriggerStatusSchema,
31562
31956
  kind: "command-driven"
31563
31957
  },
31564
- runtimeState: MotionTriggerRuntimeStateSchema
31958
+ runtimeState: MotionTriggerRuntimeStateSchema,
31959
+ /**
31960
+ * 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.
31961
+ *
31962
+ * See `RuntimeStateDurability`. Enforced by
31963
+ * `scripts/check-runtime-state-durability.ts`.
31964
+ */
31965
+ durability: "session"
31565
31966
  };
31566
31967
  var MotionZoneRegionSchema = external_exports.object({
31567
31968
  id: external_exports.number(),
@@ -31616,7 +32017,17 @@ var motionZonesCapability = {
31616
32017
  schema: MotionZoneStatusSchema,
31617
32018
  kind: "poll"
31618
32019
  },
31619
- runtimeState: MotionZoneStatusSchema
32020
+ runtimeState: MotionZoneStatusSchema,
32021
+ /**
32022
+ * 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.
32023
+ *
32024
+ * See `RuntimeStateDurability`. Enforced by
32025
+ * `scripts/check-runtime-state-durability.ts`.
32026
+ */
32027
+ durability: "restored",
32028
+ /** Clock fields: written, but excluded from the compare that decides
32029
+ * whether persisting is worth a SQLite commit. */
32030
+ volatileStateFields: ["lastFetchedAt"]
31620
32031
  };
31621
32032
  var NativeObjectClassEnum = external_exports.enum([
31622
32033
  "person",
@@ -31679,7 +32090,17 @@ var nativeObjectDetectionCapability = {
31679
32090
  schema: NativeObjectDetectionStatusSchema,
31680
32091
  kind: "push"
31681
32092
  },
31682
- runtimeState: NativeObjectDetectionRuntimeStateSchema
32093
+ runtimeState: NativeObjectDetectionRuntimeStateSchema,
32094
+ /**
32095
+ * 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.
32096
+ *
32097
+ * See `RuntimeStateDurability`. Enforced by
32098
+ * `scripts/check-runtime-state-durability.ts`.
32099
+ */
32100
+ durability: "restored",
32101
+ /** Clock fields: written, but excluded from the compare that decides
32102
+ * whether persisting is worth a SQLite commit. */
32103
+ volatileStateFields: ["lastFetchedAt"]
31683
32104
  };
31684
32105
  var StreamNetworkStatsSchema = external_exports.object({
31685
32106
  nominalBitrateKbps: external_exports.number(),
@@ -32002,7 +32423,14 @@ var notifierCapability = {
32002
32423
  * form reads `supports` to gate optional fields; history pane reads
32003
32424
  * `lastSentAt` / `lastError` / `queueDepth`.
32004
32425
  */
32005
- runtimeState: NotifierStatusSchema
32426
+ runtimeState: NotifierStatusSchema,
32427
+ /**
32428
+ * Runtime-state durability: **session** — live queue depth and last-send state; a restored queue depth describes a queue that no longer exists.
32429
+ *
32430
+ * See `RuntimeStateDurability`. Enforced by
32431
+ * `scripts/check-runtime-state-durability.ts`.
32432
+ */
32433
+ durability: "session"
32006
32434
  };
32007
32435
  var NumericSensorStatusSchema = external_exports.object({
32008
32436
  value: external_exports.number(),
@@ -32028,7 +32456,17 @@ var numericSensorCapability = {
32028
32456
  schema: NumericSensorStatusSchema,
32029
32457
  kind: "push"
32030
32458
  },
32031
- runtimeState: NumericSensorStatusSchema
32459
+ runtimeState: NumericSensorStatusSchema,
32460
+ /**
32461
+ * 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.
32462
+ *
32463
+ * See `RuntimeStateDurability`. Enforced by
32464
+ * `scripts/check-runtime-state-durability.ts`.
32465
+ */
32466
+ durability: "restored",
32467
+ /** Clock fields: written, but excluded from the compare that decides
32468
+ * whether persisting is worth a SQLite commit. */
32469
+ volatileStateFields: ["lastFetchedAt"]
32032
32470
  };
32033
32471
  var OsdOverlayKindEnum = external_exports.enum([
32034
32472
  "text",
@@ -32451,7 +32889,14 @@ var petFeederCapability = {
32451
32889
  * the full slice via `device.state.petFeeder.value` and refresh on
32452
32890
  * every poll without re-querying the provider.
32453
32891
  */
32454
- runtimeState: PetFeederStatusSchema
32892
+ runtimeState: PetFeederStatusSchema,
32893
+ /**
32894
+ * Runtime-state durability: **session** — live appliance state re-published on connect.
32895
+ *
32896
+ * See `RuntimeStateDurability`. Enforced by
32897
+ * `scripts/check-runtime-state-durability.ts`.
32898
+ */
32899
+ durability: "session"
32455
32900
  };
32456
32901
  var VehicleSchema = external_exports.object({
32457
32902
  id: external_exports.string(),
@@ -32785,7 +33230,17 @@ var powerMeterCapability = {
32785
33230
  schema: PowerMeterStatusSchema,
32786
33231
  kind: "push"
32787
33232
  },
32788
- runtimeState: PowerMeterStatusSchema
33233
+ runtimeState: PowerMeterStatusSchema,
33234
+ /**
33235
+ * Runtime-state durability: **restored** — as `numeric-sensor`; `kwhTotal` is an accumulator whose restored value is the baseline.
33236
+ *
33237
+ * See `RuntimeStateDurability`. Enforced by
33238
+ * `scripts/check-runtime-state-durability.ts`.
33239
+ */
33240
+ durability: "restored",
33241
+ /** Clock fields: written, but excluded from the compare that decides
33242
+ * whether persisting is worth a SQLite commit. */
33243
+ volatileStateFields: ["lastFetchedAt"]
32789
33244
  };
32790
33245
  var GpsLocationSchema = external_exports.object({
32791
33246
  /** Latitude in decimal degrees, -90..90. */
@@ -32826,7 +33281,17 @@ var presenceCapability = {
32826
33281
  * the map pin is rendered (use `DeviceFeature.PresenceGps` for the
32827
33282
  * pre-fetch fast-path check).
32828
33283
  */
32829
- runtimeState: PresenceStatusSchema
33284
+ runtimeState: PresenceStatusSchema,
33285
+ /**
33286
+ * Runtime-state durability: **restored** — occupancy-relevant: the restored state is what an occupancy rule compares the first post-restart observation against.
33287
+ *
33288
+ * See `RuntimeStateDurability`. Enforced by
33289
+ * `scripts/check-runtime-state-durability.ts`.
33290
+ */
33291
+ durability: "restored",
33292
+ /** Clock fields: written, but excluded from the compare that decides
33293
+ * whether persisting is worth a SQLite commit. */
33294
+ volatileStateFields: ["lastChangedAt"]
32830
33295
  };
32831
33296
  var PressureSensorStatusSchema = external_exports.object({
32832
33297
  /** Current pressure in hPa. */
@@ -32854,7 +33319,17 @@ var pressureSensorCapability = {
32854
33319
  schema: PressureSensorStatusSchema,
32855
33320
  kind: "push"
32856
33321
  },
32857
- runtimeState: PressureSensorStatusSchema
33322
+ runtimeState: PressureSensorStatusSchema,
33323
+ /**
33324
+ * Runtime-state durability: **restored** — as `numeric-sensor`.
33325
+ *
33326
+ * See `RuntimeStateDurability`. Enforced by
33327
+ * `scripts/check-runtime-state-durability.ts`.
33328
+ */
33329
+ durability: "restored",
33330
+ /** Clock fields: written, but excluded from the compare that decides
33331
+ * whether persisting is worth a SQLite commit. */
33332
+ volatileStateFields: ["lastFetchedAt"]
32858
33333
  };
32859
33334
  var PrivacyMaskShapeSchema = external_exports.discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
32860
33335
  var PrivacyMaskRegionSchema = external_exports.object({
@@ -32953,7 +33428,17 @@ var privacyMaskCapability = {
32953
33428
  schema: PrivacyMaskStatusSchema,
32954
33429
  kind: "poll"
32955
33430
  },
32956
- runtimeState: PrivacyMaskStatusSchema
33431
+ runtimeState: PrivacyMaskStatusSchema,
33432
+ /**
33433
+ * Runtime-state durability: **restored** — operator-drawn regions, zero real churn — 22 writes in 25 minutes, every one of them the clock.
33434
+ *
33435
+ * See `RuntimeStateDurability`. Enforced by
33436
+ * `scripts/check-runtime-state-durability.ts`.
33437
+ */
33438
+ durability: "restored",
33439
+ /** Clock fields: written, but excluded from the compare that decides
33440
+ * whether persisting is worth a SQLite commit. */
33441
+ volatileStateFields: ["lastFetchedAt"]
32957
33442
  };
32958
33443
  var PtzPresetSchema = external_exports.object({
32959
33444
  id: external_exports.string(),
@@ -33139,7 +33624,14 @@ var ptzAutotrackCapability = {
33139
33624
  * fetch / cache / fallback logic out of the four cap methods —
33140
33625
  * they become trampolines over `runtimeState`.
33141
33626
  */
33142
- runtimeState: PtzAutotrackRuntimeStateSchema
33627
+ runtimeState: PtzAutotrackRuntimeStateSchema,
33628
+ /**
33629
+ * Runtime-state durability: **session** — mirrors the camera's own autotrack config, re-read on connect.
33630
+ *
33631
+ * See `RuntimeStateDurability`. Enforced by
33632
+ * `scripts/check-runtime-state-durability.ts`.
33633
+ */
33634
+ durability: "session"
33143
33635
  };
33144
33636
  var rebootCapability = {
33145
33637
  name: "reboot",
@@ -33808,7 +34300,14 @@ var sceneMonitorCapability = {
33808
34300
  schema: SceneMonitorStatusSchema,
33809
34301
  kind: "push"
33810
34302
  },
33811
- runtimeState: SceneMonitorStatusSchema
34303
+ runtimeState: SceneMonitorStatusSchema,
34304
+ /**
34305
+ * Runtime-state durability: **session** — re-derived from the current scene on the next evaluation.
34306
+ *
34307
+ * See `RuntimeStateDurability`. Enforced by
34308
+ * `scripts/check-runtime-state-durability.ts`.
34309
+ */
34310
+ durability: "session"
33812
34311
  };
33813
34312
  var ZoneRuleModeEnum = external_exports.enum(["include", "exclude"]);
33814
34313
  var ZoneRuleSchema = external_exports.object({
@@ -33910,7 +34409,14 @@ var scriptRunnerCapability = {
33910
34409
  * `isRunning` to render a spinner during execution and surfaces
33911
34410
  * `lastError` / `lastRunSuccess` in the recent-runs panel.
33912
34411
  */
33913
- runtimeState: ScriptRunnerStatusSchema
34412
+ runtimeState: ScriptRunnerStatusSchema,
34413
+ /**
34414
+ * Runtime-state durability: **session** — a restored `isRunning: true` describes a process that died with the previous hub.
34415
+ *
34416
+ * See `RuntimeStateDurability`. Enforced by
34417
+ * `scripts/check-runtime-state-durability.ts`.
34418
+ */
34419
+ durability: "session"
33914
34420
  };
33915
34421
  var SmokeStatusSchema = external_exports.object({
33916
34422
  detected: external_exports.boolean(),
@@ -33928,7 +34434,17 @@ var smokeCapability = {
33928
34434
  schema: SmokeStatusSchema,
33929
34435
  kind: "push"
33930
34436
  },
33931
- runtimeState: SmokeStatusSchema
34437
+ runtimeState: SmokeStatusSchema,
34438
+ /**
34439
+ * Runtime-state durability: **restored** — a safety sensor must not read "clear" merely because the hub restarted.
34440
+ *
34441
+ * See `RuntimeStateDurability`. Enforced by
34442
+ * `scripts/check-runtime-state-durability.ts`.
34443
+ */
34444
+ durability: "restored",
34445
+ /** Clock fields: written, but excluded from the compare that decides
34446
+ * whether persisting is worth a SQLite commit. */
34447
+ volatileStateFields: ["lastChangedAt"]
33932
34448
  };
33933
34449
  var CamStreamDescriptorSchema = external_exports.object({
33934
34450
  camStreamId: external_exports.string().min(1),
@@ -34079,7 +34595,17 @@ var streamParamsCapability = {
34079
34595
  schema: StreamParamsStatusSchema,
34080
34596
  kind: "poll"
34081
34597
  },
34082
- runtimeState: StreamParamsStatusSchema
34598
+ runtimeState: StreamParamsStatusSchema,
34599
+ /**
34600
+ * Runtime-state durability: **restored** — operator-set encoder profile; mutation-driven.
34601
+ *
34602
+ * See `RuntimeStateDurability`. Enforced by
34603
+ * `scripts/check-runtime-state-durability.ts`.
34604
+ */
34605
+ durability: "restored",
34606
+ /** Clock fields: written, but excluded from the compare that decides
34607
+ * whether persisting is worth a SQLite commit. */
34608
+ volatileStateFields: ["lastFetchedAt"]
34083
34609
  };
34084
34610
  var SwitchStatusSchema = external_exports.object({
34085
34611
  on: external_exports.boolean(),
@@ -34118,6 +34644,16 @@ var switchCapability = {
34118
34644
  * not need to re-query the provider after a setState mutation.
34119
34645
  */
34120
34646
  runtimeState: SwitchStatusSchema,
34647
+ /**
34648
+ * Runtime-state durability: **restored** — device state an operator reads as authoritative; 55 devices, transition-driven.
34649
+ *
34650
+ * See `RuntimeStateDurability`. Enforced by
34651
+ * `scripts/check-runtime-state-durability.ts`.
34652
+ */
34653
+ durability: "restored",
34654
+ /** Clock fields: written, but excluded from the compare that decides
34655
+ * whether persisting is worth a SQLite commit. */
34656
+ volatileStateFields: ["lastChangedAt"],
34121
34657
  settings: { bindings: [{
34122
34658
  kind: "scalar",
34123
34659
  statusPath: "on",
@@ -34190,7 +34726,17 @@ var tamperCapability = {
34190
34726
  schema: TamperStatusSchema,
34191
34727
  kind: "push"
34192
34728
  },
34193
- runtimeState: TamperStatusSchema
34729
+ runtimeState: TamperStatusSchema,
34730
+ /**
34731
+ * Runtime-state durability: **restored** — as `smoke`.
34732
+ *
34733
+ * See `RuntimeStateDurability`. Enforced by
34734
+ * `scripts/check-runtime-state-durability.ts`.
34735
+ */
34736
+ durability: "restored",
34737
+ /** Clock fields: written, but excluded from the compare that decides
34738
+ * whether persisting is worth a SQLite commit. */
34739
+ volatileStateFields: ["lastChangedAt"]
34194
34740
  };
34195
34741
  var TemperatureSensorStatusSchema = external_exports.object({
34196
34742
  /** Current temperature in Celsius. */
@@ -34219,7 +34765,17 @@ var temperatureSensorCapability = {
34219
34765
  schema: TemperatureSensorStatusSchema,
34220
34766
  kind: "push"
34221
34767
  },
34222
- runtimeState: TemperatureSensorStatusSchema
34768
+ runtimeState: TemperatureSensorStatusSchema,
34769
+ /**
34770
+ * Runtime-state durability: **restored** — as `numeric-sensor` (69 of 125 writes were the clock alone).
34771
+ *
34772
+ * See `RuntimeStateDurability`. Enforced by
34773
+ * `scripts/check-runtime-state-durability.ts`.
34774
+ */
34775
+ durability: "restored",
34776
+ /** Clock fields: written, but excluded from the compare that decides
34777
+ * whether persisting is worth a SQLite commit. */
34778
+ volatileStateFields: ["lastFetchedAt"]
34223
34779
  };
34224
34780
  var ToastSchema = external_exports.object({
34225
34781
  title: external_exports.string(),
@@ -34270,7 +34826,14 @@ var updateCapability = {
34270
34826
  schema: UpdateStatusSchema,
34271
34827
  kind: "poll"
34272
34828
  },
34273
- runtimeState: UpdateStatusSchema
34829
+ runtimeState: UpdateStatusSchema,
34830
+ /**
34831
+ * Runtime-state durability: **session** — a restored `inProgress: true` describes an update that is no longer running; versions are re-probed at boot.
34832
+ *
34833
+ * See `RuntimeStateDurability`. Enforced by
34834
+ * `scripts/check-runtime-state-durability.ts`.
34835
+ */
34836
+ durability: "session"
34274
34837
  };
34275
34838
  var UserSummarySchema = external_exports.object({
34276
34839
  id: external_exports.string(),
@@ -34604,7 +35167,14 @@ var vacuumControlCapability = {
34604
35167
  * Runtime-state slice — mirrored by the kernel. UI controls watch the
34605
35168
  * slice for live state + battery + fan-speed changes.
34606
35169
  */
34607
- runtimeState: VacuumControlStatusSchema
35170
+ runtimeState: VacuumControlStatusSchema,
35171
+ /**
35172
+ * Runtime-state durability: **session** — as `media-player` — a restored `state: cleaning` is a robot that is not cleaning.
35173
+ *
35174
+ * See `RuntimeStateDurability`. Enforced by
35175
+ * `scripts/check-runtime-state-durability.ts`.
35176
+ */
35177
+ durability: "session"
34608
35178
  };
34609
35179
  var ValveStateSchema = external_exports.enum([
34610
35180
  "open",
@@ -34657,7 +35227,14 @@ var valveCapability = {
34657
35227
  * Runtime-state slice — mirrored by the kernel. UI controls watch the
34658
35228
  * slice for live position changes during a move.
34659
35229
  */
34660
- runtimeState: ValveStatusSchema
35230
+ runtimeState: ValveStatusSchema,
35231
+ /**
35232
+ * Runtime-state durability: **session** — as `brightness`.
35233
+ *
35234
+ * See `RuntimeStateDurability`. Enforced by
35235
+ * `scripts/check-runtime-state-durability.ts`.
35236
+ */
35237
+ durability: "session"
34661
35238
  };
34662
35239
  var VibrationStatusSchema = external_exports.object({
34663
35240
  detected: external_exports.boolean(),
@@ -34675,7 +35252,17 @@ var vibrationCapability = {
34675
35252
  schema: VibrationStatusSchema,
34676
35253
  kind: "push"
34677
35254
  },
34678
- runtimeState: VibrationStatusSchema
35255
+ runtimeState: VibrationStatusSchema,
35256
+ /**
35257
+ * Runtime-state durability: **restored** — as `smoke`.
35258
+ *
35259
+ * See `RuntimeStateDurability`. Enforced by
35260
+ * `scripts/check-runtime-state-durability.ts`.
35261
+ */
35262
+ durability: "restored",
35263
+ /** Clock fields: written, but excluded from the compare that decides
35264
+ * whether persisting is worth a SQLite commit. */
35265
+ volatileStateFields: ["lastChangedAt"]
34679
35266
  };
34680
35267
  var WaterHeaterStatusSchema = external_exports.object({
34681
35268
  /** Current measured temperature. Null when not reported. */
@@ -34735,7 +35322,14 @@ var waterHeaterCapability = {
34735
35322
  * Runtime-state slice — mirrored by the kernel. UI controls watch the
34736
35323
  * slice for live temperature / mode / away changes.
34737
35324
  */
34738
- runtimeState: WaterHeaterStatusSchema
35325
+ runtimeState: WaterHeaterStatusSchema,
35326
+ /**
35327
+ * Runtime-state durability: **session** — as `climate-control`.
35328
+ *
35329
+ * See `RuntimeStateDurability`. Enforced by
35330
+ * `scripts/check-runtime-state-durability.ts`.
35331
+ */
35332
+ durability: "session"
34739
35333
  };
34740
35334
  var WeatherStatusSchema = external_exports.object({
34741
35335
  /** Verbatim HA condition state (`sunny`, `cloudy`, `rainy`, …). Null
@@ -34775,7 +35369,14 @@ var weatherCapability = {
34775
35369
  * Runtime-state slice — mirrored by the kernel. The UI reads the
34776
35370
  * current conditions directly from the slice on each weather push.
34777
35371
  */
34778
- runtimeState: WeatherStatusSchema
35372
+ runtimeState: WeatherStatusSchema,
35373
+ /**
35374
+ * Runtime-state durability: **session** — a forecast is stale the moment the hub is down; the provider re-fetches on connect.
35375
+ *
35376
+ * See `RuntimeStateDurability`. Enforced by
35377
+ * `scripts/check-runtime-state-durability.ts`.
35378
+ */
35379
+ durability: "session"
34779
35380
  };
34780
35381
  var PerScopeBreakdownSchema = external_exports.object({
34781
35382
  /** Total tracked objects in this scope (frame / zone / unzoned). */
@@ -34884,7 +35485,14 @@ var zoneAnalyticsCapability = {
34884
35485
  * automatically; the explicit `getCurrentSnapshot` cap method is
34885
35486
  * still useful for one-off polls without a subscription.
34886
35487
  */
34887
- runtimeState: CameraOccupancySnapshotSchema
35488
+ runtimeState: CameraOccupancySnapshotSchema,
35489
+ /**
35490
+ * Runtime-state durability: **session** — per-frame analytics; with `audio-metrics` it is ~90 % of the offered write rate. Re-derived on the next frame.
35491
+ *
35492
+ * See `RuntimeStateDurability`. Enforced by
35493
+ * `scripts/check-runtime-state-durability.ts`.
35494
+ */
35495
+ durability: "session"
34888
35496
  };
34889
35497
  var ZoneRuleStageEnum = external_exports.enum([
34890
35498
  "motion",
@@ -34936,7 +35544,14 @@ var zoneRulesCapability = {
34936
35544
  motion: external_exports.array(ZoneRuleSchema).readonly(),
34937
35545
  detection: external_exports.array(ZoneRuleSchema).readonly(),
34938
35546
  package: external_exports.array(ZoneRuleSchema).readonly()
34939
- })
35547
+ }),
35548
+ /**
35549
+ * Runtime-state durability: **restored** — operator intent, mutation-only, same argument as `zones`.
35550
+ *
35551
+ * See `RuntimeStateDurability`. Enforced by
35552
+ * `scripts/check-runtime-state-durability.ts`.
35553
+ */
35554
+ durability: "restored"
34940
35555
  };
34941
35556
  var PIPELINE_FLOW_CAPABILITY_NAMES = [
34942
35557
  "decoder",
@@ -40626,6 +41241,7 @@ var CAP_PROVIDER_KIND_MAP = Object.freeze({
40626
41241
  "network-access": "ingress",
40627
41242
  "smtp-provider": "email"
40628
41243
  });
41244
+ var ICON_BY_ID = new Map(AUDIO_MACRO_LABELS.flatMap((macro2) => macro2.icon === void 0 ? [] : [[macro2.id, macro2.icon]]));
40629
41245
  var NC_BASE_CONDITION_KEYS = ["devices", "classes"];
40630
41246
  var BASE_CONDITION_SET = new Set(NC_BASE_CONDITION_KEYS);
40631
41247
  var TimelapseTemplateSchema = external_exports.object({