@camstack/addon-mqtt-broker 1.2.38 → 1.2.41

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.
@@ -13281,6 +13281,114 @@ method(LogEntrySchema, _void(), { kind: "mutation" }), method(object({
13281
13281
  limit: number().optional(),
13282
13282
  tags: record(string(), string()).optional()
13283
13283
  }), array(LogEntrySchema).readonly());
13284
+ /**
13285
+ * `failure-contribution` — the capability an addon reports its OWN losses
13286
+ * through, per camera, with the denominator attached. It stores nothing.
13287
+ *
13288
+ * ## The twin of `load-contribution`, and why it is a twin and not a field
13289
+ *
13290
+ * `load-contribution` answers *what did this camera COST*. This answers *what
13291
+ * did this camera LOSE*. The reporting discipline is identical and deliberately
13292
+ * copied: the contributor reports what it already knows, hub-main adds only
13293
+ * `addonId`, nothing needs global knowledge, and there is no central list for
13294
+ * somebody to forget to edit.
13295
+ *
13296
+ * They are not merged, because their invariants are opposites:
13297
+ *
13298
+ * - a `load-contribution` measurement is **absent, never zero** — a zero would
13299
+ * claim a camera cost nothing, which is a measurement nobody made;
13300
+ * - a `failure-contribution` zero is the **most valuable value on the
13301
+ * surface** — `attempts: 400, succeeded: 400` is the proof a fix landed,
13302
+ * and it is exactly what an absent entry cannot say.
13303
+ *
13304
+ * Putting a loss counter on a cost entry would also break the reconciliation
13305
+ * that gives `load-contribution` its point: contributions are subtracted from
13306
+ * `metrics.node-processes-snapshot` to find processes nobody claims. A failure
13307
+ * has no process.
13308
+ *
13309
+ * ## Why not a log line, since the counters already exist
13310
+ *
13311
+ * Several of these paths already counted themselves — `CaptureScheduler`'s
13312
+ * per-device window, `KeyFrameCaptureLog`, `bumpCropMetric`. Every one of them
13313
+ * ends in a log line, and a log line is the thing the operator asked to stop
13314
+ * needing: *"possiamo armare questi errori intanto? Così al prossimo giro
13315
+ * ricontrolliamo tutti questi punti"*. Reading them meant grepping Loki and
13316
+ * hand-correlating timestamps, which is how a 22% thumbnail gap and a 3-hour
13317
+ * media blackout were both diagnosed. The counters stay; this is where they can
13318
+ * be READ.
13319
+ *
13320
+ * ## The rate is served with its denominator or not at all
13321
+ *
13322
+ * Every entry carries `attempts` and `succeeded`. A miss count alone is
13323
+ * unreadable: on 2026-08-28 the enrichment-crop miss count read as "35x worse
13324
+ * than yesterday" and was **flat across twelve hours** once divided by the
13325
+ * successes on the same path. A surface that publishes only the numerator
13326
+ * reproduces that mistake on every read.
13327
+ *
13328
+ * ## Shape
13329
+ *
13330
+ * Copied from `load-contribution.cap.ts` (`mode: 'collection'`,
13331
+ * `internal: true`, `mount: { kind: 'skip' }`): no tRPC route of its own and no
13332
+ * generated hooks, while `addons.listCapabilityProviders` still enumerates it
13333
+ * and the hub's `CapabilityRegistry` still holds an RPC proxy per provider — so
13334
+ * a forked runner's entries reach hub-main over transport that already exists.
13335
+ * No new UDS message, no second registry (D3). The operator reads the assembled
13336
+ * result through `system.getFailureContributions`.
13337
+ */
13338
+ var FailureReasonCountSchema = object({
13339
+ /**
13340
+ * Why the attempt did not land, in the contributor's own vocabulary —
13341
+ * `worker-lease-gone`, `queue-overflow`, `timeout`, `empty-read`. The same
13342
+ * strings that already appear in this repo's logs and, where one exists, the
13343
+ * same string the per-track `previewMissReason` records (D276): a second
13344
+ * vocabulary for the same loss would make the row and the counter
13345
+ * un-joinable.
13346
+ */
13347
+ reason: string(),
13348
+ count: number().int().nonnegative()
13349
+ });
13350
+ var FailureContributionSchema = object({
13351
+ /**
13352
+ * The failing path — `enrichment-crop`, `inference`, `plate-ocr`,
13353
+ * `person-over-vehicle`. Free text, for the reason `load-contribution` keeps
13354
+ * `unit` free: the families are owned by different addons and a shared enum
13355
+ * is a central list that rots invisibly.
13356
+ */
13357
+ family: string(),
13358
+ /**
13359
+ * The NUMERIC device id — the same value every log line carries as
13360
+ * `tags.deviceId`. Never nullable and never absent: a contributor that
13361
+ * cannot name the camera must not emit the entry, because a fleet total
13362
+ * cannot answer the only question anybody asks of this surface.
13363
+ */
13364
+ deviceId: number().int().positive(),
13365
+ /**
13366
+ * A second dimension inside the family: the model / step id for an inference
13367
+ * timeout, so "which camera AND which model" is one read. Absent when the
13368
+ * family has a single variant.
13369
+ */
13370
+ variant: string().optional(),
13371
+ /**
13372
+ * Epoch ms this counter started — the INCARNATION MARKER. A consumer
13373
+ * differencing two reads must drop the interval when it changes, because the
13374
+ * counter restarted from zero in a respawned runner. Same discipline as
13375
+ * `LoadContribution.startedAtMs`.
13376
+ */
13377
+ sinceMs: number(),
13378
+ /** Epoch ms it was read. `atMs - sinceMs` is the interval this covers. */
13379
+ atMs: number(),
13380
+ /**
13381
+ * THE DENOMINATOR — every attempt on this path for this camera in the
13382
+ * window. A failure count published without it is the mistake this schema
13383
+ * exists to make impossible.
13384
+ */
13385
+ attempts: number().int().nonnegative(),
13386
+ /** Attempts that landed. `attempts - succeeded` is the loss. */
13387
+ succeeded: number().int().nonnegative(),
13388
+ /** The loss, partitioned. Sums to `attempts - succeeded`. */
13389
+ reasons: array(FailureReasonCountSchema).readonly()
13390
+ });
13391
+ method(_void(), array(FailureContributionSchema).readonly());
13284
13392
  var LoadContributionSchema = object({
13285
13393
  role: _enum([
13286
13394
  "decode",
@@ -13588,6 +13696,50 @@ var NodeProcessSchema = object({
13588
13696
  /** Wall-clock uptime (seconds). Parsed from `ps etime`. */
13589
13697
  uptimeSec: number()
13590
13698
  });
13699
+ /**
13700
+ * One retained container-memory reading.
13701
+ *
13702
+ * `atMs` is the timestamp of the PROCESS snapshot taken in the same tick, not
13703
+ * a second clock: that is what makes "processes sum to X, container says Y"
13704
+ * subtractable per point rather than an eyeballed comparison of two series
13705
+ * sampled at different instants.
13706
+ *
13707
+ * A reduced window keeps the sample with the LARGEST `currentBytes` in each
13708
+ * bucket, WHOLE. Taking a per-field maximum would synthesise a row whose parts
13709
+ * never coexisted, and a mean would smear away the peak this exists to find.
13710
+ */
13711
+ var ContainerMemoryPointSchema = object({
13712
+ /** Which hierarchy answered, so a reading is never ambiguous. */
13713
+ source: _enum(["cgroup-v2", "cgroup-v1"]),
13714
+ /** `memory.current` (v2) / `memory.usage_in_bytes` (v1). Always known. */
13715
+ currentBytes: number(),
13716
+ /** The cgroup's ceiling. `null` = NO LIMIT — never a sentinel, never zero. */
13717
+ limitBytes: number().nullable(),
13718
+ /** Anonymous pages: the closest thing to "what the processes allocated". */
13719
+ anonBytes: number().nullable(),
13720
+ /** Page cache. Charged to the cgroup, owned by no process. */
13721
+ fileBytes: number().nullable(),
13722
+ /**
13723
+ * Shared memory — and the field that explained the largest single surprise.
13724
+ * The i915 driver backs GPU buffers with shmem, so an inference pool or a
13725
+ * hardware-decode session holding DRM objects is charged HERE and appears
13726
+ * nowhere in a `ps` scan.
13727
+ */
13728
+ shmemBytes: number().nullable(),
13729
+ /** Kernel slab charged to this cgroup. `null` on v1, which never publishes it. */
13730
+ slabBytes: number().nullable(),
13731
+ /**
13732
+ * Shrinkable i915 GEM object bytes, from debugfs.
13733
+ *
13734
+ * **Host-wide across every DRM client, NOT cgroup-scoped.** It is not a
13735
+ * component of `currentBytes` and must not be subtracted from it; it says
13736
+ * what put the shmem there, where `shmemBytes` only says how much.
13737
+ *
13738
+ * `null` wherever debugfs is not mounted — which is inside every camstack
13739
+ * container today — and on any node with no Intel GPU.
13740
+ */
13741
+ gpuShmemBytes: number().nullable()
13742
+ }).extend({ atMs: number() });
13591
13743
  var DumpHeapSnapshotInputSchema = object({
13592
13744
  /** The addon whose runner should dump a heap snapshot. */
13593
13745
  addonId: string() });
@@ -13651,6 +13803,21 @@ var NodeLoadSeriesSchema = object({
13651
13803
  /** One entry per function seen in the window, heaviest-first. */
13652
13804
  series: array(LoadFunctionSeriesSchema).readonly(),
13653
13805
  /**
13806
+ * The CONTAINER's memory over the same window, oldest-first.
13807
+ *
13808
+ * Sits next to `series` rather than in a method of its own because the whole
13809
+ * question is a subtraction: the per-process rows in `series` sum to one
13810
+ * number and this one is another, and an operator who has to issue two calls
13811
+ * to compare them will compare two different instants. Same reader, same
13812
+ * `sinceMs`, same `bucketMs`, same timestamps.
13813
+ *
13814
+ * **EMPTY means ABSENT, never zero.** A node with no cgroup — a developer
13815
+ * Mac, a bare-metal host, a container with the hierarchy hidden — reports no
13816
+ * points at all. A zero here would be indistinguishable from a healthy
13817
+ * container and is precisely the lie this field exists to avoid.
13818
+ */
13819
+ containerMemory: array(ContainerMemoryPointSchema).readonly(),
13820
+ /**
13654
13821
  * Width of one returned bucket, in ms. Equals the sampling cadence when no
13655
13822
  * reduction was needed — so a caller can always say what one point covers
13656
13823
  * without having to know whether it was reduced.
@@ -17812,6 +17979,20 @@ var TrackSchema = object({
17812
17979
  * `=== true` and render nothing otherwise — never infer "no rider".
17813
17980
  */
17814
17981
  hasRider: boolean().optional(),
17982
+ /**
17983
+ * WHY this track ended without a NATIVE best-shot tile
17984
+ * ([D276](../decisions/adr-0276-a-stand-in-tile-is-provisional-and-a-close-says-why.md)) —
17985
+ * a composed token line (`no-key-frame capture=keyframe:native-missx4`,
17986
+ * `derive-returned-null tile=standin`, …) written at close and CLEARED by
17987
+ * the late-keyFrame upgrade when a native tile lands after all. The
17988
+ * operator-facing answer to "perché manca l'immagine?" on a track whose
17989
+ * tile is a face/plate stand-in, a raster crop, or an icon.
17990
+ *
17991
+ * **Absent ≠ "missed silently"**: a row written before the column, a hub
17992
+ * that predates the field, and every track whose tile landed native all
17993
+ * omit it. Render nothing when absent.
17994
+ */
17995
+ previewMissReason: string().optional(),
17815
17996
  ...TrackFlagFields,
17816
17997
  ...TrackRetrainFields
17817
17998
  });
@@ -25585,10 +25766,10 @@ DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceI
25585
25766
  * recording config. NOTE on events (source of truth, R5/C3): this cap carries
25586
25767
  * NO event surface — `getPlaybackManifest` returns playlist URLs only. Timeline
25587
25768
  * events (motion/object/audio) come from `pipelineAnalytics` (durable SQLite
25588
- * rows); the recorder's internal EventMap markers are ephemeral in-RAM
25589
- * annotations that are not exposed here and must not be treated as an event
25590
- * feed. Event<->footage joins are by time, padded with the shared `EVENT_PAD_MS`
25591
- * (`interfaces/recording-config.ts`).
25769
+ * rows) and are the ONLY event surface — the recorder has none. The in-RAM
25770
+ * playback markers it used to build were deleted on 2026-08-29 because nothing
25771
+ * ever read them. Event<->footage joins are by time, padded with the shared
25772
+ * `EVENT_PAD_MS` (`interfaces/recording-config.ts`).
25592
25773
  */
25593
25774
  var RecordingStatusSchema = object({
25594
25775
  deviceId: number(),
@@ -27038,6 +27219,13 @@ var LoggingSettingsPatchSchema = object({
27038
27219
  * anyone but its owner.
27039
27220
  */
27040
27221
  var ReportedLoadContributionSchema = LoadContributionSchema.extend({ addonId: string() });
27222
+ /**
27223
+ * One per-camera failure counter, plus WHO reported it.
27224
+ *
27225
+ * Same rule as {@link ReportedLoadContributionSchema}: `addonId` is stamped by
27226
+ * the hub as it enumerates providers, never by the contributor.
27227
+ */
27228
+ var ReportedFailureContributionSchema = FailureContributionSchema.extend({ addonId: string() });
27041
27229
  var GetLoggingSettingsInputSchema = object({
27042
27230
  scopeNodeId: string().optional(),
27043
27231
  /**
@@ -27096,7 +27284,7 @@ method(_void(), FeatureManifestSchema), method(_void(), HealthStatusSchema), met
27096
27284
  }), method(_void(), SiteLocationStatusSchema, {
27097
27285
  kind: "mutation",
27098
27286
  auth: "admin"
27099
- }), method(_void(), RequestCensusStatusSchema, { auth: "admin" }), method(_void(), array(ReportedLoadContributionSchema).readonly(), { auth: "admin" }), method(GetLoggingSettingsInputSchema, LoggingSettingsStateSchema, { auth: "admin" }), method(SetLoggingSettingsInputSchema, LoggingSettingsStateSchema, {
27287
+ }), method(_void(), RequestCensusStatusSchema, { auth: "admin" }), method(_void(), array(ReportedLoadContributionSchema).readonly(), { auth: "admin" }), method(_void(), array(ReportedFailureContributionSchema).readonly(), { auth: "admin" }), method(GetLoggingSettingsInputSchema, LoggingSettingsStateSchema, { auth: "admin" }), method(SetLoggingSettingsInputSchema, LoggingSettingsStateSchema, {
27100
27288
  kind: "mutation",
27101
27289
  auth: "admin"
27102
27290
  });
@@ -29678,6 +29866,12 @@ Object.freeze({
29678
29866
  addonId: null,
29679
29867
  access: "create"
29680
29868
  },
29869
+ "failureContribution.list": {
29870
+ capName: "failure-contribution",
29871
+ capScope: "system",
29872
+ addonId: null,
29873
+ access: "view"
29874
+ },
29681
29875
  "fanControl.setDirection": {
29682
29876
  capName: "fan-control",
29683
29877
  capScope: "device",
@@ -32984,6 +33178,12 @@ Object.freeze({
32984
33178
  addonId: null,
32985
33179
  access: "create"
32986
33180
  },
33181
+ "system.getFailureContributions": {
33182
+ capName: "system",
33183
+ capScope: "system",
33184
+ addonId: null,
33185
+ access: "view"
33186
+ },
32987
33187
  "system.getLoadContributions": {
32988
33188
  capName: "system",
32989
33189
  capScope: "system",
@@ -13276,6 +13276,114 @@ method(LogEntrySchema, _void(), { kind: "mutation" }), method(object({
13276
13276
  limit: number().optional(),
13277
13277
  tags: record(string(), string()).optional()
13278
13278
  }), array(LogEntrySchema).readonly());
13279
+ /**
13280
+ * `failure-contribution` — the capability an addon reports its OWN losses
13281
+ * through, per camera, with the denominator attached. It stores nothing.
13282
+ *
13283
+ * ## The twin of `load-contribution`, and why it is a twin and not a field
13284
+ *
13285
+ * `load-contribution` answers *what did this camera COST*. This answers *what
13286
+ * did this camera LOSE*. The reporting discipline is identical and deliberately
13287
+ * copied: the contributor reports what it already knows, hub-main adds only
13288
+ * `addonId`, nothing needs global knowledge, and there is no central list for
13289
+ * somebody to forget to edit.
13290
+ *
13291
+ * They are not merged, because their invariants are opposites:
13292
+ *
13293
+ * - a `load-contribution` measurement is **absent, never zero** — a zero would
13294
+ * claim a camera cost nothing, which is a measurement nobody made;
13295
+ * - a `failure-contribution` zero is the **most valuable value on the
13296
+ * surface** — `attempts: 400, succeeded: 400` is the proof a fix landed,
13297
+ * and it is exactly what an absent entry cannot say.
13298
+ *
13299
+ * Putting a loss counter on a cost entry would also break the reconciliation
13300
+ * that gives `load-contribution` its point: contributions are subtracted from
13301
+ * `metrics.node-processes-snapshot` to find processes nobody claims. A failure
13302
+ * has no process.
13303
+ *
13304
+ * ## Why not a log line, since the counters already exist
13305
+ *
13306
+ * Several of these paths already counted themselves — `CaptureScheduler`'s
13307
+ * per-device window, `KeyFrameCaptureLog`, `bumpCropMetric`. Every one of them
13308
+ * ends in a log line, and a log line is the thing the operator asked to stop
13309
+ * needing: *"possiamo armare questi errori intanto? Così al prossimo giro
13310
+ * ricontrolliamo tutti questi punti"*. Reading them meant grepping Loki and
13311
+ * hand-correlating timestamps, which is how a 22% thumbnail gap and a 3-hour
13312
+ * media blackout were both diagnosed. The counters stay; this is where they can
13313
+ * be READ.
13314
+ *
13315
+ * ## The rate is served with its denominator or not at all
13316
+ *
13317
+ * Every entry carries `attempts` and `succeeded`. A miss count alone is
13318
+ * unreadable: on 2026-08-28 the enrichment-crop miss count read as "35x worse
13319
+ * than yesterday" and was **flat across twelve hours** once divided by the
13320
+ * successes on the same path. A surface that publishes only the numerator
13321
+ * reproduces that mistake on every read.
13322
+ *
13323
+ * ## Shape
13324
+ *
13325
+ * Copied from `load-contribution.cap.ts` (`mode: 'collection'`,
13326
+ * `internal: true`, `mount: { kind: 'skip' }`): no tRPC route of its own and no
13327
+ * generated hooks, while `addons.listCapabilityProviders` still enumerates it
13328
+ * and the hub's `CapabilityRegistry` still holds an RPC proxy per provider — so
13329
+ * a forked runner's entries reach hub-main over transport that already exists.
13330
+ * No new UDS message, no second registry (D3). The operator reads the assembled
13331
+ * result through `system.getFailureContributions`.
13332
+ */
13333
+ var FailureReasonCountSchema = object({
13334
+ /**
13335
+ * Why the attempt did not land, in the contributor's own vocabulary —
13336
+ * `worker-lease-gone`, `queue-overflow`, `timeout`, `empty-read`. The same
13337
+ * strings that already appear in this repo's logs and, where one exists, the
13338
+ * same string the per-track `previewMissReason` records (D276): a second
13339
+ * vocabulary for the same loss would make the row and the counter
13340
+ * un-joinable.
13341
+ */
13342
+ reason: string(),
13343
+ count: number().int().nonnegative()
13344
+ });
13345
+ var FailureContributionSchema = object({
13346
+ /**
13347
+ * The failing path — `enrichment-crop`, `inference`, `plate-ocr`,
13348
+ * `person-over-vehicle`. Free text, for the reason `load-contribution` keeps
13349
+ * `unit` free: the families are owned by different addons and a shared enum
13350
+ * is a central list that rots invisibly.
13351
+ */
13352
+ family: string(),
13353
+ /**
13354
+ * The NUMERIC device id — the same value every log line carries as
13355
+ * `tags.deviceId`. Never nullable and never absent: a contributor that
13356
+ * cannot name the camera must not emit the entry, because a fleet total
13357
+ * cannot answer the only question anybody asks of this surface.
13358
+ */
13359
+ deviceId: number().int().positive(),
13360
+ /**
13361
+ * A second dimension inside the family: the model / step id for an inference
13362
+ * timeout, so "which camera AND which model" is one read. Absent when the
13363
+ * family has a single variant.
13364
+ */
13365
+ variant: string().optional(),
13366
+ /**
13367
+ * Epoch ms this counter started — the INCARNATION MARKER. A consumer
13368
+ * differencing two reads must drop the interval when it changes, because the
13369
+ * counter restarted from zero in a respawned runner. Same discipline as
13370
+ * `LoadContribution.startedAtMs`.
13371
+ */
13372
+ sinceMs: number(),
13373
+ /** Epoch ms it was read. `atMs - sinceMs` is the interval this covers. */
13374
+ atMs: number(),
13375
+ /**
13376
+ * THE DENOMINATOR — every attempt on this path for this camera in the
13377
+ * window. A failure count published without it is the mistake this schema
13378
+ * exists to make impossible.
13379
+ */
13380
+ attempts: number().int().nonnegative(),
13381
+ /** Attempts that landed. `attempts - succeeded` is the loss. */
13382
+ succeeded: number().int().nonnegative(),
13383
+ /** The loss, partitioned. Sums to `attempts - succeeded`. */
13384
+ reasons: array(FailureReasonCountSchema).readonly()
13385
+ });
13386
+ method(_void(), array(FailureContributionSchema).readonly());
13279
13387
  var LoadContributionSchema = object({
13280
13388
  role: _enum([
13281
13389
  "decode",
@@ -13583,6 +13691,50 @@ var NodeProcessSchema = object({
13583
13691
  /** Wall-clock uptime (seconds). Parsed from `ps etime`. */
13584
13692
  uptimeSec: number()
13585
13693
  });
13694
+ /**
13695
+ * One retained container-memory reading.
13696
+ *
13697
+ * `atMs` is the timestamp of the PROCESS snapshot taken in the same tick, not
13698
+ * a second clock: that is what makes "processes sum to X, container says Y"
13699
+ * subtractable per point rather than an eyeballed comparison of two series
13700
+ * sampled at different instants.
13701
+ *
13702
+ * A reduced window keeps the sample with the LARGEST `currentBytes` in each
13703
+ * bucket, WHOLE. Taking a per-field maximum would synthesise a row whose parts
13704
+ * never coexisted, and a mean would smear away the peak this exists to find.
13705
+ */
13706
+ var ContainerMemoryPointSchema = object({
13707
+ /** Which hierarchy answered, so a reading is never ambiguous. */
13708
+ source: _enum(["cgroup-v2", "cgroup-v1"]),
13709
+ /** `memory.current` (v2) / `memory.usage_in_bytes` (v1). Always known. */
13710
+ currentBytes: number(),
13711
+ /** The cgroup's ceiling. `null` = NO LIMIT — never a sentinel, never zero. */
13712
+ limitBytes: number().nullable(),
13713
+ /** Anonymous pages: the closest thing to "what the processes allocated". */
13714
+ anonBytes: number().nullable(),
13715
+ /** Page cache. Charged to the cgroup, owned by no process. */
13716
+ fileBytes: number().nullable(),
13717
+ /**
13718
+ * Shared memory — and the field that explained the largest single surprise.
13719
+ * The i915 driver backs GPU buffers with shmem, so an inference pool or a
13720
+ * hardware-decode session holding DRM objects is charged HERE and appears
13721
+ * nowhere in a `ps` scan.
13722
+ */
13723
+ shmemBytes: number().nullable(),
13724
+ /** Kernel slab charged to this cgroup. `null` on v1, which never publishes it. */
13725
+ slabBytes: number().nullable(),
13726
+ /**
13727
+ * Shrinkable i915 GEM object bytes, from debugfs.
13728
+ *
13729
+ * **Host-wide across every DRM client, NOT cgroup-scoped.** It is not a
13730
+ * component of `currentBytes` and must not be subtracted from it; it says
13731
+ * what put the shmem there, where `shmemBytes` only says how much.
13732
+ *
13733
+ * `null` wherever debugfs is not mounted — which is inside every camstack
13734
+ * container today — and on any node with no Intel GPU.
13735
+ */
13736
+ gpuShmemBytes: number().nullable()
13737
+ }).extend({ atMs: number() });
13586
13738
  var DumpHeapSnapshotInputSchema = object({
13587
13739
  /** The addon whose runner should dump a heap snapshot. */
13588
13740
  addonId: string() });
@@ -13646,6 +13798,21 @@ var NodeLoadSeriesSchema = object({
13646
13798
  /** One entry per function seen in the window, heaviest-first. */
13647
13799
  series: array(LoadFunctionSeriesSchema).readonly(),
13648
13800
  /**
13801
+ * The CONTAINER's memory over the same window, oldest-first.
13802
+ *
13803
+ * Sits next to `series` rather than in a method of its own because the whole
13804
+ * question is a subtraction: the per-process rows in `series` sum to one
13805
+ * number and this one is another, and an operator who has to issue two calls
13806
+ * to compare them will compare two different instants. Same reader, same
13807
+ * `sinceMs`, same `bucketMs`, same timestamps.
13808
+ *
13809
+ * **EMPTY means ABSENT, never zero.** A node with no cgroup — a developer
13810
+ * Mac, a bare-metal host, a container with the hierarchy hidden — reports no
13811
+ * points at all. A zero here would be indistinguishable from a healthy
13812
+ * container and is precisely the lie this field exists to avoid.
13813
+ */
13814
+ containerMemory: array(ContainerMemoryPointSchema).readonly(),
13815
+ /**
13649
13816
  * Width of one returned bucket, in ms. Equals the sampling cadence when no
13650
13817
  * reduction was needed — so a caller can always say what one point covers
13651
13818
  * without having to know whether it was reduced.
@@ -17807,6 +17974,20 @@ var TrackSchema = object({
17807
17974
  * `=== true` and render nothing otherwise — never infer "no rider".
17808
17975
  */
17809
17976
  hasRider: boolean().optional(),
17977
+ /**
17978
+ * WHY this track ended without a NATIVE best-shot tile
17979
+ * ([D276](../decisions/adr-0276-a-stand-in-tile-is-provisional-and-a-close-says-why.md)) —
17980
+ * a composed token line (`no-key-frame capture=keyframe:native-missx4`,
17981
+ * `derive-returned-null tile=standin`, …) written at close and CLEARED by
17982
+ * the late-keyFrame upgrade when a native tile lands after all. The
17983
+ * operator-facing answer to "perché manca l'immagine?" on a track whose
17984
+ * tile is a face/plate stand-in, a raster crop, or an icon.
17985
+ *
17986
+ * **Absent ≠ "missed silently"**: a row written before the column, a hub
17987
+ * that predates the field, and every track whose tile landed native all
17988
+ * omit it. Render nothing when absent.
17989
+ */
17990
+ previewMissReason: string().optional(),
17810
17991
  ...TrackFlagFields,
17811
17992
  ...TrackRetrainFields
17812
17993
  });
@@ -25580,10 +25761,10 @@ DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceI
25580
25761
  * recording config. NOTE on events (source of truth, R5/C3): this cap carries
25581
25762
  * NO event surface — `getPlaybackManifest` returns playlist URLs only. Timeline
25582
25763
  * events (motion/object/audio) come from `pipelineAnalytics` (durable SQLite
25583
- * rows); the recorder's internal EventMap markers are ephemeral in-RAM
25584
- * annotations that are not exposed here and must not be treated as an event
25585
- * feed. Event<->footage joins are by time, padded with the shared `EVENT_PAD_MS`
25586
- * (`interfaces/recording-config.ts`).
25764
+ * rows) and are the ONLY event surface — the recorder has none. The in-RAM
25765
+ * playback markers it used to build were deleted on 2026-08-29 because nothing
25766
+ * ever read them. Event<->footage joins are by time, padded with the shared
25767
+ * `EVENT_PAD_MS` (`interfaces/recording-config.ts`).
25587
25768
  */
25588
25769
  var RecordingStatusSchema = object({
25589
25770
  deviceId: number(),
@@ -27033,6 +27214,13 @@ var LoggingSettingsPatchSchema = object({
27033
27214
  * anyone but its owner.
27034
27215
  */
27035
27216
  var ReportedLoadContributionSchema = LoadContributionSchema.extend({ addonId: string() });
27217
+ /**
27218
+ * One per-camera failure counter, plus WHO reported it.
27219
+ *
27220
+ * Same rule as {@link ReportedLoadContributionSchema}: `addonId` is stamped by
27221
+ * the hub as it enumerates providers, never by the contributor.
27222
+ */
27223
+ var ReportedFailureContributionSchema = FailureContributionSchema.extend({ addonId: string() });
27036
27224
  var GetLoggingSettingsInputSchema = object({
27037
27225
  scopeNodeId: string().optional(),
27038
27226
  /**
@@ -27091,7 +27279,7 @@ method(_void(), FeatureManifestSchema), method(_void(), HealthStatusSchema), met
27091
27279
  }), method(_void(), SiteLocationStatusSchema, {
27092
27280
  kind: "mutation",
27093
27281
  auth: "admin"
27094
- }), method(_void(), RequestCensusStatusSchema, { auth: "admin" }), method(_void(), array(ReportedLoadContributionSchema).readonly(), { auth: "admin" }), method(GetLoggingSettingsInputSchema, LoggingSettingsStateSchema, { auth: "admin" }), method(SetLoggingSettingsInputSchema, LoggingSettingsStateSchema, {
27282
+ }), method(_void(), RequestCensusStatusSchema, { auth: "admin" }), method(_void(), array(ReportedLoadContributionSchema).readonly(), { auth: "admin" }), method(_void(), array(ReportedFailureContributionSchema).readonly(), { auth: "admin" }), method(GetLoggingSettingsInputSchema, LoggingSettingsStateSchema, { auth: "admin" }), method(SetLoggingSettingsInputSchema, LoggingSettingsStateSchema, {
27095
27283
  kind: "mutation",
27096
27284
  auth: "admin"
27097
27285
  });
@@ -29673,6 +29861,12 @@ Object.freeze({
29673
29861
  addonId: null,
29674
29862
  access: "create"
29675
29863
  },
29864
+ "failureContribution.list": {
29865
+ capName: "failure-contribution",
29866
+ capScope: "system",
29867
+ addonId: null,
29868
+ access: "view"
29869
+ },
29676
29870
  "fanControl.setDirection": {
29677
29871
  capName: "fan-control",
29678
29872
  capScope: "device",
@@ -32979,6 +33173,12 @@ Object.freeze({
32979
33173
  addonId: null,
32980
33174
  access: "create"
32981
33175
  },
33176
+ "system.getFailureContributions": {
33177
+ capName: "system",
33178
+ capScope: "system",
33179
+ addonId: null,
33180
+ access: "view"
33181
+ },
32982
33182
  "system.getLoadContributions": {
32983
33183
  capName: "system",
32984
33184
  capScope: "system",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-mqtt-broker",
3
- "version": "1.2.38",
3
+ "version": "1.2.41",
4
4
  "description": "MQTT broker registry addon for CamStack — manages external broker entries + an optional embedded aedes broker. Consumers spin up their own `mqtt.js` clients via the `mqtt-broker` cap.",
5
5
  "keywords": [
6
6
  "camstack",