@camstack/system 1.2.222 → 1.2.224

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 (62) 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 +2 -2
  12. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +2 -2
  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-backend.d.ts +30 -1
  42. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +0 -0
  43. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +0 -0
  44. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
  45. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
  46. package/dist/builtins/system-config/system-config.addon.js +1 -1
  47. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  48. package/dist/builtins/winston-logging/index.js +1 -1
  49. package/dist/builtins/winston-logging/index.mjs +1 -1
  50. package/dist/{custom-action-registry-DvVMHLfJ.js → custom-action-registry-BTB-LgGN.js} +1 -1
  51. package/dist/{custom-action-registry-DvtOs-tp.mjs → custom-action-registry-CdLp1P9C.mjs} +1 -1
  52. package/dist/{dist-0sWJNwme.js → dist-DdRxWA7g.js} +151 -24
  53. package/dist/{dist-T9GvfhgV.mjs → dist-DmfYrdAn.mjs} +151 -24
  54. package/dist/index.js +3 -3
  55. package/dist/index.mjs +5 -5
  56. package/dist/kernel/heap-watch.d.ts +14 -0
  57. package/dist/kernel/process-cpu-census.d.ts +74 -0
  58. package/dist/{manifest-system-deps-YYKKCKSF.js → manifest-system-deps-8x1jgPz_.js} +138 -1
  59. package/dist/{manifest-system-deps-D4cmEnqQ.mjs → manifest-system-deps-BhYmLVHw.mjs} +139 -2
  60. package/dist/{retired-settings-keys-DmVZAH9M.mjs → retired-settings-keys-B0JHsynV.mjs} +1 -1
  61. package/dist/{retired-settings-keys-Dh-XMfFx.js → retired-settings-keys-C-jOWHI0.js} +1 -1
  62. package/package.json +1 -1
@@ -1470,6 +1470,134 @@ function formatGcCensus(window) {
1470
1470
  const perMin = (n) => window.windowMs <= 0 ? "?" : (n / (window.windowMs / 6e4)).toFixed(1);
1471
1471
  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)}`;
1472
1472
  }
1473
+ /**
1474
+ * The census. Always exists — `process.cpuUsage()` is available on every
1475
+ * platform Node runs on, so unlike the GC census there is no runtime in which
1476
+ * this has nothing to report.
1477
+ */
1478
+ function createProcessCpuCensus(options) {
1479
+ let windowStart = options.startedAt;
1480
+ let cpuAtStart = options.cpuUsageUs();
1481
+ let tasksAtStart = options.readTasks();
1482
+ return { read: (at) => {
1483
+ const windowMs = at - windowStart;
1484
+ if (windowMs < 1e3) return null;
1485
+ const cpuNow = options.cpuUsageUs();
1486
+ const tasksNow = options.readTasks();
1487
+ const cpuUs = cpuNow - cpuAtStart;
1488
+ const percentOfCore = cpuUs <= 0 ? 0 : round1(cpuUs / 1e3 / windowMs * 100);
1489
+ const reading = {
1490
+ percentOfCore,
1491
+ windowMs,
1492
+ v8Workers: shareOfWorkers(tasksAtStart, tasksNow, percentOfCore)
1493
+ };
1494
+ windowStart = at;
1495
+ cpuAtStart = cpuNow;
1496
+ tasksAtStart = tasksNow;
1497
+ return reading;
1498
+ } };
1499
+ }
1500
+ /**
1501
+ * The worker share, or `null`.
1502
+ *
1503
+ * Every way this can fail to be a reading returns `null`: either snapshot
1504
+ * missing, no thread scheduled at all across the window (a share of nothing is
1505
+ * not zero percent — it is no measurement), or a delta that went BACKWARDS,
1506
+ * which means the thread set changed under us and the subtraction describes
1507
+ * nothing real.
1508
+ */
1509
+ function shareOfWorkers(before, after, percentOfCore) {
1510
+ if (before === null || after === null) return null;
1511
+ const b = sum(before);
1512
+ const a = sum(after);
1513
+ const workerTicks = a.worker - b.worker;
1514
+ const totalTicks = a.total - b.total;
1515
+ if (workerTicks < 0 || totalTicks <= 0 || workerTicks > totalTicks) return null;
1516
+ return {
1517
+ percentOfCore: round1(percentOfCore * (workerTicks / totalTicks)),
1518
+ threads: a.workerThreads
1519
+ };
1520
+ }
1521
+ var V8_WORKER_COMM = "V8Worker";
1522
+ function sum(tasks) {
1523
+ let worker = 0;
1524
+ let total = 0;
1525
+ let workerThreads = 0;
1526
+ for (const t of tasks) {
1527
+ total += t.ticks;
1528
+ if (t.comm === V8_WORKER_COMM) {
1529
+ worker += t.ticks;
1530
+ workerThreads += 1;
1531
+ }
1532
+ }
1533
+ return {
1534
+ worker,
1535
+ total,
1536
+ workerThreads
1537
+ };
1538
+ }
1539
+ function round1(n) {
1540
+ return Math.round(n * 10) / 10;
1541
+ }
1542
+ /**
1543
+ * Per-thread ticks for THIS process, or `null` where that cannot be read.
1544
+ *
1545
+ * `/proc/self/task/<tid>/stat` is `pid (comm) state ppid …`, and `comm` may
1546
+ * itself contain spaces and parentheses — so the split is on the LAST `)`,
1547
+ * never on whitespace. `utime` and `stime` are the 12th and 13th fields after
1548
+ * it. Everything that can fail is inside the try: a non-Linux platform, a
1549
+ * container with `hidepid`, a thread that exits between the readdir and the
1550
+ * read. A thread that vanishes mid-scan is skipped rather than failing the
1551
+ * whole reading — it contributed to neither snapshot's total.
1552
+ */
1553
+ function readSelfTaskTicks() {
1554
+ try {
1555
+ const tids = (0, node_fs.readdirSync)("/proc/self/task");
1556
+ const out = [];
1557
+ for (const tid of tids) {
1558
+ const parsed = parseTaskStat(tid);
1559
+ if (parsed !== null) out.push(parsed);
1560
+ }
1561
+ return out.length === 0 ? null : out;
1562
+ } catch {
1563
+ return null;
1564
+ }
1565
+ }
1566
+ function parseTaskStat(tid) {
1567
+ try {
1568
+ const raw = (0, node_fs.readFileSync)(`/proc/self/task/${tid}/stat`, "utf8");
1569
+ const close = raw.lastIndexOf(") ");
1570
+ const open = raw.indexOf(" (");
1571
+ if (close < 0 || open < 0 || close <= open) return null;
1572
+ const comm = raw.slice(open + 2, close);
1573
+ const fields = raw.slice(close + 2).split(" ");
1574
+ const utime = Number(fields[11]);
1575
+ const stime = Number(fields[12]);
1576
+ if (!Number.isFinite(utime) || !Number.isFinite(stime)) return null;
1577
+ return {
1578
+ comm,
1579
+ ticks: utime + stime
1580
+ };
1581
+ } catch {
1582
+ return null;
1583
+ }
1584
+ }
1585
+ /**
1586
+ * The two fields, APPENDED LAST on the `[mem]` line — after everything D446,
1587
+ * D456 and D458 appended, so every Loki prefix written since 2026-08-29 still
1588
+ * matches (D446's rule).
1589
+ *
1590
+ * `procCpu` prints whenever there is a window, including at 0.0 %, because an
1591
+ * idle process is a reading and it is the one that says a runner is alive and
1592
+ * doing nothing. `v8WorkerCpu` is CONDITIONAL and its absence is the reading:
1593
+ * the platform could not be asked. It carries its thread count because "36.6 %
1594
+ * over four threads" and "36.6 % on one" are different faults.
1595
+ */
1596
+ function formatProcessCpu(reading) {
1597
+ if (reading === null || reading === void 0) return "";
1598
+ const workers = reading.v8Workers;
1599
+ return ` procCpu=${reading.percentOfCore.toFixed(1)}%` + (workers === null ? "" : ` v8WorkerCpu=${workers.percentOfCore.toFixed(1)}%/${workers.threads}thr`);
1600
+ }
1473
1601
  //#endregion
1474
1602
  //#region src/kernel/heap-watch.ts
1475
1603
  /**
@@ -2069,6 +2197,15 @@ function startHeapWatch(label = HUB_MAIN_HEAP_WATCH_LABEL, sink = consoleSink, i
2069
2197
  const now = reclaimOptions?.now ?? (() => Date.now());
2070
2198
  const gcObserver = probes?.gcObserver ?? nodeGcObserver();
2071
2199
  const gcCensus = createGcCensus(gcObserver.install, gcObserver.kinds, now());
2200
+ const cpuProbe = probes?.processCpu;
2201
+ const processCpu = createProcessCpuCensus({
2202
+ cpuUsageUs: cpuProbe?.cpuUsageUs ?? (() => {
2203
+ const u = process.cpuUsage();
2204
+ return u.user + u.system;
2205
+ }),
2206
+ readTasks: cpuProbe?.readTasks ?? readSelfTaskTicks,
2207
+ startedAt: now()
2208
+ });
2072
2209
  const triggerMb = reclaimOptions?.triggerMb ?? 1024;
2073
2210
  const minIntervalMs = reclaimOptions?.minIntervalMs ?? 12e4;
2074
2211
  const steadyStateIntervalMs = reclaimOptions?.steadyStateIntervalMs ?? 6e5;
@@ -2171,7 +2308,7 @@ function startHeapWatch(label = HUB_MAIN_HEAP_WATCH_LABEL, sink = consoleSink, i
2171
2308
  const due = at - lastLoggedAt >= intervalMs;
2172
2309
  if (mode === "escalated" || due) {
2173
2310
  lastLoggedAt = at;
2174
- const line = format(label, sample, loopDelay?.read(), budgetMb, `${formatHeapSpaces(readSpaces())}${formatEventPlane(eventPlane?.read())}` + formatSocketPlane(socketPlane?.read()) + formatMeshQueue(meshQueue?.()) + formatGcCensus(gcCensus?.read(at)));
2311
+ const line = format(label, sample, loopDelay?.read(), budgetMb, `${formatHeapSpaces(readSpaces())}${formatEventPlane(eventPlane?.read())}` + formatSocketPlane(socketPlane?.read()) + formatMeshQueue(meshQueue?.()) + formatGcCensus(gcCensus?.read(at)) + formatProcessCpu(processCpu.read(at)));
2175
2312
  if (sample.nearLimit) sink.warn(`${line} — APPROACHING HEAP LIMIT`);
2176
2313
  else if (mode === "escalated") sink.warn(`${line} — heap elevated, sampling every ${probeIntervalMs}ms`);
2177
2314
  else sink.info(line);
@@ -6,7 +6,7 @@ import { unlink } from "node:fs/promises";
6
6
  import * as path$1 from "node:path";
7
7
  import { isAbsolute, join } from "node:path";
8
8
  import * as fs from "node:fs";
9
- import { existsSync } from "node:fs";
9
+ import { existsSync, readFileSync, readdirSync } from "node:fs";
10
10
  import { execFile } from "node:child_process";
11
11
  import * as os from "node:os";
12
12
  import { tmpdir } from "node:os";
@@ -1467,6 +1467,134 @@ function formatGcCensus(window) {
1467
1467
  const perMin = (n) => window.windowMs <= 0 ? "?" : (n / (window.windowMs / 6e4)).toFixed(1);
1468
1468
  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)}`;
1469
1469
  }
1470
+ /**
1471
+ * The census. Always exists — `process.cpuUsage()` is available on every
1472
+ * platform Node runs on, so unlike the GC census there is no runtime in which
1473
+ * this has nothing to report.
1474
+ */
1475
+ function createProcessCpuCensus(options) {
1476
+ let windowStart = options.startedAt;
1477
+ let cpuAtStart = options.cpuUsageUs();
1478
+ let tasksAtStart = options.readTasks();
1479
+ return { read: (at) => {
1480
+ const windowMs = at - windowStart;
1481
+ if (windowMs < 1e3) return null;
1482
+ const cpuNow = options.cpuUsageUs();
1483
+ const tasksNow = options.readTasks();
1484
+ const cpuUs = cpuNow - cpuAtStart;
1485
+ const percentOfCore = cpuUs <= 0 ? 0 : round1(cpuUs / 1e3 / windowMs * 100);
1486
+ const reading = {
1487
+ percentOfCore,
1488
+ windowMs,
1489
+ v8Workers: shareOfWorkers(tasksAtStart, tasksNow, percentOfCore)
1490
+ };
1491
+ windowStart = at;
1492
+ cpuAtStart = cpuNow;
1493
+ tasksAtStart = tasksNow;
1494
+ return reading;
1495
+ } };
1496
+ }
1497
+ /**
1498
+ * The worker share, or `null`.
1499
+ *
1500
+ * Every way this can fail to be a reading returns `null`: either snapshot
1501
+ * missing, no thread scheduled at all across the window (a share of nothing is
1502
+ * not zero percent — it is no measurement), or a delta that went BACKWARDS,
1503
+ * which means the thread set changed under us and the subtraction describes
1504
+ * nothing real.
1505
+ */
1506
+ function shareOfWorkers(before, after, percentOfCore) {
1507
+ if (before === null || after === null) return null;
1508
+ const b = sum(before);
1509
+ const a = sum(after);
1510
+ const workerTicks = a.worker - b.worker;
1511
+ const totalTicks = a.total - b.total;
1512
+ if (workerTicks < 0 || totalTicks <= 0 || workerTicks > totalTicks) return null;
1513
+ return {
1514
+ percentOfCore: round1(percentOfCore * (workerTicks / totalTicks)),
1515
+ threads: a.workerThreads
1516
+ };
1517
+ }
1518
+ var V8_WORKER_COMM = "V8Worker";
1519
+ function sum(tasks) {
1520
+ let worker = 0;
1521
+ let total = 0;
1522
+ let workerThreads = 0;
1523
+ for (const t of tasks) {
1524
+ total += t.ticks;
1525
+ if (t.comm === V8_WORKER_COMM) {
1526
+ worker += t.ticks;
1527
+ workerThreads += 1;
1528
+ }
1529
+ }
1530
+ return {
1531
+ worker,
1532
+ total,
1533
+ workerThreads
1534
+ };
1535
+ }
1536
+ function round1(n) {
1537
+ return Math.round(n * 10) / 10;
1538
+ }
1539
+ /**
1540
+ * Per-thread ticks for THIS process, or `null` where that cannot be read.
1541
+ *
1542
+ * `/proc/self/task/<tid>/stat` is `pid (comm) state ppid …`, and `comm` may
1543
+ * itself contain spaces and parentheses — so the split is on the LAST `)`,
1544
+ * never on whitespace. `utime` and `stime` are the 12th and 13th fields after
1545
+ * it. Everything that can fail is inside the try: a non-Linux platform, a
1546
+ * container with `hidepid`, a thread that exits between the readdir and the
1547
+ * read. A thread that vanishes mid-scan is skipped rather than failing the
1548
+ * whole reading — it contributed to neither snapshot's total.
1549
+ */
1550
+ function readSelfTaskTicks() {
1551
+ try {
1552
+ const tids = readdirSync("/proc/self/task");
1553
+ const out = [];
1554
+ for (const tid of tids) {
1555
+ const parsed = parseTaskStat(tid);
1556
+ if (parsed !== null) out.push(parsed);
1557
+ }
1558
+ return out.length === 0 ? null : out;
1559
+ } catch {
1560
+ return null;
1561
+ }
1562
+ }
1563
+ function parseTaskStat(tid) {
1564
+ try {
1565
+ const raw = readFileSync(`/proc/self/task/${tid}/stat`, "utf8");
1566
+ const close = raw.lastIndexOf(") ");
1567
+ const open = raw.indexOf(" (");
1568
+ if (close < 0 || open < 0 || close <= open) return null;
1569
+ const comm = raw.slice(open + 2, close);
1570
+ const fields = raw.slice(close + 2).split(" ");
1571
+ const utime = Number(fields[11]);
1572
+ const stime = Number(fields[12]);
1573
+ if (!Number.isFinite(utime) || !Number.isFinite(stime)) return null;
1574
+ return {
1575
+ comm,
1576
+ ticks: utime + stime
1577
+ };
1578
+ } catch {
1579
+ return null;
1580
+ }
1581
+ }
1582
+ /**
1583
+ * The two fields, APPENDED LAST on the `[mem]` line — after everything D446,
1584
+ * D456 and D458 appended, so every Loki prefix written since 2026-08-29 still
1585
+ * matches (D446's rule).
1586
+ *
1587
+ * `procCpu` prints whenever there is a window, including at 0.0 %, because an
1588
+ * idle process is a reading and it is the one that says a runner is alive and
1589
+ * doing nothing. `v8WorkerCpu` is CONDITIONAL and its absence is the reading:
1590
+ * the platform could not be asked. It carries its thread count because "36.6 %
1591
+ * over four threads" and "36.6 % on one" are different faults.
1592
+ */
1593
+ function formatProcessCpu(reading) {
1594
+ if (reading === null || reading === void 0) return "";
1595
+ const workers = reading.v8Workers;
1596
+ return ` procCpu=${reading.percentOfCore.toFixed(1)}%` + (workers === null ? "" : ` v8WorkerCpu=${workers.percentOfCore.toFixed(1)}%/${workers.threads}thr`);
1597
+ }
1470
1598
  //#endregion
1471
1599
  //#region src/kernel/heap-watch.ts
1472
1600
  /**
@@ -2066,6 +2194,15 @@ function startHeapWatch(label = HUB_MAIN_HEAP_WATCH_LABEL, sink = consoleSink, i
2066
2194
  const now = reclaimOptions?.now ?? (() => Date.now());
2067
2195
  const gcObserver = probes?.gcObserver ?? nodeGcObserver();
2068
2196
  const gcCensus = createGcCensus(gcObserver.install, gcObserver.kinds, now());
2197
+ const cpuProbe = probes?.processCpu;
2198
+ const processCpu = createProcessCpuCensus({
2199
+ cpuUsageUs: cpuProbe?.cpuUsageUs ?? (() => {
2200
+ const u = process.cpuUsage();
2201
+ return u.user + u.system;
2202
+ }),
2203
+ readTasks: cpuProbe?.readTasks ?? readSelfTaskTicks,
2204
+ startedAt: now()
2205
+ });
2069
2206
  const triggerMb = reclaimOptions?.triggerMb ?? 1024;
2070
2207
  const minIntervalMs = reclaimOptions?.minIntervalMs ?? 12e4;
2071
2208
  const steadyStateIntervalMs = reclaimOptions?.steadyStateIntervalMs ?? 6e5;
@@ -2168,7 +2305,7 @@ function startHeapWatch(label = HUB_MAIN_HEAP_WATCH_LABEL, sink = consoleSink, i
2168
2305
  const due = at - lastLoggedAt >= intervalMs;
2169
2306
  if (mode === "escalated" || due) {
2170
2307
  lastLoggedAt = at;
2171
- const line = format(label, sample, loopDelay?.read(), budgetMb, `${formatHeapSpaces(readSpaces())}${formatEventPlane(eventPlane?.read())}` + formatSocketPlane(socketPlane?.read()) + formatMeshQueue(meshQueue?.()) + formatGcCensus(gcCensus?.read(at)));
2308
+ const line = format(label, sample, loopDelay?.read(), budgetMb, `${formatHeapSpaces(readSpaces())}${formatEventPlane(eventPlane?.read())}` + formatSocketPlane(socketPlane?.read()) + formatMeshQueue(meshQueue?.()) + formatGcCensus(gcCensus?.read(at)) + formatProcessCpu(processCpu.read(at)));
2172
2309
  if (sample.nearLimit) sink.warn(`${line} — APPROACHING HEAP LIMIT`);
2173
2310
  else if (mode === "escalated") sink.warn(`${line} — heap elevated, sampling every ${probeIntervalMs}ms`);
2174
2311
  else sink.info(line);
@@ -1,4 +1,4 @@
1
- import { an as asJsonObject } from "./dist-T9GvfhgV.mjs";
1
+ import { an as asJsonObject } from "./dist-DmfYrdAn.mjs";
2
2
  //#region src/builtins/sqlite-storage/retired-settings-keys.ts
3
3
  /**
4
4
  * Is THIS node the one whose settings store is the cluster's authority?
@@ -1,4 +1,4 @@
1
- const require_dist = require("./dist-0sWJNwme.js");
1
+ const require_dist = require("./dist-DdRxWA7g.js");
2
2
  //#region src/builtins/sqlite-storage/retired-settings-keys.ts
3
3
  /**
4
4
  * Is THIS node the one whose settings store is the cluster's authority?
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/system",
3
- "version": "1.2.222",
3
+ "version": "1.2.224",
4
4
  "description": "Core addon for CamStack — builtins, pipeline, process management, auth, logging, events",
5
5
  "keywords": [
6
6
  "camstack",