@camstack/system 1.2.86 → 1.2.88

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  2. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  3. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  4. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  5. package/dist/builtins/alerts/alerts.addon.js +1 -1
  6. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  7. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
  8. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
  9. package/dist/builtins/console-logging/index.js +1 -1
  10. package/dist/builtins/console-logging/index.mjs +1 -1
  11. package/dist/builtins/core-blocks/core-blocks.addon.js +1 -1
  12. package/dist/builtins/core-blocks/core-blocks.addon.mjs +1 -1
  13. package/dist/builtins/device-manager/device-manager.addon.js +155 -18
  14. package/dist/builtins/device-manager/device-manager.addon.mjs +155 -18
  15. package/dist/builtins/device-manager/device-state-mirror.d.ts +51 -6
  16. package/dist/builtins/device-manager/runtime-state-persist-gate.d.ts +32 -0
  17. package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
  18. package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
  19. package/dist/builtins/hub-forwarder/index.js +1 -1
  20. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  21. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  22. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  23. package/dist/builtins/local-auth/local-auth.addon.js +1 -1
  24. package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
  25. package/dist/builtins/local-network/local-network.addon.js +1 -1
  26. package/dist/builtins/local-network/local-network.addon.mjs +1 -1
  27. package/dist/builtins/loki-logging/index.js +1 -1
  28. package/dist/builtins/loki-logging/index.mjs +1 -1
  29. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  30. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  31. package/dist/builtins/platform-probe/index.js +1 -1
  32. package/dist/builtins/platform-probe/index.mjs +1 -1
  33. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  34. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  35. package/dist/builtins/snapshot/index.js +1 -1
  36. package/dist/builtins/snapshot/index.mjs +1 -1
  37. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  38. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  39. package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +15 -0
  40. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +37 -1
  41. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +37 -1
  42. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
  43. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
  44. package/dist/builtins/system-config/system-config.addon.js +1 -1
  45. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  46. package/dist/builtins/winston-logging/index.js +1 -1
  47. package/dist/builtins/winston-logging/index.mjs +1 -1
  48. package/dist/{dist-BV5Bug9t.js → dist-B4WyhfjH.js} +1010 -90
  49. package/dist/{dist-B90N7AWO.mjs → dist-DlDY9mQO.mjs} +1005 -91
  50. package/dist/index.js +30 -4
  51. package/dist/index.mjs +30 -4
  52. package/dist/kernel/config-manager.d.ts +32 -0
  53. package/package.json +1 -1
@@ -2353,19 +2353,6 @@ function toNodeId(idOrRunnerId) {
2353
2353
  return head === void 0 || head.length === 0 ? idOrRunnerId : head;
2354
2354
  }
2355
2355
  /**
2356
- * Generic types for capability definitions.
2357
- *
2358
- * A capability is defined with Zod schemas for methods, events, and settings.
2359
- * TypeScript types are inferred via z.infer<> — zero duplication.
2360
- *
2361
- * Pattern:
2362
- * 1. Define Zod schemas for data, methods, settings
2363
- * 2. Export const capabilityDef = { ... } satisfies CapabilityDefinition
2364
- * 3. Export type IProvider = InferProvider<typeof capabilityDef>
2365
- * 4. Addon implements IProvider
2366
- * 5. Registry auto-mounts tRPC router from definition.methods
2367
- */
2368
- /**
2369
2356
  * Resolve the EFFECTIVE mount hint for a cap — the explicit `mount` when
2370
2357
  * present, else the scope/mode/deviceNative-derived default. Single source
2371
2358
  * of truth shared by the runtime builder and any codegen that needs the
@@ -7501,7 +7488,14 @@ var cameraStreamsCapability = {
7501
7488
  low: zod.z.string().optional()
7502
7489
  }),
7503
7490
  lastChangedAt: zod.z.number()
7504
- })
7491
+ }),
7492
+ /**
7493
+ * 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.
7494
+ *
7495
+ * See `RuntimeStateDurability`. Enforced by
7496
+ * `scripts/check-runtime-state-durability.ts`.
7497
+ */
7498
+ durability: "session"
7505
7499
  };
7506
7500
  /** `z.void()` — input carries no data. */
7507
7501
  function isVoidInput(schema) {
@@ -8494,6 +8488,13 @@ var deviceDiscoveryCapability = {
8494
8488
  kind: "poll"
8495
8489
  },
8496
8490
  runtimeState: DeviceDiscoveryStatusSchema.extend({ lastFetchedAt: zod.z.number().int().nonnegative() }),
8491
+ /**
8492
+ * Runtime-state durability: **session** — 5.7 KB of scan output on the largest device, fully re-derivable by re-scanning.
8493
+ *
8494
+ * See `RuntimeStateDurability`. Enforced by
8495
+ * `scripts/check-runtime-state-durability.ts`.
8496
+ */
8497
+ durability: "session",
8497
8498
  methods: {
8498
8499
  /**
8499
8500
  * Snapshot of the current `discovered` list. Returns the
@@ -11064,11 +11065,33 @@ var NotificationFormatSchema = zod.z.enum([
11064
11065
  * Named by INTENT, never by glyph. "check" would tie the vocabulary to one
11065
11066
  * renderer's icon set; "acknowledge" survives an adapter that draws it
11066
11067
  * differently.
11068
+ *
11069
+ * ── A TOKEN IS NOT A WIRE VALUE ─────────────────────────────────────
11070
+ *
11071
+ * These names are for US. **No adapter may forward one verbatim.** Each maps
11072
+ * the whole set onto its own renderer's vocabulary through a
11073
+ * `Record<NotificationActionIcon, string>` — a Record, never a lookup with a
11074
+ * fallback, so adding a member here fails every adapter's build until someone
11075
+ * decides its glyph, which is the only place that decision can be made
11076
+ * honestly.
11077
+ *
11078
+ * This paragraph is the bug. Zentik declared `actionIcons: true` and passed
11079
+ * `disarm` straight through; iOS feeds that string to
11080
+ * `UNNotificationActionIcon(systemImageName:)`, `disarm` is not an SF Symbol,
11081
+ * and every snooze and alarm button arrived BLANK. A pass-through is not a
11082
+ * mapping, and "the field is documented" is not "the value renders".
11083
+ *
11084
+ * Adding a member is TRAIN-BOUND. The enum lives in the published
11085
+ * `@camstack/server` closure and the cap seam validates against the HUB's copy,
11086
+ * so an addon that emits a token the running hub does not know does not lose an
11087
+ * icon — its whole `send` fails Zod validation and the notification never
11088
+ * arrives. Never emit a new token from an addon before the train carrying it.
11067
11089
  */
11068
11090
  var NotificationActionIconSchema = zod.z.enum([
11069
11091
  "acknowledge",
11070
11092
  "dismiss",
11071
11093
  "silence",
11094
+ "snooze",
11072
11095
  "view",
11073
11096
  "play",
11074
11097
  "open",
@@ -11076,9 +11099,13 @@ var NotificationActionIconSchema = zod.z.enum([
11076
11099
  "lock",
11077
11100
  "unlock",
11078
11101
  "arm",
11102
+ "arm-home",
11103
+ "arm-away",
11104
+ "arm-night",
11079
11105
  "disarm",
11080
11106
  "light",
11081
- "alert"
11107
+ "alert",
11108
+ "camera"
11082
11109
  ]);
11083
11110
  /** A single tap-through action button. */
11084
11111
  var NotificationActionSchema = zod.z.object({
@@ -11094,7 +11121,23 @@ var NotificationActionSchema = zod.z.object({
11094
11121
  * else — see `notification-center/action-token.ts` for what that does and
11095
11122
  * does not buy.
11096
11123
  */
11097
- destructive: zod.z.boolean().optional()
11124
+ destructive: zod.z.boolean().optional(),
11125
+ /**
11126
+ * How the tap should REACH the url.
11127
+ *
11128
+ * `navigate` (absent, and every button authored before this field) opens it:
11129
+ * the phone leaves the notification and shows whatever the callback returns.
11130
+ * That is right for a button whose answer the operator wants to read.
11131
+ *
11132
+ * `background` fires it as a POST and stays put. It exists for the buttons
11133
+ * whose whole point is not to interrupt — "silence this for 30 minutes" is
11134
+ * an answer to the notification, and being thrown into a browser tab to
11135
+ * confirm it costs more attention than the notification did. A backend that
11136
+ * cannot do a background call renders it as an ordinary link (the adapters
11137
+ * fall back rather than dropping the button), so this is a preference, never
11138
+ * a requirement.
11139
+ */
11140
+ mode: zod.z.enum(["navigate", "background"]).optional()
11098
11141
  });
11099
11142
  /**
11100
11143
  * The canonical notification. `body` is the only hard field (Apprise model).
@@ -11278,6 +11321,24 @@ var notificationOutputCapability = {
11278
11321
  }), zod.z.void(), { kind: "mutation" })
11279
11322
  }
11280
11323
  };
11324
+ new Set([
11325
+ {
11326
+ id: "person",
11327
+ name: "Person"
11328
+ },
11329
+ {
11330
+ id: "vehicle",
11331
+ name: "Vehicle"
11332
+ },
11333
+ {
11334
+ id: "animal",
11335
+ name: "Animal"
11336
+ },
11337
+ {
11338
+ id: "package",
11339
+ name: "Package"
11340
+ }
11341
+ ].map((l) => l.id));
11281
11342
  var COCO_TO_MACRO = {
11282
11343
  mapping: {
11283
11344
  person: "person",
@@ -11962,7 +12023,17 @@ var alarmPanelCapability = {
11962
12023
  * full slice; renders an arm button per `availableModes` entry and
11963
12024
  * a PIN field iff `requiresCode === true`.
11964
12025
  */
11965
- runtimeState: AlarmPanelStatusSchema
12026
+ runtimeState: AlarmPanelStatusSchema,
12027
+ /**
12028
+ * Runtime-state durability: **restored** — armed state is the one thing a panel must not lose across a restart.
12029
+ *
12030
+ * See `RuntimeStateDurability`. Enforced by
12031
+ * `scripts/check-runtime-state-durability.ts`.
12032
+ */
12033
+ durability: "restored",
12034
+ /** Clock fields: written, but excluded from the compare that decides
12035
+ * whether persisting is worth a SQLite commit. */
12036
+ volatileStateFields: ["lastChangedAt"]
11966
12037
  };
11967
12038
  /**
11968
12039
  * Shared geometry vocabulary for on-frame shape caps — privacy-mask,
@@ -12105,6 +12176,8 @@ var NcSystemEventKindSchema = zod.z.enum([
12105
12176
  "alarm-triggered",
12106
12177
  "alarm-armed",
12107
12178
  "alarm-disarmed",
12179
+ "alarm-arming",
12180
+ "alarm-arm-refused",
12108
12181
  "camera-online",
12109
12182
  "camera-offline",
12110
12183
  "camera-disabled",
@@ -12141,6 +12214,9 @@ var NcSystemEventConditionSchema = zod.z.object({
12141
12214
  nodeIds: zod.z.array(zod.z.string().min(1)).min(1).optional(),
12142
12215
  packageNames: zod.z.array(zod.z.string().min(1)).min(1).optional()
12143
12216
  });
12217
+ /** Hard ceiling on a window (24h). A snooze that could not expire would be an
12218
+ * outage the operator asked for once and forgot. */
12219
+ var NC_SNOOZE_MAX_MINUTES = 1440;
12144
12220
  /** One weekly activation window. `startMinute > endMinute` crosses midnight. */
12145
12221
  var NcScheduleWindowSchema = zod.z.object({
12146
12222
  /** Days of week the window STARTS on (0 = Sunday … 6 = Saturday). */
@@ -12530,15 +12606,15 @@ var NcConditionsSchema = zod.z.object({
12530
12606
  * (an `immediate` rule naming an `audio-*` class, one notification per
12531
12607
  * classified sample) stays exactly as it was for rules that already use it.
12532
12608
  *
12533
- * NOT in {@link NC_CONDITION_CATALOG} yet, and that is the sequencing rule
12534
- * rather than an oversight: the viewer mirrors the descriptor enums BY HAND
12535
- * (`camstack/src/data/notification-center.ts`, guarded by
12536
- * `scripts/check-viewer-condition-mirror.ts`) and its rule editor STRIPS the
12609
+ * In {@link NC_CONDITION_CATALOG} since P2, and the ORDER it got there is the
12610
+ * rule rather than an accident: the viewer mirrors the descriptor enums BY
12611
+ * HAND (`camstack/src/data/notification-center.ts`, guarded by
12612
+ * `scripts/check-viewer-condition-mirror.ts`) and its rule editor strips the
12537
12613
  * condition fields it does not know when a rule is saved from the phone.
12538
12614
  * Publishing an editor for a condition the app cannot round-trip is how an
12539
- * operator loses a rule's conditions by opening it — so the descriptor, the
12540
- * admin widget and the viewer mirror land together (P2 + P3), and only then
12541
- * does an audio rule become authorable.
12615
+ * operator loses a rule's conditions by opening it — so the viewer mirror
12616
+ * (P3, shipped) went FIRST, and the descriptor an editor renders from
12617
+ * follows here.
12542
12618
  */
12543
12619
  audio: NcAudioConditionSchema.optional()
12544
12620
  });
@@ -12774,6 +12850,30 @@ var NcRuleInputSchema = zod.z.object({
12774
12850
  */
12775
12851
  snoozeAllowGlobal: zod.z.boolean().optional(),
12776
12852
  /**
12853
+ * The snooze durations THIS rule's notification offers as buttons, in
12854
+ * minutes.
12855
+ *
12856
+ * Three states, and all three are distinct — which is exactly why this is
12857
+ * `.optional()` and never `.default()`. A Zod default does not run on the
12858
+ * addon cap path (three production failures in one day), so a schema default
12859
+ * would collapse the first two:
12860
+ *
12861
+ * | value | meaning |
12862
+ * | --- | --- |
12863
+ * | absent | the operator never said ⇒ {@link NC_DEFAULT_SNOOZE_MINUTES} |
12864
+ * | `[]` | **no snooze buttons on this rule** — the explicit override |
12865
+ * | a list | these choices, de-duplicated and sorted, at most four |
12866
+ *
12867
+ * `.max(4)` because the notifier's own action budget is small (ntfy allows
12868
+ * three buttons in total) and a rule that spent it all on snooze choices
12869
+ * would push its own tap-through actions off the notification.
12870
+ *
12871
+ * An empty list is NOT an alarm exemption: a rule the alarm is about, or
12872
+ * that arms the panel, is exempt automatically and cannot be silenced by a
12873
+ * window from anywhere (D133).
12874
+ */
12875
+ snoozeOptions: zod.z.array(zod.z.number().int().min(1).max(NC_SNOOZE_MAX_MINUTES)).max(4).optional(),
12876
+ /**
12777
12877
  * Devices this rule ACTUATES — arm the alarm, open a gate, turn on a light.
12778
12878
  *
12779
12879
  * This is what makes the rule set the alarm's trigger set without the alarm
@@ -12873,6 +12973,7 @@ var NcConditionDescriptorSchema = zod.z.object({
12873
12973
  "device",
12874
12974
  "package",
12875
12975
  "occupancy",
12976
+ "audio",
12876
12977
  "system"
12877
12978
  ]),
12878
12979
  label: zod.z.string(),
@@ -12891,6 +12992,7 @@ var NcConditionDescriptorSchema = zod.z.object({
12891
12992
  "crossingSelect",
12892
12993
  "polygonDraw",
12893
12994
  "occupancy",
12995
+ "audio",
12894
12996
  "deviceState",
12895
12997
  "systemEvent"
12896
12998
  ]),
@@ -13042,7 +13144,20 @@ var NcSnoozeInputSchema = zod.z.object({
13042
13144
  ruleId: zod.z.string().optional(),
13043
13145
  /** Required when `scope: 'device'`. */
13044
13146
  deviceId: zod.z.number().int().optional(),
13045
- durationMinutes: zod.z.number().int().min(1).max(1440),
13147
+ /**
13148
+ * Narrow the window to these subject classes — "the cat, not the person".
13149
+ *
13150
+ * ORTHOGONAL to `scope`, deliberately, and absent means EVERY class: that is
13151
+ * what every window authored before this field meant, so no persisted row
13152
+ * changes meaning and no client has to learn anything to keep working.
13153
+ *
13154
+ * It is what makes the window's real key `(deviceId, classes[])` and lets it
13155
+ * cross rules (D133): the operator points at a camera and a kind of thing,
13156
+ * not at whichever of their four rules happened to produce the notification
13157
+ * they are dismissing.
13158
+ */
13159
+ classes: zod.z.array(zod.z.string().min(1)).min(1).optional(),
13160
+ durationMinutes: zod.z.number().int().min(1).max(NC_SNOOZE_MAX_MINUTES),
13046
13161
  /**
13047
13162
  * Silence this for EVERY recipient, not just the caller. Permission is
13048
13163
  * checked server-side (the rule's `snoozeAllowGlobal`, or admin for the
@@ -13067,6 +13182,10 @@ var NcSnoozeSchema = zod.z.object({
13067
13182
  scope: NcSnoozeScopeSchema,
13068
13183
  ruleId: zod.z.string().optional(),
13069
13184
  deviceId: zod.z.number().int().optional(),
13185
+ /** Subject classes this window covers. ABSENT = every class — see
13186
+ * {@link NcSnoozeInputSchema.shape.classes}. Lives in the JSON blob and has
13187
+ * no SQLite column: nothing queries a window by class. */
13188
+ classes: zod.z.array(zod.z.string().min(1)).min(1).optional(),
13070
13189
  startedAt: zod.z.number(),
13071
13190
  /** Exclusive: at exactly this instant the snooze is over. Expiry is a
13072
13191
  * COMPARISON, not a job — no sweeper can leave the operator silenced. */
@@ -15829,7 +15948,14 @@ var zonesCapability = {
15829
15948
  * handle. Slice shape is `{ zones: Zone[] }` so future extensions
15830
15949
  * (e.g. zone groupings) can sit alongside the polygon list.
15831
15950
  */
15832
- runtimeState: zod.z.object({ zones: zod.z.array(ZoneSchema).readonly() })
15951
+ runtimeState: zod.z.object({ zones: zod.z.array(ZoneSchema).readonly() }),
15952
+ /**
15953
+ * 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.
15954
+ *
15955
+ * See `RuntimeStateDurability`. Enforced by
15956
+ * `scripts/check-runtime-state-durability.ts`.
15957
+ */
15958
+ durability: "restored"
15833
15959
  };
15834
15960
  /**
15835
15961
  * A bounding box in NORMALIZED [0,1] frame coordinates for `getNativeCrop`. The
@@ -15999,6 +16125,22 @@ var detectionFpsField = {
15999
16125
  default: 10,
16000
16126
  step: 1
16001
16127
  };
16128
+ /**
16129
+ * The occupancy re-check interval. DEFAULT 300 s (2026-08-13 — was 30 s).
16130
+ *
16131
+ * The recheck is now on by default (a parked car is invisible to occupancy
16132
+ * rules until the stationary registry has been rebuilt by motion, which after a
16133
+ * restart may be never on a quiet camera). Each cycle re-subscribes a detection
16134
+ * session — an RTSP re-dial — so the switch is only affordable at a WIDE
16135
+ * interval: 300 s is ~12 re-dials an hour per camera, against 120 at the old
16136
+ * 30 s. A parked car is therefore counted within 5 minutes of a restart.
16137
+ *
16138
+ * Why not wider: `max` is 300 and raising it is TRAIN-BOUND, not addon-bound —
16139
+ * the host validates `attachCamera` against ITS copy of this schema, so a
16140
+ * runner asked for 600 would be rejected by the hub until a `@camstack/server`
16141
+ * carrying the wider bound is installed everywhere. 300 is the widest value
16142
+ * that ships with an addon deploy.
16143
+ */
16002
16144
  var occupancyRecheckSecField = {
16003
16145
  min: 0,
16004
16146
  max: 300,
@@ -16200,15 +16342,21 @@ var RunnerCameraConfigSchema = zod.z.object({
16200
16342
  */
16201
16343
  onboardMotionDrivesAnalyzer: zod.z.boolean().default(true),
16202
16344
  /**
16203
- * Master toggle for the occupancy re-check. When `false` (DEFAULT) the runner
16204
- * never arms the periodic recheck timer, regardless of `occupancyRecheckSec`
16205
- * this is off by default because the recheck re-subscribes a detection session
16206
- * every N seconds while `watching`, a major source of pull-decoder re-dial
16207
- * churn (each cycle creates+tears a session → RTSP re-dial → latency). The
16345
+ * Master toggle for the occupancy re-check. When `false` the runner never arms
16346
+ * the periodic recheck timer, regardless of `occupancyRecheckSec`; the
16208
16347
  * `occupancyRecheckSec` / `occupancyRecheckFrames` sliders only take effect
16209
16348
  * (and only render) when this is enabled.
16210
- */
16211
- occupancyRecheckEnabled: zod.z.boolean().default(false),
16349
+ *
16350
+ * DEFAULT `true` since 2026-08-13 (was `false`). It was off because the
16351
+ * recheck re-subscribes a detection session every N seconds while `watching`
16352
+ * — each cycle creates+tears a session ⇒ an RTSP re-dial ⇒ latency, a major
16353
+ * pull-decoder churn source. What that bought was a blind spot: a STATIONARY
16354
+ * object is counted only while the stationary registry holds it, and the
16355
+ * registry rebuilds from motion, so after a restart a parked car was invisible
16356
+ * to every occupancy rule until something moved in front of it. The churn is
16357
+ * now paid on the interval instead — see `occupancyRecheckSecField`.
16358
+ */
16359
+ occupancyRecheckEnabled: zod.z.boolean().default(true),
16212
16360
  occupancyRecheckSec: zod.z.number().min(occupancyRecheckSecField.min).max(occupancyRecheckSecField.max).default(occupancyRecheckSecField.default),
16213
16361
  occupancyRecheckFrames: zod.z.number().min(occupancyRecheckFramesField.min).max(occupancyRecheckFramesField.max).default(occupancyRecheckFramesField.default),
16214
16362
  /**
@@ -19823,7 +19971,17 @@ var airQualitySensorCapability = {
19823
19971
  schema: AirQualitySensorStatusSchema,
19824
19972
  kind: "push"
19825
19973
  },
19826
- runtimeState: AirQualitySensorStatusSchema
19974
+ runtimeState: AirQualitySensorStatusSchema,
19975
+ /**
19976
+ * Runtime-state durability: **restored** — as `numeric-sensor`.
19977
+ *
19978
+ * See `RuntimeStateDurability`. Enforced by
19979
+ * `scripts/check-runtime-state-durability.ts`.
19980
+ */
19981
+ durability: "restored",
19982
+ /** Clock fields: written, but excluded from the compare that decides
19983
+ * whether persisting is worth a SQLite commit. */
19984
+ volatileStateFields: ["lastFetchedAt"]
19827
19985
  };
19828
19986
  /**
19829
19987
  * Ambient illuminance reading in lux. Drives Home Assistant `sensor`
@@ -19855,7 +20013,17 @@ var ambientLightSensorCapability = {
19855
20013
  schema: AmbientLightSensorStatusSchema,
19856
20014
  kind: "push"
19857
20015
  },
19858
- runtimeState: AmbientLightSensorStatusSchema
20016
+ runtimeState: AmbientLightSensorStatusSchema,
20017
+ /**
20018
+ * Runtime-state durability: **restored** — as `numeric-sensor`.
20019
+ *
20020
+ * See `RuntimeStateDurability`. Enforced by
20021
+ * `scripts/check-runtime-state-durability.ts`.
20022
+ */
20023
+ durability: "restored",
20024
+ /** Clock fields: written, but excluded from the compare that decides
20025
+ * whether persisting is worth a SQLite commit. */
20026
+ volatileStateFields: ["lastFetchedAt"]
19859
20027
  };
19860
20028
  /**
19861
20029
  * Per-class audio metrics aggregated over a sliding window.
@@ -19982,7 +20150,14 @@ var audioMetricsCapability = {
19982
20150
  }), AudioMetricsHistorySchema)
19983
20151
  },
19984
20152
  /** Reactive runtime-state mirror — live `device.state.audioMetrics.value`. */
19985
- runtimeState: AudioMetricsSnapshotSchema
20153
+ runtimeState: AudioMetricsSnapshotSchema,
20154
+ /**
20155
+ * 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.
20156
+ *
20157
+ * See `RuntimeStateDurability`. Enforced by
20158
+ * `scripts/check-runtime-state-durability.ts`.
20159
+ */
20160
+ durability: "session"
19986
20161
  };
19987
20162
  /**
19988
20163
  * Automation-control cap. Models HA `automation.*` entities on
@@ -20044,7 +20219,14 @@ var automationControlCapability = {
20044
20219
  * reads `enabled` (toggle) + `isRunning` (spinner) + `lastError`
20045
20220
  * (badge) directly.
20046
20221
  */
20047
- runtimeState: AutomationControlStatusSchema
20222
+ runtimeState: AutomationControlStatusSchema,
20223
+ /**
20224
+ * 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.
20225
+ *
20226
+ * See `RuntimeStateDurability`. Enforced by
20227
+ * `scripts/check-runtime-state-durability.ts`.
20228
+ */
20229
+ durability: "session"
20048
20230
  };
20049
20231
  /**
20050
20232
  * Battery status snapshot. Emitted by providers whose device is
@@ -20150,7 +20332,17 @@ onStatusChanged: { data: zod.z.object({
20150
20332
  * via `device.runtimeState.getCapState('battery')` regardless of
20151
20333
  * the underlying driver.
20152
20334
  */
20153
- runtimeState: BatteryStatusSchema
20335
+ runtimeState: BatteryStatusSchema,
20336
+ /**
20337
+ * 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.
20338
+ *
20339
+ * See `RuntimeStateDurability`. Enforced by
20340
+ * `scripts/check-runtime-state-durability.ts`.
20341
+ */
20342
+ durability: "restored",
20343
+ /** Clock fields: written, but excluded from the compare that decides
20344
+ * whether persisting is worth a SQLite commit. */
20345
+ volatileStateFields: ["lastUpdated"]
20154
20346
  };
20155
20347
  /**
20156
20348
  * Generic boolean sensor — last-resort fallback when no domain-
@@ -20179,7 +20371,17 @@ var binaryCapability = {
20179
20371
  schema: BinaryStatusSchema,
20180
20372
  kind: "push"
20181
20373
  },
20182
- runtimeState: BinaryStatusSchema
20374
+ runtimeState: BinaryStatusSchema,
20375
+ /**
20376
+ * Runtime-state durability: **restored** — transition-driven sensor state; the restored value gives the boot comparison.
20377
+ *
20378
+ * See `RuntimeStateDurability`. Enforced by
20379
+ * `scripts/check-runtime-state-durability.ts`.
20380
+ */
20381
+ durability: "restored",
20382
+ /** Clock fields: written, but excluded from the compare that decides
20383
+ * whether persisting is worth a SQLite commit. */
20384
+ volatileStateFields: ["lastChangedAt"]
20183
20385
  };
20184
20386
  /**
20185
20387
  * Dimmable-light brightness control. Co-exists with `switch` on the
@@ -20232,7 +20434,14 @@ onBrightnessChanged: { data: zod.z.object({
20232
20434
  * by the kernel. Read via `device.state.brightness.value` so UI
20233
20435
  * sliders surface the current level without polling the provider.
20234
20436
  */
20235
- runtimeState: BrightnessStatusSchema
20437
+ runtimeState: BrightnessStatusSchema,
20438
+ /**
20439
+ * Runtime-state durability: **session** — live lamp state, re-published by the provider on connect.
20440
+ *
20441
+ * See `RuntimeStateDurability`. Enforced by
20442
+ * `scripts/check-runtime-state-durability.ts`.
20443
+ */
20444
+ durability: "session"
20236
20445
  };
20237
20446
  /**
20238
20447
  * button — device-scoped capability for HA `button.*` / `input_button.*`
@@ -20361,7 +20570,17 @@ var carbonMonoxideCapability = {
20361
20570
  schema: CarbonMonoxideStatusSchema,
20362
20571
  kind: "push"
20363
20572
  },
20364
- runtimeState: CarbonMonoxideStatusSchema
20573
+ runtimeState: CarbonMonoxideStatusSchema,
20574
+ /**
20575
+ * Runtime-state durability: **restored** — as `smoke`.
20576
+ *
20577
+ * See `RuntimeStateDurability`. Enforced by
20578
+ * `scripts/check-runtime-state-durability.ts`.
20579
+ */
20580
+ durability: "restored",
20581
+ /** Clock fields: written, but excluded from the compare that decides
20582
+ * whether persisting is worth a SQLite commit. */
20583
+ volatileStateFields: ["lastChangedAt"]
20365
20584
  };
20366
20585
  /**
20367
20586
  * HVAC / climate control cap. Models the full surface of a HA
@@ -20521,7 +20740,14 @@ var climateControlCapability = {
20521
20740
  * the full slice via `device.state.climate-control.value` and refresh
20522
20741
  * on every push without re-querying the provider.
20523
20742
  */
20524
- runtimeState: ClimateControlStatusSchema
20743
+ runtimeState: ClimateControlStatusSchema,
20744
+ /**
20745
+ * Runtime-state durability: **session** — as `brightness`; `currentTemp` moves continuously and is re-published on connect.
20746
+ *
20747
+ * See `RuntimeStateDurability`. Enforced by
20748
+ * `scripts/check-runtime-state-durability.ts`.
20749
+ */
20750
+ durability: "session"
20525
20751
  };
20526
20752
  /**
20527
20753
  * Color-light cap. Coexists with `switch` (on/off) and `brightness`
@@ -20631,7 +20857,14 @@ onColorChanged: { data: zod.z.object({
20631
20857
  * kernel. Read via `device.state.color.value` so UI pickers surface
20632
20858
  * the current chromaticity without polling the provider.
20633
20859
  */
20634
- runtimeState: ColorStatusSchema
20860
+ runtimeState: ColorStatusSchema,
20861
+ /**
20862
+ * Runtime-state durability: **session** — as `brightness`.
20863
+ *
20864
+ * See `RuntimeStateDurability`. Enforced by
20865
+ * `scripts/check-runtime-state-durability.ts`.
20866
+ */
20867
+ durability: "session"
20635
20868
  };
20636
20869
  var ConnectionTestOutcomeSchema = zod.z.discriminatedUnion("outcome", [
20637
20870
  zod.z.object({
@@ -20697,7 +20930,17 @@ var connectivityCapability = {
20697
20930
  schema: ConnectivityStatusSchema,
20698
20931
  kind: "push"
20699
20932
  },
20700
- runtimeState: ConnectivityStatusSchema
20933
+ runtimeState: ConnectivityStatusSchema,
20934
+ /**
20935
+ * Runtime-state durability: **restored** — same shape and same argument as `device-status`, for links rather than devices.
20936
+ *
20937
+ * See `RuntimeStateDurability`. Enforced by
20938
+ * `scripts/check-runtime-state-durability.ts`.
20939
+ */
20940
+ durability: "restored",
20941
+ /** Clock fields: written, but excluded from the compare that decides
20942
+ * whether persisting is worth a SQLite commit. */
20943
+ volatileStateFields: ["lastChangedAt"]
20701
20944
  };
20702
20945
  /**
20703
20946
  * Generic device-consumables capability — surfaces a device's
@@ -20779,7 +21022,14 @@ reset: method(zod.z.object({
20779
21022
  }
20780
21023
  }
20781
21024
  },
20782
- runtimeState: ConsumablesStatusSchema.extend({ lastFetchedAt: zod.z.number() })
21025
+ runtimeState: ConsumablesStatusSchema.extend({ lastFetchedAt: zod.z.number() }),
21026
+ /**
21027
+ * Runtime-state durability: **session** — the authority is the appliance; the provider re-reads the whole item array on connect.
21028
+ *
21029
+ * See `RuntimeStateDurability`. Enforced by
21030
+ * `scripts/check-runtime-state-durability.ts`.
21031
+ */
21032
+ durability: "session"
20783
21033
  };
20784
21034
  /**
20785
21035
  * Door / window / opening / garage / valve contact sensor. Boolean
@@ -20810,7 +21060,17 @@ var contactCapability = {
20810
21060
  schema: ContactStatusSchema,
20811
21061
  kind: "push"
20812
21062
  },
20813
- runtimeState: ContactStatusSchema
21063
+ runtimeState: ContactStatusSchema,
21064
+ /**
21065
+ * Runtime-state durability: **restored** — a door left open across a restart must still read open.
21066
+ *
21067
+ * See `RuntimeStateDurability`. Enforced by
21068
+ * `scripts/check-runtime-state-durability.ts`.
21069
+ */
21070
+ durability: "restored",
21071
+ /** Clock fields: written, but excluded from the compare that decides
21072
+ * whether persisting is worth a SQLite commit. */
21073
+ volatileStateFields: ["lastChangedAt"]
20814
21074
  };
20815
21075
  /**
20816
21076
  * Unified user-settable input cap. Models HA's `number` /
@@ -20940,7 +21200,14 @@ var controlCapability = {
20940
21200
  * dropdown / text field / date picker) read the slice's discriminant
20941
21201
  * and value directly without polling the provider.
20942
21202
  */
20943
- runtimeState: ControlStatusSchema
21203
+ runtimeState: ControlStatusSchema,
21204
+ /**
21205
+ * Runtime-state durability: **session** — a generic control mirrors an external entity that re-publishes on connect; the options array is re-derived with it.
21206
+ *
21207
+ * See `RuntimeStateDurability`. Enforced by
21208
+ * `scripts/check-runtime-state-durability.ts`.
21209
+ */
21210
+ durability: "session"
20944
21211
  };
20945
21212
  /**
20946
21213
  * Window covering / blinds / garage door / valve cap. Models HA
@@ -21023,7 +21290,17 @@ var coverCapability = {
21023
21290
  * Runtime-state slice — mirrored by the kernel. UI controls watch
21024
21291
  * the slice for live position changes during a move.
21025
21292
  */
21026
- runtimeState: CoverStatusSchema
21293
+ runtimeState: CoverStatusSchema,
21294
+ /**
21295
+ * Runtime-state durability: **restored** — position survives a restart on the device; the mirror should agree at boot rather than read blank.
21296
+ *
21297
+ * See `RuntimeStateDurability`. Enforced by
21298
+ * `scripts/check-runtime-state-durability.ts`.
21299
+ */
21300
+ durability: "restored",
21301
+ /** Clock fields: written, but excluded from the compare that decides
21302
+ * whether persisting is worth a SQLite commit. */
21303
+ volatileStateFields: ["lastChangedAt"]
21027
21304
  };
21028
21305
  /**
21029
21306
  * Vendor-neutral day/night (IR-cut) control — the per-camera config cap
@@ -21117,7 +21394,17 @@ var dayNightCapability = {
21117
21394
  schema: DayNightStatusSchema,
21118
21395
  kind: "poll"
21119
21396
  },
21120
- runtimeState: DayNightStatusSchema
21397
+ runtimeState: DayNightStatusSchema,
21398
+ /**
21399
+ * Runtime-state durability: **restored** — operator-set IR-cut behaviour; mutation-driven.
21400
+ *
21401
+ * See `RuntimeStateDurability`. Enforced by
21402
+ * `scripts/check-runtime-state-durability.ts`.
21403
+ */
21404
+ durability: "restored",
21405
+ /** Clock fields: written, but excluded from the compare that decides
21406
+ * whether persisting is worth a SQLite commit. */
21407
+ volatileStateFields: ["lastFetchedAt"]
21121
21408
  };
21122
21409
  /**
21123
21410
  * Generic device-level status snapshot. Auto-registered by `BaseDevice`
@@ -21164,7 +21451,17 @@ onStatusChanged: { data: zod.z.object({
21164
21451
  schema: DeviceStatusSchema,
21165
21452
  kind: "push"
21166
21453
  },
21167
- runtimeState: DeviceStatusSchema
21454
+ runtimeState: DeviceStatusSchema,
21455
+ /**
21456
+ * 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.
21457
+ *
21458
+ * See `RuntimeStateDurability`. Enforced by
21459
+ * `scripts/check-runtime-state-durability.ts`.
21460
+ */
21461
+ durability: "restored",
21462
+ /** Clock fields: written, but excluded from the compare that decides
21463
+ * whether persisting is worth a SQLite commit. */
21464
+ volatileStateFields: ["lastChangedAt"]
21168
21465
  };
21169
21466
  /**
21170
21467
  * Doorbell button cap. Two kinds of providers coexist behind this cap
@@ -21226,7 +21523,14 @@ onPressed: { data: DoorbellPressEventSchema } },
21226
21523
  * `device.state.doorbell.value`. UIs can show "last ring 5m ago"
21227
21524
  * without subscribing.
21228
21525
  */
21229
- runtimeState: DoorbellStatusSchema
21526
+ runtimeState: DoorbellStatusSchema,
21527
+ /**
21528
+ * 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.
21529
+ *
21530
+ * See `RuntimeStateDurability`. Enforced by
21531
+ * `scripts/check-runtime-state-durability.ts`.
21532
+ */
21533
+ durability: "restored"
21230
21534
  };
21231
21535
  /**
21232
21536
  * Enum-state sensor — a string value picked from a finite option set.
@@ -21266,7 +21570,17 @@ var enumSensorCapability = {
21266
21570
  schema: EnumSensorStatusSchema,
21267
21571
  kind: "push"
21268
21572
  },
21269
- runtimeState: EnumSensorStatusSchema
21573
+ runtimeState: EnumSensorStatusSchema,
21574
+ /**
21575
+ * Runtime-state durability: **restored** — as `numeric-sensor`; 80 devices.
21576
+ *
21577
+ * See `RuntimeStateDurability`. Enforced by
21578
+ * `scripts/check-runtime-state-durability.ts`.
21579
+ */
21580
+ durability: "restored",
21581
+ /** Clock fields: written, but excluded from the compare that decides
21582
+ * whether persisting is worth a SQLite commit. */
21583
+ volatileStateFields: ["lastFetchedAt"]
21270
21584
  };
21271
21585
  /**
21272
21586
  * Generic stateless event emitter. Installed on a `DeviceType.EventEmitter`
@@ -21302,7 +21616,14 @@ var eventEmitterCapability = {
21302
21616
  schema: EventEmitterStatusSchema,
21303
21617
  kind: "push"
21304
21618
  },
21305
- runtimeState: EventEmitterStatusSchema
21619
+ runtimeState: EventEmitterStatusSchema,
21620
+ /**
21621
+ * Runtime-state durability: **session** — `eventCountSinceStart` names its own scope.
21622
+ *
21623
+ * See `RuntimeStateDurability`. Enforced by
21624
+ * `scripts/check-runtime-state-durability.ts`.
21625
+ */
21626
+ durability: "session"
21306
21627
  };
21307
21628
  var EventItemSchema = zod.z.object({
21308
21629
  id: zod.z.string(),
@@ -21619,7 +21940,14 @@ var fanControlCapability = {
21619
21940
  * Runtime-state slice — mirrored by the kernel. UI fan speed
21620
21941
  * sliders read `percentage` for live updates.
21621
21942
  */
21622
- runtimeState: FanControlStatusSchema
21943
+ runtimeState: FanControlStatusSchema,
21944
+ /**
21945
+ * Runtime-state durability: **session** — as `brightness`.
21946
+ *
21947
+ * See `RuntimeStateDurability`. Enforced by
21948
+ * `scripts/check-runtime-state-durability.ts`.
21949
+ */
21950
+ durability: "session"
21623
21951
  };
21624
21952
  /**
21625
21953
  * Per-device feature/identity probe slice. Holds the runtime-resolved
@@ -21695,7 +22023,14 @@ onProbeChanged: { data: zod.z.object({
21695
22023
  schema: FeatureProbeStatusSchema,
21696
22024
  kind: "push"
21697
22025
  },
21698
- runtimeState: FeatureProbeStatusSchema
22026
+ runtimeState: FeatureProbeStatusSchema,
22027
+ /**
22028
+ * 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.
22029
+ *
22030
+ * See `RuntimeStateDurability`. Enforced by
22031
+ * `scripts/check-runtime-state-durability.ts`.
22032
+ */
22033
+ durability: "session"
21699
22034
  };
21700
22035
  /**
21701
22036
  * Water leak / moisture sensor. Boolean "is liquid currently
@@ -21722,7 +22057,17 @@ var floodCapability = {
21722
22057
  schema: FloodStatusSchema,
21723
22058
  kind: "push"
21724
22059
  },
21725
- runtimeState: FloodStatusSchema
22060
+ runtimeState: FloodStatusSchema,
22061
+ /**
22062
+ * Runtime-state durability: **restored** — as `smoke`.
22063
+ *
22064
+ * See `RuntimeStateDurability`. Enforced by
22065
+ * `scripts/check-runtime-state-durability.ts`.
22066
+ */
22067
+ durability: "restored",
22068
+ /** Clock fields: written, but excluded from the compare that decides
22069
+ * whether persisting is worth a SQLite commit. */
22070
+ volatileStateFields: ["lastChangedAt"]
21726
22071
  };
21727
22072
  /**
21728
22073
  * Combustible-gas (LPG / methane / hydrogen) alarm sensor. Drives
@@ -21745,7 +22090,17 @@ var gasCapability = {
21745
22090
  schema: GasStatusSchema,
21746
22091
  kind: "push"
21747
22092
  },
21748
- runtimeState: GasStatusSchema
22093
+ runtimeState: GasStatusSchema,
22094
+ /**
22095
+ * Runtime-state durability: **restored** — as `smoke`.
22096
+ *
22097
+ * See `RuntimeStateDurability`. Enforced by
22098
+ * `scripts/check-runtime-state-durability.ts`.
22099
+ */
22100
+ durability: "restored",
22101
+ /** Clock fields: written, but excluded from the compare that decides
22102
+ * whether persisting is worth a SQLite commit. */
22103
+ volatileStateFields: ["lastChangedAt"]
21749
22104
  };
21750
22105
  /**
21751
22106
  * Humidifier / dehumidifier cap. Models HA `humidifier.*` entities —
@@ -21821,7 +22176,14 @@ var humidifierCapability = {
21821
22176
  * Runtime-state slice — mirrored by the kernel. UI controls watch the
21822
22177
  * slice for live humidity / mode changes.
21823
22178
  */
21824
- runtimeState: HumidifierStatusSchema
22179
+ runtimeState: HumidifierStatusSchema,
22180
+ /**
22181
+ * Runtime-state durability: **session** — as `climate-control`.
22182
+ *
22183
+ * See `RuntimeStateDurability`. Enforced by
22184
+ * `scripts/check-runtime-state-durability.ts`.
22185
+ */
22186
+ durability: "session"
21825
22187
  };
21826
22188
  /**
21827
22189
  * Single-metric humidity reading. Drives Home Assistant `sensor`
@@ -21857,7 +22219,17 @@ var humiditySensorCapability = {
21857
22219
  schema: HumiditySensorStatusSchema,
21858
22220
  kind: "push"
21859
22221
  },
21860
- runtimeState: HumiditySensorStatusSchema
22222
+ runtimeState: HumiditySensorStatusSchema,
22223
+ /**
22224
+ * Runtime-state durability: **restored** — as `numeric-sensor` (67 of 75 writes were the clock alone).
22225
+ *
22226
+ * See `RuntimeStateDurability`. Enforced by
22227
+ * `scripts/check-runtime-state-durability.ts`.
22228
+ */
22229
+ durability: "restored",
22230
+ /** Clock fields: written, but excluded from the compare that decides
22231
+ * whether persisting is worth a SQLite commit. */
22232
+ volatileStateFields: ["lastFetchedAt"]
21861
22233
  };
21862
22234
  /**
21863
22235
  * Image display cap. Models a single still image exposed by an integration —
@@ -21895,7 +22267,14 @@ var imageCapability = {
21895
22267
  * Runtime-state slice — mirrored by the kernel. The UI reads `url`
21896
22268
  * directly and renders the still image.
21897
22269
  */
21898
- runtimeState: ImageStatusSchema
22270
+ runtimeState: ImageStatusSchema,
22271
+ /**
22272
+ * Runtime-state durability: **session** — a snapshot URL is a session-scoped handle; a restored one points at nothing.
22273
+ *
22274
+ * See `RuntimeStateDurability`. Enforced by
22275
+ * `scripts/check-runtime-state-durability.ts`.
22276
+ */
22277
+ durability: "session"
21899
22278
  };
21900
22279
  /**
21901
22280
  * Vendor-neutral image / picture-adjustment cap — the per-camera config
@@ -22044,7 +22423,17 @@ var imageSettingsCapability = {
22044
22423
  schema: ImageSettingsStatusSchema,
22045
22424
  kind: "poll"
22046
22425
  },
22047
- runtimeState: ImageSettingsStatusSchema
22426
+ runtimeState: ImageSettingsStatusSchema,
22427
+ /**
22428
+ * Runtime-state durability: **restored** — operator-set camera imaging; mutation-driven.
22429
+ *
22430
+ * See `RuntimeStateDurability`. Enforced by
22431
+ * `scripts/check-runtime-state-durability.ts`.
22432
+ */
22433
+ durability: "restored",
22434
+ /** Clock fields: written, but excluded from the compare that decides
22435
+ * whether persisting is worth a SQLite commit. */
22436
+ volatileStateFields: ["lastFetchedAt"]
22048
22437
  };
22049
22438
  /**
22050
22439
  * integrations — system-scoped singleton capability for integration
@@ -22453,7 +22842,14 @@ var lawnMowerControlCapability = {
22453
22842
  * Runtime-state slice — mirrored by the kernel. UI controls watch the
22454
22843
  * slice for live activity + battery changes.
22455
22844
  */
22456
- runtimeState: LawnMowerControlStatusSchema
22845
+ runtimeState: LawnMowerControlStatusSchema,
22846
+ /**
22847
+ * Runtime-state durability: **session** — as `vacuum-control`.
22848
+ *
22849
+ * See `RuntimeStateDurability`. Enforced by
22850
+ * `scripts/check-runtime-state-durability.ts`.
22851
+ */
22852
+ durability: "session"
22457
22853
  };
22458
22854
  /**
22459
22855
  * local-network — hub-only singleton.
@@ -22756,7 +23152,17 @@ var lockControlCapability = {
22756
23152
  * read `state` and disable themselves during `locking`/`unlocking`
22757
23153
  * transitions.
22758
23154
  */
22759
- runtimeState: LockControlStatusSchema
23155
+ runtimeState: LockControlStatusSchema,
23156
+ /**
23157
+ * Runtime-state durability: **restored** — a lock left locked must still read locked.
23158
+ *
23159
+ * See `RuntimeStateDurability`. Enforced by
23160
+ * `scripts/check-runtime-state-durability.ts`.
23161
+ */
23162
+ durability: "restored",
23163
+ /** Clock fields: written, but excluded from the compare that decides
23164
+ * whether persisting is worth a SQLite commit. */
23165
+ volatileStateFields: ["lastChangedAt"]
22760
23166
  };
22761
23167
  /**
22762
23168
  * Media-player cap. Models HA `media_player.*` (Sonos, Chromecast,
@@ -22918,7 +23324,14 @@ var mediaPlayerCapability = {
22918
23324
  * full slice for live now-playing, volume, and progress updates
22919
23325
  * without polling.
22920
23326
  */
22921
- runtimeState: MediaPlayerStatusSchema
23327
+ runtimeState: MediaPlayerStatusSchema,
23328
+ /**
23329
+ * Runtime-state durability: **session** — a restored transport position describes a playback that stopped when the hub did.
23330
+ *
23331
+ * See `RuntimeStateDurability`. Enforced by
23332
+ * `scripts/check-runtime-state-durability.ts`.
23333
+ */
23334
+ durability: "session"
22922
23335
  };
22923
23336
  /**
22924
23337
  * mesh-network — collection cap for mesh-VPN providers.
@@ -23243,7 +23656,14 @@ onMotionChanged: { data: MotionOnMotionChangedDataSchema } },
23243
23656
  * `device.state.motion.value`. Reads never invoke the provider, so
23244
23657
  * UIs and other addons can poll the cached state safely.
23245
23658
  */
23246
- runtimeState: MotionStatusSchema
23659
+ runtimeState: MotionStatusSchema,
23660
+ /**
23661
+ * 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.
23662
+ *
23663
+ * See `RuntimeStateDurability`. Enforced by
23664
+ * `scripts/check-runtime-state-durability.ts`.
23665
+ */
23666
+ durability: "session"
23247
23667
  };
23248
23668
  /**
23249
23669
  * Motion-trigger toggle for accessory devices.
@@ -23308,7 +23728,14 @@ var motionTriggerCapability = {
23308
23728
  schema: MotionTriggerStatusSchema,
23309
23729
  kind: "command-driven"
23310
23730
  },
23311
- runtimeState: MotionTriggerRuntimeStateSchema
23731
+ runtimeState: MotionTriggerRuntimeStateSchema,
23732
+ /**
23733
+ * 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.
23734
+ *
23735
+ * See `RuntimeStateDurability`. Enforced by
23736
+ * `scripts/check-runtime-state-durability.ts`.
23737
+ */
23738
+ durability: "session"
23312
23739
  };
23313
23740
  /**
23314
23741
  * Motion-zones share the same MaskShape vocabulary as privacy-mask — the
@@ -23375,7 +23802,17 @@ var motionZonesCapability = {
23375
23802
  schema: MotionZoneStatusSchema,
23376
23803
  kind: "poll"
23377
23804
  },
23378
- runtimeState: MotionZoneStatusSchema
23805
+ runtimeState: MotionZoneStatusSchema,
23806
+ /**
23807
+ * 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.
23808
+ *
23809
+ * See `RuntimeStateDurability`. Enforced by
23810
+ * `scripts/check-runtime-state-durability.ts`.
23811
+ */
23812
+ durability: "restored",
23813
+ /** Clock fields: written, but excluded from the compare that decides
23814
+ * whether persisting is worth a SQLite commit. */
23815
+ volatileStateFields: ["lastFetchedAt"]
23379
23816
  };
23380
23817
  /**
23381
23818
  * On-camera AI object detection cap. Surfaces per-device the classes
@@ -23449,7 +23886,17 @@ var nativeObjectDetectionCapability = {
23449
23886
  schema: NativeObjectDetectionStatusSchema,
23450
23887
  kind: "push"
23451
23888
  },
23452
- runtimeState: NativeObjectDetectionRuntimeStateSchema
23889
+ runtimeState: NativeObjectDetectionRuntimeStateSchema,
23890
+ /**
23891
+ * 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.
23892
+ *
23893
+ * See `RuntimeStateDurability`. Enforced by
23894
+ * `scripts/check-runtime-state-durability.ts`.
23895
+ */
23896
+ durability: "restored",
23897
+ /** Clock fields: written, but excluded from the compare that decides
23898
+ * whether persisting is worth a SQLite commit. */
23899
+ volatileStateFields: ["lastFetchedAt"]
23453
23900
  };
23454
23901
  /**
23455
23902
  * network-quality — system-scoped singleton capability tracking RTT,
@@ -23836,7 +24283,14 @@ onSent: { data: zod.z.object({
23836
24283
  * form reads `supports` to gate optional fields; history pane reads
23837
24284
  * `lastSentAt` / `lastError` / `queueDepth`.
23838
24285
  */
23839
- runtimeState: NotifierStatusSchema
24286
+ runtimeState: NotifierStatusSchema,
24287
+ /**
24288
+ * Runtime-state durability: **session** — live queue depth and last-send state; a restored queue depth describes a queue that no longer exists.
24289
+ *
24290
+ * See `RuntimeStateDurability`. Enforced by
24291
+ * `scripts/check-runtime-state-durability.ts`.
24292
+ */
24293
+ durability: "session"
23840
24294
  };
23841
24295
  /**
23842
24296
  * Generic numeric sensor — last-resort fallback when no typed numeric
@@ -23879,7 +24333,17 @@ var numericSensorCapability = {
23879
24333
  schema: NumericSensorStatusSchema,
23880
24334
  kind: "push"
23881
24335
  },
23882
- runtimeState: NumericSensorStatusSchema
24336
+ runtimeState: NumericSensorStatusSchema,
24337
+ /**
24338
+ * 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.
24339
+ *
24340
+ * See `RuntimeStateDurability`. Enforced by
24341
+ * `scripts/check-runtime-state-durability.ts`.
24342
+ */
24343
+ durability: "restored",
24344
+ /** Clock fields: written, but excluded from the compare that decides
24345
+ * whether persisting is worth a SQLite commit. */
24346
+ volatileStateFields: ["lastFetchedAt"]
23883
24347
  };
23884
24348
  /**
23885
24349
  * Generic on-screen-display (video overlay) cap. Each camera exposes
@@ -24358,7 +24822,14 @@ var petFeederCapability = {
24358
24822
  * the full slice via `device.state.petFeeder.value` and refresh on
24359
24823
  * every poll without re-querying the provider.
24360
24824
  */
24361
- runtimeState: PetFeederStatusSchema
24825
+ runtimeState: PetFeederStatusSchema,
24826
+ /**
24827
+ * Runtime-state durability: **session** — live appliance state re-published on connect.
24828
+ *
24829
+ * See `RuntimeStateDurability`. Enforced by
24830
+ * `scripts/check-runtime-state-durability.ts`.
24831
+ */
24832
+ durability: "session"
24362
24833
  };
24363
24834
  var VehicleSchema = zod.z.object({
24364
24835
  id: zod.z.string(),
@@ -24715,7 +25186,17 @@ var powerMeterCapability = {
24715
25186
  schema: PowerMeterStatusSchema,
24716
25187
  kind: "push"
24717
25188
  },
24718
- runtimeState: PowerMeterStatusSchema
25189
+ runtimeState: PowerMeterStatusSchema,
25190
+ /**
25191
+ * Runtime-state durability: **restored** — as `numeric-sensor`; `kwhTotal` is an accumulator whose restored value is the baseline.
25192
+ *
25193
+ * See `RuntimeStateDurability`. Enforced by
25194
+ * `scripts/check-runtime-state-durability.ts`.
25195
+ */
25196
+ durability: "restored",
25197
+ /** Clock fields: written, but excluded from the compare that decides
25198
+ * whether persisting is worth a SQLite commit. */
25199
+ volatileStateFields: ["lastFetchedAt"]
24719
25200
  };
24720
25201
  /**
24721
25202
  * Presence cap. Models HA `person.*` and `device_tracker.*` entities
@@ -24772,7 +25253,17 @@ var presenceCapability = {
24772
25253
  * the map pin is rendered (use `DeviceFeature.PresenceGps` for the
24773
25254
  * pre-fetch fast-path check).
24774
25255
  */
24775
- runtimeState: PresenceStatusSchema
25256
+ runtimeState: PresenceStatusSchema,
25257
+ /**
25258
+ * Runtime-state durability: **restored** — occupancy-relevant: the restored state is what an occupancy rule compares the first post-restart observation against.
25259
+ *
25260
+ * See `RuntimeStateDurability`. Enforced by
25261
+ * `scripts/check-runtime-state-durability.ts`.
25262
+ */
25263
+ durability: "restored",
25264
+ /** Clock fields: written, but excluded from the compare that decides
25265
+ * whether persisting is worth a SQLite commit. */
25266
+ volatileStateFields: ["lastChangedAt"]
24776
25267
  };
24777
25268
  /**
24778
25269
  * Atmospheric pressure reading in hectopascals. Drives Home Assistant
@@ -24808,7 +25299,17 @@ var pressureSensorCapability = {
24808
25299
  schema: PressureSensorStatusSchema,
24809
25300
  kind: "push"
24810
25301
  },
24811
- runtimeState: PressureSensorStatusSchema
25302
+ runtimeState: PressureSensorStatusSchema,
25303
+ /**
25304
+ * Runtime-state durability: **restored** — as `numeric-sensor`.
25305
+ *
25306
+ * See `RuntimeStateDurability`. Enforced by
25307
+ * `scripts/check-runtime-state-durability.ts`.
25308
+ */
25309
+ durability: "restored",
25310
+ /** Clock fields: written, but excluded from the compare that decides
25311
+ * whether persisting is worth a SQLite commit. */
25312
+ volatileStateFields: ["lastFetchedAt"]
24812
25313
  };
24813
25314
  /**
24814
25315
  * PRIVACY — what the camera deliberately does not capture. Two planes:
@@ -24938,7 +25439,17 @@ var privacyMaskCapability = {
24938
25439
  schema: PrivacyMaskStatusSchema,
24939
25440
  kind: "poll"
24940
25441
  },
24941
- runtimeState: PrivacyMaskStatusSchema
25442
+ runtimeState: PrivacyMaskStatusSchema,
25443
+ /**
25444
+ * Runtime-state durability: **restored** — operator-drawn regions, zero real churn — 22 writes in 25 minutes, every one of them the clock.
25445
+ *
25446
+ * See `RuntimeStateDurability`. Enforced by
25447
+ * `scripts/check-runtime-state-durability.ts`.
25448
+ */
25449
+ durability: "restored",
25450
+ /** Clock fields: written, but excluded from the compare that decides
25451
+ * whether persisting is worth a SQLite commit. */
25452
+ volatileStateFields: ["lastFetchedAt"]
24942
25453
  };
24943
25454
  var PtzPresetSchema = zod.z.object({
24944
25455
  id: zod.z.string(),
@@ -25181,7 +25692,14 @@ var ptzAutotrackCapability = {
25181
25692
  * fetch / cache / fallback logic out of the four cap methods —
25182
25693
  * they become trampolines over `runtimeState`.
25183
25694
  */
25184
- runtimeState: PtzAutotrackRuntimeStateSchema
25695
+ runtimeState: PtzAutotrackRuntimeStateSchema,
25696
+ /**
25697
+ * Runtime-state durability: **session** — mirrors the camera's own autotrack config, re-read on connect.
25698
+ *
25699
+ * See `RuntimeStateDurability`. Enforced by
25700
+ * `scripts/check-runtime-state-durability.ts`.
25701
+ */
25702
+ durability: "session"
25185
25703
  };
25186
25704
  /**
25187
25705
  * reboot — device-scoped capability for "soft" device reboots (firmware
@@ -25989,7 +26507,14 @@ var sceneMonitorCapability = {
25989
26507
  schema: SceneMonitorStatusSchema,
25990
26508
  kind: "push"
25991
26509
  },
25992
- runtimeState: SceneMonitorStatusSchema
26510
+ runtimeState: SceneMonitorStatusSchema,
26511
+ /**
26512
+ * Runtime-state durability: **session** — re-derived from the current scene on the next evaluation.
26513
+ *
26514
+ * See `RuntimeStateDurability`. Enforced by
26515
+ * `scripts/check-runtime-state-durability.ts`.
26516
+ */
26517
+ durability: "session"
25993
26518
  };
25994
26519
  /**
25995
26520
  * Per-stage gating mode applied to the zones a rule references.
@@ -26133,7 +26658,14 @@ var scriptRunnerCapability = {
26133
26658
  * `isRunning` to render a spinner during execution and surfaces
26134
26659
  * `lastError` / `lastRunSuccess` in the recent-runs panel.
26135
26660
  */
26136
- runtimeState: ScriptRunnerStatusSchema
26661
+ runtimeState: ScriptRunnerStatusSchema,
26662
+ /**
26663
+ * Runtime-state durability: **session** — a restored `isRunning: true` describes a process that died with the previous hub.
26664
+ *
26665
+ * See `RuntimeStateDurability`. Enforced by
26666
+ * `scripts/check-runtime-state-durability.ts`.
26667
+ */
26668
+ durability: "session"
26137
26669
  };
26138
26670
  /**
26139
26671
  * Smoke alarm sensor — boolean "is smoke currently detected" with
@@ -26160,7 +26692,17 @@ var smokeCapability = {
26160
26692
  schema: SmokeStatusSchema,
26161
26693
  kind: "push"
26162
26694
  },
26163
- runtimeState: SmokeStatusSchema
26695
+ runtimeState: SmokeStatusSchema,
26696
+ /**
26697
+ * Runtime-state durability: **restored** — a safety sensor must not read "clear" merely because the hub restarted.
26698
+ *
26699
+ * See `RuntimeStateDurability`. Enforced by
26700
+ * `scripts/check-runtime-state-durability.ts`.
26701
+ */
26702
+ durability: "restored",
26703
+ /** Clock fields: written, but excluded from the compare that decides
26704
+ * whether persisting is worth a SQLite commit. */
26705
+ volatileStateFields: ["lastChangedAt"]
26164
26706
  };
26165
26707
  /**
26166
26708
  * One publishable camera stream as its OWNING PROVIDER describes it — the same
@@ -26346,7 +26888,17 @@ var streamParamsCapability = {
26346
26888
  schema: StreamParamsStatusSchema,
26347
26889
  kind: "poll"
26348
26890
  },
26349
- runtimeState: StreamParamsStatusSchema
26891
+ runtimeState: StreamParamsStatusSchema,
26892
+ /**
26893
+ * Runtime-state durability: **restored** — operator-set encoder profile; mutation-driven.
26894
+ *
26895
+ * See `RuntimeStateDurability`. Enforced by
26896
+ * `scripts/check-runtime-state-durability.ts`.
26897
+ */
26898
+ durability: "restored",
26899
+ /** Clock fields: written, but excluded from the compare that decides
26900
+ * whether persisting is worth a SQLite commit. */
26901
+ volatileStateFields: ["lastFetchedAt"]
26350
26902
  };
26351
26903
  /**
26352
26904
  * The three well-known stream profiles in render order. Exported so the
@@ -26649,6 +27201,16 @@ var switchCapability = {
26649
27201
  * not need to re-query the provider after a setState mutation.
26650
27202
  */
26651
27203
  runtimeState: SwitchStatusSchema,
27204
+ /**
27205
+ * Runtime-state durability: **restored** — device state an operator reads as authoritative; 55 devices, transition-driven.
27206
+ *
27207
+ * See `RuntimeStateDurability`. Enforced by
27208
+ * `scripts/check-runtime-state-durability.ts`.
27209
+ */
27210
+ durability: "restored",
27211
+ /** Clock fields: written, but excluded from the compare that decides
27212
+ * whether persisting is worth a SQLite commit. */
27213
+ volatileStateFields: ["lastChangedAt"],
26652
27214
  settings: { bindings: [{
26653
27215
  kind: "scalar",
26654
27216
  statusPath: "on",
@@ -26743,7 +27305,17 @@ var tamperCapability = {
26743
27305
  schema: TamperStatusSchema,
26744
27306
  kind: "push"
26745
27307
  },
26746
- runtimeState: TamperStatusSchema
27308
+ runtimeState: TamperStatusSchema,
27309
+ /**
27310
+ * Runtime-state durability: **restored** — as `smoke`.
27311
+ *
27312
+ * See `RuntimeStateDurability`. Enforced by
27313
+ * `scripts/check-runtime-state-durability.ts`.
27314
+ */
27315
+ durability: "restored",
27316
+ /** Clock fields: written, but excluded from the compare that decides
27317
+ * whether persisting is worth a SQLite commit. */
27318
+ volatileStateFields: ["lastChangedAt"]
26747
27319
  };
26748
27320
  /**
26749
27321
  * Single-metric temperature reading. Drives Home Assistant `sensor`
@@ -26788,7 +27360,17 @@ var temperatureSensorCapability = {
26788
27360
  schema: TemperatureSensorStatusSchema,
26789
27361
  kind: "push"
26790
27362
  },
26791
- runtimeState: TemperatureSensorStatusSchema
27363
+ runtimeState: TemperatureSensorStatusSchema,
27364
+ /**
27365
+ * Runtime-state durability: **restored** — as `numeric-sensor` (69 of 125 writes were the clock alone).
27366
+ *
27367
+ * See `RuntimeStateDurability`. Enforced by
27368
+ * `scripts/check-runtime-state-durability.ts`.
27369
+ */
27370
+ durability: "restored",
27371
+ /** Clock fields: written, but excluded from the compare that decides
27372
+ * whether persisting is worth a SQLite commit. */
27373
+ volatileStateFields: ["lastFetchedAt"]
26792
27374
  };
26793
27375
  /**
26794
27376
  * toast — system-scoped singleton capability that streams toast
@@ -26864,7 +27446,14 @@ var updateCapability = {
26864
27446
  schema: UpdateStatusSchema,
26865
27447
  kind: "poll"
26866
27448
  },
26867
- runtimeState: UpdateStatusSchema
27449
+ runtimeState: UpdateStatusSchema,
27450
+ /**
27451
+ * Runtime-state durability: **session** — a restored `inProgress: true` describes an update that is no longer running; versions are re-probed at boot.
27452
+ *
27453
+ * See `RuntimeStateDurability`. Enforced by
27454
+ * `scripts/check-runtime-state-durability.ts`.
27455
+ */
27456
+ durability: "session"
26868
27457
  };
26869
27458
  var UserSummarySchema = zod.z.object({
26870
27459
  id: zod.z.string(),
@@ -27240,7 +27829,14 @@ var vacuumControlCapability = {
27240
27829
  * Runtime-state slice — mirrored by the kernel. UI controls watch the
27241
27830
  * slice for live state + battery + fan-speed changes.
27242
27831
  */
27243
- runtimeState: VacuumControlStatusSchema
27832
+ runtimeState: VacuumControlStatusSchema,
27833
+ /**
27834
+ * Runtime-state durability: **session** — as `media-player` — a restored `state: cleaning` is a robot that is not cleaning.
27835
+ *
27836
+ * See `RuntimeStateDurability`. Enforced by
27837
+ * `scripts/check-runtime-state-durability.ts`.
27838
+ */
27839
+ durability: "session"
27244
27840
  };
27245
27841
  /**
27246
27842
  * Pipe / water / gas valve cap. Models HA `valve.*` entities — anything
@@ -27310,7 +27906,14 @@ var valveCapability = {
27310
27906
  * Runtime-state slice — mirrored by the kernel. UI controls watch the
27311
27907
  * slice for live position changes during a move.
27312
27908
  */
27313
- runtimeState: ValveStatusSchema
27909
+ runtimeState: ValveStatusSchema,
27910
+ /**
27911
+ * Runtime-state durability: **session** — as `brightness`.
27912
+ *
27913
+ * See `RuntimeStateDurability`. Enforced by
27914
+ * `scripts/check-runtime-state-durability.ts`.
27915
+ */
27916
+ durability: "session"
27314
27917
  };
27315
27918
  /**
27316
27919
  * Vibration / shake / impact sensor. Drives Home Assistant
@@ -27332,7 +27935,17 @@ var vibrationCapability = {
27332
27935
  schema: VibrationStatusSchema,
27333
27936
  kind: "push"
27334
27937
  },
27335
- runtimeState: VibrationStatusSchema
27938
+ runtimeState: VibrationStatusSchema,
27939
+ /**
27940
+ * Runtime-state durability: **restored** — as `smoke`.
27941
+ *
27942
+ * See `RuntimeStateDurability`. Enforced by
27943
+ * `scripts/check-runtime-state-durability.ts`.
27944
+ */
27945
+ durability: "restored",
27946
+ /** Clock fields: written, but excluded from the compare that decides
27947
+ * whether persisting is worth a SQLite commit. */
27948
+ volatileStateFields: ["lastChangedAt"]
27336
27949
  };
27337
27950
  /**
27338
27951
  * Water heater / boiler cap. Models HA `water_heater.*` entities — a
@@ -27406,7 +28019,14 @@ var waterHeaterCapability = {
27406
28019
  * Runtime-state slice — mirrored by the kernel. UI controls watch the
27407
28020
  * slice for live temperature / mode / away changes.
27408
28021
  */
27409
- runtimeState: WaterHeaterStatusSchema
28022
+ runtimeState: WaterHeaterStatusSchema,
28023
+ /**
28024
+ * Runtime-state durability: **session** — as `climate-control`.
28025
+ *
28026
+ * See `RuntimeStateDurability`. Enforced by
28027
+ * `scripts/check-runtime-state-durability.ts`.
28028
+ */
28029
+ durability: "session"
27410
28030
  };
27411
28031
  /**
27412
28032
  * Weather provider cap. Models HA `weather.*` entities — a read-only
@@ -27465,7 +28085,14 @@ var weatherCapability = {
27465
28085
  * Runtime-state slice — mirrored by the kernel. The UI reads the
27466
28086
  * current conditions directly from the slice on each weather push.
27467
28087
  */
27468
- runtimeState: WeatherStatusSchema
28088
+ runtimeState: WeatherStatusSchema,
28089
+ /**
28090
+ * Runtime-state durability: **session** — a forecast is stale the moment the hub is down; the provider re-fetches on connect.
28091
+ *
28092
+ * See `RuntimeStateDurability`. Enforced by
28093
+ * `scripts/check-runtime-state-durability.ts`.
28094
+ */
28095
+ durability: "session"
27469
28096
  };
27470
28097
  /**
27471
28098
  * Per-zone occupancy aggregation produced by the analytics frame
@@ -27627,7 +28254,14 @@ var zoneAnalyticsCapability = {
27627
28254
  * automatically; the explicit `getCurrentSnapshot` cap method is
27628
28255
  * still useful for one-off polls without a subscription.
27629
28256
  */
27630
- runtimeState: CameraOccupancySnapshotSchema
28257
+ runtimeState: CameraOccupancySnapshotSchema,
28258
+ /**
28259
+ * Runtime-state durability: **session** — per-frame analytics; with `audio-metrics` it is ~90 % of the offered write rate. Re-derived on the next frame.
28260
+ *
28261
+ * See `RuntimeStateDurability`. Enforced by
28262
+ * `scripts/check-runtime-state-durability.ts`.
28263
+ */
28264
+ durability: "session"
27631
28265
  };
27632
28266
  /**
27633
28267
  * Stages a {@link ZoneRule} can apply to. Discriminator on the rules
@@ -27705,7 +28339,14 @@ var zoneRulesCapability = {
27705
28339
  motion: zod.z.array(ZoneRuleSchema).readonly(),
27706
28340
  detection: zod.z.array(ZoneRuleSchema).readonly(),
27707
28341
  package: zod.z.array(ZoneRuleSchema).readonly()
27708
- })
28342
+ }),
28343
+ /**
28344
+ * Runtime-state durability: **restored** — operator intent, mutation-only, same argument as `zones`.
28345
+ *
28346
+ * See `RuntimeStateDurability`. Enforced by
28347
+ * `scripts/check-runtime-state-durability.ts`.
28348
+ */
28349
+ durability: "restored"
27709
28350
  };
27710
28351
  /**
27711
28352
  * Runtime defaults -- used by ConfigManager.get() for backward compatibility
@@ -33922,6 +34563,279 @@ Object.freeze({
33922
34563
  "network-access": "ingress",
33923
34564
  "smtp-provider": "email"
33924
34565
  });
34566
+ /**
34567
+ * Per-cap runtime-state policy, projected from every `*.cap.ts` that declares
34568
+ * `runtimeState`. 62 caps: 33 `restored`, 29 `session`.
34569
+ *
34570
+ * A cap absent from this map has no runtime-state slice at all. A cap PRESENT
34571
+ * with `durability: 'session'` has one and has decided not to keep it.
34572
+ */
34573
+ var RUNTIME_STATE_POLICY = {
34574
+ "air-quality-sensor": {
34575
+ durability: "restored",
34576
+ volatileFields: ["lastFetchedAt"]
34577
+ },
34578
+ "alarm-panel": {
34579
+ durability: "restored",
34580
+ volatileFields: ["lastChangedAt"]
34581
+ },
34582
+ "ambient-light-sensor": {
34583
+ durability: "restored",
34584
+ volatileFields: ["lastFetchedAt"]
34585
+ },
34586
+ "audio-metrics": {
34587
+ durability: "session",
34588
+ volatileFields: []
34589
+ },
34590
+ "automation-control": {
34591
+ durability: "session",
34592
+ volatileFields: []
34593
+ },
34594
+ "battery": {
34595
+ durability: "restored",
34596
+ volatileFields: ["lastUpdated"]
34597
+ },
34598
+ "binary": {
34599
+ durability: "restored",
34600
+ volatileFields: ["lastChangedAt"]
34601
+ },
34602
+ "brightness": {
34603
+ durability: "session",
34604
+ volatileFields: []
34605
+ },
34606
+ "camera-streams": {
34607
+ durability: "session",
34608
+ volatileFields: []
34609
+ },
34610
+ "carbon-monoxide": {
34611
+ durability: "restored",
34612
+ volatileFields: ["lastChangedAt"]
34613
+ },
34614
+ "climate-control": {
34615
+ durability: "session",
34616
+ volatileFields: []
34617
+ },
34618
+ "color": {
34619
+ durability: "session",
34620
+ volatileFields: []
34621
+ },
34622
+ "connectivity": {
34623
+ durability: "restored",
34624
+ volatileFields: ["lastChangedAt"]
34625
+ },
34626
+ "consumables": {
34627
+ durability: "session",
34628
+ volatileFields: []
34629
+ },
34630
+ "contact": {
34631
+ durability: "restored",
34632
+ volatileFields: ["lastChangedAt"]
34633
+ },
34634
+ "control": {
34635
+ durability: "session",
34636
+ volatileFields: []
34637
+ },
34638
+ "cover": {
34639
+ durability: "restored",
34640
+ volatileFields: ["lastChangedAt"]
34641
+ },
34642
+ "day-night": {
34643
+ durability: "restored",
34644
+ volatileFields: ["lastFetchedAt"]
34645
+ },
34646
+ "device-discovery": {
34647
+ durability: "session",
34648
+ volatileFields: []
34649
+ },
34650
+ "device-status": {
34651
+ durability: "restored",
34652
+ volatileFields: ["lastChangedAt"]
34653
+ },
34654
+ "doorbell": {
34655
+ durability: "restored",
34656
+ volatileFields: []
34657
+ },
34658
+ "enum-sensor": {
34659
+ durability: "restored",
34660
+ volatileFields: ["lastFetchedAt"]
34661
+ },
34662
+ "event-emitter": {
34663
+ durability: "session",
34664
+ volatileFields: []
34665
+ },
34666
+ "fan-control": {
34667
+ durability: "session",
34668
+ volatileFields: []
34669
+ },
34670
+ "feature-probe": {
34671
+ durability: "session",
34672
+ volatileFields: []
34673
+ },
34674
+ "flood": {
34675
+ durability: "restored",
34676
+ volatileFields: ["lastChangedAt"]
34677
+ },
34678
+ "gas": {
34679
+ durability: "restored",
34680
+ volatileFields: ["lastChangedAt"]
34681
+ },
34682
+ "humidifier": {
34683
+ durability: "session",
34684
+ volatileFields: []
34685
+ },
34686
+ "humidity-sensor": {
34687
+ durability: "restored",
34688
+ volatileFields: ["lastFetchedAt"]
34689
+ },
34690
+ "image": {
34691
+ durability: "session",
34692
+ volatileFields: []
34693
+ },
34694
+ "image-settings": {
34695
+ durability: "restored",
34696
+ volatileFields: ["lastFetchedAt"]
34697
+ },
34698
+ "lawn-mower-control": {
34699
+ durability: "session",
34700
+ volatileFields: []
34701
+ },
34702
+ "lock-control": {
34703
+ durability: "restored",
34704
+ volatileFields: ["lastChangedAt"]
34705
+ },
34706
+ "media-player": {
34707
+ durability: "session",
34708
+ volatileFields: []
34709
+ },
34710
+ "motion": {
34711
+ durability: "session",
34712
+ volatileFields: []
34713
+ },
34714
+ "motion-trigger": {
34715
+ durability: "session",
34716
+ volatileFields: []
34717
+ },
34718
+ "motion-zones": {
34719
+ durability: "restored",
34720
+ volatileFields: ["lastFetchedAt"]
34721
+ },
34722
+ "native-object-detection": {
34723
+ durability: "restored",
34724
+ volatileFields: ["lastFetchedAt"]
34725
+ },
34726
+ "notifier": {
34727
+ durability: "session",
34728
+ volatileFields: []
34729
+ },
34730
+ "numeric-sensor": {
34731
+ durability: "restored",
34732
+ volatileFields: ["lastFetchedAt"]
34733
+ },
34734
+ "pet-feeder": {
34735
+ durability: "session",
34736
+ volatileFields: []
34737
+ },
34738
+ "power-meter": {
34739
+ durability: "restored",
34740
+ volatileFields: ["lastFetchedAt"]
34741
+ },
34742
+ "presence": {
34743
+ durability: "restored",
34744
+ volatileFields: ["lastChangedAt"]
34745
+ },
34746
+ "pressure-sensor": {
34747
+ durability: "restored",
34748
+ volatileFields: ["lastFetchedAt"]
34749
+ },
34750
+ "privacy-mask": {
34751
+ durability: "restored",
34752
+ volatileFields: ["lastFetchedAt"]
34753
+ },
34754
+ "ptz-autotrack": {
34755
+ durability: "session",
34756
+ volatileFields: []
34757
+ },
34758
+ "scene-monitor": {
34759
+ durability: "session",
34760
+ volatileFields: []
34761
+ },
34762
+ "script-runner": {
34763
+ durability: "session",
34764
+ volatileFields: []
34765
+ },
34766
+ "smoke": {
34767
+ durability: "restored",
34768
+ volatileFields: ["lastChangedAt"]
34769
+ },
34770
+ "stream-params": {
34771
+ durability: "restored",
34772
+ volatileFields: ["lastFetchedAt"]
34773
+ },
34774
+ "switch": {
34775
+ durability: "restored",
34776
+ volatileFields: ["lastChangedAt"]
34777
+ },
34778
+ "tamper": {
34779
+ durability: "restored",
34780
+ volatileFields: ["lastChangedAt"]
34781
+ },
34782
+ "temperature-sensor": {
34783
+ durability: "restored",
34784
+ volatileFields: ["lastFetchedAt"]
34785
+ },
34786
+ "update": {
34787
+ durability: "session",
34788
+ volatileFields: []
34789
+ },
34790
+ "vacuum-control": {
34791
+ durability: "session",
34792
+ volatileFields: []
34793
+ },
34794
+ "valve": {
34795
+ durability: "session",
34796
+ volatileFields: []
34797
+ },
34798
+ "vibration": {
34799
+ durability: "restored",
34800
+ volatileFields: ["lastChangedAt"]
34801
+ },
34802
+ "water-heater": {
34803
+ durability: "session",
34804
+ volatileFields: []
34805
+ },
34806
+ "weather": {
34807
+ durability: "session",
34808
+ volatileFields: []
34809
+ },
34810
+ "zone-analytics": {
34811
+ durability: "session",
34812
+ volatileFields: []
34813
+ },
34814
+ "zone-rules": {
34815
+ durability: "restored",
34816
+ volatileFields: []
34817
+ },
34818
+ "zones": {
34819
+ durability: "restored",
34820
+ volatileFields: []
34821
+ }
34822
+ };
34823
+ /**
34824
+ * The policy for `capName`. An UNKNOWN cap resolves to `'session'` — an
34825
+ * addon-private slice the codegen has never seen is not persisted until its
34826
+ * capability says so, which is the safe direction: the cost of a lost session
34827
+ * value is a cold window, the cost of an unasked-for persist is a commit per
34828
+ * second on the fleet's busiest write path.
34829
+ */
34830
+ function runtimeStatePolicyFor(capName) {
34831
+ return RUNTIME_STATE_POLICY[capName] ?? SESSION_ONLY_POLICY;
34832
+ }
34833
+ /** Shared fallback instance — see {@link runtimeStatePolicyFor}. */
34834
+ var SESSION_ONLY_POLICY = {
34835
+ durability: "session",
34836
+ volatileFields: []
34837
+ };
34838
+ new Map(AUDIO_MACRO_LABELS.flatMap((macro) => macro.icon === void 0 ? [] : [[macro.id, macro.icon]]));
33925
34839
  new Set(["devices", "classes"]);
33926
34840
  /**
33927
34841
  * TimelapseRule — the STANDALONE scheduled timelapse producer's rule model.
@@ -34950,6 +35864,12 @@ Object.defineProperty(exports, "resolveCapMount", {
34950
35864
  return resolveCapMount;
34951
35865
  }
34952
35866
  });
35867
+ Object.defineProperty(exports, "runtimeStatePolicyFor", {
35868
+ enumerable: true,
35869
+ get: function() {
35870
+ return runtimeStatePolicyFor;
35871
+ }
35872
+ });
34953
35873
  Object.defineProperty(exports, "scopeKey", {
34954
35874
  enumerable: true,
34955
35875
  get: function() {