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
@@ -846,3 +846,108 @@ export function _resetV2State() {
846
846
  _v2TaskContributions.clear();
847
847
  _v2Distributions.length = 0;
848
848
  }
849
+
850
+
851
+ // ===== V2 Surface: Agent Economy governance overlay (CLI v0.137.0) =====
852
+ export const ECONOMY_ACCOUNT_MATURITY_V2 = Object.freeze({
853
+ PENDING: "pending", ACTIVE: "active", FROZEN: "frozen", CLOSED: "closed",
854
+ });
855
+ export const ECONOMY_TX_LIFECYCLE_V2 = Object.freeze({
856
+ QUEUED: "queued", PROCESSING: "processing", SETTLED: "settled", FAILED: "failed", CANCELLED: "cancelled",
857
+ });
858
+
859
+ const _econAcctTrans = new Map([
860
+ [ECONOMY_ACCOUNT_MATURITY_V2.PENDING, new Set([ECONOMY_ACCOUNT_MATURITY_V2.ACTIVE, ECONOMY_ACCOUNT_MATURITY_V2.CLOSED])],
861
+ [ECONOMY_ACCOUNT_MATURITY_V2.ACTIVE, new Set([ECONOMY_ACCOUNT_MATURITY_V2.FROZEN, ECONOMY_ACCOUNT_MATURITY_V2.CLOSED])],
862
+ [ECONOMY_ACCOUNT_MATURITY_V2.FROZEN, new Set([ECONOMY_ACCOUNT_MATURITY_V2.ACTIVE, ECONOMY_ACCOUNT_MATURITY_V2.CLOSED])],
863
+ [ECONOMY_ACCOUNT_MATURITY_V2.CLOSED, new Set()],
864
+ ]);
865
+ const _econAcctTerminal = new Set([ECONOMY_ACCOUNT_MATURITY_V2.CLOSED]);
866
+ const _econTxTrans = new Map([
867
+ [ECONOMY_TX_LIFECYCLE_V2.QUEUED, new Set([ECONOMY_TX_LIFECYCLE_V2.PROCESSING, ECONOMY_TX_LIFECYCLE_V2.CANCELLED])],
868
+ [ECONOMY_TX_LIFECYCLE_V2.PROCESSING, new Set([ECONOMY_TX_LIFECYCLE_V2.SETTLED, ECONOMY_TX_LIFECYCLE_V2.FAILED, ECONOMY_TX_LIFECYCLE_V2.CANCELLED])],
869
+ [ECONOMY_TX_LIFECYCLE_V2.SETTLED, new Set()],
870
+ [ECONOMY_TX_LIFECYCLE_V2.FAILED, new Set()],
871
+ [ECONOMY_TX_LIFECYCLE_V2.CANCELLED, new Set()],
872
+ ]);
873
+
874
+ const _econAccts = new Map();
875
+ const _econTxs = new Map();
876
+ let _econMaxActivePerHolder = 20;
877
+ let _econMaxPendingPerAcct = 30;
878
+ let _econAcctIdleMs = 7 * 24 * 60 * 60 * 1000;
879
+ let _econTxStuckMs = 5 * 60 * 1000;
880
+
881
+ function _econPos(n, lbl) { const v = Math.floor(Number(n)); if (!Number.isFinite(v) || v <= 0) throw new Error(`${lbl} must be positive integer`); return v; }
882
+
883
+ export function setMaxActiveEconomyAccountsPerHolderV2(n) { _econMaxActivePerHolder = _econPos(n, "maxActiveEconomyAccountsPerHolder"); }
884
+ export function getMaxActiveEconomyAccountsPerHolderV2() { return _econMaxActivePerHolder; }
885
+ export function setMaxPendingEconomyTxsPerAccountV2(n) { _econMaxPendingPerAcct = _econPos(n, "maxPendingEconomyTxsPerAccount"); }
886
+ export function getMaxPendingEconomyTxsPerAccountV2() { return _econMaxPendingPerAcct; }
887
+ export function setEconomyAccountIdleMsV2(n) { _econAcctIdleMs = _econPos(n, "economyAccountIdleMs"); }
888
+ export function getEconomyAccountIdleMsV2() { return _econAcctIdleMs; }
889
+ export function setEconomyTxStuckMsV2(n) { _econTxStuckMs = _econPos(n, "economyTxStuckMs"); }
890
+ export function getEconomyTxStuckMsV2() { return _econTxStuckMs; }
891
+
892
+ export function _resetStateAgentEconomyV2() {
893
+ _econAccts.clear(); _econTxs.clear();
894
+ _econMaxActivePerHolder = 20; _econMaxPendingPerAcct = 30;
895
+ _econAcctIdleMs = 7 * 24 * 60 * 60 * 1000; _econTxStuckMs = 5 * 60 * 1000;
896
+ }
897
+
898
+ export function registerEconomyAccountV2({ id, holder, currency, metadata } = {}) {
899
+ if (!id || typeof id !== "string") throw new Error("id is required");
900
+ if (!holder || typeof holder !== "string") throw new Error("holder is required");
901
+ if (_econAccts.has(id)) throw new Error(`economy account ${id} already registered`);
902
+ const now = Date.now();
903
+ const a = { id, holder, currency: currency || "CLC", status: ECONOMY_ACCOUNT_MATURITY_V2.PENDING, createdAt: now, updatedAt: now, activatedAt: null, closedAt: null, lastTouchedAt: now, metadata: { ...(metadata || {}) } };
904
+ _econAccts.set(id, a);
905
+ return { ...a, metadata: { ...a.metadata } };
906
+ }
907
+ function _econCheckA(from, to) { const a = _econAcctTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid economy account transition ${from} → ${to}`); }
908
+ function _econCountActive(holder) { let n = 0; for (const a of _econAccts.values()) if (a.holder === holder && a.status === ECONOMY_ACCOUNT_MATURITY_V2.ACTIVE) n++; return n; }
909
+
910
+ export function activateEconomyAccountV2(id) {
911
+ const a = _econAccts.get(id); if (!a) throw new Error(`economy account ${id} not found`);
912
+ _econCheckA(a.status, ECONOMY_ACCOUNT_MATURITY_V2.ACTIVE);
913
+ const recovery = a.status === ECONOMY_ACCOUNT_MATURITY_V2.FROZEN;
914
+ if (!recovery) { const c = _econCountActive(a.holder); if (c >= _econMaxActivePerHolder) throw new Error(`max active economy accounts per holder (${_econMaxActivePerHolder}) reached for ${a.holder}`); }
915
+ const now = Date.now(); a.status = ECONOMY_ACCOUNT_MATURITY_V2.ACTIVE; a.updatedAt = now; a.lastTouchedAt = now; if (!a.activatedAt) a.activatedAt = now;
916
+ return { ...a, metadata: { ...a.metadata } };
917
+ }
918
+ export function freezeEconomyAccountV2(id) { const a = _econAccts.get(id); if (!a) throw new Error(`economy account ${id} not found`); _econCheckA(a.status, ECONOMY_ACCOUNT_MATURITY_V2.FROZEN); a.status = ECONOMY_ACCOUNT_MATURITY_V2.FROZEN; a.updatedAt = Date.now(); return { ...a, metadata: { ...a.metadata } }; }
919
+ export function closeEconomyAccountV2(id) { const a = _econAccts.get(id); if (!a) throw new Error(`economy account ${id} not found`); _econCheckA(a.status, ECONOMY_ACCOUNT_MATURITY_V2.CLOSED); const now = Date.now(); a.status = ECONOMY_ACCOUNT_MATURITY_V2.CLOSED; a.updatedAt = now; if (!a.closedAt) a.closedAt = now; return { ...a, metadata: { ...a.metadata } }; }
920
+ export function touchEconomyAccountV2(id) { const a = _econAccts.get(id); if (!a) throw new Error(`economy account ${id} not found`); if (_econAcctTerminal.has(a.status)) throw new Error(`cannot touch terminal economy account ${id}`); const now = Date.now(); a.lastTouchedAt = now; a.updatedAt = now; return { ...a, metadata: { ...a.metadata } }; }
921
+ export function getEconomyAccountV2(id) { const a = _econAccts.get(id); if (!a) return null; return { ...a, metadata: { ...a.metadata } }; }
922
+ export function listEconomyAccountsV2() { return [..._econAccts.values()].map((a) => ({ ...a, metadata: { ...a.metadata } })); }
923
+
924
+ function _econCountPending(aid) { let n = 0; for (const t of _econTxs.values()) if (t.accountId === aid && (t.status === ECONOMY_TX_LIFECYCLE_V2.QUEUED || t.status === ECONOMY_TX_LIFECYCLE_V2.PROCESSING)) n++; return n; }
925
+
926
+ export function createEconomyTxV2({ id, accountId, amount, metadata } = {}) {
927
+ if (!id || typeof id !== "string") throw new Error("id is required");
928
+ if (!accountId || typeof accountId !== "string") throw new Error("accountId is required");
929
+ if (_econTxs.has(id)) throw new Error(`economy tx ${id} already exists`);
930
+ if (!_econAccts.has(accountId)) throw new Error(`economy account ${accountId} not found`);
931
+ const pending = _econCountPending(accountId);
932
+ if (pending >= _econMaxPendingPerAcct) throw new Error(`max pending economy txs per account (${_econMaxPendingPerAcct}) reached for ${accountId}`);
933
+ const now = Date.now();
934
+ const t = { id, accountId, amount: amount || "0", status: ECONOMY_TX_LIFECYCLE_V2.QUEUED, createdAt: now, updatedAt: now, startedAt: null, settledAt: null, metadata: { ...(metadata || {}) } };
935
+ _econTxs.set(id, t);
936
+ return { ...t, metadata: { ...t.metadata } };
937
+ }
938
+ function _econCheckT(from, to) { const a = _econTxTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid economy tx transition ${from} → ${to}`); }
939
+ export function startEconomyTxV2(id) { const t = _econTxs.get(id); if (!t) throw new Error(`economy tx ${id} not found`); _econCheckT(t.status, ECONOMY_TX_LIFECYCLE_V2.PROCESSING); const now = Date.now(); t.status = ECONOMY_TX_LIFECYCLE_V2.PROCESSING; t.updatedAt = now; if (!t.startedAt) t.startedAt = now; return { ...t, metadata: { ...t.metadata } }; }
940
+ export function settleEconomyTxV2(id) { const t = _econTxs.get(id); if (!t) throw new Error(`economy tx ${id} not found`); _econCheckT(t.status, ECONOMY_TX_LIFECYCLE_V2.SETTLED); const now = Date.now(); t.status = ECONOMY_TX_LIFECYCLE_V2.SETTLED; t.updatedAt = now; if (!t.settledAt) t.settledAt = now; return { ...t, metadata: { ...t.metadata } }; }
941
+ export function failEconomyTxV2(id, reason) { const t = _econTxs.get(id); if (!t) throw new Error(`economy tx ${id} not found`); _econCheckT(t.status, ECONOMY_TX_LIFECYCLE_V2.FAILED); const now = Date.now(); t.status = ECONOMY_TX_LIFECYCLE_V2.FAILED; t.updatedAt = now; if (!t.settledAt) t.settledAt = now; if (reason) t.metadata.failReason = String(reason); return { ...t, metadata: { ...t.metadata } }; }
942
+ export function cancelEconomyTxV2(id, reason) { const t = _econTxs.get(id); if (!t) throw new Error(`economy tx ${id} not found`); _econCheckT(t.status, ECONOMY_TX_LIFECYCLE_V2.CANCELLED); const now = Date.now(); t.status = ECONOMY_TX_LIFECYCLE_V2.CANCELLED; t.updatedAt = now; if (!t.settledAt) t.settledAt = now; if (reason) t.metadata.cancelReason = String(reason); return { ...t, metadata: { ...t.metadata } }; }
943
+ export function getEconomyTxV2(id) { const t = _econTxs.get(id); if (!t) return null; return { ...t, metadata: { ...t.metadata } }; }
944
+ export function listEconomyTxsV2() { return [..._econTxs.values()].map((t) => ({ ...t, metadata: { ...t.metadata } })); }
945
+
946
+ export function autoFreezeIdleEconomyAccountsV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const a of _econAccts.values()) if (a.status === ECONOMY_ACCOUNT_MATURITY_V2.ACTIVE && (t - a.lastTouchedAt) >= _econAcctIdleMs) { a.status = ECONOMY_ACCOUNT_MATURITY_V2.FROZEN; a.updatedAt = t; flipped.push(a.id); } return { flipped, count: flipped.length }; }
947
+ export function autoFailStuckEconomyTxsV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const tx of _econTxs.values()) if (tx.status === ECONOMY_TX_LIFECYCLE_V2.PROCESSING && tx.startedAt != null && (t - tx.startedAt) >= _econTxStuckMs) { tx.status = ECONOMY_TX_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 }; }
948
+
949
+ export function getAgentEconomyGovStatsV2() {
950
+ const accountsByStatus = {}; for (const s of Object.values(ECONOMY_ACCOUNT_MATURITY_V2)) accountsByStatus[s] = 0; for (const a of _econAccts.values()) accountsByStatus[a.status]++;
951
+ const txsByStatus = {}; for (const s of Object.values(ECONOMY_TX_LIFECYCLE_V2)) txsByStatus[s] = 0; for (const t of _econTxs.values()) txsByStatus[t.status]++;
952
+ return { totalAccountsV2: _econAccts.size, totalTxsV2: _econTxs.size, maxActiveEconomyAccountsPerHolder: _econMaxActivePerHolder, maxPendingEconomyTxsPerAccount: _econMaxPendingPerAcct, economyAccountIdleMs: _econAcctIdleMs, economyTxStuckMs: _econTxStuckMs, accountsByStatus, txsByStatus };
953
+ }
@@ -742,3 +742,108 @@ export function _resetV2State() {
742
742
  _v2DataSources.clear();
743
743
  _v2StatusHistory.clear();
744
744
  }
745
+
746
+
747
+ // ===== V2 Surface: App Builder governance overlay (CLI v0.138.0) =====
748
+ export const APP_MATURITY_V2 = Object.freeze({
749
+ PENDING: "pending", ACTIVE: "active", PAUSED: "paused", ARCHIVED: "archived",
750
+ });
751
+ export const APP_BUILD_LIFECYCLE_V2 = Object.freeze({
752
+ QUEUED: "queued", BUILDING: "building", SUCCEEDED: "succeeded", FAILED: "failed", CANCELLED: "cancelled",
753
+ });
754
+
755
+ const _appTrans = new Map([
756
+ [APP_MATURITY_V2.PENDING, new Set([APP_MATURITY_V2.ACTIVE, APP_MATURITY_V2.ARCHIVED])],
757
+ [APP_MATURITY_V2.ACTIVE, new Set([APP_MATURITY_V2.PAUSED, APP_MATURITY_V2.ARCHIVED])],
758
+ [APP_MATURITY_V2.PAUSED, new Set([APP_MATURITY_V2.ACTIVE, APP_MATURITY_V2.ARCHIVED])],
759
+ [APP_MATURITY_V2.ARCHIVED, new Set()],
760
+ ]);
761
+ const _appTerminal = new Set([APP_MATURITY_V2.ARCHIVED]);
762
+ const _appBuildTrans = new Map([
763
+ [APP_BUILD_LIFECYCLE_V2.QUEUED, new Set([APP_BUILD_LIFECYCLE_V2.BUILDING, APP_BUILD_LIFECYCLE_V2.CANCELLED])],
764
+ [APP_BUILD_LIFECYCLE_V2.BUILDING, new Set([APP_BUILD_LIFECYCLE_V2.SUCCEEDED, APP_BUILD_LIFECYCLE_V2.FAILED, APP_BUILD_LIFECYCLE_V2.CANCELLED])],
765
+ [APP_BUILD_LIFECYCLE_V2.SUCCEEDED, new Set()],
766
+ [APP_BUILD_LIFECYCLE_V2.FAILED, new Set()],
767
+ [APP_BUILD_LIFECYCLE_V2.CANCELLED, new Set()],
768
+ ]);
769
+
770
+ const _appsV2 = new Map();
771
+ const _appBuilds = new Map();
772
+ let _appMaxActivePerOwner = 10;
773
+ let _appMaxPendingBuildsPerApp = 20;
774
+ let _appIdleMs = 30 * 24 * 60 * 60 * 1000;
775
+ let _appBuildStuckMs = 10 * 60 * 1000;
776
+
777
+ function _appPos(n, lbl) { const v = Math.floor(Number(n)); if (!Number.isFinite(v) || v <= 0) throw new Error(`${lbl} must be positive integer`); return v; }
778
+
779
+ export function setMaxActiveAppsPerOwnerV2(n) { _appMaxActivePerOwner = _appPos(n, "maxActiveAppsPerOwner"); }
780
+ export function getMaxActiveAppsPerOwnerV2() { return _appMaxActivePerOwner; }
781
+ export function setMaxPendingAppBuildsPerAppV2(n) { _appMaxPendingBuildsPerApp = _appPos(n, "maxPendingAppBuildsPerApp"); }
782
+ export function getMaxPendingAppBuildsPerAppV2() { return _appMaxPendingBuildsPerApp; }
783
+ export function setAppIdleMsV2(n) { _appIdleMs = _appPos(n, "appIdleMs"); }
784
+ export function getAppIdleMsV2() { return _appIdleMs; }
785
+ export function setAppBuildStuckMsV2(n) { _appBuildStuckMs = _appPos(n, "appBuildStuckMs"); }
786
+ export function getAppBuildStuckMsV2() { return _appBuildStuckMs; }
787
+
788
+ export function _resetStateAppBuilderV2() {
789
+ _appsV2.clear(); _appBuilds.clear();
790
+ _appMaxActivePerOwner = 10; _appMaxPendingBuildsPerApp = 20;
791
+ _appIdleMs = 30 * 24 * 60 * 60 * 1000; _appBuildStuckMs = 10 * 60 * 1000;
792
+ }
793
+
794
+ export function registerAppV2({ id, owner, name, metadata } = {}) {
795
+ if (!id || typeof id !== "string") throw new Error("id is required");
796
+ if (!owner || typeof owner !== "string") throw new Error("owner is required");
797
+ if (_appsV2.has(id)) throw new Error(`app ${id} already registered`);
798
+ const now = Date.now();
799
+ const a = { id, owner, name: name || id, status: APP_MATURITY_V2.PENDING, createdAt: now, updatedAt: now, activatedAt: null, archivedAt: null, lastTouchedAt: now, metadata: { ...(metadata || {}) } };
800
+ _appsV2.set(id, a);
801
+ return { ...a, metadata: { ...a.metadata } };
802
+ }
803
+ function _appCheckA(from, to) { const a = _appTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid app transition ${from} → ${to}`); }
804
+ function _appCountActive(owner) { let n = 0; for (const a of _appsV2.values()) if (a.owner === owner && a.status === APP_MATURITY_V2.ACTIVE) n++; return n; }
805
+
806
+ export function activateAppV2(id) {
807
+ const a = _appsV2.get(id); if (!a) throw new Error(`app ${id} not found`);
808
+ _appCheckA(a.status, APP_MATURITY_V2.ACTIVE);
809
+ const recovery = a.status === APP_MATURITY_V2.PAUSED;
810
+ if (!recovery) { const c = _appCountActive(a.owner); if (c >= _appMaxActivePerOwner) throw new Error(`max active apps per owner (${_appMaxActivePerOwner}) reached for ${a.owner}`); }
811
+ const now = Date.now(); a.status = APP_MATURITY_V2.ACTIVE; a.updatedAt = now; a.lastTouchedAt = now; if (!a.activatedAt) a.activatedAt = now;
812
+ return { ...a, metadata: { ...a.metadata } };
813
+ }
814
+ export function pauseAppV2(id) { const a = _appsV2.get(id); if (!a) throw new Error(`app ${id} not found`); _appCheckA(a.status, APP_MATURITY_V2.PAUSED); a.status = APP_MATURITY_V2.PAUSED; a.updatedAt = Date.now(); return { ...a, metadata: { ...a.metadata } }; }
815
+ export function archiveAppV2(id) { const a = _appsV2.get(id); if (!a) throw new Error(`app ${id} not found`); _appCheckA(a.status, APP_MATURITY_V2.ARCHIVED); const now = Date.now(); a.status = APP_MATURITY_V2.ARCHIVED; a.updatedAt = now; if (!a.archivedAt) a.archivedAt = now; return { ...a, metadata: { ...a.metadata } }; }
816
+ export function touchAppV2(id) { const a = _appsV2.get(id); if (!a) throw new Error(`app ${id} not found`); if (_appTerminal.has(a.status)) throw new Error(`cannot touch terminal app ${id}`); const now = Date.now(); a.lastTouchedAt = now; a.updatedAt = now; return { ...a, metadata: { ...a.metadata } }; }
817
+ export function getAppV2(id) { const a = _appsV2.get(id); if (!a) return null; return { ...a, metadata: { ...a.metadata } }; }
818
+ export function listAppsV2() { return [..._appsV2.values()].map((a) => ({ ...a, metadata: { ...a.metadata } })); }
819
+
820
+ function _appCountPendingBuilds(appId) { let n = 0; for (const b of _appBuilds.values()) if (b.appId === appId && (b.status === APP_BUILD_LIFECYCLE_V2.QUEUED || b.status === APP_BUILD_LIFECYCLE_V2.BUILDING)) n++; return n; }
821
+
822
+ export function createAppBuildV2({ id, appId, target, metadata } = {}) {
823
+ if (!id || typeof id !== "string") throw new Error("id is required");
824
+ if (!appId || typeof appId !== "string") throw new Error("appId is required");
825
+ if (_appBuilds.has(id)) throw new Error(`app build ${id} already exists`);
826
+ if (!_appsV2.has(appId)) throw new Error(`app ${appId} not found`);
827
+ const pending = _appCountPendingBuilds(appId);
828
+ if (pending >= _appMaxPendingBuildsPerApp) throw new Error(`max pending app builds per app (${_appMaxPendingBuildsPerApp}) reached for ${appId}`);
829
+ const now = Date.now();
830
+ const b = { id, appId, target: target || "web", status: APP_BUILD_LIFECYCLE_V2.QUEUED, createdAt: now, updatedAt: now, startedAt: null, settledAt: null, metadata: { ...(metadata || {}) } };
831
+ _appBuilds.set(id, b);
832
+ return { ...b, metadata: { ...b.metadata } };
833
+ }
834
+ function _appCheckB(from, to) { const a = _appBuildTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid app build transition ${from} → ${to}`); }
835
+ export function startAppBuildV2(id) { const b = _appBuilds.get(id); if (!b) throw new Error(`app build ${id} not found`); _appCheckB(b.status, APP_BUILD_LIFECYCLE_V2.BUILDING); const now = Date.now(); b.status = APP_BUILD_LIFECYCLE_V2.BUILDING; b.updatedAt = now; if (!b.startedAt) b.startedAt = now; return { ...b, metadata: { ...b.metadata } }; }
836
+ export function succeedAppBuildV2(id) { const b = _appBuilds.get(id); if (!b) throw new Error(`app build ${id} not found`); _appCheckB(b.status, APP_BUILD_LIFECYCLE_V2.SUCCEEDED); const now = Date.now(); b.status = APP_BUILD_LIFECYCLE_V2.SUCCEEDED; b.updatedAt = now; if (!b.settledAt) b.settledAt = now; return { ...b, metadata: { ...b.metadata } }; }
837
+ export function failAppBuildV2(id, reason) { const b = _appBuilds.get(id); if (!b) throw new Error(`app build ${id} not found`); _appCheckB(b.status, APP_BUILD_LIFECYCLE_V2.FAILED); const now = Date.now(); b.status = APP_BUILD_LIFECYCLE_V2.FAILED; b.updatedAt = now; if (!b.settledAt) b.settledAt = now; if (reason) b.metadata.failReason = String(reason); return { ...b, metadata: { ...b.metadata } }; }
838
+ export function cancelAppBuildV2(id, reason) { const b = _appBuilds.get(id); if (!b) throw new Error(`app build ${id} not found`); _appCheckB(b.status, APP_BUILD_LIFECYCLE_V2.CANCELLED); const now = Date.now(); b.status = APP_BUILD_LIFECYCLE_V2.CANCELLED; b.updatedAt = now; if (!b.settledAt) b.settledAt = now; if (reason) b.metadata.cancelReason = String(reason); return { ...b, metadata: { ...b.metadata } }; }
839
+ export function getAppBuildV2(id) { const b = _appBuilds.get(id); if (!b) return null; return { ...b, metadata: { ...b.metadata } }; }
840
+ export function listAppBuildsV2() { return [..._appBuilds.values()].map((b) => ({ ...b, metadata: { ...b.metadata } })); }
841
+
842
+ export function autoPauseIdleAppsV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const a of _appsV2.values()) if (a.status === APP_MATURITY_V2.ACTIVE && (t - a.lastTouchedAt) >= _appIdleMs) { a.status = APP_MATURITY_V2.PAUSED; a.updatedAt = t; flipped.push(a.id); } return { flipped, count: flipped.length }; }
843
+ export function autoFailStuckAppBuildsV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const b of _appBuilds.values()) if (b.status === APP_BUILD_LIFECYCLE_V2.BUILDING && b.startedAt != null && (t - b.startedAt) >= _appBuildStuckMs) { b.status = APP_BUILD_LIFECYCLE_V2.FAILED; b.updatedAt = t; if (!b.settledAt) b.settledAt = t; b.metadata.failReason = "auto-fail-stuck"; flipped.push(b.id); } return { flipped, count: flipped.length }; }
844
+
845
+ export function getAppBuilderGovStatsV2() {
846
+ const appsByStatus = {}; for (const s of Object.values(APP_MATURITY_V2)) appsByStatus[s] = 0; for (const a of _appsV2.values()) appsByStatus[a.status]++;
847
+ const buildsByStatus = {}; for (const s of Object.values(APP_BUILD_LIFECYCLE_V2)) buildsByStatus[s] = 0; for (const b of _appBuilds.values()) buildsByStatus[b.status]++;
848
+ return { totalAppsV2: _appsV2.size, totalAppBuildsV2: _appBuilds.size, maxActiveAppsPerOwner: _appMaxActivePerOwner, maxPendingAppBuildsPerApp: _appMaxPendingBuildsPerApp, appIdleMs: _appIdleMs, appBuildStuckMs: _appBuildStuckMs, appsByStatus, buildsByStatus };
849
+ }
@@ -492,3 +492,108 @@ Reply with a JSON object: { "action": "retry|add_step|skip", "newParams": {...},
492
492
  return null;
493
493
  }
494
494
  }
495
+
496
+
497
+ // ===== V2 Surface: Autonomous Agent governance overlay (CLI v0.138.0) =====
498
+ export const AUTOAGENT_MATURITY_V2 = Object.freeze({
499
+ PENDING: "pending", ACTIVE: "active", PAUSED: "paused", ARCHIVED: "archived",
500
+ });
501
+ export const AUTOAGENT_RUN_LIFECYCLE_V2 = Object.freeze({
502
+ QUEUED: "queued", RUNNING: "running", COMPLETED: "completed", FAILED: "failed", CANCELLED: "cancelled",
503
+ });
504
+
505
+ const _aaTrans = new Map([
506
+ [AUTOAGENT_MATURITY_V2.PENDING, new Set([AUTOAGENT_MATURITY_V2.ACTIVE, AUTOAGENT_MATURITY_V2.ARCHIVED])],
507
+ [AUTOAGENT_MATURITY_V2.ACTIVE, new Set([AUTOAGENT_MATURITY_V2.PAUSED, AUTOAGENT_MATURITY_V2.ARCHIVED])],
508
+ [AUTOAGENT_MATURITY_V2.PAUSED, new Set([AUTOAGENT_MATURITY_V2.ACTIVE, AUTOAGENT_MATURITY_V2.ARCHIVED])],
509
+ [AUTOAGENT_MATURITY_V2.ARCHIVED, new Set()],
510
+ ]);
511
+ const _aaTerminal = new Set([AUTOAGENT_MATURITY_V2.ARCHIVED]);
512
+ const _aaRunTrans = new Map([
513
+ [AUTOAGENT_RUN_LIFECYCLE_V2.QUEUED, new Set([AUTOAGENT_RUN_LIFECYCLE_V2.RUNNING, AUTOAGENT_RUN_LIFECYCLE_V2.CANCELLED])],
514
+ [AUTOAGENT_RUN_LIFECYCLE_V2.RUNNING, new Set([AUTOAGENT_RUN_LIFECYCLE_V2.COMPLETED, AUTOAGENT_RUN_LIFECYCLE_V2.FAILED, AUTOAGENT_RUN_LIFECYCLE_V2.CANCELLED])],
515
+ [AUTOAGENT_RUN_LIFECYCLE_V2.COMPLETED, new Set()],
516
+ [AUTOAGENT_RUN_LIFECYCLE_V2.FAILED, new Set()],
517
+ [AUTOAGENT_RUN_LIFECYCLE_V2.CANCELLED, new Set()],
518
+ ]);
519
+
520
+ const _aaAgents = new Map();
521
+ const _aaRuns = new Map();
522
+ let _aaMaxActivePerOwner = 5;
523
+ let _aaMaxPendingRunsPerAgent = 10;
524
+ let _aaAgentIdleMs = 7 * 24 * 60 * 60 * 1000;
525
+ let _aaRunStuckMs = 30 * 60 * 1000;
526
+
527
+ function _aaPos(n, lbl) { const v = Math.floor(Number(n)); if (!Number.isFinite(v) || v <= 0) throw new Error(`${lbl} must be positive integer`); return v; }
528
+
529
+ export function setMaxActiveAutoAgentsPerOwnerV2(n) { _aaMaxActivePerOwner = _aaPos(n, "maxActiveAutoAgentsPerOwner"); }
530
+ export function getMaxActiveAutoAgentsPerOwnerV2() { return _aaMaxActivePerOwner; }
531
+ export function setMaxPendingAutoAgentRunsPerAgentV2(n) { _aaMaxPendingRunsPerAgent = _aaPos(n, "maxPendingAutoAgentRunsPerAgent"); }
532
+ export function getMaxPendingAutoAgentRunsPerAgentV2() { return _aaMaxPendingRunsPerAgent; }
533
+ export function setAutoAgentIdleMsV2(n) { _aaAgentIdleMs = _aaPos(n, "autoAgentIdleMs"); }
534
+ export function getAutoAgentIdleMsV2() { return _aaAgentIdleMs; }
535
+ export function setAutoAgentRunStuckMsV2(n) { _aaRunStuckMs = _aaPos(n, "autoAgentRunStuckMs"); }
536
+ export function getAutoAgentRunStuckMsV2() { return _aaRunStuckMs; }
537
+
538
+ export function _resetStateAutonomousAgentV2() {
539
+ _aaAgents.clear(); _aaRuns.clear();
540
+ _aaMaxActivePerOwner = 5; _aaMaxPendingRunsPerAgent = 10;
541
+ _aaAgentIdleMs = 7 * 24 * 60 * 60 * 1000; _aaRunStuckMs = 30 * 60 * 1000;
542
+ }
543
+
544
+ export function registerAutoAgentV2({ id, owner, goal, metadata } = {}) {
545
+ if (!id || typeof id !== "string") throw new Error("id is required");
546
+ if (!owner || typeof owner !== "string") throw new Error("owner is required");
547
+ if (_aaAgents.has(id)) throw new Error(`auto-agent ${id} already registered`);
548
+ const now = Date.now();
549
+ const a = { id, owner, goal: goal || "", status: AUTOAGENT_MATURITY_V2.PENDING, createdAt: now, updatedAt: now, activatedAt: null, archivedAt: null, lastTouchedAt: now, metadata: { ...(metadata || {}) } };
550
+ _aaAgents.set(id, a);
551
+ return { ...a, metadata: { ...a.metadata } };
552
+ }
553
+ function _aaCheckA(from, to) { const a = _aaTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid auto-agent transition ${from} → ${to}`); }
554
+ function _aaCountActive(owner) { let n = 0; for (const a of _aaAgents.values()) if (a.owner === owner && a.status === AUTOAGENT_MATURITY_V2.ACTIVE) n++; return n; }
555
+
556
+ export function activateAutoAgentV2(id) {
557
+ const a = _aaAgents.get(id); if (!a) throw new Error(`auto-agent ${id} not found`);
558
+ _aaCheckA(a.status, AUTOAGENT_MATURITY_V2.ACTIVE);
559
+ const recovery = a.status === AUTOAGENT_MATURITY_V2.PAUSED;
560
+ if (!recovery) { const c = _aaCountActive(a.owner); if (c >= _aaMaxActivePerOwner) throw new Error(`max active auto-agents per owner (${_aaMaxActivePerOwner}) reached for ${a.owner}`); }
561
+ const now = Date.now(); a.status = AUTOAGENT_MATURITY_V2.ACTIVE; a.updatedAt = now; a.lastTouchedAt = now; if (!a.activatedAt) a.activatedAt = now;
562
+ return { ...a, metadata: { ...a.metadata } };
563
+ }
564
+ export function pauseAutoAgentV2(id) { const a = _aaAgents.get(id); if (!a) throw new Error(`auto-agent ${id} not found`); _aaCheckA(a.status, AUTOAGENT_MATURITY_V2.PAUSED); a.status = AUTOAGENT_MATURITY_V2.PAUSED; a.updatedAt = Date.now(); return { ...a, metadata: { ...a.metadata } }; }
565
+ export function archiveAutoAgentV2(id) { const a = _aaAgents.get(id); if (!a) throw new Error(`auto-agent ${id} not found`); _aaCheckA(a.status, AUTOAGENT_MATURITY_V2.ARCHIVED); const now = Date.now(); a.status = AUTOAGENT_MATURITY_V2.ARCHIVED; a.updatedAt = now; if (!a.archivedAt) a.archivedAt = now; return { ...a, metadata: { ...a.metadata } }; }
566
+ export function touchAutoAgentV2(id) { const a = _aaAgents.get(id); if (!a) throw new Error(`auto-agent ${id} not found`); if (_aaTerminal.has(a.status)) throw new Error(`cannot touch terminal auto-agent ${id}`); const now = Date.now(); a.lastTouchedAt = now; a.updatedAt = now; return { ...a, metadata: { ...a.metadata } }; }
567
+ export function getAutoAgentV2(id) { const a = _aaAgents.get(id); if (!a) return null; return { ...a, metadata: { ...a.metadata } }; }
568
+ export function listAutoAgentsV2() { return [..._aaAgents.values()].map((a) => ({ ...a, metadata: { ...a.metadata } })); }
569
+
570
+ function _aaCountPendingRuns(aid) { let n = 0; for (const r of _aaRuns.values()) if (r.agentId === aid && (r.status === AUTOAGENT_RUN_LIFECYCLE_V2.QUEUED || r.status === AUTOAGENT_RUN_LIFECYCLE_V2.RUNNING)) n++; return n; }
571
+
572
+ export function createAutoAgentRunV2({ id, agentId, prompt, metadata } = {}) {
573
+ if (!id || typeof id !== "string") throw new Error("id is required");
574
+ if (!agentId || typeof agentId !== "string") throw new Error("agentId is required");
575
+ if (_aaRuns.has(id)) throw new Error(`auto-agent run ${id} already exists`);
576
+ if (!_aaAgents.has(agentId)) throw new Error(`auto-agent ${agentId} not found`);
577
+ const pending = _aaCountPendingRuns(agentId);
578
+ if (pending >= _aaMaxPendingRunsPerAgent) throw new Error(`max pending auto-agent runs per agent (${_aaMaxPendingRunsPerAgent}) reached for ${agentId}`);
579
+ const now = Date.now();
580
+ const r = { id, agentId, prompt: prompt || "", status: AUTOAGENT_RUN_LIFECYCLE_V2.QUEUED, createdAt: now, updatedAt: now, startedAt: null, settledAt: null, metadata: { ...(metadata || {}) } };
581
+ _aaRuns.set(id, r);
582
+ return { ...r, metadata: { ...r.metadata } };
583
+ }
584
+ function _aaCheckR(from, to) { const a = _aaRunTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid auto-agent run transition ${from} → ${to}`); }
585
+ export function startAutoAgentRunV2(id) { const r = _aaRuns.get(id); if (!r) throw new Error(`auto-agent run ${id} not found`); _aaCheckR(r.status, AUTOAGENT_RUN_LIFECYCLE_V2.RUNNING); const now = Date.now(); r.status = AUTOAGENT_RUN_LIFECYCLE_V2.RUNNING; r.updatedAt = now; if (!r.startedAt) r.startedAt = now; return { ...r, metadata: { ...r.metadata } }; }
586
+ export function completeAutoAgentRunV2(id) { const r = _aaRuns.get(id); if (!r) throw new Error(`auto-agent run ${id} not found`); _aaCheckR(r.status, AUTOAGENT_RUN_LIFECYCLE_V2.COMPLETED); const now = Date.now(); r.status = AUTOAGENT_RUN_LIFECYCLE_V2.COMPLETED; r.updatedAt = now; if (!r.settledAt) r.settledAt = now; return { ...r, metadata: { ...r.metadata } }; }
587
+ export function failAutoAgentRunV2(id, reason) { const r = _aaRuns.get(id); if (!r) throw new Error(`auto-agent run ${id} not found`); _aaCheckR(r.status, AUTOAGENT_RUN_LIFECYCLE_V2.FAILED); const now = Date.now(); r.status = AUTOAGENT_RUN_LIFECYCLE_V2.FAILED; r.updatedAt = now; if (!r.settledAt) r.settledAt = now; if (reason) r.metadata.failReason = String(reason); return { ...r, metadata: { ...r.metadata } }; }
588
+ export function cancelAutoAgentRunV2(id, reason) { const r = _aaRuns.get(id); if (!r) throw new Error(`auto-agent run ${id} not found`); _aaCheckR(r.status, AUTOAGENT_RUN_LIFECYCLE_V2.CANCELLED); const now = Date.now(); r.status = AUTOAGENT_RUN_LIFECYCLE_V2.CANCELLED; r.updatedAt = now; if (!r.settledAt) r.settledAt = now; if (reason) r.metadata.cancelReason = String(reason); return { ...r, metadata: { ...r.metadata } }; }
589
+ export function getAutoAgentRunV2(id) { const r = _aaRuns.get(id); if (!r) return null; return { ...r, metadata: { ...r.metadata } }; }
590
+ export function listAutoAgentRunsV2() { return [..._aaRuns.values()].map((r) => ({ ...r, metadata: { ...r.metadata } })); }
591
+
592
+ export function autoPauseIdleAutoAgentsV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const a of _aaAgents.values()) if (a.status === AUTOAGENT_MATURITY_V2.ACTIVE && (t - a.lastTouchedAt) >= _aaAgentIdleMs) { a.status = AUTOAGENT_MATURITY_V2.PAUSED; a.updatedAt = t; flipped.push(a.id); } return { flipped, count: flipped.length }; }
593
+ export function autoFailStuckAutoAgentRunsV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const r of _aaRuns.values()) if (r.status === AUTOAGENT_RUN_LIFECYCLE_V2.RUNNING && r.startedAt != null && (t - r.startedAt) >= _aaRunStuckMs) { r.status = AUTOAGENT_RUN_LIFECYCLE_V2.FAILED; r.updatedAt = t; if (!r.settledAt) r.settledAt = t; r.metadata.failReason = "auto-fail-stuck"; flipped.push(r.id); } return { flipped, count: flipped.length }; }
594
+
595
+ export function getAutonomousAgentGovStatsV2() {
596
+ const agentsByStatus = {}; for (const s of Object.values(AUTOAGENT_MATURITY_V2)) agentsByStatus[s] = 0; for (const a of _aaAgents.values()) agentsByStatus[a.status]++;
597
+ const runsByStatus = {}; for (const s of Object.values(AUTOAGENT_RUN_LIFECYCLE_V2)) runsByStatus[s] = 0; for (const r of _aaRuns.values()) runsByStatus[r.status]++;
598
+ return { totalAutoAgentsV2: _aaAgents.size, totalAutoAgentRunsV2: _aaRuns.size, maxActiveAutoAgentsPerOwner: _aaMaxActivePerOwner, maxPendingAutoAgentRunsPerAgent: _aaMaxPendingRunsPerAgent, autoAgentIdleMs: _aaAgentIdleMs, autoAgentRunStuckMs: _aaRunStuckMs, agentsByStatus, runsByStatus };
599
+ }
@@ -635,3 +635,108 @@ export function _resetV2State() {
635
635
  _reportStatusV2.clear();
636
636
  _statusHistoryV2.clear();
637
637
  }
638
+
639
+
640
+ // ===== V2 Surface: BI Engine governance overlay (CLI v0.135.0) =====
641
+ export const BI_DATASET_MATURITY_V2 = Object.freeze({
642
+ PENDING: "pending", ACTIVE: "active", STALE: "stale", ARCHIVED: "archived",
643
+ });
644
+ export const BI_QUERY_LIFECYCLE_V2 = Object.freeze({
645
+ QUEUED: "queued", RUNNING: "running", COMPLETED: "completed", FAILED: "failed", CANCELLED: "cancelled",
646
+ });
647
+
648
+ const _biDsTrans = new Map([
649
+ [BI_DATASET_MATURITY_V2.PENDING, new Set([BI_DATASET_MATURITY_V2.ACTIVE, BI_DATASET_MATURITY_V2.ARCHIVED])],
650
+ [BI_DATASET_MATURITY_V2.ACTIVE, new Set([BI_DATASET_MATURITY_V2.STALE, BI_DATASET_MATURITY_V2.ARCHIVED])],
651
+ [BI_DATASET_MATURITY_V2.STALE, new Set([BI_DATASET_MATURITY_V2.ACTIVE, BI_DATASET_MATURITY_V2.ARCHIVED])],
652
+ [BI_DATASET_MATURITY_V2.ARCHIVED, new Set()],
653
+ ]);
654
+ const _biDsTerminal = new Set([BI_DATASET_MATURITY_V2.ARCHIVED]);
655
+ const _biQTrans = new Map([
656
+ [BI_QUERY_LIFECYCLE_V2.QUEUED, new Set([BI_QUERY_LIFECYCLE_V2.RUNNING, BI_QUERY_LIFECYCLE_V2.CANCELLED])],
657
+ [BI_QUERY_LIFECYCLE_V2.RUNNING, new Set([BI_QUERY_LIFECYCLE_V2.COMPLETED, BI_QUERY_LIFECYCLE_V2.FAILED, BI_QUERY_LIFECYCLE_V2.CANCELLED])],
658
+ [BI_QUERY_LIFECYCLE_V2.COMPLETED, new Set()],
659
+ [BI_QUERY_LIFECYCLE_V2.FAILED, new Set()],
660
+ [BI_QUERY_LIFECYCLE_V2.CANCELLED, new Set()],
661
+ ]);
662
+
663
+ const _biDatasets = new Map();
664
+ const _biQueries = new Map();
665
+ let _biMaxActivePerOwner = 8;
666
+ let _biMaxPendingPerDs = 10;
667
+ let _biDsIdleMs = 7 * 24 * 60 * 60 * 1000;
668
+ let _biQStuckMs = 5 * 60 * 1000;
669
+
670
+ function _biPos(n, lbl) { const v = Math.floor(Number(n)); if (!Number.isFinite(v) || v <= 0) throw new Error(`${lbl} must be positive integer`); return v; }
671
+
672
+ export function setMaxActiveBiDatasetsPerOwnerV2(n) { _biMaxActivePerOwner = _biPos(n, "maxActiveBiDatasetsPerOwner"); }
673
+ export function getMaxActiveBiDatasetsPerOwnerV2() { return _biMaxActivePerOwner; }
674
+ export function setMaxPendingBiQueriesPerDatasetV2(n) { _biMaxPendingPerDs = _biPos(n, "maxPendingBiQueriesPerDataset"); }
675
+ export function getMaxPendingBiQueriesPerDatasetV2() { return _biMaxPendingPerDs; }
676
+ export function setBiDatasetIdleMsV2(n) { _biDsIdleMs = _biPos(n, "biDatasetIdleMs"); }
677
+ export function getBiDatasetIdleMsV2() { return _biDsIdleMs; }
678
+ export function setBiQueryStuckMsV2(n) { _biQStuckMs = _biPos(n, "biQueryStuckMs"); }
679
+ export function getBiQueryStuckMsV2() { return _biQStuckMs; }
680
+
681
+ export function _resetStateBiEngineV2() {
682
+ _biDatasets.clear(); _biQueries.clear();
683
+ _biMaxActivePerOwner = 8; _biMaxPendingPerDs = 10;
684
+ _biDsIdleMs = 7 * 24 * 60 * 60 * 1000; _biQStuckMs = 5 * 60 * 1000;
685
+ }
686
+
687
+ export function registerBiDatasetV2({ id, owner, source, metadata } = {}) {
688
+ if (!id || typeof id !== "string") throw new Error("id is required");
689
+ if (!owner || typeof owner !== "string") throw new Error("owner is required");
690
+ if (_biDatasets.has(id)) throw new Error(`bi dataset ${id} already registered`);
691
+ const now = Date.now();
692
+ const d = { id, owner, source: source || "", status: BI_DATASET_MATURITY_V2.PENDING, createdAt: now, updatedAt: now, activatedAt: null, archivedAt: null, lastTouchedAt: now, metadata: { ...(metadata || {}) } };
693
+ _biDatasets.set(id, d);
694
+ return { ...d, metadata: { ...d.metadata } };
695
+ }
696
+ function _biCheckD(from, to) { const a = _biDsTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid bi dataset transition ${from} → ${to}`); }
697
+ function _biCountActive(owner) { let n = 0; for (const d of _biDatasets.values()) if (d.owner === owner && d.status === BI_DATASET_MATURITY_V2.ACTIVE) n++; return n; }
698
+
699
+ export function activateBiDatasetV2(id) {
700
+ const d = _biDatasets.get(id); if (!d) throw new Error(`bi dataset ${id} not found`);
701
+ _biCheckD(d.status, BI_DATASET_MATURITY_V2.ACTIVE);
702
+ const recovery = d.status === BI_DATASET_MATURITY_V2.STALE;
703
+ if (!recovery) { const a = _biCountActive(d.owner); if (a >= _biMaxActivePerOwner) throw new Error(`max active bi datasets per owner (${_biMaxActivePerOwner}) reached for ${d.owner}`); }
704
+ const now = Date.now(); d.status = BI_DATASET_MATURITY_V2.ACTIVE; d.updatedAt = now; d.lastTouchedAt = now; if (!d.activatedAt) d.activatedAt = now;
705
+ return { ...d, metadata: { ...d.metadata } };
706
+ }
707
+ export function staleBiDatasetV2(id) { const d = _biDatasets.get(id); if (!d) throw new Error(`bi dataset ${id} not found`); _biCheckD(d.status, BI_DATASET_MATURITY_V2.STALE); d.status = BI_DATASET_MATURITY_V2.STALE; d.updatedAt = Date.now(); return { ...d, metadata: { ...d.metadata } }; }
708
+ export function archiveBiDatasetV2(id) { const d = _biDatasets.get(id); if (!d) throw new Error(`bi dataset ${id} not found`); _biCheckD(d.status, BI_DATASET_MATURITY_V2.ARCHIVED); const now = Date.now(); d.status = BI_DATASET_MATURITY_V2.ARCHIVED; d.updatedAt = now; if (!d.archivedAt) d.archivedAt = now; return { ...d, metadata: { ...d.metadata } }; }
709
+ export function touchBiDatasetV2(id) { const d = _biDatasets.get(id); if (!d) throw new Error(`bi dataset ${id} not found`); if (_biDsTerminal.has(d.status)) throw new Error(`cannot touch terminal bi dataset ${id}`); const now = Date.now(); d.lastTouchedAt = now; d.updatedAt = now; return { ...d, metadata: { ...d.metadata } }; }
710
+ export function getBiDatasetV2(id) { const d = _biDatasets.get(id); if (!d) return null; return { ...d, metadata: { ...d.metadata } }; }
711
+ export function listBiDatasetsV2() { return [..._biDatasets.values()].map((d) => ({ ...d, metadata: { ...d.metadata } })); }
712
+
713
+ function _biCountPending(did) { let n = 0; for (const q of _biQueries.values()) if (q.datasetId === did && (q.status === BI_QUERY_LIFECYCLE_V2.QUEUED || q.status === BI_QUERY_LIFECYCLE_V2.RUNNING)) n++; return n; }
714
+
715
+ export function createBiQueryV2({ id, datasetId, sql, metadata } = {}) {
716
+ if (!id || typeof id !== "string") throw new Error("id is required");
717
+ if (!datasetId || typeof datasetId !== "string") throw new Error("datasetId is required");
718
+ if (_biQueries.has(id)) throw new Error(`bi query ${id} already exists`);
719
+ if (!_biDatasets.has(datasetId)) throw new Error(`bi dataset ${datasetId} not found`);
720
+ const pending = _biCountPending(datasetId);
721
+ if (pending >= _biMaxPendingPerDs) throw new Error(`max pending bi queries per dataset (${_biMaxPendingPerDs}) reached for ${datasetId}`);
722
+ const now = Date.now();
723
+ const q = { id, datasetId, sql: sql || "", status: BI_QUERY_LIFECYCLE_V2.QUEUED, createdAt: now, updatedAt: now, startedAt: null, settledAt: null, metadata: { ...(metadata || {}) } };
724
+ _biQueries.set(id, q);
725
+ return { ...q, metadata: { ...q.metadata } };
726
+ }
727
+ function _biCheckQ(from, to) { const a = _biQTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid bi query transition ${from} → ${to}`); }
728
+ export function startBiQueryV2(id) { const q = _biQueries.get(id); if (!q) throw new Error(`bi query ${id} not found`); _biCheckQ(q.status, BI_QUERY_LIFECYCLE_V2.RUNNING); const now = Date.now(); q.status = BI_QUERY_LIFECYCLE_V2.RUNNING; q.updatedAt = now; if (!q.startedAt) q.startedAt = now; return { ...q, metadata: { ...q.metadata } }; }
729
+ export function completeBiQueryV2(id) { const q = _biQueries.get(id); if (!q) throw new Error(`bi query ${id} not found`); _biCheckQ(q.status, BI_QUERY_LIFECYCLE_V2.COMPLETED); const now = Date.now(); q.status = BI_QUERY_LIFECYCLE_V2.COMPLETED; q.updatedAt = now; if (!q.settledAt) q.settledAt = now; return { ...q, metadata: { ...q.metadata } }; }
730
+ export function failBiQueryV2(id, reason) { const q = _biQueries.get(id); if (!q) throw new Error(`bi query ${id} not found`); _biCheckQ(q.status, BI_QUERY_LIFECYCLE_V2.FAILED); const now = Date.now(); q.status = BI_QUERY_LIFECYCLE_V2.FAILED; q.updatedAt = now; if (!q.settledAt) q.settledAt = now; if (reason) q.metadata.failReason = String(reason); return { ...q, metadata: { ...q.metadata } }; }
731
+ export function cancelBiQueryV2(id, reason) { const q = _biQueries.get(id); if (!q) throw new Error(`bi query ${id} not found`); _biCheckQ(q.status, BI_QUERY_LIFECYCLE_V2.CANCELLED); const now = Date.now(); q.status = BI_QUERY_LIFECYCLE_V2.CANCELLED; q.updatedAt = now; if (!q.settledAt) q.settledAt = now; if (reason) q.metadata.cancelReason = String(reason); return { ...q, metadata: { ...q.metadata } }; }
732
+ export function getBiQueryV2(id) { const q = _biQueries.get(id); if (!q) return null; return { ...q, metadata: { ...q.metadata } }; }
733
+ export function listBiQueriesV2() { return [..._biQueries.values()].map((q) => ({ ...q, metadata: { ...q.metadata } })); }
734
+
735
+ export function autoStaleIdleBiDatasetsV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const d of _biDatasets.values()) if (d.status === BI_DATASET_MATURITY_V2.ACTIVE && (t - d.lastTouchedAt) >= _biDsIdleMs) { d.status = BI_DATASET_MATURITY_V2.STALE; d.updatedAt = t; flipped.push(d.id); } return { flipped, count: flipped.length }; }
736
+ export function autoFailStuckBiQueriesV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const q of _biQueries.values()) if (q.status === BI_QUERY_LIFECYCLE_V2.RUNNING && q.startedAt != null && (t - q.startedAt) >= _biQStuckMs) { q.status = BI_QUERY_LIFECYCLE_V2.FAILED; q.updatedAt = t; if (!q.settledAt) q.settledAt = t; q.metadata.failReason = "auto-fail-stuck"; flipped.push(q.id); } return { flipped, count: flipped.length }; }
737
+
738
+ export function getBiEngineStatsV2() {
739
+ const datasetsByStatus = {}; for (const s of Object.values(BI_DATASET_MATURITY_V2)) datasetsByStatus[s] = 0; for (const d of _biDatasets.values()) datasetsByStatus[d.status]++;
740
+ const queriesByStatus = {}; for (const s of Object.values(BI_QUERY_LIFECYCLE_V2)) queriesByStatus[s] = 0; for (const q of _biQueries.values()) queriesByStatus[q.status]++;
741
+ return { totalDatasetsV2: _biDatasets.size, totalQueriesV2: _biQueries.size, maxActiveBiDatasetsPerOwner: _biMaxActivePerOwner, maxPendingBiQueriesPerDataset: _biMaxPendingPerDs, biDatasetIdleMs: _biDsIdleMs, biQueryStuckMs: _biQStuckMs, datasetsByStatus, queriesByStatus };
742
+ }
@@ -320,3 +320,84 @@ export class BM25Search {
320
320
  };
321
321
  }
322
322
  }
323
+
324
+
325
+ // =====================================================================
326
+ // BM25 Search V2 governance overlay
327
+ // =====================================================================
328
+ export const BM25_PROFILE_MATURITY_V2 = Object.freeze({ PENDING: "pending", ACTIVE: "active", STALE: "stale", ARCHIVED: "archived" });
329
+ export const BM25_QUERY_LIFECYCLE_V2 = Object.freeze({ QUEUED: "queued", SEARCHING: "searching", COMPLETED: "completed", FAILED: "failed", CANCELLED: "cancelled" });
330
+ const _bm25PTrans = new Map([
331
+ [BM25_PROFILE_MATURITY_V2.PENDING, new Set([BM25_PROFILE_MATURITY_V2.ACTIVE, BM25_PROFILE_MATURITY_V2.ARCHIVED])],
332
+ [BM25_PROFILE_MATURITY_V2.ACTIVE, new Set([BM25_PROFILE_MATURITY_V2.STALE, BM25_PROFILE_MATURITY_V2.ARCHIVED])],
333
+ [BM25_PROFILE_MATURITY_V2.STALE, new Set([BM25_PROFILE_MATURITY_V2.ACTIVE, BM25_PROFILE_MATURITY_V2.ARCHIVED])],
334
+ [BM25_PROFILE_MATURITY_V2.ARCHIVED, new Set()],
335
+ ]);
336
+ const _bm25PTerminal = new Set([BM25_PROFILE_MATURITY_V2.ARCHIVED]);
337
+ const _bm25JTrans = new Map([
338
+ [BM25_QUERY_LIFECYCLE_V2.QUEUED, new Set([BM25_QUERY_LIFECYCLE_V2.SEARCHING, BM25_QUERY_LIFECYCLE_V2.CANCELLED])],
339
+ [BM25_QUERY_LIFECYCLE_V2.SEARCHING, new Set([BM25_QUERY_LIFECYCLE_V2.COMPLETED, BM25_QUERY_LIFECYCLE_V2.FAILED, BM25_QUERY_LIFECYCLE_V2.CANCELLED])],
340
+ [BM25_QUERY_LIFECYCLE_V2.COMPLETED, new Set()],
341
+ [BM25_QUERY_LIFECYCLE_V2.FAILED, new Set()],
342
+ [BM25_QUERY_LIFECYCLE_V2.CANCELLED, new Set()],
343
+ ]);
344
+ const _bm25PsV2 = new Map();
345
+ const _bm25JsV2 = new Map();
346
+ let _bm25MaxActive = 8, _bm25MaxPending = 20, _bm25IdleMs = 30 * 24 * 60 * 60 * 1000, _bm25StuckMs = 30 * 1000;
347
+ function _bm25Pos(n, label) { const v = Math.floor(Number(n)); if (!Number.isFinite(v) || v <= 0) throw new Error(`${label} must be positive integer`); return v; }
348
+ function _bm25CheckP(from, to) { const a = _bm25PTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid bm25 profile transition ${from} → ${to}`); }
349
+ function _bm25CheckJ(from, to) { const a = _bm25JTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid bm25 query transition ${from} → ${to}`); }
350
+ function _bm25CountActive(owner) { let c = 0; for (const p of _bm25PsV2.values()) if (p.owner === owner && p.status === BM25_PROFILE_MATURITY_V2.ACTIVE) c++; return c; }
351
+ function _bm25CountPending(profileId) { let c = 0; for (const j of _bm25JsV2.values()) if (j.profileId === profileId && (j.status === BM25_QUERY_LIFECYCLE_V2.QUEUED || j.status === BM25_QUERY_LIFECYCLE_V2.SEARCHING)) c++; return c; }
352
+ export function setMaxActiveBm25ProfilesPerOwnerV2(n) { _bm25MaxActive = _bm25Pos(n, "maxActiveBm25ProfilesPerOwner"); }
353
+ export function getMaxActiveBm25ProfilesPerOwnerV2() { return _bm25MaxActive; }
354
+ export function setMaxPendingBm25QueriesPerProfileV2(n) { _bm25MaxPending = _bm25Pos(n, "maxPendingBm25QueriesPerProfile"); }
355
+ export function getMaxPendingBm25QueriesPerProfileV2() { return _bm25MaxPending; }
356
+ export function setBm25ProfileIdleMsV2(n) { _bm25IdleMs = _bm25Pos(n, "bm25ProfileIdleMs"); }
357
+ export function getBm25ProfileIdleMsV2() { return _bm25IdleMs; }
358
+ export function setBm25QueryStuckMsV2(n) { _bm25StuckMs = _bm25Pos(n, "bm25QueryStuckMs"); }
359
+ export function getBm25QueryStuckMsV2() { return _bm25StuckMs; }
360
+ export function _resetStateBm25SearchV2() { _bm25PsV2.clear(); _bm25JsV2.clear(); _bm25MaxActive = 8; _bm25MaxPending = 20; _bm25IdleMs = 30 * 24 * 60 * 60 * 1000; _bm25StuckMs = 30 * 1000; }
361
+ export function registerBm25ProfileV2({ id, owner, field, metadata } = {}) {
362
+ if (!id || !owner) throw new Error("id and owner required");
363
+ if (_bm25PsV2.has(id)) throw new Error(`bm25 profile ${id} already exists`);
364
+ const now = Date.now();
365
+ const p = { id, owner, field: field || "content", status: BM25_PROFILE_MATURITY_V2.PENDING, createdAt: now, updatedAt: now, lastTouchedAt: now, activatedAt: null, archivedAt: null, metadata: { ...(metadata || {}) } };
366
+ _bm25PsV2.set(id, p); return { ...p, metadata: { ...p.metadata } };
367
+ }
368
+ export function activateBm25ProfileV2(id) {
369
+ const p = _bm25PsV2.get(id); if (!p) throw new Error(`bm25 profile ${id} not found`);
370
+ const isInitial = p.status === BM25_PROFILE_MATURITY_V2.PENDING;
371
+ _bm25CheckP(p.status, BM25_PROFILE_MATURITY_V2.ACTIVE);
372
+ if (isInitial && _bm25CountActive(p.owner) >= _bm25MaxActive) throw new Error(`max active bm25 profiles for owner ${p.owner} reached`);
373
+ const now = Date.now(); p.status = BM25_PROFILE_MATURITY_V2.ACTIVE; p.updatedAt = now; p.lastTouchedAt = now;
374
+ if (!p.activatedAt) p.activatedAt = now;
375
+ return { ...p, metadata: { ...p.metadata } };
376
+ }
377
+ export function staleBm25ProfileV2(id) { const p = _bm25PsV2.get(id); if (!p) throw new Error(`bm25 profile ${id} not found`); _bm25CheckP(p.status, BM25_PROFILE_MATURITY_V2.STALE); p.status = BM25_PROFILE_MATURITY_V2.STALE; p.updatedAt = Date.now(); return { ...p, metadata: { ...p.metadata } }; }
378
+ export function archiveBm25ProfileV2(id) { const p = _bm25PsV2.get(id); if (!p) throw new Error(`bm25 profile ${id} not found`); _bm25CheckP(p.status, BM25_PROFILE_MATURITY_V2.ARCHIVED); const now = Date.now(); p.status = BM25_PROFILE_MATURITY_V2.ARCHIVED; p.updatedAt = now; if (!p.archivedAt) p.archivedAt = now; return { ...p, metadata: { ...p.metadata } }; }
379
+ export function touchBm25ProfileV2(id) { const p = _bm25PsV2.get(id); if (!p) throw new Error(`bm25 profile ${id} not found`); if (_bm25PTerminal.has(p.status)) throw new Error(`cannot touch terminal bm25 profile ${id}`); const now = Date.now(); p.lastTouchedAt = now; p.updatedAt = now; return { ...p, metadata: { ...p.metadata } }; }
380
+ export function getBm25ProfileV2(id) { const p = _bm25PsV2.get(id); if (!p) return null; return { ...p, metadata: { ...p.metadata } }; }
381
+ export function listBm25ProfilesV2() { return [..._bm25PsV2.values()].map((p) => ({ ...p, metadata: { ...p.metadata } })); }
382
+ export function createBm25QueryV2({ id, profileId, q, metadata } = {}) {
383
+ if (!id || !profileId) throw new Error("id and profileId required");
384
+ if (_bm25JsV2.has(id)) throw new Error(`bm25 query ${id} already exists`);
385
+ if (!_bm25PsV2.has(profileId)) throw new Error(`bm25 profile ${profileId} not found`);
386
+ if (_bm25CountPending(profileId) >= _bm25MaxPending) throw new Error(`max pending bm25 queries for profile ${profileId} reached`);
387
+ const now = Date.now();
388
+ const j = { id, profileId, q: q || "", status: BM25_QUERY_LIFECYCLE_V2.QUEUED, createdAt: now, updatedAt: now, startedAt: null, settledAt: null, metadata: { ...(metadata || {}) } };
389
+ _bm25JsV2.set(id, j); return { ...j, metadata: { ...j.metadata } };
390
+ }
391
+ export function searchingBm25QueryV2(id) { const j = _bm25JsV2.get(id); if (!j) throw new Error(`bm25 query ${id} not found`); _bm25CheckJ(j.status, BM25_QUERY_LIFECYCLE_V2.SEARCHING); const now = Date.now(); j.status = BM25_QUERY_LIFECYCLE_V2.SEARCHING; j.updatedAt = now; if (!j.startedAt) j.startedAt = now; return { ...j, metadata: { ...j.metadata } }; }
392
+ export function completeBm25QueryV2(id) { const j = _bm25JsV2.get(id); if (!j) throw new Error(`bm25 query ${id} not found`); _bm25CheckJ(j.status, BM25_QUERY_LIFECYCLE_V2.COMPLETED); const now = Date.now(); j.status = BM25_QUERY_LIFECYCLE_V2.COMPLETED; j.updatedAt = now; if (!j.settledAt) j.settledAt = now; return { ...j, metadata: { ...j.metadata } }; }
393
+ export function failBm25QueryV2(id, reason) { const j = _bm25JsV2.get(id); if (!j) throw new Error(`bm25 query ${id} not found`); _bm25CheckJ(j.status, BM25_QUERY_LIFECYCLE_V2.FAILED); const now = Date.now(); j.status = BM25_QUERY_LIFECYCLE_V2.FAILED; j.updatedAt = now; if (!j.settledAt) j.settledAt = now; if (reason) j.metadata.failReason = String(reason); return { ...j, metadata: { ...j.metadata } }; }
394
+ export function cancelBm25QueryV2(id, reason) { const j = _bm25JsV2.get(id); if (!j) throw new Error(`bm25 query ${id} not found`); _bm25CheckJ(j.status, BM25_QUERY_LIFECYCLE_V2.CANCELLED); const now = Date.now(); j.status = BM25_QUERY_LIFECYCLE_V2.CANCELLED; j.updatedAt = now; if (!j.settledAt) j.settledAt = now; if (reason) j.metadata.cancelReason = String(reason); return { ...j, metadata: { ...j.metadata } }; }
395
+ export function getBm25QueryV2(id) { const j = _bm25JsV2.get(id); if (!j) return null; return { ...j, metadata: { ...j.metadata } }; }
396
+ export function listBm25QueriesV2() { return [..._bm25JsV2.values()].map((j) => ({ ...j, metadata: { ...j.metadata } })); }
397
+ export function autoStaleIdleBm25ProfilesV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const p of _bm25PsV2.values()) if (p.status === BM25_PROFILE_MATURITY_V2.ACTIVE && (t - p.lastTouchedAt) >= _bm25IdleMs) { p.status = BM25_PROFILE_MATURITY_V2.STALE; p.updatedAt = t; flipped.push(p.id); } return { flipped, count: flipped.length }; }
398
+ export function autoFailStuckBm25QueriesV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const j of _bm25JsV2.values()) if (j.status === BM25_QUERY_LIFECYCLE_V2.SEARCHING && j.startedAt != null && (t - j.startedAt) >= _bm25StuckMs) { j.status = BM25_QUERY_LIFECYCLE_V2.FAILED; j.updatedAt = t; if (!j.settledAt) j.settledAt = t; j.metadata.failReason = "auto-fail-stuck"; flipped.push(j.id); } return { flipped, count: flipped.length }; }
399
+ export function getBm25SearchGovStatsV2() {
400
+ const profilesByStatus = {}; for (const v of Object.values(BM25_PROFILE_MATURITY_V2)) profilesByStatus[v] = 0; for (const p of _bm25PsV2.values()) profilesByStatus[p.status]++;
401
+ const queriesByStatus = {}; for (const v of Object.values(BM25_QUERY_LIFECYCLE_V2)) queriesByStatus[v] = 0; for (const j of _bm25JsV2.values()) queriesByStatus[j.status]++;
402
+ return { totalBm25ProfilesV2: _bm25PsV2.size, totalBm25QueriesV2: _bm25JsV2.size, maxActiveBm25ProfilesPerOwner: _bm25MaxActive, maxPendingBm25QueriesPerProfile: _bm25MaxPending, bm25ProfileIdleMs: _bm25IdleMs, bm25QueryStuckMs: _bm25StuckMs, profilesByStatus, queriesByStatus };
403
+ }