chainlesschain 0.143.0 → 0.152.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 (227) hide show
  1. package/package.json +1 -1
  2. package/src/commands/a2a.js +196 -28
  3. package/src/commands/activitypub.js +364 -27
  4. package/src/commands/agent-network.js +217 -0
  5. package/src/commands/agent.js +587 -103
  6. package/src/commands/audit.js +206 -0
  7. package/src/commands/automation.js +201 -0
  8. package/src/commands/bi.js +355 -27
  9. package/src/commands/bm25.js +111 -27
  10. package/src/commands/browse.js +403 -29
  11. package/src/commands/ccron.js +128 -28
  12. package/src/commands/chat.js +207 -0
  13. package/src/commands/codegen.js +207 -0
  14. package/src/commands/collab.js +211 -0
  15. package/src/commands/compliance.js +824 -34
  16. package/src/commands/compt.js +127 -29
  17. package/src/commands/consol.js +8 -2
  18. package/src/commands/cowork.js +783 -34
  19. package/src/commands/crosschain.js +182 -28
  20. package/src/commands/dao.js +182 -28
  21. package/src/commands/dbevo.js +227 -0
  22. package/src/commands/dev.js +207 -0
  23. package/src/commands/did-v2.js +217 -0
  24. package/src/commands/did.js +221 -0
  25. package/src/commands/dlp.js +385 -27
  26. package/src/commands/economy.js +205 -50
  27. package/src/commands/evolution.js +203 -50
  28. package/src/commands/evomap.js +387 -27
  29. package/src/commands/export.js +213 -0
  30. package/src/commands/federation.js +209 -0
  31. package/src/commands/fflag.js +74 -22
  32. package/src/commands/fusion.js +205 -0
  33. package/src/commands/git.js +177 -37
  34. package/src/commands/governance.js +209 -0
  35. package/src/commands/hardening.js +209 -0
  36. package/src/commands/hmemory.js +204 -50
  37. package/src/commands/hook.js +209 -0
  38. package/src/commands/import.js +209 -0
  39. package/src/commands/incentive.js +209 -0
  40. package/src/commands/inference.js +170 -34
  41. package/src/commands/infra.js +203 -0
  42. package/src/commands/instinct.js +209 -0
  43. package/src/commands/ipfs.js +207 -0
  44. package/src/commands/itbudget.js +149 -33
  45. package/src/commands/kg.js +206 -0
  46. package/src/commands/llm.js +217 -0
  47. package/src/commands/lowcode.js +195 -38
  48. package/src/commands/marketplace.js +206 -0
  49. package/src/commands/matrix.js +386 -27
  50. package/src/commands/mcp.js +217 -0
  51. package/src/commands/mcpscaf.js +145 -33
  52. package/src/commands/meminj.js +145 -33
  53. package/src/commands/memory.js +209 -0
  54. package/src/commands/multimodal.js +203 -0
  55. package/src/commands/nlprog.js +225 -0
  56. package/src/commands/nostr.js +387 -27
  57. package/src/commands/note.js +205 -0
  58. package/src/commands/ops.js +219 -0
  59. package/src/commands/orchestrate.js +217 -0
  60. package/src/commands/orchgov.js +144 -33
  61. package/src/commands/org.js +209 -0
  62. package/src/commands/p2p.js +209 -0
  63. package/src/commands/pdfp.js +109 -27
  64. package/src/commands/perception.js +209 -0
  65. package/src/commands/perf.js +169 -32
  66. package/src/commands/perm.js +144 -33
  67. package/src/commands/permmem.js +203 -0
  68. package/src/commands/pipeline.js +207 -52
  69. package/src/commands/planmode.js +141 -32
  70. package/src/commands/plugin-ecosystem.js +209 -0
  71. package/src/commands/pqc.js +213 -0
  72. package/src/commands/privacy.js +203 -0
  73. package/src/commands/promcomp.js +111 -27
  74. package/src/commands/quantization.js +207 -0
  75. package/src/commands/rcache.js +205 -0
  76. package/src/commands/recommend.js +410 -34
  77. package/src/commands/reputation.js +208 -0
  78. package/src/commands/runtime.js +205 -0
  79. package/src/commands/sandbox.js +206 -0
  80. package/src/commands/scim.js +209 -0
  81. package/src/commands/seshhook.js +145 -33
  82. package/src/commands/seshsearch.js +141 -33
  83. package/src/commands/seshtail.js +144 -33
  84. package/src/commands/seshu.js +152 -33
  85. package/src/commands/session.js +209 -0
  86. package/src/commands/sganal.js +123 -29
  87. package/src/commands/siem.js +201 -34
  88. package/src/commands/skill.js +207 -0
  89. package/src/commands/sla.js +212 -0
  90. package/src/commands/slotfill.js +146 -33
  91. package/src/commands/social.js +358 -32
  92. package/src/commands/sso.js +209 -0
  93. package/src/commands/stress.js +206 -0
  94. package/src/commands/svccont.js +145 -33
  95. package/src/commands/sync.js +209 -0
  96. package/src/commands/tech.js +209 -0
  97. package/src/commands/tenant.js +217 -0
  98. package/src/commands/terraform.js +206 -0
  99. package/src/commands/tms.js +171 -33
  100. package/src/commands/tokens.js +209 -0
  101. package/src/commands/topiccls.js +146 -33
  102. package/src/commands/trust.js +217 -0
  103. package/src/commands/uprof.js +141 -32
  104. package/src/commands/vcheck.js +122 -28
  105. package/src/commands/wallet.js +209 -0
  106. package/src/commands/webfetch.js +141 -32
  107. package/src/commands/workflow.js +203 -0
  108. package/src/commands/zkp.js +184 -28
  109. package/src/index.js +180 -0
  110. package/src/lib/a2a-protocol.js +319 -51
  111. package/src/lib/activitypub-bridge.js +622 -50
  112. package/src/lib/agent-economy.js +304 -51
  113. package/src/lib/agent-network.js +341 -0
  114. package/src/lib/aiops.js +346 -0
  115. package/src/lib/app-builder.js +279 -46
  116. package/src/lib/audit-logger.js +321 -0
  117. package/src/lib/automation-engine.js +335 -0
  118. package/src/lib/autonomous-agent.js +284 -48
  119. package/src/lib/autonomous-developer.js +332 -0
  120. package/src/lib/bi-engine.js +616 -49
  121. package/src/lib/bm25-search.js +301 -49
  122. package/src/lib/browser-automation.js +630 -49
  123. package/src/lib/chat-core.js +336 -0
  124. package/src/lib/claude-code-bridge.js +341 -0
  125. package/src/lib/code-agent.js +339 -0
  126. package/src/lib/collaboration-governance.js +334 -0
  127. package/src/lib/community-governance.js +346 -0
  128. package/src/lib/compliance-framework-reporter.js +305 -51
  129. package/src/lib/compliance-manager.js +330 -0
  130. package/src/lib/compression-telemetry.js +301 -49
  131. package/src/lib/content-recommendation.js +351 -0
  132. package/src/lib/content-recommender.js +317 -52
  133. package/src/lib/cowork-cron.js +298 -49
  134. package/src/lib/cowork-learning.js +333 -0
  135. package/src/lib/cowork-share.js +338 -0
  136. package/src/lib/cowork-task-runner.js +308 -51
  137. package/src/lib/cowork-workflow.js +327 -0
  138. package/src/lib/cross-chain.js +311 -51
  139. package/src/lib/dao-governance.js +280 -46
  140. package/src/lib/dbevo.js +351 -0
  141. package/src/lib/decentral-infra.js +330 -0
  142. package/src/lib/did-manager.js +341 -0
  143. package/src/lib/did-v2-manager.js +341 -0
  144. package/src/lib/dlp-engine.js +626 -49
  145. package/src/lib/evolution-system.js +278 -47
  146. package/src/lib/evomap-governance.js +334 -0
  147. package/src/lib/evomap-manager.js +280 -46
  148. package/src/lib/execution-backend.js +294 -48
  149. package/src/lib/feature-flags.js +294 -49
  150. package/src/lib/federation-hardening.js +340 -0
  151. package/src/lib/git-integration.js +285 -47
  152. package/src/lib/hardening-manager.js +341 -0
  153. package/src/lib/hierarchical-memory.js +284 -48
  154. package/src/lib/hook-manager.js +341 -0
  155. package/src/lib/inference-network.js +308 -51
  156. package/src/lib/instinct-manager.js +346 -0
  157. package/src/lib/ipfs-storage.js +334 -0
  158. package/src/lib/iteration-budget.js +302 -50
  159. package/src/lib/knowledge-exporter.js +341 -0
  160. package/src/lib/knowledge-graph.js +333 -0
  161. package/src/lib/knowledge-importer.js +341 -0
  162. package/src/lib/llm-providers.js +346 -0
  163. package/src/lib/matrix-bridge.js +620 -47
  164. package/src/lib/mcp-registry.js +346 -0
  165. package/src/lib/mcp-scaffold.js +318 -54
  166. package/src/lib/memory-injection.js +288 -49
  167. package/src/lib/memory-manager.js +336 -0
  168. package/src/lib/multimodal.js +330 -0
  169. package/src/lib/nl-programming.js +341 -0
  170. package/src/lib/nostr-bridge.js +622 -49
  171. package/src/lib/note-versioning.js +339 -0
  172. package/src/lib/orchestrator.js +293 -48
  173. package/src/lib/org-manager.js +336 -0
  174. package/src/lib/p2p-manager.js +341 -0
  175. package/src/lib/pdf-parser.js +298 -49
  176. package/src/lib/perception.js +346 -0
  177. package/src/lib/perf-tuning.js +309 -50
  178. package/src/lib/permanent-memory.js +327 -0
  179. package/src/lib/permission-engine.js +287 -49
  180. package/src/lib/pipeline-orchestrator.js +289 -49
  181. package/src/lib/plan-mode.js +298 -51
  182. package/src/lib/plugin-ecosystem.js +346 -0
  183. package/src/lib/pqc-manager.js +346 -0
  184. package/src/lib/privacy-computing.js +335 -0
  185. package/src/lib/protocol-fusion.js +338 -0
  186. package/src/lib/quantization.js +337 -0
  187. package/src/lib/reputation-optimizer.js +340 -0
  188. package/src/lib/response-cache.js +333 -0
  189. package/src/lib/sandbox-v2.js +327 -0
  190. package/src/lib/scim-manager.js +346 -0
  191. package/src/lib/service-container.js +313 -52
  192. package/src/lib/session-consolidator.js +296 -49
  193. package/src/lib/session-hooks.js +312 -53
  194. package/src/lib/session-manager.js +334 -0
  195. package/src/lib/session-search.js +304 -51
  196. package/src/lib/session-tail.js +288 -49
  197. package/src/lib/session-usage.js +298 -52
  198. package/src/lib/siem-exporter.js +298 -51
  199. package/src/lib/skill-loader.js +334 -0
  200. package/src/lib/skill-marketplace.js +345 -0
  201. package/src/lib/sla-manager.js +341 -0
  202. package/src/lib/slot-filler.js +303 -51
  203. package/src/lib/social-graph-analytics.js +295 -49
  204. package/src/lib/social-graph.js +272 -49
  205. package/src/lib/social-manager.js +330 -0
  206. package/src/lib/sso-manager.js +340 -0
  207. package/src/lib/stress-tester.js +342 -0
  208. package/src/lib/sub-agent-registry.js +302 -53
  209. package/src/lib/sync-manager.js +336 -0
  210. package/src/lib/task-model-selector.js +302 -50
  211. package/src/lib/tech-learning-engine.js +341 -0
  212. package/src/lib/tenant-saas.js +341 -0
  213. package/src/lib/terraform-manager.js +333 -0
  214. package/src/lib/threat-intel.js +330 -0
  215. package/src/lib/todo-manager.js +281 -47
  216. package/src/lib/token-incentive.js +341 -0
  217. package/src/lib/token-tracker.js +336 -0
  218. package/src/lib/topic-classifier.js +297 -49
  219. package/src/lib/trust-security.js +343 -0
  220. package/src/lib/ueba.js +340 -0
  221. package/src/lib/universal-runtime.js +330 -0
  222. package/src/lib/user-profile.js +294 -50
  223. package/src/lib/version-checker.js +304 -50
  224. package/src/lib/wallet-manager.js +336 -0
  225. package/src/lib/web-fetch.js +292 -51
  226. package/src/lib/workflow-engine.js +330 -0
  227. package/src/lib/zkp-engine.js +286 -49
@@ -409,81 +409,304 @@ export function _resetState() {
409
409
 
410
410
  // ===== V2 Surface: Social Graph governance overlay (CLI v0.141.0) =====
411
411
  export const SG_NODE_MATURITY_V2 = Object.freeze({
412
- PENDING: "pending", ACTIVE: "active", INACTIVE: "inactive", REMOVED: "removed",
412
+ PENDING: "pending",
413
+ ACTIVE: "active",
414
+ INACTIVE: "inactive",
415
+ REMOVED: "removed",
413
416
  });
414
417
  export const SG_EDGE_LIFECYCLE_V2 = Object.freeze({
415
- PROPOSED: "proposed", ESTABLISHED: "established", SEVERED: "severed", EXPIRED: "expired", CANCELLED: "cancelled",
418
+ PROPOSED: "proposed",
419
+ ESTABLISHED: "established",
420
+ SEVERED: "severed",
421
+ EXPIRED: "expired",
422
+ CANCELLED: "cancelled",
416
423
  });
417
424
  const _sgNTrans = new Map([
418
- [SG_NODE_MATURITY_V2.PENDING, new Set([SG_NODE_MATURITY_V2.ACTIVE, SG_NODE_MATURITY_V2.REMOVED])],
419
- [SG_NODE_MATURITY_V2.ACTIVE, new Set([SG_NODE_MATURITY_V2.INACTIVE, SG_NODE_MATURITY_V2.REMOVED])],
420
- [SG_NODE_MATURITY_V2.INACTIVE, new Set([SG_NODE_MATURITY_V2.ACTIVE, SG_NODE_MATURITY_V2.REMOVED])],
425
+ [
426
+ SG_NODE_MATURITY_V2.PENDING,
427
+ new Set([SG_NODE_MATURITY_V2.ACTIVE, SG_NODE_MATURITY_V2.REMOVED]),
428
+ ],
429
+ [
430
+ SG_NODE_MATURITY_V2.ACTIVE,
431
+ new Set([SG_NODE_MATURITY_V2.INACTIVE, SG_NODE_MATURITY_V2.REMOVED]),
432
+ ],
433
+ [
434
+ SG_NODE_MATURITY_V2.INACTIVE,
435
+ new Set([SG_NODE_MATURITY_V2.ACTIVE, SG_NODE_MATURITY_V2.REMOVED]),
436
+ ],
421
437
  [SG_NODE_MATURITY_V2.REMOVED, new Set()],
422
438
  ]);
423
439
  const _sgNTerminal = new Set([SG_NODE_MATURITY_V2.REMOVED]);
424
440
  const _sgETrans = new Map([
425
- [SG_EDGE_LIFECYCLE_V2.PROPOSED, new Set([SG_EDGE_LIFECYCLE_V2.ESTABLISHED, SG_EDGE_LIFECYCLE_V2.CANCELLED])],
426
- [SG_EDGE_LIFECYCLE_V2.ESTABLISHED, new Set([SG_EDGE_LIFECYCLE_V2.SEVERED, SG_EDGE_LIFECYCLE_V2.EXPIRED])],
441
+ [
442
+ SG_EDGE_LIFECYCLE_V2.PROPOSED,
443
+ new Set([SG_EDGE_LIFECYCLE_V2.ESTABLISHED, SG_EDGE_LIFECYCLE_V2.CANCELLED]),
444
+ ],
445
+ [
446
+ SG_EDGE_LIFECYCLE_V2.ESTABLISHED,
447
+ new Set([SG_EDGE_LIFECYCLE_V2.SEVERED, SG_EDGE_LIFECYCLE_V2.EXPIRED]),
448
+ ],
427
449
  [SG_EDGE_LIFECYCLE_V2.SEVERED, new Set()],
428
450
  [SG_EDGE_LIFECYCLE_V2.EXPIRED, new Set()],
429
451
  [SG_EDGE_LIFECYCLE_V2.CANCELLED, new Set()],
430
452
  ]);
431
453
  const _sgNsV2 = new Map();
432
454
  const _sgEsV2 = new Map();
433
- let _sgMaxActivePerOwner = 50, _sgMaxPendingEdgesPerNode = 100, _sgIdleMs = 60 * 24 * 60 * 60 * 1000, _sgStuckMs = 14 * 24 * 60 * 60 * 1000;
434
- function _sgPos(n, label) { const v = Math.floor(Number(n)); if (!Number.isFinite(v) || v <= 0) throw new Error(`${label} must be positive integer`); return v; }
435
- function _sgCheckN(from, to) { const a = _sgNTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid sg node transition ${from} → ${to}`); }
436
- function _sgCheckE(from, to) { const a = _sgETrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid sg edge transition ${from} → ${to}`); }
437
- export function setMaxActiveSgNodesPerOwnerV2(n) { _sgMaxActivePerOwner = _sgPos(n, "maxActiveSgNodesPerOwner"); }
438
- export function getMaxActiveSgNodesPerOwnerV2() { return _sgMaxActivePerOwner; }
439
- export function setMaxPendingSgEdgesPerNodeV2(n) { _sgMaxPendingEdgesPerNode = _sgPos(n, "maxPendingSgEdgesPerNode"); }
440
- export function getMaxPendingSgEdgesPerNodeV2() { return _sgMaxPendingEdgesPerNode; }
441
- export function setSgNodeIdleMsV2(n) { _sgIdleMs = _sgPos(n, "sgNodeIdleMs"); }
442
- export function getSgNodeIdleMsV2() { return _sgIdleMs; }
443
- export function setSgEdgeStuckMsV2(n) { _sgStuckMs = _sgPos(n, "sgEdgeStuckMs"); }
444
- export function getSgEdgeStuckMsV2() { return _sgStuckMs; }
445
- export function _resetStateSocialGraphV2() { _sgNsV2.clear(); _sgEsV2.clear(); _sgMaxActivePerOwner = 50; _sgMaxPendingEdgesPerNode = 100; _sgIdleMs = 60 * 24 * 60 * 60 * 1000; _sgStuckMs = 14 * 24 * 60 * 60 * 1000; }
455
+ let _sgMaxActivePerOwner = 50,
456
+ _sgMaxPendingEdgesPerNode = 100,
457
+ _sgIdleMs = 60 * 24 * 60 * 60 * 1000,
458
+ _sgStuckMs = 14 * 24 * 60 * 60 * 1000;
459
+ function _sgPos(n, label) {
460
+ const v = Math.floor(Number(n));
461
+ if (!Number.isFinite(v) || v <= 0)
462
+ throw new Error(`${label} must be positive integer`);
463
+ return v;
464
+ }
465
+ function _sgCheckN(from, to) {
466
+ const a = _sgNTrans.get(from);
467
+ if (!a || !a.has(to))
468
+ throw new Error(`invalid sg node transition ${from} → ${to}`);
469
+ }
470
+ function _sgCheckE(from, to) {
471
+ const a = _sgETrans.get(from);
472
+ if (!a || !a.has(to))
473
+ throw new Error(`invalid sg edge transition ${from} → ${to}`);
474
+ }
475
+ export function setMaxActiveSgNodesPerOwnerV2(n) {
476
+ _sgMaxActivePerOwner = _sgPos(n, "maxActiveSgNodesPerOwner");
477
+ }
478
+ export function getMaxActiveSgNodesPerOwnerV2() {
479
+ return _sgMaxActivePerOwner;
480
+ }
481
+ export function setMaxPendingSgEdgesPerNodeV2(n) {
482
+ _sgMaxPendingEdgesPerNode = _sgPos(n, "maxPendingSgEdgesPerNode");
483
+ }
484
+ export function getMaxPendingSgEdgesPerNodeV2() {
485
+ return _sgMaxPendingEdgesPerNode;
486
+ }
487
+ export function setSgNodeIdleMsV2(n) {
488
+ _sgIdleMs = _sgPos(n, "sgNodeIdleMs");
489
+ }
490
+ export function getSgNodeIdleMsV2() {
491
+ return _sgIdleMs;
492
+ }
493
+ export function setSgEdgeStuckMsV2(n) {
494
+ _sgStuckMs = _sgPos(n, "sgEdgeStuckMs");
495
+ }
496
+ export function getSgEdgeStuckMsV2() {
497
+ return _sgStuckMs;
498
+ }
499
+ export function _resetStateSocialGraphV2() {
500
+ _sgNsV2.clear();
501
+ _sgEsV2.clear();
502
+ _sgMaxActivePerOwner = 50;
503
+ _sgMaxPendingEdgesPerNode = 100;
504
+ _sgIdleMs = 60 * 24 * 60 * 60 * 1000;
505
+ _sgStuckMs = 14 * 24 * 60 * 60 * 1000;
506
+ }
446
507
  export function registerSgNodeV2({ id, owner, handle, metadata } = {}) {
447
- if (!id) throw new Error("sg node id required"); if (!owner) throw new Error("sg node owner required");
508
+ if (!id) throw new Error("sg node id required");
509
+ if (!owner) throw new Error("sg node owner required");
448
510
  if (_sgNsV2.has(id)) throw new Error(`sg node ${id} already registered`);
449
511
  const now = Date.now();
450
- const n = { id, owner, handle: handle || id, status: SG_NODE_MATURITY_V2.PENDING, createdAt: now, updatedAt: now, activatedAt: null, removedAt: null, lastTouchedAt: now, metadata: { ...(metadata || {}) } };
451
- _sgNsV2.set(id, n); return { ...n, metadata: { ...n.metadata } };
512
+ const n = {
513
+ id,
514
+ owner,
515
+ handle: handle || id,
516
+ status: SG_NODE_MATURITY_V2.PENDING,
517
+ createdAt: now,
518
+ updatedAt: now,
519
+ activatedAt: null,
520
+ removedAt: null,
521
+ lastTouchedAt: now,
522
+ metadata: { ...(metadata || {}) },
523
+ };
524
+ _sgNsV2.set(id, n);
525
+ return { ...n, metadata: { ...n.metadata } };
526
+ }
527
+ function _sgCountActive(owner) {
528
+ let n = 0;
529
+ for (const v of _sgNsV2.values())
530
+ if (v.owner === owner && v.status === SG_NODE_MATURITY_V2.ACTIVE) n++;
531
+ return n;
452
532
  }
453
- function _sgCountActive(owner) { let n = 0; for (const v of _sgNsV2.values()) if (v.owner === owner && v.status === SG_NODE_MATURITY_V2.ACTIVE) n++; return n; }
454
533
  export function activateSgNodeV2(id) {
455
- const n = _sgNsV2.get(id); if (!n) throw new Error(`sg node ${id} not found`);
534
+ const n = _sgNsV2.get(id);
535
+ if (!n) throw new Error(`sg node ${id} not found`);
456
536
  _sgCheckN(n.status, SG_NODE_MATURITY_V2.ACTIVE);
457
537
  const recovery = n.status === SG_NODE_MATURITY_V2.INACTIVE;
458
- if (!recovery && _sgCountActive(n.owner) >= _sgMaxActivePerOwner) throw new Error(`max active sg nodes for owner ${n.owner} reached`);
459
- const now = Date.now(); n.status = SG_NODE_MATURITY_V2.ACTIVE; n.updatedAt = now; n.lastTouchedAt = now; if (!n.activatedAt) n.activatedAt = now;
538
+ if (!recovery && _sgCountActive(n.owner) >= _sgMaxActivePerOwner)
539
+ throw new Error(`max active sg nodes for owner ${n.owner} reached`);
540
+ const now = Date.now();
541
+ n.status = SG_NODE_MATURITY_V2.ACTIVE;
542
+ n.updatedAt = now;
543
+ n.lastTouchedAt = now;
544
+ if (!n.activatedAt) n.activatedAt = now;
545
+ return { ...n, metadata: { ...n.metadata } };
546
+ }
547
+ export function deactivateSgNodeV2(id) {
548
+ const n = _sgNsV2.get(id);
549
+ if (!n) throw new Error(`sg node ${id} not found`);
550
+ _sgCheckN(n.status, SG_NODE_MATURITY_V2.INACTIVE);
551
+ n.status = SG_NODE_MATURITY_V2.INACTIVE;
552
+ n.updatedAt = Date.now();
553
+ return { ...n, metadata: { ...n.metadata } };
554
+ }
555
+ export function removeSgNodeV2(id) {
556
+ const n = _sgNsV2.get(id);
557
+ if (!n) throw new Error(`sg node ${id} not found`);
558
+ _sgCheckN(n.status, SG_NODE_MATURITY_V2.REMOVED);
559
+ const now = Date.now();
560
+ n.status = SG_NODE_MATURITY_V2.REMOVED;
561
+ n.updatedAt = now;
562
+ if (!n.removedAt) n.removedAt = now;
563
+ return { ...n, metadata: { ...n.metadata } };
564
+ }
565
+ export function touchSgNodeV2(id) {
566
+ const n = _sgNsV2.get(id);
567
+ if (!n) throw new Error(`sg node ${id} not found`);
568
+ if (_sgNTerminal.has(n.status))
569
+ throw new Error(`cannot touch terminal sg node ${id}`);
570
+ const now = Date.now();
571
+ n.lastTouchedAt = now;
572
+ n.updatedAt = now;
573
+ return { ...n, metadata: { ...n.metadata } };
574
+ }
575
+ export function getSgNodeV2(id) {
576
+ const n = _sgNsV2.get(id);
577
+ if (!n) return null;
460
578
  return { ...n, metadata: { ...n.metadata } };
461
579
  }
462
- export function deactivateSgNodeV2(id) { const n = _sgNsV2.get(id); if (!n) throw new Error(`sg node ${id} not found`); _sgCheckN(n.status, SG_NODE_MATURITY_V2.INACTIVE); n.status = SG_NODE_MATURITY_V2.INACTIVE; n.updatedAt = Date.now(); return { ...n, metadata: { ...n.metadata } }; }
463
- export function removeSgNodeV2(id) { const n = _sgNsV2.get(id); if (!n) throw new Error(`sg node ${id} not found`); _sgCheckN(n.status, SG_NODE_MATURITY_V2.REMOVED); const now = Date.now(); n.status = SG_NODE_MATURITY_V2.REMOVED; n.updatedAt = now; if (!n.removedAt) n.removedAt = now; return { ...n, metadata: { ...n.metadata } }; }
464
- export function touchSgNodeV2(id) { const n = _sgNsV2.get(id); if (!n) throw new Error(`sg node ${id} not found`); if (_sgNTerminal.has(n.status)) throw new Error(`cannot touch terminal sg node ${id}`); const now = Date.now(); n.lastTouchedAt = now; n.updatedAt = now; return { ...n, metadata: { ...n.metadata } }; }
465
- export function getSgNodeV2(id) { const n = _sgNsV2.get(id); if (!n) return null; return { ...n, metadata: { ...n.metadata } }; }
466
- export function listSgNodesV2() { return [..._sgNsV2.values()].map((n) => ({ ...n, metadata: { ...n.metadata } })); }
467
- function _sgCountPending(nodeId) { let n = 0; for (const e of _sgEsV2.values()) if (e.nodeId === nodeId && e.status === SG_EDGE_LIFECYCLE_V2.PROPOSED) n++; return n; }
580
+ export function listSgNodesV2() {
581
+ return [..._sgNsV2.values()].map((n) => ({
582
+ ...n,
583
+ metadata: { ...n.metadata },
584
+ }));
585
+ }
586
+ function _sgCountPending(nodeId) {
587
+ let n = 0;
588
+ for (const e of _sgEsV2.values())
589
+ if (e.nodeId === nodeId && e.status === SG_EDGE_LIFECYCLE_V2.PROPOSED) n++;
590
+ return n;
591
+ }
468
592
  export function createSgEdgeV2({ id, nodeId, targetId, metadata } = {}) {
469
- if (!id) throw new Error("sg edge id required"); if (!nodeId) throw new Error("sg edge nodeId required");
593
+ if (!id) throw new Error("sg edge id required");
594
+ if (!nodeId) throw new Error("sg edge nodeId required");
470
595
  if (_sgEsV2.has(id)) throw new Error(`sg edge ${id} already exists`);
471
596
  if (!_sgNsV2.has(nodeId)) throw new Error(`sg node ${nodeId} not found`);
472
- if (_sgCountPending(nodeId) >= _sgMaxPendingEdgesPerNode) throw new Error(`max pending sg edges for node ${nodeId} reached`);
597
+ if (_sgCountPending(nodeId) >= _sgMaxPendingEdgesPerNode)
598
+ throw new Error(`max pending sg edges for node ${nodeId} reached`);
599
+ const now = Date.now();
600
+ const e = {
601
+ id,
602
+ nodeId,
603
+ targetId: targetId || "",
604
+ status: SG_EDGE_LIFECYCLE_V2.PROPOSED,
605
+ createdAt: now,
606
+ updatedAt: now,
607
+ startedAt: now,
608
+ settledAt: null,
609
+ metadata: { ...(metadata || {}) },
610
+ };
611
+ _sgEsV2.set(id, e);
612
+ return { ...e, metadata: { ...e.metadata } };
613
+ }
614
+ export function establishSgEdgeV2(id) {
615
+ const e = _sgEsV2.get(id);
616
+ if (!e) throw new Error(`sg edge ${id} not found`);
617
+ _sgCheckE(e.status, SG_EDGE_LIFECYCLE_V2.ESTABLISHED);
618
+ const now = Date.now();
619
+ e.status = SG_EDGE_LIFECYCLE_V2.ESTABLISHED;
620
+ e.updatedAt = now;
621
+ if (!e.settledAt) e.settledAt = now;
622
+ return { ...e, metadata: { ...e.metadata } };
623
+ }
624
+ export function severSgEdgeV2(id, reason) {
625
+ const e = _sgEsV2.get(id);
626
+ if (!e) throw new Error(`sg edge ${id} not found`);
627
+ _sgCheckE(e.status, SG_EDGE_LIFECYCLE_V2.SEVERED);
628
+ const now = Date.now();
629
+ e.status = SG_EDGE_LIFECYCLE_V2.SEVERED;
630
+ e.updatedAt = now;
631
+ if (reason) e.metadata.severReason = String(reason);
632
+ return { ...e, metadata: { ...e.metadata } };
633
+ }
634
+ export function expireSgEdgeV2(id) {
635
+ const e = _sgEsV2.get(id);
636
+ if (!e) throw new Error(`sg edge ${id} not found`);
637
+ _sgCheckE(e.status, SG_EDGE_LIFECYCLE_V2.EXPIRED);
638
+ const now = Date.now();
639
+ e.status = SG_EDGE_LIFECYCLE_V2.EXPIRED;
640
+ e.updatedAt = now;
641
+ return { ...e, metadata: { ...e.metadata } };
642
+ }
643
+ export function cancelSgEdgeV2(id, reason) {
644
+ const e = _sgEsV2.get(id);
645
+ if (!e) throw new Error(`sg edge ${id} not found`);
646
+ _sgCheckE(e.status, SG_EDGE_LIFECYCLE_V2.CANCELLED);
473
647
  const now = Date.now();
474
- const e = { id, nodeId, targetId: targetId || "", status: SG_EDGE_LIFECYCLE_V2.PROPOSED, createdAt: now, updatedAt: now, startedAt: now, settledAt: null, metadata: { ...(metadata || {}) } };
475
- _sgEsV2.set(id, e); return { ...e, metadata: { ...e.metadata } };
476
- }
477
- export function establishSgEdgeV2(id) { const e = _sgEsV2.get(id); if (!e) throw new Error(`sg edge ${id} not found`); _sgCheckE(e.status, SG_EDGE_LIFECYCLE_V2.ESTABLISHED); const now = Date.now(); e.status = SG_EDGE_LIFECYCLE_V2.ESTABLISHED; e.updatedAt = now; if (!e.settledAt) e.settledAt = now; return { ...e, metadata: { ...e.metadata } }; }
478
- export function severSgEdgeV2(id, reason) { const e = _sgEsV2.get(id); if (!e) throw new Error(`sg edge ${id} not found`); _sgCheckE(e.status, SG_EDGE_LIFECYCLE_V2.SEVERED); const now = Date.now(); e.status = SG_EDGE_LIFECYCLE_V2.SEVERED; e.updatedAt = now; if (reason) e.metadata.severReason = String(reason); return { ...e, metadata: { ...e.metadata } }; }
479
- export function expireSgEdgeV2(id) { const e = _sgEsV2.get(id); if (!e) throw new Error(`sg edge ${id} not found`); _sgCheckE(e.status, SG_EDGE_LIFECYCLE_V2.EXPIRED); const now = Date.now(); e.status = SG_EDGE_LIFECYCLE_V2.EXPIRED; e.updatedAt = now; return { ...e, metadata: { ...e.metadata } }; }
480
- export function cancelSgEdgeV2(id, reason) { const e = _sgEsV2.get(id); if (!e) throw new Error(`sg edge ${id} not found`); _sgCheckE(e.status, SG_EDGE_LIFECYCLE_V2.CANCELLED); const now = Date.now(); e.status = SG_EDGE_LIFECYCLE_V2.CANCELLED; e.updatedAt = now; if (!e.settledAt) e.settledAt = now; if (reason) e.metadata.cancelReason = String(reason); return { ...e, metadata: { ...e.metadata } }; }
481
- export function getSgEdgeV2(id) { const e = _sgEsV2.get(id); if (!e) return null; return { ...e, metadata: { ...e.metadata } }; }
482
- export function listSgEdgesV2() { return [..._sgEsV2.values()].map((e) => ({ ...e, metadata: { ...e.metadata } })); }
483
- export function autoDeactivateIdleSgNodesV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const n of _sgNsV2.values()) if (n.status === SG_NODE_MATURITY_V2.ACTIVE && (t - n.lastTouchedAt) >= _sgIdleMs) { n.status = SG_NODE_MATURITY_V2.INACTIVE; n.updatedAt = t; flipped.push(n.id); } return { flipped, count: flipped.length }; }
484
- export function autoExpireStaleSgEdgesV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const e of _sgEsV2.values()) if (e.status === SG_EDGE_LIFECYCLE_V2.PROPOSED && (t - e.startedAt) >= _sgStuckMs) { e.status = SG_EDGE_LIFECYCLE_V2.CANCELLED; e.updatedAt = t; if (!e.settledAt) e.settledAt = t; e.metadata.cancelReason = "auto-cancel-stale"; flipped.push(e.id); } return { flipped, count: flipped.length }; }
648
+ e.status = SG_EDGE_LIFECYCLE_V2.CANCELLED;
649
+ e.updatedAt = now;
650
+ if (!e.settledAt) e.settledAt = now;
651
+ if (reason) e.metadata.cancelReason = String(reason);
652
+ return { ...e, metadata: { ...e.metadata } };
653
+ }
654
+ export function getSgEdgeV2(id) {
655
+ const e = _sgEsV2.get(id);
656
+ if (!e) return null;
657
+ return { ...e, metadata: { ...e.metadata } };
658
+ }
659
+ export function listSgEdgesV2() {
660
+ return [..._sgEsV2.values()].map((e) => ({
661
+ ...e,
662
+ metadata: { ...e.metadata },
663
+ }));
664
+ }
665
+ export function autoDeactivateIdleSgNodesV2({ now } = {}) {
666
+ const t = now ?? Date.now();
667
+ const flipped = [];
668
+ for (const n of _sgNsV2.values())
669
+ if (
670
+ n.status === SG_NODE_MATURITY_V2.ACTIVE &&
671
+ t - n.lastTouchedAt >= _sgIdleMs
672
+ ) {
673
+ n.status = SG_NODE_MATURITY_V2.INACTIVE;
674
+ n.updatedAt = t;
675
+ flipped.push(n.id);
676
+ }
677
+ return { flipped, count: flipped.length };
678
+ }
679
+ export function autoExpireStaleSgEdgesV2({ now } = {}) {
680
+ const t = now ?? Date.now();
681
+ const flipped = [];
682
+ for (const e of _sgEsV2.values())
683
+ if (
684
+ e.status === SG_EDGE_LIFECYCLE_V2.PROPOSED &&
685
+ t - e.startedAt >= _sgStuckMs
686
+ ) {
687
+ e.status = SG_EDGE_LIFECYCLE_V2.CANCELLED;
688
+ e.updatedAt = t;
689
+ if (!e.settledAt) e.settledAt = t;
690
+ e.metadata.cancelReason = "auto-cancel-stale";
691
+ flipped.push(e.id);
692
+ }
693
+ return { flipped, count: flipped.length };
694
+ }
485
695
  export function getSocialGraphGovStatsV2() {
486
- const nodesByStatus = {}; for (const v of Object.values(SG_NODE_MATURITY_V2)) nodesByStatus[v] = 0; for (const n of _sgNsV2.values()) nodesByStatus[n.status]++;
487
- const edgesByStatus = {}; for (const v of Object.values(SG_EDGE_LIFECYCLE_V2)) edgesByStatus[v] = 0; for (const e of _sgEsV2.values()) edgesByStatus[e.status]++;
488
- return { totalSgNodesV2: _sgNsV2.size, totalSgEdgesV2: _sgEsV2.size, maxActiveSgNodesPerOwner: _sgMaxActivePerOwner, maxPendingSgEdgesPerNode: _sgMaxPendingEdgesPerNode, sgNodeIdleMs: _sgIdleMs, sgEdgeStuckMs: _sgStuckMs, nodesByStatus, edgesByStatus };
696
+ const nodesByStatus = {};
697
+ for (const v of Object.values(SG_NODE_MATURITY_V2)) nodesByStatus[v] = 0;
698
+ for (const n of _sgNsV2.values()) nodesByStatus[n.status]++;
699
+ const edgesByStatus = {};
700
+ for (const v of Object.values(SG_EDGE_LIFECYCLE_V2)) edgesByStatus[v] = 0;
701
+ for (const e of _sgEsV2.values()) edgesByStatus[e.status]++;
702
+ return {
703
+ totalSgNodesV2: _sgNsV2.size,
704
+ totalSgEdgesV2: _sgEsV2.size,
705
+ maxActiveSgNodesPerOwner: _sgMaxActivePerOwner,
706
+ maxPendingSgEdgesPerNode: _sgMaxPendingEdgesPerNode,
707
+ sgNodeIdleMs: _sgIdleMs,
708
+ sgEdgeStuckMs: _sgStuckMs,
709
+ nodesByStatus,
710
+ edgesByStatus,
711
+ };
489
712
  }
@@ -607,3 +607,333 @@ export function _resetStateSocialManagerV2() {
607
607
  _relationshipIdleMsV2 = SOCIAL_DEFAULT_RELATIONSHIP_IDLE_MS;
608
608
  _threadStuckMsV2 = SOCIAL_DEFAULT_THREAD_STUCK_MS;
609
609
  }
610
+
611
+ // =====================================================================
612
+ // social-manager V2 governance overlay (iter22)
613
+ // =====================================================================
614
+ export const SMGOV_PROFILE_MATURITY_V2 = Object.freeze({
615
+ PENDING: "pending",
616
+ ACTIVE: "active",
617
+ MUTED: "muted",
618
+ ARCHIVED: "archived",
619
+ });
620
+ export const SMGOV_POST_LIFECYCLE_V2 = Object.freeze({
621
+ QUEUED: "queued",
622
+ POSTING: "posting",
623
+ POSTED: "posted",
624
+ FAILED: "failed",
625
+ CANCELLED: "cancelled",
626
+ });
627
+ const _smgovPTrans = new Map([
628
+ [
629
+ SMGOV_PROFILE_MATURITY_V2.PENDING,
630
+ new Set([
631
+ SMGOV_PROFILE_MATURITY_V2.ACTIVE,
632
+ SMGOV_PROFILE_MATURITY_V2.ARCHIVED,
633
+ ]),
634
+ ],
635
+ [
636
+ SMGOV_PROFILE_MATURITY_V2.ACTIVE,
637
+ new Set([
638
+ SMGOV_PROFILE_MATURITY_V2.MUTED,
639
+ SMGOV_PROFILE_MATURITY_V2.ARCHIVED,
640
+ ]),
641
+ ],
642
+ [
643
+ SMGOV_PROFILE_MATURITY_V2.MUTED,
644
+ new Set([
645
+ SMGOV_PROFILE_MATURITY_V2.ACTIVE,
646
+ SMGOV_PROFILE_MATURITY_V2.ARCHIVED,
647
+ ]),
648
+ ],
649
+ [SMGOV_PROFILE_MATURITY_V2.ARCHIVED, new Set()],
650
+ ]);
651
+ const _smgovPTerminal = new Set([SMGOV_PROFILE_MATURITY_V2.ARCHIVED]);
652
+ const _smgovJTrans = new Map([
653
+ [
654
+ SMGOV_POST_LIFECYCLE_V2.QUEUED,
655
+ new Set([
656
+ SMGOV_POST_LIFECYCLE_V2.POSTING,
657
+ SMGOV_POST_LIFECYCLE_V2.CANCELLED,
658
+ ]),
659
+ ],
660
+ [
661
+ SMGOV_POST_LIFECYCLE_V2.POSTING,
662
+ new Set([
663
+ SMGOV_POST_LIFECYCLE_V2.POSTED,
664
+ SMGOV_POST_LIFECYCLE_V2.FAILED,
665
+ SMGOV_POST_LIFECYCLE_V2.CANCELLED,
666
+ ]),
667
+ ],
668
+ [SMGOV_POST_LIFECYCLE_V2.POSTED, new Set()],
669
+ [SMGOV_POST_LIFECYCLE_V2.FAILED, new Set()],
670
+ [SMGOV_POST_LIFECYCLE_V2.CANCELLED, new Set()],
671
+ ]);
672
+ const _smgovPsV2 = new Map();
673
+ const _smgovJsV2 = new Map();
674
+ let _smgovMaxActive = 10,
675
+ _smgovMaxPending = 30,
676
+ _smgovIdleMs = 30 * 24 * 60 * 60 * 1000,
677
+ _smgovStuckMs = 60 * 1000;
678
+ function _smgovPos(n, label) {
679
+ const v = Math.floor(Number(n));
680
+ if (!Number.isFinite(v) || v <= 0)
681
+ throw new Error(`${label} must be positive integer`);
682
+ return v;
683
+ }
684
+ function _smgovCheckP(from, to) {
685
+ const a = _smgovPTrans.get(from);
686
+ if (!a || !a.has(to))
687
+ throw new Error(`invalid smgov profile transition ${from} → ${to}`);
688
+ }
689
+ function _smgovCheckJ(from, to) {
690
+ const a = _smgovJTrans.get(from);
691
+ if (!a || !a.has(to))
692
+ throw new Error(`invalid smgov post transition ${from} → ${to}`);
693
+ }
694
+ function _smgovCountActive(owner) {
695
+ let c = 0;
696
+ for (const p of _smgovPsV2.values())
697
+ if (p.owner === owner && p.status === SMGOV_PROFILE_MATURITY_V2.ACTIVE) c++;
698
+ return c;
699
+ }
700
+ function _smgovCountPending(profileId) {
701
+ let c = 0;
702
+ for (const j of _smgovJsV2.values())
703
+ if (
704
+ j.profileId === profileId &&
705
+ (j.status === SMGOV_POST_LIFECYCLE_V2.QUEUED ||
706
+ j.status === SMGOV_POST_LIFECYCLE_V2.POSTING)
707
+ )
708
+ c++;
709
+ return c;
710
+ }
711
+ export function setMaxActiveSmgovProfilesPerOwnerV2(n) {
712
+ _smgovMaxActive = _smgovPos(n, "maxActiveSmgovProfilesPerOwner");
713
+ }
714
+ export function getMaxActiveSmgovProfilesPerOwnerV2() {
715
+ return _smgovMaxActive;
716
+ }
717
+ export function setMaxPendingSmgovPostsPerProfileV2(n) {
718
+ _smgovMaxPending = _smgovPos(n, "maxPendingSmgovPostsPerProfile");
719
+ }
720
+ export function getMaxPendingSmgovPostsPerProfileV2() {
721
+ return _smgovMaxPending;
722
+ }
723
+ export function setSmgovProfileIdleMsV2(n) {
724
+ _smgovIdleMs = _smgovPos(n, "smgovProfileIdleMs");
725
+ }
726
+ export function getSmgovProfileIdleMsV2() {
727
+ return _smgovIdleMs;
728
+ }
729
+ export function setSmgovPostStuckMsV2(n) {
730
+ _smgovStuckMs = _smgovPos(n, "smgovPostStuckMs");
731
+ }
732
+ export function getSmgovPostStuckMsV2() {
733
+ return _smgovStuckMs;
734
+ }
735
+ export function _resetStateSocialManagerGovV2() {
736
+ _smgovPsV2.clear();
737
+ _smgovJsV2.clear();
738
+ _smgovMaxActive = 10;
739
+ _smgovMaxPending = 30;
740
+ _smgovIdleMs = 30 * 24 * 60 * 60 * 1000;
741
+ _smgovStuckMs = 60 * 1000;
742
+ }
743
+ export function registerSmgovProfileV2({ id, owner, channel, metadata } = {}) {
744
+ if (!id || !owner) throw new Error("id and owner required");
745
+ if (_smgovPsV2.has(id)) throw new Error(`smgov profile ${id} already exists`);
746
+ const now = Date.now();
747
+ const p = {
748
+ id,
749
+ owner,
750
+ channel: channel || "timeline",
751
+ status: SMGOV_PROFILE_MATURITY_V2.PENDING,
752
+ createdAt: now,
753
+ updatedAt: now,
754
+ lastTouchedAt: now,
755
+ activatedAt: null,
756
+ archivedAt: null,
757
+ metadata: { ...(metadata || {}) },
758
+ };
759
+ _smgovPsV2.set(id, p);
760
+ return { ...p, metadata: { ...p.metadata } };
761
+ }
762
+ export function activateSmgovProfileV2(id) {
763
+ const p = _smgovPsV2.get(id);
764
+ if (!p) throw new Error(`smgov profile ${id} not found`);
765
+ const isInitial = p.status === SMGOV_PROFILE_MATURITY_V2.PENDING;
766
+ _smgovCheckP(p.status, SMGOV_PROFILE_MATURITY_V2.ACTIVE);
767
+ if (isInitial && _smgovCountActive(p.owner) >= _smgovMaxActive)
768
+ throw new Error(`max active smgov profiles for owner ${p.owner} reached`);
769
+ const now = Date.now();
770
+ p.status = SMGOV_PROFILE_MATURITY_V2.ACTIVE;
771
+ p.updatedAt = now;
772
+ p.lastTouchedAt = now;
773
+ if (!p.activatedAt) p.activatedAt = now;
774
+ return { ...p, metadata: { ...p.metadata } };
775
+ }
776
+ export function muteSmgovProfileV2(id) {
777
+ const p = _smgovPsV2.get(id);
778
+ if (!p) throw new Error(`smgov profile ${id} not found`);
779
+ _smgovCheckP(p.status, SMGOV_PROFILE_MATURITY_V2.MUTED);
780
+ p.status = SMGOV_PROFILE_MATURITY_V2.MUTED;
781
+ p.updatedAt = Date.now();
782
+ return { ...p, metadata: { ...p.metadata } };
783
+ }
784
+ export function archiveSmgovProfileV2(id) {
785
+ const p = _smgovPsV2.get(id);
786
+ if (!p) throw new Error(`smgov profile ${id} not found`);
787
+ _smgovCheckP(p.status, SMGOV_PROFILE_MATURITY_V2.ARCHIVED);
788
+ const now = Date.now();
789
+ p.status = SMGOV_PROFILE_MATURITY_V2.ARCHIVED;
790
+ p.updatedAt = now;
791
+ if (!p.archivedAt) p.archivedAt = now;
792
+ return { ...p, metadata: { ...p.metadata } };
793
+ }
794
+ export function touchSmgovProfileV2(id) {
795
+ const p = _smgovPsV2.get(id);
796
+ if (!p) throw new Error(`smgov profile ${id} not found`);
797
+ if (_smgovPTerminal.has(p.status))
798
+ throw new Error(`cannot touch terminal smgov profile ${id}`);
799
+ const now = Date.now();
800
+ p.lastTouchedAt = now;
801
+ p.updatedAt = now;
802
+ return { ...p, metadata: { ...p.metadata } };
803
+ }
804
+ export function getSmgovProfileV2(id) {
805
+ const p = _smgovPsV2.get(id);
806
+ if (!p) return null;
807
+ return { ...p, metadata: { ...p.metadata } };
808
+ }
809
+ export function listSmgovProfilesV2() {
810
+ return [..._smgovPsV2.values()].map((p) => ({
811
+ ...p,
812
+ metadata: { ...p.metadata },
813
+ }));
814
+ }
815
+ export function createSmgovPostV2({ id, profileId, author, metadata } = {}) {
816
+ if (!id || !profileId) throw new Error("id and profileId required");
817
+ if (_smgovJsV2.has(id)) throw new Error(`smgov post ${id} already exists`);
818
+ if (!_smgovPsV2.has(profileId))
819
+ throw new Error(`smgov profile ${profileId} not found`);
820
+ if (_smgovCountPending(profileId) >= _smgovMaxPending)
821
+ throw new Error(`max pending smgov posts for profile ${profileId} reached`);
822
+ const now = Date.now();
823
+ const j = {
824
+ id,
825
+ profileId,
826
+ author: author || "",
827
+ status: SMGOV_POST_LIFECYCLE_V2.QUEUED,
828
+ createdAt: now,
829
+ updatedAt: now,
830
+ startedAt: null,
831
+ settledAt: null,
832
+ metadata: { ...(metadata || {}) },
833
+ };
834
+ _smgovJsV2.set(id, j);
835
+ return { ...j, metadata: { ...j.metadata } };
836
+ }
837
+ export function postingSmgovPostV2(id) {
838
+ const j = _smgovJsV2.get(id);
839
+ if (!j) throw new Error(`smgov post ${id} not found`);
840
+ _smgovCheckJ(j.status, SMGOV_POST_LIFECYCLE_V2.POSTING);
841
+ const now = Date.now();
842
+ j.status = SMGOV_POST_LIFECYCLE_V2.POSTING;
843
+ j.updatedAt = now;
844
+ if (!j.startedAt) j.startedAt = now;
845
+ return { ...j, metadata: { ...j.metadata } };
846
+ }
847
+ export function completePostSmgovV2(id) {
848
+ const j = _smgovJsV2.get(id);
849
+ if (!j) throw new Error(`smgov post ${id} not found`);
850
+ _smgovCheckJ(j.status, SMGOV_POST_LIFECYCLE_V2.POSTED);
851
+ const now = Date.now();
852
+ j.status = SMGOV_POST_LIFECYCLE_V2.POSTED;
853
+ j.updatedAt = now;
854
+ if (!j.settledAt) j.settledAt = now;
855
+ return { ...j, metadata: { ...j.metadata } };
856
+ }
857
+ export function failSmgovPostV2(id, reason) {
858
+ const j = _smgovJsV2.get(id);
859
+ if (!j) throw new Error(`smgov post ${id} not found`);
860
+ _smgovCheckJ(j.status, SMGOV_POST_LIFECYCLE_V2.FAILED);
861
+ const now = Date.now();
862
+ j.status = SMGOV_POST_LIFECYCLE_V2.FAILED;
863
+ j.updatedAt = now;
864
+ if (!j.settledAt) j.settledAt = now;
865
+ if (reason) j.metadata.failReason = String(reason);
866
+ return { ...j, metadata: { ...j.metadata } };
867
+ }
868
+ export function cancelSmgovPostV2(id, reason) {
869
+ const j = _smgovJsV2.get(id);
870
+ if (!j) throw new Error(`smgov post ${id} not found`);
871
+ _smgovCheckJ(j.status, SMGOV_POST_LIFECYCLE_V2.CANCELLED);
872
+ const now = Date.now();
873
+ j.status = SMGOV_POST_LIFECYCLE_V2.CANCELLED;
874
+ j.updatedAt = now;
875
+ if (!j.settledAt) j.settledAt = now;
876
+ if (reason) j.metadata.cancelReason = String(reason);
877
+ return { ...j, metadata: { ...j.metadata } };
878
+ }
879
+ export function getSmgovPostV2(id) {
880
+ const j = _smgovJsV2.get(id);
881
+ if (!j) return null;
882
+ return { ...j, metadata: { ...j.metadata } };
883
+ }
884
+ export function listSmgovPostsV2() {
885
+ return [..._smgovJsV2.values()].map((j) => ({
886
+ ...j,
887
+ metadata: { ...j.metadata },
888
+ }));
889
+ }
890
+ export function autoMuteIdleSmgovProfilesV2({ now } = {}) {
891
+ const t = now ?? Date.now();
892
+ const flipped = [];
893
+ for (const p of _smgovPsV2.values())
894
+ if (
895
+ p.status === SMGOV_PROFILE_MATURITY_V2.ACTIVE &&
896
+ t - p.lastTouchedAt >= _smgovIdleMs
897
+ ) {
898
+ p.status = SMGOV_PROFILE_MATURITY_V2.MUTED;
899
+ p.updatedAt = t;
900
+ flipped.push(p.id);
901
+ }
902
+ return { flipped, count: flipped.length };
903
+ }
904
+ export function autoFailStuckSmgovPostsV2({ now } = {}) {
905
+ const t = now ?? Date.now();
906
+ const flipped = [];
907
+ for (const j of _smgovJsV2.values())
908
+ if (
909
+ j.status === SMGOV_POST_LIFECYCLE_V2.POSTING &&
910
+ j.startedAt != null &&
911
+ t - j.startedAt >= _smgovStuckMs
912
+ ) {
913
+ j.status = SMGOV_POST_LIFECYCLE_V2.FAILED;
914
+ j.updatedAt = t;
915
+ if (!j.settledAt) j.settledAt = t;
916
+ j.metadata.failReason = "auto-fail-stuck";
917
+ flipped.push(j.id);
918
+ }
919
+ return { flipped, count: flipped.length };
920
+ }
921
+ export function getSocialManagerGovStatsV2() {
922
+ const profilesByStatus = {};
923
+ for (const v of Object.values(SMGOV_PROFILE_MATURITY_V2))
924
+ profilesByStatus[v] = 0;
925
+ for (const p of _smgovPsV2.values()) profilesByStatus[p.status]++;
926
+ const postsByStatus = {};
927
+ for (const v of Object.values(SMGOV_POST_LIFECYCLE_V2)) postsByStatus[v] = 0;
928
+ for (const j of _smgovJsV2.values()) postsByStatus[j.status]++;
929
+ return {
930
+ totalSmgovProfilesV2: _smgovPsV2.size,
931
+ totalSmgovPostsV2: _smgovJsV2.size,
932
+ maxActiveSmgovProfilesPerOwner: _smgovMaxActive,
933
+ maxPendingSmgovPostsPerProfile: _smgovMaxPending,
934
+ smgovProfileIdleMs: _smgovIdleMs,
935
+ smgovPostStuckMs: _smgovStuckMs,
936
+ profilesByStatus,
937
+ postsByStatus,
938
+ };
939
+ }