chainlesschain 0.81.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 (209) hide show
  1. package/bin/chainlesschain.js +0 -0
  2. package/package.json +1 -1
  3. package/src/commands/a2a.js +62 -0
  4. package/src/commands/activitypub.js +61 -0
  5. package/src/commands/agent-network.js +254 -1
  6. package/src/commands/agent.js +117 -0
  7. package/src/commands/audit.js +302 -0
  8. package/src/commands/automation.js +271 -1
  9. package/src/commands/bi.js +61 -0
  10. package/src/commands/bm25.js +78 -0
  11. package/src/commands/browse.js +64 -0
  12. package/src/commands/ccron.js +78 -0
  13. package/src/commands/codegen.js +224 -0
  14. package/src/commands/collab.js +341 -0
  15. package/src/commands/compliance.js +1075 -0
  16. package/src/commands/compt.js +78 -0
  17. package/src/commands/consol.js +231 -0
  18. package/src/commands/cowork.js +263 -0
  19. package/src/commands/crosschain.js +62 -0
  20. package/src/commands/dao.js +62 -0
  21. package/src/commands/dbevo.js +284 -0
  22. package/src/commands/dev.js +252 -0
  23. package/src/commands/did.js +358 -0
  24. package/src/commands/dlp.js +61 -0
  25. package/src/commands/economy.js +56 -0
  26. package/src/commands/encrypt.js +341 -0
  27. package/src/commands/evolution.js +56 -0
  28. package/src/commands/evomap.js +61 -0
  29. package/src/commands/export.js +256 -1
  30. package/src/commands/fflag.js +178 -0
  31. package/src/commands/fusion.js +258 -0
  32. package/src/commands/git.js +45 -0
  33. package/src/commands/governance.js +325 -0
  34. package/src/commands/hardening.js +411 -0
  35. package/src/commands/hmemory.js +56 -0
  36. package/src/commands/hook.js +148 -0
  37. package/src/commands/import.js +252 -0
  38. package/src/commands/incentive.js +322 -0
  39. package/src/commands/inference.js +42 -0
  40. package/src/commands/infra.js +244 -0
  41. package/src/commands/instinct.js +260 -0
  42. package/src/commands/ipfs.js +318 -0
  43. package/src/commands/itbudget.js +45 -0
  44. package/src/commands/kg.js +387 -0
  45. package/src/commands/llm.js +263 -0
  46. package/src/commands/lowcode.js +44 -0
  47. package/src/commands/matrix.js +62 -0
  48. package/src/commands/mcp.js +221 -0
  49. package/src/commands/mcpscaf.js +41 -0
  50. package/src/commands/meminj.js +41 -0
  51. package/src/commands/memory.js +248 -0
  52. package/src/commands/multimodal.js +296 -0
  53. package/src/commands/nlprog.js +356 -0
  54. package/src/commands/nostr.js +62 -0
  55. package/src/commands/note.js +244 -0
  56. package/src/commands/ops.js +354 -0
  57. package/src/commands/orchestrate.js +166 -0
  58. package/src/commands/orchgov.js +45 -0
  59. package/src/commands/org.js +277 -0
  60. package/src/commands/p2p.js +390 -0
  61. package/src/commands/pdfp.js +78 -0
  62. package/src/commands/perception.js +290 -0
  63. package/src/commands/perf.js +39 -0
  64. package/src/commands/perm.js +45 -0
  65. package/src/commands/permmem.js +251 -0
  66. package/src/commands/pipeline.js +57 -1
  67. package/src/commands/planmode.js +45 -0
  68. package/src/commands/plugin-ecosystem.js +273 -0
  69. package/src/commands/pqc.js +393 -0
  70. package/src/commands/promcomp.js +82 -0
  71. package/src/commands/quantization.js +351 -0
  72. package/src/commands/rcache.js +271 -0
  73. package/src/commands/recommend.js +382 -0
  74. package/src/commands/runtime.js +307 -0
  75. package/src/commands/scim.js +262 -0
  76. package/src/commands/seshhook.js +41 -0
  77. package/src/commands/seshsearch.js +41 -0
  78. package/src/commands/seshtail.js +41 -0
  79. package/src/commands/seshu.js +41 -0
  80. package/src/commands/session.js +258 -0
  81. package/src/commands/sganal.js +78 -0
  82. package/src/commands/siem.js +40 -0
  83. package/src/commands/skill.js +267 -1
  84. package/src/commands/slotfill.js +41 -0
  85. package/src/commands/social.js +290 -0
  86. package/src/commands/sso.js +186 -1
  87. package/src/commands/svccont.js +45 -0
  88. package/src/commands/sync.js +256 -0
  89. package/src/commands/tech.js +338 -0
  90. package/src/commands/tenant.js +351 -0
  91. package/src/commands/tms.js +45 -0
  92. package/src/commands/tokens.js +269 -0
  93. package/src/commands/topiccls.js +45 -0
  94. package/src/commands/trust.js +249 -0
  95. package/src/commands/uprof.js +45 -0
  96. package/src/commands/vcheck.js +78 -0
  97. package/src/commands/wallet.js +277 -0
  98. package/src/commands/webfetch.js +41 -0
  99. package/src/commands/workflow.js +171 -0
  100. package/src/commands/zkp.js +62 -0
  101. package/src/harness/prompt-compressor.js +331 -0
  102. package/src/index.js +65 -1
  103. package/src/lib/a2a-protocol.js +105 -0
  104. package/src/lib/activitypub-bridge.js +105 -0
  105. package/src/lib/agent-coordinator.js +325 -0
  106. package/src/lib/agent-economy.js +105 -0
  107. package/src/lib/agent-network.js +387 -0
  108. package/src/lib/agent-router.js +395 -0
  109. package/src/lib/aiops.js +478 -0
  110. package/src/lib/app-builder.js +105 -0
  111. package/src/lib/audit-logger.js +379 -0
  112. package/src/lib/automation-engine.js +330 -0
  113. package/src/lib/autonomous-agent.js +105 -0
  114. package/src/lib/autonomous-developer.js +350 -0
  115. package/src/lib/bi-engine.js +105 -0
  116. package/src/lib/bm25-search.js +81 -0
  117. package/src/lib/browser-automation.js +105 -0
  118. package/src/lib/code-agent.js +323 -0
  119. package/src/lib/collaboration-governance.js +364 -0
  120. package/src/lib/community-governance.js +436 -0
  121. package/src/lib/compliance-framework-reporter.js +105 -0
  122. package/src/lib/compliance-manager.js +434 -0
  123. package/src/lib/compression-telemetry.js +81 -0
  124. package/src/lib/content-recommendation.js +469 -0
  125. package/src/lib/content-recommender.js +105 -0
  126. package/src/lib/cowork-cron.js +81 -0
  127. package/src/lib/cowork-task-runner.js +105 -0
  128. package/src/lib/cross-chain.js +105 -0
  129. package/src/lib/crypto-manager.js +350 -0
  130. package/src/lib/dao-governance.js +105 -0
  131. package/src/lib/dbevo.js +338 -0
  132. package/src/lib/decentral-infra.js +340 -0
  133. package/src/lib/did-manager.js +367 -0
  134. package/src/lib/dlp-engine.js +105 -0
  135. package/src/lib/evolution-system.js +105 -0
  136. package/src/lib/evomap-manager.js +105 -0
  137. package/src/lib/execution-backend.js +105 -0
  138. package/src/lib/feature-flags.js +85 -0
  139. package/src/lib/git-integration.js +105 -0
  140. package/src/lib/hardening-manager.js +348 -0
  141. package/src/lib/hierarchical-memory.js +105 -0
  142. package/src/lib/hook-manager.js +380 -0
  143. package/src/lib/inference-network.js +105 -0
  144. package/src/lib/instinct-manager.js +332 -0
  145. package/src/lib/ipfs-storage.js +334 -0
  146. package/src/lib/iteration-budget.js +105 -0
  147. package/src/lib/knowledge-exporter.js +381 -0
  148. package/src/lib/knowledge-graph.js +432 -0
  149. package/src/lib/knowledge-importer.js +379 -0
  150. package/src/lib/llm-providers.js +391 -0
  151. package/src/lib/matrix-bridge.js +105 -0
  152. package/src/lib/mcp-registry.js +333 -0
  153. package/src/lib/mcp-scaffold.js +81 -0
  154. package/src/lib/memory-injection.js +81 -0
  155. package/src/lib/memory-manager.js +330 -0
  156. package/src/lib/multimodal.js +346 -0
  157. package/src/lib/nl-programming.js +343 -0
  158. package/src/lib/nostr-bridge.js +105 -0
  159. package/src/lib/note-versioning.js +327 -0
  160. package/src/lib/orchestrator.js +105 -0
  161. package/src/lib/org-manager.js +323 -0
  162. package/src/lib/p2p-manager.js +387 -0
  163. package/src/lib/pdf-parser.js +81 -0
  164. package/src/lib/perception.js +346 -0
  165. package/src/lib/perf-tuning.js +109 -1
  166. package/src/lib/permanent-memory.js +320 -0
  167. package/src/lib/permission-engine.js +81 -0
  168. package/src/lib/pipeline-orchestrator.js +105 -0
  169. package/src/lib/plan-mode.js +81 -0
  170. package/src/lib/plugin-ecosystem.js +377 -0
  171. package/src/lib/pqc-manager.js +368 -0
  172. package/src/lib/prompt-compressor.js +1 -10
  173. package/src/lib/protocol-fusion.js +417 -0
  174. package/src/lib/quantization.js +325 -0
  175. package/src/lib/response-cache.js +327 -0
  176. package/src/lib/scim-manager.js +329 -0
  177. package/src/lib/service-container.js +81 -0
  178. package/src/lib/session-consolidator.js +105 -0
  179. package/src/lib/session-hooks.js +81 -0
  180. package/src/lib/session-manager.js +329 -0
  181. package/src/lib/session-search.js +81 -0
  182. package/src/lib/session-tail.js +81 -0
  183. package/src/lib/session-usage.js +83 -0
  184. package/src/lib/siem-exporter.js +105 -0
  185. package/src/lib/skill-loader.js +377 -0
  186. package/src/lib/slot-filler.js +81 -0
  187. package/src/lib/social-graph-analytics.js +81 -0
  188. package/src/lib/social-graph.js +81 -0
  189. package/src/lib/social-manager.js +326 -0
  190. package/src/lib/sso-manager.js +332 -0
  191. package/src/lib/sub-agent-registry.js +110 -0
  192. package/src/lib/sync-manager.js +326 -0
  193. package/src/lib/task-model-selector.js +81 -0
  194. package/src/lib/tech-learning-engine.js +369 -0
  195. package/src/lib/tenant-saas.js +460 -0
  196. package/src/lib/threat-intel.js +335 -0
  197. package/src/lib/todo-manager.js +105 -0
  198. package/src/lib/token-incentive.js +293 -0
  199. package/src/lib/token-tracker.js +329 -0
  200. package/src/lib/topic-classifier.js +105 -0
  201. package/src/lib/trust-security.js +390 -0
  202. package/src/lib/ueba.js +389 -0
  203. package/src/lib/universal-runtime.js +325 -0
  204. package/src/lib/user-profile.js +81 -0
  205. package/src/lib/version-checker.js +81 -0
  206. package/src/lib/wallet-manager.js +326 -0
  207. package/src/lib/web-fetch.js +81 -0
  208. package/src/lib/workflow-engine.js +322 -0
  209. package/src/lib/zkp-engine.js +105 -0
@@ -593,3 +593,346 @@ export function _resetState() {
593
593
  _translations.clear();
594
594
  _conventions.clear();
595
595
  }
596
+
597
+ /* ═════════════════════════════════════════════════════════ *
598
+ * Phase 28 V2 — Spec Maturity + Dialogue Lifecycle
599
+ * ═════════════════════════════════════════════════════════ */
600
+
601
+ export const SPEC_MATURITY_V2 = Object.freeze({
602
+ DRAFT: "draft",
603
+ REFINING: "refining",
604
+ APPROVED: "approved",
605
+ IMPLEMENTED: "implemented",
606
+ ARCHIVED: "archived",
607
+ });
608
+
609
+ export const DIALOGUE_TURN_V2 = Object.freeze({
610
+ PENDING: "pending",
611
+ ANSWERED: "answered",
612
+ DISMISSED: "dismissed",
613
+ ESCALATED: "escalated",
614
+ });
615
+
616
+ const SPEC_TRANSITIONS_V2 = new Map([
617
+ ["draft", new Set(["refining", "approved", "archived"])],
618
+ ["refining", new Set(["draft", "approved", "archived"])],
619
+ ["approved", new Set(["refining", "implemented", "archived"])],
620
+ ["implemented", new Set(["archived"])],
621
+ ]);
622
+ const SPEC_TERMINALS_V2 = new Set(["archived"]);
623
+
624
+ const DIALOGUE_TRANSITIONS_V2 = new Map([
625
+ ["pending", new Set(["answered", "dismissed", "escalated"])],
626
+ ["escalated", new Set(["answered", "dismissed"])],
627
+ ]);
628
+ const DIALOGUE_TERMINALS_V2 = new Set(["answered", "dismissed"]);
629
+
630
+ export const NLPROG_DEFAULT_MAX_ACTIVE_SPECS_PER_AUTHOR = 30;
631
+ export const NLPROG_DEFAULT_MAX_PENDING_TURNS_PER_SPEC = 20;
632
+ export const NLPROG_DEFAULT_SPEC_IDLE_MS = 45 * 86400000; // 45d
633
+ export const NLPROG_DEFAULT_TURN_PENDING_MS = 7 * 86400000; // 7d
634
+
635
+ let _maxActiveSpecsPerAuthorV2 = NLPROG_DEFAULT_MAX_ACTIVE_SPECS_PER_AUTHOR;
636
+ let _maxPendingTurnsPerSpecV2 = NLPROG_DEFAULT_MAX_PENDING_TURNS_PER_SPEC;
637
+ let _specIdleMsV2 = NLPROG_DEFAULT_SPEC_IDLE_MS;
638
+ let _turnPendingMsV2 = NLPROG_DEFAULT_TURN_PENDING_MS;
639
+
640
+ function _positiveIntV2(n, label) {
641
+ const v = Math.floor(Number(n));
642
+ if (!Number.isFinite(v) || v <= 0)
643
+ throw new Error(`${label} must be a positive integer`);
644
+ return v;
645
+ }
646
+
647
+ export function getDefaultMaxActiveSpecsPerAuthorV2() {
648
+ return NLPROG_DEFAULT_MAX_ACTIVE_SPECS_PER_AUTHOR;
649
+ }
650
+ export function getMaxActiveSpecsPerAuthorV2() {
651
+ return _maxActiveSpecsPerAuthorV2;
652
+ }
653
+ export function setMaxActiveSpecsPerAuthorV2(n) {
654
+ return (_maxActiveSpecsPerAuthorV2 = _positiveIntV2(
655
+ n,
656
+ "maxActiveSpecsPerAuthor",
657
+ ));
658
+ }
659
+ export function getDefaultMaxPendingTurnsPerSpecV2() {
660
+ return NLPROG_DEFAULT_MAX_PENDING_TURNS_PER_SPEC;
661
+ }
662
+ export function getMaxPendingTurnsPerSpecV2() {
663
+ return _maxPendingTurnsPerSpecV2;
664
+ }
665
+ export function setMaxPendingTurnsPerSpecV2(n) {
666
+ return (_maxPendingTurnsPerSpecV2 = _positiveIntV2(
667
+ n,
668
+ "maxPendingTurnsPerSpec",
669
+ ));
670
+ }
671
+ export function getDefaultSpecIdleMsV2() {
672
+ return NLPROG_DEFAULT_SPEC_IDLE_MS;
673
+ }
674
+ export function getSpecIdleMsV2() {
675
+ return _specIdleMsV2;
676
+ }
677
+ export function setSpecIdleMsV2(ms) {
678
+ return (_specIdleMsV2 = _positiveIntV2(ms, "specIdleMs"));
679
+ }
680
+ export function getDefaultTurnPendingMsV2() {
681
+ return NLPROG_DEFAULT_TURN_PENDING_MS;
682
+ }
683
+ export function getTurnPendingMsV2() {
684
+ return _turnPendingMsV2;
685
+ }
686
+ export function setTurnPendingMsV2(ms) {
687
+ return (_turnPendingMsV2 = _positiveIntV2(ms, "turnPendingMs"));
688
+ }
689
+
690
+ const _specsV2 = new Map();
691
+ const _turnsV2 = new Map();
692
+
693
+ function _isActiveSpec(s) {
694
+ return (
695
+ s === SPEC_MATURITY_V2.DRAFT ||
696
+ s === SPEC_MATURITY_V2.REFINING ||
697
+ s === SPEC_MATURITY_V2.APPROVED
698
+ );
699
+ }
700
+
701
+ export function registerSpecV2(
702
+ _db,
703
+ { specId, authorId, title, initialStatus, metadata } = {},
704
+ ) {
705
+ if (!specId) throw new Error("specId is required");
706
+ if (!authorId) throw new Error("authorId is required");
707
+ if (_specsV2.has(specId)) throw new Error(`Spec ${specId} already exists`);
708
+ const status = initialStatus || SPEC_MATURITY_V2.DRAFT;
709
+ if (!Object.values(SPEC_MATURITY_V2).includes(status))
710
+ throw new Error(`Invalid initial status: ${status}`);
711
+ if (SPEC_TERMINALS_V2.has(status))
712
+ throw new Error(`Cannot register in terminal status: ${status}`);
713
+ if (_isActiveSpec(status)) {
714
+ if (getActiveSpecCount(authorId) >= _maxActiveSpecsPerAuthorV2)
715
+ throw new Error(
716
+ `Author ${authorId} reached active-spec cap (${_maxActiveSpecsPerAuthorV2})`,
717
+ );
718
+ }
719
+ const now = _now();
720
+ const record = {
721
+ specId,
722
+ authorId,
723
+ title: title || "",
724
+ status,
725
+ metadata: metadata || {},
726
+ createdAt: now,
727
+ updatedAt: now,
728
+ lastActivityAt: now,
729
+ };
730
+ _specsV2.set(specId, record);
731
+ return { ...record, metadata: { ...record.metadata } };
732
+ }
733
+
734
+ export function getSpecV2(specId) {
735
+ const r = _specsV2.get(specId);
736
+ return r ? { ...r, metadata: { ...r.metadata } } : null;
737
+ }
738
+
739
+ export function setSpecMaturityV2(_db, specId, newStatus, patch = {}) {
740
+ const record = _specsV2.get(specId);
741
+ if (!record) throw new Error(`Unknown spec: ${specId}`);
742
+ if (!Object.values(SPEC_MATURITY_V2).includes(newStatus))
743
+ throw new Error(`Invalid status: ${newStatus}`);
744
+ const allowed = SPEC_TRANSITIONS_V2.get(record.status) || new Set();
745
+ if (!allowed.has(newStatus))
746
+ throw new Error(`Invalid transition: ${record.status} -> ${newStatus}`);
747
+ if (_isActiveSpec(newStatus) && !_isActiveSpec(record.status)) {
748
+ if (getActiveSpecCount(record.authorId) >= _maxActiveSpecsPerAuthorV2)
749
+ throw new Error(
750
+ `Author ${record.authorId} reached active-spec cap (${_maxActiveSpecsPerAuthorV2})`,
751
+ );
752
+ }
753
+ record.status = newStatus;
754
+ record.updatedAt = _now();
755
+ if (patch.reason !== undefined) record.lastReason = patch.reason;
756
+ if (patch.metadata)
757
+ record.metadata = { ...record.metadata, ...patch.metadata };
758
+ return { ...record, metadata: { ...record.metadata } };
759
+ }
760
+
761
+ export function refineSpec(db, id, reason) {
762
+ return setSpecMaturityV2(db, id, SPEC_MATURITY_V2.REFINING, { reason });
763
+ }
764
+ export function approveSpec(db, id, reason) {
765
+ return setSpecMaturityV2(db, id, SPEC_MATURITY_V2.APPROVED, { reason });
766
+ }
767
+ export function implementSpec(db, id, reason) {
768
+ return setSpecMaturityV2(db, id, SPEC_MATURITY_V2.IMPLEMENTED, { reason });
769
+ }
770
+ export function archiveSpec(db, id, reason) {
771
+ return setSpecMaturityV2(db, id, SPEC_MATURITY_V2.ARCHIVED, { reason });
772
+ }
773
+
774
+ export function touchSpecActivity(specId) {
775
+ const record = _specsV2.get(specId);
776
+ if (!record) throw new Error(`Unknown spec: ${specId}`);
777
+ record.lastActivityAt = _now();
778
+ record.updatedAt = record.lastActivityAt;
779
+ return { ...record, metadata: { ...record.metadata } };
780
+ }
781
+
782
+ export function registerDialogueTurnV2(
783
+ _db,
784
+ { turnId, specId, role, question, initialStatus, metadata } = {},
785
+ ) {
786
+ if (!turnId) throw new Error("turnId is required");
787
+ if (!specId) throw new Error("specId is required");
788
+ if (!_specsV2.has(specId)) throw new Error(`Unknown spec: ${specId}`);
789
+ if (_turnsV2.has(turnId)) throw new Error(`Turn ${turnId} already exists`);
790
+ const status = initialStatus || DIALOGUE_TURN_V2.PENDING;
791
+ if (!Object.values(DIALOGUE_TURN_V2).includes(status))
792
+ throw new Error(`Invalid initial status: ${status}`);
793
+ if (DIALOGUE_TERMINALS_V2.has(status))
794
+ throw new Error(`Cannot register in terminal status: ${status}`);
795
+ if (status === DIALOGUE_TURN_V2.PENDING) {
796
+ if (getPendingTurnCount(specId) >= _maxPendingTurnsPerSpecV2)
797
+ throw new Error(
798
+ `Spec ${specId} reached pending-turn cap (${_maxPendingTurnsPerSpecV2})`,
799
+ );
800
+ }
801
+ const now = _now();
802
+ const record = {
803
+ turnId,
804
+ specId,
805
+ role: role || "user",
806
+ question: question || "",
807
+ status,
808
+ metadata: metadata || {},
809
+ createdAt: now,
810
+ updatedAt: now,
811
+ };
812
+ _turnsV2.set(turnId, record);
813
+ return { ...record, metadata: { ...record.metadata } };
814
+ }
815
+
816
+ export function getDialogueTurnV2(turnId) {
817
+ const r = _turnsV2.get(turnId);
818
+ return r ? { ...r, metadata: { ...r.metadata } } : null;
819
+ }
820
+
821
+ export function setDialogueTurnStatusV2(_db, turnId, newStatus, patch = {}) {
822
+ const record = _turnsV2.get(turnId);
823
+ if (!record) throw new Error(`Unknown turn: ${turnId}`);
824
+ if (!Object.values(DIALOGUE_TURN_V2).includes(newStatus))
825
+ throw new Error(`Invalid status: ${newStatus}`);
826
+ const allowed = DIALOGUE_TRANSITIONS_V2.get(record.status) || new Set();
827
+ if (!allowed.has(newStatus))
828
+ throw new Error(`Invalid transition: ${record.status} -> ${newStatus}`);
829
+ record.status = newStatus;
830
+ record.updatedAt = _now();
831
+ if (patch.answer !== undefined) record.answer = patch.answer;
832
+ if (patch.reason !== undefined) record.lastReason = patch.reason;
833
+ if (patch.metadata)
834
+ record.metadata = { ...record.metadata, ...patch.metadata };
835
+ return { ...record, metadata: { ...record.metadata } };
836
+ }
837
+
838
+ export function answerTurn(db, id, answer, reason) {
839
+ return setDialogueTurnStatusV2(db, id, DIALOGUE_TURN_V2.ANSWERED, {
840
+ answer,
841
+ reason,
842
+ });
843
+ }
844
+ export function dismissTurn(db, id, reason) {
845
+ return setDialogueTurnStatusV2(db, id, DIALOGUE_TURN_V2.DISMISSED, {
846
+ reason,
847
+ });
848
+ }
849
+ export function escalateTurn(db, id, reason) {
850
+ return setDialogueTurnStatusV2(db, id, DIALOGUE_TURN_V2.ESCALATED, {
851
+ reason,
852
+ });
853
+ }
854
+
855
+ export function getActiveSpecCount(authorId) {
856
+ let n = 0;
857
+ for (const r of _specsV2.values()) {
858
+ if (!_isActiveSpec(r.status)) continue;
859
+ if (authorId && r.authorId !== authorId) continue;
860
+ n++;
861
+ }
862
+ return n;
863
+ }
864
+
865
+ export function getPendingTurnCount(specId) {
866
+ let n = 0;
867
+ for (const r of _turnsV2.values()) {
868
+ if (r.status !== DIALOGUE_TURN_V2.PENDING) continue;
869
+ if (specId && r.specId !== specId) continue;
870
+ n++;
871
+ }
872
+ return n;
873
+ }
874
+
875
+ export function autoArchiveIdleSpecs(_db, nowMs) {
876
+ const now = nowMs ?? _now();
877
+ const flipped = [];
878
+ for (const r of _specsV2.values()) {
879
+ if (
880
+ r.status === SPEC_MATURITY_V2.DRAFT ||
881
+ r.status === SPEC_MATURITY_V2.REFINING ||
882
+ r.status === SPEC_MATURITY_V2.APPROVED ||
883
+ r.status === SPEC_MATURITY_V2.IMPLEMENTED
884
+ ) {
885
+ if (now - r.lastActivityAt > _specIdleMsV2) {
886
+ r.status = SPEC_MATURITY_V2.ARCHIVED;
887
+ r.updatedAt = now;
888
+ r.lastReason = "idle";
889
+ flipped.push(r.specId);
890
+ }
891
+ }
892
+ }
893
+ return { flipped, count: flipped.length };
894
+ }
895
+
896
+ export function autoDismissStalePendingTurns(_db, nowMs) {
897
+ const now = nowMs ?? _now();
898
+ const flipped = [];
899
+ for (const r of _turnsV2.values()) {
900
+ if (r.status === DIALOGUE_TURN_V2.PENDING) {
901
+ if (now - r.createdAt > _turnPendingMsV2) {
902
+ r.status = DIALOGUE_TURN_V2.DISMISSED;
903
+ r.updatedAt = now;
904
+ r.lastReason = "pending_timeout";
905
+ flipped.push(r.turnId);
906
+ }
907
+ }
908
+ }
909
+ return { flipped, count: flipped.length };
910
+ }
911
+
912
+ export function getNlProgrammingStatsV2() {
913
+ const specsByStatus = {};
914
+ for (const s of Object.values(SPEC_MATURITY_V2)) specsByStatus[s] = 0;
915
+ const turnsByStatus = {};
916
+ for (const s of Object.values(DIALOGUE_TURN_V2)) turnsByStatus[s] = 0;
917
+ for (const r of _specsV2.values()) specsByStatus[r.status]++;
918
+ for (const r of _turnsV2.values()) turnsByStatus[r.status]++;
919
+ return {
920
+ totalSpecsV2: _specsV2.size,
921
+ totalTurnsV2: _turnsV2.size,
922
+ maxActiveSpecsPerAuthor: _maxActiveSpecsPerAuthorV2,
923
+ maxPendingTurnsPerSpec: _maxPendingTurnsPerSpecV2,
924
+ specIdleMs: _specIdleMsV2,
925
+ turnPendingMs: _turnPendingMsV2,
926
+ specsByStatus,
927
+ turnsByStatus,
928
+ };
929
+ }
930
+
931
+ export function _resetStateV2() {
932
+ _maxActiveSpecsPerAuthorV2 = NLPROG_DEFAULT_MAX_ACTIVE_SPECS_PER_AUTHOR;
933
+ _maxPendingTurnsPerSpecV2 = NLPROG_DEFAULT_MAX_PENDING_TURNS_PER_SPEC;
934
+ _specIdleMsV2 = NLPROG_DEFAULT_SPEC_IDLE_MS;
935
+ _turnPendingMsV2 = NLPROG_DEFAULT_TURN_PENDING_MS;
936
+ _specsV2.clear();
937
+ _turnsV2.clear();
938
+ }
@@ -369,3 +369,108 @@ export function _resetState() {
369
369
  _keypairs.clear();
370
370
  _didMappings.clear();
371
371
  }
372
+
373
+
374
+ // ===== V2 Surface: Nostr Bridge governance overlay (CLI v0.134.0) =====
375
+ export const NOSTR_RELAY_MATURITY_V2 = Object.freeze({
376
+ PENDING: "pending", ACTIVE: "active", OFFLINE: "offline", RETIRED: "retired",
377
+ });
378
+ export const NOSTR_EVENT_LIFECYCLE_V2 = Object.freeze({
379
+ QUEUED: "queued", PUBLISHING: "publishing", PUBLISHED: "published", FAILED: "failed", CANCELLED: "cancelled",
380
+ });
381
+
382
+ const _nsRelayTrans = new Map([
383
+ [NOSTR_RELAY_MATURITY_V2.PENDING, new Set([NOSTR_RELAY_MATURITY_V2.ACTIVE, NOSTR_RELAY_MATURITY_V2.RETIRED])],
384
+ [NOSTR_RELAY_MATURITY_V2.ACTIVE, new Set([NOSTR_RELAY_MATURITY_V2.OFFLINE, NOSTR_RELAY_MATURITY_V2.RETIRED])],
385
+ [NOSTR_RELAY_MATURITY_V2.OFFLINE, new Set([NOSTR_RELAY_MATURITY_V2.ACTIVE, NOSTR_RELAY_MATURITY_V2.RETIRED])],
386
+ [NOSTR_RELAY_MATURITY_V2.RETIRED, new Set()],
387
+ ]);
388
+ const _nsRelayTerminal = new Set([NOSTR_RELAY_MATURITY_V2.RETIRED]);
389
+ const _nsEventTrans = new Map([
390
+ [NOSTR_EVENT_LIFECYCLE_V2.QUEUED, new Set([NOSTR_EVENT_LIFECYCLE_V2.PUBLISHING, NOSTR_EVENT_LIFECYCLE_V2.CANCELLED])],
391
+ [NOSTR_EVENT_LIFECYCLE_V2.PUBLISHING, new Set([NOSTR_EVENT_LIFECYCLE_V2.PUBLISHED, NOSTR_EVENT_LIFECYCLE_V2.FAILED, NOSTR_EVENT_LIFECYCLE_V2.CANCELLED])],
392
+ [NOSTR_EVENT_LIFECYCLE_V2.PUBLISHED, new Set()],
393
+ [NOSTR_EVENT_LIFECYCLE_V2.FAILED, new Set()],
394
+ [NOSTR_EVENT_LIFECYCLE_V2.CANCELLED, new Set()],
395
+ ]);
396
+
397
+ const _nsRelays = new Map();
398
+ const _nsEvents = new Map();
399
+ let _nsMaxActivePerOwner = 10;
400
+ let _nsMaxPendingPerRelay = 30;
401
+ let _nsRelayIdleMs = 60 * 60 * 1000;
402
+ let _nsEventStuckMs = 2 * 60 * 1000;
403
+
404
+ function _nsPos(n, lbl) { const v = Math.floor(Number(n)); if (!Number.isFinite(v) || v <= 0) throw new Error(`${lbl} must be positive integer`); return v; }
405
+
406
+ export function setMaxActiveNostrRelaysPerOwnerV2(n) { _nsMaxActivePerOwner = _nsPos(n, "maxActiveNostrRelaysPerOwner"); }
407
+ export function getMaxActiveNostrRelaysPerOwnerV2() { return _nsMaxActivePerOwner; }
408
+ export function setMaxPendingNostrEventsPerRelayV2(n) { _nsMaxPendingPerRelay = _nsPos(n, "maxPendingNostrEventsPerRelay"); }
409
+ export function getMaxPendingNostrEventsPerRelayV2() { return _nsMaxPendingPerRelay; }
410
+ export function setNostrRelayIdleMsV2(n) { _nsRelayIdleMs = _nsPos(n, "nostrRelayIdleMs"); }
411
+ export function getNostrRelayIdleMsV2() { return _nsRelayIdleMs; }
412
+ export function setNostrEventStuckMsV2(n) { _nsEventStuckMs = _nsPos(n, "nostrEventStuckMs"); }
413
+ export function getNostrEventStuckMsV2() { return _nsEventStuckMs; }
414
+
415
+ export function _resetStateNostrBridgeV2() {
416
+ _nsRelays.clear(); _nsEvents.clear();
417
+ _nsMaxActivePerOwner = 10; _nsMaxPendingPerRelay = 30;
418
+ _nsRelayIdleMs = 60 * 60 * 1000; _nsEventStuckMs = 2 * 60 * 1000;
419
+ }
420
+
421
+ export function registerNostrRelayV2({ id, owner, url, metadata } = {}) {
422
+ if (!id || typeof id !== "string") throw new Error("id is required");
423
+ if (!owner || typeof owner !== "string") throw new Error("owner is required");
424
+ if (_nsRelays.has(id)) throw new Error(`nostr relay ${id} already registered`);
425
+ const now = Date.now();
426
+ const r = { id, owner, url: url || "", status: NOSTR_RELAY_MATURITY_V2.PENDING, createdAt: now, updatedAt: now, activatedAt: null, retiredAt: null, lastTouchedAt: now, metadata: { ...(metadata || {}) } };
427
+ _nsRelays.set(id, r);
428
+ return { ...r, metadata: { ...r.metadata } };
429
+ }
430
+ function _nsCheckR(from, to) { const a = _nsRelayTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid nostr relay transition ${from} → ${to}`); }
431
+ function _nsCountActive(owner) { let n = 0; for (const r of _nsRelays.values()) if (r.owner === owner && r.status === NOSTR_RELAY_MATURITY_V2.ACTIVE) n++; return n; }
432
+
433
+ export function activateNostrRelayV2(id) {
434
+ const r = _nsRelays.get(id); if (!r) throw new Error(`nostr relay ${id} not found`);
435
+ _nsCheckR(r.status, NOSTR_RELAY_MATURITY_V2.ACTIVE);
436
+ const recovery = r.status === NOSTR_RELAY_MATURITY_V2.OFFLINE;
437
+ if (!recovery) { const a = _nsCountActive(r.owner); if (a >= _nsMaxActivePerOwner) throw new Error(`max active nostr relays per owner (${_nsMaxActivePerOwner}) reached for ${r.owner}`); }
438
+ const now = Date.now(); r.status = NOSTR_RELAY_MATURITY_V2.ACTIVE; r.updatedAt = now; r.lastTouchedAt = now; if (!r.activatedAt) r.activatedAt = now;
439
+ return { ...r, metadata: { ...r.metadata } };
440
+ }
441
+ export function offlineNostrRelayV2(id) { const r = _nsRelays.get(id); if (!r) throw new Error(`nostr relay ${id} not found`); _nsCheckR(r.status, NOSTR_RELAY_MATURITY_V2.OFFLINE); r.status = NOSTR_RELAY_MATURITY_V2.OFFLINE; r.updatedAt = Date.now(); return { ...r, metadata: { ...r.metadata } }; }
442
+ export function retireNostrRelayV2(id) { const r = _nsRelays.get(id); if (!r) throw new Error(`nostr relay ${id} not found`); _nsCheckR(r.status, NOSTR_RELAY_MATURITY_V2.RETIRED); const now = Date.now(); r.status = NOSTR_RELAY_MATURITY_V2.RETIRED; r.updatedAt = now; if (!r.retiredAt) r.retiredAt = now; return { ...r, metadata: { ...r.metadata } }; }
443
+ export function touchNostrRelayV2(id) { const r = _nsRelays.get(id); if (!r) throw new Error(`nostr relay ${id} not found`); if (_nsRelayTerminal.has(r.status)) throw new Error(`cannot touch terminal nostr relay ${id}`); const now = Date.now(); r.lastTouchedAt = now; r.updatedAt = now; return { ...r, metadata: { ...r.metadata } }; }
444
+ export function getNostrRelayV2(id) { const r = _nsRelays.get(id); if (!r) return null; return { ...r, metadata: { ...r.metadata } }; }
445
+ export function listNostrRelaysV2() { return [..._nsRelays.values()].map((r) => ({ ...r, metadata: { ...r.metadata } })); }
446
+
447
+ function _nsCountPending(rid) { let n = 0; for (const e of _nsEvents.values()) if (e.relayId === rid && (e.status === NOSTR_EVENT_LIFECYCLE_V2.QUEUED || e.status === NOSTR_EVENT_LIFECYCLE_V2.PUBLISHING)) n++; return n; }
448
+
449
+ export function createNostrEventV2({ id, relayId, kind, metadata } = {}) {
450
+ if (!id || typeof id !== "string") throw new Error("id is required");
451
+ if (!relayId || typeof relayId !== "string") throw new Error("relayId is required");
452
+ if (_nsEvents.has(id)) throw new Error(`nostr event ${id} already exists`);
453
+ if (!_nsRelays.has(relayId)) throw new Error(`nostr relay ${relayId} not found`);
454
+ const pending = _nsCountPending(relayId);
455
+ if (pending >= _nsMaxPendingPerRelay) throw new Error(`max pending nostr events per relay (${_nsMaxPendingPerRelay}) reached for ${relayId}`);
456
+ const now = Date.now();
457
+ const e = { id, relayId, kind: typeof kind === "number" ? kind : 1, status: NOSTR_EVENT_LIFECYCLE_V2.QUEUED, createdAt: now, updatedAt: now, startedAt: null, settledAt: null, metadata: { ...(metadata || {}) } };
458
+ _nsEvents.set(id, e);
459
+ return { ...e, metadata: { ...e.metadata } };
460
+ }
461
+ function _nsCheckE(from, to) { const a = _nsEventTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid nostr event transition ${from} → ${to}`); }
462
+ export function startNostrEventV2(id) { const e = _nsEvents.get(id); if (!e) throw new Error(`nostr event ${id} not found`); _nsCheckE(e.status, NOSTR_EVENT_LIFECYCLE_V2.PUBLISHING); const now = Date.now(); e.status = NOSTR_EVENT_LIFECYCLE_V2.PUBLISHING; e.updatedAt = now; if (!e.startedAt) e.startedAt = now; return { ...e, metadata: { ...e.metadata } }; }
463
+ export function publishNostrEventV2(id) { const e = _nsEvents.get(id); if (!e) throw new Error(`nostr event ${id} not found`); _nsCheckE(e.status, NOSTR_EVENT_LIFECYCLE_V2.PUBLISHED); const now = Date.now(); e.status = NOSTR_EVENT_LIFECYCLE_V2.PUBLISHED; e.updatedAt = now; if (!e.settledAt) e.settledAt = now; return { ...e, metadata: { ...e.metadata } }; }
464
+ export function failNostrEventV2(id, reason) { const e = _nsEvents.get(id); if (!e) throw new Error(`nostr event ${id} not found`); _nsCheckE(e.status, NOSTR_EVENT_LIFECYCLE_V2.FAILED); const now = Date.now(); e.status = NOSTR_EVENT_LIFECYCLE_V2.FAILED; e.updatedAt = now; if (!e.settledAt) e.settledAt = now; if (reason) e.metadata.failReason = String(reason); return { ...e, metadata: { ...e.metadata } }; }
465
+ export function cancelNostrEventV2(id, reason) { const e = _nsEvents.get(id); if (!e) throw new Error(`nostr event ${id} not found`); _nsCheckE(e.status, NOSTR_EVENT_LIFECYCLE_V2.CANCELLED); const now = Date.now(); e.status = NOSTR_EVENT_LIFECYCLE_V2.CANCELLED; e.updatedAt = now; if (!e.settledAt) e.settledAt = now; if (reason) e.metadata.cancelReason = String(reason); return { ...e, metadata: { ...e.metadata } }; }
466
+ export function getNostrEventV2(id) { const e = _nsEvents.get(id); if (!e) return null; return { ...e, metadata: { ...e.metadata } }; }
467
+ export function listNostrEventsV2() { return [..._nsEvents.values()].map((e) => ({ ...e, metadata: { ...e.metadata } })); }
468
+
469
+ export function autoOfflineIdleNostrRelaysV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const r of _nsRelays.values()) if (r.status === NOSTR_RELAY_MATURITY_V2.ACTIVE && (t - r.lastTouchedAt) >= _nsRelayIdleMs) { r.status = NOSTR_RELAY_MATURITY_V2.OFFLINE; r.updatedAt = t; flipped.push(r.id); } return { flipped, count: flipped.length }; }
470
+ export function autoFailStuckNostrEventsV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const e of _nsEvents.values()) if (e.status === NOSTR_EVENT_LIFECYCLE_V2.PUBLISHING && e.startedAt != null && (t - e.startedAt) >= _nsEventStuckMs) { e.status = NOSTR_EVENT_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 }; }
471
+
472
+ export function getNostrBridgeStatsV2() {
473
+ const relaysByStatus = {}; for (const s of Object.values(NOSTR_RELAY_MATURITY_V2)) relaysByStatus[s] = 0; for (const r of _nsRelays.values()) relaysByStatus[r.status]++;
474
+ const eventsByStatus = {}; for (const s of Object.values(NOSTR_EVENT_LIFECYCLE_V2)) eventsByStatus[s] = 0; for (const e of _nsEvents.values()) eventsByStatus[e.status]++;
475
+ return { totalRelaysV2: _nsRelays.size, totalEventsV2: _nsEvents.size, maxActiveNostrRelaysPerOwner: _nsMaxActivePerOwner, maxPendingNostrEventsPerRelay: _nsMaxPendingPerRelay, nostrRelayIdleMs: _nsRelayIdleMs, nostrEventStuckMs: _nsEventStuckMs, relaysByStatus, eventsByStatus };
476
+ }