@camstack/system 1.2.219 → 1.2.221

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 (68) hide show
  1. package/dist/addon-runner.js +2 -2
  2. package/dist/addon-runner.mjs +2 -2
  3. package/dist/addon-utils.js +1 -1
  4. package/dist/addon-utils.mjs +1 -1
  5. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  6. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  7. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  8. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  9. package/dist/builtins/alerts/alerts.addon.js +1 -1
  10. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  11. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
  12. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
  13. package/dist/builtins/console-logging/index.js +1 -1
  14. package/dist/builtins/console-logging/index.mjs +1 -1
  15. package/dist/builtins/core-blocks/core-blocks.addon.js +1 -1
  16. package/dist/builtins/core-blocks/core-blocks.addon.mjs +1 -1
  17. package/dist/builtins/device-manager/device-manager.addon.js +2 -2
  18. package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
  19. package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
  20. package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
  21. package/dist/builtins/hub-forwarder/index.js +1 -1
  22. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  23. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  24. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  25. package/dist/builtins/local-auth/local-auth.addon.js +1 -1
  26. package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
  27. package/dist/builtins/local-network/local-network.addon.js +1 -1
  28. package/dist/builtins/local-network/local-network.addon.mjs +1 -1
  29. package/dist/builtins/loki-logging/index.js +1 -1
  30. package/dist/builtins/loki-logging/index.mjs +1 -1
  31. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  32. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  33. package/dist/builtins/platform-probe/index.js +1 -1
  34. package/dist/builtins/platform-probe/index.mjs +1 -1
  35. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  36. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  37. package/dist/builtins/snapshot/index.js +1 -1
  38. package/dist/builtins/snapshot/index.mjs +1 -1
  39. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  40. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  41. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +0 -0
  42. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +0 -0
  43. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
  44. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
  45. package/dist/builtins/system-config/system-config.addon.js +1 -1
  46. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  47. package/dist/builtins/winston-logging/index.js +1 -1
  48. package/dist/builtins/winston-logging/index.mjs +1 -1
  49. package/dist/{custom-action-registry-DKWhaWL1.js → custom-action-registry-DvVMHLfJ.js} +1 -1
  50. package/dist/{custom-action-registry-B6gOtUWA.mjs → custom-action-registry-DvtOs-tp.mjs} +1 -1
  51. package/dist/{dist-B17W9ngu.js → dist-0sWJNwme.js} +261 -4
  52. package/dist/{dist-Cyz5_i7z.mjs → dist-T9GvfhgV.mjs} +261 -4
  53. package/dist/index.js +71 -32
  54. package/dist/index.mjs +65 -33
  55. package/dist/kernel/gc-census.d.ts +144 -0
  56. package/dist/kernel/heap-watch.d.ts +8 -0
  57. package/dist/kernel/socket-plane-report.d.ts +37 -0
  58. package/dist/kernel/transport/cap-action-census.d.ts +218 -0
  59. package/dist/kernel/transport/cap-child-index.d.ts +49 -0
  60. package/dist/kernel/transport/index.d.ts +2 -0
  61. package/dist/kernel/transport/local-child-registry.d.ts +63 -4
  62. package/dist/kernel/transport/local-transport.d.ts +9 -0
  63. package/dist/kernel/transport/socket-channel.d.ts +21 -0
  64. package/dist/{manifest-system-deps-g_nK0xsF.js → manifest-system-deps-DfpwaXkh.js} +550 -27
  65. package/dist/{manifest-system-deps-C7dihwWT.mjs → manifest-system-deps-iadzxSBr.mjs} +509 -28
  66. package/dist/{retired-settings-keys-CjvB7Etx.js → retired-settings-keys-Dh-XMfFx.js} +1 -1
  67. package/dist/{retired-settings-keys-BCYUrdsA.mjs → retired-settings-keys-DmVZAH9M.mjs} +1 -1
  68. package/package.json +1 -1
@@ -155,6 +155,166 @@ function formatEventPlane(window) {
155
155
  return ` fanoutMode=uds:${window.udsMode}/cross-node:${window.crossNodeMode} children=${window.childrenConnected} childrenUndeclared=${window.childrenUndeclared} fanoutSent=${window.fanoutSent} fanoutSuppressed=${window.fanoutSuppressed} crossNodeDelivered=${window.crossNodeDelivered} crossNodeSuppressed=${window.crossNodeSuppressed}` + (top.length === 0 ? "" : ` fanoutTop=${top}`);
156
156
  }
157
157
  //#endregion
158
+ //#region src/kernel/transport/cap-action-census.ts
159
+ /** A process that has never read the census. */
160
+ var EMPTY_CAP_ACTION_READING = /* @__PURE__ */ new Map();
161
+ /**
162
+ * Bytes that crossed on a frame carrying no cap envelope.
163
+ *
164
+ * Named rather than omitted so the census's coverage is readable off its own
165
+ * output: `register`, `addon-call`, log frames and the event fan-out all land
166
+ * here. A census that reported only what it could name would look like a
167
+ * complete attribution of whatever share it happened to cover.
168
+ */
169
+ var CAP_ACTION_UNLABELLED = "(unlabelled)";
170
+ /** Bytes of actions past {@link MAX_CAP_ACTIONS_PER_PEER} on one peer. */
171
+ var CAP_ACTION_OVERFLOW_LABEL = "(overflow)";
172
+ /**
173
+ * Distinct named actions kept per peer before the overflow bucket takes over.
174
+ *
175
+ * Sixty-four against a measured worst case of 14 (`pipeline-analytics`, the
176
+ * heaviest peer on this hub, 2026-09-11) — four times the observed shape, so a
177
+ * peer has to change character before it overflows, and a bound that is never
178
+ * reached in practice still forbids the unbounded growth a wire-supplied key
179
+ * makes possible in principle.
180
+ */
181
+ var MAX_CAP_ACTIONS_PER_PEER = 64;
182
+ /**
183
+ * `<cap>.<method>` for a cap envelope, `null` for anything else.
184
+ *
185
+ * Both directions are labelled by the same function: a child's `cap-call-out`
186
+ * and the parent's `cap-call` carry `capName` + `method` in the same two keys,
187
+ * so one predicate covers the whole plane. Anything else — a `register`, an
188
+ * `addon-call`, a log or an event — is deliberately unlabelled; see
189
+ * {@link CAP_ACTION_UNLABELLED} for where its bytes go.
190
+ *
191
+ * Cost: two property reads, two `typeof`s and one concatenation of two short
192
+ * strings, called once per `req` frame (not per frame). Against the
193
+ * `encodeFrame` it sits beside — 1 948–1 975 ns on a 0.33 kB body — it is
194
+ * noise, and unlike `recordSocketFrame` it is not on the `evt` path at all.
195
+ */
196
+ function capActionLabel(body) {
197
+ if (typeof body !== "object" || body === null) return null;
198
+ const env = body;
199
+ if (env.kind !== "cap-call" && env.kind !== "cap-call-out") return null;
200
+ if (typeof env.capName !== "string" || typeof env.method !== "string") return null;
201
+ return `${env.capName}.${env.method}`;
202
+ }
203
+ function emptyCounters() {
204
+ return {
205
+ calls: 0,
206
+ reqBytes: 0,
207
+ resBytes: 0,
208
+ raw: 0,
209
+ decoded: 0
210
+ };
211
+ }
212
+ function createCapActionCensus() {
213
+ const peers = /* @__PURE__ */ new Map();
214
+ /**
215
+ * The per-peer slot for `action`, creating it under the bound.
216
+ *
217
+ * Past {@link MAX_CAP_ACTIONS_PER_PEER} a NEW label is folded into the
218
+ * overflow bucket; labels already present keep their own slot, so a peer
219
+ * that overflows does not lose the attribution it had built.
220
+ */
221
+ const slot = (peerId, action) => {
222
+ let byAction = peers.get(peerId);
223
+ if (byAction === void 0) {
224
+ byAction = /* @__PURE__ */ new Map();
225
+ peers.set(peerId, byAction);
226
+ }
227
+ const existing = byAction.get(action);
228
+ if (existing !== void 0) return existing;
229
+ if (byAction.size >= 64) {
230
+ let overflow = byAction.get(CAP_ACTION_OVERFLOW_LABEL);
231
+ if (overflow === void 0) {
232
+ overflow = emptyCounters();
233
+ byAction.set(CAP_ACTION_OVERFLOW_LABEL, overflow);
234
+ }
235
+ return overflow;
236
+ }
237
+ const fresh = emptyCounters();
238
+ byAction.set(action, fresh);
239
+ return fresh;
240
+ };
241
+ return {
242
+ record(peerId, action, reqBytes, resBytes) {
243
+ const c = slot(peerId, action);
244
+ c.calls += 1;
245
+ c.reqBytes += reqBytes;
246
+ c.resBytes += resBytes;
247
+ },
248
+ recordForward(peerId, action, kind) {
249
+ const c = slot(peerId, action);
250
+ if (kind === "raw") c.raw += 1;
251
+ else c.decoded += 1;
252
+ },
253
+ recordUnlabelled(peerId, bytes) {
254
+ const c = slot(peerId, CAP_ACTION_UNLABELLED);
255
+ c.resBytes += bytes;
256
+ },
257
+ forget(peerId) {
258
+ peers.delete(peerId);
259
+ },
260
+ read() {
261
+ const out = /* @__PURE__ */ new Map();
262
+ for (const [peerId, byAction] of peers) {
263
+ const copy = /* @__PURE__ */ new Map();
264
+ for (const [action, c] of byAction) copy.set(action, {
265
+ calls: c.calls,
266
+ reqBytes: c.reqBytes,
267
+ resBytes: c.resBytes,
268
+ raw: c.raw,
269
+ decoded: c.decoded
270
+ });
271
+ out.set(peerId, copy);
272
+ }
273
+ return out;
274
+ }
275
+ };
276
+ }
277
+ function sampleOf(reading, peerId, action) {
278
+ return reading.get(peerId)?.get(action);
279
+ }
280
+ /**
281
+ * Subtract the previous reading from the current one.
282
+ *
283
+ * A peer whose runner RESPAWNED reconnects under the same id with counters
284
+ * that went backwards. Clamped at 0, exactly as `diffSocketPlane` clamps for
285
+ * the same reason: its traffic in that window is genuinely unknown, and a
286
+ * negative number on a rate reads as a broken meter.
287
+ */
288
+ function diffCapActionCensus(before, current, topN) {
289
+ const deltas = [];
290
+ let labelledBytes = 0;
291
+ let totalBytes = 0;
292
+ for (const [peerId, byAction] of current) for (const [action, now] of byAction) {
293
+ const then = sampleOf(before, peerId, action);
294
+ const reqBytes = Math.max(0, now.reqBytes - (then?.reqBytes ?? 0));
295
+ const resBytes = Math.max(0, now.resBytes - (then?.resBytes ?? 0));
296
+ const bytes = reqBytes + resBytes;
297
+ totalBytes += bytes;
298
+ if (action === "(unlabelled)" || action === "(overflow)") continue;
299
+ labelledBytes += bytes;
300
+ if (bytes === 0) continue;
301
+ deltas.push({
302
+ peerId,
303
+ action,
304
+ calls: Math.max(0, now.calls - (then?.calls ?? 0)),
305
+ reqBytes,
306
+ resBytes,
307
+ raw: Math.max(0, now.raw - (then?.raw ?? 0)),
308
+ decoded: Math.max(0, now.decoded - (then?.decoded ?? 0))
309
+ });
310
+ }
311
+ return {
312
+ top: deltas.toSorted((a, b) => b.reqBytes + b.resBytes - (a.reqBytes + a.resBytes) || a.peerId.localeCompare(b.peerId) || a.action.localeCompare(b.action)).slice(0, topN),
313
+ labelledBytes,
314
+ totalBytes
315
+ };
316
+ }
317
+ //#endregion
158
318
  //#region src/kernel/transport/socket-traffic.ts
159
319
  function createSocketDirectionCounters() {
160
320
  return {
@@ -316,10 +476,12 @@ function createSocketPlaneReader(sources) {
316
476
  });
317
477
  }
318
478
  const forward = registry.readForwardCensus?.();
479
+ const actions = registry.readActionCensus?.();
319
480
  return {
320
481
  peers,
321
482
  peersConnected: listed.length,
322
- ...forward === void 0 ? {} : { forward }
483
+ ...forward === void 0 ? {} : { forward },
484
+ ...actions === void 0 ? {} : { actions }
323
485
  };
324
486
  } catch {
325
487
  return;
@@ -422,6 +584,7 @@ function diffSocketPlane(baseline, current, topN = 5) {
422
584
  if (peerMessages(delta) > 0) deltas.push(delta);
423
585
  }
424
586
  const forward = diffForward(current.forward, baseline.forward);
587
+ const actions = current.actions === void 0 ? void 0 : diffCapActionCensus(baseline.actions ?? EMPTY_CAP_ACTION_READING, current.actions, 5);
425
588
  return {
426
589
  peersConnected: current.peersConnected,
427
590
  peersMeasured: current.peers.length,
@@ -430,7 +593,8 @@ function diffSocketPlane(baseline, current, topN = 5) {
430
593
  top: deltas.toSorted((a, b) => peerMessages(b) - peerMessages(a) || a.peerId.localeCompare(b.peerId)).slice(0, topN),
431
594
  topBytes: deltas.toSorted((a, b) => peerBytes(b) - peerBytes(a) || a.peerId.localeCompare(b.peerId)).slice(0, topN),
432
595
  queued: readSocketQueues(current),
433
- ...forward === void 0 ? {} : { forward }
596
+ ...forward === void 0 ? {} : { forward },
597
+ ...actions === void 0 ? {} : { actions }
434
598
  };
435
599
  }
436
600
  function createSocketPlaneMeter(reader, topN = 5) {
@@ -441,7 +605,8 @@ function createSocketPlaneMeter(reader, topN = 5) {
441
605
  const window = diffSocketPlane(baseline, current, topN);
442
606
  baseline = {
443
607
  peers: new Map(current.peers.map((p) => [p.peerId, p])),
444
- ...current.forward === void 0 ? {} : { forward: current.forward }
608
+ ...current.forward === void 0 ? {} : { forward: current.forward },
609
+ ...current.actions === void 0 ? {} : { actions: current.actions }
445
610
  };
446
611
  return window;
447
612
  } };
@@ -478,6 +643,24 @@ function formatPeer(delta) {
478
643
  return `${delta.peerId}:tx=${delta.tx.reqMessages}/${delta.tx.resMessages}/${delta.tx.evtMessages}:rx=${delta.rx.reqMessages}/${delta.rx.resMessages}/${delta.rx.evtMessages}:txkB=${formatPeerBytes(delta.tx)}:rxkB=${formatPeerBytes(delta.rx)}`;
479
644
  }
480
645
  /**
646
+ * One named action: `<peer>!<cap>.<method>:<kB>kB/<calls>:r<raw>/d<decoded>`.
647
+ *
648
+ * `!` separates the peer from the action because `.` already separates cap
649
+ * from method and a single delimiter for both would make the token ambiguous
650
+ * to split.
651
+ *
652
+ * The raw/decoded pair is the half that did not exist anywhere before D456.
653
+ * `socketFwd=` answers it for the whole plane — 30 349/5 051 on this hub — and
654
+ * a plane-wide ratio cannot tell a method that is entirely forwarded from one
655
+ * that is entirely decoded, which is the difference between bytes hub-main
656
+ * copies and bytes hub-main reads. The census pays for the two counters it
657
+ * takes; the conclusion they buy is which of the line's megabytes are actually
658
+ * expensive.
659
+ */
660
+ function formatAction(entry) {
661
+ return `${entry.peerId}!${entry.action}:${kb$1(entry.reqBytes + entry.resBytes)}kB/${entry.calls}:r${entry.raw}/d${entry.decoded}`;
662
+ }
663
+ /**
481
664
  * The suffix appended to a `[mem]` line — leading space included, empty when
482
665
  * this process has no local socket plane.
483
666
  *
@@ -503,7 +686,7 @@ function formatSocketPlane(window) {
503
686
  const named = new Set(window.top.map((p) => p.peerId));
504
687
  const topBytes = window.topBytes.filter((p) => !named.has(p.peerId)).map(formatPeer).join(",");
505
688
  const queuedTop = window.queued.top.map((p) => `${p.peerId}:${kb$1(p.bytes)}`).join(",");
506
- return ` socketPeers=${window.peersMeasured}/${window.peersConnected} socketTx=${formatDirection(window.tx)} socketRx=${formatDirection(window.rx)}` + (top.length === 0 ? "" : ` socketTop=${top}`) + (topBytes.length === 0 ? "" : ` socketTopBytes=${topBytes}`) + ` socketQueued=${kb$1(window.queued.totalBytes)}kB` + (window.queued.unmeasured === 0 ? "" : ` socketQueuedUnmeasured=${window.queued.unmeasured}`) + (queuedTop.length === 0 ? "" : ` socketQueuedTop=${queuedTop}`) + (window.forward === void 0 ? "" : ` socketFwd=${window.forward.raw}/${window.forward.decoded}`);
689
+ return ` socketPeers=${window.peersMeasured}/${window.peersConnected} socketTx=${formatDirection(window.tx)} socketRx=${formatDirection(window.rx)}` + (top.length === 0 ? "" : ` socketTop=${top}`) + (topBytes.length === 0 ? "" : ` socketTopBytes=${topBytes}`) + ` socketQueued=${kb$1(window.queued.totalBytes)}kB` + (window.queued.unmeasured === 0 ? "" : ` socketQueuedUnmeasured=${window.queued.unmeasured}`) + (queuedTop.length === 0 ? "" : ` socketQueuedTop=${queuedTop}`) + (window.forward === void 0 ? "" : ` socketFwd=${window.forward.raw}/${window.forward.decoded}`) + (window.actions === void 0 ? "" : ` socketActions=${kb$1(window.actions.labelledBytes)}/${kb$1(window.actions.totalBytes)}kB` + (window.actions.top.length === 0 ? "" : ` socketTopActions=${window.actions.top.map(formatAction).join(",")}`));
507
690
  }
508
691
  //#endregion
509
692
  //#region src/kernel/moleculer/mesh-queue-report.ts
@@ -1139,6 +1322,125 @@ function formatArrayBufferCensus(label, report, context) {
1139
1322
  return `[mem] ${label} arrayBuffer census: live=${live}MB in ${report.count} ArrayBuffers (raw arrayBuffers=${context.rawMb}MB at the trigger → ${verdict}) top sizes: ${report.topSizes.map(formatExact).join(", ") || "(none)"}; buckets: ${report.buckets.map(formatBucket).join(", ") || "(none)"}; detached=${report.detached} took=${context.tookMs}ms — cost: ONE forced full GC (the same pause as a reclaim pass), walked in memory, nothing serialised, nothing written; trigger: ${context.reason}`;
1140
1323
  }
1141
1324
  //#endregion
1325
+ //#region src/kernel/gc-census.ts
1326
+ function countsOf(entries, kinds) {
1327
+ let majors = 0;
1328
+ let minors = 0;
1329
+ let incrementals = 0;
1330
+ let pauseMs = 0;
1331
+ for (const e of entries) {
1332
+ if (e.kind === kinds.major) majors++;
1333
+ else if (e.kind === kinds.minor) minors++;
1334
+ else if (e.kind === kinds.incremental) incrementals++;
1335
+ pauseMs += e.durationMs;
1336
+ }
1337
+ return {
1338
+ majors,
1339
+ minors,
1340
+ incrementals,
1341
+ pauseMs,
1342
+ windowMs: 0
1343
+ };
1344
+ }
1345
+ /**
1346
+ * Build a census over an injected observer.
1347
+ *
1348
+ * Returns `undefined` when the observer cannot be installed — the caller then
1349
+ * prints nothing, which is the honest reading. It must never degrade into a
1350
+ * census that reports zero collections: a process whose GC is not being
1351
+ * observed and a process that is not collecting look identical on the line, and
1352
+ * they are the two answers furthest apart.
1353
+ */
1354
+ function createGcCensus(install, kinds, startedAt) {
1355
+ let pending = [];
1356
+ const stopObserving = install((entry) => {
1357
+ pending.push(entry);
1358
+ });
1359
+ if (stopObserving === void 0) return void 0;
1360
+ let windowStart = startedAt;
1361
+ return {
1362
+ read: (at) => {
1363
+ const windowMs = at - windowStart;
1364
+ if (windowMs < 1e3) return null;
1365
+ const taken = pending;
1366
+ pending = [];
1367
+ windowStart = at;
1368
+ return {
1369
+ ...countsOf(taken, kinds),
1370
+ windowMs
1371
+ };
1372
+ },
1373
+ stop: () => {
1374
+ stopObserving();
1375
+ pending = [];
1376
+ }
1377
+ };
1378
+ }
1379
+ /**
1380
+ * The observer this process actually gets.
1381
+ *
1382
+ * Everything that can fail is inside the try: a runtime without
1383
+ * `perf_hooks`, without the `gc` entry type, or without the kind constants
1384
+ * yields `undefined` from `install`, and {@link createGcCensus} then declines
1385
+ * to exist rather than reporting zeros.
1386
+ */
1387
+ function nodeGcObserver() {
1388
+ return {
1389
+ kinds: readKinds({
1390
+ major: 4,
1391
+ minor: 1,
1392
+ incremental: 8
1393
+ }),
1394
+ install: (observe) => {
1395
+ try {
1396
+ const observer = new (process.getBuiltinModule("node:perf_hooks")).PerformanceObserver((list) => {
1397
+ for (const entry of list.getEntries()) {
1398
+ const detail = "detail" in entry ? entry.detail : void 0;
1399
+ observe({
1400
+ kind: typeof detail === "object" && detail !== null && "kind" in detail && typeof detail.kind === "number" ? detail.kind : -1,
1401
+ durationMs: entry.duration
1402
+ });
1403
+ }
1404
+ });
1405
+ observer.observe({ entryTypes: ["gc"] });
1406
+ return () => {
1407
+ observer.disconnect();
1408
+ };
1409
+ } catch {
1410
+ return;
1411
+ }
1412
+ }
1413
+ };
1414
+ }
1415
+ function readKinds(fallback) {
1416
+ try {
1417
+ const c = process.getBuiltinModule("node:perf_hooks").constants;
1418
+ return {
1419
+ major: c.NODE_PERFORMANCE_GC_MAJOR,
1420
+ minor: c.NODE_PERFORMANCE_GC_MINOR,
1421
+ incremental: c.NODE_PERFORMANCE_GC_INCREMENTAL
1422
+ };
1423
+ } catch {
1424
+ return fallback;
1425
+ }
1426
+ }
1427
+ /**
1428
+ * The two fields, APPENDED LAST on the `[mem]` line.
1429
+ *
1430
+ * D446's rule: no existing field moves, so every Loki prefix written since
1431
+ * 2026-08-29 still matches. `gc=` prints even when nothing was collected — a
1432
+ * window with no collections is a reading, and it is the reading that says a
1433
+ * process is idle rather than unobserved. `gcPauseMs=` is the MAIN-THREAD
1434
+ * pause only; the concurrent marking that cost hub-main 70 % of its CPU is on
1435
+ * the platform workers and no in-process counter sees it, which is why the
1436
+ * field is named for the thread it describes (D456, part 4).
1437
+ */
1438
+ function formatGcCensus(window) {
1439
+ if (window === null || window === void 0) return "";
1440
+ const perMin = (n) => window.windowMs <= 0 ? "?" : (n / (window.windowMs / 6e4)).toFixed(1);
1441
+ return ` gc=maj${window.majors}/min${window.minors}/inc${window.incrementals}@${Math.round(window.windowMs / 1e3)}s gcMajPerMin=${perMin(window.majors)} gcPauseMs=${Math.round(window.pauseMs)}`;
1442
+ }
1443
+ //#endregion
1142
1444
  //#region src/kernel/heap-watch.ts
1143
1445
  /**
1144
1446
  * heap-watch — hub-main's own memory, on the record, and returned to the OS.
@@ -1735,6 +2037,8 @@ function startHeapWatch(label = HUB_MAIN_HEAP_WATCH_LABEL, sink = consoleSink, i
1735
2037
  const socketPlane = probes?.socketPlane === void 0 ? void 0 : createSocketPlaneMeter(probes.socketPlane);
1736
2038
  const readMemory = reclaimOptions?.readMemory ?? (() => process.memoryUsage());
1737
2039
  const now = reclaimOptions?.now ?? (() => Date.now());
2040
+ const gcObserver = probes?.gcObserver ?? nodeGcObserver();
2041
+ const gcCensus = createGcCensus(gcObserver.install, gcObserver.kinds, now());
1738
2042
  const triggerMb = reclaimOptions?.triggerMb ?? 1024;
1739
2043
  const minIntervalMs = reclaimOptions?.minIntervalMs ?? 12e4;
1740
2044
  const steadyStateIntervalMs = reclaimOptions?.steadyStateIntervalMs ?? 6e5;
@@ -1837,7 +2141,7 @@ function startHeapWatch(label = HUB_MAIN_HEAP_WATCH_LABEL, sink = consoleSink, i
1837
2141
  const due = at - lastLoggedAt >= intervalMs;
1838
2142
  if (mode === "escalated" || due) {
1839
2143
  lastLoggedAt = at;
1840
- const line = format(label, sample, loopDelay?.read(), budgetMb, `${formatHeapSpaces(readSpaces())}${formatEventPlane(eventPlane?.read())}` + formatSocketPlane(socketPlane?.read()) + formatMeshQueue(meshQueue?.()));
2144
+ const line = format(label, sample, loopDelay?.read(), budgetMb, `${formatHeapSpaces(readSpaces())}${formatEventPlane(eventPlane?.read())}` + formatSocketPlane(socketPlane?.read()) + formatMeshQueue(meshQueue?.()) + formatGcCensus(gcCensus?.read(at)));
1841
2145
  if (sample.nearLimit) sink.warn(`${line} — APPROACHING HEAP LIMIT`);
1842
2146
  else if (mode === "escalated") sink.warn(`${line} — heap elevated, sampling every ${probeIntervalMs}ms`);
1843
2147
  else sink.info(line);
@@ -1894,6 +2198,7 @@ function startHeapWatch(label = HUB_MAIN_HEAP_WATCH_LABEL, sink = consoleSink, i
1894
2198
  stopped = true;
1895
2199
  clearInterval(timer);
1896
2200
  loopDelay?.stop();
2201
+ gcCensus?.stop();
1897
2202
  };
1898
2203
  }
1899
2204
  /**
@@ -5915,6 +6220,8 @@ var SocketChannel = class {
5915
6220
  txCounters = createSocketDirectionCounters();
5916
6221
  /** Frames read from the peer, cumulative, split by kind. */
5917
6222
  rxCounters = createSocketDirectionCounters();
6223
+ /** See {@link CapActionChannelObserver}. Absent = no per-action census. */
6224
+ actionObserver = null;
5918
6225
  constructor(socket) {
5919
6226
  this.socket = socket;
5920
6227
  socket.on("data", (chunk) => this.onData(chunk));
@@ -5945,16 +6252,26 @@ var SocketChannel = class {
5945
6252
  }, timeoutMs);
5946
6253
  timer.unref?.();
5947
6254
  }
6255
+ const label = this.labelSafely(body);
5948
6256
  this.pending.set(id, {
5949
6257
  resolve,
5950
6258
  reject,
5951
- timer
6259
+ timer,
6260
+ action: null
5952
6261
  });
5953
- this.send({
6262
+ const reqBytes = this.send({
5954
6263
  k: "req",
5955
6264
  id,
5956
6265
  body
5957
6266
  }, opts?.payload);
6267
+ const entry = this.pending.get(id);
6268
+ if (entry !== void 0 && label !== void 0) this.pending.set(id, {
6269
+ ...entry,
6270
+ action: {
6271
+ label,
6272
+ reqBytes
6273
+ }
6274
+ });
5958
6275
  });
5959
6276
  }
5960
6277
  emit(body) {
@@ -5964,6 +6281,36 @@ var SocketChannel = class {
5964
6281
  body
5965
6282
  });
5966
6283
  }
6284
+ /**
6285
+ * Wire the per-action census. Only one observer is active at a time; an
6286
+ * unwired channel records nothing at all (never zeros).
6287
+ */
6288
+ observeActions(observer) {
6289
+ this.actionObserver = observer;
6290
+ }
6291
+ /**
6292
+ * The label for one envelope, or `undefined` when there is nothing to
6293
+ * record. Wrapped: a broken labeller must never fail the call it watches —
6294
+ * the same discipline `LocalChildRegistry.recordCapUsage` applies, and for
6295
+ * the same reason.
6296
+ */
6297
+ labelSafely(body) {
6298
+ const obs = this.actionObserver;
6299
+ if (obs === null) return void 0;
6300
+ try {
6301
+ return obs.label(body);
6302
+ } catch {
6303
+ return null;
6304
+ }
6305
+ }
6306
+ /** Settle one request/response pair on the census. Never throws. */
6307
+ recordAction(label, reqBytes, resBytes) {
6308
+ const obs = this.actionObserver;
6309
+ if (obs === null) return;
6310
+ try {
6311
+ obs.record(label, reqBytes, resBytes);
6312
+ } catch {}
6313
+ }
5967
6314
  /** Replace the request handler. Only one handler is active at a time. */
5968
6315
  onRequest(handler) {
5969
6316
  this.requestHandler = handler;
@@ -6011,21 +6358,27 @@ var SocketChannel = class {
6011
6358
  * are never copied into the head. A forwarded payload is a view into the
6012
6359
  * frame it arrived on, and that frame's buffer is never mutated, so handing
6013
6360
  * the view to the socket is safe.
6361
+ *
6362
+ * Returns the on-the-wire bytes it charged — the same number the per-kind
6363
+ * counter got, so the per-action census can never disagree with the per-peer
6364
+ * one. `0` when the channel is closed and nothing was written.
6014
6365
  */
6015
6366
  send(frame, payload) {
6016
- if (this.closed) return;
6367
+ if (this.closed) return 0;
6017
6368
  if (payload === void 0) {
6018
6369
  const encoded = encodeFrame(frame);
6019
6370
  recordSocketFrame(this.txCounters, frame.k, encoded.byteLength);
6020
6371
  this.socket.write(encoded);
6021
- return;
6372
+ return encoded.byteLength;
6022
6373
  }
6023
6374
  const head = encodeFrameHead(frame, payload);
6024
- recordSocketFrame(this.txCounters, frame.k, head.byteLength + payload.byteLength);
6375
+ const bytes = head.byteLength + payload.byteLength;
6376
+ recordSocketFrame(this.txCounters, frame.k, bytes);
6025
6377
  this.socket.cork();
6026
6378
  this.socket.write(head);
6027
6379
  this.socket.write(payload);
6028
6380
  this.socket.uncork();
6381
+ return bytes;
6029
6382
  }
6030
6383
  onData(chunk) {
6031
6384
  const frames = this.decoder.push(chunk);
@@ -6044,28 +6397,31 @@ var SocketChannel = class {
6044
6397
  async handleFrame(frame, wireBytes) {
6045
6398
  recordSocketFrame(this.rxCounters, frame.k, wireBytes);
6046
6399
  if (frame.k === "req") {
6400
+ const label = this.labelSafely(frame.body);
6401
+ let resBytes = 0;
6047
6402
  try {
6048
6403
  const result = await this.requestHandler(frame.body, frame.pl);
6049
- if (result instanceof PayloadReply) this.send({
6404
+ if (result instanceof PayloadReply) resBytes = this.send({
6050
6405
  k: "res",
6051
6406
  id: frame.id,
6052
6407
  ok: true,
6053
6408
  body: result.body
6054
6409
  }, result.payload);
6055
- else this.send({
6410
+ else resBytes = this.send({
6056
6411
  k: "res",
6057
6412
  id: frame.id,
6058
6413
  ok: true,
6059
6414
  body: result
6060
6415
  });
6061
6416
  } catch (err) {
6062
- this.send({
6417
+ resBytes = this.send({
6063
6418
  k: "res",
6064
6419
  id: frame.id,
6065
6420
  ok: false,
6066
6421
  err: err instanceof Error ? err.message : String(err)
6067
6422
  });
6068
6423
  }
6424
+ if (label !== void 0) this.recordAction(label, wireBytes, resBytes);
6069
6425
  return;
6070
6426
  }
6071
6427
  if (frame.k === "res") {
@@ -6073,6 +6429,7 @@ var SocketChannel = class {
6073
6429
  if (!p) return;
6074
6430
  this.pending.delete(frame.id);
6075
6431
  if (p.timer !== null) clearTimeout(p.timer);
6432
+ if (p.action !== null) this.recordAction(p.action.label, p.action.reqBytes, wireBytes);
6076
6433
  if (!frame.ok) p.reject(new Error(frame.err));
6077
6434
  else if (frame.pl !== void 0) p.resolve(new PayloadReply(frame.body, frame.pl));
6078
6435
  else p.resolve(frame.body);
@@ -6626,6 +6983,64 @@ function deliverShared(state, event) {
6626
6983
  }
6627
6984
  }
6628
6985
  //#endregion
6986
+ //#region src/kernel/transport/cap-child-index.ts
6987
+ /** Separator that cannot occur in a kebab cap name, so the key is unambiguous. */
6988
+ var DEVICE_KEY_SEPARATOR = "\0";
6989
+ var NO_CANDIDATES = Object.freeze([]);
6990
+ var MapCapChildIndex = class {
6991
+ deviceOwners;
6992
+ singletons;
6993
+ constructor(deviceOwners, singletons) {
6994
+ this.deviceOwners = deviceOwners;
6995
+ this.singletons = singletons;
6996
+ }
6997
+ deviceOwner(capName, deviceId) {
6998
+ return this.deviceOwners.get(`${capName}${DEVICE_KEY_SEPARATOR}${deviceId}`) ?? null;
6999
+ }
7000
+ singletonCandidates(capName) {
7001
+ return this.singletons.get(capName) ?? NO_CANDIDATES;
7002
+ }
7003
+ };
7004
+ /**
7005
+ * Build the `(cap, device?) → child` index from the connected children.
7006
+ *
7007
+ * A PURE function of what it is handed — it captures nothing, subscribes to
7008
+ * nothing and cannot be updated in place. That is the whole safety argument
7009
+ * (D3, D457): the only way to change what it says is to build a new one from
7010
+ * the `children` map, so an index can never name a child that map has already
7011
+ * dropped. An incremental index — add on register, remove on close — would be
7012
+ * a second registry that can disagree with the first, and a stale one routes
7013
+ * to a dead runner, which is strictly worse than a slow scan.
7014
+ *
7015
+ * Cost: O(children × descriptors), paid once per mutation of the children map
7016
+ * (a register, a re-register, a disconnect) rather than once per cap call.
7017
+ *
7018
+ * The two tiers stay separate, exactly as the scan had them: a device lookup
7019
+ * is never answered from a deviceId-less descriptor. `resolveChildId` owns
7020
+ * the fallback from tier 1 to tier 2, and folding it in here would make it
7021
+ * unreachable.
7022
+ */
7023
+ function buildCapChildIndex(entries) {
7024
+ const deviceOwners = /* @__PURE__ */ new Map();
7025
+ const singletons = /* @__PURE__ */ new Map();
7026
+ for (const entry of entries) {
7027
+ const namedForThisChild = /* @__PURE__ */ new Set();
7028
+ for (const cap of entry.caps) {
7029
+ if (cap.deviceId === void 0) {
7030
+ if (namedForThisChild.has(cap.capName)) continue;
7031
+ namedForThisChild.add(cap.capName);
7032
+ const candidates = singletons.get(cap.capName);
7033
+ if (candidates === void 0) singletons.set(cap.capName, [entry.childId]);
7034
+ else candidates.push(entry.childId);
7035
+ continue;
7036
+ }
7037
+ const key = `${cap.capName}${DEVICE_KEY_SEPARATOR}${cap.deviceId}`;
7038
+ if (!deviceOwners.has(key)) deviceOwners.set(key, entry.childId);
7039
+ }
7040
+ }
7041
+ return new MapCapChildIndex(deviceOwners, singletons);
7042
+ }
7043
+ //#endregion
6629
7044
  //#region src/kernel/transport/cap-routing-hints.ts
6630
7045
  /** Lift {@link CapRoutingHints} from a call's args. Never throws. */
6631
7046
  function liftRoutingHints(args) {
@@ -6637,8 +7052,6 @@ function liftRoutingHints(args) {
6637
7052
  ...typeof addonId === "string" && addonId.length > 0 ? { addonId } : {}
6638
7053
  };
6639
7054
  }
6640
- //#endregion
6641
- //#region src/kernel/transport/local-child-registry.ts
6642
7055
  function readFanoutMode() {
6643
7056
  const raw = process.env.CAMSTACK_UDS_EVENT_FANOUT;
6644
7057
  if (raw === "shadow" || raw === "broadcast") return raw;
@@ -6679,6 +7092,14 @@ var LocalChildRegistry = class {
6679
7092
  /** See {@link ForwardCensus}. Mutable counters on the hot path, by design. */
6680
7093
  forwardedRaw = 0;
6681
7094
  forwardedDecoded = 0;
7095
+ /**
7096
+ * The per-ACTION byte census (D456). `ForwardCensus` above is the same
7097
+ * question asked of the whole plane; this one asks it per `<cap>.<method>`,
7098
+ * beside the bytes that method actually moved. Both are kept: `socketFwd=`
7099
+ * says whether the negotiation is working at all, and a `raw=0` on ONE
7100
+ * method with `raw>0` on its neighbours is a different fault.
7101
+ */
7102
+ actionCensus = createCapActionCensus();
6682
7103
  /** See {@link LocalChildRegistryOptions.capTimeoutMs}. */
6683
7104
  capTimeoutMs;
6684
7105
  /** See {@link LocalChildRegistryOptions.capUsageObserver}. */
@@ -6692,6 +7113,12 @@ var LocalChildRegistry = class {
6692
7113
  /** Last pattern-set string logged per child, to dedup the INFO line. */
6693
7114
  loggedPatternSet = /* @__PURE__ */ new Map();
6694
7115
  /**
7116
+ * Derived `(cap, device?) → child` index over {@link children}, or `null`
7117
+ * when it must be rebuilt. See {@link capIndex} for why it is a cache and
7118
+ * never a registry (D3, D457).
7119
+ */
7120
+ capChildIndex = null;
7121
+ /**
6695
7122
  * Accepts either a plain positional `server` argument (backward-compatible)
6696
7123
  * or a full `LocalChildRegistryOptions` object.
6697
7124
  *
@@ -6772,6 +7199,21 @@ var LocalChildRegistry = class {
6772
7199
  };
6773
7200
  }
6774
7201
  /**
7202
+ * Cumulative per-action byte census: peer → `<cap>.<method>` → bytes, calls
7203
+ * and the raw/decoded split. A COPY (`cap-action-census.ts` explains why it
7204
+ * must be one); the heartbeat subtracts the previous reading.
7205
+ *
7206
+ * This is the instrument D454 closed by asking for. `socketTopBytes=` names
7207
+ * the peer that moves the bytes and `txkB=` says they are responses; neither
7208
+ * can say WHICH method originates them, and after raw-forward the bytes that
7209
+ * cross are no longer the proxy for what hub-main pays — 85.7 % of sibling
7210
+ * calls cross unread. What costs is what hub-main LOOKS at, and that is the
7211
+ * `decoded` half of an entry, next to the bytes it carried.
7212
+ */
7213
+ readActionCensus() {
7214
+ return this.actionCensus.read();
7215
+ }
7216
+ /**
6775
7217
  * The regime the counters above were produced under, read once from
6776
7218
  * `CAMSTACK_UDS_EVENT_FANOUT` at construction.
6777
7219
  *
@@ -6885,11 +7327,12 @@ var LocalChildRegistry = class {
6885
7327
  * compete for the same capName.
6886
7328
  */
6887
7329
  resolveChildId(capName, deviceId) {
7330
+ const index = this.capIndex();
6888
7331
  if (deviceId !== void 0) {
6889
- const deviceOwner = this.findChildId((cap) => cap.capName === capName && cap.deviceId === deviceId);
7332
+ const deviceOwner = index.deviceOwner(capName, deviceId);
6890
7333
  if (deviceOwner !== null) return deviceOwner;
6891
7334
  }
6892
- const candidates = this.findAllChildIds((cap) => cap.capName === capName && cap.deviceId === void 0);
7335
+ const candidates = index.singletonCandidates(capName);
6893
7336
  if (candidates.length === 0) return null;
6894
7337
  if (candidates.length === 1) return candidates[0];
6895
7338
  const preferredAddonId = this.getActiveSingletonAddonId?.(capName) ?? null;
@@ -6922,16 +7365,37 @@ var LocalChildRegistry = class {
6922
7365
  });
6923
7366
  } catch {}
6924
7367
  }
6925
- /** First child whose cap manifest contains a descriptor matching `predicate`. */
6926
- findChildId(predicate) {
6927
- for (const entry of this.children.values()) if (entry.caps.some(predicate)) return entry.childId;
6928
- return null;
7368
+ /**
7369
+ * The cap index over the CURRENT children, rebuilt on first use after any
7370
+ * mutation of {@link children}.
7371
+ *
7372
+ * This replaced a linear walk of every child's cap manifest per
7373
+ * `cap-call-out`, measured at **7.1 % of hub-main's busy main thread**
7374
+ * across 39 children (D456). Why it did not exist before is the whole
7375
+ * design: what it indexes moves — a runner is replaced on every update, a
7376
+ * crash respawns one, a child re-registers with a replacement manifest after
7377
+ * init — and an index that names a dead child routes work into a socket
7378
+ * nobody is reading, which is strictly worse than a slow scan.
7379
+ *
7380
+ * So it is not maintained; it is DISCARDED. `buildCapChildIndex` is a pure
7381
+ * function of `children.values()`, the only two writers of that map
7382
+ * ({@link invalidateCapIndex}'s call sites) drop the index in the same
7383
+ * statement, and nothing else can construct one. There is no add-on-register
7384
+ * / remove-on-close path that could disagree with the map — i.e. no shadow
7385
+ * registry (D3): the map remains the single authority and this holds no fact
7386
+ * it does not.
7387
+ *
7388
+ * The operator's active-singleton preference is deliberately NOT indexed —
7389
+ * it changes without any child connecting or leaving, so `resolveChildId`
7390
+ * reads it live and the index only supplies the candidate list.
7391
+ */
7392
+ capIndex() {
7393
+ if (this.capChildIndex === null) this.capChildIndex = buildCapChildIndex(this.children.values());
7394
+ return this.capChildIndex;
6929
7395
  }
6930
- /** Every child whose cap manifest contains a descriptor matching `predicate`. */
6931
- findAllChildIds(predicate) {
6932
- const out = [];
6933
- for (const entry of this.children.values()) if (entry.caps.some(predicate)) out.push(entry.childId);
6934
- return out;
7396
+ /** Drop the derived index. MUST follow every write to {@link children}. */
7397
+ invalidateCapIndex() {
7398
+ this.capChildIndex = null;
6935
7399
  }
6936
7400
  /**
6937
7401
  * Does the named child currently provide `(capName, deviceId?)`?
@@ -7127,6 +7591,14 @@ var LocalChildRegistry = class {
7127
7591
  onConnection(channel) {
7128
7592
  let childId = null;
7129
7593
  const incarnation = this.nextIncarnation++;
7594
+ channel.observeActions?.({
7595
+ label: capActionLabel,
7596
+ record: (label, reqBytes, resBytes) => {
7597
+ const peerId = childId ?? "(pre-register)";
7598
+ if (label === null) this.actionCensus.recordUnlabelled(peerId, reqBytes + resBytes);
7599
+ else this.actionCensus.record(peerId, label, reqBytes, resBytes);
7600
+ }
7601
+ });
7130
7602
  channel.onEvent((body) => {
7131
7603
  const msg = body;
7132
7604
  if (msg.kind === "event") {
@@ -7169,6 +7641,7 @@ var LocalChildRegistry = class {
7169
7641
  incarnation,
7170
7642
  rawForward: msg.rawForward === true
7171
7643
  });
7644
+ this.invalidateCapIndex();
7172
7645
  this.logPatternSet(msg.childId, eventPatterns);
7173
7646
  this.registeredHandler({
7174
7647
  childId: msg.childId,
@@ -7200,6 +7673,8 @@ var LocalChildRegistry = class {
7200
7673
  const addonPinned = pinnedNodeId === void 0 && this.isAddonPinnedCall?.(out.capName, out.method, hints) === true;
7201
7674
  const target = !(out.native === true) && !aggregated && !addonPinned && (pinnedNodeId === void 0 || pinTargetsThisNode) ? this.resolveChildId(out.capName, out.deviceId) : null;
7202
7675
  this.recordCapUsage(childId, target, out.capName, out.method);
7676
+ const actionPeer = childId ?? "(pre-register)";
7677
+ const actionLabel = `${out.capName}.${out.method}`;
7203
7678
  if (target !== null) {
7204
7679
  if (!this.egressRoutedCaps.has(out.capName)) {
7205
7680
  this.egressRoutedCaps.add(out.capName);
@@ -7208,6 +7683,7 @@ var LocalChildRegistry = class {
7208
7683
  const entry = this.children.get(target);
7209
7684
  if (payload !== void 0 && entry !== void 0 && entry.rawForward) {
7210
7685
  this.forwardedRaw += 1;
7686
+ this.actionCensus.recordForward(actionPeer, actionLabel, "raw");
7211
7687
  const forward = {
7212
7688
  kind: "cap-call",
7213
7689
  capName: out.capName,
@@ -7222,9 +7698,12 @@ var LocalChildRegistry = class {
7222
7698
  });
7223
7699
  }
7224
7700
  this.forwardedDecoded += 1;
7225
- return this.callCap(buildInput());
7701
+ this.actionCensus.recordForward(actionPeer, actionLabel, "decoded");
7702
+ const input = buildInput();
7703
+ return entry !== void 0 ? this.callCapOnChild(target, input) : this.callCap(input);
7226
7704
  }
7227
7705
  this.forwardedDecoded += 1;
7706
+ this.actionCensus.recordForward(actionPeer, actionLabel, "decoded");
7228
7707
  if (this.onUnownedCall !== void 0) return this.onUnownedCall(buildInput());
7229
7708
  throw new Error(`${UDS_NO_ROUTE_PREFIX}: cap-call-out has no local provider for "${out.capName}" and no fallback`);
7230
7709
  }
@@ -7247,7 +7726,9 @@ var LocalChildRegistry = class {
7247
7726
  return;
7248
7727
  }
7249
7728
  this.children.delete(childId);
7729
+ this.invalidateCapIndex();
7250
7730
  this.childEventStats.delete(childId);
7731
+ this.actionCensus.forget(childId);
7251
7732
  this.loggedPatternSet.delete(childId);
7252
7733
  this.goneHandler(childId, incarnation);
7253
7734
  });
@@ -10747,6 +11228,18 @@ Object.defineProperty(exports, "AddonDepsManager", {
10747
11228
  return AddonDepsManager;
10748
11229
  }
10749
11230
  });
11231
+ Object.defineProperty(exports, "CAP_ACTION_OVERFLOW_LABEL", {
11232
+ enumerable: true,
11233
+ get: function() {
11234
+ return CAP_ACTION_OVERFLOW_LABEL;
11235
+ }
11236
+ });
11237
+ Object.defineProperty(exports, "CAP_ACTION_UNLABELLED", {
11238
+ enumerable: true,
11239
+ get: function() {
11240
+ return CAP_ACTION_UNLABELLED;
11241
+ }
11242
+ });
10750
11243
  Object.defineProperty(exports, "CapRouteError", {
10751
11244
  enumerable: true,
10752
11245
  get: function() {
@@ -10789,6 +11282,12 @@ Object.defineProperty(exports, "DeviceRegistry", {
10789
11282
  return DeviceRegistry;
10790
11283
  }
10791
11284
  });
11285
+ Object.defineProperty(exports, "EMPTY_CAP_ACTION_READING", {
11286
+ enumerable: true,
11287
+ get: function() {
11288
+ return EMPTY_CAP_ACTION_READING;
11289
+ }
11290
+ });
10792
11291
  Object.defineProperty(exports, "EMPTY_SOCKET_DIRECTION", {
10793
11292
  enumerable: true,
10794
11293
  get: function() {
@@ -10885,6 +11384,12 @@ Object.defineProperty(exports, "LocalChildRegistry", {
10885
11384
  return LocalChildRegistry;
10886
11385
  }
10887
11386
  });
11387
+ Object.defineProperty(exports, "MAX_CAP_ACTIONS_PER_PEER", {
11388
+ enumerable: true,
11389
+ get: function() {
11390
+ return MAX_CAP_ACTIONS_PER_PEER;
11391
+ }
11392
+ });
10888
11393
  Object.defineProperty(exports, "MESH_QUEUE_TOP_N", {
10889
11394
  enumerable: true,
10890
11395
  get: function() {
@@ -11041,6 +11546,12 @@ Object.defineProperty(exports, "callWithServiceDiscovery", {
11041
11546
  return callWithServiceDiscovery;
11042
11547
  }
11043
11548
  });
11549
+ Object.defineProperty(exports, "capActionLabel", {
11550
+ enumerable: true,
11551
+ get: function() {
11552
+ return capActionLabel;
11553
+ }
11554
+ });
11044
11555
  Object.defineProperty(exports, "capActionName", {
11045
11556
  enumerable: true,
11046
11557
  get: function() {
@@ -11113,6 +11624,12 @@ Object.defineProperty(exports, "createBrokerDeviceManagerApi", {
11113
11624
  return createBrokerDeviceManagerApi;
11114
11625
  }
11115
11626
  });
11627
+ Object.defineProperty(exports, "createCapActionCensus", {
11628
+ enumerable: true,
11629
+ get: function() {
11630
+ return createCapActionCensus;
11631
+ }
11632
+ });
11116
11633
  Object.defineProperty(exports, "createDeferredHeapWatchSink", {
11117
11634
  enumerable: true,
11118
11635
  get: function() {
@@ -11239,6 +11756,12 @@ Object.defineProperty(exports, "deserializeTypedArrays", {
11239
11756
  return deserializeTypedArrays;
11240
11757
  }
11241
11758
  });
11759
+ Object.defineProperty(exports, "diffCapActionCensus", {
11760
+ enumerable: true,
11761
+ get: function() {
11762
+ return diffCapActionCensus;
11763
+ }
11764
+ });
11242
11765
  Object.defineProperty(exports, "diffEventPlane", {
11243
11766
  enumerable: true,
11244
11767
  get: function() {