camstack 1.2.53 → 1.2.54

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.
@@ -21687,6 +21687,80 @@ var logDestinationCapability = {
21687
21687
  /** BIG PLAN 2: declarative mount hint — read by `@camstack/system` `buildCapRouters`. */
21688
21688
  mount: { kind: "skip" }
21689
21689
  };
21690
+ var FailureReasonCountSchema = external_exports.object({
21691
+ /**
21692
+ * Why the attempt did not land, in the contributor's own vocabulary —
21693
+ * `worker-lease-gone`, `queue-overflow`, `timeout`, `empty-read`. The same
21694
+ * strings that already appear in this repo's logs and, where one exists, the
21695
+ * same string the per-track `previewMissReason` records (D276): a second
21696
+ * vocabulary for the same loss would make the row and the counter
21697
+ * un-joinable.
21698
+ */
21699
+ reason: external_exports.string(),
21700
+ count: external_exports.number().int().nonnegative()
21701
+ });
21702
+ var FailureContributionSchema = external_exports.object({
21703
+ /**
21704
+ * The failing path — `enrichment-crop`, `inference`, `plate-ocr`,
21705
+ * `person-over-vehicle`. Free text, for the reason `load-contribution` keeps
21706
+ * `unit` free: the families are owned by different addons and a shared enum
21707
+ * is a central list that rots invisibly.
21708
+ */
21709
+ family: external_exports.string(),
21710
+ /**
21711
+ * The NUMERIC device id — the same value every log line carries as
21712
+ * `tags.deviceId`. Never nullable and never absent: a contributor that
21713
+ * cannot name the camera must not emit the entry, because a fleet total
21714
+ * cannot answer the only question anybody asks of this surface.
21715
+ */
21716
+ deviceId: external_exports.number().int().positive(),
21717
+ /**
21718
+ * A second dimension inside the family: the model / step id for an inference
21719
+ * timeout, so "which camera AND which model" is one read. Absent when the
21720
+ * family has a single variant.
21721
+ */
21722
+ variant: external_exports.string().optional(),
21723
+ /**
21724
+ * Epoch ms this counter started — the INCARNATION MARKER. A consumer
21725
+ * differencing two reads must drop the interval when it changes, because the
21726
+ * counter restarted from zero in a respawned runner. Same discipline as
21727
+ * `LoadContribution.startedAtMs`.
21728
+ */
21729
+ sinceMs: external_exports.number(),
21730
+ /** Epoch ms it was read. `atMs - sinceMs` is the interval this covers. */
21731
+ atMs: external_exports.number(),
21732
+ /**
21733
+ * THE DENOMINATOR — every attempt on this path for this camera in the
21734
+ * window. A failure count published without it is the mistake this schema
21735
+ * exists to make impossible.
21736
+ */
21737
+ attempts: external_exports.number().int().nonnegative(),
21738
+ /** Attempts that landed. `attempts - succeeded` is the loss. */
21739
+ succeeded: external_exports.number().int().nonnegative(),
21740
+ /** The loss, partitioned. Sums to `attempts - succeeded`. */
21741
+ reasons: external_exports.array(FailureReasonCountSchema).readonly()
21742
+ });
21743
+ var failureContributionCapability = {
21744
+ name: "failure-contribution",
21745
+ scope: "system",
21746
+ mode: "collection",
21747
+ internal: true,
21748
+ methods: {
21749
+ /**
21750
+ * This addon's per-camera failure counters, read live from bounded in-RAM
21751
+ * state it already keeps. Inert: no persistence, no sampling, no timer.
21752
+ *
21753
+ * READING NEVER RESETS. The counters are CUMULATIVE since `sinceMs`, and a
21754
+ * consumer that wants a rate differences two reads. A draining read would
21755
+ * make two operators with the page open each destroy half of the other's
21756
+ * numbers, and `load-contribution` already settled the same question the
21757
+ * same way for `cpuSeconds`.
21758
+ */
21759
+ list: method(external_exports.void(), external_exports.array(FailureContributionSchema).readonly())
21760
+ },
21761
+ /** In-process only — enumerated through `addons.listCapabilityProviders`. */
21762
+ mount: { kind: "skip" }
21763
+ };
21690
21764
  var LOAD_CONTRIBUTION_ROLES = [
21691
21765
  "decode",
21692
21766
  "transcode",
@@ -25679,6 +25753,20 @@ var TrackSchema = external_exports.object({
25679
25753
  * `=== true` and render nothing otherwise — never infer "no rider".
25680
25754
  */
25681
25755
  hasRider: external_exports.boolean().optional(),
25756
+ /**
25757
+ * WHY this track ended without a NATIVE best-shot tile
25758
+ * ([D276](../decisions/adr-0276-a-stand-in-tile-is-provisional-and-a-close-says-why.md)) —
25759
+ * a composed token line (`no-key-frame capture=keyframe:native-missx4`,
25760
+ * `derive-returned-null tile=standin`, …) written at close and CLEARED by
25761
+ * the late-keyFrame upgrade when a native tile lands after all. The
25762
+ * operator-facing answer to "perché manca l'immagine?" on a track whose
25763
+ * tile is a face/plate stand-in, a raster crop, or an icon.
25764
+ *
25765
+ * **Absent ≠ "missed silently"**: a row written before the column, a hub
25766
+ * that predates the field, and every track whose tile landed native all
25767
+ * omit it. Render nothing when absent.
25768
+ */
25769
+ previewMissReason: external_exports.string().optional(),
25682
25770
  ...TrackFlagFields,
25683
25771
  ...TrackRetrainFields
25684
25772
  });
@@ -37178,6 +37266,7 @@ var LoggingSettingsPatchSchema = external_exports.object({
37178
37266
  channels: external_exports.array(LogChannelWindowPatchSchema).readonly().optional()
37179
37267
  });
37180
37268
  var ReportedLoadContributionSchema = LoadContributionSchema.extend({ addonId: external_exports.string() });
37269
+ var ReportedFailureContributionSchema = FailureContributionSchema.extend({ addonId: external_exports.string() });
37181
37270
  var GetLoggingSettingsInputSchema = external_exports.object({
37182
37271
  scopeNodeId: external_exports.string().optional(),
37183
37272
  /**
@@ -37287,6 +37376,28 @@ var systemCapability = {
37287
37376
  */
37288
37377
  getLoadContributions: method(external_exports.void(), external_exports.array(ReportedLoadContributionSchema).readonly(), { auth: "admin" }),
37289
37378
  /**
37379
+ * Every `failure-contribution` an addon on this cluster reports — per
37380
+ * camera, per reason, **with the denominator attached**.
37381
+ *
37382
+ * This is the surface the operator asked for on 2026-08-28 (*"possiamo
37383
+ * armare questi errori intanto? Così al prossimo giro ricontrolliamo tutti
37384
+ * questi punti"*). Before it, four live failure modes could only be counted
37385
+ * by grepping Loki and hand-correlating timestamps, which is exactly how a
37386
+ * 22% thumbnail gap and a 3-hour media blackout were diagnosed — twice.
37387
+ *
37388
+ * Read it as a RATIO, never as a count. `attempts` is on every entry
37389
+ * because the count on its own lies: `enrichment crop native miss` read as
37390
+ * "35x worse than yesterday" and was flat across twelve hours once divided
37391
+ * by the successes on the same path.
37392
+ *
37393
+ * The counters are CUMULATIVE since each entry's `sinceMs`. Reading does
37394
+ * not reset them, and `sinceMs` changing means the reporting runner
37395
+ * respawned — a consumer differencing two reads drops that interval.
37396
+ *
37397
+ * Admin-only: the rows name cameras and the paths that fail on them.
37398
+ */
37399
+ getFailureContributions: method(external_exports.void(), external_exports.array(ReportedFailureContributionSchema).readonly(), { auth: "admin" }),
37400
+ /**
37290
37401
  * The logging settings document — levels and armed diagnostics — resolved
37291
37402
  * for `nodeId`, or for the cluster when `nodeId` is absent.
37292
37403
  *
@@ -40159,6 +40270,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
40159
40270
  addonId: null,
40160
40271
  access: "create"
40161
40272
  },
40273
+ "failureContribution.list": {
40274
+ capName: "failure-contribution",
40275
+ capScope: "system",
40276
+ addonId: null,
40277
+ access: "view"
40278
+ },
40162
40279
  "fanControl.setDirection": {
40163
40280
  capName: "fan-control",
40164
40281
  capScope: "device",
@@ -43465,6 +43582,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
43465
43582
  addonId: null,
43466
43583
  access: "create"
43467
43584
  },
43585
+ "system.getFailureContributions": {
43586
+ capName: "system",
43587
+ capScope: "system",
43588
+ addonId: null,
43589
+ access: "view"
43590
+ },
43468
43591
  "system.getLoadContributions": {
43469
43592
  capName: "system",
43470
43593
  capScope: "system",
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runDiscover
4
- } from "./chunk-P6IF6IX5.js";
4
+ } from "./chunk-NEA5DJLZ.js";
5
5
  import "./chunk-LMMQX4CK.js";
6
6
 
7
7
  // src/cli.ts
@@ -38,7 +38,7 @@ async function runServe(args) {
38
38
  ...typeof values.data === "string" ? { data: values.data } : {}
39
39
  };
40
40
  Object.assign(process.env, buildServeEnv(opts));
41
- await import("./launcher-3YAJ644E.js");
41
+ await import("./launcher-QLUF66FQ.js");
42
42
  }
43
43
 
44
44
  // src/commands/agent.ts
@@ -83,7 +83,7 @@ async function runAgent(args) {
83
83
  ...typeof values.port === "string" ? { port: values.port } : {}
84
84
  };
85
85
  Object.assign(process.env, buildAgentEnv(opts));
86
- await import("./launcher-3YAJ644E.js");
86
+ await import("./launcher-QLUF66FQ.js");
87
87
  }
88
88
 
89
89
  // src/commands/setup.ts
@@ -1130,7 +1130,7 @@ function isUnknown(_value) {
1130
1130
  return true;
1131
1131
  }
1132
1132
  async function resolveServerInteractive(presetNamespace) {
1133
- const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-255INDLH.js");
1133
+ const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-2O7WGGRD.js");
1134
1134
  if (presetNamespace) {
1135
1135
  const spinner4 = clack.spinner();
1136
1136
  spinner4.start(`Discovering hub on LAN (namespace "${presetNamespace}")`);
@@ -5,7 +5,7 @@ import {
5
5
  filterHubNodes,
6
6
  resolveHubFromDiscovered,
7
7
  runDiscover
8
- } from "./chunk-P6IF6IX5.js";
8
+ } from "./chunk-NEA5DJLZ.js";
9
9
  import "./chunk-LMMQX4CK.js";
10
10
  export {
11
11
  DEFAULT_HUB_HTTPS_PORT,
@@ -23633,9 +23633,9 @@ var require_zod = __commonJS({
23633
23633
  }
23634
23634
  });
23635
23635
 
23636
- // ../system/dist/dist-DdEXjTDo.js
23637
- var require_dist_DdEXjTDo = __commonJS({
23638
- "../system/dist/dist-DdEXjTDo.js"(exports) {
23636
+ // ../system/dist/dist-CImxMt5h.js
23637
+ var require_dist_CImxMt5h = __commonJS({
23638
+ "../system/dist/dist-CImxMt5h.js"(exports) {
23639
23639
  "use strict";
23640
23640
  var zod = require_zod();
23641
23641
  var EventCategory = /* @__PURE__ */ (function(EventCategory2) {
@@ -32354,6 +32354,80 @@ var require_dist_DdEXjTDo = __commonJS({
32354
32354
  /** BIG PLAN 2: declarative mount hint — read by `@camstack/system` `buildCapRouters`. */
32355
32355
  mount: { kind: "skip" }
32356
32356
  };
32357
+ var FailureReasonCountSchema = zod.z.object({
32358
+ /**
32359
+ * Why the attempt did not land, in the contributor's own vocabulary —
32360
+ * `worker-lease-gone`, `queue-overflow`, `timeout`, `empty-read`. The same
32361
+ * strings that already appear in this repo's logs and, where one exists, the
32362
+ * same string the per-track `previewMissReason` records (D276): a second
32363
+ * vocabulary for the same loss would make the row and the counter
32364
+ * un-joinable.
32365
+ */
32366
+ reason: zod.z.string(),
32367
+ count: zod.z.number().int().nonnegative()
32368
+ });
32369
+ var FailureContributionSchema = zod.z.object({
32370
+ /**
32371
+ * The failing path — `enrichment-crop`, `inference`, `plate-ocr`,
32372
+ * `person-over-vehicle`. Free text, for the reason `load-contribution` keeps
32373
+ * `unit` free: the families are owned by different addons and a shared enum
32374
+ * is a central list that rots invisibly.
32375
+ */
32376
+ family: zod.z.string(),
32377
+ /**
32378
+ * The NUMERIC device id — the same value every log line carries as
32379
+ * `tags.deviceId`. Never nullable and never absent: a contributor that
32380
+ * cannot name the camera must not emit the entry, because a fleet total
32381
+ * cannot answer the only question anybody asks of this surface.
32382
+ */
32383
+ deviceId: zod.z.number().int().positive(),
32384
+ /**
32385
+ * A second dimension inside the family: the model / step id for an inference
32386
+ * timeout, so "which camera AND which model" is one read. Absent when the
32387
+ * family has a single variant.
32388
+ */
32389
+ variant: zod.z.string().optional(),
32390
+ /**
32391
+ * Epoch ms this counter started — the INCARNATION MARKER. A consumer
32392
+ * differencing two reads must drop the interval when it changes, because the
32393
+ * counter restarted from zero in a respawned runner. Same discipline as
32394
+ * `LoadContribution.startedAtMs`.
32395
+ */
32396
+ sinceMs: zod.z.number(),
32397
+ /** Epoch ms it was read. `atMs - sinceMs` is the interval this covers. */
32398
+ atMs: zod.z.number(),
32399
+ /**
32400
+ * THE DENOMINATOR — every attempt on this path for this camera in the
32401
+ * window. A failure count published without it is the mistake this schema
32402
+ * exists to make impossible.
32403
+ */
32404
+ attempts: zod.z.number().int().nonnegative(),
32405
+ /** Attempts that landed. `attempts - succeeded` is the loss. */
32406
+ succeeded: zod.z.number().int().nonnegative(),
32407
+ /** The loss, partitioned. Sums to `attempts - succeeded`. */
32408
+ reasons: zod.z.array(FailureReasonCountSchema).readonly()
32409
+ });
32410
+ var failureContributionCapability = {
32411
+ name: "failure-contribution",
32412
+ scope: "system",
32413
+ mode: "collection",
32414
+ internal: true,
32415
+ methods: {
32416
+ /**
32417
+ * This addon's per-camera failure counters, read live from bounded in-RAM
32418
+ * state it already keeps. Inert: no persistence, no sampling, no timer.
32419
+ *
32420
+ * READING NEVER RESETS. The counters are CUMULATIVE since `sinceMs`, and a
32421
+ * consumer that wants a rate differences two reads. A draining read would
32422
+ * make two operators with the page open each destroy half of the other's
32423
+ * numbers, and `load-contribution` already settled the same question the
32424
+ * same way for `cpuSeconds`.
32425
+ */
32426
+ list: method(zod.z.void(), zod.z.array(FailureContributionSchema).readonly())
32427
+ },
32428
+ /** In-process only — enumerated through `addons.listCapabilityProviders`. */
32429
+ mount: { kind: "skip" }
32430
+ };
32357
32431
  var LoadContributionSchema = zod.z.object({
32358
32432
  role: zod.z.enum([
32359
32433
  "decode",
@@ -36340,6 +36414,20 @@ var require_dist_DdEXjTDo = __commonJS({
36340
36414
  * `=== true` and render nothing otherwise — never infer "no rider".
36341
36415
  */
36342
36416
  hasRider: zod.z.boolean().optional(),
36417
+ /**
36418
+ * WHY this track ended without a NATIVE best-shot tile
36419
+ * ([D276](../decisions/adr-0276-a-stand-in-tile-is-provisional-and-a-close-says-why.md)) —
36420
+ * a composed token line (`no-key-frame capture=keyframe:native-missx4`,
36421
+ * `derive-returned-null tile=standin`, …) written at close and CLEARED by
36422
+ * the late-keyFrame upgrade when a native tile lands after all. The
36423
+ * operator-facing answer to "perché manca l'immagine?" on a track whose
36424
+ * tile is a face/plate stand-in, a raster crop, or an icon.
36425
+ *
36426
+ * **Absent ≠ "missed silently"**: a row written before the column, a hub
36427
+ * that predates the field, and every track whose tile landed native all
36428
+ * omit it. Render nothing when absent.
36429
+ */
36430
+ previewMissReason: zod.z.string().optional(),
36343
36431
  ...TrackFlagFields,
36344
36432
  ...TrackRetrainFields
36345
36433
  });
@@ -47923,6 +48011,7 @@ var require_dist_DdEXjTDo = __commonJS({
47923
48011
  channels: zod.z.array(LogChannelWindowPatchSchema).readonly().optional()
47924
48012
  });
47925
48013
  var ReportedLoadContributionSchema = LoadContributionSchema.extend({ addonId: zod.z.string() });
48014
+ var ReportedFailureContributionSchema = FailureContributionSchema.extend({ addonId: zod.z.string() });
47926
48015
  var GetLoggingSettingsInputSchema = zod.z.object({
47927
48016
  scopeNodeId: zod.z.string().optional(),
47928
48017
  /**
@@ -48032,6 +48121,28 @@ var require_dist_DdEXjTDo = __commonJS({
48032
48121
  */
48033
48122
  getLoadContributions: method(zod.z.void(), zod.z.array(ReportedLoadContributionSchema).readonly(), { auth: "admin" }),
48034
48123
  /**
48124
+ * Every `failure-contribution` an addon on this cluster reports — per
48125
+ * camera, per reason, **with the denominator attached**.
48126
+ *
48127
+ * This is the surface the operator asked for on 2026-08-28 (*"possiamo
48128
+ * armare questi errori intanto? Così al prossimo giro ricontrolliamo tutti
48129
+ * questi punti"*). Before it, four live failure modes could only be counted
48130
+ * by grepping Loki and hand-correlating timestamps, which is exactly how a
48131
+ * 22% thumbnail gap and a 3-hour media blackout were diagnosed — twice.
48132
+ *
48133
+ * Read it as a RATIO, never as a count. `attempts` is on every entry
48134
+ * because the count on its own lies: `enrichment crop native miss` read as
48135
+ * "35x worse than yesterday" and was flat across twelve hours once divided
48136
+ * by the successes on the same path.
48137
+ *
48138
+ * The counters are CUMULATIVE since each entry's `sinceMs`. Reading does
48139
+ * not reset them, and `sinceMs` changing means the reporting runner
48140
+ * respawned — a consumer differencing two reads drops that interval.
48141
+ *
48142
+ * Admin-only: the rows name cameras and the paths that fail on them.
48143
+ */
48144
+ getFailureContributions: method(zod.z.void(), zod.z.array(ReportedFailureContributionSchema).readonly(), { auth: "admin" }),
48145
+ /**
48035
48146
  * The logging settings document — levels and armed diagnostics — resolved
48036
48147
  * for `nodeId`, or for the cluster when `nodeId` is absent.
48037
48148
  *
@@ -49436,6 +49547,7 @@ var require_dist_DdEXjTDo = __commonJS({
49436
49547
  eventEmitterCapability,
49437
49548
  eventsCapability,
49438
49549
  faceGalleryCapability,
49550
+ failureContributionCapability,
49439
49551
  fanControlCapability,
49440
49552
  featureProbeCapability,
49441
49553
  filesystemBrowseCapability,
@@ -51440,6 +51552,12 @@ var require_dist_DdEXjTDo = __commonJS({
51440
51552
  addonId: null,
51441
51553
  access: "create"
51442
51554
  },
51555
+ "failureContribution.list": {
51556
+ capName: "failure-contribution",
51557
+ capScope: "system",
51558
+ addonId: null,
51559
+ access: "view"
51560
+ },
51443
51561
  "fanControl.setDirection": {
51444
51562
  capName: "fan-control",
51445
51563
  capScope: "device",
@@ -54746,6 +54864,12 @@ var require_dist_DdEXjTDo = __commonJS({
54746
54864
  addonId: null,
54747
54865
  access: "create"
54748
54866
  },
54867
+ "system.getFailureContributions": {
54868
+ capName: "system",
54869
+ capScope: "system",
54870
+ addonId: null,
54871
+ access: "view"
54872
+ },
54749
54873
  "system.getLoadContributions": {
54750
54874
  capName: "system",
54751
54875
  capScope: "system",
@@ -58515,7 +58639,7 @@ var require_alerts_addon = __commonJS({
58515
58639
  [Symbol.toStringTag]: { value: "Module" }
58516
58640
  });
58517
58641
  require_chunk_Cek0wNdY();
58518
- var require_dist10 = require_dist_DdEXjTDo();
58642
+ var require_dist10 = require_dist_CImxMt5h();
58519
58643
  function selectExpired(alerts, cutoffMs) {
58520
58644
  return alerts.filter((a) => a.createdAt < cutoffMs).sort((a, b) => a.createdAt - b.createdAt).map((a) => a.id);
58521
58645
  }
@@ -59334,7 +59458,7 @@ var require_console_logging = __commonJS({
59334
59458
  [Symbol.toStringTag]: { value: "Module" }
59335
59459
  });
59336
59460
  require_chunk_Cek0wNdY();
59337
- var require_dist10 = require_dist_DdEXjTDo();
59461
+ var require_dist10 = require_dist_CImxMt5h();
59338
59462
  var require_formatter = require_formatter_DqAKDlvN();
59339
59463
  var LEVEL_RANK = {
59340
59464
  debug: 0,
@@ -59428,7 +59552,7 @@ var require_core_blocks_addon = __commonJS({
59428
59552
  "use strict";
59429
59553
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
59430
59554
  var require_chunk = require_chunk_Cek0wNdY();
59431
- var require_dist10 = require_dist_DdEXjTDo();
59555
+ var require_dist10 = require_dist_CImxMt5h();
59432
59556
  var node_crypto = __require("crypto");
59433
59557
  var node_fs_promises = __require("fs/promises");
59434
59558
  node_fs_promises = require_chunk.__toESM(node_fs_promises);
@@ -60325,11 +60449,11 @@ var require_core_blocks = __commonJS({
60325
60449
  }
60326
60450
  });
60327
60451
 
60328
- // ../system/dist/retired-settings-keys-BXaTgLyZ.js
60329
- var require_retired_settings_keys_BXaTgLyZ = __commonJS({
60330
- "../system/dist/retired-settings-keys-BXaTgLyZ.js"(exports) {
60452
+ // ../system/dist/retired-settings-keys-C7gLUS3x.js
60453
+ var require_retired_settings_keys_C7gLUS3x = __commonJS({
60454
+ "../system/dist/retired-settings-keys-C7gLUS3x.js"(exports) {
60331
60455
  "use strict";
60332
- var require_dist10 = require_dist_DdEXjTDo();
60456
+ var require_dist10 = require_dist_CImxMt5h();
60333
60457
  function settingsStoreIsAuthoritativeHere(env) {
60334
60458
  const raw = (env["CAMSTACK_ROLE"] ?? "").trim().toLowerCase();
60335
60459
  return raw === "" || raw === "hub";
@@ -62543,8 +62667,8 @@ var require_device_manager_addon = __commonJS({
62543
62667
  [Symbol.toStringTag]: { value: "Module" }
62544
62668
  });
62545
62669
  require_chunk_Cek0wNdY();
62546
- var require_dist10 = require_dist_DdEXjTDo();
62547
- var require_retired_settings_keys = require_retired_settings_keys_BXaTgLyZ();
62670
+ var require_dist10 = require_dist_CImxMt5h();
62671
+ var require_retired_settings_keys = require_retired_settings_keys_C7gLUS3x();
62548
62672
  var node_crypto = __require("crypto");
62549
62673
  var _camstack_types_node = require_node();
62550
62674
  var JOB_HISTORY = 20;
@@ -67293,7 +67417,7 @@ var require_hub_forwarder = __commonJS({
67293
67417
  [Symbol.toStringTag]: { value: "Module" }
67294
67418
  });
67295
67419
  require_chunk_Cek0wNdY();
67296
- var require_dist10 = require_dist_DdEXjTDo();
67420
+ var require_dist10 = require_dist_CImxMt5h();
67297
67421
  var require_formatter = require_formatter_DqAKDlvN();
67298
67422
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
67299
67423
  var HubForwarderDestination = class {
@@ -67430,7 +67554,7 @@ var require_liveness_monitor_addon = __commonJS({
67430
67554
  "use strict";
67431
67555
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
67432
67556
  require_chunk_Cek0wNdY();
67433
- var require_dist10 = require_dist_DdEXjTDo();
67557
+ var require_dist10 = require_dist_CImxMt5h();
67434
67558
  var NO_DEVICES = "liveness:no-devices";
67435
67559
  var ALL_OFFLINE = "liveness:all-devices-offline";
67436
67560
  var NO_FOOTAGE_PREFIX = "liveness:no-footage:";
@@ -67620,7 +67744,7 @@ var require_local_auth_addon = __commonJS({
67620
67744
  [Symbol.toStringTag]: { value: "Module" }
67621
67745
  });
67622
67746
  var require_chunk = require_chunk_Cek0wNdY();
67623
- var require_dist10 = require_dist_DdEXjTDo();
67747
+ var require_dist10 = require_dist_CImxMt5h();
67624
67748
  var node_crypto = __require("crypto");
67625
67749
  node_crypto = require_chunk.__toESM(node_crypto);
67626
67750
  var crypto$1 = __require("crypto");
@@ -75433,7 +75557,7 @@ var require_loki_logging = __commonJS({
75433
75557
  [Symbol.toStringTag]: { value: "Module" }
75434
75558
  });
75435
75559
  require_chunk_Cek0wNdY();
75436
- var require_dist10 = require_dist_DdEXjTDo();
75560
+ var require_dist10 = require_dist_CImxMt5h();
75437
75561
  function sanitizeLabelName(raw) {
75438
75562
  const replaced = raw.replaceAll(/[^a-zA-Z0-9_]/g, "_");
75439
75563
  return /^[a-zA-Z_]/.test(replaced) ? replaced : `_${replaced}`;
@@ -75998,7 +76122,7 @@ var require_native_metrics_addon = __commonJS({
75998
76122
  [Symbol.toStringTag]: { value: "Module" }
75999
76123
  });
76000
76124
  var require_chunk = require_chunk_Cek0wNdY();
76001
- var require_dist10 = require_dist_DdEXjTDo();
76125
+ var require_dist10 = require_dist_CImxMt5h();
76002
76126
  var node_fs_promises = __require("fs/promises");
76003
76127
  var node_child_process = __require("child_process");
76004
76128
  var node_util = __require("util");
@@ -77955,7 +78079,7 @@ var require_filesystem_storage_addon = __commonJS({
77955
78079
  [Symbol.toStringTag]: { value: "Module" }
77956
78080
  });
77957
78081
  var require_chunk = require_chunk_Cek0wNdY();
77958
- var require_dist10 = require_dist_DdEXjTDo();
78082
+ var require_dist10 = require_dist_CImxMt5h();
77959
78083
  var node_crypto = __require("crypto");
77960
78084
  var node_fs_promises = __require("fs/promises");
77961
78085
  var node_path = __require("path");
@@ -79071,8 +79195,8 @@ var require_sqlite_settings_addon = __commonJS({
79071
79195
  [Symbol.toStringTag]: { value: "Module" }
79072
79196
  });
79073
79197
  var require_chunk = require_chunk_Cek0wNdY();
79074
- var require_dist10 = require_dist_DdEXjTDo();
79075
- var require_retired_settings_keys = require_retired_settings_keys_BXaTgLyZ();
79198
+ var require_dist10 = require_dist_CImxMt5h();
79199
+ var require_retired_settings_keys = require_retired_settings_keys_C7gLUS3x();
79076
79200
  var node_crypto = __require("crypto");
79077
79201
  var node_fs = __require("fs");
79078
79202
  var node_module = __require("module");
@@ -81351,7 +81475,7 @@ var require_storage_orchestrator_addon = __commonJS({
81351
81475
  [Symbol.toStringTag]: { value: "Module" }
81352
81476
  });
81353
81477
  var require_chunk = require_chunk_Cek0wNdY();
81354
- var require_dist10 = require_dist_DdEXjTDo();
81478
+ var require_dist10 = require_dist_CImxMt5h();
81355
81479
  var node_crypto = __require("crypto");
81356
81480
  var node_fs_promises = __require("fs/promises");
81357
81481
  node_fs_promises = require_chunk.__toESM(node_fs_promises);
@@ -83232,7 +83356,7 @@ var require_system_config_addon = __commonJS({
83232
83356
  [Symbol.toStringTag]: { value: "Module" }
83233
83357
  });
83234
83358
  require_chunk_Cek0wNdY();
83235
- var require_dist10 = require_dist_DdEXjTDo();
83359
+ var require_dist10 = require_dist_CImxMt5h();
83236
83360
  var SECTION_TITLES = {
83237
83361
  server: "Server",
83238
83362
  auth: "Authentication"
@@ -101293,7 +101417,7 @@ var require_winston_logging = __commonJS({
101293
101417
  [Symbol.toStringTag]: { value: "Module" }
101294
101418
  });
101295
101419
  var require_chunk = require_chunk_Cek0wNdY();
101296
- var require_dist10 = require_dist_DdEXjTDo();
101420
+ var require_dist10 = require_dist_CImxMt5h();
101297
101421
  var require_formatter = require_formatter_DqAKDlvN();
101298
101422
  var node_path = __require("path");
101299
101423
  node_path = require_chunk.__toESM(node_path);
@@ -107181,6 +107305,7 @@ var require_addon = __commonJS({
107181
107305
  "data-store-provider": ["histogram", "query"],
107182
107306
  "device-export": ["listExposedDevices", "listSupportedDeviceKinds"],
107183
107307
  "device-provider": ["discoverDevices", "getDevices"],
107308
+ "failure-contribution": ["list"],
107184
107309
  "llm": [
107185
107310
  "getDefaults",
107186
107311
  "getUsage",
@@ -113780,12 +113905,12 @@ var require_dist2 = __commonJS({
113780
113905
  }
113781
113906
  });
113782
113907
 
113783
- // ../system/dist/manifest-python-deps-CivtrAha.js
113784
- var require_manifest_python_deps_CivtrAha = __commonJS({
113785
- "../system/dist/manifest-python-deps-CivtrAha.js"(exports) {
113908
+ // ../system/dist/manifest-python-deps-BaVekjRY.js
113909
+ var require_manifest_python_deps_BaVekjRY = __commonJS({
113910
+ "../system/dist/manifest-python-deps-BaVekjRY.js"(exports) {
113786
113911
  "use strict";
113787
113912
  var require_chunk = require_chunk_Cek0wNdY();
113788
- require_dist_DdEXjTDo();
113913
+ require_dist_CImxMt5h();
113789
113914
  var node_crypto = __require("crypto");
113790
113915
  node_crypto = require_chunk.__toESM(node_crypto);
113791
113916
  var _camstack_types_node = require_node();
@@ -124900,7 +125025,7 @@ var require_dist3 = __commonJS({
124900
125025
  "use strict";
124901
125026
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
124902
125027
  var require_chunk = require_chunk_Cek0wNdY();
124903
- var require_dist10 = require_dist_DdEXjTDo();
125028
+ var require_dist10 = require_dist_CImxMt5h();
124904
125029
  var require_builtins_alerts_alerts_addon = require_alerts_addon();
124905
125030
  require_alerts();
124906
125031
  var require_formatter = require_formatter_DqAKDlvN();
@@ -124926,7 +125051,7 @@ var require_dist3 = __commonJS({
124926
125051
  var require_builtins_winston_logging_index = require_winston_logging();
124927
125052
  var require_file_data_plane = require_file_data_plane_DO8KbxCe();
124928
125053
  var require_tls$1 = require_tls_u8QCJCFE();
124929
- var require_manifest_python_deps = require_manifest_python_deps_CivtrAha();
125054
+ var require_manifest_python_deps = require_manifest_python_deps_BaVekjRY();
124930
125055
  var require_resource_monitor = require_resource_monitor_CdnzxBLP();
124931
125056
  var require_custom_action_registry = require_custom_action_registry_jY0NOZK8();
124932
125057
  var zod = require_zod();
@@ -207518,6 +207643,97 @@ var require_dist4 = __commonJS({
207518
207643
  }
207519
207644
  return [...buckets.values()].toSorted((a, b) => a.atMs - b.atMs);
207520
207645
  }
207646
+ var MAX_REASONS_PER_KEY = 16;
207647
+ var MAX_KEYS = 1024;
207648
+ var OVERFLOW_REASON = "other";
207649
+ function counterKey(deviceId, family, variant) {
207650
+ return variant === void 0 ? `${deviceId}\0${family}` : `${deviceId}\0${family}\0${variant}`;
207651
+ }
207652
+ var FailureCounters = class {
207653
+ maxKeys;
207654
+ maxReasons;
207655
+ counters = /* @__PURE__ */ new Map();
207656
+ refused = 0;
207657
+ constructor(maxKeys = MAX_KEYS, maxReasons = 16) {
207658
+ this.maxKeys = maxKeys;
207659
+ this.maxReasons = maxReasons;
207660
+ }
207661
+ /**
207662
+ * Counters refused because {@link MAX_KEYS} was already held.
207663
+ *
207664
+ * Cumulative for the life of the instance: a bound that bit is a fact about
207665
+ * the deployment, and a surface that hid it would under-report a fleet
207666
+ * precisely when the fleet got large enough to matter.
207667
+ */
207668
+ get keysRefused() {
207669
+ return this.refused;
207670
+ }
207671
+ /** Counters currently held. */
207672
+ get size() {
207673
+ return this.counters.size;
207674
+ }
207675
+ /**
207676
+ * Fold one observation in.
207677
+ *
207678
+ * A non-positive or non-integer `deviceId` is REFUSED rather than bucketed:
207679
+ * see the module docblock — an entry that cannot name its camera is worse
207680
+ * than no entry.
207681
+ */
207682
+ note(observation, nowMs) {
207683
+ if (!Number.isInteger(observation.deviceId) || observation.deviceId <= 0) return;
207684
+ const key = counterKey(observation.deviceId, observation.family, observation.variant);
207685
+ let counter = this.counters.get(key);
207686
+ if (counter === void 0) {
207687
+ if (this.counters.size >= this.maxKeys) {
207688
+ this.refused += 1;
207689
+ return;
207690
+ }
207691
+ counter = {
207692
+ deviceId: observation.deviceId,
207693
+ family: observation.family,
207694
+ variant: observation.variant,
207695
+ sinceMs: nowMs,
207696
+ attempts: 0,
207697
+ succeeded: 0,
207698
+ reasons: /* @__PURE__ */ new Map()
207699
+ };
207700
+ this.counters.set(key, counter);
207701
+ }
207702
+ counter.attempts += 1;
207703
+ if (observation.reason === void 0) {
207704
+ counter.succeeded += 1;
207705
+ return;
207706
+ }
207707
+ const reason = counter.reasons.has(observation.reason) || counter.reasons.size < this.maxReasons ? observation.reason : OVERFLOW_REASON;
207708
+ counter.reasons.set(reason, (counter.reasons.get(reason) ?? 0) + 1);
207709
+ }
207710
+ /** Read every counter. Never mutates — see the module docblock. */
207711
+ snapshot(nowMs) {
207712
+ const out = [];
207713
+ for (const counter of this.counters.values()) out.push({
207714
+ deviceId: counter.deviceId,
207715
+ family: counter.family,
207716
+ ...counter.variant !== void 0 ? { variant: counter.variant } : {},
207717
+ sinceMs: counter.sinceMs,
207718
+ atMs: nowMs,
207719
+ attempts: counter.attempts,
207720
+ succeeded: counter.succeeded,
207721
+ reasons: [...counter.reasons.entries()].map(([reason, count]) => ({
207722
+ reason,
207723
+ count
207724
+ })).toSorted((a, b) => b.count - a.count)
207725
+ });
207726
+ return out;
207727
+ }
207728
+ /** Drop everything (host disposal). */
207729
+ clear() {
207730
+ this.counters.clear();
207731
+ }
207732
+ };
207733
+ function failureRate(sample) {
207734
+ if (sample.attempts <= 0) return null;
207735
+ return (sample.attempts - sample.succeeded) / sample.attempts;
207736
+ }
207521
207737
  var FORMAT_KEYS = [
207522
207738
  "onnx",
207523
207739
  "coreml",
@@ -214146,6 +214362,80 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
214146
214362
  /** BIG PLAN 2: declarative mount hint — read by `@camstack/system` `buildCapRouters`. */
214147
214363
  mount: { kind: "skip" }
214148
214364
  };
214365
+ var FailureReasonCountSchema = zod.z.object({
214366
+ /**
214367
+ * Why the attempt did not land, in the contributor's own vocabulary —
214368
+ * `worker-lease-gone`, `queue-overflow`, `timeout`, `empty-read`. The same
214369
+ * strings that already appear in this repo's logs and, where one exists, the
214370
+ * same string the per-track `previewMissReason` records (D276): a second
214371
+ * vocabulary for the same loss would make the row and the counter
214372
+ * un-joinable.
214373
+ */
214374
+ reason: zod.z.string(),
214375
+ count: zod.z.number().int().nonnegative()
214376
+ });
214377
+ var FailureContributionSchema = zod.z.object({
214378
+ /**
214379
+ * The failing path — `enrichment-crop`, `inference`, `plate-ocr`,
214380
+ * `person-over-vehicle`. Free text, for the reason `load-contribution` keeps
214381
+ * `unit` free: the families are owned by different addons and a shared enum
214382
+ * is a central list that rots invisibly.
214383
+ */
214384
+ family: zod.z.string(),
214385
+ /**
214386
+ * The NUMERIC device id — the same value every log line carries as
214387
+ * `tags.deviceId`. Never nullable and never absent: a contributor that
214388
+ * cannot name the camera must not emit the entry, because a fleet total
214389
+ * cannot answer the only question anybody asks of this surface.
214390
+ */
214391
+ deviceId: zod.z.number().int().positive(),
214392
+ /**
214393
+ * A second dimension inside the family: the model / step id for an inference
214394
+ * timeout, so "which camera AND which model" is one read. Absent when the
214395
+ * family has a single variant.
214396
+ */
214397
+ variant: zod.z.string().optional(),
214398
+ /**
214399
+ * Epoch ms this counter started — the INCARNATION MARKER. A consumer
214400
+ * differencing two reads must drop the interval when it changes, because the
214401
+ * counter restarted from zero in a respawned runner. Same discipline as
214402
+ * `LoadContribution.startedAtMs`.
214403
+ */
214404
+ sinceMs: zod.z.number(),
214405
+ /** Epoch ms it was read. `atMs - sinceMs` is the interval this covers. */
214406
+ atMs: zod.z.number(),
214407
+ /**
214408
+ * THE DENOMINATOR — every attempt on this path for this camera in the
214409
+ * window. A failure count published without it is the mistake this schema
214410
+ * exists to make impossible.
214411
+ */
214412
+ attempts: zod.z.number().int().nonnegative(),
214413
+ /** Attempts that landed. `attempts - succeeded` is the loss. */
214414
+ succeeded: zod.z.number().int().nonnegative(),
214415
+ /** The loss, partitioned. Sums to `attempts - succeeded`. */
214416
+ reasons: zod.z.array(FailureReasonCountSchema).readonly()
214417
+ });
214418
+ var failureContributionCapability = {
214419
+ name: "failure-contribution",
214420
+ scope: "system",
214421
+ mode: "collection",
214422
+ internal: true,
214423
+ methods: {
214424
+ /**
214425
+ * This addon's per-camera failure counters, read live from bounded in-RAM
214426
+ * state it already keeps. Inert: no persistence, no sampling, no timer.
214427
+ *
214428
+ * READING NEVER RESETS. The counters are CUMULATIVE since `sinceMs`, and a
214429
+ * consumer that wants a rate differences two reads. A draining read would
214430
+ * make two operators with the page open each destroy half of the other's
214431
+ * numbers, and `load-contribution` already settled the same question the
214432
+ * same way for `cpuSeconds`.
214433
+ */
214434
+ list: require_sleep.method(zod.z.void(), zod.z.array(FailureContributionSchema).readonly())
214435
+ },
214436
+ /** In-process only — enumerated through `addons.listCapabilityProviders`. */
214437
+ mount: { kind: "skip" }
214438
+ };
214149
214439
  var LOAD_CONTRIBUTION_ROLES = [
214150
214440
  "decode",
214151
214441
  "transcode",
@@ -218937,6 +219227,20 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
218937
219227
  * `=== true` and render nothing otherwise — never infer "no rider".
218938
219228
  */
218939
219229
  hasRider: zod.z.boolean().optional(),
219230
+ /**
219231
+ * WHY this track ended without a NATIVE best-shot tile
219232
+ * ([D276](../decisions/adr-0276-a-stand-in-tile-is-provisional-and-a-close-says-why.md)) —
219233
+ * a composed token line (`no-key-frame capture=keyframe:native-missx4`,
219234
+ * `derive-returned-null tile=standin`, …) written at close and CLEARED by
219235
+ * the late-keyFrame upgrade when a native tile lands after all. The
219236
+ * operator-facing answer to "perché manca l'immagine?" on a track whose
219237
+ * tile is a face/plate stand-in, a raster crop, or an icon.
219238
+ *
219239
+ * **Absent ≠ "missed silently"**: a row written before the column, a hub
219240
+ * that predates the field, and every track whose tile landed native all
219241
+ * omit it. Render nothing when absent.
219242
+ */
219243
+ previewMissReason: zod.z.string().optional(),
218940
219244
  ...TrackFlagFields,
218941
219245
  ...TrackRetrainFields
218942
219246
  });
@@ -230711,6 +231015,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
230711
231015
  channels: zod.z.array(LogChannelWindowPatchSchema).readonly().optional()
230712
231016
  });
230713
231017
  var ReportedLoadContributionSchema = LoadContributionSchema.extend({ addonId: zod.z.string() });
231018
+ var ReportedFailureContributionSchema = FailureContributionSchema.extend({ addonId: zod.z.string() });
230714
231019
  var GetLoggingSettingsInputSchema = zod.z.object({
230715
231020
  scopeNodeId: zod.z.string().optional(),
230716
231021
  /**
@@ -230820,6 +231125,28 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
230820
231125
  */
230821
231126
  getLoadContributions: require_sleep.method(zod.z.void(), zod.z.array(ReportedLoadContributionSchema).readonly(), { auth: "admin" }),
230822
231127
  /**
231128
+ * Every `failure-contribution` an addon on this cluster reports — per
231129
+ * camera, per reason, **with the denominator attached**.
231130
+ *
231131
+ * This is the surface the operator asked for on 2026-08-28 (*"possiamo
231132
+ * armare questi errori intanto? Così al prossimo giro ricontrolliamo tutti
231133
+ * questi punti"*). Before it, four live failure modes could only be counted
231134
+ * by grepping Loki and hand-correlating timestamps, which is exactly how a
231135
+ * 22% thumbnail gap and a 3-hour media blackout were diagnosed — twice.
231136
+ *
231137
+ * Read it as a RATIO, never as a count. `attempts` is on every entry
231138
+ * because the count on its own lies: `enrichment crop native miss` read as
231139
+ * "35x worse than yesterday" and was flat across twelve hours once divided
231140
+ * by the successes on the same path.
231141
+ *
231142
+ * The counters are CUMULATIVE since each entry's `sinceMs`. Reading does
231143
+ * not reset them, and `sinceMs` changing means the reporting runner
231144
+ * respawned — a consumer differencing two reads drops that interval.
231145
+ *
231146
+ * Admin-only: the rows name cameras and the paths that fail on them.
231147
+ */
231148
+ getFailureContributions: require_sleep.method(zod.z.void(), zod.z.array(ReportedFailureContributionSchema).readonly(), { auth: "admin" }),
231149
+ /**
230823
231150
  * The logging settings document — levels and armed diagnostics — resolved
230824
231151
  * for `nodeId`, or for the cluster when `nodeId` is absent.
230825
231152
  *
@@ -234378,6 +234705,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
234378
234705
  eventEmitter: "event-emitter",
234379
234706
  events: "events",
234380
234707
  faceGallery: "face-gallery",
234708
+ failureContribution: "failure-contribution",
234381
234709
  fanControl: "fan-control",
234382
234710
  featureProbe: "feature-probe",
234383
234711
  filesystemBrowse: "filesystem-browse",
@@ -234702,6 +235030,10 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
234702
235030
  key: "faceGallery",
234703
235031
  name: "face-gallery"
234704
235032
  },
235033
+ {
235034
+ key: "failureContribution",
235035
+ name: "failure-contribution"
235036
+ },
234705
235037
  {
234706
235038
  key: "fanControl",
234707
235039
  name: "fan-control"
@@ -235137,6 +235469,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
235137
235469
  eventEmitterCapability,
235138
235470
  eventsCapability,
235139
235471
  faceGalleryCapability,
235472
+ failureContributionCapability,
235140
235473
  fanControlCapability,
235141
235474
  featureProbeCapability,
235142
235475
  filesystemBrowseCapability,
@@ -237141,6 +237474,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
237141
237474
  addonId: null,
237142
237475
  access: "create"
237143
237476
  },
237477
+ "failureContribution.list": {
237478
+ capName: "failure-contribution",
237479
+ capScope: "system",
237480
+ addonId: null,
237481
+ access: "view"
237482
+ },
237144
237483
  "fanControl.setDirection": {
237145
237484
  capName: "fan-control",
237146
237485
  capScope: "device",
@@ -240447,6 +240786,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
240447
240786
  addonId: null,
240448
240787
  access: "create"
240449
240788
  },
240789
+ "system.getFailureContributions": {
240790
+ capName: "system",
240791
+ capScope: "system",
240792
+ addonId: null,
240793
+ access: "view"
240794
+ },
240450
240795
  "system.getLoadContributions": {
240451
240796
  capName: "system",
240452
240797
  capScope: "system",
@@ -241136,6 +241481,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
241136
241481
  "embedding-encoder",
241137
241482
  "events",
241138
241483
  "face-gallery",
241484
+ "failure-contribution",
241139
241485
  "fan-control",
241140
241486
  "filesystem-browse",
241141
241487
  "humidifier",
@@ -241300,6 +241646,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
241300
241646
  "device-state",
241301
241647
  "embedding-encoder",
241302
241648
  "face-gallery",
241649
+ "failure-contribution",
241303
241650
  "filesystem-browse",
241304
241651
  "integrations",
241305
241652
  "llm",
@@ -244199,6 +244546,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
244199
244546
  detectSiteLocation: (input) => dispatch("system", "detectSiteLocation", "mutation", input),
244200
244547
  getRequestCensus: (input) => dispatch("system", "getRequestCensus", "query", input),
244201
244548
  getLoadContributions: (input) => dispatch("system", "getLoadContributions", "query", input),
244549
+ getFailureContributions: (input) => dispatch("system", "getFailureContributions", "query", input),
244202
244550
  getLoggingSettings: (input) => dispatch("system", "getLoggingSettings", "query", input),
244203
244551
  setLoggingSettings: (input) => dispatch("system", "setLoggingSettings", "mutation", input)
244204
244552
  },
@@ -247241,6 +247589,9 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
247241
247589
  exports.ExpressionSourceSchema = ExpressionSourceSchema;
247242
247590
  exports.FIRST_LEVEL_MACRO_CLASSES = FIRST_LEVEL_MACRO_CLASSES;
247243
247591
  exports.FULL_IMAGE_BBOX = FULL_IMAGE_BBOX;
247592
+ exports.FailureContributionSchema = FailureContributionSchema;
247593
+ exports.FailureCounters = FailureCounters;
247594
+ exports.FailureReasonCountSchema = FailureReasonCountSchema;
247244
247595
  exports.FanControlStatusSchema = FanControlStatusSchema;
247245
247596
  exports.FanDirectionSchema = FanDirectionSchema;
247246
247597
  exports.FeatureManifestSchema = FeatureManifestSchema;
@@ -247356,6 +247707,8 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
247356
247707
  exports.MAX_EXPRESSION_CALL_ARGS = MAX_EXPRESSION_CALL_ARGS;
247357
247708
  exports.MAX_EXPRESSION_EVAL_STEPS = MAX_EXPRESSION_EVAL_STEPS;
247358
247709
  exports.MAX_EXPRESSION_SOURCE_LENGTH = MAX_EXPRESSION_SOURCE_LENGTH;
247710
+ exports.MAX_KEYS = MAX_KEYS;
247711
+ exports.MAX_REASONS_PER_KEY = MAX_REASONS_PER_KEY;
247359
247712
  exports.MAX_SENSOR_TRIGGER_DEVICES = MAX_SENSOR_TRIGGER_DEVICES;
247360
247713
  exports.METHOD_ACCESS_MAP = METHOD_ACCESS_MAP;
247361
247714
  exports.METHOD_DEVICE_SELECTORS = METHOD_DEVICE_SELECTORS;
@@ -247526,6 +247879,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
247526
247879
  exports.OPERATOR_WRITTEN_STALE_MS = OPERATOR_WRITTEN_STALE_MS;
247527
247880
  exports.OPS_LOG_DEFAULT_LIMIT = OPS_LOG_DEFAULT_LIMIT;
247528
247881
  exports.OPS_LOG_RING_DEFAULT_MAX = OPS_LOG_RING_DEFAULT_MAX;
247882
+ exports.OVERFLOW_REASON = OVERFLOW_REASON;
247529
247883
  exports.OauthIntegrationDescriptorSchema = OauthIntegrationDescriptorSchema;
247530
247884
  exports.ObjectEventSchema = ObjectEventSchema;
247531
247885
  exports.OpsLogDomainSchema = OpsLogDomainSchema;
@@ -247647,6 +248001,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
247647
248001
  exports.RelocateMediaInputSchema = RelocateMediaInputSchema;
247648
248002
  exports.RenderedAsSchema = RenderedAsSchema;
247649
248003
  exports.ReportMotionInputSchema = ReportMotionInputSchema;
248004
+ exports.ReportedFailureContributionSchema = ReportedFailureContributionSchema;
247650
248005
  exports.ReportedLoadContributionSchema = ReportedLoadContributionSchema;
247651
248006
  exports.RequestCensusGroupSchema = RequestCensusGroupSchema;
247652
248007
  exports.RequestCensusProcedureSchema = RequestCensusProcedureSchema;
@@ -248045,6 +248400,8 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
248045
248400
  exports.extractNestedAddonId = extractNestedAddonId;
248046
248401
  exports.extractSourceInfoFromMetadata = extractSourceInfoFromMetadata;
248047
248402
  exports.faceGalleryCapability = faceGalleryCapability;
248403
+ exports.failureContributionCapability = failureContributionCapability;
248404
+ exports.failureRate = failureRate;
248048
248405
  exports.fanControlCapability = fanControlCapability;
248049
248406
  exports.featureProbeCapability = featureProbeCapability;
248050
248407
  exports.filesystemBrowseCapability = filesystemBrowseCapability;
@@ -405402,6 +405759,37 @@ var require_collection_preference = __commonJS({
405402
405759
  }
405403
405760
  });
405404
405761
 
405762
+ // ../../server/backend/dist/api/core/failure-contributions.js
405763
+ var require_failure_contributions = __commonJS({
405764
+ "../../server/backend/dist/api/core/failure-contributions.js"(exports) {
405765
+ "use strict";
405766
+ Object.defineProperty(exports, "__esModule", { value: true });
405767
+ exports.EMPTY_FAILURE_CONTRIBUTION_PLANE = void 0;
405768
+ exports.buildFailureContributionPlane = buildFailureContributionPlane;
405769
+ var types_1 = require_dist4();
405770
+ exports.EMPTY_FAILURE_CONTRIBUTION_PLANE = {
405771
+ contributions: async () => []
405772
+ };
405773
+ function buildFailureContributionPlane(source, onProviderError) {
405774
+ return {
405775
+ contributions: async () => {
405776
+ const out = [];
405777
+ for (const [addonId, provider] of source.entries()) {
405778
+ try {
405779
+ for (const entry of await provider.list()) {
405780
+ out.push({ ...entry, addonId });
405781
+ }
405782
+ } catch (err) {
405783
+ onProviderError?.(addonId, (0, types_1.errMsg)(err));
405784
+ }
405785
+ }
405786
+ return out;
405787
+ }
405788
+ };
405789
+ }
405790
+ }
405791
+ });
405792
+
405405
405793
  // ../../server/backend/dist/api/core/load-contributions.js
405406
405794
  var require_load_contributions = __commonJS({
405407
405795
  "../../server/backend/dist/api/core/load-contributions.js"(exports) {
@@ -406474,6 +406862,7 @@ var require_cap_providers = __commonJS({
406474
406862
  var agent_installed_packages_js_1 = require_agent_installed_packages();
406475
406863
  var http_request_census_singleton_js_1 = require_http_request_census_singleton();
406476
406864
  var collection_preference_js_1 = require_collection_preference();
406865
+ var failure_contributions_js_1 = require_failure_contributions();
406477
406866
  var load_contributions_js_1 = require_load_contributions();
406478
406867
  var logging_settings_js_1 = require_logging_settings();
406479
406868
  var request_census_settings_js_1 = require_request_census_settings();
@@ -406495,6 +406884,9 @@ var require_cap_providers = __commonJS({
406495
406884
  const loadContributions = (0, load_contributions_js_1.buildLoadContributionPlane)({ entries: () => registry?.getCollectionEntries("load-contribution") ?? [] }, (addonId, error) => {
406496
406885
  logger?.warn("load-contribution provider unreachable", { meta: { addonId, error } });
406497
406886
  });
406887
+ const failureContributions = (0, failure_contributions_js_1.buildFailureContributionPlane)({ entries: () => registry?.getCollectionEntries("failure-contribution") ?? [] }, (addonId, error) => {
406888
+ logger?.warn("failure-contribution provider unreachable", { meta: { addonId, error } });
406889
+ });
406498
406890
  const loggingSettings = new logging_settings_js_1.LoggingSettingsService({
406499
406891
  store,
406500
406892
  gate: (0, system_1.getLoggingGate)(),
@@ -406522,6 +406914,7 @@ var require_cap_providers = __commonJS({
406522
406914
  return result;
406523
406915
  },
406524
406916
  getLoadContributions: async () => loadContributions.contributions(),
406917
+ getFailureContributions: async () => failureContributions.contributions(),
406525
406918
  getRetentionConfig: async () => getRetention(registry)?.getConfig() ?? null,
406526
406919
  setRetentionConfig: async (input) => {
406527
406920
  getRetention(registry)?.setConfig(input);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "camstack",
3
- "version": "1.2.53",
3
+ "version": "1.2.54",
4
4
  "description": "CLI tool for managing and running CamStack server",
5
5
  "keywords": [
6
6
  "camstack",