@camstack/addon-post-analysis 1.2.282 → 1.2.283

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.
@@ -17956,6 +17956,9 @@ var NcSystemEventKindSchema = _enum([
17956
17956
  "device-battery-normal",
17957
17957
  "device-consumable-low",
17958
17958
  "device-consumable-normal",
17959
+ "device-tank-low",
17960
+ "device-tank-full",
17961
+ "device-tank-normal",
17959
17962
  "stream-online",
17960
17963
  "stream-offline",
17961
17964
  "node-online",
@@ -18016,6 +18019,18 @@ var NC_ALARM_SYSTEM_EVENT_KINDS = [
18016
18019
  "alarm-disarmed"
18017
18020
  ];
18018
18021
  /**
18022
+ * The two kinds a RULE's consumable threshold speaks about (D642). Named once:
18023
+ * the filter scoping (`systemEventFilterApplies`), the hub's threshold census
18024
+ * and both editors read it.
18025
+ */
18026
+ var NC_CONSUMABLE_SYSTEM_EVENT_KINDS = ["device-consumable-low", "device-consumable-normal"];
18027
+ /** A vacuum's tank alerts (D642) — raised on the provider's own verdict. */
18028
+ var NC_TANK_SYSTEM_EVENT_KINDS = [
18029
+ "device-tank-low",
18030
+ "device-tank-full",
18031
+ "device-tank-normal"
18032
+ ];
18033
+ /**
18019
18034
  * One coherent system-event condition. `kinds` is the required opt-in safety
18020
18035
  * gate; the remaining lists are optional narrowing filters relevant to the
18021
18036
  * selected kinds.
@@ -18049,8 +18064,27 @@ var NcSystemEventConditionSchema = object({
18049
18064
  */
18050
18065
  excludeDeviceIds: array(number().int()).min(1).optional(),
18051
18066
  nodeIds: array(string().min(1)).min(1).optional(),
18052
- packageNames: array(string().min(1)).min(1).optional()
18067
+ packageNames: array(string().min(1)).min(1).optional(),
18068
+ /**
18069
+ * At or below this remaining-life %, a consumable is LOW for THIS rule
18070
+ * (D642). Absent = {@link NC_CONSUMABLE_LOW_PERCENT_DEFAULT}; at most
18071
+ * {@link NC_CONSUMABLE_LOW_PERCENT_MAX}, so every episode can recover. Scoped to the
18072
+ * consumable kinds (`systemEventFilterApplies`) and to the device-events
18073
+ * family; ignored on every other kind.
18074
+ *
18075
+ * It is a property of the RULE because the operator decided so: a rule at
18076
+ * 25 must be told about a filter at 20 %, a rule at 10 must not. The hub
18077
+ * keeps one episode per (threshold, device, item) — its own hysteresis, its
18078
+ * own reminder — and a rule hears only the episode judged at ITS threshold,
18079
+ * exactly as an occupancy rule hears only the edge of its own count. A
18080
+ * provider's own `replace` verdict is low at every threshold.
18081
+ */
18082
+ consumableLowPercent: number().int().min(1).max(95).optional()
18053
18083
  });
18084
+ /** The consumable threshold a system-event condition judges at (D642). */
18085
+ function consumableLowPercentOf(condition) {
18086
+ return condition.consumableLowPercent ?? 15;
18087
+ }
18054
18088
  /** Hard ceiling on a window (24h). A snooze that could not expire would be an
18055
18089
  * outage the operator asked for once and forgot. */
18056
18090
  var NC_SNOOZE_MAX_MINUTES = 1440;
@@ -19328,6 +19362,18 @@ var NC_CONDITION_CATALOG = [
19328
19362
  value: "device-consumable-normal",
19329
19363
  label: "Consumable replaced"
19330
19364
  },
19365
+ {
19366
+ value: "device-tank-low",
19367
+ label: "Tank low (water, detergent)"
19368
+ },
19369
+ {
19370
+ value: "device-tank-full",
19371
+ label: "Tank full (dirty water, dust)"
19372
+ },
19373
+ {
19374
+ value: "device-tank-normal",
19375
+ label: "Tank back to normal"
19376
+ },
19331
19377
  {
19332
19378
  value: "export-completed",
19333
19379
  label: "Export completed"
@@ -29723,12 +29769,20 @@ reset: method(object({
29723
29769
  },
29724
29770
  runtimeState: ConsumablesStatusSchema.extend({ lastFetchedAt: number() }),
29725
29771
  /**
29726
- * Runtime-state durability: **session** — the authority is the appliance; the provider re-reads the whole item array on connect.
29772
+ * Runtime-state durability: **restored** — nothing else holds the value
29773
+ * (D642). A consumable can often be read only in a device's wake window (the
29774
+ * Dreame mower's CMS counters answer only while it charges), so a restart
29775
+ * that wiped the slice left the panel empty and the alerts blind until the
29776
+ * next wake — 2026-09-26, mower 503 idle with `items: []`. A restored item is
29777
+ * the previous observation, not a claim about now; the provider overwrites it
29778
+ * the moment it reads the device again.
29727
29779
  *
29728
29780
  * See `RuntimeStateDurability`. Enforced by
29729
29781
  * `scripts/check-runtime-state-durability.ts`.
29730
29782
  */
29731
- durability: "session"
29783
+ durability: "restored",
29784
+ /** Clocks, not content: a re-read that changed no item costs no commit. */
29785
+ volatileStateFields: ["lastChangedAt", "lastFetchedAt"]
29732
29786
  };
29733
29787
  /**
29734
29788
  * Door / window / opening / garage / valve contact sensor. Boolean
@@ -50716,12 +50770,55 @@ function audioModeOf(value) {
50716
50770
  return null;
50717
50771
  }
50718
50772
  new Set(["devices", "classes"]);
50719
- /** Every filter, for the callers that must cover all four (guards, tests). */
50773
+ /**
50774
+ * WHICH narrowing filter speaks about WHICH system-event kind — one predicate,
50775
+ * consumed by the rule ENGINE and by every rule EDITOR.
50776
+ *
50777
+ * ── The failure this file exists for ───────────────────────────────────────
50778
+ * `NcSystemEventConditionSchema` carries four optional narrowing lists
50779
+ * (`deviceIds`, `deviceTypes`, `nodeIds`, `packageNames`) beside a required
50780
+ * `kinds` gate. They are not four filters over one vocabulary: each belongs to
50781
+ * a FAMILY of kinds and is meaningless outside it. A node going away has no
50782
+ * device type; a completed export has no package; `stream-offline` deliberately
50783
+ * carries no device type at all (a stream belongs to a camera by construction).
50784
+ *
50785
+ * The engine applied all four to every kind, so a filter from one family failed
50786
+ * a kind from another family CLOSED. The operator's live rule "Eventi di
50787
+ * sistema" selected eleven kinds and set `deviceTypes: ['camera']` — the only
50788
+ * way to say "only my cameras" about the two liveness kinds — and NINE of the
50789
+ * eleven silently stopped being deliverable. Four days of history contained
50790
+ * `device-online` and `device-offline` and nothing else, across a window in
50791
+ * which agents were restarted and addons were updated.
50792
+ *
50793
+ * Both editors already computed this scoping, to decide which filter boxes to
50794
+ * render; the cap's own docblock already promised it ("Narrow a `device-*` kind
50795
+ * to these device TYPES"). Only the engine disagreed, and it disagreed in the
50796
+ * destructive direction. So the rule is stated ONCE, here, and the engine and
50797
+ * the editors are readers of it rather than three independent authors.
50798
+ *
50799
+ * ── The direction ─────────────────────────────────────────────────────────
50800
+ * Out of family ⇒ the filter is IGNORED, never fail-closed. An editor that
50801
+ * hides a box has already told the operator this filter does not speak about
50802
+ * these kinds, so honouring it as an exclusion contradicts the only
50803
+ * explanation the operator was ever given. Inside its family the filter still
50804
+ * narrows, and still fails CLOSED on a subject that cannot produce the identity
50805
+ * it tests (a device the mirror cannot name is not evidence of a camera).
50806
+ */
50807
+ /**
50808
+ * Every filter, for the callers that must cover all of them (guards, tests).
50809
+ *
50810
+ * `consumableLowPercent` (D642) is not a list but it is a filter in exactly
50811
+ * this sense: it belongs to a family of kinds (the consumable pair) and the
50812
+ * engine consults it only there. It differs in one way the readers must know —
50813
+ * its ABSENCE is not "no narrowing" but the default threshold, because a
50814
+ * consumable episode is always judged at SOME threshold.
50815
+ */
50720
50816
  var NC_SYSTEM_EVENT_FILTER_KEYS = [
50721
50817
  "deviceIds",
50722
50818
  "deviceTypes",
50723
50819
  "nodeIds",
50724
- "packageNames"
50820
+ "packageNames",
50821
+ "consumableLowPercent"
50725
50822
  ];
50726
50823
  /**
50727
50824
  * Does `filter` say anything about `kind`?
@@ -50735,6 +50832,7 @@ function systemEventFilterApplies(kind, filter) {
50735
50832
  case "deviceTypes": return kind.startsWith("device-") || kind === "detection-blind";
50736
50833
  case "nodeIds": return kind.startsWith("node-") || kind === "addon-crash-loop" || kind === "addon-update-available" || kind === "addon-updated" || kind === "server-update-available" || kind === "wrapper-update-available" || kind === "server-updated";
50737
50834
  case "packageNames": return kind.endsWith("update-available") || kind === "addon-updated" || kind === "server-updated";
50835
+ case "consumableLowPercent": return NC_CONSUMABLE_SYSTEM_EVENT_KINDS.includes(kind);
50738
50836
  }
50739
50837
  }
50740
50838
  /**
@@ -50770,6 +50868,9 @@ var NC_SYSTEM_EVENT_FAMILY = {
50770
50868
  "device-battery-normal": "device-events",
50771
50869
  "device-consumable-low": "device-events",
50772
50870
  "device-consumable-normal": "device-events",
50871
+ "device-tank-low": "device-events",
50872
+ "device-tank-full": "device-events",
50873
+ "device-tank-normal": "device-events",
50773
50874
  "stream-online": "device-events",
50774
50875
  "stream-offline": "device-events",
50775
50876
  "detection-blind": "device-events",
@@ -50801,7 +50902,7 @@ var NC_SYSTEM_EVENT_FAMILY = {
50801
50902
  new Map(Object.entries(NC_SYSTEM_EVENT_FAMILY));
50802
50903
  var NC_SYSTEM_EVENT_CONDITION_FILTER_KEYS = [...NC_SYSTEM_EVENT_FILTER_KEYS, "excludeDeviceIds"];
50803
50904
  /**
50804
- * The filters a family may carry. The four base filters are the union of
50905
+ * The filters a family may carry. The base filters are the union of
50805
50906
  * `systemEventFilterApplies` over the family's kinds (the spec pins that
50806
50907
  * equality). `excludeDeviceIds` is a device-events filter only: an alarm is
50807
50908
  * narrowed to the camera that triggered it and excludes nothing.
@@ -50810,7 +50911,8 @@ var NC_SYSTEM_EVENT_FAMILY_FILTERS = {
50810
50911
  "device-events": [
50811
50912
  "deviceIds",
50812
50913
  "excludeDeviceIds",
50813
- "deviceTypes"
50914
+ "deviceTypes",
50915
+ "consumableLowPercent"
50814
50916
  ],
50815
50917
  system: ["nodeIds", "packageNames"],
50816
50918
  alarm: ["deviceIds"]
@@ -50845,6 +50947,16 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
50845
50947
  label: "Consumables",
50846
50948
  kinds: ["device-consumable-low", "device-consumable-normal"]
50847
50949
  },
50950
+ {
50951
+ id: "tanks",
50952
+ family: "device-events",
50953
+ label: "Tanks",
50954
+ kinds: [
50955
+ "device-tank-low",
50956
+ "device-tank-full",
50957
+ "device-tank-normal"
50958
+ ]
50959
+ },
50848
50960
  {
50849
50961
  id: "detection-blind",
50850
50962
  family: "device-events",
@@ -51088,6 +51200,11 @@ var RULE_BODY_ONLY = ["body"];
51088
51200
  var RULE_TEXT = ["title", "body"];
51089
51201
  var BATTERY = ["device-battery-low", "device-battery-normal"];
51090
51202
  var CONSUMABLE = ["device-consumable-low", "device-consumable-normal"];
51203
+ var TANK = [
51204
+ "device-tank-low",
51205
+ "device-tank-full",
51206
+ "device-tank-normal"
51207
+ ];
51091
51208
  var UPDATES = [
51092
51209
  "addon-update-available",
51093
51210
  "server-update-available",
@@ -51113,6 +51230,7 @@ var DEVICE_EVENTS = [
51113
51230
  "device-enabled",
51114
51231
  ...BATTERY,
51115
51232
  ...CONSUMABLE,
51233
+ ...TANK,
51116
51234
  "stream-online",
51117
51235
  "stream-offline",
51118
51236
  "detection-blind",
@@ -51410,6 +51528,17 @@ var NC_TEMPLATE_VARS = [
51410
51528
  kinds: ["system"],
51411
51529
  systemEventKinds: [...CONSUMABLE]
51412
51530
  },
51531
+ {
51532
+ name: "tank",
51533
+ label: "Tank",
51534
+ description: "Which tank: clean water, dirty water, detergent or dust bin.",
51535
+ example: "clean water",
51536
+ group: "system",
51537
+ families: ["rule"],
51538
+ fields: [...RULE_TEXT],
51539
+ kinds: ["system"],
51540
+ systemEventKinds: [...TANK]
51541
+ },
51413
51542
  {
51414
51543
  name: "profile",
51415
51544
  label: "Stream profile",
@@ -51802,6 +51931,38 @@ var NC_TEMPLATE_VARS = [
51802
51931
  fields: [...RULE_TEXT]
51803
51932
  }
51804
51933
  ];
51934
+ /**
51935
+ * System-event kinds the SERVED catalog holds back (D642): the kinds the hub
51936
+ * produces before the installed viewers can parse them.
51937
+ *
51938
+ * The viewer parses `getTemplateCatalog` WHOLE, with its own strict
51939
+ * `NcSystemEventKindSchema` on every descriptor's `systemEventKinds`, so one
51940
+ * kind it does not know — in `{{deviceName}}`, which every device event names —
51941
+ * empties every {{var}} picker on every phone (the same trap
51942
+ * `NcTemplateVarKindSchema` froze the rule kinds for). The in-process catalog
51943
+ * keeps them: the producer parity and the preview render read it.
51944
+ *
51945
+ * SELF-EXPIRING: `scripts/check-nc-mirrors-in-sync.ts` reads this list as the
51946
+ * viewer's allowance and fails the day the viewer mirrors one of these kinds —
51947
+ * delete it from here then, and the served catalog names it again.
51948
+ */
51949
+ var NC_TEMPLATE_HELD_BACK_SYSTEM_EVENT_KINDS = [
51950
+ "device-tank-low",
51951
+ "device-tank-full",
51952
+ "device-tank-normal"
51953
+ ];
51954
+ /**
51955
+ * The catalog as `getTemplateCatalog` SERVES it: every descriptor, with the
51956
+ * held-back kinds removed from its `systemEventKinds`. A descriptor that named
51957
+ * only held-back kinds is served with an empty list — offered to no system
51958
+ * rule an installed viewer can author, which is exactly true.
51959
+ */
51960
+ function servedTemplateVars() {
51961
+ return NC_TEMPLATE_VARS.map((d) => d.systemEventKinds === void 0 ? d : {
51962
+ ...d,
51963
+ systemEventKinds: d.systemEventKinds.filter((kind) => !NC_TEMPLATE_HELD_BACK_SYSTEM_EVENT_KINDS.includes(kind))
51964
+ });
51965
+ }
51805
51966
  /** The caption fields see a fixed, smaller vocabulary (`timelapsePreviewText`,
51806
51967
  * `summaryCaptionText`). Declared here rather than as `fields` on every
51807
51968
  * descriptor so the whole rule stays in one line of code. */
@@ -53068,6 +53229,12 @@ Object.defineProperty(exports, "NC_CONDITION_CATALOG", {
53068
53229
  return NC_CONDITION_CATALOG;
53069
53230
  }
53070
53231
  });
53232
+ Object.defineProperty(exports, "NC_CONSUMABLE_SYSTEM_EVENT_KINDS", {
53233
+ enumerable: true,
53234
+ get: function() {
53235
+ return NC_CONSUMABLE_SYSTEM_EVENT_KINDS;
53236
+ }
53237
+ });
53071
53238
  Object.defineProperty(exports, "NC_DEFAULT_SNOOZE_MINUTES", {
53072
53239
  enumerable: true,
53073
53240
  get: function() {
@@ -53086,6 +53253,12 @@ Object.defineProperty(exports, "NC_SNOOZE_MAX_MINUTES", {
53086
53253
  return NC_SNOOZE_MAX_MINUTES;
53087
53254
  }
53088
53255
  });
53256
+ Object.defineProperty(exports, "NC_TANK_SYSTEM_EVENT_KINDS", {
53257
+ enumerable: true,
53258
+ get: function() {
53259
+ return NC_TANK_SYSTEM_EVENT_KINDS;
53260
+ }
53261
+ });
53089
53262
  Object.defineProperty(exports, "NC_TAXONOMY", {
53090
53263
  enumerable: true,
53091
53264
  get: function() {
@@ -53368,6 +53541,12 @@ Object.defineProperty(exports, "canonicalHash", {
53368
53541
  return canonicalHash;
53369
53542
  }
53370
53543
  });
53544
+ Object.defineProperty(exports, "consumableLowPercentOf", {
53545
+ enumerable: true,
53546
+ get: function() {
53547
+ return consumableLowPercentOf;
53548
+ }
53549
+ });
53371
53550
  Object.defineProperty(exports, "cosineSimilarity", {
53372
53551
  enumerable: true,
53373
53552
  get: function() {
@@ -53638,6 +53817,12 @@ Object.defineProperty(exports, "sensorRaisedOf", {
53638
53817
  return sensorRaisedOf;
53639
53818
  }
53640
53819
  });
53820
+ Object.defineProperty(exports, "servedTemplateVars", {
53821
+ enumerable: true,
53822
+ get: function() {
53823
+ return servedTemplateVars;
53824
+ }
53825
+ });
53641
53826
  Object.defineProperty(exports, "sleep", {
53642
53827
  enumerable: true,
53643
53828
  get: function() {
@@ -17925,6 +17925,9 @@ var NcSystemEventKindSchema = _enum([
17925
17925
  "device-battery-normal",
17926
17926
  "device-consumable-low",
17927
17927
  "device-consumable-normal",
17928
+ "device-tank-low",
17929
+ "device-tank-full",
17930
+ "device-tank-normal",
17928
17931
  "stream-online",
17929
17932
  "stream-offline",
17930
17933
  "node-online",
@@ -17985,6 +17988,18 @@ var NC_ALARM_SYSTEM_EVENT_KINDS = [
17985
17988
  "alarm-disarmed"
17986
17989
  ];
17987
17990
  /**
17991
+ * The two kinds a RULE's consumable threshold speaks about (D642). Named once:
17992
+ * the filter scoping (`systemEventFilterApplies`), the hub's threshold census
17993
+ * and both editors read it.
17994
+ */
17995
+ var NC_CONSUMABLE_SYSTEM_EVENT_KINDS = ["device-consumable-low", "device-consumable-normal"];
17996
+ /** A vacuum's tank alerts (D642) — raised on the provider's own verdict. */
17997
+ var NC_TANK_SYSTEM_EVENT_KINDS = [
17998
+ "device-tank-low",
17999
+ "device-tank-full",
18000
+ "device-tank-normal"
18001
+ ];
18002
+ /**
17988
18003
  * One coherent system-event condition. `kinds` is the required opt-in safety
17989
18004
  * gate; the remaining lists are optional narrowing filters relevant to the
17990
18005
  * selected kinds.
@@ -18018,8 +18033,27 @@ var NcSystemEventConditionSchema = object({
18018
18033
  */
18019
18034
  excludeDeviceIds: array(number().int()).min(1).optional(),
18020
18035
  nodeIds: array(string().min(1)).min(1).optional(),
18021
- packageNames: array(string().min(1)).min(1).optional()
18036
+ packageNames: array(string().min(1)).min(1).optional(),
18037
+ /**
18038
+ * At or below this remaining-life %, a consumable is LOW for THIS rule
18039
+ * (D642). Absent = {@link NC_CONSUMABLE_LOW_PERCENT_DEFAULT}; at most
18040
+ * {@link NC_CONSUMABLE_LOW_PERCENT_MAX}, so every episode can recover. Scoped to the
18041
+ * consumable kinds (`systemEventFilterApplies`) and to the device-events
18042
+ * family; ignored on every other kind.
18043
+ *
18044
+ * It is a property of the RULE because the operator decided so: a rule at
18045
+ * 25 must be told about a filter at 20 %, a rule at 10 must not. The hub
18046
+ * keeps one episode per (threshold, device, item) — its own hysteresis, its
18047
+ * own reminder — and a rule hears only the episode judged at ITS threshold,
18048
+ * exactly as an occupancy rule hears only the edge of its own count. A
18049
+ * provider's own `replace` verdict is low at every threshold.
18050
+ */
18051
+ consumableLowPercent: number().int().min(1).max(95).optional()
18022
18052
  });
18053
+ /** The consumable threshold a system-event condition judges at (D642). */
18054
+ function consumableLowPercentOf(condition) {
18055
+ return condition.consumableLowPercent ?? 15;
18056
+ }
18023
18057
  /** Hard ceiling on a window (24h). A snooze that could not expire would be an
18024
18058
  * outage the operator asked for once and forgot. */
18025
18059
  var NC_SNOOZE_MAX_MINUTES = 1440;
@@ -19297,6 +19331,18 @@ var NC_CONDITION_CATALOG = [
19297
19331
  value: "device-consumable-normal",
19298
19332
  label: "Consumable replaced"
19299
19333
  },
19334
+ {
19335
+ value: "device-tank-low",
19336
+ label: "Tank low (water, detergent)"
19337
+ },
19338
+ {
19339
+ value: "device-tank-full",
19340
+ label: "Tank full (dirty water, dust)"
19341
+ },
19342
+ {
19343
+ value: "device-tank-normal",
19344
+ label: "Tank back to normal"
19345
+ },
19300
19346
  {
19301
19347
  value: "export-completed",
19302
19348
  label: "Export completed"
@@ -29692,12 +29738,20 @@ reset: method(object({
29692
29738
  },
29693
29739
  runtimeState: ConsumablesStatusSchema.extend({ lastFetchedAt: number() }),
29694
29740
  /**
29695
- * Runtime-state durability: **session** — the authority is the appliance; the provider re-reads the whole item array on connect.
29741
+ * Runtime-state durability: **restored** — nothing else holds the value
29742
+ * (D642). A consumable can often be read only in a device's wake window (the
29743
+ * Dreame mower's CMS counters answer only while it charges), so a restart
29744
+ * that wiped the slice left the panel empty and the alerts blind until the
29745
+ * next wake — 2026-09-26, mower 503 idle with `items: []`. A restored item is
29746
+ * the previous observation, not a claim about now; the provider overwrites it
29747
+ * the moment it reads the device again.
29696
29748
  *
29697
29749
  * See `RuntimeStateDurability`. Enforced by
29698
29750
  * `scripts/check-runtime-state-durability.ts`.
29699
29751
  */
29700
- durability: "session"
29752
+ durability: "restored",
29753
+ /** Clocks, not content: a re-read that changed no item costs no commit. */
29754
+ volatileStateFields: ["lastChangedAt", "lastFetchedAt"]
29701
29755
  };
29702
29756
  /**
29703
29757
  * Door / window / opening / garage / valve contact sensor. Boolean
@@ -50685,12 +50739,55 @@ function audioModeOf(value) {
50685
50739
  return null;
50686
50740
  }
50687
50741
  new Set(["devices", "classes"]);
50688
- /** Every filter, for the callers that must cover all four (guards, tests). */
50742
+ /**
50743
+ * WHICH narrowing filter speaks about WHICH system-event kind — one predicate,
50744
+ * consumed by the rule ENGINE and by every rule EDITOR.
50745
+ *
50746
+ * ── The failure this file exists for ───────────────────────────────────────
50747
+ * `NcSystemEventConditionSchema` carries four optional narrowing lists
50748
+ * (`deviceIds`, `deviceTypes`, `nodeIds`, `packageNames`) beside a required
50749
+ * `kinds` gate. They are not four filters over one vocabulary: each belongs to
50750
+ * a FAMILY of kinds and is meaningless outside it. A node going away has no
50751
+ * device type; a completed export has no package; `stream-offline` deliberately
50752
+ * carries no device type at all (a stream belongs to a camera by construction).
50753
+ *
50754
+ * The engine applied all four to every kind, so a filter from one family failed
50755
+ * a kind from another family CLOSED. The operator's live rule "Eventi di
50756
+ * sistema" selected eleven kinds and set `deviceTypes: ['camera']` — the only
50757
+ * way to say "only my cameras" about the two liveness kinds — and NINE of the
50758
+ * eleven silently stopped being deliverable. Four days of history contained
50759
+ * `device-online` and `device-offline` and nothing else, across a window in
50760
+ * which agents were restarted and addons were updated.
50761
+ *
50762
+ * Both editors already computed this scoping, to decide which filter boxes to
50763
+ * render; the cap's own docblock already promised it ("Narrow a `device-*` kind
50764
+ * to these device TYPES"). Only the engine disagreed, and it disagreed in the
50765
+ * destructive direction. So the rule is stated ONCE, here, and the engine and
50766
+ * the editors are readers of it rather than three independent authors.
50767
+ *
50768
+ * ── The direction ─────────────────────────────────────────────────────────
50769
+ * Out of family ⇒ the filter is IGNORED, never fail-closed. An editor that
50770
+ * hides a box has already told the operator this filter does not speak about
50771
+ * these kinds, so honouring it as an exclusion contradicts the only
50772
+ * explanation the operator was ever given. Inside its family the filter still
50773
+ * narrows, and still fails CLOSED on a subject that cannot produce the identity
50774
+ * it tests (a device the mirror cannot name is not evidence of a camera).
50775
+ */
50776
+ /**
50777
+ * Every filter, for the callers that must cover all of them (guards, tests).
50778
+ *
50779
+ * `consumableLowPercent` (D642) is not a list but it is a filter in exactly
50780
+ * this sense: it belongs to a family of kinds (the consumable pair) and the
50781
+ * engine consults it only there. It differs in one way the readers must know —
50782
+ * its ABSENCE is not "no narrowing" but the default threshold, because a
50783
+ * consumable episode is always judged at SOME threshold.
50784
+ */
50689
50785
  var NC_SYSTEM_EVENT_FILTER_KEYS = [
50690
50786
  "deviceIds",
50691
50787
  "deviceTypes",
50692
50788
  "nodeIds",
50693
- "packageNames"
50789
+ "packageNames",
50790
+ "consumableLowPercent"
50694
50791
  ];
50695
50792
  /**
50696
50793
  * Does `filter` say anything about `kind`?
@@ -50704,6 +50801,7 @@ function systemEventFilterApplies(kind, filter) {
50704
50801
  case "deviceTypes": return kind.startsWith("device-") || kind === "detection-blind";
50705
50802
  case "nodeIds": return kind.startsWith("node-") || kind === "addon-crash-loop" || kind === "addon-update-available" || kind === "addon-updated" || kind === "server-update-available" || kind === "wrapper-update-available" || kind === "server-updated";
50706
50803
  case "packageNames": return kind.endsWith("update-available") || kind === "addon-updated" || kind === "server-updated";
50804
+ case "consumableLowPercent": return NC_CONSUMABLE_SYSTEM_EVENT_KINDS.includes(kind);
50707
50805
  }
50708
50806
  }
50709
50807
  /**
@@ -50739,6 +50837,9 @@ var NC_SYSTEM_EVENT_FAMILY = {
50739
50837
  "device-battery-normal": "device-events",
50740
50838
  "device-consumable-low": "device-events",
50741
50839
  "device-consumable-normal": "device-events",
50840
+ "device-tank-low": "device-events",
50841
+ "device-tank-full": "device-events",
50842
+ "device-tank-normal": "device-events",
50742
50843
  "stream-online": "device-events",
50743
50844
  "stream-offline": "device-events",
50744
50845
  "detection-blind": "device-events",
@@ -50770,7 +50871,7 @@ var NC_SYSTEM_EVENT_FAMILY = {
50770
50871
  new Map(Object.entries(NC_SYSTEM_EVENT_FAMILY));
50771
50872
  var NC_SYSTEM_EVENT_CONDITION_FILTER_KEYS = [...NC_SYSTEM_EVENT_FILTER_KEYS, "excludeDeviceIds"];
50772
50873
  /**
50773
- * The filters a family may carry. The four base filters are the union of
50874
+ * The filters a family may carry. The base filters are the union of
50774
50875
  * `systemEventFilterApplies` over the family's kinds (the spec pins that
50775
50876
  * equality). `excludeDeviceIds` is a device-events filter only: an alarm is
50776
50877
  * narrowed to the camera that triggered it and excludes nothing.
@@ -50779,7 +50880,8 @@ var NC_SYSTEM_EVENT_FAMILY_FILTERS = {
50779
50880
  "device-events": [
50780
50881
  "deviceIds",
50781
50882
  "excludeDeviceIds",
50782
- "deviceTypes"
50883
+ "deviceTypes",
50884
+ "consumableLowPercent"
50783
50885
  ],
50784
50886
  system: ["nodeIds", "packageNames"],
50785
50887
  alarm: ["deviceIds"]
@@ -50814,6 +50916,16 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
50814
50916
  label: "Consumables",
50815
50917
  kinds: ["device-consumable-low", "device-consumable-normal"]
50816
50918
  },
50919
+ {
50920
+ id: "tanks",
50921
+ family: "device-events",
50922
+ label: "Tanks",
50923
+ kinds: [
50924
+ "device-tank-low",
50925
+ "device-tank-full",
50926
+ "device-tank-normal"
50927
+ ]
50928
+ },
50817
50929
  {
50818
50930
  id: "detection-blind",
50819
50931
  family: "device-events",
@@ -51057,6 +51169,11 @@ var RULE_BODY_ONLY = ["body"];
51057
51169
  var RULE_TEXT = ["title", "body"];
51058
51170
  var BATTERY = ["device-battery-low", "device-battery-normal"];
51059
51171
  var CONSUMABLE = ["device-consumable-low", "device-consumable-normal"];
51172
+ var TANK = [
51173
+ "device-tank-low",
51174
+ "device-tank-full",
51175
+ "device-tank-normal"
51176
+ ];
51060
51177
  var UPDATES = [
51061
51178
  "addon-update-available",
51062
51179
  "server-update-available",
@@ -51082,6 +51199,7 @@ var DEVICE_EVENTS = [
51082
51199
  "device-enabled",
51083
51200
  ...BATTERY,
51084
51201
  ...CONSUMABLE,
51202
+ ...TANK,
51085
51203
  "stream-online",
51086
51204
  "stream-offline",
51087
51205
  "detection-blind",
@@ -51379,6 +51497,17 @@ var NC_TEMPLATE_VARS = [
51379
51497
  kinds: ["system"],
51380
51498
  systemEventKinds: [...CONSUMABLE]
51381
51499
  },
51500
+ {
51501
+ name: "tank",
51502
+ label: "Tank",
51503
+ description: "Which tank: clean water, dirty water, detergent or dust bin.",
51504
+ example: "clean water",
51505
+ group: "system",
51506
+ families: ["rule"],
51507
+ fields: [...RULE_TEXT],
51508
+ kinds: ["system"],
51509
+ systemEventKinds: [...TANK]
51510
+ },
51382
51511
  {
51383
51512
  name: "profile",
51384
51513
  label: "Stream profile",
@@ -51771,6 +51900,38 @@ var NC_TEMPLATE_VARS = [
51771
51900
  fields: [...RULE_TEXT]
51772
51901
  }
51773
51902
  ];
51903
+ /**
51904
+ * System-event kinds the SERVED catalog holds back (D642): the kinds the hub
51905
+ * produces before the installed viewers can parse them.
51906
+ *
51907
+ * The viewer parses `getTemplateCatalog` WHOLE, with its own strict
51908
+ * `NcSystemEventKindSchema` on every descriptor's `systemEventKinds`, so one
51909
+ * kind it does not know — in `{{deviceName}}`, which every device event names —
51910
+ * empties every {{var}} picker on every phone (the same trap
51911
+ * `NcTemplateVarKindSchema` froze the rule kinds for). The in-process catalog
51912
+ * keeps them: the producer parity and the preview render read it.
51913
+ *
51914
+ * SELF-EXPIRING: `scripts/check-nc-mirrors-in-sync.ts` reads this list as the
51915
+ * viewer's allowance and fails the day the viewer mirrors one of these kinds —
51916
+ * delete it from here then, and the served catalog names it again.
51917
+ */
51918
+ var NC_TEMPLATE_HELD_BACK_SYSTEM_EVENT_KINDS = [
51919
+ "device-tank-low",
51920
+ "device-tank-full",
51921
+ "device-tank-normal"
51922
+ ];
51923
+ /**
51924
+ * The catalog as `getTemplateCatalog` SERVES it: every descriptor, with the
51925
+ * held-back kinds removed from its `systemEventKinds`. A descriptor that named
51926
+ * only held-back kinds is served with an empty list — offered to no system
51927
+ * rule an installed viewer can author, which is exactly true.
51928
+ */
51929
+ function servedTemplateVars() {
51930
+ return NC_TEMPLATE_VARS.map((d) => d.systemEventKinds === void 0 ? d : {
51931
+ ...d,
51932
+ systemEventKinds: d.systemEventKinds.filter((kind) => !NC_TEMPLATE_HELD_BACK_SYSTEM_EVENT_KINDS.includes(kind))
51933
+ });
51934
+ }
51774
51935
  /** The caption fields see a fixed, smaller vocabulary (`timelapsePreviewText`,
51775
51936
  * `summaryCaptionText`). Declared here rather than as `fields` on every
51776
51937
  * descriptor so the whole rule stays in one line of code. */
@@ -52845,4 +53006,4 @@ function vectorDimFromBase64(encoded) {
52845
53006
  return Math.floor(Buffer.from(encoded, "base64").byteLength / 4);
52846
53007
  }
52847
53008
  //#endregion
52848
- export { PoolMemoryWatchdog as $, systemEventFamilyProblems as $t, NC_SENSOR_TRANSITION_KINDS as A, isEventOwnerType as At, NcRuleSchema as B, parseProcStatus as Bt, MAX_BIRTH_DECISION_RECORDS as C, partialRecord as Cn, encodeVectorBase64 as Ct, NC_ALARM_SYSTEM_EVENT_KINDS as D, EventCategory as Dn, failureContributionCapability as Dt, MediaFileKindEnum as E, unknown as En, faceGalleryCapability as Et, NcAlarmSettingsPatchSchema as F, isSystemDelivery as Ft, NcSnoozeSchema as G, readTimelapseGeneratedAt as Gt, NcRuleUpdateInputSchema as H, pipelineAnalyticsCapability as Ht, NcConditionDescriptorSchema as I, kebabToCamel as It, NcTaxonomySchema as J, ruleBelongsToAlarm as Jt, NcSnoozeSuppressedSchema as K, resolveLocationMode as Kt, NcConditionsSchema as L, mayWriteToLocation as Lt, NC_TAXONOMY as M, isMediaOwnerType as Mt, NC_TEMPLATE_VARS as N, isScheduleActive as Nt, NC_CONDITION_CATALOG as O, hfModelUrl as Ot, NcAlarmConfigSchema as P, isSourceCap as Pt, OpsLogEntrySchema as Q, subKindsOf as Qt, NcRuleInputSchema as R, notificationRulesCapability as Rt, MAX_ARCHIVED_DEBUG_NOTES as S, object as Sn, embeddingEncoderCapability as St, MOTION_CLOSE_AFTER_MS as T, string as Tn, evictionPolicyOfLocation as Tt, NcScheduleSchema as U, plateGalleryCapability as Ut, NcRuleTargetSchema as V, pickClusterStepModels as Vt, NcSnoozeInputSchema as W, readDeviceStateFrom as Wt, NcTemplatePreviewSchema as X, sensorRaisedOf as Xt, NcTemplatePreviewInputSchema as Y, sceneMonitorCapability as Yt, NcTemplateVarDescriptorSchema as Z, storageOccupancyCapability as Zt, FIRST_LEVEL_MACRO_CLASSES as _, array as _n, audioModeOf as _t, BirthDecisionRecordSchema as a, canonicalHash as an, SCENE_DEFAULT_UNCOVERED_POLICY as at, LabelAttributionSchema as b, literal as bn, deriveRecordingMode as bt, CoverStateSchema as c, DeviceType as cn, TIMELAPSE_DENSE_FLOOR_SEC as ct, DEFAULT_TIMELAPSE_PREVIEW_TEXT as d, defineCustomActions as dn, TimelapseRuleSchema as dt, systemEventFilterApplies as en, RECORDING_EXPORT_MAX_READ_BYTES as et, DETECTION_MACRO_CLASSES as f, hydrateSchema as fn, TrackSourceSchema as ft, EVENT_OWNER_TYPES as g, _enum as gn, audioMetricsCapability as gt, EVENT_KIND_BY_CAP as h, sleep as hn, assertTimelapseCadences as ht, BaseDevice as i, errMsg as in, SCENE_DEFAULT_ANCHOR_THRESHOLD as it, NC_SNOOZE_MAX_MINUTES as j, isKnownTemplateVar as jt, NC_DEFAULT_SNOOZE_MINUTES as k, isDetectionMacroClass as kt, DEFAULT_EVENT_COLOR as l, createEvent as ln, TimelapseRuleInputSchema as lt, DeclaredDevices as m, nodePin as mn, alarmPanelCapability as mt, AlarmArmModeSchema as n, vectorDimFromBase64 as nn, RetrainStatusSchema as nt, CLUSTER_MODEL_SCOPED_STEPS as o, BaseAddon as on, SCENE_DIVERGED as ot, DETECTION_PIPELINE_CAP_NAME as p, isDeviceScopedCap as pn, addonWidgetsSourceCapability as pt, NcSystemEventKindSchema as q, resolvePoolMemoryPolicy as qt, ArchivedDebugNoteSchema as r, zoneAnalyticsCapability as rn, SCENE_CONFIRM_DEFAULT_TIMEOUT_MS as rt, COCO_TO_MACRO as s, CamProfileSchema as sn, SceneMonitorSchema as st, AUDIO_MACRO_LABELS as t, templateVarsFor as tn, RECORDING_SOURCE_CAMSTACK_ADDON as tt, DEFAULT_FIRST_SIGHTING_FRESHNESS_MS as u, customAction as un, TimelapseRulePatchSchema as ut, FULL_IMAGE_BBOX as v, boolean as vn, buildEventKindDescriptor as vt, MAX_BIRTH_LATENCY_PROXY_MS as w, record as wn, evaluateSensorEdge as wt, LockStateSchema as x, number as xn, describeSystemEventFamilyProblem as xt, FailureCounters as y, discriminatedUnion as yn, cosineSimilarity as yt, NcRulePatchSchema as z, occupancyScope as zt };
53009
+ export { NcTemplateVarDescriptorSchema as $, sensorRaisedOf as $t, NC_DEFAULT_SNOOZE_MINUTES as A, unknown as An, failureContributionCapability as At, NcRuleInputSchema as B, mayWriteToLocation as Bt, MAX_BIRTH_DECISION_RECORDS as C, discriminatedUnion as Cn, deriveRecordingMode as Ct, NC_ALARM_SYSTEM_EVENT_KINDS as D, partialRecord as Dn, evaluateSensorEdge as Dt, MediaFileKindEnum as E, object as En, encodeVectorBase64 as Et, NC_TEMPLATE_VARS as F, isMediaOwnerType as Ft, NcScheduleSchema as G, pipelineAnalyticsCapability as Gt, NcRuleSchema as H, occupancyScope as Ht, NcAlarmConfigSchema as I, isScheduleActive as It, NcSnoozeSuppressedSchema as J, readTimelapseGeneratedAt as Jt, NcSnoozeInputSchema as K, plateGalleryCapability as Kt, NcAlarmSettingsPatchSchema as L, isSourceCap as Lt, NC_SNOOZE_MAX_MINUTES as M, isDetectionMacroClass as Mt, NC_TANK_SYSTEM_EVENT_KINDS as N, isEventOwnerType as Nt, NC_CONDITION_CATALOG as O, record as On, evictionPolicyOfLocation as Ot, NC_TAXONOMY as P, isKnownTemplateVar as Pt, NcTemplatePreviewSchema as Q, sceneMonitorCapability as Qt, NcConditionDescriptorSchema as R, isSystemDelivery as Rt, MAX_ARCHIVED_DEBUG_NOTES as S, boolean as Sn, cosineSimilarity as St, MOTION_CLOSE_AFTER_MS as T, number as Tn, embeddingEncoderCapability as Tt, NcRuleTargetSchema as U, parseProcStatus as Ut, NcRulePatchSchema as V, notificationRulesCapability as Vt, NcRuleUpdateInputSchema as W, pickClusterStepModels as Wt, NcTaxonomySchema as X, resolvePoolMemoryPolicy as Xt, NcSystemEventKindSchema as Y, resolveLocationMode as Yt, NcTemplatePreviewInputSchema as Z, ruleBelongsToAlarm as Zt, FIRST_LEVEL_MACRO_CLASSES as _, isDeviceScopedCap as _n, assertTimelapseCadences as _t, BirthDecisionRecordSchema as a, templateVarsFor as an, SCENE_CONFIRM_DEFAULT_TIMEOUT_MS as at, LabelAttributionSchema as b, _enum as bn, buildEventKindDescriptor as bt, CoverStateSchema as c, errMsg as cn, SCENE_DIVERGED as ct, DEFAULT_TIMELAPSE_PREVIEW_TEXT as d, CamProfileSchema as dn, TimelapseRuleInputSchema as dt, servedTemplateVars as en, OpsLogEntrySchema as et, DETECTION_MACRO_CLASSES as f, DeviceType as fn, TimelapseRulePatchSchema as ft, EVENT_OWNER_TYPES as g, hydrateSchema as gn, alarmPanelCapability as gt, EVENT_KIND_BY_CAP as h, defineCustomActions as hn, addonWidgetsSourceCapability as ht, BaseDevice as i, systemEventFilterApplies as in, RetrainStatusSchema as it, NC_SENSOR_TRANSITION_KINDS as j, EventCategory as jn, hfModelUrl as jt, NC_CONSUMABLE_SYSTEM_EVENT_KINDS as k, string as kn, faceGalleryCapability as kt, DEFAULT_EVENT_COLOR as l, canonicalHash as ln, SceneMonitorSchema as lt, DeclaredDevices as m, customAction as mn, TrackSourceSchema as mt, AlarmArmModeSchema as n, subKindsOf as nn, RECORDING_EXPORT_MAX_READ_BYTES as nt, CLUSTER_MODEL_SCOPED_STEPS as o, vectorDimFromBase64 as on, SCENE_DEFAULT_ANCHOR_THRESHOLD as ot, DETECTION_PIPELINE_CAP_NAME as p, createEvent as pn, TimelapseRuleSchema as pt, NcSnoozeSchema as q, readDeviceStateFrom as qt, ArchivedDebugNoteSchema as r, systemEventFamilyProblems as rn, RECORDING_SOURCE_CAMSTACK_ADDON as rt, COCO_TO_MACRO as s, zoneAnalyticsCapability as sn, SCENE_DEFAULT_UNCOVERED_POLICY as st, AUDIO_MACRO_LABELS as t, storageOccupancyCapability as tn, PoolMemoryWatchdog as tt, DEFAULT_FIRST_SIGHTING_FRESHNESS_MS as u, BaseAddon as un, TIMELAPSE_DENSE_FLOOR_SEC as ut, FULL_IMAGE_BBOX as v, nodePin as vn, audioMetricsCapability as vt, MAX_BIRTH_LATENCY_PROXY_MS as w, literal as wn, describeSystemEventFamilyProblem as wt, LockStateSchema as x, array as xn, consumableLowPercentOf as xt, FailureCounters as y, sleep as yn, audioModeOf as yt, NcConditionsSchema as z, kebabToCamel as zt };
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_dist = require("../dist-D0zzdvSd.js");
5
+ const require_dist = require("../dist-CT5xOY86.js");
6
6
  let node_fs = require("node:fs");
7
7
  node_fs = require_dist.__toESM(node_fs);
8
8
  let node_path = require("node:path");
@@ -1,4 +1,4 @@
1
- import { $ as PoolMemoryWatchdog, Bt as parseProcStatus, Ot as hfModelUrl, St as embeddingEncoderCapability, on as BaseAddon, qt as resolvePoolMemoryPolicy } from "../dist-C3zTKShG.mjs";
1
+ import { Tt as embeddingEncoderCapability, Ut as parseProcStatus, Xt as resolvePoolMemoryPolicy, jt as hfModelUrl, tt as PoolMemoryWatchdog, un as BaseAddon } from "../dist-zp1v7cCp.mjs";
2
2
  import { createRequire } from "node:module";
3
3
  import * as fs from "node:fs";
4
4
  import * as path$1 from "node:path";
@@ -2,7 +2,7 @@ import { a as e, i as t, n, o as r, r as i, t as a } from "./_virtual_mf___mfe_i
2
2
  import { t as o } from "./_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-B3Wx5J80.mjs";
3
3
  import { a as s, i as c, n as l, o as u, r as d, s as f, t as p } from "./_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DWPDYuJS.mjs";
4
4
  import { n as m, r as h, t as g } from "./_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-Bm-iyjmq.mjs";
5
- import { t as _ } from "./_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DT-cQNv-.mjs";
5
+ import { t as _ } from "./_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CZkZhroP.mjs";
6
6
  //#region ../../node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.js
7
7
  var v = (...e) => e.filter((e, t, n) => !!e && e.trim() !== "" && n.indexOf(e) === t).join(" ").trim(), y = (e) => e.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), b = (e) => e.replace(/^([A-Z])|[\s-_]+(\w)/g, (e, t, n) => n ? n.toUpperCase() : t.toLowerCase()), x = (e) => {
8
8
  let t = b(e);