@camstack/addon-post-analysis 1.2.655 → 1.2.656

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 (15) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/{clip-model-registry-C-en5vSD.js → clip-model-registry-BQ_2RsIp.js} +473 -5
  3. package/dist/{clip-model-registry-_b3KHYFm.mjs → clip-model-registry-C06M8A8U.mjs} +473 -5
  4. package/dist/embedding-encoder/index.js +1 -1
  5. package/dist/embedding-encoder/index.mjs +1 -1
  6. package/dist/pipeline-analytics/_stub.js +2 -2
  7. package/dist/pipeline-analytics/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-CF-Mts9j.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-8vah5-KD.mjs} +2 -2
  8. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-YXyP9GJm.mjs +26 -0
  9. package/dist/pipeline-analytics/{_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DXQUFp7P.mjs → _virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-gv38vKug.mjs} +1 -1
  10. package/dist/pipeline-analytics/{hostInit-BSfz5s98.mjs → hostInit-0O7AUcsV.mjs} +2 -2
  11. package/dist/pipeline-analytics/index.js +20 -2
  12. package/dist/pipeline-analytics/index.mjs +20 -2
  13. package/dist/pipeline-analytics/remoteEntry.js +1 -1
  14. package/package.json +1 -1
  15. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-C7OJ7wek.mjs +0 -26
package/CHANGELOG.md CHANGED
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.2.656] - 2026-10-31
11
+
12
+ ### Changed
13
+
14
+ - A lock reporting door-open counts as an opening for the alarm.
15
+
10
16
  ## [1.2.655] - 2026-10-31
11
17
 
12
18
  ### Changed
@@ -5676,7 +5676,7 @@ var ZodIssueCode = {
5676
5676
  var ZodFirstPartyTypeKind;
5677
5677
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5678
5678
  //#endregion
5679
- //#region ../types/dist/sleep-CeyhrcOk.mjs
5679
+ //#region ../types/dist/sleep-SX9bkW3_.mjs
5680
5680
  /**
5681
5681
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5682
5682
  * window to float samples (D455).
@@ -9347,6 +9347,7 @@ var CAP_NAMES = Object.freeze([
9347
9347
  "remote-layout-components",
9348
9348
  "running-state",
9349
9349
  "scene-monitor",
9350
+ "schedulers",
9350
9351
  "script-runner",
9351
9352
  "server-management",
9352
9353
  "settings-store",
@@ -10292,7 +10293,8 @@ Object.freeze({
10292
10293
  "unlocked",
10293
10294
  "locking",
10294
10295
  "unlocking",
10295
- "jammed"
10296
+ "jammed",
10297
+ "door-open"
10296
10298
  ]
10297
10299
  }],
10298
10300
  "media-player": [
@@ -17786,6 +17788,11 @@ var ACTUATOR_CAP_VOCABULARY = {
17786
17788
  value: "jammed",
17787
17789
  label: t("Jammed", "Inceppata"),
17788
17790
  phrase: t("When {device} jams", "Quando {device} si inceppa")
17791
+ },
17792
+ {
17793
+ value: "door-open",
17794
+ label: t("Door open", "Porta aperta"),
17795
+ phrase: t("When the door of {device} opens", "Quando la porta di {device} si apre")
17789
17796
  }
17790
17797
  ],
17791
17798
  icon: "lock"
@@ -21276,6 +21283,7 @@ var SYSTEM_CAP_VOCABULARY = {
21276
21283
  records: system(INTERNAL),
21277
21284
  remote: system("the per-device remote setup — authored in the Customize remote editor, sent through the remote UI"),
21278
21285
  "remote-layout-components": system("the palette of the remote template editor — read-only data, never actuated"),
21286
+ schedulers: system("time schedulers — authored on their own page, not device actions"),
21279
21287
  "server-management": system(CLUSTER),
21280
21288
  "settings-store": system(INTERNAL),
21281
21289
  "smtp-provider": system(INTERNAL),
@@ -42399,6 +42407,122 @@ var AutomationWhenSchema = lazy(() => discriminatedUnion("kind", [
42399
42407
  StationaryPresentLeafSchema,
42400
42408
  ExpressionLeafSchema
42401
42409
  ]));
42410
+ var EVENT_KINDS = new Set([
42411
+ "device-becomes",
42412
+ "device-event",
42413
+ "schedule",
42414
+ "manual",
42415
+ "interval",
42416
+ "detection",
42417
+ "stationary"
42418
+ ]);
42419
+ function isEventLeaf(node) {
42420
+ return EVENT_KINDS.has(node.kind);
42421
+ }
42422
+ function isLeaf(node) {
42423
+ return node.kind !== "all" && node.kind !== "any" && node.kind !== "not";
42424
+ }
42425
+ /** Depth of a tree, root container = 1. A bare leaf is depth 1. */
42426
+ function whenDepth(node) {
42427
+ if (isLeaf(node)) return 1;
42428
+ if (node.kind === "not") return 1 + whenDepth(node.child);
42429
+ let deepest = 0;
42430
+ for (const child of node.children) deepest = Math.max(deepest, whenDepth(child));
42431
+ return 1 + deepest;
42432
+ }
42433
+ /** Leaves only — containers do not count toward the leaf budget. */
42434
+ function countWhenLeaves(node) {
42435
+ if (isLeaf(node)) return 1;
42436
+ if (node.kind === "not") return countWhenLeaves(node.child);
42437
+ let total = 0;
42438
+ for (const child of node.children) total += countWhenLeaves(child);
42439
+ return total;
42440
+ }
42441
+ /** Every leaf with its path (`when`, `when.0`, `when.0.1`, `when.0` under a `not`). */
42442
+ function forEachLeaf(node, visit, path = "when") {
42443
+ if (isLeaf(node)) {
42444
+ visit(node, path);
42445
+ return;
42446
+ }
42447
+ if (node.kind === "not") {
42448
+ forEachLeaf(node.child, visit, `${path}.0`);
42449
+ return;
42450
+ }
42451
+ node.children.forEach((child, i) => {
42452
+ forEachLeaf(child, visit, `${path}.${i}`);
42453
+ });
42454
+ }
42455
+ function hasEventLeaves(node) {
42456
+ let found = false;
42457
+ forEachLeaf(node, (leaf) => {
42458
+ if (isEventLeaf(leaf)) found = true;
42459
+ });
42460
+ return found;
42461
+ }
42462
+ function hasEmptyContainer(node) {
42463
+ if (isLeaf(node)) return false;
42464
+ if (node.kind === "not") return hasEmptyContainer(node.child);
42465
+ if (node.children.length === 0) return true;
42466
+ return node.children.some(hasEmptyContainer);
42467
+ }
42468
+ var LEAF_WORDS = {
42469
+ "device-becomes": "a device value that becomes",
42470
+ "device-event": "a device event",
42471
+ schedule: "a schedule",
42472
+ manual: "a manual run",
42473
+ interval: "an interval",
42474
+ detection: "a detection",
42475
+ stationary: "a parked object appearing or leaving"
42476
+ };
42477
+ function say(kind) {
42478
+ return LEAF_WORDS[kind] ?? kind;
42479
+ }
42480
+ /**
42481
+ * The cheapest set of event leaves that makes `node` true, with negation pushed
42482
+ * down to the leaves first (De Morgan), so `not(any(A, B))` and `all(not A,
42483
+ * not B)` are the same shape to the check. A negated event is its own error: an
42484
+ * event is an instant, "the event did not occur" is true at every other moment.
42485
+ */
42486
+ function eventNeed(node, path, negated) {
42487
+ if (isLeaf(node)) {
42488
+ if (!isEventLeaf(node)) return { paths: [] };
42489
+ if (negated) return { error: `"not" is applied to ${say(node.kind)} (${path}) — an event is an instant, so "it did not happen" is true at every other moment and can never start a run. Negate a state ("is") instead, or remove the "not"` };
42490
+ return { paths: [{
42491
+ path,
42492
+ kind: node.kind
42493
+ }] };
42494
+ }
42495
+ if (node.kind === "not") return eventNeed(node.child, `${path}.0`, !negated);
42496
+ const conjunctive = node.kind === "all" !== negated;
42497
+ const parts = [];
42498
+ for (let i = 0; i < node.children.length; i += 1) {
42499
+ const child = node.children[i];
42500
+ if (child === void 0) continue;
42501
+ const need = eventNeed(child, `${path}.${i}`, negated);
42502
+ if ("error" in need) return need;
42503
+ parts.push(need);
42504
+ }
42505
+ if (conjunctive) return { paths: parts.flatMap((p) => p.paths) };
42506
+ let best;
42507
+ for (const part of parts) if (best === void 0 || part.paths.length < best.paths.length) best = part;
42508
+ return best ?? { paths: [] };
42509
+ }
42510
+ /**
42511
+ * Author-time bounds and sense check of a `when` tree. Returns `null` when it
42512
+ * is legal, else a message the editor shows verbatim.
42513
+ */
42514
+ function validateWhenTree(when) {
42515
+ if (hasEmptyContainer(when)) return "a group is empty — group existing rows instead of leaving a container to fill";
42516
+ const depth = whenDepth(when);
42517
+ if (depth > 4) return `the rules nest ${depth} levels deep — the limit is 4. "not (any of …)" is the same as "all of (not …)", which is one level shallower`;
42518
+ const leaves = countWhenLeaves(when);
42519
+ if (leaves > 32) return `the rules use ${leaves} rows — the limit is 32`;
42520
+ const need = eventNeed(when, "when", false);
42521
+ if ("error" in need) return need.error;
42522
+ const [first, second] = need.paths;
42523
+ if (first !== void 0 && second !== void 0) return `${say(first.kind)} (${first.path}) and ${say(second.kind)} (${second.path}) would both have to happen at the same instant, and an event happens at one moment — this can never run. Use "any of" to start on either, or turn one of them into a state ("is") that must already hold`;
42524
+ return null;
42525
+ }
42402
42526
  /**
42403
42527
  * The recipe shape before the single `when` tree: a flat list of triggers
42404
42528
  * (OR'd, each an instant) and an optional condition tree. Stored recipes —
@@ -42754,6 +42878,187 @@ function convertLegacyRecipe(legacy) {
42754
42878
  var AutomationRecipeSchema = union([CurrentAutomationRecipeSchema, LegacyAutomationRecipeSchema.transform(convertLegacyRecipe)]);
42755
42879
  new Set(Object.values(COCO_TO_MACRO.mapping));
42756
42880
  /**
42881
+ * Schedulers (D983) — an entity that performs actions over the day.
42882
+ *
42883
+ * A scheduler has profiles; a profile has weekdays and a timeline of POINTS.
42884
+ * A point is an `edge` (run once at its time), a `hold` (from this point until
42885
+ * the next point of the profile, keep the steps' effects true) or a `release`
42886
+ * (end the current hold without acting). The scheduler AND each profile carry
42887
+ * a manual `enabled` flag and an optional `activeWhen`: a `when` STATE tree
42888
+ * (facts only — an event leaf is an instant and cannot be "in force").
42889
+ *
42890
+ * This file is the data half: the schemas, and the author-time rules that
42891
+ * decide whether a scheduler can be saved at all (a hold needs an action that
42892
+ * leads to a state; a sun point needs the site location). It holds no runtime.
42893
+ */
42894
+ /** A `when` tree that is a STATE: no event leaf, and legal as a tree. */
42895
+ var SchedulerStateTreeSchema = AutomationWhenSchema.superRefine((when, ctx) => {
42896
+ if (hasEventLeaves(when)) {
42897
+ ctx.addIssue({
42898
+ code: "custom",
42899
+ message: "a scheduler condition is a state — an event (\"becomes\", \"detects\", \"at a time\") is an instant and cannot be in force"
42900
+ });
42901
+ return;
42902
+ }
42903
+ const problem = validateWhenTree(when);
42904
+ if (problem !== null) ctx.addIssue({
42905
+ code: "custom",
42906
+ message: problem
42907
+ });
42908
+ });
42909
+ /** A point's moment: a clock time or a sun event. A one-shot date is not a position on a day. */
42910
+ var SchedulerTimeSpecSchema = TimeSpecSchema.refine((spec) => spec.kind !== "date", { message: "a scheduler point is a clock time or a sun event — a one-shot date has no place on a timeline" });
42911
+ var SchedulerPointModeSchema = _enum([
42912
+ "edge",
42913
+ "hold",
42914
+ "release"
42915
+ ]);
42916
+ /** What a hold does when someone changes the device by hand. */
42917
+ var HoldOverrideSchema = discriminatedUnion("mode", [object({ mode: literal("respect") }), object({
42918
+ mode: literal("reassert"),
42919
+ /** How long the manual state is left alone before the hold puts its own back. */
42920
+ graceMs: number().int().min(0).max(24 * 36e5)
42921
+ })]);
42922
+ /** A missed edge up to this late still runs. */
42923
+ var DEFAULT_MAX_LATE_MS = 10 * 6e4;
42924
+ var SchedulerPointSchema = object({
42925
+ id: string().min(1).max(64),
42926
+ at: SchedulerTimeSpecSchema,
42927
+ mode: SchedulerPointModeSchema,
42928
+ /** The actions of an `edge` or `hold`; a `release` has none. */
42929
+ steps: array(ActionStepSchema).max(20).default([]),
42930
+ /** Checked when the point runs (an edge) or is applied (a hold). */
42931
+ conditions: SchedulerStateTreeSchema.optional(),
42932
+ /** Hold only; absent means `respect`. */
42933
+ override: HoldOverrideSchema.optional(),
42934
+ /** Hold only: re-applications per window; absent means {@link DEFAULT_MAX_HOLD_ATTEMPTS}. */
42935
+ maxHoldAttempts: number().int().min(1).max(20).optional()
42936
+ });
42937
+ var SchedulerProfileSchema = object({
42938
+ id: string().min(1).max(64),
42939
+ name: string().min(1).max(120),
42940
+ enabled: boolean().default(true),
42941
+ activeWhen: SchedulerStateTreeSchema.optional(),
42942
+ days: array(WeekdayKeySchema).min(1).max(7),
42943
+ points: array(SchedulerPointSchema).max(50)
42944
+ });
42945
+ /** What an operator writes. */
42946
+ var SchedulerInputSchema = object({
42947
+ name: string().min(1).max(120),
42948
+ enabled: boolean().default(true),
42949
+ activeWhen: SchedulerStateTreeSchema.optional(),
42950
+ /** Higher wins when two holds want the same device in different states. */
42951
+ priority: number().int().min(0).max(100).default(0),
42952
+ maxLateMs: number().int().min(1e3).max(24 * 36e5).default(DEFAULT_MAX_LATE_MS),
42953
+ profiles: array(SchedulerProfileSchema).max(20)
42954
+ });
42955
+ var SchedulerSchema = SchedulerInputSchema.extend({
42956
+ id: string().min(1),
42957
+ createdAt: number(),
42958
+ updatedAt: number()
42959
+ });
42960
+ /** Every outcome a scheduler reports to the runs ledger (`AutomationRunTrace.scheduler`). */
42961
+ var SchedulerOutcomeSchema = _enum([
42962
+ "done",
42963
+ "missed",
42964
+ "inactive",
42965
+ "condition-false",
42966
+ "failed",
42967
+ "held",
42968
+ "gave-up",
42969
+ "overridden",
42970
+ "suspended-manual"
42971
+ ]);
42972
+ _enum([
42973
+ "not-found",
42974
+ "invalid-scheduler",
42975
+ "invalid-date"
42976
+ ]);
42977
+ var LOCAL_DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
42978
+ /** One point of the day, placed. `at` is `null` when the sun never crosses that day. */
42979
+ var SchedulerPreviewPointSchema = object({
42980
+ pointId: string(),
42981
+ mode: SchedulerPointModeSchema,
42982
+ at: number().nullable(),
42983
+ /** A hold: when its window ends (the next point, else the end of the day). */
42984
+ until: number().nullable(),
42985
+ /** The point's steps are held on a different scheduler's claim at this time — see `conflicts`. */
42986
+ stepCount: number().int()
42987
+ });
42988
+ var SchedulerPreviewSchema = object({
42989
+ schedulerId: string(),
42990
+ /** The site-local day previewed. */
42991
+ date: string().regex(LOCAL_DATE_PATTERN),
42992
+ timeZone: string(),
42993
+ /** Why no profile is in force, or `null` when one is. */
42994
+ idleReason: string().nullable(),
42995
+ /** The profile in force that day: first in list order whose rules hold. */
42996
+ profileId: string().nullable(),
42997
+ points: array(SchedulerPreviewPointSchema)
42998
+ });
42999
+ /** Two holds that want the same device in different states at the same time. */
43000
+ var SchedulerConflictSchema = object({
43001
+ deviceId: number().int(),
43002
+ cap: string(),
43003
+ field: string(),
43004
+ mine: object({
43005
+ profileId: string(),
43006
+ pointId: string(),
43007
+ value: union([
43008
+ string(),
43009
+ number(),
43010
+ boolean()
43011
+ ]),
43012
+ priority: number().int()
43013
+ }),
43014
+ other: object({
43015
+ schedulerId: string(),
43016
+ schedulerName: string(),
43017
+ profileId: string(),
43018
+ pointId: string(),
43019
+ value: union([
43020
+ string(),
43021
+ number(),
43022
+ boolean()
43023
+ ]),
43024
+ priority: number().int()
43025
+ }),
43026
+ /** The overlapping stretch, as site-local minutes of the day. */
43027
+ fromMinute: number().int(),
43028
+ toMinute: number().int(),
43029
+ /** `mine` | `other` | `tie` — who holds when it happens (a tie: the one that started first). */
43030
+ winner: _enum([
43031
+ "mine",
43032
+ "other",
43033
+ "tie"
43034
+ ])
43035
+ });
43036
+ var HoldTargetStatusSchema = _enum([
43037
+ "pending",
43038
+ "held",
43039
+ "suspended-manual",
43040
+ "gave-up",
43041
+ "overridden"
43042
+ ]);
43043
+ var SchedulerStatusSchema = object({
43044
+ schedulerId: string(),
43045
+ profileId: string().nullable(),
43046
+ /** The hold in force right now, with where each target stands. */
43047
+ hold: object({
43048
+ pointId: string(),
43049
+ until: number(),
43050
+ /** `true` while the scheduler or profile `activeWhen` is false. */
43051
+ suspendedInactive: boolean(),
43052
+ targets: array(object({
43053
+ deviceId: number().int(),
43054
+ cap: string(),
43055
+ field: string(),
43056
+ status: HoldTargetStatusSchema,
43057
+ attempts: number().int()
43058
+ }))
43059
+ }).nullable()
43060
+ });
43061
+ /**
42757
43062
  * Run traces — what an automation (or, later, an Action run) DID, node by node,
42758
43063
  * so the editor can paint every block green or red with its reason.
42759
43064
  *
@@ -42889,7 +43194,13 @@ var AutomationRunTraceSchema = object({
42889
43194
  /** How many identical consecutive skips this trace stands for (>= 1). */
42890
43195
  repeat: number().int().min(1),
42891
43196
  /** When the latest of those repeats happened. */
42892
- lastAt: number()
43197
+ lastAt: number(),
43198
+ /**
43199
+ * A scheduler point's own outcome (D983). `outcome` carries the closest
43200
+ * automation outcome so a reader that does not know schedulers still reads
43201
+ * the trace; this field says exactly what happened.
43202
+ */
43203
+ scheduler: SchedulerOutcomeSchema.optional()
42893
43204
  });
42894
43205
  /**
42895
43206
  * What the hub's `runs` ledger holds for one owner (`automation:<blockId>` or
@@ -46430,6 +46741,7 @@ method(object({
46430
46741
  kind: "mutation",
46431
46742
  auth: "admin"
46432
46743
  }), method(object({ blockIds: array(string()) }), object({ states: array(CompositionBlockStateSchema) }), { auth: "admin" });
46744
+ DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.PetFountain, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Gateway, DeviceType.Camera, DeviceType.Lock, DeviceType.Camera, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
46433
46745
  var NUMBER = {
46434
46746
  kind: "fixed",
46435
46747
  result: ["number"]
@@ -67251,6 +67563,43 @@ method(object({}), array(ActionEntrySchema), { auth: "admin" }), method(object({
67251
67563
  auth: "admin"
67252
67564
  });
67253
67565
  /**
67566
+ * schedulers — timelines of edge and hold points that perform actions over the
67567
+ * day (D983). Provided by the core-blocks builtin on the hub, beside `actions`:
67568
+ * the same runs ledger (owner `scheduler:<id>`), the same target resolver, the
67569
+ * same step runner.
67570
+ *
67571
+ * The hub runs ONE timer for the next point across every scheduler. A save is
67572
+ * refused with its reason (`[invalid-scheduler] …`) when a hold has a step that
67573
+ * leads to no state, or a sun point has no site location to read.
67574
+ */
67575
+ var SchedulerIdInput = object({ schedulerId: string().min(1) });
67576
+ method(object({}), array(SchedulerSchema), { auth: "admin" }), method(SchedulerIdInput, object({ scheduler: SchedulerSchema.nullable() }), { auth: "admin" }), method(object({ scheduler: SchedulerInputSchema }), object({ scheduler: SchedulerSchema }), {
67577
+ kind: "mutation",
67578
+ auth: "admin"
67579
+ }), method(object({
67580
+ schedulerId: string().min(1),
67581
+ scheduler: SchedulerInputSchema
67582
+ }), object({ scheduler: SchedulerSchema }), {
67583
+ kind: "mutation",
67584
+ auth: "admin"
67585
+ }), method(SchedulerIdInput, _void(), {
67586
+ kind: "mutation",
67587
+ auth: "admin"
67588
+ }), method(object({
67589
+ schedulerId: string().min(1),
67590
+ profileId: string().min(1).optional(),
67591
+ enabled: boolean()
67592
+ }), object({ scheduler: SchedulerSchema }), {
67593
+ kind: "mutation",
67594
+ auth: "admin"
67595
+ }), method(object({
67596
+ schedulerId: string().min(1),
67597
+ date: string().regex(LOCAL_DATE_PATTERN).optional()
67598
+ }), SchedulerPreviewSchema, { auth: "admin" }), method(object({
67599
+ scheduler: SchedulerInputSchema,
67600
+ schedulerId: string().min(1).optional()
67601
+ }), object({ conflicts: array(SchedulerConflictSchema) }), { auth: "admin" }), method(object({}), array(SchedulerStatusSchema), { auth: "admin" }), method(SchedulerIdInput, object({ traces: array(AutomationRunTraceSchema) }), { auth: "admin" });
67602
+ /**
67254
67603
  * actions — the ONE surface for runnable actions, for the UI and for
67255
67604
  * automations. Provided by the core-blocks builtin on the hub.
67256
67605
  *
@@ -71556,6 +71905,8 @@ var IntegrationWithStateSchema = object({
71556
71905
  name: string(),
71557
71906
  enabled: boolean(),
71558
71907
  info: record(string(), unknown()).readonly(),
71908
+ /** The discovery candidate this integration was set up from (D984). */
71909
+ originStableId: string().optional(),
71559
71910
  createdAt: number(),
71560
71911
  updatedAt: number(),
71561
71912
  processState: string()
@@ -71566,6 +71917,8 @@ var IntegrationLiteSchema = object({
71566
71917
  name: string(),
71567
71918
  enabled: boolean(),
71568
71919
  info: record(string(), unknown()).readonly(),
71920
+ /** The discovery candidate this integration was set up from (D984). */
71921
+ originStableId: string().optional(),
71569
71922
  createdAt: number(),
71570
71923
  updatedAt: number()
71571
71924
  });
@@ -71663,6 +72016,8 @@ var CreateIntegrationInputSchema = object({
71663
72016
  name: string(),
71664
72017
  enabled: boolean().optional(),
71665
72018
  info: record(string(), unknown()).optional(),
72019
+ /** `stableId` of the discovery candidate the form was seeded from (D984). */
72020
+ originStableId: string().optional(),
71666
72021
  settings: record(string(), unknown()).optional(),
71667
72022
  /** Keys of `settings` the form's schema declares secret (by type) — kept in
71668
72023
  * the keychain, not the table (D787). */
@@ -72443,12 +72798,22 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
72443
72798
  * reports `LockEntityFeature.OPEN` (bit value 1) in HA
72444
72799
  * `supported_features`.
72445
72800
  */
72801
+ /**
72802
+ * `door-open` (D984): the linked door contact reads open, so the bolt cannot be
72803
+ * thrown. It is the lock's REAL reported state, written into the mirrored slice
72804
+ * by the door-contact Customize extension — never a provider's own value, and
72805
+ * never a projection a reader has to compute. Precedence: a native `jammed`
72806
+ * wins; otherwise an open contact reports `door-open` whatever the native state
72807
+ * says (`locked` included); a closed or unknown contact leaves the native state.
72808
+ * A `lock()` is refused while the state is `door-open`; `unlock()` never is.
72809
+ */
72446
72810
  var LockStateSchema = _enum([
72447
72811
  "locked",
72448
72812
  "unlocked",
72449
72813
  "locking",
72450
72814
  "unlocking",
72451
- "jammed"
72815
+ "jammed",
72816
+ "door-open"
72452
72817
  ]);
72453
72818
  var LockControlStatusSchema = object({
72454
72819
  /** Lifecycle state of the lock. `jammed` means the motor reported
@@ -72457,6 +72822,38 @@ var LockControlStatusSchema = object({
72457
72822
  /** Ms epoch when the slice was last updated. */
72458
72823
  lastChangedAt: number()
72459
72824
  });
72825
+ /**
72826
+ * "Door contact" Customize extension (D984): the ONE extension that replaces a
72827
+ * native field. `state` is listed in `overridable` for this target, so the
72828
+ * validator and the guard accept it and nothing else.
72829
+ */
72830
+ var lockControlCustomize = {
72831
+ version: 1,
72832
+ overridable: [{
72833
+ path: "state",
72834
+ by: "door-contact"
72835
+ }],
72836
+ targets: [{
72837
+ id: "door-contact",
72838
+ cardinality: "scalar",
72839
+ vocabulary: {
72840
+ cap: "lock-control",
72841
+ stateField: "state"
72842
+ },
72843
+ deviceTypes: [DeviceType.Lock],
72844
+ apply: "replace",
72845
+ path: "state",
72846
+ override: {
72847
+ whenSourceTrue: "door-open",
72848
+ unlessNative: ["jammed"]
72849
+ },
72850
+ sources: [{
72851
+ kind: "binary",
72852
+ transforms: [{ kind: "identity" }]
72853
+ }],
72854
+ sourceReport: { status: "assignment-status" }
72855
+ }]
72856
+ };
72460
72857
  var lockControlCapability = {
72461
72858
  name: "lock-control",
72462
72859
  scope: "device",
@@ -72502,6 +72899,7 @@ var lockControlCapability = {
72502
72899
  * transitions.
72503
72900
  */
72504
72901
  runtimeState: LockControlStatusSchema,
72902
+ customize: lockControlCustomize,
72505
72903
  /**
72506
72904
  * Runtime-state durability: **restored** — a lock left locked must still read locked.
72507
72905
  *
@@ -81016,7 +81414,6 @@ discriminatedUnion("kind", [object({
81016
81414
  })]);
81017
81415
  DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
81018
81416
  SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
81019
- DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.PetFountain, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Gateway, DeviceType.Camera, DeviceType.Camera, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
81020
81417
  String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
81021
81418
  DeviceRole.BinarySensor, DeviceRole.MotionSensor;
81022
81419
  new Set(CAP_NAMES);
@@ -90129,6 +90526,76 @@ Object.freeze({
90129
90526
  access: "create",
90130
90527
  role: "feature:scenes"
90131
90528
  },
90529
+ "schedulers.conflicts": {
90530
+ capName: "schedulers",
90531
+ capScope: "system",
90532
+ addonId: null,
90533
+ access: "view",
90534
+ role: "admin"
90535
+ },
90536
+ "schedulers.create": {
90537
+ capName: "schedulers",
90538
+ capScope: "system",
90539
+ addonId: null,
90540
+ access: "create",
90541
+ role: "admin"
90542
+ },
90543
+ "schedulers.delete": {
90544
+ capName: "schedulers",
90545
+ capScope: "system",
90546
+ addonId: null,
90547
+ access: "delete",
90548
+ role: "admin"
90549
+ },
90550
+ "schedulers.get": {
90551
+ capName: "schedulers",
90552
+ capScope: "system",
90553
+ addonId: null,
90554
+ access: "view",
90555
+ role: "admin"
90556
+ },
90557
+ "schedulers.getStatus": {
90558
+ capName: "schedulers",
90559
+ capScope: "system",
90560
+ addonId: null,
90561
+ access: "view",
90562
+ role: "admin"
90563
+ },
90564
+ "schedulers.getTraces": {
90565
+ capName: "schedulers",
90566
+ capScope: "system",
90567
+ addonId: null,
90568
+ access: "view",
90569
+ role: "admin"
90570
+ },
90571
+ "schedulers.list": {
90572
+ capName: "schedulers",
90573
+ capScope: "system",
90574
+ addonId: null,
90575
+ access: "view",
90576
+ role: "admin"
90577
+ },
90578
+ "schedulers.preview": {
90579
+ capName: "schedulers",
90580
+ capScope: "system",
90581
+ addonId: null,
90582
+ access: "view",
90583
+ role: "admin"
90584
+ },
90585
+ "schedulers.setEnabled": {
90586
+ capName: "schedulers",
90587
+ capScope: "system",
90588
+ addonId: null,
90589
+ access: "create",
90590
+ role: "admin"
90591
+ },
90592
+ "schedulers.update": {
90593
+ capName: "schedulers",
90594
+ capScope: "system",
90595
+ addonId: null,
90596
+ access: "create",
90597
+ role: "admin"
90598
+ },
90132
90599
  "scriptRunner.getStatus": {
90133
90600
  capName: "script-runner",
90134
90601
  capScope: "device",
@@ -98714,6 +99181,7 @@ new Set([
98714
99181
  "locking",
98715
99182
  "unlocking",
98716
99183
  "jammed",
99184
+ "door-open",
98717
99185
  "on",
98718
99186
  "off",
98719
99187
  "home",