chainlesschain 0.47.9 → 0.51.0

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 (73) hide show
  1. package/bin/chainlesschain.js +0 -0
  2. package/package.json +1 -1
  3. package/src/assets/web-panel/.build-hash +1 -1
  4. package/src/assets/web-panel/assets/{AppLayout-6SPt_8Y_.js → AppLayout-Rvi759IS.js} +1 -1
  5. package/src/assets/web-panel/assets/Dashboard-BS-tzGNj.css +1 -0
  6. package/src/assets/web-panel/assets/{Dashboard-Br7kCwKJ.js → Dashboard-DBhFxXYQ.js} +2 -2
  7. package/src/assets/web-panel/assets/{index-tN-8TosE.js → index-uL0cZ8N_.js} +2 -2
  8. package/src/assets/web-panel/index.html +2 -2
  9. package/src/commands/codegen.js +303 -0
  10. package/src/commands/collab.js +482 -0
  11. package/src/commands/crosschain.js +382 -0
  12. package/src/commands/dbevo.js +388 -0
  13. package/src/commands/dev.js +411 -0
  14. package/src/commands/federation.js +427 -0
  15. package/src/commands/fusion.js +332 -0
  16. package/src/commands/governance.js +505 -0
  17. package/src/commands/hardening.js +110 -0
  18. package/src/commands/incentive.js +373 -0
  19. package/src/commands/inference.js +304 -0
  20. package/src/commands/infra.js +361 -0
  21. package/src/commands/ipfs.js +392 -0
  22. package/src/commands/kg.js +371 -0
  23. package/src/commands/marketplace.js +326 -0
  24. package/src/commands/mcp.js +97 -18
  25. package/src/commands/multimodal.js +404 -0
  26. package/src/commands/nlprog.js +329 -0
  27. package/src/commands/ops.js +408 -0
  28. package/src/commands/perception.js +385 -0
  29. package/src/commands/pqc.js +34 -0
  30. package/src/commands/privacy.js +345 -0
  31. package/src/commands/quantization.js +280 -0
  32. package/src/commands/recommend.js +336 -0
  33. package/src/commands/reputation.js +349 -0
  34. package/src/commands/runtime.js +500 -0
  35. package/src/commands/sla.js +352 -0
  36. package/src/commands/stress.js +252 -0
  37. package/src/commands/tech.js +268 -0
  38. package/src/commands/tenant.js +576 -0
  39. package/src/commands/trust.js +366 -0
  40. package/src/harness/mcp-client.js +330 -54
  41. package/src/index.js +118 -0
  42. package/src/lib/aiops.js +523 -0
  43. package/src/lib/autonomous-developer.js +524 -0
  44. package/src/lib/code-agent.js +442 -0
  45. package/src/lib/collaboration-governance.js +556 -0
  46. package/src/lib/community-governance.js +649 -0
  47. package/src/lib/content-recommendation.js +600 -0
  48. package/src/lib/cross-chain.js +669 -0
  49. package/src/lib/dbevo.js +669 -0
  50. package/src/lib/decentral-infra.js +445 -0
  51. package/src/lib/federation-hardening.js +587 -0
  52. package/src/lib/hardening-manager.js +409 -0
  53. package/src/lib/inference-network.js +407 -0
  54. package/src/lib/ipfs-storage.js +575 -0
  55. package/src/lib/knowledge-graph.js +530 -0
  56. package/src/lib/mcp-client.js +3 -0
  57. package/src/lib/multimodal.js +725 -0
  58. package/src/lib/nl-programming.js +595 -0
  59. package/src/lib/perception.js +500 -0
  60. package/src/lib/pqc-manager.js +141 -9
  61. package/src/lib/privacy-computing.js +575 -0
  62. package/src/lib/protocol-fusion.js +535 -0
  63. package/src/lib/quantization.js +362 -0
  64. package/src/lib/reputation-optimizer.js +509 -0
  65. package/src/lib/skill-marketplace.js +397 -0
  66. package/src/lib/sla-manager.js +484 -0
  67. package/src/lib/stress-tester.js +383 -0
  68. package/src/lib/tech-learning-engine.js +651 -0
  69. package/src/lib/tenant-saas.js +831 -0
  70. package/src/lib/token-incentive.js +513 -0
  71. package/src/lib/trust-security.js +473 -0
  72. package/src/lib/universal-runtime.js +771 -0
  73. package/src/assets/web-panel/assets/Dashboard-CKeMmCoT.css +0 -1
@@ -0,0 +1,500 @@
1
+ /**
2
+ * `cc runtime` — CLI surface for Phase 63 Universal Runtime.
3
+ *
4
+ * Exposes plugin lifecycle, hot update/rollback, profiling,
5
+ * state sync, platform info, health check, metrics, configure.
6
+ */
7
+
8
+ import { Command } from "commander";
9
+
10
+ import {
11
+ PLUGIN_STATUS,
12
+ UPDATE_TYPE,
13
+ HEALTH_STATUS,
14
+ PROFILE_TYPES,
15
+ ensureRuntimeTables,
16
+ loadPlugin,
17
+ unloadPlugin,
18
+ setPluginStatus,
19
+ getPlugin,
20
+ listPlugins,
21
+ hotUpdate,
22
+ rollbackUpdate,
23
+ listUpdates,
24
+ takeProfile,
25
+ getProfile,
26
+ listProfiles,
27
+ setState,
28
+ getState,
29
+ listState,
30
+ deleteState,
31
+ configure,
32
+ getConfig,
33
+ getPlatformInfo,
34
+ healthCheck,
35
+ getMetrics,
36
+ getRuntimeStats,
37
+ } from "../lib/universal-runtime.js";
38
+
39
+ function _dbFromCtx(cmd) {
40
+ const root = cmd?.parent?.parent ?? cmd?.parent;
41
+ return root?._db;
42
+ }
43
+
44
+ function _parseJson(raw) {
45
+ if (raw == null) return null;
46
+ try {
47
+ return JSON.parse(raw);
48
+ } catch (_e) {
49
+ return raw;
50
+ }
51
+ }
52
+
53
+ export function registerRuntimeCommand(program) {
54
+ const runtime = new Command("runtime")
55
+ .description("Universal application runtime (Phase 63)")
56
+ .hook("preAction", (thisCmd) => {
57
+ const db = _dbFromCtx(thisCmd);
58
+ if (db) ensureRuntimeTables(db);
59
+ });
60
+
61
+ /* ── Catalogs ─────────────────────────────────────── */
62
+
63
+ runtime
64
+ .command("plugin-statuses")
65
+ .description("List plugin lifecycle statuses")
66
+ .option("--json", "JSON output")
67
+ .action((opts) => {
68
+ const statuses = Object.values(PLUGIN_STATUS);
69
+ if (opts.json) return console.log(JSON.stringify(statuses, null, 2));
70
+ for (const s of statuses) console.log(` ${s}`);
71
+ });
72
+
73
+ runtime
74
+ .command("update-types")
75
+ .description("List update types (patch/minor/major/rollback)")
76
+ .option("--json", "JSON output")
77
+ .action((opts) => {
78
+ const types = Object.values(UPDATE_TYPE);
79
+ if (opts.json) return console.log(JSON.stringify(types, null, 2));
80
+ for (const t of types) console.log(` ${t}`);
81
+ });
82
+
83
+ runtime
84
+ .command("health-levels")
85
+ .description("List health levels")
86
+ .option("--json", "JSON output")
87
+ .action((opts) => {
88
+ const levels = Object.values(HEALTH_STATUS);
89
+ if (opts.json) return console.log(JSON.stringify(levels, null, 2));
90
+ for (const l of levels) console.log(` ${l}`);
91
+ });
92
+
93
+ runtime
94
+ .command("profile-types")
95
+ .description("List profile sample types (cpu/memory/flamegraph)")
96
+ .option("--json", "JSON output")
97
+ .action((opts) => {
98
+ if (opts.json) return console.log(JSON.stringify(PROFILE_TYPES, null, 2));
99
+ for (const t of PROFILE_TYPES) console.log(` ${t}`);
100
+ });
101
+
102
+ /* ── Plugin lifecycle ─────────────────────────────── */
103
+
104
+ runtime
105
+ .command("plugin-load")
106
+ .description("Load a plugin")
107
+ .requiredOption("-n, --name <name>", "Plugin name")
108
+ .option("-v, --version <version>", "Version", "1.0.0")
109
+ .option("-c, --config <json>", "Config JSON")
110
+ .option("-a, --apis <json>", "Exposed APIs JSON array")
111
+ .option("-p, --permissions <json>", "Permissions JSON array")
112
+ .option("--json", "JSON output")
113
+ .action((opts) => {
114
+ const db = _dbFromCtx(runtime);
115
+ const result = loadPlugin(db, {
116
+ name: opts.name,
117
+ version: opts.version,
118
+ config: opts.config ? _parseJson(opts.config) : undefined,
119
+ apis: opts.apis ? _parseJson(opts.apis) : undefined,
120
+ permissions: opts.permissions
121
+ ? _parseJson(opts.permissions)
122
+ : undefined,
123
+ });
124
+ if (opts.json) return console.log(JSON.stringify(result, null, 2));
125
+ console.log(
126
+ result.loaded
127
+ ? `Plugin loaded: ${result.pluginId}`
128
+ : `Failed: ${result.reason}`,
129
+ );
130
+ });
131
+
132
+ runtime
133
+ .command("plugin-unload <id>")
134
+ .description("Unload a plugin")
135
+ .option("--json", "JSON output")
136
+ .action((id, opts) => {
137
+ const db = _dbFromCtx(runtime);
138
+ const result = unloadPlugin(db, id);
139
+ if (opts.json) return console.log(JSON.stringify(result, null, 2));
140
+ console.log(
141
+ result.unloaded ? "Plugin unloaded." : `Failed: ${result.reason}`,
142
+ );
143
+ });
144
+
145
+ runtime
146
+ .command("plugin-status <id> <status>")
147
+ .description("Set plugin status (loading/active/suspended/error/unloaded)")
148
+ .option("--json", "JSON output")
149
+ .action((id, status, opts) => {
150
+ const db = _dbFromCtx(runtime);
151
+ const result = setPluginStatus(db, id, status);
152
+ if (opts.json) return console.log(JSON.stringify(result, null, 2));
153
+ console.log(
154
+ result.updated ? "Plugin status updated." : `Failed: ${result.reason}`,
155
+ );
156
+ });
157
+
158
+ runtime
159
+ .command("plugin-show <id>")
160
+ .description("Show plugin details")
161
+ .option("--json", "JSON output")
162
+ .action((id, opts) => {
163
+ const db = _dbFromCtx(runtime);
164
+ const p = getPlugin(db, id);
165
+ if (!p) return console.log("Plugin not found.");
166
+ if (opts.json) return console.log(JSON.stringify(p, null, 2));
167
+ console.log(`ID: ${p.id}`);
168
+ console.log(`Name: ${p.name}`);
169
+ console.log(`Version: ${p.version}`);
170
+ console.log(`Status: ${p.status}`);
171
+ if (p.config) console.log(`Config: ${p.config}`);
172
+ if (p.apis) console.log(`APIs: ${p.apis}`);
173
+ if (p.permissions) console.log(`Perms: ${p.permissions}`);
174
+ if (p.loaded_at)
175
+ console.log(`Loaded: ${new Date(p.loaded_at).toISOString()}`);
176
+ });
177
+
178
+ runtime
179
+ .command("plugins")
180
+ .description("List plugins")
181
+ .option("-s, --status <status>", "Filter by status")
182
+ .option("--limit <n>", "Max results", parseInt)
183
+ .option("--json", "JSON output")
184
+ .action((opts) => {
185
+ const db = _dbFromCtx(runtime);
186
+ const results = listPlugins(db, {
187
+ status: opts.status,
188
+ limit: opts.limit,
189
+ });
190
+ if (opts.json) return console.log(JSON.stringify(results, null, 2));
191
+ if (results.length === 0) return console.log("No plugins.");
192
+ for (const p of results) {
193
+ console.log(
194
+ ` ${p.status.padEnd(10)} ${p.version.padEnd(8)} ${p.name.padEnd(24)} ${p.id.slice(0, 14)}`,
195
+ );
196
+ }
197
+ });
198
+
199
+ /* ── Hot update ───────────────────────────────────── */
200
+
201
+ runtime
202
+ .command("hot-update <pluginId> <newVersion>")
203
+ .description("Apply a hot update to a plugin")
204
+ .option("-t, --type <type>", "Update type override (patch/minor/major)")
205
+ .option("--json", "JSON output")
206
+ .action((pluginId, newVersion, opts) => {
207
+ const db = _dbFromCtx(runtime);
208
+ const result = hotUpdate(db, pluginId, newVersion, {
209
+ updateType: opts.type,
210
+ });
211
+ if (opts.json) return console.log(JSON.stringify(result, null, 2));
212
+ if (result.updated) {
213
+ console.log(
214
+ `Updated ${pluginId}: ${result.fromVersion} → ${result.toVersion} (${result.updateType})`,
215
+ );
216
+ } else {
217
+ console.log(`Failed: ${result.reason}`);
218
+ }
219
+ });
220
+
221
+ runtime
222
+ .command("rollback <updateId>")
223
+ .description("Roll back a previous update")
224
+ .option("--json", "JSON output")
225
+ .action((updateId, opts) => {
226
+ const db = _dbFromCtx(runtime);
227
+ const result = rollbackUpdate(db, updateId);
228
+ if (opts.json) return console.log(JSON.stringify(result, null, 2));
229
+ if (result.rolledBack) {
230
+ console.log(
231
+ `Rolled back: ${result.fromVersion} → ${result.toVersion} (${result.rollbackId})`,
232
+ );
233
+ } else {
234
+ console.log(`Failed: ${result.reason}`);
235
+ }
236
+ });
237
+
238
+ runtime
239
+ .command("updates")
240
+ .description("List updates")
241
+ .option("-p, --plugin <id>", "Filter by plugin id")
242
+ .option("--limit <n>", "Max results", parseInt)
243
+ .option("--json", "JSON output")
244
+ .action((opts) => {
245
+ const db = _dbFromCtx(runtime);
246
+ const results = listUpdates(db, {
247
+ pluginId: opts.plugin,
248
+ limit: opts.limit,
249
+ });
250
+ if (opts.json) return console.log(JSON.stringify(results, null, 2));
251
+ if (results.length === 0) return console.log("No updates.");
252
+ for (const u of results) {
253
+ console.log(
254
+ ` ${u.update_type.padEnd(9)} ${(u.from_version || "-").padEnd(8)} → ${(u.to_version || "-").padEnd(8)} ${u.plugin_id.slice(0, 14)} ${u.id.slice(0, 14)}`,
255
+ );
256
+ }
257
+ });
258
+
259
+ /* ── Profile ──────────────────────────────────────── */
260
+
261
+ runtime
262
+ .command("profile")
263
+ .description("Take a runtime profile sample")
264
+ .option("-t, --type <type>", "Profile type (cpu/memory/flamegraph)", "cpu")
265
+ .option("-d, --duration <ms>", "Duration in ms", parseInt)
266
+ .option("--json", "JSON output")
267
+ .action((opts) => {
268
+ const db = _dbFromCtx(runtime);
269
+ const result = takeProfile(db, {
270
+ type: opts.type,
271
+ duration: opts.duration,
272
+ });
273
+ if (opts.json) return console.log(JSON.stringify(result, null, 2));
274
+ if (result.taken) {
275
+ console.log(`Profile: ${result.profileId} (${result.type})`);
276
+ } else {
277
+ console.log(`Failed: ${result.reason}`);
278
+ }
279
+ });
280
+
281
+ runtime
282
+ .command("profile-show <id>")
283
+ .description("Show profile details")
284
+ .option("--json", "JSON output")
285
+ .action((id, opts) => {
286
+ const db = _dbFromCtx(runtime);
287
+ const p = getProfile(db, id);
288
+ if (!p) return console.log("Profile not found.");
289
+ if (opts.json) return console.log(JSON.stringify(p, null, 2));
290
+ console.log(`ID: ${p.id}`);
291
+ console.log(`Type: ${p.profile_type}`);
292
+ console.log(`Duration: ${p.duration_ms}ms`);
293
+ console.log(`Created: ${new Date(p.created_at).toISOString()}`);
294
+ if (p.data) {
295
+ console.log(`Data:`);
296
+ console.log(JSON.stringify(p.data, null, 2));
297
+ }
298
+ });
299
+
300
+ runtime
301
+ .command("profiles")
302
+ .description("List profiles")
303
+ .option("-t, --type <type>", "Filter by profile type")
304
+ .option("--limit <n>", "Max results", parseInt)
305
+ .option("--json", "JSON output")
306
+ .action((opts) => {
307
+ const db = _dbFromCtx(runtime);
308
+ const results = listProfiles(db, { type: opts.type, limit: opts.limit });
309
+ if (opts.json) return console.log(JSON.stringify(results, null, 2));
310
+ if (results.length === 0) return console.log("No profiles.");
311
+ for (const p of results) {
312
+ console.log(
313
+ ` ${p.profile_type.padEnd(11)} ${String(p.duration_ms).padEnd(8)}ms ${p.id.slice(0, 14)}`,
314
+ );
315
+ }
316
+ });
317
+
318
+ /* ── State sync ───────────────────────────────────── */
319
+
320
+ runtime
321
+ .command("state-set <key> <value>")
322
+ .description("Set a synced state value (JSON or string)")
323
+ .option("--json", "JSON output")
324
+ .action((key, value, opts) => {
325
+ const db = _dbFromCtx(runtime);
326
+ const parsed = _parseJson(value);
327
+ const result = setState(db, key, parsed);
328
+ if (opts.json) return console.log(JSON.stringify(result, null, 2));
329
+ console.log(
330
+ result.set ? `State set: ${key}` : `Failed: ${result.reason}`,
331
+ );
332
+ });
333
+
334
+ runtime
335
+ .command("state-get <key>")
336
+ .description("Get a synced state value")
337
+ .option("--json", "JSON output")
338
+ .action((key, opts) => {
339
+ const db = _dbFromCtx(runtime);
340
+ const result = getState(db, key);
341
+ if (!result) return console.log("Key not found.");
342
+ if (opts.json) return console.log(JSON.stringify(result, null, 2));
343
+ console.log(
344
+ `${key} = ${typeof result.value === "string" ? result.value : JSON.stringify(result.value)}`,
345
+ );
346
+ });
347
+
348
+ runtime
349
+ .command("state-list")
350
+ .description("List synced state keys")
351
+ .option("--limit <n>", "Max results", parseInt)
352
+ .option("--json", "JSON output")
353
+ .action((opts) => {
354
+ const db = _dbFromCtx(runtime);
355
+ const results = listState(db, { limit: opts.limit });
356
+ if (opts.json) return console.log(JSON.stringify(results, null, 2));
357
+ if (results.length === 0) return console.log("No state.");
358
+ for (const s of results) {
359
+ const val =
360
+ typeof s.value === "string" ? s.value : JSON.stringify(s.value);
361
+ console.log(` ${s.key.padEnd(24)} ${val}`);
362
+ }
363
+ });
364
+
365
+ runtime
366
+ .command("state-delete <key>")
367
+ .description("Delete a synced state entry")
368
+ .option("--json", "JSON output")
369
+ .action((key, opts) => {
370
+ const db = _dbFromCtx(runtime);
371
+ const result = deleteState(db, key);
372
+ if (opts.json) return console.log(JSON.stringify(result, null, 2));
373
+ console.log(result.deleted ? "Deleted." : `Failed: ${result.reason}`);
374
+ });
375
+
376
+ /* ── Platform / health / metrics ──────────────────── */
377
+
378
+ runtime
379
+ .command("platform")
380
+ .description("Show platform info")
381
+ .option("--json", "JSON output")
382
+ .action((opts) => {
383
+ const info = getPlatformInfo();
384
+ if (opts.json) return console.log(JSON.stringify(info, null, 2));
385
+ console.log(`Platform: ${info.platform}`);
386
+ console.log(`Arch: ${info.arch}`);
387
+ console.log(`Node: ${info.nodeVersion}`);
388
+ if (info.electronVersion)
389
+ console.log(`Electron: ${info.electronVersion}`);
390
+ console.log(`PID: ${info.pid}`);
391
+ console.log(`CPUs: ${info.cpus}`);
392
+ console.log(`Total memory: ${info.totalMemoryBytes} bytes`);
393
+ console.log(`Free memory: ${info.freeMemoryBytes} bytes`);
394
+ if (info.hostname) console.log(`Host: ${info.hostname}`);
395
+ console.log(`Uptime (proc): ${info.processUptimeMs}ms`);
396
+ console.log(`Heap used: ${info.heapUsed} bytes`);
397
+ });
398
+
399
+ runtime
400
+ .command("health")
401
+ .description("Run a runtime health check")
402
+ .option("--json", "JSON output")
403
+ .action((opts) => {
404
+ const h = healthCheck();
405
+ if (opts.json) return console.log(JSON.stringify(h, null, 2));
406
+ console.log(`Status: ${h.status}`);
407
+ console.log(`Uptime: ${h.uptimeMs}ms`);
408
+ console.log(
409
+ `Heap: ${h.memory.heapUsed}/${h.memory.limitBytes} (${(h.memory.heapRatio * 100).toFixed(2)}%)`,
410
+ );
411
+ console.log(
412
+ `Plugins: total=${h.plugins.total} active=${h.plugins.active} errors=${h.plugins.errors}`,
413
+ );
414
+ console.log(`Errors: ${h.errors}`);
415
+ });
416
+
417
+ runtime
418
+ .command("metrics")
419
+ .description("Show runtime metrics")
420
+ .option("--json", "JSON output")
421
+ .action((opts) => {
422
+ const m = getMetrics();
423
+ if (opts.json) return console.log(JSON.stringify(m, null, 2));
424
+ console.log(`Uptime: ${m.uptimeMs}ms`);
425
+ console.log(`Plugins loaded: ${m.pluginsLoaded}`);
426
+ console.log(`Plugins unloaded: ${m.pluginsUnloaded}`);
427
+ console.log(`Hot updates: ${m.hotUpdates}`);
428
+ console.log(`Rollbacks: ${m.rollbacks}`);
429
+ console.log(`Profiles taken: ${m.profilesTaken}`);
430
+ console.log(`State writes: ${m.stateWrites}`);
431
+ console.log(`Active plugins: ${m.activePlugins}`);
432
+ console.log(`Total plugins: ${m.totalPlugins}`);
433
+ console.log(`Total updates: ${m.totalUpdates}`);
434
+ console.log(`Total profiles: ${m.totalProfiles}`);
435
+ console.log(`State keys: ${m.stateKeys}`);
436
+ console.log(`Errors: ${m.errors}`);
437
+ });
438
+
439
+ /* ── Configure ────────────────────────────────────── */
440
+
441
+ runtime
442
+ .command("configure <key> <value>")
443
+ .description("Update a runtime config key (JSON or string)")
444
+ .option("--json", "JSON output")
445
+ .action((key, value, opts) => {
446
+ const db = _dbFromCtx(runtime);
447
+ const parsed = _parseJson(value);
448
+ const result = configure(db, key, parsed);
449
+ if (opts.json) return console.log(JSON.stringify(result, null, 2));
450
+ console.log(
451
+ result.configured
452
+ ? `Configured: ${key} = ${typeof parsed === "string" ? parsed : JSON.stringify(parsed)}`
453
+ : `Failed: ${result.reason}`,
454
+ );
455
+ });
456
+
457
+ runtime
458
+ .command("config")
459
+ .description("Show current runtime config")
460
+ .option("--json", "JSON output")
461
+ .action((opts) => {
462
+ const c = getConfig();
463
+ if (opts.json) return console.log(JSON.stringify(c, null, 2));
464
+ for (const [k, v] of Object.entries(c)) {
465
+ console.log(
466
+ ` ${k.padEnd(24)} ${typeof v === "string" ? v : JSON.stringify(v)}`,
467
+ );
468
+ }
469
+ });
470
+
471
+ /* ── Stats ────────────────────────────────────────── */
472
+
473
+ runtime
474
+ .command("stats")
475
+ .description("Runtime statistics (plugins/updates/profiles/state counts)")
476
+ .option("--json", "JSON output")
477
+ .action((opts) => {
478
+ const s = getRuntimeStats();
479
+ if (opts.json) return console.log(JSON.stringify(s, null, 2));
480
+ console.log(
481
+ `Plugins: ${s.plugins} · Updates: ${s.updates} · Profiles: ${s.profiles} · State: ${s.state}`,
482
+ );
483
+ console.log(`By plugin status:`);
484
+ for (const [k, v] of Object.entries(s.byPluginStatus)) {
485
+ if (v > 0) console.log(` ${k.padEnd(10)} ${v}`);
486
+ }
487
+ console.log(`By update type:`);
488
+ for (const [k, v] of Object.entries(s.byUpdateType)) {
489
+ if (v > 0) console.log(` ${k.padEnd(10)} ${v}`);
490
+ }
491
+ console.log(`By profile type:`);
492
+ for (const [k, v] of Object.entries(s.byProfileType)) {
493
+ if (v > 0) console.log(` ${k.padEnd(11)} ${v}`);
494
+ }
495
+ console.log(`Health: ${s.health.status}`);
496
+ console.log(`Uptime: ${s.metrics.uptimeMs}ms`);
497
+ });
498
+
499
+ program.addCommand(runtime);
500
+ }