chainlesschain 0.132.0 → 0.143.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 (106) hide show
  1. package/package.json +1 -1
  2. package/src/commands/a2a.js +62 -0
  3. package/src/commands/activitypub.js +61 -0
  4. package/src/commands/agent.js +117 -0
  5. package/src/commands/bi.js +61 -0
  6. package/src/commands/bm25.js +78 -0
  7. package/src/commands/browse.js +64 -0
  8. package/src/commands/ccron.js +78 -0
  9. package/src/commands/compliance.js +40 -0
  10. package/src/commands/compt.js +78 -0
  11. package/src/commands/consol.js +231 -0
  12. package/src/commands/cowork.js +42 -0
  13. package/src/commands/crosschain.js +62 -0
  14. package/src/commands/dao.js +62 -0
  15. package/src/commands/dlp.js +61 -0
  16. package/src/commands/economy.js +56 -0
  17. package/src/commands/evolution.js +56 -0
  18. package/src/commands/evomap.js +61 -0
  19. package/src/commands/fflag.js +178 -0
  20. package/src/commands/git.js +45 -0
  21. package/src/commands/hmemory.js +56 -0
  22. package/src/commands/inference.js +42 -0
  23. package/src/commands/itbudget.js +45 -0
  24. package/src/commands/lowcode.js +44 -0
  25. package/src/commands/matrix.js +62 -0
  26. package/src/commands/mcpscaf.js +41 -0
  27. package/src/commands/meminj.js +41 -0
  28. package/src/commands/nostr.js +62 -0
  29. package/src/commands/orchgov.js +45 -0
  30. package/src/commands/pdfp.js +78 -0
  31. package/src/commands/perf.js +39 -0
  32. package/src/commands/perm.js +45 -0
  33. package/src/commands/pipeline.js +57 -1
  34. package/src/commands/planmode.js +45 -0
  35. package/src/commands/promcomp.js +82 -0
  36. package/src/commands/recommend.js +42 -0
  37. package/src/commands/seshhook.js +41 -0
  38. package/src/commands/seshsearch.js +41 -0
  39. package/src/commands/seshtail.js +41 -0
  40. package/src/commands/seshu.js +41 -0
  41. package/src/commands/sganal.js +78 -0
  42. package/src/commands/siem.js +40 -0
  43. package/src/commands/slotfill.js +41 -0
  44. package/src/commands/social.js +34 -0
  45. package/src/commands/svccont.js +45 -0
  46. package/src/commands/tms.js +45 -0
  47. package/src/commands/topiccls.js +45 -0
  48. package/src/commands/uprof.js +45 -0
  49. package/src/commands/vcheck.js +78 -0
  50. package/src/commands/webfetch.js +41 -0
  51. package/src/commands/zkp.js +62 -0
  52. package/src/harness/prompt-compressor.js +331 -0
  53. package/src/index.js +61 -1
  54. package/src/lib/a2a-protocol.js +105 -0
  55. package/src/lib/activitypub-bridge.js +105 -0
  56. package/src/lib/agent-economy.js +105 -0
  57. package/src/lib/app-builder.js +105 -0
  58. package/src/lib/autonomous-agent.js +105 -0
  59. package/src/lib/bi-engine.js +105 -0
  60. package/src/lib/bm25-search.js +81 -0
  61. package/src/lib/browser-automation.js +105 -0
  62. package/src/lib/compliance-framework-reporter.js +105 -0
  63. package/src/lib/compression-telemetry.js +81 -0
  64. package/src/lib/content-recommender.js +105 -0
  65. package/src/lib/cowork-cron.js +81 -0
  66. package/src/lib/cowork-task-runner.js +105 -0
  67. package/src/lib/cross-chain.js +105 -0
  68. package/src/lib/dao-governance.js +105 -0
  69. package/src/lib/dlp-engine.js +105 -0
  70. package/src/lib/evolution-system.js +105 -0
  71. package/src/lib/evomap-manager.js +105 -0
  72. package/src/lib/execution-backend.js +105 -0
  73. package/src/lib/feature-flags.js +85 -0
  74. package/src/lib/git-integration.js +105 -0
  75. package/src/lib/hierarchical-memory.js +105 -0
  76. package/src/lib/inference-network.js +105 -0
  77. package/src/lib/iteration-budget.js +105 -0
  78. package/src/lib/matrix-bridge.js +105 -0
  79. package/src/lib/mcp-scaffold.js +81 -0
  80. package/src/lib/memory-injection.js +81 -0
  81. package/src/lib/nostr-bridge.js +105 -0
  82. package/src/lib/orchestrator.js +105 -0
  83. package/src/lib/pdf-parser.js +81 -0
  84. package/src/lib/perf-tuning.js +105 -0
  85. package/src/lib/permission-engine.js +81 -0
  86. package/src/lib/pipeline-orchestrator.js +105 -0
  87. package/src/lib/plan-mode.js +81 -0
  88. package/src/lib/prompt-compressor.js +1 -10
  89. package/src/lib/service-container.js +81 -0
  90. package/src/lib/session-consolidator.js +105 -0
  91. package/src/lib/session-hooks.js +81 -0
  92. package/src/lib/session-search.js +81 -0
  93. package/src/lib/session-tail.js +81 -0
  94. package/src/lib/session-usage.js +83 -0
  95. package/src/lib/siem-exporter.js +105 -0
  96. package/src/lib/slot-filler.js +81 -0
  97. package/src/lib/social-graph-analytics.js +81 -0
  98. package/src/lib/social-graph.js +81 -0
  99. package/src/lib/sub-agent-registry.js +110 -0
  100. package/src/lib/task-model-selector.js +81 -0
  101. package/src/lib/todo-manager.js +105 -0
  102. package/src/lib/topic-classifier.js +105 -0
  103. package/src/lib/user-profile.js +81 -0
  104. package/src/lib/version-checker.js +81 -0
  105. package/src/lib/web-fetch.js +81 -0
  106. package/src/lib/zkp-engine.js +105 -0
@@ -465,3 +465,108 @@ function _appendHistory(cwd, entry, userMessage) {
465
465
  // Best-effort — don't fail the task for history write errors
466
466
  }
467
467
  }
468
+
469
+
470
+ // ===== V2 Surface: Cowork Task Runner governance overlay (CLI v0.139.0) =====
471
+ export const RUNNER_PROFILE_MATURITY_V2 = Object.freeze({
472
+ PENDING: "pending", ACTIVE: "active", PAUSED: "paused", RETIRED: "retired",
473
+ });
474
+ export const RUNNER_EXEC_LIFECYCLE_V2 = Object.freeze({
475
+ QUEUED: "queued", RUNNING: "running", SUCCEEDED: "succeeded", FAILED: "failed", CANCELLED: "cancelled",
476
+ });
477
+
478
+ const _rpTrans = new Map([
479
+ [RUNNER_PROFILE_MATURITY_V2.PENDING, new Set([RUNNER_PROFILE_MATURITY_V2.ACTIVE, RUNNER_PROFILE_MATURITY_V2.RETIRED])],
480
+ [RUNNER_PROFILE_MATURITY_V2.ACTIVE, new Set([RUNNER_PROFILE_MATURITY_V2.PAUSED, RUNNER_PROFILE_MATURITY_V2.RETIRED])],
481
+ [RUNNER_PROFILE_MATURITY_V2.PAUSED, new Set([RUNNER_PROFILE_MATURITY_V2.ACTIVE, RUNNER_PROFILE_MATURITY_V2.RETIRED])],
482
+ [RUNNER_PROFILE_MATURITY_V2.RETIRED, new Set()],
483
+ ]);
484
+ const _rpTerminal = new Set([RUNNER_PROFILE_MATURITY_V2.RETIRED]);
485
+ const _reTrans = new Map([
486
+ [RUNNER_EXEC_LIFECYCLE_V2.QUEUED, new Set([RUNNER_EXEC_LIFECYCLE_V2.RUNNING, RUNNER_EXEC_LIFECYCLE_V2.CANCELLED])],
487
+ [RUNNER_EXEC_LIFECYCLE_V2.RUNNING, new Set([RUNNER_EXEC_LIFECYCLE_V2.SUCCEEDED, RUNNER_EXEC_LIFECYCLE_V2.FAILED, RUNNER_EXEC_LIFECYCLE_V2.CANCELLED])],
488
+ [RUNNER_EXEC_LIFECYCLE_V2.SUCCEEDED, new Set()],
489
+ [RUNNER_EXEC_LIFECYCLE_V2.FAILED, new Set()],
490
+ [RUNNER_EXEC_LIFECYCLE_V2.CANCELLED, new Set()],
491
+ ]);
492
+
493
+ const _rpsV2 = new Map();
494
+ const _resV2 = new Map();
495
+ let _rpMaxActivePerOwner = 8;
496
+ let _rpMaxPendingExecsPerProfile = 15;
497
+ let _rpIdleMs = 14 * 24 * 60 * 60 * 1000;
498
+ let _reStuckMs = 20 * 60 * 1000;
499
+
500
+ function _rpPos(n, lbl) { const v = Math.floor(Number(n)); if (!Number.isFinite(v) || v <= 0) throw new Error(`${lbl} must be positive integer`); return v; }
501
+
502
+ export function setMaxActiveRunnerProfilesPerOwnerV2(n) { _rpMaxActivePerOwner = _rpPos(n, "maxActiveRunnerProfilesPerOwner"); }
503
+ export function getMaxActiveRunnerProfilesPerOwnerV2() { return _rpMaxActivePerOwner; }
504
+ export function setMaxPendingRunnerExecsPerProfileV2(n) { _rpMaxPendingExecsPerProfile = _rpPos(n, "maxPendingRunnerExecsPerProfile"); }
505
+ export function getMaxPendingRunnerExecsPerProfileV2() { return _rpMaxPendingExecsPerProfile; }
506
+ export function setRunnerProfileIdleMsV2(n) { _rpIdleMs = _rpPos(n, "runnerProfileIdleMs"); }
507
+ export function getRunnerProfileIdleMsV2() { return _rpIdleMs; }
508
+ export function setRunnerExecStuckMsV2(n) { _reStuckMs = _rpPos(n, "runnerExecStuckMs"); }
509
+ export function getRunnerExecStuckMsV2() { return _reStuckMs; }
510
+
511
+ export function _resetStateRunnerV2() {
512
+ _rpsV2.clear(); _resV2.clear();
513
+ _rpMaxActivePerOwner = 8; _rpMaxPendingExecsPerProfile = 15;
514
+ _rpIdleMs = 14 * 24 * 60 * 60 * 1000; _reStuckMs = 20 * 60 * 1000;
515
+ }
516
+
517
+ export function registerRunnerProfileV2({ id, owner, template, metadata } = {}) {
518
+ if (!id || typeof id !== "string") throw new Error("id is required");
519
+ if (!owner || typeof owner !== "string") throw new Error("owner is required");
520
+ if (_rpsV2.has(id)) throw new Error(`runner profile ${id} already registered`);
521
+ const now = Date.now();
522
+ const p = { id, owner, template: template || "default", status: RUNNER_PROFILE_MATURITY_V2.PENDING, createdAt: now, updatedAt: now, activatedAt: null, retiredAt: null, lastTouchedAt: now, metadata: { ...(metadata || {}) } };
523
+ _rpsV2.set(id, p);
524
+ return { ...p, metadata: { ...p.metadata } };
525
+ }
526
+ function _rpCheckP(from, to) { const a = _rpTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid runner profile transition ${from} → ${to}`); }
527
+ function _rpCountActive(owner) { let n = 0; for (const p of _rpsV2.values()) if (p.owner === owner && p.status === RUNNER_PROFILE_MATURITY_V2.ACTIVE) n++; return n; }
528
+
529
+ export function activateRunnerProfileV2(id) {
530
+ const p = _rpsV2.get(id); if (!p) throw new Error(`runner profile ${id} not found`);
531
+ _rpCheckP(p.status, RUNNER_PROFILE_MATURITY_V2.ACTIVE);
532
+ const recovery = p.status === RUNNER_PROFILE_MATURITY_V2.PAUSED;
533
+ if (!recovery) { const c = _rpCountActive(p.owner); if (c >= _rpMaxActivePerOwner) throw new Error(`max active runner profiles per owner (${_rpMaxActivePerOwner}) reached for ${p.owner}`); }
534
+ const now = Date.now(); p.status = RUNNER_PROFILE_MATURITY_V2.ACTIVE; p.updatedAt = now; p.lastTouchedAt = now; if (!p.activatedAt) p.activatedAt = now;
535
+ return { ...p, metadata: { ...p.metadata } };
536
+ }
537
+ export function pauseRunnerProfileV2(id) { const p = _rpsV2.get(id); if (!p) throw new Error(`runner profile ${id} not found`); _rpCheckP(p.status, RUNNER_PROFILE_MATURITY_V2.PAUSED); p.status = RUNNER_PROFILE_MATURITY_V2.PAUSED; p.updatedAt = Date.now(); return { ...p, metadata: { ...p.metadata } }; }
538
+ export function retireRunnerProfileV2(id) { const p = _rpsV2.get(id); if (!p) throw new Error(`runner profile ${id} not found`); _rpCheckP(p.status, RUNNER_PROFILE_MATURITY_V2.RETIRED); const now = Date.now(); p.status = RUNNER_PROFILE_MATURITY_V2.RETIRED; p.updatedAt = now; if (!p.retiredAt) p.retiredAt = now; return { ...p, metadata: { ...p.metadata } }; }
539
+ export function touchRunnerProfileV2(id) { const p = _rpsV2.get(id); if (!p) throw new Error(`runner profile ${id} not found`); if (_rpTerminal.has(p.status)) throw new Error(`cannot touch terminal runner profile ${id}`); const now = Date.now(); p.lastTouchedAt = now; p.updatedAt = now; return { ...p, metadata: { ...p.metadata } }; }
540
+ export function getRunnerProfileV2(id) { const p = _rpsV2.get(id); if (!p) return null; return { ...p, metadata: { ...p.metadata } }; }
541
+ export function listRunnerProfilesV2() { return [..._rpsV2.values()].map((p) => ({ ...p, metadata: { ...p.metadata } })); }
542
+
543
+ function _reCountPending(profileId) { let n = 0; for (const e of _resV2.values()) if (e.profileId === profileId && (e.status === RUNNER_EXEC_LIFECYCLE_V2.QUEUED || e.status === RUNNER_EXEC_LIFECYCLE_V2.RUNNING)) n++; return n; }
544
+
545
+ export function createRunnerExecV2({ id, profileId, taskInput, metadata } = {}) {
546
+ if (!id || typeof id !== "string") throw new Error("id is required");
547
+ if (!profileId || typeof profileId !== "string") throw new Error("profileId is required");
548
+ if (_resV2.has(id)) throw new Error(`runner exec ${id} already exists`);
549
+ if (!_rpsV2.has(profileId)) throw new Error(`runner profile ${profileId} not found`);
550
+ const pending = _reCountPending(profileId);
551
+ if (pending >= _rpMaxPendingExecsPerProfile) throw new Error(`max pending runner execs per profile (${_rpMaxPendingExecsPerProfile}) reached for ${profileId}`);
552
+ const now = Date.now();
553
+ const e = { id, profileId, taskInput: taskInput || "", status: RUNNER_EXEC_LIFECYCLE_V2.QUEUED, createdAt: now, updatedAt: now, startedAt: null, settledAt: null, metadata: { ...(metadata || {}) } };
554
+ _resV2.set(id, e);
555
+ return { ...e, metadata: { ...e.metadata } };
556
+ }
557
+ function _reCheckE(from, to) { const a = _reTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid runner exec transition ${from} → ${to}`); }
558
+ export function startRunnerExecV2(id) { const e = _resV2.get(id); if (!e) throw new Error(`runner exec ${id} not found`); _reCheckE(e.status, RUNNER_EXEC_LIFECYCLE_V2.RUNNING); const now = Date.now(); e.status = RUNNER_EXEC_LIFECYCLE_V2.RUNNING; e.updatedAt = now; if (!e.startedAt) e.startedAt = now; return { ...e, metadata: { ...e.metadata } }; }
559
+ export function succeedRunnerExecV2(id) { const e = _resV2.get(id); if (!e) throw new Error(`runner exec ${id} not found`); _reCheckE(e.status, RUNNER_EXEC_LIFECYCLE_V2.SUCCEEDED); const now = Date.now(); e.status = RUNNER_EXEC_LIFECYCLE_V2.SUCCEEDED; e.updatedAt = now; if (!e.settledAt) e.settledAt = now; return { ...e, metadata: { ...e.metadata } }; }
560
+ export function failRunnerExecV2(id, reason) { const e = _resV2.get(id); if (!e) throw new Error(`runner exec ${id} not found`); _reCheckE(e.status, RUNNER_EXEC_LIFECYCLE_V2.FAILED); const now = Date.now(); e.status = RUNNER_EXEC_LIFECYCLE_V2.FAILED; e.updatedAt = now; if (!e.settledAt) e.settledAt = now; if (reason) e.metadata.failReason = String(reason); return { ...e, metadata: { ...e.metadata } }; }
561
+ export function cancelRunnerExecV2(id, reason) { const e = _resV2.get(id); if (!e) throw new Error(`runner exec ${id} not found`); _reCheckE(e.status, RUNNER_EXEC_LIFECYCLE_V2.CANCELLED); const now = Date.now(); e.status = RUNNER_EXEC_LIFECYCLE_V2.CANCELLED; e.updatedAt = now; if (!e.settledAt) e.settledAt = now; if (reason) e.metadata.cancelReason = String(reason); return { ...e, metadata: { ...e.metadata } }; }
562
+ export function getRunnerExecV2(id) { const e = _resV2.get(id); if (!e) return null; return { ...e, metadata: { ...e.metadata } }; }
563
+ export function listRunnerExecsV2() { return [..._resV2.values()].map((e) => ({ ...e, metadata: { ...e.metadata } })); }
564
+
565
+ export function autoPauseIdleRunnerProfilesV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const p of _rpsV2.values()) if (p.status === RUNNER_PROFILE_MATURITY_V2.ACTIVE && (t - p.lastTouchedAt) >= _rpIdleMs) { p.status = RUNNER_PROFILE_MATURITY_V2.PAUSED; p.updatedAt = t; flipped.push(p.id); } return { flipped, count: flipped.length }; }
566
+ export function autoFailStuckRunnerExecsV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const e of _resV2.values()) if (e.status === RUNNER_EXEC_LIFECYCLE_V2.RUNNING && e.startedAt != null && (t - e.startedAt) >= _reStuckMs) { e.status = RUNNER_EXEC_LIFECYCLE_V2.FAILED; e.updatedAt = t; if (!e.settledAt) e.settledAt = t; e.metadata.failReason = "auto-fail-stuck"; flipped.push(e.id); } return { flipped, count: flipped.length }; }
567
+
568
+ export function getRunnerGovStatsV2() {
569
+ const profilesByStatus = {}; for (const s of Object.values(RUNNER_PROFILE_MATURITY_V2)) profilesByStatus[s] = 0; for (const p of _rpsV2.values()) profilesByStatus[p.status]++;
570
+ const execsByStatus = {}; for (const s of Object.values(RUNNER_EXEC_LIFECYCLE_V2)) execsByStatus[s] = 0; for (const e of _resV2.values()) execsByStatus[e.status]++;
571
+ return { totalRunnerProfilesV2: _rpsV2.size, totalRunnerExecsV2: _resV2.size, maxActiveRunnerProfilesPerOwner: _rpMaxActivePerOwner, maxPendingRunnerExecsPerProfile: _rpMaxPendingExecsPerProfile, runnerProfileIdleMs: _rpIdleMs, runnerExecStuckMs: _reStuckMs, profilesByStatus, execsByStatus };
572
+ }
@@ -1012,3 +1012,108 @@ export function getCrossChainStatsV2() {
1012
1012
  configuredChains: _chainConfigs.size,
1013
1013
  };
1014
1014
  }
1015
+
1016
+
1017
+ // ===== V2 Surface: Cross-Chain governance overlay (CLI v0.136.0) =====
1018
+ export const XCHAIN_CHANNEL_MATURITY_V2 = Object.freeze({
1019
+ PENDING: "pending", ACTIVE: "active", PAUSED: "paused", DECOMMISSIONED: "decommissioned",
1020
+ });
1021
+ export const XCHAIN_TRANSFER_LIFECYCLE_V2 = Object.freeze({
1022
+ QUEUED: "queued", RELAYING: "relaying", CONFIRMED: "confirmed", FAILED: "failed", CANCELLED: "cancelled",
1023
+ });
1024
+
1025
+ const _xcChanTrans = new Map([
1026
+ [XCHAIN_CHANNEL_MATURITY_V2.PENDING, new Set([XCHAIN_CHANNEL_MATURITY_V2.ACTIVE, XCHAIN_CHANNEL_MATURITY_V2.DECOMMISSIONED])],
1027
+ [XCHAIN_CHANNEL_MATURITY_V2.ACTIVE, new Set([XCHAIN_CHANNEL_MATURITY_V2.PAUSED, XCHAIN_CHANNEL_MATURITY_V2.DECOMMISSIONED])],
1028
+ [XCHAIN_CHANNEL_MATURITY_V2.PAUSED, new Set([XCHAIN_CHANNEL_MATURITY_V2.ACTIVE, XCHAIN_CHANNEL_MATURITY_V2.DECOMMISSIONED])],
1029
+ [XCHAIN_CHANNEL_MATURITY_V2.DECOMMISSIONED, new Set()],
1030
+ ]);
1031
+ const _xcChanTerminal = new Set([XCHAIN_CHANNEL_MATURITY_V2.DECOMMISSIONED]);
1032
+ const _xcTxTrans = new Map([
1033
+ [XCHAIN_TRANSFER_LIFECYCLE_V2.QUEUED, new Set([XCHAIN_TRANSFER_LIFECYCLE_V2.RELAYING, XCHAIN_TRANSFER_LIFECYCLE_V2.CANCELLED])],
1034
+ [XCHAIN_TRANSFER_LIFECYCLE_V2.RELAYING, new Set([XCHAIN_TRANSFER_LIFECYCLE_V2.CONFIRMED, XCHAIN_TRANSFER_LIFECYCLE_V2.FAILED, XCHAIN_TRANSFER_LIFECYCLE_V2.CANCELLED])],
1035
+ [XCHAIN_TRANSFER_LIFECYCLE_V2.CONFIRMED, new Set()],
1036
+ [XCHAIN_TRANSFER_LIFECYCLE_V2.FAILED, new Set()],
1037
+ [XCHAIN_TRANSFER_LIFECYCLE_V2.CANCELLED, new Set()],
1038
+ ]);
1039
+
1040
+ const _xcChans = new Map();
1041
+ const _xcTxs = new Map();
1042
+ let _xcMaxActivePerOwner = 10;
1043
+ let _xcMaxPendingPerChan = 20;
1044
+ let _xcChanIdleMs = 24 * 60 * 60 * 1000;
1045
+ let _xcTxStuckMs = 15 * 60 * 1000;
1046
+
1047
+ function _xcPos(n, lbl) { const v = Math.floor(Number(n)); if (!Number.isFinite(v) || v <= 0) throw new Error(`${lbl} must be positive integer`); return v; }
1048
+
1049
+ export function setMaxActiveXchainChannelsPerOwnerV2(n) { _xcMaxActivePerOwner = _xcPos(n, "maxActiveXchainChannelsPerOwner"); }
1050
+ export function getMaxActiveXchainChannelsPerOwnerV2() { return _xcMaxActivePerOwner; }
1051
+ export function setMaxPendingXchainTransfersPerChannelV2(n) { _xcMaxPendingPerChan = _xcPos(n, "maxPendingXchainTransfersPerChannel"); }
1052
+ export function getMaxPendingXchainTransfersPerChannelV2() { return _xcMaxPendingPerChan; }
1053
+ export function setXchainChannelIdleMsV2(n) { _xcChanIdleMs = _xcPos(n, "xchainChannelIdleMs"); }
1054
+ export function getXchainChannelIdleMsV2() { return _xcChanIdleMs; }
1055
+ export function setXchainTransferStuckMsV2(n) { _xcTxStuckMs = _xcPos(n, "xchainTransferStuckMs"); }
1056
+ export function getXchainTransferStuckMsV2() { return _xcTxStuckMs; }
1057
+
1058
+ export function _resetStateCrossChainV2() {
1059
+ _xcChans.clear(); _xcTxs.clear();
1060
+ _xcMaxActivePerOwner = 10; _xcMaxPendingPerChan = 20;
1061
+ _xcChanIdleMs = 24 * 60 * 60 * 1000; _xcTxStuckMs = 15 * 60 * 1000;
1062
+ }
1063
+
1064
+ export function registerXchainChannelV2({ id, owner, fromChain, toChain, metadata } = {}) {
1065
+ if (!id || typeof id !== "string") throw new Error("id is required");
1066
+ if (!owner || typeof owner !== "string") throw new Error("owner is required");
1067
+ if (_xcChans.has(id)) throw new Error(`xchain channel ${id} already registered`);
1068
+ const now = Date.now();
1069
+ const c = { id, owner, fromChain: fromChain || "", toChain: toChain || "", status: XCHAIN_CHANNEL_MATURITY_V2.PENDING, createdAt: now, updatedAt: now, activatedAt: null, decommissionedAt: null, lastTouchedAt: now, metadata: { ...(metadata || {}) } };
1070
+ _xcChans.set(id, c);
1071
+ return { ...c, metadata: { ...c.metadata } };
1072
+ }
1073
+ function _xcCheckC(from, to) { const a = _xcChanTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid xchain channel transition ${from} → ${to}`); }
1074
+ function _xcCountActive(owner) { let n = 0; for (const c of _xcChans.values()) if (c.owner === owner && c.status === XCHAIN_CHANNEL_MATURITY_V2.ACTIVE) n++; return n; }
1075
+
1076
+ export function activateXchainChannelV2(id) {
1077
+ const c = _xcChans.get(id); if (!c) throw new Error(`xchain channel ${id} not found`);
1078
+ _xcCheckC(c.status, XCHAIN_CHANNEL_MATURITY_V2.ACTIVE);
1079
+ const recovery = c.status === XCHAIN_CHANNEL_MATURITY_V2.PAUSED;
1080
+ if (!recovery) { const a = _xcCountActive(c.owner); if (a >= _xcMaxActivePerOwner) throw new Error(`max active xchain channels per owner (${_xcMaxActivePerOwner}) reached for ${c.owner}`); }
1081
+ const now = Date.now(); c.status = XCHAIN_CHANNEL_MATURITY_V2.ACTIVE; c.updatedAt = now; c.lastTouchedAt = now; if (!c.activatedAt) c.activatedAt = now;
1082
+ return { ...c, metadata: { ...c.metadata } };
1083
+ }
1084
+ export function pauseXchainChannelV2(id) { const c = _xcChans.get(id); if (!c) throw new Error(`xchain channel ${id} not found`); _xcCheckC(c.status, XCHAIN_CHANNEL_MATURITY_V2.PAUSED); c.status = XCHAIN_CHANNEL_MATURITY_V2.PAUSED; c.updatedAt = Date.now(); return { ...c, metadata: { ...c.metadata } }; }
1085
+ export function decommissionXchainChannelV2(id) { const c = _xcChans.get(id); if (!c) throw new Error(`xchain channel ${id} not found`); _xcCheckC(c.status, XCHAIN_CHANNEL_MATURITY_V2.DECOMMISSIONED); const now = Date.now(); c.status = XCHAIN_CHANNEL_MATURITY_V2.DECOMMISSIONED; c.updatedAt = now; if (!c.decommissionedAt) c.decommissionedAt = now; return { ...c, metadata: { ...c.metadata } }; }
1086
+ export function touchXchainChannelV2(id) { const c = _xcChans.get(id); if (!c) throw new Error(`xchain channel ${id} not found`); if (_xcChanTerminal.has(c.status)) throw new Error(`cannot touch terminal xchain channel ${id}`); const now = Date.now(); c.lastTouchedAt = now; c.updatedAt = now; return { ...c, metadata: { ...c.metadata } }; }
1087
+ export function getXchainChannelV2(id) { const c = _xcChans.get(id); if (!c) return null; return { ...c, metadata: { ...c.metadata } }; }
1088
+ export function listXchainChannelsV2() { return [..._xcChans.values()].map((c) => ({ ...c, metadata: { ...c.metadata } })); }
1089
+
1090
+ function _xcCountPending(cid) { let n = 0; for (const t of _xcTxs.values()) if (t.channelId === cid && (t.status === XCHAIN_TRANSFER_LIFECYCLE_V2.QUEUED || t.status === XCHAIN_TRANSFER_LIFECYCLE_V2.RELAYING)) n++; return n; }
1091
+
1092
+ export function createXchainTransferV2({ id, channelId, amount, metadata } = {}) {
1093
+ if (!id || typeof id !== "string") throw new Error("id is required");
1094
+ if (!channelId || typeof channelId !== "string") throw new Error("channelId is required");
1095
+ if (_xcTxs.has(id)) throw new Error(`xchain transfer ${id} already exists`);
1096
+ if (!_xcChans.has(channelId)) throw new Error(`xchain channel ${channelId} not found`);
1097
+ const pending = _xcCountPending(channelId);
1098
+ if (pending >= _xcMaxPendingPerChan) throw new Error(`max pending xchain transfers per channel (${_xcMaxPendingPerChan}) reached for ${channelId}`);
1099
+ const now = Date.now();
1100
+ const t = { id, channelId, amount: amount || "0", status: XCHAIN_TRANSFER_LIFECYCLE_V2.QUEUED, createdAt: now, updatedAt: now, startedAt: null, settledAt: null, metadata: { ...(metadata || {}) } };
1101
+ _xcTxs.set(id, t);
1102
+ return { ...t, metadata: { ...t.metadata } };
1103
+ }
1104
+ function _xcCheckT(from, to) { const a = _xcTxTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid xchain transfer transition ${from} → ${to}`); }
1105
+ export function startXchainTransferV2(id) { const t = _xcTxs.get(id); if (!t) throw new Error(`xchain transfer ${id} not found`); _xcCheckT(t.status, XCHAIN_TRANSFER_LIFECYCLE_V2.RELAYING); const now = Date.now(); t.status = XCHAIN_TRANSFER_LIFECYCLE_V2.RELAYING; t.updatedAt = now; if (!t.startedAt) t.startedAt = now; return { ...t, metadata: { ...t.metadata } }; }
1106
+ export function confirmXchainTransferV2(id) { const t = _xcTxs.get(id); if (!t) throw new Error(`xchain transfer ${id} not found`); _xcCheckT(t.status, XCHAIN_TRANSFER_LIFECYCLE_V2.CONFIRMED); const now = Date.now(); t.status = XCHAIN_TRANSFER_LIFECYCLE_V2.CONFIRMED; t.updatedAt = now; if (!t.settledAt) t.settledAt = now; return { ...t, metadata: { ...t.metadata } }; }
1107
+ export function failXchainTransferV2(id, reason) { const t = _xcTxs.get(id); if (!t) throw new Error(`xchain transfer ${id} not found`); _xcCheckT(t.status, XCHAIN_TRANSFER_LIFECYCLE_V2.FAILED); const now = Date.now(); t.status = XCHAIN_TRANSFER_LIFECYCLE_V2.FAILED; t.updatedAt = now; if (!t.settledAt) t.settledAt = now; if (reason) t.metadata.failReason = String(reason); return { ...t, metadata: { ...t.metadata } }; }
1108
+ export function cancelXchainTransferV2(id, reason) { const t = _xcTxs.get(id); if (!t) throw new Error(`xchain transfer ${id} not found`); _xcCheckT(t.status, XCHAIN_TRANSFER_LIFECYCLE_V2.CANCELLED); const now = Date.now(); t.status = XCHAIN_TRANSFER_LIFECYCLE_V2.CANCELLED; t.updatedAt = now; if (!t.settledAt) t.settledAt = now; if (reason) t.metadata.cancelReason = String(reason); return { ...t, metadata: { ...t.metadata } }; }
1109
+ export function getXchainTransferV2(id) { const t = _xcTxs.get(id); if (!t) return null; return { ...t, metadata: { ...t.metadata } }; }
1110
+ export function listXchainTransfersV2() { return [..._xcTxs.values()].map((t) => ({ ...t, metadata: { ...t.metadata } })); }
1111
+
1112
+ export function autoPauseIdleXchainChannelsV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const c of _xcChans.values()) if (c.status === XCHAIN_CHANNEL_MATURITY_V2.ACTIVE && (t - c.lastTouchedAt) >= _xcChanIdleMs) { c.status = XCHAIN_CHANNEL_MATURITY_V2.PAUSED; c.updatedAt = t; flipped.push(c.id); } return { flipped, count: flipped.length }; }
1113
+ export function autoFailStuckXchainTransfersV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const tx of _xcTxs.values()) if (tx.status === XCHAIN_TRANSFER_LIFECYCLE_V2.RELAYING && tx.startedAt != null && (t - tx.startedAt) >= _xcTxStuckMs) { tx.status = XCHAIN_TRANSFER_LIFECYCLE_V2.FAILED; tx.updatedAt = t; if (!tx.settledAt) tx.settledAt = t; tx.metadata.failReason = "auto-fail-stuck"; flipped.push(tx.id); } return { flipped, count: flipped.length }; }
1114
+
1115
+ export function getCrossChainGovStatsV2() {
1116
+ const channelsByStatus = {}; for (const s of Object.values(XCHAIN_CHANNEL_MATURITY_V2)) channelsByStatus[s] = 0; for (const c of _xcChans.values()) channelsByStatus[c.status]++;
1117
+ const transfersByStatus = {}; for (const s of Object.values(XCHAIN_TRANSFER_LIFECYCLE_V2)) transfersByStatus[s] = 0; for (const t of _xcTxs.values()) transfersByStatus[t.status]++;
1118
+ return { totalChannelsV2: _xcChans.size, totalTransfersV2: _xcTxs.size, maxActiveXchainChannelsPerOwner: _xcMaxActivePerOwner, maxPendingXchainTransfersPerChannel: _xcMaxPendingPerChan, xchainChannelIdleMs: _xcChanIdleMs, xchainTransferStuckMs: _xcTxStuckMs, channelsByStatus, transfersByStatus };
1119
+ }
@@ -863,3 +863,108 @@ export function _resetState() {
863
863
  maxSingleAllocation: 100000,
864
864
  };
865
865
  }
866
+
867
+
868
+ // ===== V2 Surface: DAO Governance overlay (CLI v0.136.0) =====
869
+ export const DAO_ORG_MATURITY_V2 = Object.freeze({
870
+ PENDING: "pending", ACTIVE: "active", PAUSED: "paused", DISSOLVED: "dissolved",
871
+ });
872
+ export const DAO_PROPOSAL_LIFECYCLE_V2 = Object.freeze({
873
+ QUEUED: "queued", VOTING: "voting", PASSED: "passed", FAILED: "failed", CANCELLED: "cancelled",
874
+ });
875
+
876
+ const _daoOrgTrans = new Map([
877
+ [DAO_ORG_MATURITY_V2.PENDING, new Set([DAO_ORG_MATURITY_V2.ACTIVE, DAO_ORG_MATURITY_V2.DISSOLVED])],
878
+ [DAO_ORG_MATURITY_V2.ACTIVE, new Set([DAO_ORG_MATURITY_V2.PAUSED, DAO_ORG_MATURITY_V2.DISSOLVED])],
879
+ [DAO_ORG_MATURITY_V2.PAUSED, new Set([DAO_ORG_MATURITY_V2.ACTIVE, DAO_ORG_MATURITY_V2.DISSOLVED])],
880
+ [DAO_ORG_MATURITY_V2.DISSOLVED, new Set()],
881
+ ]);
882
+ const _daoOrgTerminal = new Set([DAO_ORG_MATURITY_V2.DISSOLVED]);
883
+ const _daoPropTrans = new Map([
884
+ [DAO_PROPOSAL_LIFECYCLE_V2.QUEUED, new Set([DAO_PROPOSAL_LIFECYCLE_V2.VOTING, DAO_PROPOSAL_LIFECYCLE_V2.CANCELLED])],
885
+ [DAO_PROPOSAL_LIFECYCLE_V2.VOTING, new Set([DAO_PROPOSAL_LIFECYCLE_V2.PASSED, DAO_PROPOSAL_LIFECYCLE_V2.FAILED, DAO_PROPOSAL_LIFECYCLE_V2.CANCELLED])],
886
+ [DAO_PROPOSAL_LIFECYCLE_V2.PASSED, new Set()],
887
+ [DAO_PROPOSAL_LIFECYCLE_V2.FAILED, new Set()],
888
+ [DAO_PROPOSAL_LIFECYCLE_V2.CANCELLED, new Set()],
889
+ ]);
890
+
891
+ const _daoOrgs = new Map();
892
+ const _daoProps = new Map();
893
+ let _daoMaxActivePerOwner = 8;
894
+ let _daoMaxPendingPerOrg = 50;
895
+ let _daoOrgIdleMs = 7 * 24 * 60 * 60 * 1000;
896
+ let _daoPropStuckMs = 2 * 60 * 1000;
897
+
898
+ function _daoPos(n, lbl) { const v = Math.floor(Number(n)); if (!Number.isFinite(v) || v <= 0) throw new Error(`${lbl} must be positive integer`); return v; }
899
+
900
+ export function setMaxActiveDaoOrgsPerOwnerV2(n) { _daoMaxActivePerOwner = _daoPos(n, "maxActiveDaoOrgsPerOwner"); }
901
+ export function getMaxActiveDaoOrgsPerOwnerV2() { return _daoMaxActivePerOwner; }
902
+ export function setMaxPendingDaoProposalsPerOrgV2(n) { _daoMaxPendingPerOrg = _daoPos(n, "maxPendingDaoProposalsPerOrg"); }
903
+ export function getMaxPendingDaoProposalsPerOrgV2() { return _daoMaxPendingPerOrg; }
904
+ export function setDaoOrgIdleMsV2(n) { _daoOrgIdleMs = _daoPos(n, "daoOrgIdleMs"); }
905
+ export function getDaoOrgIdleMsV2() { return _daoOrgIdleMs; }
906
+ export function setDaoProposalStuckMsV2(n) { _daoPropStuckMs = _daoPos(n, "daoProposalStuckMs"); }
907
+ export function getDaoProposalStuckMsV2() { return _daoPropStuckMs; }
908
+
909
+ export function _resetStateDaoGovernanceV2() {
910
+ _daoOrgs.clear(); _daoProps.clear();
911
+ _daoMaxActivePerOwner = 8; _daoMaxPendingPerOrg = 50;
912
+ _daoOrgIdleMs = 7 * 24 * 60 * 60 * 1000; _daoPropStuckMs = 2 * 60 * 1000;
913
+ }
914
+
915
+ export function registerDaoOrgV2({ id, owner, name, metadata } = {}) {
916
+ if (!id || typeof id !== "string") throw new Error("id is required");
917
+ if (!owner || typeof owner !== "string") throw new Error("owner is required");
918
+ if (_daoOrgs.has(id)) throw new Error(`dao org ${id} already registered`);
919
+ const now = Date.now();
920
+ const o = { id, owner, name: name || id, status: DAO_ORG_MATURITY_V2.PENDING, createdAt: now, updatedAt: now, activatedAt: null, dissolvedAt: null, lastTouchedAt: now, metadata: { ...(metadata || {}) } };
921
+ _daoOrgs.set(id, o);
922
+ return { ...o, metadata: { ...o.metadata } };
923
+ }
924
+ function _daoCheckO(from, to) { const a = _daoOrgTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid dao org transition ${from} → ${to}`); }
925
+ function _daoCountActive(owner) { let n = 0; for (const o of _daoOrgs.values()) if (o.owner === owner && o.status === DAO_ORG_MATURITY_V2.ACTIVE) n++; return n; }
926
+
927
+ export function activateDaoOrgV2(id) {
928
+ const o = _daoOrgs.get(id); if (!o) throw new Error(`dao org ${id} not found`);
929
+ _daoCheckO(o.status, DAO_ORG_MATURITY_V2.ACTIVE);
930
+ const recovery = o.status === DAO_ORG_MATURITY_V2.PAUSED;
931
+ if (!recovery) { const a = _daoCountActive(o.owner); if (a >= _daoMaxActivePerOwner) throw new Error(`max active dao orgs per owner (${_daoMaxActivePerOwner}) reached for ${o.owner}`); }
932
+ const now = Date.now(); o.status = DAO_ORG_MATURITY_V2.ACTIVE; o.updatedAt = now; o.lastTouchedAt = now; if (!o.activatedAt) o.activatedAt = now;
933
+ return { ...o, metadata: { ...o.metadata } };
934
+ }
935
+ export function pauseDaoOrgV2(id) { const o = _daoOrgs.get(id); if (!o) throw new Error(`dao org ${id} not found`); _daoCheckO(o.status, DAO_ORG_MATURITY_V2.PAUSED); o.status = DAO_ORG_MATURITY_V2.PAUSED; o.updatedAt = Date.now(); return { ...o, metadata: { ...o.metadata } }; }
936
+ export function dissolveDaoOrgV2(id) { const o = _daoOrgs.get(id); if (!o) throw new Error(`dao org ${id} not found`); _daoCheckO(o.status, DAO_ORG_MATURITY_V2.DISSOLVED); const now = Date.now(); o.status = DAO_ORG_MATURITY_V2.DISSOLVED; o.updatedAt = now; if (!o.dissolvedAt) o.dissolvedAt = now; return { ...o, metadata: { ...o.metadata } }; }
937
+ export function touchDaoOrgV2(id) { const o = _daoOrgs.get(id); if (!o) throw new Error(`dao org ${id} not found`); if (_daoOrgTerminal.has(o.status)) throw new Error(`cannot touch terminal dao org ${id}`); const now = Date.now(); o.lastTouchedAt = now; o.updatedAt = now; return { ...o, metadata: { ...o.metadata } }; }
938
+ export function getDaoOrgV2(id) { const o = _daoOrgs.get(id); if (!o) return null; return { ...o, metadata: { ...o.metadata } }; }
939
+ export function listDaoOrgsV2() { return [..._daoOrgs.values()].map((o) => ({ ...o, metadata: { ...o.metadata } })); }
940
+
941
+ function _daoCountPending(oid) { let n = 0; for (const p of _daoProps.values()) if (p.orgId === oid && (p.status === DAO_PROPOSAL_LIFECYCLE_V2.QUEUED || p.status === DAO_PROPOSAL_LIFECYCLE_V2.VOTING)) n++; return n; }
942
+
943
+ export function createDaoProposalV2({ id, orgId, title, metadata } = {}) {
944
+ if (!id || typeof id !== "string") throw new Error("id is required");
945
+ if (!orgId || typeof orgId !== "string") throw new Error("orgId is required");
946
+ if (_daoProps.has(id)) throw new Error(`dao proposal ${id} already exists`);
947
+ if (!_daoOrgs.has(orgId)) throw new Error(`dao org ${orgId} not found`);
948
+ const pending = _daoCountPending(orgId);
949
+ if (pending >= _daoMaxPendingPerOrg) throw new Error(`max pending dao proposals per org (${_daoMaxPendingPerOrg}) reached for ${orgId}`);
950
+ const now = Date.now();
951
+ const p = { id, orgId, title: title || id, status: DAO_PROPOSAL_LIFECYCLE_V2.QUEUED, createdAt: now, updatedAt: now, startedAt: null, settledAt: null, metadata: { ...(metadata || {}) } };
952
+ _daoProps.set(id, p);
953
+ return { ...p, metadata: { ...p.metadata } };
954
+ }
955
+ function _daoCheckP(from, to) { const a = _daoPropTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid dao proposal transition ${from} → ${to}`); }
956
+ export function startDaoProposalV2(id) { const p = _daoProps.get(id); if (!p) throw new Error(`dao proposal ${id} not found`); _daoCheckP(p.status, DAO_PROPOSAL_LIFECYCLE_V2.VOTING); const now = Date.now(); p.status = DAO_PROPOSAL_LIFECYCLE_V2.VOTING; p.updatedAt = now; if (!p.startedAt) p.startedAt = now; return { ...p, metadata: { ...p.metadata } }; }
957
+ export function passDaoProposalV2(id) { const p = _daoProps.get(id); if (!p) throw new Error(`dao proposal ${id} not found`); _daoCheckP(p.status, DAO_PROPOSAL_LIFECYCLE_V2.PASSED); const now = Date.now(); p.status = DAO_PROPOSAL_LIFECYCLE_V2.PASSED; p.updatedAt = now; if (!p.settledAt) p.settledAt = now; return { ...p, metadata: { ...p.metadata } }; }
958
+ export function failDaoProposalV2(id, reason) { const p = _daoProps.get(id); if (!p) throw new Error(`dao proposal ${id} not found`); _daoCheckP(p.status, DAO_PROPOSAL_LIFECYCLE_V2.FAILED); const now = Date.now(); p.status = DAO_PROPOSAL_LIFECYCLE_V2.FAILED; p.updatedAt = now; if (!p.settledAt) p.settledAt = now; if (reason) p.metadata.failReason = String(reason); return { ...p, metadata: { ...p.metadata } }; }
959
+ export function cancelDaoProposalV2(id, reason) { const p = _daoProps.get(id); if (!p) throw new Error(`dao proposal ${id} not found`); _daoCheckP(p.status, DAO_PROPOSAL_LIFECYCLE_V2.CANCELLED); const now = Date.now(); p.status = DAO_PROPOSAL_LIFECYCLE_V2.CANCELLED; p.updatedAt = now; if (!p.settledAt) p.settledAt = now; if (reason) p.metadata.cancelReason = String(reason); return { ...p, metadata: { ...p.metadata } }; }
960
+ export function getDaoProposalV2(id) { const p = _daoProps.get(id); if (!p) return null; return { ...p, metadata: { ...p.metadata } }; }
961
+ export function listDaoProposalsV2() { return [..._daoProps.values()].map((p) => ({ ...p, metadata: { ...p.metadata } })); }
962
+
963
+ export function autoPauseIdleDaoOrgsV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const o of _daoOrgs.values()) if (o.status === DAO_ORG_MATURITY_V2.ACTIVE && (t - o.lastTouchedAt) >= _daoOrgIdleMs) { o.status = DAO_ORG_MATURITY_V2.PAUSED; o.updatedAt = t; flipped.push(o.id); } return { flipped, count: flipped.length }; }
964
+ export function autoFailStuckDaoProposalsV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const p of _daoProps.values()) if (p.status === DAO_PROPOSAL_LIFECYCLE_V2.VOTING && p.startedAt != null && (t - p.startedAt) >= _daoPropStuckMs) { p.status = DAO_PROPOSAL_LIFECYCLE_V2.FAILED; p.updatedAt = t; if (!p.settledAt) p.settledAt = t; p.metadata.failReason = "auto-fail-stuck"; flipped.push(p.id); } return { flipped, count: flipped.length }; }
965
+
966
+ export function getDaoGovernanceGovStatsV2() {
967
+ const orgsByStatus = {}; for (const s of Object.values(DAO_ORG_MATURITY_V2)) orgsByStatus[s] = 0; for (const o of _daoOrgs.values()) orgsByStatus[o.status]++;
968
+ const proposalsByStatus = {}; for (const s of Object.values(DAO_PROPOSAL_LIFECYCLE_V2)) proposalsByStatus[s] = 0; for (const p of _daoProps.values()) proposalsByStatus[p.status]++;
969
+ return { totalOrgsV2: _daoOrgs.size, totalProposalsV2: _daoProps.size, maxActiveDaoOrgsPerOwner: _daoMaxActivePerOwner, maxPendingDaoProposalsPerOrg: _daoMaxPendingPerOrg, daoOrgIdleMs: _daoOrgIdleMs, daoProposalStuckMs: _daoPropStuckMs, orgsByStatus, proposalsByStatus };
970
+ }
@@ -691,3 +691,108 @@ export function getHighestUnresolvedSeverity() {
691
691
  }
692
692
 
693
693
  export { _v2PolicyMeta, _v2IncidentMeta, _builtinPolicyTemplates };
694
+
695
+
696
+ // ===== V2 Surface: DLP Engine governance overlay (CLI v0.135.0) =====
697
+ export const DLP_POLICY_MATURITY_V2 = Object.freeze({
698
+ PENDING: "pending", ACTIVE: "active", SUSPENDED: "suspended", RETIRED: "retired",
699
+ });
700
+ export const DLP_SCAN_LIFECYCLE_V2 = Object.freeze({
701
+ QUEUED: "queued", SCANNING: "scanning", COMPLETED: "completed", FAILED: "failed", CANCELLED: "cancelled",
702
+ });
703
+
704
+ const _dlpPolTrans = new Map([
705
+ [DLP_POLICY_MATURITY_V2.PENDING, new Set([DLP_POLICY_MATURITY_V2.ACTIVE, DLP_POLICY_MATURITY_V2.RETIRED])],
706
+ [DLP_POLICY_MATURITY_V2.ACTIVE, new Set([DLP_POLICY_MATURITY_V2.SUSPENDED, DLP_POLICY_MATURITY_V2.RETIRED])],
707
+ [DLP_POLICY_MATURITY_V2.SUSPENDED, new Set([DLP_POLICY_MATURITY_V2.ACTIVE, DLP_POLICY_MATURITY_V2.RETIRED])],
708
+ [DLP_POLICY_MATURITY_V2.RETIRED, new Set()],
709
+ ]);
710
+ const _dlpPolTerminal = new Set([DLP_POLICY_MATURITY_V2.RETIRED]);
711
+ const _dlpScanTrans = new Map([
712
+ [DLP_SCAN_LIFECYCLE_V2.QUEUED, new Set([DLP_SCAN_LIFECYCLE_V2.SCANNING, DLP_SCAN_LIFECYCLE_V2.CANCELLED])],
713
+ [DLP_SCAN_LIFECYCLE_V2.SCANNING, new Set([DLP_SCAN_LIFECYCLE_V2.COMPLETED, DLP_SCAN_LIFECYCLE_V2.FAILED, DLP_SCAN_LIFECYCLE_V2.CANCELLED])],
714
+ [DLP_SCAN_LIFECYCLE_V2.COMPLETED, new Set()],
715
+ [DLP_SCAN_LIFECYCLE_V2.FAILED, new Set()],
716
+ [DLP_SCAN_LIFECYCLE_V2.CANCELLED, new Set()],
717
+ ]);
718
+
719
+ const _dlpPols = new Map();
720
+ const _dlpScans = new Map();
721
+ let _dlpMaxActivePerOwner = 16;
722
+ let _dlpMaxPendingPerPol = 20;
723
+ let _dlpPolIdleMs = 12 * 60 * 60 * 1000;
724
+ let _dlpScanStuckMs = 5 * 60 * 1000;
725
+
726
+ function _dlpPos(n, lbl) { const v = Math.floor(Number(n)); if (!Number.isFinite(v) || v <= 0) throw new Error(`${lbl} must be positive integer`); return v; }
727
+
728
+ export function setMaxActiveDlpPoliciesPerOwnerV2(n) { _dlpMaxActivePerOwner = _dlpPos(n, "maxActiveDlpPoliciesPerOwner"); }
729
+ export function getMaxActiveDlpPoliciesPerOwnerV2() { return _dlpMaxActivePerOwner; }
730
+ export function setMaxPendingDlpScansPerPolicyV2(n) { _dlpMaxPendingPerPol = _dlpPos(n, "maxPendingDlpScansPerPolicy"); }
731
+ export function getMaxPendingDlpScansPerPolicyV2() { return _dlpMaxPendingPerPol; }
732
+ export function setDlpPolicyIdleMsV2(n) { _dlpPolIdleMs = _dlpPos(n, "dlpPolicyIdleMs"); }
733
+ export function getDlpPolicyIdleMsV2() { return _dlpPolIdleMs; }
734
+ export function setDlpScanStuckMsV2(n) { _dlpScanStuckMs = _dlpPos(n, "dlpScanStuckMs"); }
735
+ export function getDlpScanStuckMsV2() { return _dlpScanStuckMs; }
736
+
737
+ export function _resetStateDlpEngineV2() {
738
+ _dlpPols.clear(); _dlpScans.clear();
739
+ _dlpMaxActivePerOwner = 16; _dlpMaxPendingPerPol = 20;
740
+ _dlpPolIdleMs = 12 * 60 * 60 * 1000; _dlpScanStuckMs = 5 * 60 * 1000;
741
+ }
742
+
743
+ export function registerDlpPolicyV2({ id, owner, classification, metadata } = {}) {
744
+ if (!id || typeof id !== "string") throw new Error("id is required");
745
+ if (!owner || typeof owner !== "string") throw new Error("owner is required");
746
+ if (_dlpPols.has(id)) throw new Error(`dlp policy ${id} already registered`);
747
+ const now = Date.now();
748
+ const p = { id, owner, classification: classification || "internal", status: DLP_POLICY_MATURITY_V2.PENDING, createdAt: now, updatedAt: now, activatedAt: null, retiredAt: null, lastTouchedAt: now, metadata: { ...(metadata || {}) } };
749
+ _dlpPols.set(id, p);
750
+ return { ...p, metadata: { ...p.metadata } };
751
+ }
752
+ function _dlpCheckP(from, to) { const a = _dlpPolTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid dlp policy transition ${from} → ${to}`); }
753
+ function _dlpCountActive(owner) { let n = 0; for (const p of _dlpPols.values()) if (p.owner === owner && p.status === DLP_POLICY_MATURITY_V2.ACTIVE) n++; return n; }
754
+
755
+ export function activateDlpPolicyV2(id) {
756
+ const p = _dlpPols.get(id); if (!p) throw new Error(`dlp policy ${id} not found`);
757
+ _dlpCheckP(p.status, DLP_POLICY_MATURITY_V2.ACTIVE);
758
+ const recovery = p.status === DLP_POLICY_MATURITY_V2.SUSPENDED;
759
+ if (!recovery) { const a = _dlpCountActive(p.owner); if (a >= _dlpMaxActivePerOwner) throw new Error(`max active dlp policies per owner (${_dlpMaxActivePerOwner}) reached for ${p.owner}`); }
760
+ const now = Date.now(); p.status = DLP_POLICY_MATURITY_V2.ACTIVE; p.updatedAt = now; p.lastTouchedAt = now; if (!p.activatedAt) p.activatedAt = now;
761
+ return { ...p, metadata: { ...p.metadata } };
762
+ }
763
+ export function suspendDlpPolicyV2(id) { const p = _dlpPols.get(id); if (!p) throw new Error(`dlp policy ${id} not found`); _dlpCheckP(p.status, DLP_POLICY_MATURITY_V2.SUSPENDED); p.status = DLP_POLICY_MATURITY_V2.SUSPENDED; p.updatedAt = Date.now(); return { ...p, metadata: { ...p.metadata } }; }
764
+ export function retireDlpPolicyV2(id) { const p = _dlpPols.get(id); if (!p) throw new Error(`dlp policy ${id} not found`); _dlpCheckP(p.status, DLP_POLICY_MATURITY_V2.RETIRED); const now = Date.now(); p.status = DLP_POLICY_MATURITY_V2.RETIRED; p.updatedAt = now; if (!p.retiredAt) p.retiredAt = now; return { ...p, metadata: { ...p.metadata } }; }
765
+ export function touchDlpPolicyV2(id) { const p = _dlpPols.get(id); if (!p) throw new Error(`dlp policy ${id} not found`); if (_dlpPolTerminal.has(p.status)) throw new Error(`cannot touch terminal dlp policy ${id}`); const now = Date.now(); p.lastTouchedAt = now; p.updatedAt = now; return { ...p, metadata: { ...p.metadata } }; }
766
+ export function getDlpPolicyV2(id) { const p = _dlpPols.get(id); if (!p) return null; return { ...p, metadata: { ...p.metadata } }; }
767
+ export function listDlpPoliciesV2() { return [..._dlpPols.values()].map((p) => ({ ...p, metadata: { ...p.metadata } })); }
768
+
769
+ function _dlpCountPending(pid) { let n = 0; for (const s of _dlpScans.values()) if (s.policyId === pid && (s.status === DLP_SCAN_LIFECYCLE_V2.QUEUED || s.status === DLP_SCAN_LIFECYCLE_V2.SCANNING)) n++; return n; }
770
+
771
+ export function createDlpScanV2({ id, policyId, target, metadata } = {}) {
772
+ if (!id || typeof id !== "string") throw new Error("id is required");
773
+ if (!policyId || typeof policyId !== "string") throw new Error("policyId is required");
774
+ if (_dlpScans.has(id)) throw new Error(`dlp scan ${id} already exists`);
775
+ if (!_dlpPols.has(policyId)) throw new Error(`dlp policy ${policyId} not found`);
776
+ const pending = _dlpCountPending(policyId);
777
+ if (pending >= _dlpMaxPendingPerPol) throw new Error(`max pending dlp scans per policy (${_dlpMaxPendingPerPol}) reached for ${policyId}`);
778
+ const now = Date.now();
779
+ const s = { id, policyId, target: target || "", status: DLP_SCAN_LIFECYCLE_V2.QUEUED, createdAt: now, updatedAt: now, startedAt: null, settledAt: null, metadata: { ...(metadata || {}) } };
780
+ _dlpScans.set(id, s);
781
+ return { ...s, metadata: { ...s.metadata } };
782
+ }
783
+ function _dlpCheckS(from, to) { const a = _dlpScanTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid dlp scan transition ${from} → ${to}`); }
784
+ export function startDlpScanV2(id) { const s = _dlpScans.get(id); if (!s) throw new Error(`dlp scan ${id} not found`); _dlpCheckS(s.status, DLP_SCAN_LIFECYCLE_V2.SCANNING); const now = Date.now(); s.status = DLP_SCAN_LIFECYCLE_V2.SCANNING; s.updatedAt = now; if (!s.startedAt) s.startedAt = now; return { ...s, metadata: { ...s.metadata } }; }
785
+ export function completeDlpScanV2(id) { const s = _dlpScans.get(id); if (!s) throw new Error(`dlp scan ${id} not found`); _dlpCheckS(s.status, DLP_SCAN_LIFECYCLE_V2.COMPLETED); const now = Date.now(); s.status = DLP_SCAN_LIFECYCLE_V2.COMPLETED; s.updatedAt = now; if (!s.settledAt) s.settledAt = now; return { ...s, metadata: { ...s.metadata } }; }
786
+ export function failDlpScanV2(id, reason) { const s = _dlpScans.get(id); if (!s) throw new Error(`dlp scan ${id} not found`); _dlpCheckS(s.status, DLP_SCAN_LIFECYCLE_V2.FAILED); const now = Date.now(); s.status = DLP_SCAN_LIFECYCLE_V2.FAILED; s.updatedAt = now; if (!s.settledAt) s.settledAt = now; if (reason) s.metadata.failReason = String(reason); return { ...s, metadata: { ...s.metadata } }; }
787
+ export function cancelDlpScanV2(id, reason) { const s = _dlpScans.get(id); if (!s) throw new Error(`dlp scan ${id} not found`); _dlpCheckS(s.status, DLP_SCAN_LIFECYCLE_V2.CANCELLED); const now = Date.now(); s.status = DLP_SCAN_LIFECYCLE_V2.CANCELLED; s.updatedAt = now; if (!s.settledAt) s.settledAt = now; if (reason) s.metadata.cancelReason = String(reason); return { ...s, metadata: { ...s.metadata } }; }
788
+ export function getDlpScanV2(id) { const s = _dlpScans.get(id); if (!s) return null; return { ...s, metadata: { ...s.metadata } }; }
789
+ export function listDlpScansV2() { return [..._dlpScans.values()].map((s) => ({ ...s, metadata: { ...s.metadata } })); }
790
+
791
+ export function autoSuspendIdleDlpPoliciesV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const p of _dlpPols.values()) if (p.status === DLP_POLICY_MATURITY_V2.ACTIVE && (t - p.lastTouchedAt) >= _dlpPolIdleMs) { p.status = DLP_POLICY_MATURITY_V2.SUSPENDED; p.updatedAt = t; flipped.push(p.id); } return { flipped, count: flipped.length }; }
792
+ export function autoFailStuckDlpScansV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const s of _dlpScans.values()) if (s.status === DLP_SCAN_LIFECYCLE_V2.SCANNING && s.startedAt != null && (t - s.startedAt) >= _dlpScanStuckMs) { s.status = DLP_SCAN_LIFECYCLE_V2.FAILED; s.updatedAt = t; if (!s.settledAt) s.settledAt = t; s.metadata.failReason = "auto-fail-stuck"; flipped.push(s.id); } return { flipped, count: flipped.length }; }
793
+
794
+ export function getDlpEngineStatsV2() {
795
+ const policiesByStatus = {}; for (const s of Object.values(DLP_POLICY_MATURITY_V2)) policiesByStatus[s] = 0; for (const p of _dlpPols.values()) policiesByStatus[p.status]++;
796
+ const scansByStatus = {}; for (const s of Object.values(DLP_SCAN_LIFECYCLE_V2)) scansByStatus[s] = 0; for (const sc of _dlpScans.values()) scansByStatus[sc.status]++;
797
+ return { totalPoliciesV2: _dlpPols.size, totalScansV2: _dlpScans.size, maxActiveDlpPoliciesPerOwner: _dlpMaxActivePerOwner, maxPendingDlpScansPerPolicy: _dlpMaxPendingPerPol, dlpPolicyIdleMs: _dlpPolIdleMs, dlpScanStuckMs: _dlpScanStuckMs, policiesByStatus, scansByStatus };
798
+ }
@@ -959,3 +959,108 @@ export function _resetV2State() {
959
959
  _v2Config.predictionHorizonMs = 86400000;
960
960
  _v2Config.growthLogRetentionDays = 365;
961
961
  }
962
+
963
+
964
+ // ===== V2 Surface: Evolution System governance overlay (CLI v0.137.0) =====
965
+ export const EVO_GOAL_MATURITY_V2 = Object.freeze({
966
+ PENDING: "pending", ACTIVE: "active", PAUSED: "paused", ARCHIVED: "archived",
967
+ });
968
+ export const EVO_CYCLE_LIFECYCLE_V2 = Object.freeze({
969
+ QUEUED: "queued", RUNNING: "running", COMPLETED: "completed", FAILED: "failed", CANCELLED: "cancelled",
970
+ });
971
+
972
+ const _evoGoalTrans = new Map([
973
+ [EVO_GOAL_MATURITY_V2.PENDING, new Set([EVO_GOAL_MATURITY_V2.ACTIVE, EVO_GOAL_MATURITY_V2.ARCHIVED])],
974
+ [EVO_GOAL_MATURITY_V2.ACTIVE, new Set([EVO_GOAL_MATURITY_V2.PAUSED, EVO_GOAL_MATURITY_V2.ARCHIVED])],
975
+ [EVO_GOAL_MATURITY_V2.PAUSED, new Set([EVO_GOAL_MATURITY_V2.ACTIVE, EVO_GOAL_MATURITY_V2.ARCHIVED])],
976
+ [EVO_GOAL_MATURITY_V2.ARCHIVED, new Set()],
977
+ ]);
978
+ const _evoGoalTerminal = new Set([EVO_GOAL_MATURITY_V2.ARCHIVED]);
979
+ const _evoCycleTrans = new Map([
980
+ [EVO_CYCLE_LIFECYCLE_V2.QUEUED, new Set([EVO_CYCLE_LIFECYCLE_V2.RUNNING, EVO_CYCLE_LIFECYCLE_V2.CANCELLED])],
981
+ [EVO_CYCLE_LIFECYCLE_V2.RUNNING, new Set([EVO_CYCLE_LIFECYCLE_V2.COMPLETED, EVO_CYCLE_LIFECYCLE_V2.FAILED, EVO_CYCLE_LIFECYCLE_V2.CANCELLED])],
982
+ [EVO_CYCLE_LIFECYCLE_V2.COMPLETED, new Set()],
983
+ [EVO_CYCLE_LIFECYCLE_V2.FAILED, new Set()],
984
+ [EVO_CYCLE_LIFECYCLE_V2.CANCELLED, new Set()],
985
+ ]);
986
+
987
+ const _evoGoals = new Map();
988
+ const _evoCycles = new Map();
989
+ let _evoMaxActivePerOwner = 6;
990
+ let _evoMaxPendingPerGoal = 12;
991
+ let _evoGoalIdleMs = 14 * 24 * 60 * 60 * 1000;
992
+ let _evoCycleStuckMs = 10 * 60 * 1000;
993
+
994
+ function _evoPos(n, lbl) { const v = Math.floor(Number(n)); if (!Number.isFinite(v) || v <= 0) throw new Error(`${lbl} must be positive integer`); return v; }
995
+
996
+ export function setMaxActiveEvoGoalsPerOwnerV2(n) { _evoMaxActivePerOwner = _evoPos(n, "maxActiveEvoGoalsPerOwner"); }
997
+ export function getMaxActiveEvoGoalsPerOwnerV2() { return _evoMaxActivePerOwner; }
998
+ export function setMaxPendingEvoCyclesPerGoalV2(n) { _evoMaxPendingPerGoal = _evoPos(n, "maxPendingEvoCyclesPerGoal"); }
999
+ export function getMaxPendingEvoCyclesPerGoalV2() { return _evoMaxPendingPerGoal; }
1000
+ export function setEvoGoalIdleMsV2(n) { _evoGoalIdleMs = _evoPos(n, "evoGoalIdleMs"); }
1001
+ export function getEvoGoalIdleMsV2() { return _evoGoalIdleMs; }
1002
+ export function setEvoCycleStuckMsV2(n) { _evoCycleStuckMs = _evoPos(n, "evoCycleStuckMs"); }
1003
+ export function getEvoCycleStuckMsV2() { return _evoCycleStuckMs; }
1004
+
1005
+ export function _resetStateEvolutionSystemV2() {
1006
+ _evoGoals.clear(); _evoCycles.clear();
1007
+ _evoMaxActivePerOwner = 6; _evoMaxPendingPerGoal = 12;
1008
+ _evoGoalIdleMs = 14 * 24 * 60 * 60 * 1000; _evoCycleStuckMs = 10 * 60 * 1000;
1009
+ }
1010
+
1011
+ export function registerEvoGoalV2({ id, owner, objective, metadata } = {}) {
1012
+ if (!id || typeof id !== "string") throw new Error("id is required");
1013
+ if (!owner || typeof owner !== "string") throw new Error("owner is required");
1014
+ if (_evoGoals.has(id)) throw new Error(`evo goal ${id} already registered`);
1015
+ const now = Date.now();
1016
+ const g = { id, owner, objective: objective || "", status: EVO_GOAL_MATURITY_V2.PENDING, createdAt: now, updatedAt: now, activatedAt: null, archivedAt: null, lastTouchedAt: now, metadata: { ...(metadata || {}) } };
1017
+ _evoGoals.set(id, g);
1018
+ return { ...g, metadata: { ...g.metadata } };
1019
+ }
1020
+ function _evoCheckG(from, to) { const a = _evoGoalTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid evo goal transition ${from} → ${to}`); }
1021
+ function _evoCountActive(owner) { let n = 0; for (const g of _evoGoals.values()) if (g.owner === owner && g.status === EVO_GOAL_MATURITY_V2.ACTIVE) n++; return n; }
1022
+
1023
+ export function activateEvoGoalV2(id) {
1024
+ const g = _evoGoals.get(id); if (!g) throw new Error(`evo goal ${id} not found`);
1025
+ _evoCheckG(g.status, EVO_GOAL_MATURITY_V2.ACTIVE);
1026
+ const recovery = g.status === EVO_GOAL_MATURITY_V2.PAUSED;
1027
+ if (!recovery) { const a = _evoCountActive(g.owner); if (a >= _evoMaxActivePerOwner) throw new Error(`max active evo goals per owner (${_evoMaxActivePerOwner}) reached for ${g.owner}`); }
1028
+ const now = Date.now(); g.status = EVO_GOAL_MATURITY_V2.ACTIVE; g.updatedAt = now; g.lastTouchedAt = now; if (!g.activatedAt) g.activatedAt = now;
1029
+ return { ...g, metadata: { ...g.metadata } };
1030
+ }
1031
+ export function pauseEvoGoalV2(id) { const g = _evoGoals.get(id); if (!g) throw new Error(`evo goal ${id} not found`); _evoCheckG(g.status, EVO_GOAL_MATURITY_V2.PAUSED); g.status = EVO_GOAL_MATURITY_V2.PAUSED; g.updatedAt = Date.now(); return { ...g, metadata: { ...g.metadata } }; }
1032
+ export function archiveEvoGoalV2(id) { const g = _evoGoals.get(id); if (!g) throw new Error(`evo goal ${id} not found`); _evoCheckG(g.status, EVO_GOAL_MATURITY_V2.ARCHIVED); const now = Date.now(); g.status = EVO_GOAL_MATURITY_V2.ARCHIVED; g.updatedAt = now; if (!g.archivedAt) g.archivedAt = now; return { ...g, metadata: { ...g.metadata } }; }
1033
+ export function touchEvoGoalV2(id) { const g = _evoGoals.get(id); if (!g) throw new Error(`evo goal ${id} not found`); if (_evoGoalTerminal.has(g.status)) throw new Error(`cannot touch terminal evo goal ${id}`); const now = Date.now(); g.lastTouchedAt = now; g.updatedAt = now; return { ...g, metadata: { ...g.metadata } }; }
1034
+ export function getEvoGoalV2(id) { const g = _evoGoals.get(id); if (!g) return null; return { ...g, metadata: { ...g.metadata } }; }
1035
+ export function listEvoGoalsV2() { return [..._evoGoals.values()].map((g) => ({ ...g, metadata: { ...g.metadata } })); }
1036
+
1037
+ function _evoCountPending(gid) { let n = 0; for (const c of _evoCycles.values()) if (c.goalId === gid && (c.status === EVO_CYCLE_LIFECYCLE_V2.QUEUED || c.status === EVO_CYCLE_LIFECYCLE_V2.RUNNING)) n++; return n; }
1038
+
1039
+ export function createEvoCycleV2({ id, goalId, generation, metadata } = {}) {
1040
+ if (!id || typeof id !== "string") throw new Error("id is required");
1041
+ if (!goalId || typeof goalId !== "string") throw new Error("goalId is required");
1042
+ if (_evoCycles.has(id)) throw new Error(`evo cycle ${id} already exists`);
1043
+ if (!_evoGoals.has(goalId)) throw new Error(`evo goal ${goalId} not found`);
1044
+ const pending = _evoCountPending(goalId);
1045
+ if (pending >= _evoMaxPendingPerGoal) throw new Error(`max pending evo cycles per goal (${_evoMaxPendingPerGoal}) reached for ${goalId}`);
1046
+ const now = Date.now();
1047
+ const c = { id, goalId, generation: generation ?? 0, status: EVO_CYCLE_LIFECYCLE_V2.QUEUED, createdAt: now, updatedAt: now, startedAt: null, settledAt: null, metadata: { ...(metadata || {}) } };
1048
+ _evoCycles.set(id, c);
1049
+ return { ...c, metadata: { ...c.metadata } };
1050
+ }
1051
+ function _evoCheckC(from, to) { const a = _evoCycleTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid evo cycle transition ${from} → ${to}`); }
1052
+ export function startEvoCycleV2(id) { const c = _evoCycles.get(id); if (!c) throw new Error(`evo cycle ${id} not found`); _evoCheckC(c.status, EVO_CYCLE_LIFECYCLE_V2.RUNNING); const now = Date.now(); c.status = EVO_CYCLE_LIFECYCLE_V2.RUNNING; c.updatedAt = now; if (!c.startedAt) c.startedAt = now; return { ...c, metadata: { ...c.metadata } }; }
1053
+ export function completeEvoCycleV2(id) { const c = _evoCycles.get(id); if (!c) throw new Error(`evo cycle ${id} not found`); _evoCheckC(c.status, EVO_CYCLE_LIFECYCLE_V2.COMPLETED); const now = Date.now(); c.status = EVO_CYCLE_LIFECYCLE_V2.COMPLETED; c.updatedAt = now; if (!c.settledAt) c.settledAt = now; return { ...c, metadata: { ...c.metadata } }; }
1054
+ export function failEvoCycleV2(id, reason) { const c = _evoCycles.get(id); if (!c) throw new Error(`evo cycle ${id} not found`); _evoCheckC(c.status, EVO_CYCLE_LIFECYCLE_V2.FAILED); const now = Date.now(); c.status = EVO_CYCLE_LIFECYCLE_V2.FAILED; c.updatedAt = now; if (!c.settledAt) c.settledAt = now; if (reason) c.metadata.failReason = String(reason); return { ...c, metadata: { ...c.metadata } }; }
1055
+ export function cancelEvoCycleV2(id, reason) { const c = _evoCycles.get(id); if (!c) throw new Error(`evo cycle ${id} not found`); _evoCheckC(c.status, EVO_CYCLE_LIFECYCLE_V2.CANCELLED); const now = Date.now(); c.status = EVO_CYCLE_LIFECYCLE_V2.CANCELLED; c.updatedAt = now; if (!c.settledAt) c.settledAt = now; if (reason) c.metadata.cancelReason = String(reason); return { ...c, metadata: { ...c.metadata } }; }
1056
+ export function getEvoCycleV2(id) { const c = _evoCycles.get(id); if (!c) return null; return { ...c, metadata: { ...c.metadata } }; }
1057
+ export function listEvoCyclesV2() { return [..._evoCycles.values()].map((c) => ({ ...c, metadata: { ...c.metadata } })); }
1058
+
1059
+ export function autoPauseIdleEvoGoalsV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const g of _evoGoals.values()) if (g.status === EVO_GOAL_MATURITY_V2.ACTIVE && (t - g.lastTouchedAt) >= _evoGoalIdleMs) { g.status = EVO_GOAL_MATURITY_V2.PAUSED; g.updatedAt = t; flipped.push(g.id); } return { flipped, count: flipped.length }; }
1060
+ export function autoFailStuckEvoCyclesV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const c of _evoCycles.values()) if (c.status === EVO_CYCLE_LIFECYCLE_V2.RUNNING && c.startedAt != null && (t - c.startedAt) >= _evoCycleStuckMs) { c.status = EVO_CYCLE_LIFECYCLE_V2.FAILED; c.updatedAt = t; if (!c.settledAt) c.settledAt = t; c.metadata.failReason = "auto-fail-stuck"; flipped.push(c.id); } return { flipped, count: flipped.length }; }
1061
+
1062
+ export function getEvolutionSystemGovStatsV2() {
1063
+ const goalsByStatus = {}; for (const s of Object.values(EVO_GOAL_MATURITY_V2)) goalsByStatus[s] = 0; for (const g of _evoGoals.values()) goalsByStatus[g.status]++;
1064
+ const cyclesByStatus = {}; for (const s of Object.values(EVO_CYCLE_LIFECYCLE_V2)) cyclesByStatus[s] = 0; for (const c of _evoCycles.values()) cyclesByStatus[c.status]++;
1065
+ return { totalGoalsV2: _evoGoals.size, totalCyclesV2: _evoCycles.size, maxActiveEvoGoalsPerOwner: _evoMaxActivePerOwner, maxPendingEvoCyclesPerGoal: _evoMaxPendingPerGoal, evoGoalIdleMs: _evoGoalIdleMs, evoCycleStuckMs: _evoCycleStuckMs, goalsByStatus, cyclesByStatus };
1066
+ }