@camstack/addon-provider-rademacher 0.2.34 → 0.2.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/addon.js +255 -25
  2. package/dist/addon.mjs +255 -25
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -984,7 +984,7 @@ var Rademacher = class {
984
984
  }
985
985
  };
986
986
  //#endregion
987
- //#region ../types/dist/event-category-CIa_iT6b.mjs
987
+ //#region ../types/dist/event-category-BZL-fdNj.mjs
988
988
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
989
989
  EventCategory["SystemBoot"] = "system.boot";
990
990
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -1421,7 +1421,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
1421
1421
  EventCategory["MetricsNodeResourcesSnapshot"] = "metrics.node-resources-snapshot";
1422
1422
  /**
1423
1423
  * Periodic per-node process-tree snapshot (camstack-related pids
1424
- * with ghost / managed / root classification). Emitted ~0.2 Hz by
1424
+ * with root / managed / system classification). Emitted ~0.2 Hz by
1425
1425
  * the metrics-provider addon. Drives the Cluster → Processes tab
1426
1426
  * without polling `metricsProvider.listNodeProcesses`.
1427
1427
  */
@@ -12213,6 +12213,19 @@ var SettingsRecordSchema = object({
12213
12213
  data: record(string(), unknown())
12214
12214
  });
12215
12215
  /**
12216
+ * One record of a BULK insert — {@link SettingsRecordSchema} with the id made
12217
+ * optional.
12218
+ *
12219
+ * A separate schema rather than loosening the shared one: every other method
12220
+ * on this cap addresses a row BY its id, and making that field optional
12221
+ * everywhere would turn a forgotten key into a silently generated one on
12222
+ * `update` and `delete` as well.
12223
+ */
12224
+ var BulkRecordSchema = object({
12225
+ id: string().optional(),
12226
+ data: record(string(), unknown())
12227
+ });
12228
+ /**
12216
12229
  * Column declaration for a structured (SQL-backed) collection.
12217
12230
  *
12218
12231
  * Logical types — the backend translates each to the matching SQLite
@@ -12269,6 +12282,10 @@ method(object({
12269
12282
  collection: string(),
12270
12283
  record: SettingsRecordSchema
12271
12284
  }), _void(), { kind: "mutation" }), method(object({
12285
+ namespace: string().optional(),
12286
+ collection: string(),
12287
+ records: array(BulkRecordSchema).readonly()
12288
+ }), object({ inserted: number().int() }), { kind: "mutation" }), method(object({
12272
12289
  namespace: string().optional(),
12273
12290
  collection: string(),
12274
12291
  id: string(),
@@ -12377,6 +12394,13 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
12377
12394
  }), _void(), {
12378
12395
  kind: "mutation",
12379
12396
  auth: "admin"
12397
+ }), method(object({
12398
+ namespace: string().optional(),
12399
+ collection: string(),
12400
+ records: array(BulkRecordSchema).readonly()
12401
+ }), object({ inserted: number().int() }), {
12402
+ kind: "mutation",
12403
+ auth: "admin"
12380
12404
  }), method(object({
12381
12405
  namespace: string().optional(),
12382
12406
  collection: string(),
@@ -14307,6 +14331,68 @@ method(LogEntrySchema, _void(), { kind: "mutation" }), method(object({
14307
14331
  limit: number().optional(),
14308
14332
  tags: record(string(), string()).optional()
14309
14333
  }), array(LogEntrySchema).readonly());
14334
+ var LoadContributionSchema = object({
14335
+ role: _enum([
14336
+ "decode",
14337
+ "transcode",
14338
+ "recording",
14339
+ "streaming",
14340
+ "detection"
14341
+ ]),
14342
+ /**
14343
+ * The NUMERIC device id — the same value every log line carries as
14344
+ * `tags.deviceId`. `null` means this cost genuinely belongs to no single
14345
+ * camera (a shared pool), NOT that the contributor forgot to look it up: a
14346
+ * contributor that cannot name its camera must not emit the entry at all,
14347
+ * because an unnamed per-camera entry is indistinguishable from a shared one
14348
+ * and would quietly turn one camera's cost into everybody's.
14349
+ */
14350
+ deviceId: number().int().positive().nullable(),
14351
+ attribution: _enum([
14352
+ "measured",
14353
+ "accounted",
14354
+ "unattributable"
14355
+ ]),
14356
+ /**
14357
+ * What ONE entry is, in the contributor's own words — `615/high`,
14358
+ * `617/native`, `cuda:0 shared pool`. Free text because the unit differs per
14359
+ * family and inventing a common one would lose the only information that
14360
+ * makes two entries for the same camera distinguishable.
14361
+ */
14362
+ unit: string(),
14363
+ /**
14364
+ * The OS process this cost lives in, when there is one. Present so a
14365
+ * consumer can (a) tell two generations of the same unit apart across a
14366
+ * restart, and (b) subtract claimed processes from the node's process
14367
+ * snapshot to see what NOBODY claimed. Absent for an entry that owns no
14368
+ * process of its own.
14369
+ */
14370
+ pid: number().int().positive().optional(),
14371
+ /**
14372
+ * When this generation started. The pid's incarnation marker: a consumer
14373
+ * differencing {@link LoadContributionSchema.shape.cpuSeconds} must drop the
14374
+ * window when this changes, because the counter restarted from zero in a new
14375
+ * process.
14376
+ */
14377
+ startedAtMs: number().optional(),
14378
+ /**
14379
+ * CUMULATIVE CPU seconds this unit has consumed since it started — user +
14380
+ * system, read from the child's own `/proc/<pid>/stat` at the moment the
14381
+ * contribution is asked for.
14382
+ *
14383
+ * Cumulative and not a rate on purpose: a rate needs a window, a window
14384
+ * needs a sampler, and a new per-node sampler is the defect half of
14385
+ * `docs/architecture/load-ledger.md` documents. A counter can be differenced
14386
+ * by whoever already keeps a history; a rate cannot be un-averaged.
14387
+ *
14388
+ * Absent — never zero — on a node with no `/proc`, on a read failure, and on
14389
+ * an entry with no process.
14390
+ */
14391
+ cpuSeconds: number().optional(),
14392
+ /** Resident bytes of this unit's process, same source and same rules. */
14393
+ rssBytes: number().optional()
14394
+ });
14395
+ method(_void(), array(LoadContributionSchema).readonly());
14310
14396
  /**
14311
14397
  * `login-method` — collection cap through which auth addons contribute
14312
14398
  * their pre-auth login surfaces to the login page. This is the SINGLE,
@@ -14510,8 +14596,7 @@ var NodeProcessSchema = object({
14510
14596
  classification: _enum([
14511
14597
  "root",
14512
14598
  "managed",
14513
- "system",
14514
- "ghost"
14599
+ "system"
14515
14600
  ]),
14516
14601
  /** `$process` addon binding when `managed`, else null. */
14517
14602
  addonId: string().nullable(),
@@ -14519,22 +14604,39 @@ var NodeProcessSchema = object({
14519
14604
  nodeId: string().nullable(),
14520
14605
  /** Truncated command line. */
14521
14606
  command: string(),
14607
+ /**
14608
+ * `ps pcpu` — CPU averaged over the process's WHOLE LIFETIME, not a rate.
14609
+ * On a runner up for days it barely moves. Fine as a column, useless as a
14610
+ * series: use `cpuMainPercent + cpuGcPercent` for anything time-varying.
14611
+ */
14522
14612
  cpuPercent: number(),
14523
14613
  memoryRssBytes: number(),
14614
+ /**
14615
+ * Instantaneous CPU% of the process's own threads over the last
14616
+ * process-snapshot window, from a `/proc/<pid>/task/*` tick delta.
14617
+ *
14618
+ * `null` = UNKNOWN, never zero: no previous sample yet (first tick after
14619
+ * boot), the pid was recycled, or this node is not Linux.
14620
+ */
14621
+ cpuMainPercent: number().nullable(),
14622
+ /**
14623
+ * Instantaneous CPU% of V8's `V8Worker` platform pool over the same window.
14624
+ *
14625
+ * This is the number that rewrote the 2026-08-27 diagnosis — hub-main 73%,
14626
+ * `stream-broker` 61% (`docs/architecture/load-ledger.md`). A CPU chart that
14627
+ * does not separate it from `cpuMainPercent` shows "busy" where the truth is
14628
+ * "allocating too much".
14629
+ *
14630
+ * Concurrent GC is the dominant tenant of that pool but not the only one
14631
+ * (background compilation runs there too), so it is reported as
14632
+ * "GC / V8 helpers" rather than as pure collection time. `null` has the same
14633
+ * meaning as on `cpuMainPercent`.
14634
+ */
14635
+ cpuGcPercent: number().nullable(),
14636
+ /** Threads seen in the tick scan. `null` under the same conditions. */
14637
+ threadCount: number().nullable(),
14524
14638
  /** Wall-clock uptime (seconds). Parsed from `ps etime`. */
14525
- uptimeSec: number(),
14526
- /** True when ancestor walk reaches `ppid=1` (reparented to init/launchd). */
14527
- orphaned: boolean()
14528
- });
14529
- var KillProcessInputSchema = object({
14530
- pid: number(),
14531
- /** Force = SIGKILL. Default is SIGTERM. */
14532
- force: boolean().optional()
14533
- });
14534
- var KillProcessResultSchema = object({
14535
- success: boolean(),
14536
- reason: string().optional(),
14537
- signal: _enum(["SIGTERM", "SIGKILL"]).optional()
14639
+ uptimeSec: number()
14538
14640
  });
14539
14641
  var DumpHeapSnapshotInputSchema = object({
14540
14642
  /** The addon whose runner should dump a heap snapshot. */
@@ -14547,6 +14649,104 @@ var DumpHeapSnapshotResultSchema = object({
14547
14649
  pid: number().optional(),
14548
14650
  reason: string().optional()
14549
14651
  });
14652
+ /**
14653
+ * One point of one function's series.
14654
+ *
14655
+ * The unsuffixed fields are the bucket's **MAXIMUM**, and that choice is the
14656
+ * point of the whole surface. The two obvious reductions both lie: a mean per
14657
+ * bucket smears a spike away, and taking every Nth sample skips it outright.
14658
+ * Either would give us a tool built to find peaks that does not show peaks.
14659
+ * `...Min` carries the other end, `samples` says how many raw snapshots folded
14660
+ * into the bucket, and a mean stays derivable where it is wanted.
14661
+ *
14662
+ * An UNREDUCED point is a one-sample bucket: `samples === 1` and each `...Min`
14663
+ * equals its unsuffixed twin. Reduced and unreduced are the same shape, so a
14664
+ * caller cannot tell which it received — which is what "one reader" means.
14665
+ */
14666
+ var LoadPointSchema = object({
14667
+ /** Bucket START, or the snapshot's own timestamp when unreduced. */
14668
+ atMs: number(),
14669
+ /** Raw snapshots in this bucket. Never 0 — AN EMPTY BUCKET IS ABSENT. */
14670
+ samples: number().int(),
14671
+ /**
14672
+ * `null` = UNKNOWN and it PROPAGATES: a bucket is null unless every process
14673
+ * of every snapshot in it reported a thread split. A partial sum is a
14674
+ * smaller number that looks exactly as real as a complete one.
14675
+ */
14676
+ cpuMainPercent: number().nullable(),
14677
+ cpuMainPercentMin: number().nullable(),
14678
+ cpuGcPercent: number().nullable(),
14679
+ cpuGcPercentMin: number().nullable(),
14680
+ /** Lifetime-average CPU%, summed. Always known — and never a rate. */
14681
+ cpuLifetimePercent: number(),
14682
+ cpuLifetimePercentMin: number(),
14683
+ memoryRssBytes: number(),
14684
+ memoryRssBytesMin: number(),
14685
+ processCount: number().int(),
14686
+ processCountMin: number().int()
14687
+ });
14688
+ /** One function's series. `key` is an addonId, `__root__` or `__unattributed__`. */
14689
+ var LoadFunctionSeriesSchema = object({
14690
+ key: string(),
14691
+ kind: _enum([
14692
+ "addon",
14693
+ "root",
14694
+ "unattributed"
14695
+ ]),
14696
+ /** Oldest-first. A missing interval is MISSING — never zero-filled. */
14697
+ points: array(LoadPointSchema).readonly()
14698
+ });
14699
+ var NodeLoadSeriesSchema = object({
14700
+ nodeId: string(),
14701
+ /** One entry per function seen in the window, heaviest-first. */
14702
+ series: array(LoadFunctionSeriesSchema).readonly(),
14703
+ /**
14704
+ * Width of one returned bucket, in ms. Equals the sampling cadence when no
14705
+ * reduction was needed — so a caller can always say what one point covers
14706
+ * without having to know whether it was reduced.
14707
+ */
14708
+ bucketMs: number(),
14709
+ /** Raw snapshots that went into this answer, across both tiers. */
14710
+ retainedSamples: number(),
14711
+ /** Oldest snapshot represented, or `null` when nothing is retained. */
14712
+ oldestAtMs: number().nullable(),
14713
+ /** The fixed sampling cadence in force on the cluster, in ms. */
14714
+ cadenceMs: number(),
14715
+ /**
14716
+ * Did the DURABLE tier contribute? `false` means the answer is the hot ring
14717
+ * alone — an agent (which holds no table), or a store that refused.
14718
+ * Reported because "the last hour" and "the last six hours" are different
14719
+ * questions and an operator must not have to guess which was answered.
14720
+ */
14721
+ durable: boolean()
14722
+ });
14723
+ var GetLoadSeriesInputSchema = object({
14724
+ /**
14725
+ * The node whose series is wanted.
14726
+ *
14727
+ * NOT named `nodeId`: the generated cap router strips a top-level
14728
+ * `nodeId` from every method input and uses it to ROUTE the call to
14729
+ * that node's provider (`generated-cap-routers.ts`). A series target
14730
+ * called `nodeId` would silently become a routing pin and never reach
14731
+ * the provider. The hub holds every node it hears from, so the
14732
+ * ordinary call is unpinned — answered by the hub, for any node.
14733
+ */
14734
+ forNodeId: string(),
14735
+ /**
14736
+ * EXCLUSIVE lower bound. A caller passes the newest `atMs` it already
14737
+ * holds and receives only what it is missing, so seeding a live chart
14738
+ * from this method cannot double a point already drawn.
14739
+ */
14740
+ sinceMs: number().optional(),
14741
+ /**
14742
+ * Most points the caller wants PER FUNCTION. The window is reduced to fit,
14743
+ * preserving min and max per bucket.
14744
+ *
14745
+ * Absent means NO reduction — legitimate for a short window and a trap for a
14746
+ * long one, which is why a chart passes its own pixel width.
14747
+ */
14748
+ maxPoints: number().int().positive().optional()
14749
+ });
14550
14750
  var SystemMetricsSchema = object({
14551
14751
  cpuPercent: number(),
14552
14752
  memoryPercent: number(),
@@ -14557,10 +14757,7 @@ var SystemMetricsSchema = object({
14557
14757
  gpuPercent: number().optional(),
14558
14758
  gpuMemoryPercent: number().optional()
14559
14759
  });
14560
- method(_void(), SystemResourceSnapshotSchema), method(_void(), SystemResourceSnapshotSchema.nullable()), method(_void(), SystemMetricsSchema), method(object({ dirPath: string() }), DiskSpaceInfoSchema), method(_void(), MetricsGpuInfoSchema.nullable()), method(_void(), number().nullable()), method(object({ pids: array(number()) }), array(PidResourceStatsSchema)), method(_void(), array(AddonInstanceSchema).readonly()), method(object({ addonId: string() }), PidResourceStatsSchema.nullable()), method(_void(), array(NodeProcessSchema).readonly()), method(KillProcessInputSchema, KillProcessResultSchema, {
14561
- kind: "mutation",
14562
- auth: "admin"
14563
- }), method(DumpHeapSnapshotInputSchema, DumpHeapSnapshotResultSchema, {
14760
+ method(_void(), SystemResourceSnapshotSchema), method(_void(), SystemResourceSnapshotSchema.nullable()), method(_void(), SystemMetricsSchema), method(object({ dirPath: string() }), DiskSpaceInfoSchema), method(_void(), MetricsGpuInfoSchema.nullable()), method(_void(), number().nullable()), method(object({ pids: array(number()) }), array(PidResourceStatsSchema)), method(_void(), array(AddonInstanceSchema).readonly()), method(object({ addonId: string() }), PidResourceStatsSchema.nullable()), method(_void(), array(NodeProcessSchema).readonly()), method(GetLoadSeriesInputSchema, NodeLoadSeriesSchema), method(DumpHeapSnapshotInputSchema, DumpHeapSnapshotResultSchema, {
14564
14761
  kind: "mutation",
14565
14762
  auth: "admin"
14566
14763
  });
@@ -29890,6 +30087,15 @@ var LoggingSettingsPatchSchema = object({
29890
30087
  * authority over the whole hierarchy and answers for every layer, so the
29891
30088
  * layer selector needs a name the transport does not already own.
29892
30089
  */
30090
+ /**
30091
+ * One contribution, plus WHO reported it.
30092
+ *
30093
+ * The addon and node are added by the hub as it enumerates providers, never by
30094
+ * the contributor: an addon reporting its own identity could report somebody
30095
+ * else's, and the whole point of this surface is that no claim is made by
30096
+ * anyone but its owner.
30097
+ */
30098
+ var ReportedLoadContributionSchema = LoadContributionSchema.extend({ addonId: string() });
29893
30099
  var GetLoggingSettingsInputSchema = object({
29894
30100
  scopeNodeId: string().optional(),
29895
30101
  /**
@@ -29948,7 +30154,7 @@ method(_void(), FeatureManifestSchema), method(_void(), HealthStatusSchema), met
29948
30154
  }), method(_void(), SiteLocationStatusSchema, {
29949
30155
  kind: "mutation",
29950
30156
  auth: "admin"
29951
- }), method(_void(), RequestCensusStatusSchema, { auth: "admin" }), method(GetLoggingSettingsInputSchema, LoggingSettingsStateSchema, { auth: "admin" }), method(SetLoggingSettingsInputSchema, LoggingSettingsStateSchema, {
30157
+ }), method(_void(), RequestCensusStatusSchema, { auth: "admin" }), method(_void(), array(ReportedLoadContributionSchema).readonly(), { auth: "admin" }), method(GetLoggingSettingsInputSchema, LoggingSettingsStateSchema, { auth: "admin" }), method(SetLoggingSettingsInputSchema, LoggingSettingsStateSchema, {
29952
30158
  kind: "mutation",
29953
30159
  auth: "admin"
29954
30160
  });
@@ -32972,6 +33178,12 @@ Object.freeze({
32972
33178
  addonId: null,
32973
33179
  access: "create"
32974
33180
  },
33181
+ "dataStoreProvider.insertMany": {
33182
+ capName: "data-store-provider",
33183
+ capScope: "system",
33184
+ addonId: null,
33185
+ access: "create"
33186
+ },
32975
33187
  "dataStoreProvider.isEmpty": {
32976
33188
  capName: "data-store-provider",
32977
33189
  capScope: "system",
@@ -34286,6 +34498,12 @@ Object.freeze({
34286
34498
  addonId: null,
34287
34499
  access: "create"
34288
34500
  },
34501
+ "loadContribution.list": {
34502
+ capName: "load-contribution",
34503
+ capScope: "system",
34504
+ addonId: null,
34505
+ access: "view"
34506
+ },
34289
34507
  "localNetwork.downloadCa": {
34290
34508
  capName: "local-network",
34291
34509
  capScope: "system",
@@ -34586,17 +34804,17 @@ Object.freeze({
34586
34804
  addonId: null,
34587
34805
  access: "view"
34588
34806
  },
34589
- "metricsProvider.getProcessStats": {
34807
+ "metricsProvider.getLoadSeries": {
34590
34808
  capName: "metrics-provider",
34591
34809
  capScope: "system",
34592
34810
  addonId: null,
34593
34811
  access: "view"
34594
34812
  },
34595
- "metricsProvider.killProcess": {
34813
+ "metricsProvider.getProcessStats": {
34596
34814
  capName: "metrics-provider",
34597
34815
  capScope: "system",
34598
34816
  addonId: null,
34599
- access: "create"
34817
+ access: "view"
34600
34818
  },
34601
34819
  "metricsProvider.listAddonInstances": {
34602
34820
  capName: "metrics-provider",
@@ -36608,6 +36826,12 @@ Object.freeze({
36608
36826
  addonId: null,
36609
36827
  access: "create"
36610
36828
  },
36829
+ "settingsStore.insertMany": {
36830
+ capName: "settings-store",
36831
+ capScope: "system",
36832
+ addonId: null,
36833
+ access: "create"
36834
+ },
36611
36835
  "settingsStore.isEmpty": {
36612
36836
  capName: "settings-store",
36613
36837
  capScope: "system",
@@ -37220,6 +37444,12 @@ Object.freeze({
37220
37444
  addonId: null,
37221
37445
  access: "create"
37222
37446
  },
37447
+ "system.getLoadContributions": {
37448
+ capName: "system",
37449
+ capScope: "system",
37450
+ addonId: null,
37451
+ access: "view"
37452
+ },
37223
37453
  "system.getLoggingSettings": {
37224
37454
  capName: "system",
37225
37455
  capScope: "system",
package/dist/addon.mjs CHANGED
@@ -983,7 +983,7 @@ var Rademacher = class {
983
983
  }
984
984
  };
985
985
  //#endregion
986
- //#region ../types/dist/event-category-CIa_iT6b.mjs
986
+ //#region ../types/dist/event-category-BZL-fdNj.mjs
987
987
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
988
988
  EventCategory["SystemBoot"] = "system.boot";
989
989
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -1420,7 +1420,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
1420
1420
  EventCategory["MetricsNodeResourcesSnapshot"] = "metrics.node-resources-snapshot";
1421
1421
  /**
1422
1422
  * Periodic per-node process-tree snapshot (camstack-related pids
1423
- * with ghost / managed / root classification). Emitted ~0.2 Hz by
1423
+ * with root / managed / system classification). Emitted ~0.2 Hz by
1424
1424
  * the metrics-provider addon. Drives the Cluster → Processes tab
1425
1425
  * without polling `metricsProvider.listNodeProcesses`.
1426
1426
  */
@@ -12212,6 +12212,19 @@ var SettingsRecordSchema = object({
12212
12212
  data: record(string(), unknown())
12213
12213
  });
12214
12214
  /**
12215
+ * One record of a BULK insert — {@link SettingsRecordSchema} with the id made
12216
+ * optional.
12217
+ *
12218
+ * A separate schema rather than loosening the shared one: every other method
12219
+ * on this cap addresses a row BY its id, and making that field optional
12220
+ * everywhere would turn a forgotten key into a silently generated one on
12221
+ * `update` and `delete` as well.
12222
+ */
12223
+ var BulkRecordSchema = object({
12224
+ id: string().optional(),
12225
+ data: record(string(), unknown())
12226
+ });
12227
+ /**
12215
12228
  * Column declaration for a structured (SQL-backed) collection.
12216
12229
  *
12217
12230
  * Logical types — the backend translates each to the matching SQLite
@@ -12268,6 +12281,10 @@ method(object({
12268
12281
  collection: string(),
12269
12282
  record: SettingsRecordSchema
12270
12283
  }), _void(), { kind: "mutation" }), method(object({
12284
+ namespace: string().optional(),
12285
+ collection: string(),
12286
+ records: array(BulkRecordSchema).readonly()
12287
+ }), object({ inserted: number().int() }), { kind: "mutation" }), method(object({
12271
12288
  namespace: string().optional(),
12272
12289
  collection: string(),
12273
12290
  id: string(),
@@ -12376,6 +12393,13 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
12376
12393
  }), _void(), {
12377
12394
  kind: "mutation",
12378
12395
  auth: "admin"
12396
+ }), method(object({
12397
+ namespace: string().optional(),
12398
+ collection: string(),
12399
+ records: array(BulkRecordSchema).readonly()
12400
+ }), object({ inserted: number().int() }), {
12401
+ kind: "mutation",
12402
+ auth: "admin"
12379
12403
  }), method(object({
12380
12404
  namespace: string().optional(),
12381
12405
  collection: string(),
@@ -14306,6 +14330,68 @@ method(LogEntrySchema, _void(), { kind: "mutation" }), method(object({
14306
14330
  limit: number().optional(),
14307
14331
  tags: record(string(), string()).optional()
14308
14332
  }), array(LogEntrySchema).readonly());
14333
+ var LoadContributionSchema = object({
14334
+ role: _enum([
14335
+ "decode",
14336
+ "transcode",
14337
+ "recording",
14338
+ "streaming",
14339
+ "detection"
14340
+ ]),
14341
+ /**
14342
+ * The NUMERIC device id — the same value every log line carries as
14343
+ * `tags.deviceId`. `null` means this cost genuinely belongs to no single
14344
+ * camera (a shared pool), NOT that the contributor forgot to look it up: a
14345
+ * contributor that cannot name its camera must not emit the entry at all,
14346
+ * because an unnamed per-camera entry is indistinguishable from a shared one
14347
+ * and would quietly turn one camera's cost into everybody's.
14348
+ */
14349
+ deviceId: number().int().positive().nullable(),
14350
+ attribution: _enum([
14351
+ "measured",
14352
+ "accounted",
14353
+ "unattributable"
14354
+ ]),
14355
+ /**
14356
+ * What ONE entry is, in the contributor's own words — `615/high`,
14357
+ * `617/native`, `cuda:0 shared pool`. Free text because the unit differs per
14358
+ * family and inventing a common one would lose the only information that
14359
+ * makes two entries for the same camera distinguishable.
14360
+ */
14361
+ unit: string(),
14362
+ /**
14363
+ * The OS process this cost lives in, when there is one. Present so a
14364
+ * consumer can (a) tell two generations of the same unit apart across a
14365
+ * restart, and (b) subtract claimed processes from the node's process
14366
+ * snapshot to see what NOBODY claimed. Absent for an entry that owns no
14367
+ * process of its own.
14368
+ */
14369
+ pid: number().int().positive().optional(),
14370
+ /**
14371
+ * When this generation started. The pid's incarnation marker: a consumer
14372
+ * differencing {@link LoadContributionSchema.shape.cpuSeconds} must drop the
14373
+ * window when this changes, because the counter restarted from zero in a new
14374
+ * process.
14375
+ */
14376
+ startedAtMs: number().optional(),
14377
+ /**
14378
+ * CUMULATIVE CPU seconds this unit has consumed since it started — user +
14379
+ * system, read from the child's own `/proc/<pid>/stat` at the moment the
14380
+ * contribution is asked for.
14381
+ *
14382
+ * Cumulative and not a rate on purpose: a rate needs a window, a window
14383
+ * needs a sampler, and a new per-node sampler is the defect half of
14384
+ * `docs/architecture/load-ledger.md` documents. A counter can be differenced
14385
+ * by whoever already keeps a history; a rate cannot be un-averaged.
14386
+ *
14387
+ * Absent — never zero — on a node with no `/proc`, on a read failure, and on
14388
+ * an entry with no process.
14389
+ */
14390
+ cpuSeconds: number().optional(),
14391
+ /** Resident bytes of this unit's process, same source and same rules. */
14392
+ rssBytes: number().optional()
14393
+ });
14394
+ method(_void(), array(LoadContributionSchema).readonly());
14309
14395
  /**
14310
14396
  * `login-method` — collection cap through which auth addons contribute
14311
14397
  * their pre-auth login surfaces to the login page. This is the SINGLE,
@@ -14509,8 +14595,7 @@ var NodeProcessSchema = object({
14509
14595
  classification: _enum([
14510
14596
  "root",
14511
14597
  "managed",
14512
- "system",
14513
- "ghost"
14598
+ "system"
14514
14599
  ]),
14515
14600
  /** `$process` addon binding when `managed`, else null. */
14516
14601
  addonId: string().nullable(),
@@ -14518,22 +14603,39 @@ var NodeProcessSchema = object({
14518
14603
  nodeId: string().nullable(),
14519
14604
  /** Truncated command line. */
14520
14605
  command: string(),
14606
+ /**
14607
+ * `ps pcpu` — CPU averaged over the process's WHOLE LIFETIME, not a rate.
14608
+ * On a runner up for days it barely moves. Fine as a column, useless as a
14609
+ * series: use `cpuMainPercent + cpuGcPercent` for anything time-varying.
14610
+ */
14521
14611
  cpuPercent: number(),
14522
14612
  memoryRssBytes: number(),
14613
+ /**
14614
+ * Instantaneous CPU% of the process's own threads over the last
14615
+ * process-snapshot window, from a `/proc/<pid>/task/*` tick delta.
14616
+ *
14617
+ * `null` = UNKNOWN, never zero: no previous sample yet (first tick after
14618
+ * boot), the pid was recycled, or this node is not Linux.
14619
+ */
14620
+ cpuMainPercent: number().nullable(),
14621
+ /**
14622
+ * Instantaneous CPU% of V8's `V8Worker` platform pool over the same window.
14623
+ *
14624
+ * This is the number that rewrote the 2026-08-27 diagnosis — hub-main 73%,
14625
+ * `stream-broker` 61% (`docs/architecture/load-ledger.md`). A CPU chart that
14626
+ * does not separate it from `cpuMainPercent` shows "busy" where the truth is
14627
+ * "allocating too much".
14628
+ *
14629
+ * Concurrent GC is the dominant tenant of that pool but not the only one
14630
+ * (background compilation runs there too), so it is reported as
14631
+ * "GC / V8 helpers" rather than as pure collection time. `null` has the same
14632
+ * meaning as on `cpuMainPercent`.
14633
+ */
14634
+ cpuGcPercent: number().nullable(),
14635
+ /** Threads seen in the tick scan. `null` under the same conditions. */
14636
+ threadCount: number().nullable(),
14523
14637
  /** Wall-clock uptime (seconds). Parsed from `ps etime`. */
14524
- uptimeSec: number(),
14525
- /** True when ancestor walk reaches `ppid=1` (reparented to init/launchd). */
14526
- orphaned: boolean()
14527
- });
14528
- var KillProcessInputSchema = object({
14529
- pid: number(),
14530
- /** Force = SIGKILL. Default is SIGTERM. */
14531
- force: boolean().optional()
14532
- });
14533
- var KillProcessResultSchema = object({
14534
- success: boolean(),
14535
- reason: string().optional(),
14536
- signal: _enum(["SIGTERM", "SIGKILL"]).optional()
14638
+ uptimeSec: number()
14537
14639
  });
14538
14640
  var DumpHeapSnapshotInputSchema = object({
14539
14641
  /** The addon whose runner should dump a heap snapshot. */
@@ -14546,6 +14648,104 @@ var DumpHeapSnapshotResultSchema = object({
14546
14648
  pid: number().optional(),
14547
14649
  reason: string().optional()
14548
14650
  });
14651
+ /**
14652
+ * One point of one function's series.
14653
+ *
14654
+ * The unsuffixed fields are the bucket's **MAXIMUM**, and that choice is the
14655
+ * point of the whole surface. The two obvious reductions both lie: a mean per
14656
+ * bucket smears a spike away, and taking every Nth sample skips it outright.
14657
+ * Either would give us a tool built to find peaks that does not show peaks.
14658
+ * `...Min` carries the other end, `samples` says how many raw snapshots folded
14659
+ * into the bucket, and a mean stays derivable where it is wanted.
14660
+ *
14661
+ * An UNREDUCED point is a one-sample bucket: `samples === 1` and each `...Min`
14662
+ * equals its unsuffixed twin. Reduced and unreduced are the same shape, so a
14663
+ * caller cannot tell which it received — which is what "one reader" means.
14664
+ */
14665
+ var LoadPointSchema = object({
14666
+ /** Bucket START, or the snapshot's own timestamp when unreduced. */
14667
+ atMs: number(),
14668
+ /** Raw snapshots in this bucket. Never 0 — AN EMPTY BUCKET IS ABSENT. */
14669
+ samples: number().int(),
14670
+ /**
14671
+ * `null` = UNKNOWN and it PROPAGATES: a bucket is null unless every process
14672
+ * of every snapshot in it reported a thread split. A partial sum is a
14673
+ * smaller number that looks exactly as real as a complete one.
14674
+ */
14675
+ cpuMainPercent: number().nullable(),
14676
+ cpuMainPercentMin: number().nullable(),
14677
+ cpuGcPercent: number().nullable(),
14678
+ cpuGcPercentMin: number().nullable(),
14679
+ /** Lifetime-average CPU%, summed. Always known — and never a rate. */
14680
+ cpuLifetimePercent: number(),
14681
+ cpuLifetimePercentMin: number(),
14682
+ memoryRssBytes: number(),
14683
+ memoryRssBytesMin: number(),
14684
+ processCount: number().int(),
14685
+ processCountMin: number().int()
14686
+ });
14687
+ /** One function's series. `key` is an addonId, `__root__` or `__unattributed__`. */
14688
+ var LoadFunctionSeriesSchema = object({
14689
+ key: string(),
14690
+ kind: _enum([
14691
+ "addon",
14692
+ "root",
14693
+ "unattributed"
14694
+ ]),
14695
+ /** Oldest-first. A missing interval is MISSING — never zero-filled. */
14696
+ points: array(LoadPointSchema).readonly()
14697
+ });
14698
+ var NodeLoadSeriesSchema = object({
14699
+ nodeId: string(),
14700
+ /** One entry per function seen in the window, heaviest-first. */
14701
+ series: array(LoadFunctionSeriesSchema).readonly(),
14702
+ /**
14703
+ * Width of one returned bucket, in ms. Equals the sampling cadence when no
14704
+ * reduction was needed — so a caller can always say what one point covers
14705
+ * without having to know whether it was reduced.
14706
+ */
14707
+ bucketMs: number(),
14708
+ /** Raw snapshots that went into this answer, across both tiers. */
14709
+ retainedSamples: number(),
14710
+ /** Oldest snapshot represented, or `null` when nothing is retained. */
14711
+ oldestAtMs: number().nullable(),
14712
+ /** The fixed sampling cadence in force on the cluster, in ms. */
14713
+ cadenceMs: number(),
14714
+ /**
14715
+ * Did the DURABLE tier contribute? `false` means the answer is the hot ring
14716
+ * alone — an agent (which holds no table), or a store that refused.
14717
+ * Reported because "the last hour" and "the last six hours" are different
14718
+ * questions and an operator must not have to guess which was answered.
14719
+ */
14720
+ durable: boolean()
14721
+ });
14722
+ var GetLoadSeriesInputSchema = object({
14723
+ /**
14724
+ * The node whose series is wanted.
14725
+ *
14726
+ * NOT named `nodeId`: the generated cap router strips a top-level
14727
+ * `nodeId` from every method input and uses it to ROUTE the call to
14728
+ * that node's provider (`generated-cap-routers.ts`). A series target
14729
+ * called `nodeId` would silently become a routing pin and never reach
14730
+ * the provider. The hub holds every node it hears from, so the
14731
+ * ordinary call is unpinned — answered by the hub, for any node.
14732
+ */
14733
+ forNodeId: string(),
14734
+ /**
14735
+ * EXCLUSIVE lower bound. A caller passes the newest `atMs` it already
14736
+ * holds and receives only what it is missing, so seeding a live chart
14737
+ * from this method cannot double a point already drawn.
14738
+ */
14739
+ sinceMs: number().optional(),
14740
+ /**
14741
+ * Most points the caller wants PER FUNCTION. The window is reduced to fit,
14742
+ * preserving min and max per bucket.
14743
+ *
14744
+ * Absent means NO reduction — legitimate for a short window and a trap for a
14745
+ * long one, which is why a chart passes its own pixel width.
14746
+ */
14747
+ maxPoints: number().int().positive().optional()
14748
+ });
14549
14749
  var SystemMetricsSchema = object({
14550
14750
  cpuPercent: number(),
14551
14751
  memoryPercent: number(),
@@ -14556,10 +14756,7 @@ var SystemMetricsSchema = object({
14556
14756
  gpuPercent: number().optional(),
14557
14757
  gpuMemoryPercent: number().optional()
14558
14758
  });
14559
- method(_void(), SystemResourceSnapshotSchema), method(_void(), SystemResourceSnapshotSchema.nullable()), method(_void(), SystemMetricsSchema), method(object({ dirPath: string() }), DiskSpaceInfoSchema), method(_void(), MetricsGpuInfoSchema.nullable()), method(_void(), number().nullable()), method(object({ pids: array(number()) }), array(PidResourceStatsSchema)), method(_void(), array(AddonInstanceSchema).readonly()), method(object({ addonId: string() }), PidResourceStatsSchema.nullable()), method(_void(), array(NodeProcessSchema).readonly()), method(KillProcessInputSchema, KillProcessResultSchema, {
14560
- kind: "mutation",
14561
- auth: "admin"
14562
- }), method(DumpHeapSnapshotInputSchema, DumpHeapSnapshotResultSchema, {
14759
+ method(_void(), SystemResourceSnapshotSchema), method(_void(), SystemResourceSnapshotSchema.nullable()), method(_void(), SystemMetricsSchema), method(object({ dirPath: string() }), DiskSpaceInfoSchema), method(_void(), MetricsGpuInfoSchema.nullable()), method(_void(), number().nullable()), method(object({ pids: array(number()) }), array(PidResourceStatsSchema)), method(_void(), array(AddonInstanceSchema).readonly()), method(object({ addonId: string() }), PidResourceStatsSchema.nullable()), method(_void(), array(NodeProcessSchema).readonly()), method(GetLoadSeriesInputSchema, NodeLoadSeriesSchema), method(DumpHeapSnapshotInputSchema, DumpHeapSnapshotResultSchema, {
14563
14760
  kind: "mutation",
14564
14761
  auth: "admin"
14565
14762
  });
@@ -29889,6 +30086,15 @@ var LoggingSettingsPatchSchema = object({
29889
30086
  * authority over the whole hierarchy and answers for every layer, so the
29890
30087
  * layer selector needs a name the transport does not already own.
29891
30088
  */
30089
+ /**
30090
+ * One contribution, plus WHO reported it.
30091
+ *
30092
+ * The addon and node are added by the hub as it enumerates providers, never by
30093
+ * the contributor: an addon reporting its own identity could report somebody
30094
+ * else's, and the whole point of this surface is that no claim is made by
30095
+ * anyone but its owner.
30096
+ */
30097
+ var ReportedLoadContributionSchema = LoadContributionSchema.extend({ addonId: string() });
29892
30098
  var GetLoggingSettingsInputSchema = object({
29893
30099
  scopeNodeId: string().optional(),
29894
30100
  /**
@@ -29947,7 +30153,7 @@ method(_void(), FeatureManifestSchema), method(_void(), HealthStatusSchema), met
29947
30153
  }), method(_void(), SiteLocationStatusSchema, {
29948
30154
  kind: "mutation",
29949
30155
  auth: "admin"
29950
- }), method(_void(), RequestCensusStatusSchema, { auth: "admin" }), method(GetLoggingSettingsInputSchema, LoggingSettingsStateSchema, { auth: "admin" }), method(SetLoggingSettingsInputSchema, LoggingSettingsStateSchema, {
30156
+ }), method(_void(), RequestCensusStatusSchema, { auth: "admin" }), method(_void(), array(ReportedLoadContributionSchema).readonly(), { auth: "admin" }), method(GetLoggingSettingsInputSchema, LoggingSettingsStateSchema, { auth: "admin" }), method(SetLoggingSettingsInputSchema, LoggingSettingsStateSchema, {
29951
30157
  kind: "mutation",
29952
30158
  auth: "admin"
29953
30159
  });
@@ -32971,6 +33177,12 @@ Object.freeze({
32971
33177
  addonId: null,
32972
33178
  access: "create"
32973
33179
  },
33180
+ "dataStoreProvider.insertMany": {
33181
+ capName: "data-store-provider",
33182
+ capScope: "system",
33183
+ addonId: null,
33184
+ access: "create"
33185
+ },
32974
33186
  "dataStoreProvider.isEmpty": {
32975
33187
  capName: "data-store-provider",
32976
33188
  capScope: "system",
@@ -34285,6 +34497,12 @@ Object.freeze({
34285
34497
  addonId: null,
34286
34498
  access: "create"
34287
34499
  },
34500
+ "loadContribution.list": {
34501
+ capName: "load-contribution",
34502
+ capScope: "system",
34503
+ addonId: null,
34504
+ access: "view"
34505
+ },
34288
34506
  "localNetwork.downloadCa": {
34289
34507
  capName: "local-network",
34290
34508
  capScope: "system",
@@ -34585,17 +34803,17 @@ Object.freeze({
34585
34803
  addonId: null,
34586
34804
  access: "view"
34587
34805
  },
34588
- "metricsProvider.getProcessStats": {
34806
+ "metricsProvider.getLoadSeries": {
34589
34807
  capName: "metrics-provider",
34590
34808
  capScope: "system",
34591
34809
  addonId: null,
34592
34810
  access: "view"
34593
34811
  },
34594
- "metricsProvider.killProcess": {
34812
+ "metricsProvider.getProcessStats": {
34595
34813
  capName: "metrics-provider",
34596
34814
  capScope: "system",
34597
34815
  addonId: null,
34598
- access: "create"
34816
+ access: "view"
34599
34817
  },
34600
34818
  "metricsProvider.listAddonInstances": {
34601
34819
  capName: "metrics-provider",
@@ -36607,6 +36825,12 @@ Object.freeze({
36607
36825
  addonId: null,
36608
36826
  access: "create"
36609
36827
  },
36828
+ "settingsStore.insertMany": {
36829
+ capName: "settings-store",
36830
+ capScope: "system",
36831
+ addonId: null,
36832
+ access: "create"
36833
+ },
36610
36834
  "settingsStore.isEmpty": {
36611
36835
  capName: "settings-store",
36612
36836
  capScope: "system",
@@ -37219,6 +37443,12 @@ Object.freeze({
37219
37443
  addonId: null,
37220
37444
  access: "create"
37221
37445
  },
37446
+ "system.getLoadContributions": {
37447
+ capName: "system",
37448
+ capScope: "system",
37449
+ addonId: null,
37450
+ access: "view"
37451
+ },
37222
37452
  "system.getLoggingSettings": {
37223
37453
  capName: "system",
37224
37454
  capScope: "system",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-rademacher",
3
- "version": "0.2.34",
3
+ "version": "0.2.36",
4
4
  "description": "Rademacher HomePilot device-provider addon for CamStack — wraps the @apocaliss92/noderademacher local-hub client (roller shutters over the cover cap)",
5
5
  "keywords": [
6
6
  "camstack",