@camstack/addon-post-analysis 1.2.338 → 1.2.340

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.
@@ -48,7 +48,7 @@ under [Non-commercial models](#non-commercial-models).
48
48
 
49
49
  Training data under attribution terms:
50
50
 
51
- - **COCO 2017** (training data of `yolo26n` and 50 more): annotations CC-BY-4.0; images under their Flickr owners' terms. https://cocodataset.org/#termsofuse
51
+ - **COCO 2017** (training data of `yolo26n-seg` and 50 more): annotations CC-BY-4.0; images under their Flickr owners' terms. https://cocodataset.org/#termsofuse
52
52
  - **WIDER FACE** (training data of `yunet-2023mar`): research-oriented terms; images CC BY-NC-ND. http://shuoyang1213.me/WIDERFACE/
53
53
  - **Open Images V7** (training data of `animal-classifier`): annotations CC-BY-4.0 (Google LLC); images listed as CC-BY-2.0, no warranty. https://storage.googleapis.com/openimages/web/factsfigures_v7.html
54
54
  - **DrBimmer/vehicle-classification** (training data of `vehicle-type-v1`): CC-BY-NC-4.0 — treated as binding the trained weights (conservative reading). https://huggingface.co/datasets/DrBimmer/vehicle-classification
@@ -62,7 +62,7 @@ Training data under attribution terms:
62
62
  cards link here instead of repeating it.
63
63
  -->
64
64
 
65
- The folders `objectDetection/yolo26`, `objectDetection/yolov9` and `segmentation/yolo26-seg` of the model mirror hold Ultralytics weights,
65
+ The folders `segmentation/yolo26-seg`, `objectDetection/yolo26` and `objectDetection/yolov9` of the model mirror hold Ultralytics weights,
66
66
  modified by CamStack and distributed under AGPL-3.0. Their Corresponding Source
67
67
  is published in the mirror itself, in its **`source/`** folder,
68
68
  **https://huggingface.co/camstack/camstack-models/tree/main/source**, together
@@ -120,6 +120,7 @@ entry kept resolvable for a saved selection but no longer offered.
120
120
 
121
121
  | Catalog ids | Upstream | Code / weights | Training data | CamStack changes | Downloaded from |
122
122
  | --- | --- | --- | --- | --- | --- |
123
+ | `yolo26n-seg`, `yolo26s-seg`, `yolo26m-seg` | [Ultralytics](https://github.com/ultralytics/ultralytics) | AGPL-3.0 / AGPL-3.0 (`AGPL-3.0.txt`) | COCO 2017: annotations CC-BY-4.0; images under their Flickr owners' terms | exported to ONNX, OpenVINO IR and CoreML | mirror `segmentation/yolo26-seg` |
123
124
  | `yolo26n` (default), `yolo26s`, `yolo26m`, `yolo26l`, `yolo26x` (hidden), `yolo26n-fp16` (hidden), `yolo26n-int8`, `yolo26s-fp16` (hidden), `yolo26s-int8`, `yolo26m-fp16` (hidden), `yolo26m-int8`, `yolo26l-fp16` (hidden), `yolo26l-int8`, `yolo26n-320`, `yolo26n-320-int8`, `yolo26n-256`, `yolo26n-256-int8`, `yolo26s-320`, `yolo26s-320-int8`, `yolo26s-256`, `yolo26s-256-int8`, `yolo26m-320`, `yolo26m-320-int8`, `yolo26m-256`, `yolo26m-256-int8`, `yolo26l-320`, `yolo26l-320-int8`, `yolo26l-256`, `yolo26l-256-int8`, `yolo26x-fp16` (hidden), `yolo26x-int8` (hidden) | [Ultralytics](https://github.com/ultralytics/ultralytics) | AGPL-3.0 / AGPL-3.0 (`AGPL-3.0.txt`) | COCO 2017: annotations CC-BY-4.0; images under their Flickr owners' terms | exported to ONNX, OpenVINO IR and CoreML (scripts/build-camstack-models.py); OpenVINO FP16 export; exported to OpenVINO IR, then OpenVINO NNCF INT8 post-training quantisation; re-exported at 320×320 to ONNX, OpenVINO IR and CoreML; re-exported at 320×320 to OpenVINO IR; OpenVINO NNCF INT8 post-training quantisation; re-exported at 256×256 to ONNX, OpenVINO IR and CoreML; re-exported at 256×256 to OpenVINO IR; OpenVINO NNCF INT8 post-training quantisation | mirror `objectDetection/yolo26` |
124
125
  | `ssd-mobilenet-v2-coco-edgetpu` (default) | [Google Coral test_data](https://github.com/google-coral/test_data) | Apache-2.0 / Apache-2.0 (`Apache-2.0.txt`) | COCO 2017: annotations CC-BY-4.0; images under their Flickr owners' terms | none | https://github.com/google-coral/test_data |
125
126
  | `yolov9t-320`, `yolov9t-320-int8`, `yolov9t-640`, `yolov9t-640-int8`, `yolov9s-320`, `yolov9s-320-int8`, `yolov9s-640`, `yolov9s-640-int8`, `yolov9m-320`, `yolov9m-320-int8`, `yolov9m-640`, `yolov9m-640-int8`, `yolov9c-320`, `yolov9c-320-int8`, `yolov9c-640`, `yolov9c-640-int8` | [Ultralytics](https://github.com/ultralytics/ultralytics) | AGPL-3.0 / AGPL-3.0 (`AGPL-3.0.txt`) | COCO 2017: annotations CC-BY-4.0; images under their Flickr owners' terms | exported at 320×320 to ONNX, OpenVINO IR FP16 and CoreML; exported at 320×320 to OpenVINO IR; OpenVINO NNCF INT8 post-training quantisation; exported at 640×640 to ONNX, OpenVINO IR FP16 and CoreML; exported at 640×640 to OpenVINO IR; OpenVINO NNCF INT8 post-training quantisation | mirror `objectDetection/yolov9` |
@@ -190,12 +191,6 @@ entry kept resolvable for a saved selection but no longer offered.
190
191
  | --- | --- | --- | --- | --- | --- |
191
192
  | `u2netp` (default) | [xuebinqin/U-2-Net](https://github.com/xuebinqin/U-2-Net) | Apache-2.0 / Apache-2.0 (`Apache-2.0.txt`) | DUTS-TR: not checked | converted to ONNX, OpenVINO IR and CoreML | mirror `segmentationRefiner/u2netp` |
192
193
 
193
- ### Instance segmentation (dormant step)
194
-
195
- | Catalog ids | Upstream | Code / weights | Training data | CamStack changes | Downloaded from |
196
- | --- | --- | --- | --- | --- | --- |
197
- | `yolo26n-seg`, `yolo26s-seg`, `yolo26m-seg` | [Ultralytics](https://github.com/ultralytics/ultralytics) | AGPL-3.0 / AGPL-3.0 (`AGPL-3.0.txt`) | COCO 2017: annotations CC-BY-4.0; images under their Flickr owners' terms | exported to ONNX, OpenVINO IR and CoreML | mirror `segmentation/yolo26-seg` |
198
-
199
194
  ### Audio
200
195
 
201
196
  | Catalog ids | Upstream | Code / weights | Training data | CamStack changes | Downloaded from |
@@ -11568,8 +11568,19 @@ var LABEL_SUPPLY_STEP_IDS = [
11568
11568
  ];
11569
11569
  /** Steps whose box a root detection can BE. */
11570
11570
  var CROP_SUPPLY_STEP_IDS = ["plate-detection", "face-detection"];
11571
+ /**
11572
+ * Steps whose per-detection MASK a root detection can carry (D737). The live
11573
+ * mask step is `segmentation` — a frame-plane refiner that runs its own model
11574
+ * once per detection crop. (`instance-segmentation` is a dormant step id that
11575
+ * no camera tree carries.)
11576
+ */
11577
+ var MASK_SUPPLY_STEP_IDS = ["segmentation"];
11571
11578
  /** Every step a root model can supply. */
11572
- var ROOT_SUPPLIABLE_STEP_IDS = [...LABEL_SUPPLY_STEP_IDS, ...CROP_SUPPLY_STEP_IDS];
11579
+ var ROOT_SUPPLIABLE_STEP_IDS = [
11580
+ ...LABEL_SUPPLY_STEP_IDS,
11581
+ ...CROP_SUPPLY_STEP_IDS,
11582
+ ...MASK_SUPPLY_STEP_IDS
11583
+ ];
11573
11584
  /** Narrow a step id to a suppliable one — type guard, not a cast. */
11574
11585
  function isRootSuppliableStepId(value) {
11575
11586
  return ROOT_SUPPLIABLE_STEP_IDS.some((id) => id === value);
@@ -11748,25 +11759,36 @@ var ModelLicenseSchema = preprocess((value) => typeof value === "string" ? { wei
11748
11759
  * - `crop`: the root draws the box the step would have found (`license_plate`
11749
11760
  * for plate-detection, `face` for face-detection). The box becomes a detail
11750
11761
  * child of the `parentMacro` detection that contains it — never a track.
11762
+ * - `mask`: the root's decode emits an instance mask with every detection (a
11763
+ * YOLO26-seg root, D737) — the `segmentation` step's result, carried on the
11764
+ * detection in the shape that step produces. Derived from the model's
11765
+ * postprocessor on read, never stored by an import.
11751
11766
  */
11752
- var RootStepSupplySchema = discriminatedUnion("kind", [object({
11753
- kind: literal("label"),
11754
- stepId: _enum(LABEL_SUPPLY_STEP_IDS),
11755
- labelToEffect: record(string(), string()),
11756
- uncovered: array(string()).readonly()
11757
- }), object({
11758
- kind: literal("crop"),
11759
- stepId: _enum(CROP_SUPPLY_STEP_IDS),
11760
- rootLabels: array(string()).readonly(),
11761
- parentMacro: _enum(["vehicle", "person"]),
11762
- childClass: _enum(["plate", "face"]),
11763
- /**
11764
- * The root's smaller input side, stamped on read by `rootSuppliesOf` from
11765
- * the model entry — what a step's `minRootInputPx` gate judges. Never
11766
- * stored by an import.
11767
- */
11768
- rootInputPx: number().int().positive().optional()
11769
- })]);
11767
+ var RootStepSupplySchema = discriminatedUnion("kind", [
11768
+ object({
11769
+ kind: literal("label"),
11770
+ stepId: _enum(LABEL_SUPPLY_STEP_IDS),
11771
+ labelToEffect: record(string(), string()),
11772
+ uncovered: array(string()).readonly()
11773
+ }),
11774
+ object({
11775
+ kind: literal("crop"),
11776
+ stepId: _enum(CROP_SUPPLY_STEP_IDS),
11777
+ rootLabels: array(string()).readonly(),
11778
+ parentMacro: _enum(["vehicle", "person"]),
11779
+ childClass: _enum(["plate", "face"]),
11780
+ /**
11781
+ * The root's smaller input side, stamped on read by `rootSuppliesOf` from
11782
+ * the model entry — what a step's `minRootInputPx` gate judges. Never
11783
+ * stored by an import.
11784
+ */
11785
+ rootInputPx: number().int().positive().optional()
11786
+ }),
11787
+ object({
11788
+ kind: literal("mask"),
11789
+ stepId: _enum(MASK_SUPPLY_STEP_IDS)
11790
+ })
11791
+ ]);
11770
11792
  var ModelCatalogEntrySchema = object({
11771
11793
  id: string(),
11772
11794
  name: string(),
@@ -19575,6 +19597,12 @@ function buildViewerLink(input) {
19575
19597
  if (base === "" || isAppLinkBase(base)) return null;
19576
19598
  return `${base}${HUB_VIEWER_MOUNT}${route.path}${encodeQuery(route.query)}`;
19577
19599
  }
19600
+ var HUB_ADDRESS_ROLES = [
19601
+ "appConnections",
19602
+ "notificationTaps",
19603
+ "internal",
19604
+ "publicEndpoint"
19605
+ ];
19578
19606
  /**
19579
19607
  * Transport bounds for AI capability methods.
19580
19608
  *
@@ -24750,7 +24778,13 @@ var NcAlarmModeDelaysListSchema = array(object({
24750
24778
  * Absent = false (logged, not sent). Even when true it is not sent when that same sensor
24751
24779
  * is the one that starts the entry delay — the entry-delay notification already names it.
24752
24780
  */
24753
- notifySensorRewatched: boolean().optional()
24781
+ notifySensorRewatched: boolean().optional(),
24782
+ /**
24783
+ * D735: notify "ignored" when a sensor this arm bypassed really MOVED while armed (its own
24784
+ * change time is after the arm) and set nothing off. Absent = false (logged, not sent). A
24785
+ * re-sync, a recovery from `unavailable` or a duplicate is never announced, switch or not.
24786
+ */
24787
+ notifySensorIgnored: boolean().optional()
24754
24788
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one entry per arm mode" });
24755
24789
  var NcAlarmModeDelaysEditListSchema = array(object({
24756
24790
  mode: AlarmArmModeSchema,
@@ -24763,7 +24797,9 @@ var NcAlarmModeDelaysEditListSchema = array(object({
24763
24797
  /** D706: set the switch, or `null` to clear it (back to the default, false). */
24764
24798
  notifyDuringEntryDelay: boolean().nullable().optional(),
24765
24799
  /** D706: set the switch, or `null` to clear it (back to the default, false). */
24766
- notifySensorRewatched: boolean().nullable().optional()
24800
+ notifySensorRewatched: boolean().nullable().optional(),
24801
+ /** D735: set the switch, or `null` to clear it (back to the default, false). */
24802
+ notifySensorIgnored: boolean().nullable().optional()
24767
24803
  })).max(8).refine(uniqueModes, { message: "modeDelays: at most one edit per arm mode" });
24768
24804
  /** One switch of the alarm table: put ONE device on, or take it off, ONE mode's list. */
24769
24805
  var NcAlarmNonBlockingEditSchema = object({
@@ -39476,7 +39512,7 @@ var GetConnectionEndpointsResultSchema = object({
39476
39512
  localPort: AdvertisedLocalPortSchema
39477
39513
  });
39478
39514
  /**
39479
- * The address flagged for notification links. `baseUrl: null` = AUTO, which
39515
+ * The address flagged for notification taps (`notificationTaps`). `baseUrl: null` = AUTO, which
39480
39516
  * since D709 is the CamStack app link; `resolved` reports the effective value,
39481
39517
  * so the UI can show it either way.
39482
39518
  */
@@ -39511,8 +39547,8 @@ var ViewerEndpointsSchema = object({
39511
39547
  });
39512
39548
  /**
39513
39549
  * DEPRECATED compatibility shape of `getHubAddresses` (D729 amendment, kept
39514
- * one release for addons built against it): `cluster` is the `agents` role,
39515
- * `browser` the `signIn` role; `override` is the flagged address.
39550
+ * for addons built against it): `cluster` is the `internal` role, `browser`
39551
+ * the `publicEndpoint` role; `override` is the flagged address.
39516
39552
  */
39517
39553
  var HubAddressSnapshotSchema = object({
39518
39554
  override: string().nullable(),
@@ -39528,15 +39564,11 @@ var HubAddressesSchema = object({
39528
39564
  browser: HubAddressSnapshotSchema
39529
39565
  });
39530
39566
  /**
39531
- * What an address is used for (`hub-address.ts`). `viewer` is many-valued;
39532
- * `notifications`, `agents` and `signIn` are carried by at most one address.
39567
+ * What an address is used for (`hub-address.ts`, D734). `appConnections` is
39568
+ * many-valued; `notificationTaps`, `publicEndpoint` and `internal` are carried
39569
+ * by at most one address.
39533
39570
  */
39534
- var HubAddressRoleSchema = _enum([
39535
- "viewer",
39536
- "notifications",
39537
- "agents",
39538
- "signIn"
39539
- ]);
39571
+ var HubAddressRoleSchema = _enum(HUB_ADDRESS_ROLES);
39540
39572
  var RoleSourceSchema = _enum([
39541
39573
  "flagged",
39542
39574
  "auto",
@@ -39550,8 +39582,8 @@ var HubAddressRoleResolutionSchema = object({
39550
39582
  resolved: string().nullable(),
39551
39583
  source: RoleSourceSchema
39552
39584
  });
39553
- var HubViewerResolutionSchema = object({
39554
- /** The addresses flagged `viewer`, or empty = automatic. */
39585
+ var HubAppConnectionsResolutionSchema = object({
39586
+ /** The addresses flagged `appConnections`, or empty = automatic. */
39555
39587
  flagged: array(string()).readonly(),
39556
39588
  /** What the apps race right now. */
39557
39589
  resolved: array(string()).readonly(),
@@ -39571,10 +39603,10 @@ var HubAddressBookSchema = object({
39571
39603
  eligible: array(HubAddressRoleSchema).readonly()
39572
39604
  })).readonly(),
39573
39605
  roles: object({
39574
- viewer: HubViewerResolutionSchema,
39575
- notifications: HubAddressRoleResolutionSchema,
39576
- agents: HubAddressRoleResolutionSchema,
39577
- signIn: HubAddressRoleResolutionSchema
39606
+ appConnections: HubAppConnectionsResolutionSchema,
39607
+ notificationTaps: HubAddressRoleResolutionSchema,
39608
+ internal: HubAddressRoleResolutionSchema,
39609
+ publicEndpoint: HubAddressRoleResolutionSchema
39578
39610
  }),
39579
39611
  /** The `hub=` an app link carries (D709), or null. */
39580
39612
  appLinkHub: string().nullable()
@@ -39669,19 +39701,18 @@ var localNetworkCapability = {
39669
39701
  * tunnel always emits `https://` regardless. */
39670
39702
  scheme: _enum(["http", "https"]).optional(),
39671
39703
  /** Append the CamStack app link entry (`kind: 'app-link'`, D709) —
39672
- * an address notification links can be flagged with, not a hub
39704
+ * an address notification taps can be flagged with, not a hub
39673
39705
  * route. Default `false`: racers and rankers never see it. */
39674
39706
  includeAppLink: boolean().optional()
39675
39707
  }), GetConnectionEndpointsResultSchema),
39676
39708
  /**
39677
- * The address notification links are flagged with. `baseUrl: null` means
39678
- * AUTO, which is the CamStack app link (D709): viewer taps go through
39679
- * `https://camstack.zentik.app/…?hub=<appLinkHub>` and open the app. Any
39680
- * hub address the palette lists can be flagged instead; then viewer taps,
39681
- * attachment links and action buttons all use it. Signed media and
39682
- * buttons never use the app link — with it flagged (or AUTO) they keep
39683
- * the ranked hub ladder (a configured origin, a connected tunnel, then
39684
- * the LAN), never loopback.
39709
+ * The `notificationTaps` role (D734): where TAPPING a notification opens.
39710
+ * `baseUrl: null` means AUTO, which is the CamStack app link (D709): taps
39711
+ * go through `https://camstack.zentik.app/…?hub=<appLinkHub>` and open the
39712
+ * app. Any hub address the palette lists can be flagged instead; then a
39713
+ * tap opens that address. Only the tap: action buttons, attachment /
39714
+ * media links and admin links follow the `publicEndpoint` role
39715
+ * (`getAddresses().roles.publicEndpoint`), never this one.
39685
39716
  *
39686
39717
  * Why an explicit marker: the automatic ranking cannot know which of
39687
39718
  * several reachable addresses the RECIPIENT can actually open. A link is
@@ -39691,14 +39722,13 @@ var localNetworkCapability = {
39691
39722
  */
39692
39723
  getNotificationEndpoint: method(_void(), NotificationEndpointSchema),
39693
39724
  /**
39694
- * @deprecated Use `setAddressRole({ role: 'notifications', … })`. Kept so
39695
- * an older admin UI keeps working: it writes the same `notifications`
39696
- * flag, with the same validation. `baseUrl: null` restores automatic; an
39725
+ * @deprecated Use `setAddressRole({ role: 'notificationTaps', … })`. It
39726
+ * writes the same `notificationTaps` flag, with the same validation. `baseUrl: null` restores automatic; an
39697
39727
  * address that is not detected becomes a custom address.
39698
39728
  */
39699
39729
  setNotificationEndpoint: method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }),
39700
39730
  /**
39701
- * The `viewer` role as shipped apps read it: the flagged addresses
39731
+ * The `appConnections` role as shipped apps read it: the flagged addresses
39702
39732
  * (detected or custom), or empty for AUTO — every LAN IPv4 address plus
39703
39733
  * the public tunnel, never IPv6, mesh, loopback or a custom address.
39704
39734
  * `resolved` is the set as it stands right now; the custom ones in it are
@@ -39706,8 +39736,8 @@ var localNetworkCapability = {
39706
39736
  */
39707
39737
  getViewerEndpoints: method(_void(), ViewerEndpointsSchema),
39708
39738
  /**
39709
- * @deprecated Use `setAddressRole({ role: 'viewer', … })`. Kept so an
39710
- * older admin UI keeps working: it replaces the same `viewer` flags.
39739
+ * @deprecated Use `setAddressRole({ role: 'appConnections', … })`. It
39740
+ * replaces the same `appConnections` flags.
39711
39741
  * Empty `baseUrls` restores automatic.
39712
39742
  */
39713
39743
  setViewerEndpoints: method(object({ baseUrls: array(string()).readonly() }), ViewerEndpointsSchema, { kind: "mutation" }),
@@ -39716,10 +39746,12 @@ var localNetworkCapability = {
39716
39746
  * reading of "which address is this hub reached at, for what": detected
39717
39747
  * endpoints and custom addresses with their role flags, and per role the
39718
39748
  * flagged address, the one in use and whether it is automatic. Agent
39719
- * deliveries, sign-in and LAN devices read `roles.agents` / `roles.signIn`
39720
- * here; nothing ranks the palette itself. `scheme` is the one the caller
39721
- * shows LAN rows in (as `getConnectionEndpoints`); agents and sign-in are
39722
- * always resolved over the HTTPS palette.
39749
+ * deliveries and LAN devices read `roles.internal`; sign-in, OAuth2 and
39750
+ * the notification centre's buttons / media / admin links read
39751
+ * `roles.publicEndpoint`; nothing ranks the palette itself. `scheme` is
39752
+ * the one the caller shows LAN rows in (as `getConnectionEndpoints`);
39753
+ * `internal` and `publicEndpoint` are always resolved over the HTTPS
39754
+ * palette.
39723
39755
  */
39724
39756
  getAddresses: method(object({ scheme: _enum(["http", "https"]).optional() }).optional(), HubAddressBookSchema),
39725
39757
  /**
@@ -39744,8 +39776,9 @@ var localNetworkCapability = {
39744
39776
  * Flag (`enabled: true`) or unflag an address for a role. For a
39745
39777
  * single-valued role, flagging moves the flag off every other address.
39746
39778
  * `baseUrl: null` returns the role to automatic. The address must be a row
39747
- * of the table (detected, custom, or the app link for notifications);
39748
- * `signIn` on a plain-http address is refused unless `acceptInsecureHttp`.
39779
+ * of the table (detected, custom, or the app link for `notificationTaps`);
39780
+ * `publicEndpoint` on a plain-http address is refused unless
39781
+ * `acceptInsecureHttp`, and never takes the app link.
39749
39782
  */
39750
39783
  setAddressRole: method(object({
39751
39784
  role: HubAddressRoleSchema,
@@ -39757,9 +39790,9 @@ var localNetworkCapability = {
39757
39790
  auth: "admin"
39758
39791
  }),
39759
39792
  /**
39760
- * @deprecated Read `getAddresses().roles.agents` / `.signIn`. Kept one
39761
- * release so an addon built against the D729 amendment keeps resolving:
39762
- * `cluster` = the `agents` role, `browser` = the `signIn` role.
39793
+ * @deprecated Read `getAddresses().roles.internal` / `.publicEndpoint`.
39794
+ * Kept so an addon built against the D729 amendment keeps resolving:
39795
+ * `cluster` = the `internal` role, `browser` = the `publicEndpoint` role.
39763
39796
  */
39764
39797
  getHubAddresses: method(_void(), HubAddressesSchema),
39765
39798
  /**
@@ -61041,17 +61074,23 @@ var NC_ALARM_DELAY_FIELDS = [
61041
61074
  * all read this one constant.
61042
61075
  */
61043
61076
  var NC_ALARM_DEFAULT_TRIGGERED_DURATION_SEC = 30;
61044
- var NC_ALARM_NOTIFY_FIELDS = ["notifyDuringEntryDelay", "notifySensorRewatched"];
61077
+ var NC_ALARM_NOTIFY_FIELDS = [
61078
+ "notifyDuringEntryDelay",
61079
+ "notifySensorRewatched",
61080
+ "notifySensorIgnored"
61081
+ ];
61045
61082
  /**
61046
61083
  * The switches `mode` runs on. There is no global value: absent is OFF (operator decision
61047
61084
  * 2026-10-06 — the entry-delay notification is the only one by default, and "watched again"
61048
- * is not sent). An answer from an older hub carries no switch and reads as off.
61085
+ * is not sent; 2026-10-07 — nor is "ignored", D735). An answer from an older hub carries no
61086
+ * switch and reads as off.
61049
61087
  */
61050
61088
  function resolveModeNotifyPolicy(settings, mode) {
61051
61089
  const entry = (settings.modeDelays ?? []).find((e) => e.mode === mode);
61052
61090
  return {
61053
61091
  notifyDuringEntryDelay: entry?.notifyDuringEntryDelay === true,
61054
- notifySensorRewatched: entry?.notifySensorRewatched === true
61092
+ notifySensorRewatched: entry?.notifySensorRewatched === true,
61093
+ notifySensorIgnored: entry?.notifySensorIgnored === true
61055
61094
  };
61056
61095
  }
61057
61096
  /**
@@ -61128,6 +61167,7 @@ function applyModeDelaysEdits(current, edits) {
61128
61167
  const schedule = editedSchedule(base.schedule, edit.schedule);
61129
61168
  const duringEntry = editedFlag(base.notifyDuringEntryDelay, edit.notifyDuringEntryDelay);
61130
61169
  const rewatched = editedFlag(base.notifySensorRewatched, edit.notifySensorRewatched);
61170
+ const ignored = editedFlag(base.notifySensorIgnored, edit.notifySensorIgnored);
61131
61171
  if (exit !== void 0) next.exitDelaySec = exit;
61132
61172
  if (entry !== void 0) next.entryDelaySec = entry;
61133
61173
  if (triggered !== void 0) next.triggeredDurationSec = triggered;
@@ -61135,10 +61175,11 @@ function applyModeDelaysEdits(current, edits) {
61135
61175
  if (schedule !== void 0) next.schedule = schedule;
61136
61176
  if (duringEntry !== void 0) next.notifyDuringEntryDelay = duringEntry;
61137
61177
  if (rewatched !== void 0) next.notifySensorRewatched = rewatched;
61178
+ if (ignored !== void 0) next.notifySensorIgnored = ignored;
61138
61179
  if (at >= 0) out[at] = next;
61139
61180
  else out.push(next);
61140
61181
  }
61141
- return out.filter((e) => e.exitDelaySec !== void 0 || e.entryDelaySec !== void 0 || e.triggeredDurationSec !== void 0 || e.postTriggeredAction !== void 0 || e.schedule !== void 0 || e.notifyDuringEntryDelay !== void 0 || e.notifySensorRewatched !== void 0);
61182
+ return out.filter((e) => e.exitDelaySec !== void 0 || e.entryDelaySec !== void 0 || e.triggeredDurationSec !== void 0 || e.postTriggeredAction !== void 0 || e.schedule !== void 0 || e.notifyDuringEntryDelay !== void 0 || e.notifySensorRewatched !== void 0 || e.notifySensorIgnored !== void 0);
61142
61183
  }
61143
61184
  /**
61144
61185
  * Put ONE device on, or take it off, ONE mode's device-id list. A no-op answers