chainlesschain 0.66.0 → 0.132.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 (143) hide show
  1. package/bin/chainlesschain.js +0 -0
  2. package/package.json +1 -1
  3. package/src/commands/a2a.js +380 -0
  4. package/src/commands/agent-network.js +254 -1
  5. package/src/commands/audit.js +302 -0
  6. package/src/commands/automation.js +271 -1
  7. package/src/commands/bi.js +348 -0
  8. package/src/commands/codegen.js +224 -0
  9. package/src/commands/collab.js +341 -0
  10. package/src/commands/compliance.js +1035 -0
  11. package/src/commands/cowork.js +221 -0
  12. package/src/commands/crosschain.js +218 -0
  13. package/src/commands/dbevo.js +284 -0
  14. package/src/commands/dev.js +252 -0
  15. package/src/commands/did.js +358 -0
  16. package/src/commands/dlp.js +341 -0
  17. package/src/commands/encrypt.js +341 -0
  18. package/src/commands/evomap.js +394 -0
  19. package/src/commands/export.js +256 -1
  20. package/src/commands/federation.js +283 -0
  21. package/src/commands/fusion.js +258 -0
  22. package/src/commands/governance.js +325 -0
  23. package/src/commands/hardening.js +411 -0
  24. package/src/commands/hook.js +148 -0
  25. package/src/commands/import.js +252 -0
  26. package/src/commands/incentive.js +322 -0
  27. package/src/commands/inference.js +318 -0
  28. package/src/commands/infra.js +244 -0
  29. package/src/commands/instinct.js +260 -0
  30. package/src/commands/ipfs.js +318 -0
  31. package/src/commands/kg.js +387 -0
  32. package/src/commands/llm.js +263 -0
  33. package/src/commands/lowcode.js +356 -0
  34. package/src/commands/marketplace.js +256 -0
  35. package/src/commands/mcp.js +221 -0
  36. package/src/commands/memory.js +248 -0
  37. package/src/commands/multimodal.js +296 -0
  38. package/src/commands/nlprog.js +356 -0
  39. package/src/commands/note.js +244 -0
  40. package/src/commands/ops.js +354 -0
  41. package/src/commands/orchestrate.js +166 -0
  42. package/src/commands/org.js +277 -0
  43. package/src/commands/p2p.js +390 -0
  44. package/src/commands/perception.js +290 -0
  45. package/src/commands/permmem.js +251 -0
  46. package/src/commands/plugin-ecosystem.js +273 -0
  47. package/src/commands/pqc.js +393 -0
  48. package/src/commands/privacy.js +321 -0
  49. package/src/commands/quantization.js +351 -0
  50. package/src/commands/rcache.js +271 -0
  51. package/src/commands/recommend.js +340 -0
  52. package/src/commands/reputation.js +261 -0
  53. package/src/commands/runtime.js +307 -0
  54. package/src/commands/scim.js +262 -0
  55. package/src/commands/session.js +258 -0
  56. package/src/commands/siem.js +246 -0
  57. package/src/commands/skill.js +267 -1
  58. package/src/commands/sla.js +259 -0
  59. package/src/commands/social.js +256 -0
  60. package/src/commands/sso.js +186 -1
  61. package/src/commands/stress.js +230 -0
  62. package/src/commands/sync.js +256 -0
  63. package/src/commands/tech.js +338 -0
  64. package/src/commands/tenant.js +351 -0
  65. package/src/commands/terraform.js +245 -0
  66. package/src/commands/tokens.js +269 -0
  67. package/src/commands/trust.js +249 -0
  68. package/src/commands/wallet.js +277 -0
  69. package/src/commands/workflow.js +171 -0
  70. package/src/commands/zkp.js +335 -0
  71. package/src/index.js +4 -0
  72. package/src/lib/a2a-protocol.js +451 -0
  73. package/src/lib/agent-coordinator.js +325 -0
  74. package/src/lib/agent-network.js +387 -0
  75. package/src/lib/agent-router.js +395 -0
  76. package/src/lib/aiops.js +478 -0
  77. package/src/lib/app-builder.js +239 -0
  78. package/src/lib/audit-logger.js +379 -0
  79. package/src/lib/automation-engine.js +330 -0
  80. package/src/lib/autonomous-developer.js +350 -0
  81. package/src/lib/bi-engine.js +338 -0
  82. package/src/lib/code-agent.js +323 -0
  83. package/src/lib/collaboration-governance.js +364 -0
  84. package/src/lib/community-governance.js +436 -0
  85. package/src/lib/compliance-manager.js +434 -0
  86. package/src/lib/content-recommendation.js +469 -0
  87. package/src/lib/cross-chain.js +345 -0
  88. package/src/lib/crypto-manager.js +350 -0
  89. package/src/lib/dbevo.js +338 -0
  90. package/src/lib/decentral-infra.js +340 -0
  91. package/src/lib/did-manager.js +367 -0
  92. package/src/lib/dlp-engine.js +389 -0
  93. package/src/lib/evomap-federation.js +177 -0
  94. package/src/lib/evomap-governance.js +276 -0
  95. package/src/lib/federation-hardening.js +259 -0
  96. package/src/lib/hardening-manager.js +348 -0
  97. package/src/lib/hook-manager.js +380 -0
  98. package/src/lib/inference-network.js +330 -0
  99. package/src/lib/instinct-manager.js +332 -0
  100. package/src/lib/ipfs-storage.js +334 -0
  101. package/src/lib/knowledge-exporter.js +381 -0
  102. package/src/lib/knowledge-graph.js +432 -0
  103. package/src/lib/knowledge-importer.js +379 -0
  104. package/src/lib/llm-providers.js +391 -0
  105. package/src/lib/mcp-registry.js +333 -0
  106. package/src/lib/memory-manager.js +330 -0
  107. package/src/lib/multimodal.js +346 -0
  108. package/src/lib/nl-programming.js +343 -0
  109. package/src/lib/note-versioning.js +327 -0
  110. package/src/lib/org-manager.js +323 -0
  111. package/src/lib/p2p-manager.js +387 -0
  112. package/src/lib/perception.js +346 -0
  113. package/src/lib/perf-tuning.js +4 -1
  114. package/src/lib/permanent-memory.js +320 -0
  115. package/src/lib/plugin-ecosystem.js +377 -0
  116. package/src/lib/pqc-manager.js +368 -0
  117. package/src/lib/privacy-computing.js +427 -0
  118. package/src/lib/protocol-fusion.js +417 -0
  119. package/src/lib/quantization.js +325 -0
  120. package/src/lib/reputation-optimizer.js +299 -0
  121. package/src/lib/response-cache.js +327 -0
  122. package/src/lib/scim-manager.js +329 -0
  123. package/src/lib/session-manager.js +329 -0
  124. package/src/lib/siem-exporter.js +333 -0
  125. package/src/lib/skill-loader.js +377 -0
  126. package/src/lib/skill-marketplace.js +325 -0
  127. package/src/lib/sla-manager.js +275 -0
  128. package/src/lib/social-manager.js +326 -0
  129. package/src/lib/sso-manager.js +332 -0
  130. package/src/lib/stress-tester.js +330 -0
  131. package/src/lib/sync-manager.js +326 -0
  132. package/src/lib/tech-learning-engine.js +369 -0
  133. package/src/lib/tenant-saas.js +460 -0
  134. package/src/lib/terraform-manager.js +363 -0
  135. package/src/lib/threat-intel.js +335 -0
  136. package/src/lib/token-incentive.js +293 -0
  137. package/src/lib/token-tracker.js +329 -0
  138. package/src/lib/trust-security.js +390 -0
  139. package/src/lib/ueba.js +389 -0
  140. package/src/lib/universal-runtime.js +325 -0
  141. package/src/lib/wallet-manager.js +326 -0
  142. package/src/lib/workflow-engine.js +322 -0
  143. package/src/lib/zkp-engine.js +274 -0
@@ -20,6 +20,35 @@ import {
20
20
  unpairDevice,
21
21
  generatePeerId,
22
22
  P2PBridge,
23
+ PEER_MATURITY_V2,
24
+ MESSAGE_LIFECYCLE_V2,
25
+ getMaxActivePeersPerNetworkV2,
26
+ setMaxActivePeersPerNetworkV2,
27
+ getMaxPendingMessagesPerPeerV2,
28
+ setMaxPendingMessagesPerPeerV2,
29
+ getPeerIdleMsV2,
30
+ setPeerIdleMsV2,
31
+ getMessageStuckMsV2,
32
+ setMessageStuckMsV2,
33
+ registerPeerV2,
34
+ getPeerV2,
35
+ listPeersV2,
36
+ activatePeerV2,
37
+ offlinePeerV2,
38
+ archivePeerV2,
39
+ touchPeerV2,
40
+ createMessageV2,
41
+ getMessageV2,
42
+ listMessagesV2,
43
+ startMessageV2,
44
+ deliverMessageV2,
45
+ failMessageV2,
46
+ cancelMessageV2,
47
+ getActivePeerCountV2,
48
+ getPendingMessageCountV2,
49
+ autoOfflineIdlePeersV2,
50
+ autoFailStuckMessagesV2,
51
+ getP2pManagerStatsV2,
23
52
  } from "../lib/p2p-manager.js";
24
53
 
25
54
  export function registerP2pCommand(program) {
@@ -271,4 +300,365 @@ export function registerP2pCommand(program) {
271
300
  process.exit(1);
272
301
  }
273
302
  });
303
+
304
+ // ===== V2 in-memory governance surface (no DB, no bootstrap) =====
305
+
306
+ p2p
307
+ .command("peer-maturities-v2")
308
+ .description("[V2] List peer maturity states")
309
+ .option("--json", "Output as JSON")
310
+ .action((options) => {
311
+ const states = Object.values(PEER_MATURITY_V2);
312
+ if (options.json) console.log(JSON.stringify(states, null, 2));
313
+ else for (const s of states) logger.log(s);
314
+ });
315
+
316
+ p2p
317
+ .command("message-lifecycles-v2")
318
+ .description("[V2] List message lifecycle states")
319
+ .option("--json", "Output as JSON")
320
+ .action((options) => {
321
+ const states = Object.values(MESSAGE_LIFECYCLE_V2);
322
+ if (options.json) console.log(JSON.stringify(states, null, 2));
323
+ else for (const s of states) logger.log(s);
324
+ });
325
+
326
+ p2p
327
+ .command("config-v2")
328
+ .description("[V2] Show governance config")
329
+ .option("--json", "Output as JSON")
330
+ .action((options) => {
331
+ const cfg = {
332
+ maxActivePeersPerNetwork: getMaxActivePeersPerNetworkV2(),
333
+ maxPendingMessagesPerPeer: getMaxPendingMessagesPerPeerV2(),
334
+ peerIdleMs: getPeerIdleMsV2(),
335
+ messageStuckMs: getMessageStuckMsV2(),
336
+ };
337
+ if (options.json) console.log(JSON.stringify(cfg, null, 2));
338
+ else for (const [k, v] of Object.entries(cfg)) logger.log(`${k}: ${v}`);
339
+ });
340
+
341
+ p2p
342
+ .command("set-max-active-peers-per-network-v2 <n>")
343
+ .description("[V2] Set per-network active peer cap")
344
+ .action((n) => {
345
+ try {
346
+ setMaxActivePeersPerNetworkV2(Number(n));
347
+ logger.success(
348
+ `max active peers/network = ${getMaxActivePeersPerNetworkV2()}`,
349
+ );
350
+ } catch (err) {
351
+ logger.error(err.message);
352
+ process.exit(1);
353
+ }
354
+ });
355
+
356
+ p2p
357
+ .command("set-max-pending-messages-per-peer-v2 <n>")
358
+ .description("[V2] Set per-peer pending message cap")
359
+ .action((n) => {
360
+ try {
361
+ setMaxPendingMessagesPerPeerV2(Number(n));
362
+ logger.success(
363
+ `max pending messages/peer = ${getMaxPendingMessagesPerPeerV2()}`,
364
+ );
365
+ } catch (err) {
366
+ logger.error(err.message);
367
+ process.exit(1);
368
+ }
369
+ });
370
+
371
+ p2p
372
+ .command("set-peer-idle-ms-v2 <ms>")
373
+ .description("[V2] Set peer idle threshold (ms)")
374
+ .action((ms) => {
375
+ try {
376
+ setPeerIdleMsV2(Number(ms));
377
+ logger.success(`peer idle ms = ${getPeerIdleMsV2()}`);
378
+ } catch (err) {
379
+ logger.error(err.message);
380
+ process.exit(1);
381
+ }
382
+ });
383
+
384
+ p2p
385
+ .command("set-message-stuck-ms-v2 <ms>")
386
+ .description("[V2] Set message stuck threshold (ms)")
387
+ .action((ms) => {
388
+ try {
389
+ setMessageStuckMsV2(Number(ms));
390
+ logger.success(`message stuck ms = ${getMessageStuckMsV2()}`);
391
+ } catch (err) {
392
+ logger.error(err.message);
393
+ process.exit(1);
394
+ }
395
+ });
396
+
397
+ p2p
398
+ .command("register-peer-v2 <id>")
399
+ .description("[V2] Register a peer profile (PENDING)")
400
+ .requiredOption("-n, --network <id>", "Network ID")
401
+ .option("-d, --device-name <name>", "Device name")
402
+ .option("-t, --device-type <type>", "Device type", "desktop")
403
+ .action((id, opts) => {
404
+ try {
405
+ const peer = registerPeerV2(id, {
406
+ networkId: opts.network,
407
+ deviceName: opts.deviceName,
408
+ deviceType: opts.deviceType,
409
+ });
410
+ logger.success(`peer ${peer.id} registered (status=${peer.status})`);
411
+ } catch (err) {
412
+ logger.error(err.message);
413
+ process.exit(1);
414
+ }
415
+ });
416
+
417
+ p2p
418
+ .command("activate-peer-v2 <id>")
419
+ .description("[V2] Activate a peer (pending|offline -> active)")
420
+ .action((id) => {
421
+ try {
422
+ const p = activatePeerV2(id);
423
+ logger.success(`peer ${p.id} active`);
424
+ } catch (err) {
425
+ logger.error(err.message);
426
+ process.exit(1);
427
+ }
428
+ });
429
+
430
+ p2p
431
+ .command("offline-peer-v2 <id>")
432
+ .description("[V2] Mark peer offline (active -> offline)")
433
+ .action((id) => {
434
+ try {
435
+ const p = offlinePeerV2(id);
436
+ logger.success(`peer ${p.id} offline`);
437
+ } catch (err) {
438
+ logger.error(err.message);
439
+ process.exit(1);
440
+ }
441
+ });
442
+
443
+ p2p
444
+ .command("archive-peer-v2 <id>")
445
+ .description("[V2] Archive peer (terminal)")
446
+ .action((id) => {
447
+ try {
448
+ const p = archivePeerV2(id);
449
+ logger.success(`peer ${p.id} archived`);
450
+ } catch (err) {
451
+ logger.error(err.message);
452
+ process.exit(1);
453
+ }
454
+ });
455
+
456
+ p2p
457
+ .command("touch-peer-v2 <id>")
458
+ .description("[V2] Bump peer lastSeenAt")
459
+ .action((id) => {
460
+ try {
461
+ const p = touchPeerV2(id);
462
+ logger.success(`peer ${p.id} touched`);
463
+ } catch (err) {
464
+ logger.error(err.message);
465
+ process.exit(1);
466
+ }
467
+ });
468
+
469
+ p2p
470
+ .command("get-peer-v2 <id>")
471
+ .description("[V2] Show peer profile")
472
+ .option("--json", "Output as JSON")
473
+ .action((id, opts) => {
474
+ try {
475
+ const p = getPeerV2(id);
476
+ if (!p) {
477
+ logger.info("peer not found");
478
+ return;
479
+ }
480
+ if (opts.json) console.log(JSON.stringify(p, null, 2));
481
+ else logger.log(JSON.stringify(p, null, 2));
482
+ } catch (err) {
483
+ logger.error(err.message);
484
+ process.exit(1);
485
+ }
486
+ });
487
+
488
+ p2p
489
+ .command("list-peers-v2")
490
+ .description("[V2] List peer profiles")
491
+ .option("-n, --network <id>", "Filter by network")
492
+ .option("-s, --status <s>", "Filter by status")
493
+ .option("-t, --device-type <t>", "Filter by device type")
494
+ .option("--json", "Output as JSON")
495
+ .action((opts) => {
496
+ const list = listPeersV2({
497
+ networkId: opts.network,
498
+ status: opts.status,
499
+ deviceType: opts.deviceType,
500
+ });
501
+ if (opts.json) console.log(JSON.stringify(list, null, 2));
502
+ else
503
+ for (const p of list)
504
+ logger.log(`${p.id}\t${p.networkId}\t${p.status}\t${p.deviceType}`);
505
+ });
506
+
507
+ p2p
508
+ .command("create-message-v2 <id>")
509
+ .description("[V2] Create a queued V2 message")
510
+ .requiredOption("-p, --peer <peerId>", "Peer ID")
511
+ .option("-k, --kind <kind>", "Message kind", "text")
512
+ .action((id, opts) => {
513
+ try {
514
+ const m = createMessageV2(id, { peerId: opts.peer, kind: opts.kind });
515
+ logger.success(
516
+ `message ${m.id} queued (peer=${m.peerId} kind=${m.kind})`,
517
+ );
518
+ } catch (err) {
519
+ logger.error(err.message);
520
+ process.exit(1);
521
+ }
522
+ });
523
+
524
+ p2p
525
+ .command("start-message-v2 <id>")
526
+ .description("[V2] Mark message sending (queued -> sending)")
527
+ .action((id) => {
528
+ try {
529
+ const m = startMessageV2(id);
530
+ logger.success(`message ${m.id} sending`);
531
+ } catch (err) {
532
+ logger.error(err.message);
533
+ process.exit(1);
534
+ }
535
+ });
536
+
537
+ p2p
538
+ .command("deliver-message-v2 <id>")
539
+ .description("[V2] Mark message delivered (sending -> delivered)")
540
+ .action((id) => {
541
+ try {
542
+ const m = deliverMessageV2(id);
543
+ logger.success(`message ${m.id} delivered`);
544
+ } catch (err) {
545
+ logger.error(err.message);
546
+ process.exit(1);
547
+ }
548
+ });
549
+
550
+ p2p
551
+ .command("fail-message-v2 <id>")
552
+ .description("[V2] Mark message failed (queued|sending -> failed)")
553
+ .action((id) => {
554
+ try {
555
+ const m = failMessageV2(id);
556
+ logger.success(`message ${m.id} failed`);
557
+ } catch (err) {
558
+ logger.error(err.message);
559
+ process.exit(1);
560
+ }
561
+ });
562
+
563
+ p2p
564
+ .command("cancel-message-v2 <id>")
565
+ .description("[V2] Cancel message (queued|sending -> cancelled)")
566
+ .action((id) => {
567
+ try {
568
+ const m = cancelMessageV2(id);
569
+ logger.success(`message ${m.id} cancelled`);
570
+ } catch (err) {
571
+ logger.error(err.message);
572
+ process.exit(1);
573
+ }
574
+ });
575
+
576
+ p2p
577
+ .command("get-message-v2 <id>")
578
+ .description("[V2] Show message")
579
+ .option("--json", "Output as JSON")
580
+ .action((id, opts) => {
581
+ try {
582
+ const m = getMessageV2(id);
583
+ if (!m) {
584
+ logger.info("message not found");
585
+ return;
586
+ }
587
+ if (opts.json) console.log(JSON.stringify(m, null, 2));
588
+ else logger.log(JSON.stringify(m, null, 2));
589
+ } catch (err) {
590
+ logger.error(err.message);
591
+ process.exit(1);
592
+ }
593
+ });
594
+
595
+ p2p
596
+ .command("list-messages-v2")
597
+ .description("[V2] List V2 messages")
598
+ .option("-p, --peer <peerId>", "Filter by peer")
599
+ .option("-s, --status <s>", "Filter by status")
600
+ .option("--json", "Output as JSON")
601
+ .action((opts) => {
602
+ const list = listMessagesV2({ peerId: opts.peer, status: opts.status });
603
+ if (opts.json) console.log(JSON.stringify(list, null, 2));
604
+ else
605
+ for (const m of list)
606
+ logger.log(`${m.id}\t${m.peerId}\t${m.status}\t${m.kind}`);
607
+ });
608
+
609
+ p2p
610
+ .command("active-peer-count-v2")
611
+ .description("[V2] Count active peers (optional --network filter)")
612
+ .option("-n, --network <id>", "Filter by network")
613
+ .action((opts) => {
614
+ const n = getActivePeerCountV2(opts.network);
615
+ logger.log(String(n));
616
+ });
617
+
618
+ p2p
619
+ .command("pending-message-count-v2")
620
+ .description(
621
+ "[V2] Count pending messages (queued+sending) (optional --peer filter)",
622
+ )
623
+ .option("-p, --peer <peerId>", "Filter by peer")
624
+ .action((opts) => {
625
+ const n = getPendingMessageCountV2(opts.peer);
626
+ logger.log(String(n));
627
+ });
628
+
629
+ p2p
630
+ .command("auto-offline-idle-peers-v2")
631
+ .description("[V2] Mark idle active peers offline")
632
+ .option("--now <ms>", "Override current time (ms)")
633
+ .option("--json", "Output as JSON")
634
+ .action((opts) => {
635
+ const list = autoOfflineIdlePeersV2(
636
+ opts.now ? { now: Number(opts.now) } : undefined,
637
+ );
638
+ if (opts.json) console.log(JSON.stringify(list, null, 2));
639
+ else logger.success(`offlined ${list.length} peer(s)`);
640
+ });
641
+
642
+ p2p
643
+ .command("auto-fail-stuck-messages-v2")
644
+ .description("[V2] Fail stuck sending messages")
645
+ .option("--now <ms>", "Override current time (ms)")
646
+ .option("--json", "Output as JSON")
647
+ .action((opts) => {
648
+ const list = autoFailStuckMessagesV2(
649
+ opts.now ? { now: Number(opts.now) } : undefined,
650
+ );
651
+ if (opts.json) console.log(JSON.stringify(list, null, 2));
652
+ else logger.success(`failed ${list.length} message(s)`);
653
+ });
654
+
655
+ p2p
656
+ .command("stats-v2")
657
+ .description("[V2] Show governance stats")
658
+ .option("--json", "Output as JSON")
659
+ .action((opts) => {
660
+ const s = getP2pManagerStatsV2();
661
+ if (opts.json) console.log(JSON.stringify(s, null, 2));
662
+ else logger.log(JSON.stringify(s, null, 2));
663
+ });
274
664
  }
@@ -24,8 +24,53 @@ import {
24
24
  crossModalQuery,
25
25
  getPerceptionContext,
26
26
  getPerceptionStats,
27
+
28
+ // Phase 84 V2
29
+ SENSOR_MATURITY_V2,
30
+ CAPTURE_LIFECYCLE_V2,
31
+ getDefaultMaxActiveSensorsPerOperatorV2,
32
+ getMaxActiveSensorsPerOperatorV2,
33
+ setMaxActiveSensorsPerOperatorV2,
34
+ getDefaultMaxPendingCapturesPerSensorV2,
35
+ getMaxPendingCapturesPerSensorV2,
36
+ setMaxPendingCapturesPerSensorV2,
37
+ getDefaultSensorIdleMsV2,
38
+ getSensorIdleMsV2,
39
+ setSensorIdleMsV2,
40
+ getDefaultCaptureStuckMsV2,
41
+ getCaptureStuckMsV2,
42
+ setCaptureStuckMsV2,
43
+ registerSensorV2,
44
+ getSensorV2,
45
+ setSensorMaturityV2,
46
+ activateSensor,
47
+ degradeSensor,
48
+ offlineSensor,
49
+ retireSensor,
50
+ touchSensorHeartbeat,
51
+ registerCaptureV2,
52
+ getCaptureV2,
53
+ setCaptureStatusV2,
54
+ startProcessingCapture,
55
+ markCaptureReady,
56
+ failCapture,
57
+ discardCapture,
58
+ getActiveSensorCount,
59
+ getPendingCaptureCount,
60
+ autoOfflineStaleSensors,
61
+ autoFailStuckProcessingCaptures,
62
+ getPerceptionStatsV2,
27
63
  } from "../lib/perception.js";
28
64
 
65
+ function _parseMetaV2(raw) {
66
+ if (!raw) return undefined;
67
+ try {
68
+ return JSON.parse(raw);
69
+ } catch {
70
+ throw new Error("--metadata must be valid JSON");
71
+ }
72
+ }
73
+
29
74
  function _dbFromCtx(cmd) {
30
75
  const root = cmd?.parent?.parent ?? cmd?.parent;
31
76
  return root?._db;
@@ -381,5 +426,250 @@ export function registerPerceptionCommand(program) {
381
426
  console.log(`Index: ${s.index.total} entries`);
382
427
  });
383
428
 
429
+ /* ═══════════════════════════════════════════════════ *
430
+ * Phase 84 V2 — Sensor Maturity + Capture Lifecycle
431
+ * ═══════════════════════════════════════════════════ */
432
+
433
+ perc
434
+ .command("sensor-maturities-v2")
435
+ .description("List V2 sensor maturity states")
436
+ .option("--json", "JSON output")
437
+ .action((opts) => {
438
+ const xs = Object.values(SENSOR_MATURITY_V2);
439
+ if (opts.json) return console.log(JSON.stringify(xs, null, 2));
440
+ for (const x of xs) console.log(` ${x}`);
441
+ });
442
+
443
+ perc
444
+ .command("capture-lifecycles-v2")
445
+ .description("List V2 capture lifecycle states")
446
+ .option("--json", "JSON output")
447
+ .action((opts) => {
448
+ const xs = Object.values(CAPTURE_LIFECYCLE_V2);
449
+ if (opts.json) return console.log(JSON.stringify(xs, null, 2));
450
+ for (const x of xs) console.log(` ${x}`);
451
+ });
452
+
453
+ // ── Config defaults/getters/setters ────────────────
454
+
455
+ perc
456
+ .command("default-max-active-sensors-per-operator")
457
+ .description("Default cap")
458
+ .action(() => console.log(getDefaultMaxActiveSensorsPerOperatorV2()));
459
+ perc
460
+ .command("max-active-sensors-per-operator")
461
+ .description("Current cap")
462
+ .action(() => console.log(getMaxActiveSensorsPerOperatorV2()));
463
+ perc
464
+ .command("set-max-active-sensors-per-operator <n>")
465
+ .description("Set cap")
466
+ .action((n) => console.log(setMaxActiveSensorsPerOperatorV2(n)));
467
+
468
+ perc
469
+ .command("default-max-pending-captures-per-sensor")
470
+ .description("Default cap")
471
+ .action(() => console.log(getDefaultMaxPendingCapturesPerSensorV2()));
472
+ perc
473
+ .command("max-pending-captures-per-sensor")
474
+ .description("Current cap")
475
+ .action(() => console.log(getMaxPendingCapturesPerSensorV2()));
476
+ perc
477
+ .command("set-max-pending-captures-per-sensor <n>")
478
+ .description("Set cap")
479
+ .action((n) => console.log(setMaxPendingCapturesPerSensorV2(n)));
480
+
481
+ perc
482
+ .command("default-sensor-idle-ms")
483
+ .description("Default idle ms")
484
+ .action(() => console.log(getDefaultSensorIdleMsV2()));
485
+ perc
486
+ .command("sensor-idle-ms")
487
+ .description("Current idle ms")
488
+ .action(() => console.log(getSensorIdleMsV2()));
489
+ perc
490
+ .command("set-sensor-idle-ms <ms>")
491
+ .description("Set idle ms")
492
+ .action((ms) => console.log(setSensorIdleMsV2(ms)));
493
+
494
+ perc
495
+ .command("default-capture-stuck-ms")
496
+ .description("Default stuck ms")
497
+ .action(() => console.log(getDefaultCaptureStuckMsV2()));
498
+ perc
499
+ .command("capture-stuck-ms")
500
+ .description("Current stuck ms")
501
+ .action(() => console.log(getCaptureStuckMsV2()));
502
+ perc
503
+ .command("set-capture-stuck-ms <ms>")
504
+ .description("Set stuck ms")
505
+ .action((ms) => console.log(setCaptureStuckMsV2(ms)));
506
+
507
+ // ── Counts ─────────────────────────────────────────
508
+
509
+ perc
510
+ .command("active-sensor-count")
511
+ .description("Count of ACTIVE sensors")
512
+ .option("-o, --operator <id>", "filter by operator")
513
+ .action((opts) => console.log(getActiveSensorCount(opts.operator)));
514
+
515
+ perc
516
+ .command("pending-capture-count")
517
+ .description("Count of PENDING captures")
518
+ .option("-s, --sensor <id>", "filter by sensor")
519
+ .action((opts) => console.log(getPendingCaptureCount(opts.sensor)));
520
+
521
+ // ── Sensor lifecycle ───────────────────────────────
522
+
523
+ perc
524
+ .command("register-sensor-v2 <sensor-id>")
525
+ .description("Register a V2 sensor")
526
+ .requiredOption("-o, --operator <id>", "operator id")
527
+ .requiredOption("-m, --modality <mod>", "modality")
528
+ .option("-i, --initial-status <status>", "initial status")
529
+ .option("--metadata <json>", "metadata JSON")
530
+ .action((id, opts) => {
531
+ const r = registerSensorV2(null, {
532
+ sensorId: id,
533
+ operatorId: opts.operator,
534
+ modality: opts.modality,
535
+ initialStatus: opts.initialStatus,
536
+ metadata: _parseMetaV2(opts.metadata),
537
+ });
538
+ console.log(JSON.stringify(r, null, 2));
539
+ });
540
+
541
+ perc
542
+ .command("sensor-v2 <sensor-id>")
543
+ .description("Get a V2 sensor")
544
+ .action((id) => {
545
+ const r = getSensorV2(id);
546
+ if (!r) {
547
+ console.error(`Unknown sensor: ${id}`);
548
+ process.exitCode = 1;
549
+ return;
550
+ }
551
+ console.log(JSON.stringify(r, null, 2));
552
+ });
553
+
554
+ perc
555
+ .command("set-sensor-maturity-v2 <sensor-id> <status>")
556
+ .description("Transition sensor maturity")
557
+ .option("-r, --reason <text>", "reason")
558
+ .option("--metadata <json>", "metadata JSON")
559
+ .action((id, status, opts) => {
560
+ const r = setSensorMaturityV2(null, id, status, {
561
+ reason: opts.reason,
562
+ metadata: _parseMetaV2(opts.metadata),
563
+ });
564
+ console.log(JSON.stringify(r, null, 2));
565
+ });
566
+
567
+ for (const [name, fn] of [
568
+ ["activate-sensor", activateSensor],
569
+ ["degrade-sensor", degradeSensor],
570
+ ["offline-sensor", offlineSensor],
571
+ ["retire-sensor", retireSensor],
572
+ ]) {
573
+ perc
574
+ .command(`${name} <sensor-id>`)
575
+ .description(`Transition to ${name.split("-")[0]}`)
576
+ .option("-r, --reason <text>", "reason")
577
+ .action((id, opts) => {
578
+ const r = fn(null, id, opts.reason);
579
+ console.log(JSON.stringify(r, null, 2));
580
+ });
581
+ }
582
+
583
+ perc
584
+ .command("touch-sensor-heartbeat <sensor-id>")
585
+ .description("Bump lastHeartbeatAt")
586
+ .action((id) => {
587
+ const r = touchSensorHeartbeat(id);
588
+ console.log(JSON.stringify(r, null, 2));
589
+ });
590
+
591
+ // ── Capture lifecycle ──────────────────────────────
592
+
593
+ perc
594
+ .command("register-capture-v2 <capture-id>")
595
+ .description("Register a V2 capture")
596
+ .requiredOption("-s, --sensor <id>", "sensor id")
597
+ .option("-i, --initial-status <status>", "initial status")
598
+ .option("--metadata <json>", "metadata JSON")
599
+ .action((id, opts) => {
600
+ const r = registerCaptureV2(null, {
601
+ captureId: id,
602
+ sensorId: opts.sensor,
603
+ initialStatus: opts.initialStatus,
604
+ metadata: _parseMetaV2(opts.metadata),
605
+ });
606
+ console.log(JSON.stringify(r, null, 2));
607
+ });
608
+
609
+ perc
610
+ .command("capture-v2 <capture-id>")
611
+ .description("Get a V2 capture")
612
+ .action((id) => {
613
+ const r = getCaptureV2(id);
614
+ if (!r) {
615
+ console.error(`Unknown capture: ${id}`);
616
+ process.exitCode = 1;
617
+ return;
618
+ }
619
+ console.log(JSON.stringify(r, null, 2));
620
+ });
621
+
622
+ perc
623
+ .command("set-capture-status-v2 <capture-id> <status>")
624
+ .description("Transition capture lifecycle")
625
+ .option("-r, --reason <text>", "reason")
626
+ .option("--metadata <json>", "metadata JSON")
627
+ .action((id, status, opts) => {
628
+ const r = setCaptureStatusV2(null, id, status, {
629
+ reason: opts.reason,
630
+ metadata: _parseMetaV2(opts.metadata),
631
+ });
632
+ console.log(JSON.stringify(r, null, 2));
633
+ });
634
+
635
+ for (const [name, fn] of [
636
+ ["start-processing-capture", startProcessingCapture],
637
+ ["mark-capture-ready", markCaptureReady],
638
+ ["fail-capture", failCapture],
639
+ ["discard-capture", discardCapture],
640
+ ]) {
641
+ perc
642
+ .command(`${name} <capture-id>`)
643
+ .description(`Transition capture (${name})`)
644
+ .option("-r, --reason <text>", "reason")
645
+ .action((id, opts) => {
646
+ const r = fn(null, id, opts.reason);
647
+ console.log(JSON.stringify(r, null, 2));
648
+ });
649
+ }
650
+
651
+ // ── Auto-flips + stats ─────────────────────────────
652
+
653
+ perc
654
+ .command("auto-offline-stale-sensors")
655
+ .description("Flip stale ACTIVE/DEGRADED sensors → OFFLINE")
656
+ .action(() =>
657
+ console.log(JSON.stringify(autoOfflineStaleSensors(null), null, 2)),
658
+ );
659
+
660
+ perc
661
+ .command("auto-fail-stuck-processing-captures")
662
+ .description("Flip stuck PROCESSING captures → FAILED")
663
+ .action(() =>
664
+ console.log(
665
+ JSON.stringify(autoFailStuckProcessingCaptures(null), null, 2),
666
+ ),
667
+ );
668
+
669
+ perc
670
+ .command("stats-v2")
671
+ .description("V2 stats snapshot")
672
+ .action(() => console.log(JSON.stringify(getPerceptionStatsV2(), null, 2)));
673
+
384
674
  program.addCommand(perc);
385
675
  }