camstack 1.2.22 → 1.2.24

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
@@ -21551,7 +21565,23 @@ var NotificationActionSchema = external_exports.object({
21551
21565
  * else — see `notification-center/action-token.ts` for what that does and
21552
21566
  * does not buy.
21553
21567
  */
21554
- destructive: external_exports.boolean().optional()
21568
+ destructive: external_exports.boolean().optional(),
21569
+ /**
21570
+ * How the tap should REACH the url.
21571
+ *
21572
+ * `navigate` (absent, and every button authored before this field) opens it:
21573
+ * the phone leaves the notification and shows whatever the callback returns.
21574
+ * That is right for a button whose answer the operator wants to read.
21575
+ *
21576
+ * `background` fires it as a POST and stays put. It exists for the buttons
21577
+ * whose whole point is not to interrupt — "silence this for 30 minutes" is
21578
+ * an answer to the notification, and being thrown into a browser tab to
21579
+ * confirm it costs more attention than the notification did. A backend that
21580
+ * cannot do a background call renders it as an ordinary link (the adapters
21581
+ * fall back rather than dropping the button), so this is a preference, never
21582
+ * a requirement.
21583
+ */
21584
+ mode: external_exports.enum(["navigate", "background"]).optional()
21555
21585
  });
21556
21586
  var NotificationSchema = external_exports.object({
21557
21587
  body: external_exports.string(),
@@ -22329,7 +22359,17 @@ var alarmPanelCapability = {
22329
22359
  * full slice; renders an arm button per `availableModes` entry and
22330
22360
  * a PIN field iff `requiresCode === true`.
22331
22361
  */
22332
- runtimeState: AlarmPanelStatusSchema
22362
+ runtimeState: AlarmPanelStatusSchema,
22363
+ /**
22364
+ * Runtime-state durability: **restored** — armed state is the one thing a panel must not lose across a restart.
22365
+ *
22366
+ * See `RuntimeStateDurability`. Enforced by
22367
+ * `scripts/check-runtime-state-durability.ts`.
22368
+ */
22369
+ durability: "restored",
22370
+ /** Clock fields: written, but excluded from the compare that decides
22371
+ * whether persisting is worth a SQLite commit. */
22372
+ volatileStateFields: ["lastChangedAt"]
22333
22373
  };
22334
22374
  var MaskPointSchema = external_exports.object({
22335
22375
  x: external_exports.number(),
@@ -22427,6 +22467,7 @@ var NcSystemEventConditionSchema = external_exports.object({
22427
22467
  nodeIds: external_exports.array(external_exports.string().min(1)).min(1).optional(),
22428
22468
  packageNames: external_exports.array(external_exports.string().min(1)).min(1).optional()
22429
22469
  });
22470
+ var NC_SNOOZE_MAX_MINUTES = 1440;
22430
22471
  var NcScheduleWindowSchema = external_exports.object({
22431
22472
  /** Days of week the window STARTS on (0 = Sunday … 6 = Saturday). */
22432
22473
  days: external_exports.array(external_exports.number().int().min(0).max(6)).min(1),
@@ -22683,15 +22724,15 @@ var NcConditionsSchema = external_exports.object({
22683
22724
  * (an `immediate` rule naming an `audio-*` class, one notification per
22684
22725
  * classified sample) stays exactly as it was for rules that already use it.
22685
22726
  *
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
22727
+ * In {@link NC_CONDITION_CATALOG} since P2, and the ORDER it got there is the
22728
+ * rule rather than an accident: the viewer mirrors the descriptor enums BY
22729
+ * HAND (`camstack/src/data/notification-center.ts`, guarded by
22730
+ * `scripts/check-viewer-condition-mirror.ts`) and its rule editor strips the
22690
22731
  * condition fields it does not know when a rule is saved from the phone.
22691
22732
  * 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.
22733
+ * operator loses a rule's conditions by opening it — so the viewer mirror
22734
+ * (P3, shipped) went FIRST, and the descriptor an editor renders from
22735
+ * follows here.
22695
22736
  */
22696
22737
  audio: NcAudioConditionSchema.optional()
22697
22738
  });
@@ -22860,6 +22901,30 @@ var NcRuleInputSchema = external_exports.object({
22860
22901
  */
22861
22902
  snoozeAllowGlobal: external_exports.boolean().optional(),
22862
22903
  /**
22904
+ * The snooze durations THIS rule's notification offers as buttons, in
22905
+ * minutes.
22906
+ *
22907
+ * Three states, and all three are distinct — which is exactly why this is
22908
+ * `.optional()` and never `.default()`. A Zod default does not run on the
22909
+ * addon cap path (three production failures in one day), so a schema default
22910
+ * would collapse the first two:
22911
+ *
22912
+ * | value | meaning |
22913
+ * | --- | --- |
22914
+ * | absent | the operator never said ⇒ {@link NC_DEFAULT_SNOOZE_MINUTES} |
22915
+ * | `[]` | **no snooze buttons on this rule** — the explicit override |
22916
+ * | a list | these choices, de-duplicated and sorted, at most four |
22917
+ *
22918
+ * `.max(4)` because the notifier's own action budget is small (ntfy allows
22919
+ * three buttons in total) and a rule that spent it all on snooze choices
22920
+ * would push its own tap-through actions off the notification.
22921
+ *
22922
+ * An empty list is NOT an alarm exemption: a rule the alarm is about, or
22923
+ * that arms the panel, is exempt automatically and cannot be silenced by a
22924
+ * window from anywhere (D133).
22925
+ */
22926
+ snoozeOptions: external_exports.array(external_exports.number().int().min(1).max(NC_SNOOZE_MAX_MINUTES)).max(4).optional(),
22927
+ /**
22863
22928
  * Devices this rule ACTUATES — arm the alarm, open a gate, turn on a light.
22864
22929
  *
22865
22930
  * This is what makes the rule set the alarm's trigger set without the alarm
@@ -22949,6 +23014,7 @@ var NcConditionDescriptorSchema = external_exports.object({
22949
23014
  "device",
22950
23015
  "package",
22951
23016
  "occupancy",
23017
+ "audio",
22952
23018
  "system"
22953
23019
  ]),
22954
23020
  label: external_exports.string(),
@@ -22967,6 +23033,7 @@ var NcConditionDescriptorSchema = external_exports.object({
22967
23033
  "crossingSelect",
22968
23034
  "polygonDraw",
22969
23035
  "occupancy",
23036
+ "audio",
22970
23037
  "deviceState",
22971
23038
  "systemEvent"
22972
23039
  ]),
@@ -23070,7 +23137,6 @@ var NcSnoozeScopeSchema = external_exports.enum([
23070
23137
  "device",
23071
23138
  "all"
23072
23139
  ]);
23073
- var NC_SNOOZE_MAX_MINUTES = 1440;
23074
23140
  var NcSnoozeInputSchema = external_exports.object({
23075
23141
  scope: NcSnoozeScopeSchema,
23076
23142
  /** Required when `scope: 'rule'` — a scoped snooze with no id matches
@@ -23078,6 +23144,19 @@ var NcSnoozeInputSchema = external_exports.object({
23078
23144
  ruleId: external_exports.string().optional(),
23079
23145
  /** Required when `scope: 'device'`. */
23080
23146
  deviceId: external_exports.number().int().optional(),
23147
+ /**
23148
+ * Narrow the window to these subject classes — "the cat, not the person".
23149
+ *
23150
+ * ORTHOGONAL to `scope`, deliberately, and absent means EVERY class: that is
23151
+ * what every window authored before this field meant, so no persisted row
23152
+ * changes meaning and no client has to learn anything to keep working.
23153
+ *
23154
+ * It is what makes the window's real key `(deviceId, classes[])` and lets it
23155
+ * cross rules (D133): the operator points at a camera and a kind of thing,
23156
+ * not at whichever of their four rules happened to produce the notification
23157
+ * they are dismissing.
23158
+ */
23159
+ classes: external_exports.array(external_exports.string().min(1)).min(1).optional(),
23081
23160
  durationMinutes: external_exports.number().int().min(1).max(NC_SNOOZE_MAX_MINUTES),
23082
23161
  /**
23083
23162
  * Silence this for EVERY recipient, not just the caller. Permission is
@@ -23102,6 +23181,10 @@ var NcSnoozeSchema = external_exports.object({
23102
23181
  scope: NcSnoozeScopeSchema,
23103
23182
  ruleId: external_exports.string().optional(),
23104
23183
  deviceId: external_exports.number().int().optional(),
23184
+ /** Subject classes this window covers. ABSENT = every class — see
23185
+ * {@link NcSnoozeInputSchema.shape.classes}. Lives in the JSON blob and has
23186
+ * no SQLite column: nothing queries a window by class. */
23187
+ classes: external_exports.array(external_exports.string().min(1)).min(1).optional(),
23105
23188
  startedAt: external_exports.number(),
23106
23189
  /** Exclusive: at exactly this instant the snooze is over. Expiry is a
23107
23190
  * COMPARISON, not a job — no sweeper can leave the operator silenced. */
@@ -25374,7 +25457,14 @@ var zonesCapability = {
25374
25457
  * handle. Slice shape is `{ zones: Zone[] }` so future extensions
25375
25458
  * (e.g. zone groupings) can sit alongside the polygon list.
25376
25459
  */
25377
- runtimeState: external_exports.object({ zones: external_exports.array(ZoneSchema).readonly() })
25460
+ runtimeState: external_exports.object({ zones: external_exports.array(ZoneSchema).readonly() }),
25461
+ /**
25462
+ * 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.
25463
+ *
25464
+ * See `RuntimeStateDurability`. Enforced by
25465
+ * `scripts/check-runtime-state-durability.ts`.
25466
+ */
25467
+ durability: "restored"
25378
25468
  };
25379
25469
  var NativeCropBboxSchema = external_exports.object({
25380
25470
  x: external_exports.number(),
@@ -28802,7 +28892,17 @@ var airQualitySensorCapability = {
28802
28892
  schema: AirQualitySensorStatusSchema,
28803
28893
  kind: "push"
28804
28894
  },
28805
- runtimeState: AirQualitySensorStatusSchema
28895
+ runtimeState: AirQualitySensorStatusSchema,
28896
+ /**
28897
+ * Runtime-state durability: **restored** — as `numeric-sensor`.
28898
+ *
28899
+ * See `RuntimeStateDurability`. Enforced by
28900
+ * `scripts/check-runtime-state-durability.ts`.
28901
+ */
28902
+ durability: "restored",
28903
+ /** Clock fields: written, but excluded from the compare that decides
28904
+ * whether persisting is worth a SQLite commit. */
28905
+ volatileStateFields: ["lastFetchedAt"]
28806
28906
  };
28807
28907
  var AmbientLightSensorStatusSchema = external_exports.object({
28808
28908
  /** Current illuminance in lux (lx). */
@@ -28830,7 +28930,17 @@ var ambientLightSensorCapability = {
28830
28930
  schema: AmbientLightSensorStatusSchema,
28831
28931
  kind: "push"
28832
28932
  },
28833
- runtimeState: AmbientLightSensorStatusSchema
28933
+ runtimeState: AmbientLightSensorStatusSchema,
28934
+ /**
28935
+ * Runtime-state durability: **restored** — as `numeric-sensor`.
28936
+ *
28937
+ * See `RuntimeStateDurability`. Enforced by
28938
+ * `scripts/check-runtime-state-durability.ts`.
28939
+ */
28940
+ durability: "restored",
28941
+ /** Clock fields: written, but excluded from the compare that decides
28942
+ * whether persisting is worth a SQLite commit. */
28943
+ volatileStateFields: ["lastFetchedAt"]
28834
28944
  };
28835
28945
  var AudioClassSummarySchema = external_exports.object({
28836
28946
  className: external_exports.string(),
@@ -28920,7 +29030,14 @@ var audioMetricsCapability = {
28920
29030
  }), AudioMetricsHistorySchema)
28921
29031
  },
28922
29032
  /** Reactive runtime-state mirror — live `device.state.audioMetrics.value`. */
28923
- runtimeState: AudioMetricsSnapshotSchema
29033
+ runtimeState: AudioMetricsSnapshotSchema,
29034
+ /**
29035
+ * 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.
29036
+ *
29037
+ * See `RuntimeStateDurability`. Enforced by
29038
+ * `scripts/check-runtime-state-durability.ts`.
29039
+ */
29040
+ durability: "session"
28924
29041
  };
28925
29042
  var AutomationControlStatusSchema = external_exports.object({
28926
29043
  /** Whether the automation is currently enabled. Disabled automations
@@ -28971,7 +29088,14 @@ var automationControlCapability = {
28971
29088
  * reads `enabled` (toggle) + `isRunning` (spinner) + `lastError`
28972
29089
  * (badge) directly.
28973
29090
  */
28974
- runtimeState: AutomationControlStatusSchema
29091
+ runtimeState: AutomationControlStatusSchema,
29092
+ /**
29093
+ * 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.
29094
+ *
29095
+ * See `RuntimeStateDurability`. Enforced by
29096
+ * `scripts/check-runtime-state-durability.ts`.
29097
+ */
29098
+ durability: "session"
28975
29099
  };
28976
29100
  var BatteryStatusSchema = external_exports.object({
28977
29101
  /** 0..100 inclusive. Firmware-reported. */
@@ -29072,7 +29196,17 @@ var batteryCapability = {
29072
29196
  * via `device.runtimeState.getCapState('battery')` regardless of
29073
29197
  * the underlying driver.
29074
29198
  */
29075
- runtimeState: BatteryStatusSchema
29199
+ runtimeState: BatteryStatusSchema,
29200
+ /**
29201
+ * 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.
29202
+ *
29203
+ * See `RuntimeStateDurability`. Enforced by
29204
+ * `scripts/check-runtime-state-durability.ts`.
29205
+ */
29206
+ durability: "restored",
29207
+ /** Clock fields: written, but excluded from the compare that decides
29208
+ * whether persisting is worth a SQLite commit. */
29209
+ volatileStateFields: ["lastUpdated"]
29076
29210
  };
29077
29211
  var BinaryStatusSchema = external_exports.object({
29078
29212
  on: external_exports.boolean(),
@@ -29090,7 +29224,17 @@ var binaryCapability = {
29090
29224
  schema: BinaryStatusSchema,
29091
29225
  kind: "push"
29092
29226
  },
29093
- runtimeState: BinaryStatusSchema
29227
+ runtimeState: BinaryStatusSchema,
29228
+ /**
29229
+ * Runtime-state durability: **restored** — transition-driven sensor state; the restored value gives the boot comparison.
29230
+ *
29231
+ * See `RuntimeStateDurability`. Enforced by
29232
+ * `scripts/check-runtime-state-durability.ts`.
29233
+ */
29234
+ durability: "restored",
29235
+ /** Clock fields: written, but excluded from the compare that decides
29236
+ * whether persisting is worth a SQLite commit. */
29237
+ volatileStateFields: ["lastChangedAt"]
29094
29238
  };
29095
29239
  var BrightnessStatusSchema = external_exports.object({
29096
29240
  /** Current level as 0..100 inclusive. Firmware-reported. */
@@ -29132,7 +29276,14 @@ var brightnessCapability = {
29132
29276
  * by the kernel. Read via `device.state.brightness.value` so UI
29133
29277
  * sliders surface the current level without polling the provider.
29134
29278
  */
29135
- runtimeState: BrightnessStatusSchema
29279
+ runtimeState: BrightnessStatusSchema,
29280
+ /**
29281
+ * Runtime-state durability: **session** — live lamp state, re-published by the provider on connect.
29282
+ *
29283
+ * See `RuntimeStateDurability`. Enforced by
29284
+ * `scripts/check-runtime-state-durability.ts`.
29285
+ */
29286
+ durability: "session"
29136
29287
  };
29137
29288
  var buttonCapability = {
29138
29289
  name: "button",
@@ -29212,7 +29363,17 @@ var carbonMonoxideCapability = {
29212
29363
  schema: CarbonMonoxideStatusSchema,
29213
29364
  kind: "push"
29214
29365
  },
29215
- runtimeState: CarbonMonoxideStatusSchema
29366
+ runtimeState: CarbonMonoxideStatusSchema,
29367
+ /**
29368
+ * Runtime-state durability: **restored** — as `smoke`.
29369
+ *
29370
+ * See `RuntimeStateDurability`. Enforced by
29371
+ * `scripts/check-runtime-state-durability.ts`.
29372
+ */
29373
+ durability: "restored",
29374
+ /** Clock fields: written, but excluded from the compare that decides
29375
+ * whether persisting is worth a SQLite commit. */
29376
+ volatileStateFields: ["lastChangedAt"]
29216
29377
  };
29217
29378
  var HvacModeSchema = external_exports.enum([
29218
29379
  "off",
@@ -29341,7 +29502,14 @@ var climateControlCapability = {
29341
29502
  * the full slice via `device.state.climate-control.value` and refresh
29342
29503
  * on every push without re-querying the provider.
29343
29504
  */
29344
- runtimeState: ClimateControlStatusSchema
29505
+ runtimeState: ClimateControlStatusSchema,
29506
+ /**
29507
+ * Runtime-state durability: **session** — as `brightness`; `currentTemp` moves continuously and is re-published on connect.
29508
+ *
29509
+ * See `RuntimeStateDurability`. Enforced by
29510
+ * `scripts/check-runtime-state-durability.ts`.
29511
+ */
29512
+ durability: "session"
29345
29513
  };
29346
29514
  var RgbTripletSchema = external_exports.object({
29347
29515
  r: external_exports.number().int().min(0).max(255),
@@ -29428,7 +29596,14 @@ var colorCapability = {
29428
29596
  * kernel. Read via `device.state.color.value` so UI pickers surface
29429
29597
  * the current chromaticity without polling the provider.
29430
29598
  */
29431
- runtimeState: ColorStatusSchema
29599
+ runtimeState: ColorStatusSchema,
29600
+ /**
29601
+ * Runtime-state durability: **session** — as `brightness`.
29602
+ *
29603
+ * See `RuntimeStateDurability`. Enforced by
29604
+ * `scripts/check-runtime-state-durability.ts`.
29605
+ */
29606
+ durability: "session"
29432
29607
  };
29433
29608
  var ConnectionTestOutcomeSchema = external_exports.discriminatedUnion("outcome", [
29434
29609
  external_exports.object({
@@ -29482,7 +29657,17 @@ var connectivityCapability = {
29482
29657
  schema: ConnectivityStatusSchema,
29483
29658
  kind: "push"
29484
29659
  },
29485
- runtimeState: ConnectivityStatusSchema
29660
+ runtimeState: ConnectivityStatusSchema,
29661
+ /**
29662
+ * Runtime-state durability: **restored** — same shape and same argument as `device-status`, for links rather than devices.
29663
+ *
29664
+ * See `RuntimeStateDurability`. Enforced by
29665
+ * `scripts/check-runtime-state-durability.ts`.
29666
+ */
29667
+ durability: "restored",
29668
+ /** Clock fields: written, but excluded from the compare that decides
29669
+ * whether persisting is worth a SQLite commit. */
29670
+ volatileStateFields: ["lastChangedAt"]
29486
29671
  };
29487
29672
  var ConsumableItemSchema = external_exports.object({
29488
29673
  /** Stable id, e.g. 'main-brush'. */
@@ -29549,7 +29734,14 @@ var consumablesCapability = {
29549
29734
  }
29550
29735
  }
29551
29736
  },
29552
- runtimeState: ConsumablesStatusSchema.extend({ lastFetchedAt: external_exports.number() })
29737
+ runtimeState: ConsumablesStatusSchema.extend({ lastFetchedAt: external_exports.number() }),
29738
+ /**
29739
+ * Runtime-state durability: **session** — the authority is the appliance; the provider re-reads the whole item array on connect.
29740
+ *
29741
+ * See `RuntimeStateDurability`. Enforced by
29742
+ * `scripts/check-runtime-state-durability.ts`.
29743
+ */
29744
+ durability: "session"
29553
29745
  };
29554
29746
  var ContactStatusSchema = external_exports.object({
29555
29747
  /** True when the entry is open; false when closed. */
@@ -29568,7 +29760,17 @@ var contactCapability = {
29568
29760
  schema: ContactStatusSchema,
29569
29761
  kind: "push"
29570
29762
  },
29571
- runtimeState: ContactStatusSchema
29763
+ runtimeState: ContactStatusSchema,
29764
+ /**
29765
+ * Runtime-state durability: **restored** — a door left open across a restart must still read open.
29766
+ *
29767
+ * See `RuntimeStateDurability`. Enforced by
29768
+ * `scripts/check-runtime-state-durability.ts`.
29769
+ */
29770
+ durability: "restored",
29771
+ /** Clock fields: written, but excluded from the compare that decides
29772
+ * whether persisting is worth a SQLite commit. */
29773
+ volatileStateFields: ["lastChangedAt"]
29572
29774
  };
29573
29775
  var ControlKindSchema = external_exports.enum([
29574
29776
  "numeric",
@@ -29655,7 +29857,14 @@ var controlCapability = {
29655
29857
  * dropdown / text field / date picker) read the slice's discriminant
29656
29858
  * and value directly without polling the provider.
29657
29859
  */
29658
- runtimeState: ControlStatusSchema
29860
+ runtimeState: ControlStatusSchema,
29861
+ /**
29862
+ * Runtime-state durability: **session** — a generic control mirrors an external entity that re-publishes on connect; the options array is re-derived with it.
29863
+ *
29864
+ * See `RuntimeStateDurability`. Enforced by
29865
+ * `scripts/check-runtime-state-durability.ts`.
29866
+ */
29867
+ durability: "session"
29659
29868
  };
29660
29869
  var CoverStateSchema = external_exports.enum([
29661
29870
  "open",
@@ -29717,7 +29926,17 @@ var coverCapability = {
29717
29926
  * Runtime-state slice — mirrored by the kernel. UI controls watch
29718
29927
  * the slice for live position changes during a move.
29719
29928
  */
29720
- runtimeState: CoverStatusSchema
29929
+ runtimeState: CoverStatusSchema,
29930
+ /**
29931
+ * Runtime-state durability: **restored** — position survives a restart on the device; the mirror should agree at boot rather than read blank.
29932
+ *
29933
+ * See `RuntimeStateDurability`. Enforced by
29934
+ * `scripts/check-runtime-state-durability.ts`.
29935
+ */
29936
+ durability: "restored",
29937
+ /** Clock fields: written, but excluded from the compare that decides
29938
+ * whether persisting is worth a SQLite commit. */
29939
+ volatileStateFields: ["lastChangedAt"]
29721
29940
  };
29722
29941
  var DayNightModeSchema = external_exports.enum([
29723
29942
  "auto",
@@ -29778,7 +29997,17 @@ var dayNightCapability = {
29778
29997
  schema: DayNightStatusSchema,
29779
29998
  kind: "poll"
29780
29999
  },
29781
- runtimeState: DayNightStatusSchema
30000
+ runtimeState: DayNightStatusSchema,
30001
+ /**
30002
+ * Runtime-state durability: **restored** — operator-set IR-cut behaviour; mutation-driven.
30003
+ *
30004
+ * See `RuntimeStateDurability`. Enforced by
30005
+ * `scripts/check-runtime-state-durability.ts`.
30006
+ */
30007
+ durability: "restored",
30008
+ /** Clock fields: written, but excluded from the compare that decides
30009
+ * whether persisting is worth a SQLite commit. */
30010
+ volatileStateFields: ["lastFetchedAt"]
29782
30011
  };
29783
30012
  var DeviceStatusSchema = external_exports.object({
29784
30013
  /**
@@ -29811,7 +30040,17 @@ var deviceStatusCapability = {
29811
30040
  schema: DeviceStatusSchema,
29812
30041
  kind: "push"
29813
30042
  },
29814
- runtimeState: DeviceStatusSchema
30043
+ runtimeState: DeviceStatusSchema,
30044
+ /**
30045
+ * 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.
30046
+ *
30047
+ * See `RuntimeStateDurability`. Enforced by
30048
+ * `scripts/check-runtime-state-durability.ts`.
30049
+ */
30050
+ durability: "restored",
30051
+ /** Clock fields: written, but excluded from the compare that decides
30052
+ * whether persisting is worth a SQLite commit. */
30053
+ volatileStateFields: ["lastChangedAt"]
29815
30054
  };
29816
30055
  var DoorbellStatusSchema = external_exports.object({
29817
30056
  /** Ms epoch of the last press. null = never observed since this provider started. */
@@ -29851,7 +30090,14 @@ var doorbellCapability = {
29851
30090
  * `device.state.doorbell.value`. UIs can show "last ring 5m ago"
29852
30091
  * without subscribing.
29853
30092
  */
29854
- runtimeState: DoorbellStatusSchema
30093
+ runtimeState: DoorbellStatusSchema,
30094
+ /**
30095
+ * 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.
30096
+ *
30097
+ * See `RuntimeStateDurability`. Enforced by
30098
+ * `scripts/check-runtime-state-durability.ts`.
30099
+ */
30100
+ durability: "restored"
29855
30101
  };
29856
30102
  var EnumSensorDateTimeFormatSchema = external_exports.enum([
29857
30103
  "date",
@@ -29881,7 +30127,17 @@ var enumSensorCapability = {
29881
30127
  schema: EnumSensorStatusSchema,
29882
30128
  kind: "push"
29883
30129
  },
29884
- runtimeState: EnumSensorStatusSchema
30130
+ runtimeState: EnumSensorStatusSchema,
30131
+ /**
30132
+ * Runtime-state durability: **restored** — as `numeric-sensor`; 80 devices.
30133
+ *
30134
+ * See `RuntimeStateDurability`. Enforced by
30135
+ * `scripts/check-runtime-state-durability.ts`.
30136
+ */
30137
+ durability: "restored",
30138
+ /** Clock fields: written, but excluded from the compare that decides
30139
+ * whether persisting is worth a SQLite commit. */
30140
+ volatileStateFields: ["lastFetchedAt"]
29885
30141
  };
29886
30142
  var EventFireSchema = external_exports.object({
29887
30143
  deviceId: external_exports.number(),
@@ -29907,7 +30163,14 @@ var eventEmitterCapability = {
29907
30163
  schema: EventEmitterStatusSchema,
29908
30164
  kind: "push"
29909
30165
  },
29910
- runtimeState: EventEmitterStatusSchema
30166
+ runtimeState: EventEmitterStatusSchema,
30167
+ /**
30168
+ * Runtime-state durability: **session** — `eventCountSinceStart` names its own scope.
30169
+ *
30170
+ * See `RuntimeStateDurability`. Enforced by
30171
+ * `scripts/check-runtime-state-durability.ts`.
30172
+ */
30173
+ durability: "session"
29911
30174
  };
29912
30175
  var EventItemSchema = external_exports.object({
29913
30176
  id: external_exports.string(),
@@ -30206,7 +30469,14 @@ var fanControlCapability = {
30206
30469
  * Runtime-state slice — mirrored by the kernel. UI fan speed
30207
30470
  * sliders read `percentage` for live updates.
30208
30471
  */
30209
- runtimeState: FanControlStatusSchema
30472
+ runtimeState: FanControlStatusSchema,
30473
+ /**
30474
+ * Runtime-state durability: **session** — as `brightness`.
30475
+ *
30476
+ * See `RuntimeStateDurability`. Enforced by
30477
+ * `scripts/check-runtime-state-durability.ts`.
30478
+ */
30479
+ durability: "session"
30210
30480
  };
30211
30481
  var FeatureProbeStatusSchema = external_exports.object({
30212
30482
  /**
@@ -30259,7 +30529,14 @@ var featureProbeCapability = {
30259
30529
  schema: FeatureProbeStatusSchema,
30260
30530
  kind: "push"
30261
30531
  },
30262
- runtimeState: FeatureProbeStatusSchema
30532
+ runtimeState: FeatureProbeStatusSchema,
30533
+ /**
30534
+ * 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.
30535
+ *
30536
+ * See `RuntimeStateDurability`. Enforced by
30537
+ * `scripts/check-runtime-state-durability.ts`.
30538
+ */
30539
+ durability: "session"
30263
30540
  };
30264
30541
  var FloodStatusSchema = external_exports.object({
30265
30542
  /** True when leak is currently detected. */
@@ -30278,7 +30555,17 @@ var floodCapability = {
30278
30555
  schema: FloodStatusSchema,
30279
30556
  kind: "push"
30280
30557
  },
30281
- runtimeState: FloodStatusSchema
30558
+ runtimeState: FloodStatusSchema,
30559
+ /**
30560
+ * Runtime-state durability: **restored** — as `smoke`.
30561
+ *
30562
+ * See `RuntimeStateDurability`. Enforced by
30563
+ * `scripts/check-runtime-state-durability.ts`.
30564
+ */
30565
+ durability: "restored",
30566
+ /** Clock fields: written, but excluded from the compare that decides
30567
+ * whether persisting is worth a SQLite commit. */
30568
+ volatileStateFields: ["lastChangedAt"]
30282
30569
  };
30283
30570
  var GasStatusSchema = external_exports.object({
30284
30571
  detected: external_exports.boolean(),
@@ -30296,7 +30583,17 @@ var gasCapability = {
30296
30583
  schema: GasStatusSchema,
30297
30584
  kind: "push"
30298
30585
  },
30299
- runtimeState: GasStatusSchema
30586
+ runtimeState: GasStatusSchema,
30587
+ /**
30588
+ * Runtime-state durability: **restored** — as `smoke`.
30589
+ *
30590
+ * See `RuntimeStateDurability`. Enforced by
30591
+ * `scripts/check-runtime-state-durability.ts`.
30592
+ */
30593
+ durability: "restored",
30594
+ /** Clock fields: written, but excluded from the compare that decides
30595
+ * whether persisting is worth a SQLite commit. */
30596
+ volatileStateFields: ["lastChangedAt"]
30300
30597
  };
30301
30598
  var HumidifierStatusSchema = external_exports.object({
30302
30599
  /** Whether the humidifier is currently on. */
@@ -30357,7 +30654,14 @@ var humidifierCapability = {
30357
30654
  * Runtime-state slice — mirrored by the kernel. UI controls watch the
30358
30655
  * slice for live humidity / mode changes.
30359
30656
  */
30360
- runtimeState: HumidifierStatusSchema
30657
+ runtimeState: HumidifierStatusSchema,
30658
+ /**
30659
+ * Runtime-state durability: **session** — as `climate-control`.
30660
+ *
30661
+ * See `RuntimeStateDurability`. Enforced by
30662
+ * `scripts/check-runtime-state-durability.ts`.
30663
+ */
30664
+ durability: "session"
30361
30665
  };
30362
30666
  var HumiditySensorStatusSchema = external_exports.object({
30363
30667
  /** Current relative humidity, 0..100. */
@@ -30385,7 +30689,17 @@ var humiditySensorCapability = {
30385
30689
  schema: HumiditySensorStatusSchema,
30386
30690
  kind: "push"
30387
30691
  },
30388
- runtimeState: HumiditySensorStatusSchema
30692
+ runtimeState: HumiditySensorStatusSchema,
30693
+ /**
30694
+ * Runtime-state durability: **restored** — as `numeric-sensor` (67 of 75 writes were the clock alone).
30695
+ *
30696
+ * See `RuntimeStateDurability`. Enforced by
30697
+ * `scripts/check-runtime-state-durability.ts`.
30698
+ */
30699
+ durability: "restored",
30700
+ /** Clock fields: written, but excluded from the compare that decides
30701
+ * whether persisting is worth a SQLite commit. */
30702
+ volatileStateFields: ["lastFetchedAt"]
30389
30703
  };
30390
30704
  var ImageStatusSchema = external_exports.object({
30391
30705
  /** Absolute signed URL the browser loads directly. Null when the
@@ -30409,7 +30723,14 @@ var imageCapability = {
30409
30723
  * Runtime-state slice — mirrored by the kernel. The UI reads `url`
30410
30724
  * directly and renders the still image.
30411
30725
  */
30412
- runtimeState: ImageStatusSchema
30726
+ runtimeState: ImageStatusSchema,
30727
+ /**
30728
+ * Runtime-state durability: **session** — a snapshot URL is a session-scoped handle; a restored one points at nothing.
30729
+ *
30730
+ * See `RuntimeStateDurability`. Enforced by
30731
+ * `scripts/check-runtime-state-durability.ts`.
30732
+ */
30733
+ durability: "session"
30413
30734
  };
30414
30735
  var ImageRotateSchema = external_exports.enum([
30415
30736
  "0",
@@ -30510,7 +30831,17 @@ var imageSettingsCapability = {
30510
30831
  schema: ImageSettingsStatusSchema,
30511
30832
  kind: "poll"
30512
30833
  },
30513
- runtimeState: ImageSettingsStatusSchema
30834
+ runtimeState: ImageSettingsStatusSchema,
30835
+ /**
30836
+ * Runtime-state durability: **restored** — operator-set camera imaging; mutation-driven.
30837
+ *
30838
+ * See `RuntimeStateDurability`. Enforced by
30839
+ * `scripts/check-runtime-state-durability.ts`.
30840
+ */
30841
+ durability: "restored",
30842
+ /** Clock fields: written, but excluded from the compare that decides
30843
+ * whether persisting is worth a SQLite commit. */
30844
+ volatileStateFields: ["lastFetchedAt"]
30514
30845
  };
30515
30846
  var IntegrationWithStateSchema = external_exports.object({
30516
30847
  id: external_exports.string(),
@@ -30841,7 +31172,14 @@ var lawnMowerControlCapability = {
30841
31172
  * Runtime-state slice — mirrored by the kernel. UI controls watch the
30842
31173
  * slice for live activity + battery changes.
30843
31174
  */
30844
- runtimeState: LawnMowerControlStatusSchema
31175
+ runtimeState: LawnMowerControlStatusSchema,
31176
+ /**
31177
+ * Runtime-state durability: **session** — as `vacuum-control`.
31178
+ *
31179
+ * See `RuntimeStateDurability`. Enforced by
31180
+ * `scripts/check-runtime-state-durability.ts`.
31181
+ */
31182
+ durability: "session"
30845
31183
  };
30846
31184
  var InterfaceKindEnum = external_exports.enum([
30847
31185
  "lan",
@@ -31090,7 +31428,17 @@ var lockControlCapability = {
31090
31428
  * read `state` and disable themselves during `locking`/`unlocking`
31091
31429
  * transitions.
31092
31430
  */
31093
- runtimeState: LockControlStatusSchema
31431
+ runtimeState: LockControlStatusSchema,
31432
+ /**
31433
+ * Runtime-state durability: **restored** — a lock left locked must still read locked.
31434
+ *
31435
+ * See `RuntimeStateDurability`. Enforced by
31436
+ * `scripts/check-runtime-state-durability.ts`.
31437
+ */
31438
+ durability: "restored",
31439
+ /** Clock fields: written, but excluded from the compare that decides
31440
+ * whether persisting is worth a SQLite commit. */
31441
+ volatileStateFields: ["lastChangedAt"]
31094
31442
  };
31095
31443
  var MediaPlayerStateSchema = external_exports.enum([
31096
31444
  "off",
@@ -31240,7 +31588,14 @@ var mediaPlayerCapability = {
31240
31588
  * full slice for live now-playing, volume, and progress updates
31241
31589
  * without polling.
31242
31590
  */
31243
- runtimeState: MediaPlayerStatusSchema
31591
+ runtimeState: MediaPlayerStatusSchema,
31592
+ /**
31593
+ * Runtime-state durability: **session** — a restored transport position describes a playback that stopped when the hub did.
31594
+ *
31595
+ * See `RuntimeStateDurability`. Enforced by
31596
+ * `scripts/check-runtime-state-durability.ts`.
31597
+ */
31598
+ durability: "session"
31244
31599
  };
31245
31600
  var MeshEndpointSchema = external_exports.object({
31246
31601
  /** Stable identifier within the provider (e.g. `mesh-ipv4`, `magicdns`, `funnel`). */
@@ -31524,7 +31879,14 @@ var motionCapability = {
31524
31879
  * `device.state.motion.value`. Reads never invoke the provider, so
31525
31880
  * UIs and other addons can poll the cached state safely.
31526
31881
  */
31527
- runtimeState: MotionStatusSchema
31882
+ runtimeState: MotionStatusSchema,
31883
+ /**
31884
+ * 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.
31885
+ *
31886
+ * See `RuntimeStateDurability`. Enforced by
31887
+ * `scripts/check-runtime-state-durability.ts`.
31888
+ */
31889
+ durability: "session"
31528
31890
  };
31529
31891
  var MotionTriggerStatusSchema = external_exports.object({
31530
31892
  enabled: external_exports.boolean(),
@@ -31561,7 +31923,14 @@ var motionTriggerCapability = {
31561
31923
  schema: MotionTriggerStatusSchema,
31562
31924
  kind: "command-driven"
31563
31925
  },
31564
- runtimeState: MotionTriggerRuntimeStateSchema
31926
+ runtimeState: MotionTriggerRuntimeStateSchema,
31927
+ /**
31928
+ * 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.
31929
+ *
31930
+ * See `RuntimeStateDurability`. Enforced by
31931
+ * `scripts/check-runtime-state-durability.ts`.
31932
+ */
31933
+ durability: "session"
31565
31934
  };
31566
31935
  var MotionZoneRegionSchema = external_exports.object({
31567
31936
  id: external_exports.number(),
@@ -31616,7 +31985,17 @@ var motionZonesCapability = {
31616
31985
  schema: MotionZoneStatusSchema,
31617
31986
  kind: "poll"
31618
31987
  },
31619
- runtimeState: MotionZoneStatusSchema
31988
+ runtimeState: MotionZoneStatusSchema,
31989
+ /**
31990
+ * 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.
31991
+ *
31992
+ * See `RuntimeStateDurability`. Enforced by
31993
+ * `scripts/check-runtime-state-durability.ts`.
31994
+ */
31995
+ durability: "restored",
31996
+ /** Clock fields: written, but excluded from the compare that decides
31997
+ * whether persisting is worth a SQLite commit. */
31998
+ volatileStateFields: ["lastFetchedAt"]
31620
31999
  };
31621
32000
  var NativeObjectClassEnum = external_exports.enum([
31622
32001
  "person",
@@ -31679,7 +32058,17 @@ var nativeObjectDetectionCapability = {
31679
32058
  schema: NativeObjectDetectionStatusSchema,
31680
32059
  kind: "push"
31681
32060
  },
31682
- runtimeState: NativeObjectDetectionRuntimeStateSchema
32061
+ runtimeState: NativeObjectDetectionRuntimeStateSchema,
32062
+ /**
32063
+ * 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.
32064
+ *
32065
+ * See `RuntimeStateDurability`. Enforced by
32066
+ * `scripts/check-runtime-state-durability.ts`.
32067
+ */
32068
+ durability: "restored",
32069
+ /** Clock fields: written, but excluded from the compare that decides
32070
+ * whether persisting is worth a SQLite commit. */
32071
+ volatileStateFields: ["lastFetchedAt"]
31683
32072
  };
31684
32073
  var StreamNetworkStatsSchema = external_exports.object({
31685
32074
  nominalBitrateKbps: external_exports.number(),
@@ -32002,7 +32391,14 @@ var notifierCapability = {
32002
32391
  * form reads `supports` to gate optional fields; history pane reads
32003
32392
  * `lastSentAt` / `lastError` / `queueDepth`.
32004
32393
  */
32005
- runtimeState: NotifierStatusSchema
32394
+ runtimeState: NotifierStatusSchema,
32395
+ /**
32396
+ * Runtime-state durability: **session** — live queue depth and last-send state; a restored queue depth describes a queue that no longer exists.
32397
+ *
32398
+ * See `RuntimeStateDurability`. Enforced by
32399
+ * `scripts/check-runtime-state-durability.ts`.
32400
+ */
32401
+ durability: "session"
32006
32402
  };
32007
32403
  var NumericSensorStatusSchema = external_exports.object({
32008
32404
  value: external_exports.number(),
@@ -32028,7 +32424,17 @@ var numericSensorCapability = {
32028
32424
  schema: NumericSensorStatusSchema,
32029
32425
  kind: "push"
32030
32426
  },
32031
- runtimeState: NumericSensorStatusSchema
32427
+ runtimeState: NumericSensorStatusSchema,
32428
+ /**
32429
+ * 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.
32430
+ *
32431
+ * See `RuntimeStateDurability`. Enforced by
32432
+ * `scripts/check-runtime-state-durability.ts`.
32433
+ */
32434
+ durability: "restored",
32435
+ /** Clock fields: written, but excluded from the compare that decides
32436
+ * whether persisting is worth a SQLite commit. */
32437
+ volatileStateFields: ["lastFetchedAt"]
32032
32438
  };
32033
32439
  var OsdOverlayKindEnum = external_exports.enum([
32034
32440
  "text",
@@ -32451,7 +32857,14 @@ var petFeederCapability = {
32451
32857
  * the full slice via `device.state.petFeeder.value` and refresh on
32452
32858
  * every poll without re-querying the provider.
32453
32859
  */
32454
- runtimeState: PetFeederStatusSchema
32860
+ runtimeState: PetFeederStatusSchema,
32861
+ /**
32862
+ * Runtime-state durability: **session** — live appliance state re-published on connect.
32863
+ *
32864
+ * See `RuntimeStateDurability`. Enforced by
32865
+ * `scripts/check-runtime-state-durability.ts`.
32866
+ */
32867
+ durability: "session"
32455
32868
  };
32456
32869
  var VehicleSchema = external_exports.object({
32457
32870
  id: external_exports.string(),
@@ -32785,7 +33198,17 @@ var powerMeterCapability = {
32785
33198
  schema: PowerMeterStatusSchema,
32786
33199
  kind: "push"
32787
33200
  },
32788
- runtimeState: PowerMeterStatusSchema
33201
+ runtimeState: PowerMeterStatusSchema,
33202
+ /**
33203
+ * Runtime-state durability: **restored** — as `numeric-sensor`; `kwhTotal` is an accumulator whose restored value is the baseline.
33204
+ *
33205
+ * See `RuntimeStateDurability`. Enforced by
33206
+ * `scripts/check-runtime-state-durability.ts`.
33207
+ */
33208
+ durability: "restored",
33209
+ /** Clock fields: written, but excluded from the compare that decides
33210
+ * whether persisting is worth a SQLite commit. */
33211
+ volatileStateFields: ["lastFetchedAt"]
32789
33212
  };
32790
33213
  var GpsLocationSchema = external_exports.object({
32791
33214
  /** Latitude in decimal degrees, -90..90. */
@@ -32826,7 +33249,17 @@ var presenceCapability = {
32826
33249
  * the map pin is rendered (use `DeviceFeature.PresenceGps` for the
32827
33250
  * pre-fetch fast-path check).
32828
33251
  */
32829
- runtimeState: PresenceStatusSchema
33252
+ runtimeState: PresenceStatusSchema,
33253
+ /**
33254
+ * Runtime-state durability: **restored** — occupancy-relevant: the restored state is what an occupancy rule compares the first post-restart observation against.
33255
+ *
33256
+ * See `RuntimeStateDurability`. Enforced by
33257
+ * `scripts/check-runtime-state-durability.ts`.
33258
+ */
33259
+ durability: "restored",
33260
+ /** Clock fields: written, but excluded from the compare that decides
33261
+ * whether persisting is worth a SQLite commit. */
33262
+ volatileStateFields: ["lastChangedAt"]
32830
33263
  };
32831
33264
  var PressureSensorStatusSchema = external_exports.object({
32832
33265
  /** Current pressure in hPa. */
@@ -32854,7 +33287,17 @@ var pressureSensorCapability = {
32854
33287
  schema: PressureSensorStatusSchema,
32855
33288
  kind: "push"
32856
33289
  },
32857
- runtimeState: PressureSensorStatusSchema
33290
+ runtimeState: PressureSensorStatusSchema,
33291
+ /**
33292
+ * Runtime-state durability: **restored** — as `numeric-sensor`.
33293
+ *
33294
+ * See `RuntimeStateDurability`. Enforced by
33295
+ * `scripts/check-runtime-state-durability.ts`.
33296
+ */
33297
+ durability: "restored",
33298
+ /** Clock fields: written, but excluded from the compare that decides
33299
+ * whether persisting is worth a SQLite commit. */
33300
+ volatileStateFields: ["lastFetchedAt"]
32858
33301
  };
32859
33302
  var PrivacyMaskShapeSchema = external_exports.discriminatedUnion("kind", [MaskRectShapeSchema, MaskPolygonShapeSchema]);
32860
33303
  var PrivacyMaskRegionSchema = external_exports.object({
@@ -32953,7 +33396,17 @@ var privacyMaskCapability = {
32953
33396
  schema: PrivacyMaskStatusSchema,
32954
33397
  kind: "poll"
32955
33398
  },
32956
- runtimeState: PrivacyMaskStatusSchema
33399
+ runtimeState: PrivacyMaskStatusSchema,
33400
+ /**
33401
+ * Runtime-state durability: **restored** — operator-drawn regions, zero real churn — 22 writes in 25 minutes, every one of them the clock.
33402
+ *
33403
+ * See `RuntimeStateDurability`. Enforced by
33404
+ * `scripts/check-runtime-state-durability.ts`.
33405
+ */
33406
+ durability: "restored",
33407
+ /** Clock fields: written, but excluded from the compare that decides
33408
+ * whether persisting is worth a SQLite commit. */
33409
+ volatileStateFields: ["lastFetchedAt"]
32957
33410
  };
32958
33411
  var PtzPresetSchema = external_exports.object({
32959
33412
  id: external_exports.string(),
@@ -33139,7 +33592,14 @@ var ptzAutotrackCapability = {
33139
33592
  * fetch / cache / fallback logic out of the four cap methods —
33140
33593
  * they become trampolines over `runtimeState`.
33141
33594
  */
33142
- runtimeState: PtzAutotrackRuntimeStateSchema
33595
+ runtimeState: PtzAutotrackRuntimeStateSchema,
33596
+ /**
33597
+ * Runtime-state durability: **session** — mirrors the camera's own autotrack config, re-read on connect.
33598
+ *
33599
+ * See `RuntimeStateDurability`. Enforced by
33600
+ * `scripts/check-runtime-state-durability.ts`.
33601
+ */
33602
+ durability: "session"
33143
33603
  };
33144
33604
  var rebootCapability = {
33145
33605
  name: "reboot",
@@ -33808,7 +34268,14 @@ var sceneMonitorCapability = {
33808
34268
  schema: SceneMonitorStatusSchema,
33809
34269
  kind: "push"
33810
34270
  },
33811
- runtimeState: SceneMonitorStatusSchema
34271
+ runtimeState: SceneMonitorStatusSchema,
34272
+ /**
34273
+ * Runtime-state durability: **session** — re-derived from the current scene on the next evaluation.
34274
+ *
34275
+ * See `RuntimeStateDurability`. Enforced by
34276
+ * `scripts/check-runtime-state-durability.ts`.
34277
+ */
34278
+ durability: "session"
33812
34279
  };
33813
34280
  var ZoneRuleModeEnum = external_exports.enum(["include", "exclude"]);
33814
34281
  var ZoneRuleSchema = external_exports.object({
@@ -33910,7 +34377,14 @@ var scriptRunnerCapability = {
33910
34377
  * `isRunning` to render a spinner during execution and surfaces
33911
34378
  * `lastError` / `lastRunSuccess` in the recent-runs panel.
33912
34379
  */
33913
- runtimeState: ScriptRunnerStatusSchema
34380
+ runtimeState: ScriptRunnerStatusSchema,
34381
+ /**
34382
+ * Runtime-state durability: **session** — a restored `isRunning: true` describes a process that died with the previous hub.
34383
+ *
34384
+ * See `RuntimeStateDurability`. Enforced by
34385
+ * `scripts/check-runtime-state-durability.ts`.
34386
+ */
34387
+ durability: "session"
33914
34388
  };
33915
34389
  var SmokeStatusSchema = external_exports.object({
33916
34390
  detected: external_exports.boolean(),
@@ -33928,7 +34402,17 @@ var smokeCapability = {
33928
34402
  schema: SmokeStatusSchema,
33929
34403
  kind: "push"
33930
34404
  },
33931
- runtimeState: SmokeStatusSchema
34405
+ runtimeState: SmokeStatusSchema,
34406
+ /**
34407
+ * Runtime-state durability: **restored** — a safety sensor must not read "clear" merely because the hub restarted.
34408
+ *
34409
+ * See `RuntimeStateDurability`. Enforced by
34410
+ * `scripts/check-runtime-state-durability.ts`.
34411
+ */
34412
+ durability: "restored",
34413
+ /** Clock fields: written, but excluded from the compare that decides
34414
+ * whether persisting is worth a SQLite commit. */
34415
+ volatileStateFields: ["lastChangedAt"]
33932
34416
  };
33933
34417
  var CamStreamDescriptorSchema = external_exports.object({
33934
34418
  camStreamId: external_exports.string().min(1),
@@ -34079,7 +34563,17 @@ var streamParamsCapability = {
34079
34563
  schema: StreamParamsStatusSchema,
34080
34564
  kind: "poll"
34081
34565
  },
34082
- runtimeState: StreamParamsStatusSchema
34566
+ runtimeState: StreamParamsStatusSchema,
34567
+ /**
34568
+ * Runtime-state durability: **restored** — operator-set encoder profile; mutation-driven.
34569
+ *
34570
+ * See `RuntimeStateDurability`. Enforced by
34571
+ * `scripts/check-runtime-state-durability.ts`.
34572
+ */
34573
+ durability: "restored",
34574
+ /** Clock fields: written, but excluded from the compare that decides
34575
+ * whether persisting is worth a SQLite commit. */
34576
+ volatileStateFields: ["lastFetchedAt"]
34083
34577
  };
34084
34578
  var SwitchStatusSchema = external_exports.object({
34085
34579
  on: external_exports.boolean(),
@@ -34118,6 +34612,16 @@ var switchCapability = {
34118
34612
  * not need to re-query the provider after a setState mutation.
34119
34613
  */
34120
34614
  runtimeState: SwitchStatusSchema,
34615
+ /**
34616
+ * Runtime-state durability: **restored** — device state an operator reads as authoritative; 55 devices, transition-driven.
34617
+ *
34618
+ * See `RuntimeStateDurability`. Enforced by
34619
+ * `scripts/check-runtime-state-durability.ts`.
34620
+ */
34621
+ durability: "restored",
34622
+ /** Clock fields: written, but excluded from the compare that decides
34623
+ * whether persisting is worth a SQLite commit. */
34624
+ volatileStateFields: ["lastChangedAt"],
34121
34625
  settings: { bindings: [{
34122
34626
  kind: "scalar",
34123
34627
  statusPath: "on",
@@ -34190,7 +34694,17 @@ var tamperCapability = {
34190
34694
  schema: TamperStatusSchema,
34191
34695
  kind: "push"
34192
34696
  },
34193
- runtimeState: TamperStatusSchema
34697
+ runtimeState: TamperStatusSchema,
34698
+ /**
34699
+ * Runtime-state durability: **restored** — as `smoke`.
34700
+ *
34701
+ * See `RuntimeStateDurability`. Enforced by
34702
+ * `scripts/check-runtime-state-durability.ts`.
34703
+ */
34704
+ durability: "restored",
34705
+ /** Clock fields: written, but excluded from the compare that decides
34706
+ * whether persisting is worth a SQLite commit. */
34707
+ volatileStateFields: ["lastChangedAt"]
34194
34708
  };
34195
34709
  var TemperatureSensorStatusSchema = external_exports.object({
34196
34710
  /** Current temperature in Celsius. */
@@ -34219,7 +34733,17 @@ var temperatureSensorCapability = {
34219
34733
  schema: TemperatureSensorStatusSchema,
34220
34734
  kind: "push"
34221
34735
  },
34222
- runtimeState: TemperatureSensorStatusSchema
34736
+ runtimeState: TemperatureSensorStatusSchema,
34737
+ /**
34738
+ * Runtime-state durability: **restored** — as `numeric-sensor` (69 of 125 writes were the clock alone).
34739
+ *
34740
+ * See `RuntimeStateDurability`. Enforced by
34741
+ * `scripts/check-runtime-state-durability.ts`.
34742
+ */
34743
+ durability: "restored",
34744
+ /** Clock fields: written, but excluded from the compare that decides
34745
+ * whether persisting is worth a SQLite commit. */
34746
+ volatileStateFields: ["lastFetchedAt"]
34223
34747
  };
34224
34748
  var ToastSchema = external_exports.object({
34225
34749
  title: external_exports.string(),
@@ -34270,7 +34794,14 @@ var updateCapability = {
34270
34794
  schema: UpdateStatusSchema,
34271
34795
  kind: "poll"
34272
34796
  },
34273
- runtimeState: UpdateStatusSchema
34797
+ runtimeState: UpdateStatusSchema,
34798
+ /**
34799
+ * Runtime-state durability: **session** — a restored `inProgress: true` describes an update that is no longer running; versions are re-probed at boot.
34800
+ *
34801
+ * See `RuntimeStateDurability`. Enforced by
34802
+ * `scripts/check-runtime-state-durability.ts`.
34803
+ */
34804
+ durability: "session"
34274
34805
  };
34275
34806
  var UserSummarySchema = external_exports.object({
34276
34807
  id: external_exports.string(),
@@ -34604,7 +35135,14 @@ var vacuumControlCapability = {
34604
35135
  * Runtime-state slice — mirrored by the kernel. UI controls watch the
34605
35136
  * slice for live state + battery + fan-speed changes.
34606
35137
  */
34607
- runtimeState: VacuumControlStatusSchema
35138
+ runtimeState: VacuumControlStatusSchema,
35139
+ /**
35140
+ * Runtime-state durability: **session** — as `media-player` — a restored `state: cleaning` is a robot that is not cleaning.
35141
+ *
35142
+ * See `RuntimeStateDurability`. Enforced by
35143
+ * `scripts/check-runtime-state-durability.ts`.
35144
+ */
35145
+ durability: "session"
34608
35146
  };
34609
35147
  var ValveStateSchema = external_exports.enum([
34610
35148
  "open",
@@ -34657,7 +35195,14 @@ var valveCapability = {
34657
35195
  * Runtime-state slice — mirrored by the kernel. UI controls watch the
34658
35196
  * slice for live position changes during a move.
34659
35197
  */
34660
- runtimeState: ValveStatusSchema
35198
+ runtimeState: ValveStatusSchema,
35199
+ /**
35200
+ * Runtime-state durability: **session** — as `brightness`.
35201
+ *
35202
+ * See `RuntimeStateDurability`. Enforced by
35203
+ * `scripts/check-runtime-state-durability.ts`.
35204
+ */
35205
+ durability: "session"
34661
35206
  };
34662
35207
  var VibrationStatusSchema = external_exports.object({
34663
35208
  detected: external_exports.boolean(),
@@ -34675,7 +35220,17 @@ var vibrationCapability = {
34675
35220
  schema: VibrationStatusSchema,
34676
35221
  kind: "push"
34677
35222
  },
34678
- runtimeState: VibrationStatusSchema
35223
+ runtimeState: VibrationStatusSchema,
35224
+ /**
35225
+ * Runtime-state durability: **restored** — as `smoke`.
35226
+ *
35227
+ * See `RuntimeStateDurability`. Enforced by
35228
+ * `scripts/check-runtime-state-durability.ts`.
35229
+ */
35230
+ durability: "restored",
35231
+ /** Clock fields: written, but excluded from the compare that decides
35232
+ * whether persisting is worth a SQLite commit. */
35233
+ volatileStateFields: ["lastChangedAt"]
34679
35234
  };
34680
35235
  var WaterHeaterStatusSchema = external_exports.object({
34681
35236
  /** Current measured temperature. Null when not reported. */
@@ -34735,7 +35290,14 @@ var waterHeaterCapability = {
34735
35290
  * Runtime-state slice — mirrored by the kernel. UI controls watch the
34736
35291
  * slice for live temperature / mode / away changes.
34737
35292
  */
34738
- runtimeState: WaterHeaterStatusSchema
35293
+ runtimeState: WaterHeaterStatusSchema,
35294
+ /**
35295
+ * Runtime-state durability: **session** — as `climate-control`.
35296
+ *
35297
+ * See `RuntimeStateDurability`. Enforced by
35298
+ * `scripts/check-runtime-state-durability.ts`.
35299
+ */
35300
+ durability: "session"
34739
35301
  };
34740
35302
  var WeatherStatusSchema = external_exports.object({
34741
35303
  /** Verbatim HA condition state (`sunny`, `cloudy`, `rainy`, …). Null
@@ -34775,7 +35337,14 @@ var weatherCapability = {
34775
35337
  * Runtime-state slice — mirrored by the kernel. The UI reads the
34776
35338
  * current conditions directly from the slice on each weather push.
34777
35339
  */
34778
- runtimeState: WeatherStatusSchema
35340
+ runtimeState: WeatherStatusSchema,
35341
+ /**
35342
+ * Runtime-state durability: **session** — a forecast is stale the moment the hub is down; the provider re-fetches on connect.
35343
+ *
35344
+ * See `RuntimeStateDurability`. Enforced by
35345
+ * `scripts/check-runtime-state-durability.ts`.
35346
+ */
35347
+ durability: "session"
34779
35348
  };
34780
35349
  var PerScopeBreakdownSchema = external_exports.object({
34781
35350
  /** Total tracked objects in this scope (frame / zone / unzoned). */
@@ -34884,7 +35453,14 @@ var zoneAnalyticsCapability = {
34884
35453
  * automatically; the explicit `getCurrentSnapshot` cap method is
34885
35454
  * still useful for one-off polls without a subscription.
34886
35455
  */
34887
- runtimeState: CameraOccupancySnapshotSchema
35456
+ runtimeState: CameraOccupancySnapshotSchema,
35457
+ /**
35458
+ * Runtime-state durability: **session** — per-frame analytics; with `audio-metrics` it is ~90 % of the offered write rate. Re-derived on the next frame.
35459
+ *
35460
+ * See `RuntimeStateDurability`. Enforced by
35461
+ * `scripts/check-runtime-state-durability.ts`.
35462
+ */
35463
+ durability: "session"
34888
35464
  };
34889
35465
  var ZoneRuleStageEnum = external_exports.enum([
34890
35466
  "motion",
@@ -34936,7 +35512,14 @@ var zoneRulesCapability = {
34936
35512
  motion: external_exports.array(ZoneRuleSchema).readonly(),
34937
35513
  detection: external_exports.array(ZoneRuleSchema).readonly(),
34938
35514
  package: external_exports.array(ZoneRuleSchema).readonly()
34939
- })
35515
+ }),
35516
+ /**
35517
+ * Runtime-state durability: **restored** — operator intent, mutation-only, same argument as `zones`.
35518
+ *
35519
+ * See `RuntimeStateDurability`. Enforced by
35520
+ * `scripts/check-runtime-state-durability.ts`.
35521
+ */
35522
+ durability: "restored"
34940
35523
  };
34941
35524
  var PIPELINE_FLOW_CAPABILITY_NAMES = [
34942
35525
  "decoder",
@@ -40626,6 +41209,7 @@ var CAP_PROVIDER_KIND_MAP = Object.freeze({
40626
41209
  "network-access": "ingress",
40627
41210
  "smtp-provider": "email"
40628
41211
  });
41212
+ var ICON_BY_ID = new Map(AUDIO_MACRO_LABELS.flatMap((macro2) => macro2.icon === void 0 ? [] : [[macro2.id, macro2.icon]]));
40629
41213
  var NC_BASE_CONDITION_KEYS = ["devices", "classes"];
40630
41214
  var BASE_CONDITION_SET = new Set(NC_BASE_CONDITION_KEYS);
40631
41215
  var TimelapseTemplateSchema = external_exports.object({
@@ -40771,25 +41355,32 @@ var DETAIL_CROP_PADDING_FIELD = {
40771
41355
  var NativeLeaseAdmissionSchema = external_exports.enum(["all", "inferred"]);
40772
41356
  var NativeLeaseSettingsSchema = external_exports.object({
40773
41357
  /**
40774
- * How long a retained native frame is served before it counts as a miss.
41358
+ * How many delivered frames the worker HOLDS at once, waiting for each one's
41359
+ * detection result.
41360
+ *
41361
+ * This replaced a TTL on 2026-08-13, and the replacement is the whole point:
41362
+ * a time window was never related to the event the pixels were waiting for.
41363
+ * A held frame now lives from delivery until the runner has its `FrameResult`
41364
+ * — at which moment the runner cuts the subject tiles it actually wanted and
41365
+ * releases the frame. The bound exists only so a runner that stops answering
41366
+ * cannot pin RAM: above it the OLDEST held frame is dropped and counted.
40775
41367
  *
40776
- * Must cover the FULL late-crop horizon: detection inference + the
40777
- * cross-process inference-result hop to hub post-analysis + tracking + the
40778
- * tRPC crop round-trip back. Below ~500 ms the busiest cameras' subject crops
40779
- * outrun it and fall back to the ≤640 detection frame; above ~3 s the resident
40780
- * RAM per busy camera grows linearly with no measured hit-rate gain.
41368
+ * Sizing: the steady state is `inferenceLatency × deliveredFps`, measured at
41369
+ * 40-160 ms × ≤25 fps = 1-4 frames. The default leaves headroom for a hiccup
41370
+ * without ever approaching the old resident set (43 frames × 24.9 MB at 4K).
41371
+ * Raising it does not buy hit rate it buys tolerance for a slow runner, and
41372
+ * `holdOverflow` on the metrics line is what says you need it.
40781
41373
  */
40782
- ttlMs: external_exports.number().int().min(250).max(1e4),
41374
+ holdFrames: external_exports.number().int().min(1).max(64),
40783
41375
  /**
40784
41376
  * Hard per-decode-worker RAM ceiling for retained native frames, in MB.
40785
41377
  *
40786
- * Intended as a SAFETY ceiling with the TTL as the effective cap — but check
40787
- * which one is actually binding before reasoning from that. At the shipped
40788
- * 1024 MB and a 2 800 ms TTL, a 4K camera hits the CEILING first (~43 frames
40789
- * at ~24 MB each) and the TTL never gets to expire anything; `leaseMb` /
40790
- * `leaseFrames` on the metrics line say which. When the ceiling binds, a
40791
- * change that admits fewer frames buys retention WINDOW at constant RAM
40792
- * rather than giving RAM back — lower this knob if RAM is what you wanted.
41378
+ * Since 2026-08-13 this is a SAFETY ceiling and nothing else: `holdFrames`
41379
+ * is what decides how much is held, and the ceiling is the number above which
41380
+ * something is wrong. Before that it was the effective cap at 1024 MB with
41381
+ * a 2 800 ms TTL a 4K camera sat pinned at `leaseMb:1020, leaseFrames:43`
41382
+ * with the TTL expiring nothing, which is exactly the confusion the hold
41383
+ * removes. `leaseMb` / `leaseFrames` still say what is resident.
40793
41384
  * `0` DISABLES the lease entirely and falls the worker back to the tiny
40794
41385
  * leak-prone GPU surface ring (~85% crop miss; that is what the lease exists
40795
41386
  * to replace).
@@ -40815,19 +41406,37 @@ var NativeLeaseSettingsSchema = external_exports.object({
40815
41406
  * there is the signal that some caller names frames outside the inference set
40816
41407
  * and that this must go back to `all`.
40817
41408
  */
40818
- admission: NativeLeaseAdmissionSchema
41409
+ admission: NativeLeaseAdmissionSchema,
41410
+ /**
41411
+ * RAM ceiling per decode worker, in MB, for the SUBJECT TILES — the
41412
+ * compressed native crops the worker cuts at the moment a frame's detection
41413
+ * result arrives, and keeps long after the frame itself is freed.
41414
+ *
41415
+ * This is the knob that replaced the old retention window, and it buys about
41416
+ * three orders of magnitude more of it: a tile is one subject at native
41417
+ * resolution, JPEG-encoded (~60-120 KB on a 4K person), against ~24.9 MB for
41418
+ * the frame it was cut from. A frame on which nothing was detected costs
41419
+ * nothing at all, which is the real change — the old lease paid per FRAME and
41420
+ * was interrogated per SUBJECT.
41421
+ *
41422
+ * `0` DISABLES tiles, leaving only the hold window and the ≤640 RAM
41423
+ * fallback — i.e. the pre-2026-08-13 miss profile. Set it there only to
41424
+ * reproduce that.
41425
+ */
41426
+ tileBudgetMb: external_exports.number().int().min(0).max(1024)
40819
41427
  });
40820
41428
  var DEFAULT_NATIVE_LEASE_SETTINGS = {
40821
- ttlMs: 1200,
41429
+ holdFrames: 8,
40822
41430
  budgetMb: 1024,
40823
41431
  activityMs: 15e3,
41432
+ tileBudgetMb: 64,
40824
41433
  admission: "inferred"
40825
41434
  };
40826
- var NATIVE_LEASE_TTL_FIELD = {
40827
- min: 250,
40828
- max: 1e4,
40829
- step: 50,
40830
- default: DEFAULT_NATIVE_LEASE_SETTINGS.ttlMs
41435
+ var NATIVE_LEASE_HOLD_FIELD = {
41436
+ min: 1,
41437
+ max: 64,
41438
+ step: 1,
41439
+ default: DEFAULT_NATIVE_LEASE_SETTINGS.holdFrames
40831
41440
  };
40832
41441
  var NATIVE_LEASE_BUDGET_FIELD = {
40833
41442
  min: 0,
@@ -40841,6 +41450,12 @@ var NATIVE_LEASE_ACTIVITY_FIELD = {
40841
41450
  step: 1e3,
40842
41451
  default: DEFAULT_NATIVE_LEASE_SETTINGS.activityMs
40843
41452
  };
41453
+ var NATIVE_LEASE_TILE_BUDGET_FIELD = {
41454
+ min: 0,
41455
+ max: 1024,
41456
+ step: 16,
41457
+ default: DEFAULT_NATIVE_LEASE_SETTINGS.tileBudgetMb
41458
+ };
40844
41459
  var NATIVE_LEASE_ADMISSION_FIELD = {
40845
41460
  options: [{
40846
41461
  value: "all",