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
@@ -209,3 +209,333 @@ export function updateMemoryFile(memoryDir, content) {
209
209
  fs.writeFileSync(filePath, content, "utf8");
210
210
  return { path: filePath };
211
211
  }
212
+
213
+ /* ═══════════════════════════════════════════════════════════════
214
+ * V2 Surface — Memory governance layer.
215
+ * Tracks per-category entry maturity + consolidation job lifecycle
216
+ * independent of legacy SQLite memory_entries table.
217
+ * ═══════════════════════════════════════════════════════════════ */
218
+
219
+ export const ENTRY_MATURITY_V2 = Object.freeze({
220
+ PENDING: "pending",
221
+ ACTIVE: "active",
222
+ PARKED: "parked",
223
+ ARCHIVED: "archived",
224
+ });
225
+
226
+ export const CONSOLIDATION_LIFECYCLE_V2 = Object.freeze({
227
+ QUEUED: "queued",
228
+ RUNNING: "running",
229
+ SUCCEEDED: "succeeded",
230
+ FAILED: "failed",
231
+ CANCELLED: "cancelled",
232
+ });
233
+
234
+ const ENTRY_TRANSITIONS_V2 = new Map([
235
+ ["pending", new Set(["active", "archived"])],
236
+ ["active", new Set(["parked", "archived"])],
237
+ ["parked", new Set(["active", "archived"])],
238
+ ["archived", new Set()],
239
+ ]);
240
+ const ENTRY_TERMINALS_V2 = new Set(["archived"]);
241
+
242
+ const JOB_TRANSITIONS_V2 = new Map([
243
+ ["queued", new Set(["running", "cancelled"])],
244
+ ["running", new Set(["succeeded", "failed", "cancelled"])],
245
+ ["succeeded", new Set()],
246
+ ["failed", new Set()],
247
+ ["cancelled", new Set()],
248
+ ]);
249
+ const JOB_TERMINALS_V2 = new Set(["succeeded", "failed", "cancelled"]);
250
+
251
+ export const MEMORY_DEFAULT_MAX_ACTIVE_ENTRIES_PER_CATEGORY = 200;
252
+ export const MEMORY_DEFAULT_MAX_RUNNING_JOBS_PER_SOURCE = 2;
253
+ export const MEMORY_DEFAULT_ENTRY_IDLE_MS = 1000 * 60 * 60 * 24 * 90; // 90 days
254
+ export const MEMORY_DEFAULT_JOB_STUCK_MS = 1000 * 60 * 10; // 10 minutes
255
+
256
+ const _entriesV2 = new Map();
257
+ const _jobsV2 = new Map();
258
+ let _maxActiveEntriesPerCategoryV2 =
259
+ MEMORY_DEFAULT_MAX_ACTIVE_ENTRIES_PER_CATEGORY;
260
+ let _maxRunningJobsPerSourceV2 = MEMORY_DEFAULT_MAX_RUNNING_JOBS_PER_SOURCE;
261
+ let _entryIdleMsV2 = MEMORY_DEFAULT_ENTRY_IDLE_MS;
262
+ let _jobStuckMsV2 = MEMORY_DEFAULT_JOB_STUCK_MS;
263
+
264
+ function _posIntMemoryV2(n, label) {
265
+ const v = Math.floor(Number(n));
266
+ if (!Number.isFinite(v) || v <= 0)
267
+ throw new Error(`${label} must be a positive integer`);
268
+ return v;
269
+ }
270
+
271
+ export function getMaxActiveEntriesPerCategoryV2() {
272
+ return _maxActiveEntriesPerCategoryV2;
273
+ }
274
+ export function setMaxActiveEntriesPerCategoryV2(n) {
275
+ _maxActiveEntriesPerCategoryV2 = _posIntMemoryV2(
276
+ n,
277
+ "maxActiveEntriesPerCategory",
278
+ );
279
+ }
280
+ export function getMaxRunningJobsPerSourceV2() {
281
+ return _maxRunningJobsPerSourceV2;
282
+ }
283
+ export function setMaxRunningJobsPerSourceV2(n) {
284
+ _maxRunningJobsPerSourceV2 = _posIntMemoryV2(n, "maxRunningJobsPerSource");
285
+ }
286
+ export function getEntryIdleMsV2() {
287
+ return _entryIdleMsV2;
288
+ }
289
+ export function setEntryIdleMsV2(n) {
290
+ _entryIdleMsV2 = _posIntMemoryV2(n, "entryIdleMs");
291
+ }
292
+ export function getJobStuckMsV2() {
293
+ return _jobStuckMsV2;
294
+ }
295
+ export function setJobStuckMsV2(n) {
296
+ _jobStuckMsV2 = _posIntMemoryV2(n, "jobStuckMs");
297
+ }
298
+
299
+ export function getActiveEntryCountV2(category) {
300
+ let n = 0;
301
+ for (const e of _entriesV2.values()) {
302
+ if (e.category === category && e.status === "active") n += 1;
303
+ }
304
+ return n;
305
+ }
306
+
307
+ export function getRunningJobCountV2(source) {
308
+ let n = 0;
309
+ for (const j of _jobsV2.values()) {
310
+ if (j.source === source && j.status === "running") n += 1;
311
+ }
312
+ return n;
313
+ }
314
+
315
+ function _copyEntryV2(e) {
316
+ return { ...e, metadata: { ...e.metadata } };
317
+ }
318
+ function _copyJobV2(j) {
319
+ return { ...j, metadata: { ...j.metadata } };
320
+ }
321
+
322
+ export function registerEntryV2(
323
+ id,
324
+ { category, summary, metadata = {}, now = Date.now() } = {},
325
+ ) {
326
+ if (!id || typeof id !== "string") throw new Error("id must be a string");
327
+ if (!category || typeof category !== "string")
328
+ throw new Error("category must be a string");
329
+ if (!summary || typeof summary !== "string")
330
+ throw new Error("summary must be a string");
331
+ if (_entriesV2.has(id)) throw new Error(`entry ${id} already exists`);
332
+ const e = {
333
+ id,
334
+ category,
335
+ summary,
336
+ status: "pending",
337
+ createdAt: now,
338
+ lastSeenAt: now,
339
+ activatedAt: null,
340
+ archivedAt: null,
341
+ metadata: { ...metadata },
342
+ };
343
+ _entriesV2.set(id, e);
344
+ return _copyEntryV2(e);
345
+ }
346
+
347
+ export function getEntryV2(id) {
348
+ const e = _entriesV2.get(id);
349
+ return e ? _copyEntryV2(e) : null;
350
+ }
351
+
352
+ export function listEntriesV2({ category, status } = {}) {
353
+ const out = [];
354
+ for (const e of _entriesV2.values()) {
355
+ if (category && e.category !== category) continue;
356
+ if (status && e.status !== status) continue;
357
+ out.push(_copyEntryV2(e));
358
+ }
359
+ return out;
360
+ }
361
+
362
+ export function setEntryStatusV2(id, next, { now = Date.now() } = {}) {
363
+ const e = _entriesV2.get(id);
364
+ if (!e) throw new Error(`entry ${id} not found`);
365
+ if (!ENTRY_TRANSITIONS_V2.has(next))
366
+ throw new Error(`unknown entry status: ${next}`);
367
+ if (ENTRY_TERMINALS_V2.has(e.status))
368
+ throw new Error(`entry ${id} is in terminal state ${e.status}`);
369
+ const allowed = ENTRY_TRANSITIONS_V2.get(e.status);
370
+ if (!allowed.has(next))
371
+ throw new Error(`cannot transition entry from ${e.status} to ${next}`);
372
+ if (next === "active") {
373
+ if (e.status === "pending") {
374
+ const count = getActiveEntryCountV2(e.category);
375
+ if (count >= _maxActiveEntriesPerCategoryV2)
376
+ throw new Error(
377
+ `category ${e.category} already at active-entry cap (${_maxActiveEntriesPerCategoryV2})`,
378
+ );
379
+ }
380
+ if (!e.activatedAt) e.activatedAt = now;
381
+ }
382
+ if (next === "archived" && !e.archivedAt) e.archivedAt = now;
383
+ e.status = next;
384
+ e.lastSeenAt = now;
385
+ return _copyEntryV2(e);
386
+ }
387
+
388
+ export function activateEntryV2(id, opts) {
389
+ return setEntryStatusV2(id, "active", opts);
390
+ }
391
+ export function parkEntryV2(id, opts) {
392
+ return setEntryStatusV2(id, "parked", opts);
393
+ }
394
+ export function archiveEntryV2(id, opts) {
395
+ return setEntryStatusV2(id, "archived", opts);
396
+ }
397
+
398
+ export function touchEntryV2(id, { now = Date.now() } = {}) {
399
+ const e = _entriesV2.get(id);
400
+ if (!e) throw new Error(`entry ${id} not found`);
401
+ e.lastSeenAt = now;
402
+ return _copyEntryV2(e);
403
+ }
404
+
405
+ export function createConsolidationJobV2(
406
+ id,
407
+ { source, scope, metadata = {}, now = Date.now() } = {},
408
+ ) {
409
+ if (!id || typeof id !== "string") throw new Error("id must be a string");
410
+ if (!source || typeof source !== "string")
411
+ throw new Error("source must be a string");
412
+ if (!scope || typeof scope !== "string")
413
+ throw new Error("scope must be a string");
414
+ if (_jobsV2.has(id)) throw new Error(`job ${id} already exists`);
415
+ const j = {
416
+ id,
417
+ source,
418
+ scope,
419
+ status: "queued",
420
+ createdAt: now,
421
+ lastSeenAt: now,
422
+ startedAt: null,
423
+ finishedAt: null,
424
+ metadata: { ...metadata },
425
+ };
426
+ _jobsV2.set(id, j);
427
+ return _copyJobV2(j);
428
+ }
429
+
430
+ export function getConsolidationJobV2(id) {
431
+ const j = _jobsV2.get(id);
432
+ return j ? _copyJobV2(j) : null;
433
+ }
434
+
435
+ export function listConsolidationJobsV2({ source, status } = {}) {
436
+ const out = [];
437
+ for (const j of _jobsV2.values()) {
438
+ if (source && j.source !== source) continue;
439
+ if (status && j.status !== status) continue;
440
+ out.push(_copyJobV2(j));
441
+ }
442
+ return out;
443
+ }
444
+
445
+ export function setJobStatusV2(id, next, { now = Date.now() } = {}) {
446
+ const j = _jobsV2.get(id);
447
+ if (!j) throw new Error(`job ${id} not found`);
448
+ if (!JOB_TRANSITIONS_V2.has(next))
449
+ throw new Error(`unknown job status: ${next}`);
450
+ if (JOB_TERMINALS_V2.has(j.status))
451
+ throw new Error(`job ${id} is in terminal state ${j.status}`);
452
+ const allowed = JOB_TRANSITIONS_V2.get(j.status);
453
+ if (!allowed.has(next))
454
+ throw new Error(`cannot transition job from ${j.status} to ${next}`);
455
+ if (next === "running") {
456
+ if (j.status === "queued") {
457
+ const count = getRunningJobCountV2(j.source);
458
+ if (count >= _maxRunningJobsPerSourceV2)
459
+ throw new Error(
460
+ `source ${j.source} already at running-job cap (${_maxRunningJobsPerSourceV2})`,
461
+ );
462
+ }
463
+ if (!j.startedAt) j.startedAt = now;
464
+ }
465
+ if (JOB_TERMINALS_V2.has(next) && !j.finishedAt) j.finishedAt = now;
466
+ j.status = next;
467
+ j.lastSeenAt = now;
468
+ return _copyJobV2(j);
469
+ }
470
+
471
+ export function startConsolidationJobV2(id, opts) {
472
+ return setJobStatusV2(id, "running", opts);
473
+ }
474
+ export function succeedConsolidationJobV2(id, opts) {
475
+ return setJobStatusV2(id, "succeeded", opts);
476
+ }
477
+ export function failConsolidationJobV2(id, opts) {
478
+ return setJobStatusV2(id, "failed", opts);
479
+ }
480
+ export function cancelConsolidationJobV2(id, opts) {
481
+ return setJobStatusV2(id, "cancelled", opts);
482
+ }
483
+
484
+ export function autoParkIdleEntriesV2({ now = Date.now() } = {}) {
485
+ const flipped = [];
486
+ for (const e of _entriesV2.values()) {
487
+ if (e.status !== "active") continue;
488
+ if (now - e.lastSeenAt > _entryIdleMsV2) {
489
+ e.status = "parked";
490
+ e.lastSeenAt = now;
491
+ flipped.push(_copyEntryV2(e));
492
+ }
493
+ }
494
+ return flipped;
495
+ }
496
+
497
+ export function autoFailStuckJobsV2({ now = Date.now() } = {}) {
498
+ const flipped = [];
499
+ for (const j of _jobsV2.values()) {
500
+ if (j.status !== "running") continue;
501
+ if (now - j.lastSeenAt > _jobStuckMsV2) {
502
+ j.status = "failed";
503
+ j.lastSeenAt = now;
504
+ if (!j.finishedAt) j.finishedAt = now;
505
+ flipped.push(_copyJobV2(j));
506
+ }
507
+ }
508
+ return flipped;
509
+ }
510
+
511
+ export function getMemoryManagerStatsV2() {
512
+ const entriesByStatus = {};
513
+ for (const v of Object.values(ENTRY_MATURITY_V2)) entriesByStatus[v] = 0;
514
+ for (const e of _entriesV2.values()) entriesByStatus[e.status] += 1;
515
+
516
+ const jobsByStatus = {};
517
+ for (const v of Object.values(CONSOLIDATION_LIFECYCLE_V2))
518
+ jobsByStatus[v] = 0;
519
+ for (const j of _jobsV2.values()) jobsByStatus[j.status] += 1;
520
+
521
+ return {
522
+ totalEntriesV2: _entriesV2.size,
523
+ totalJobsV2: _jobsV2.size,
524
+ maxActiveEntriesPerCategory: _maxActiveEntriesPerCategoryV2,
525
+ maxRunningJobsPerSource: _maxRunningJobsPerSourceV2,
526
+ entryIdleMs: _entryIdleMsV2,
527
+ jobStuckMs: _jobStuckMsV2,
528
+ entriesByStatus,
529
+ jobsByStatus,
530
+ };
531
+ }
532
+
533
+ export function _resetStateMemoryManagerV2() {
534
+ _entriesV2.clear();
535
+ _jobsV2.clear();
536
+ _maxActiveEntriesPerCategoryV2 =
537
+ MEMORY_DEFAULT_MAX_ACTIVE_ENTRIES_PER_CATEGORY;
538
+ _maxRunningJobsPerSourceV2 = MEMORY_DEFAULT_MAX_RUNNING_JOBS_PER_SOURCE;
539
+ _entryIdleMsV2 = MEMORY_DEFAULT_ENTRY_IDLE_MS;
540
+ _jobStuckMsV2 = MEMORY_DEFAULT_JOB_STUCK_MS;
541
+ }
@@ -723,3 +723,349 @@ export function getMultimodalStats(db) {
723
723
  export function _resetState() {
724
724
  _contextCache.clear();
725
725
  }
726
+
727
+ /* ═════════════════════════════════════════════════════════ *
728
+ * Phase 27 V2 — Session Maturity + Artifact Lifecycle
729
+ * ═════════════════════════════════════════════════════════ */
730
+
731
+ export const SESSION_MATURITY_V2 = Object.freeze({
732
+ ONBOARDING: "onboarding",
733
+ ACTIVE: "active",
734
+ PAUSED: "paused",
735
+ COMPLETED: "completed",
736
+ ARCHIVED: "archived",
737
+ });
738
+
739
+ export const ARTIFACT_LIFECYCLE_V2 = Object.freeze({
740
+ PENDING: "pending",
741
+ READY: "ready",
742
+ PURGED: "purged",
743
+ });
744
+
745
+ const SESSION_TRANSITIONS_V2 = new Map([
746
+ ["onboarding", new Set(["active", "archived"])],
747
+ ["active", new Set(["paused", "completed", "archived"])],
748
+ ["paused", new Set(["active", "completed", "archived"])],
749
+ ["completed", new Set(["archived"])],
750
+ ]);
751
+ const SESSION_TERMINALS_V2 = new Set(["archived"]);
752
+
753
+ const ARTIFACT_TRANSITIONS_V2 = new Map([
754
+ ["pending", new Set(["ready", "purged"])],
755
+ ["ready", new Set(["purged"])],
756
+ ]);
757
+ const ARTIFACT_TERMINALS_V2 = new Set(["purged"]);
758
+
759
+ export const MM_DEFAULT_MAX_ACTIVE_SESSIONS_PER_OWNER = 50;
760
+ export const MM_DEFAULT_MAX_ARTIFACTS_PER_SESSION = 200;
761
+ export const MM_DEFAULT_SESSION_IDLE_MS = 30 * 86400000;
762
+ export const MM_DEFAULT_ARTIFACT_STALE_MS = 14 * 86400000;
763
+
764
+ let _maxActiveSessionsPerOwnerV2 = MM_DEFAULT_MAX_ACTIVE_SESSIONS_PER_OWNER;
765
+ let _maxArtifactsPerSessionV2 = MM_DEFAULT_MAX_ARTIFACTS_PER_SESSION;
766
+ let _sessionIdleMsV2 = MM_DEFAULT_SESSION_IDLE_MS;
767
+ let _artifactStaleMsV2 = MM_DEFAULT_ARTIFACT_STALE_MS;
768
+
769
+ function _positiveIntV2(n, label) {
770
+ const v = Math.floor(Number(n));
771
+ if (!Number.isFinite(v) || v <= 0)
772
+ throw new Error(`${label} must be a positive integer`);
773
+ return v;
774
+ }
775
+
776
+ export function getDefaultMaxActiveSessionsPerOwnerV2() {
777
+ return MM_DEFAULT_MAX_ACTIVE_SESSIONS_PER_OWNER;
778
+ }
779
+ export function getMaxActiveSessionsPerOwnerV2() {
780
+ return _maxActiveSessionsPerOwnerV2;
781
+ }
782
+ export function setMaxActiveSessionsPerOwnerV2(n) {
783
+ return (_maxActiveSessionsPerOwnerV2 = _positiveIntV2(
784
+ n,
785
+ "maxActiveSessionsPerOwner",
786
+ ));
787
+ }
788
+ export function getDefaultMaxArtifactsPerSessionV2() {
789
+ return MM_DEFAULT_MAX_ARTIFACTS_PER_SESSION;
790
+ }
791
+ export function getMaxArtifactsPerSessionV2() {
792
+ return _maxArtifactsPerSessionV2;
793
+ }
794
+ export function setMaxArtifactsPerSessionV2(n) {
795
+ return (_maxArtifactsPerSessionV2 = _positiveIntV2(
796
+ n,
797
+ "maxArtifactsPerSession",
798
+ ));
799
+ }
800
+ export function getDefaultSessionIdleMsV2() {
801
+ return MM_DEFAULT_SESSION_IDLE_MS;
802
+ }
803
+ export function getSessionIdleMsV2() {
804
+ return _sessionIdleMsV2;
805
+ }
806
+ export function setSessionIdleMsV2(ms) {
807
+ return (_sessionIdleMsV2 = _positiveIntV2(ms, "sessionIdleMs"));
808
+ }
809
+ export function getDefaultArtifactStaleMsV2() {
810
+ return MM_DEFAULT_ARTIFACT_STALE_MS;
811
+ }
812
+ export function getArtifactStaleMsV2() {
813
+ return _artifactStaleMsV2;
814
+ }
815
+ export function setArtifactStaleMsV2(ms) {
816
+ return (_artifactStaleMsV2 = _positiveIntV2(ms, "artifactStaleMs"));
817
+ }
818
+
819
+ const _sessionsV2 = new Map();
820
+ const _artifactsV2 = new Map();
821
+
822
+ export function registerSessionV2(
823
+ _db,
824
+ { sessionId, ownerId, title, initialStatus, metadata } = {},
825
+ ) {
826
+ if (!sessionId) throw new Error("sessionId is required");
827
+ if (!ownerId) throw new Error("ownerId is required");
828
+ if (_sessionsV2.has(sessionId))
829
+ throw new Error(`Session ${sessionId} already exists`);
830
+ const status = initialStatus || SESSION_MATURITY_V2.ONBOARDING;
831
+ if (!Object.values(SESSION_MATURITY_V2).includes(status))
832
+ throw new Error(`Invalid initial status: ${status}`);
833
+ if (SESSION_TERMINALS_V2.has(status))
834
+ throw new Error(`Cannot register in terminal status: ${status}`);
835
+ if (status === SESSION_MATURITY_V2.ACTIVE) {
836
+ if (getActiveSessionCount(ownerId) >= _maxActiveSessionsPerOwnerV2)
837
+ throw new Error(
838
+ `Owner ${ownerId} reached active-session cap (${_maxActiveSessionsPerOwnerV2})`,
839
+ );
840
+ }
841
+ const now = Date.now();
842
+ const record = {
843
+ sessionId,
844
+ ownerId,
845
+ title: title || "",
846
+ status,
847
+ metadata: metadata || {},
848
+ createdAt: now,
849
+ updatedAt: now,
850
+ lastActivityAt: now,
851
+ };
852
+ _sessionsV2.set(sessionId, record);
853
+ return { ...record, metadata: { ...record.metadata } };
854
+ }
855
+
856
+ export function getSessionV2(sessionId) {
857
+ const r = _sessionsV2.get(sessionId);
858
+ return r ? { ...r, metadata: { ...r.metadata } } : null;
859
+ }
860
+
861
+ export function setSessionMaturityV2(_db, sessionId, newStatus, patch = {}) {
862
+ const record = _sessionsV2.get(sessionId);
863
+ if (!record) throw new Error(`Unknown session: ${sessionId}`);
864
+ if (!Object.values(SESSION_MATURITY_V2).includes(newStatus))
865
+ throw new Error(`Invalid status: ${newStatus}`);
866
+ const allowed = SESSION_TRANSITIONS_V2.get(record.status) || new Set();
867
+ if (!allowed.has(newStatus))
868
+ throw new Error(`Invalid transition: ${record.status} -> ${newStatus}`);
869
+ if (newStatus === SESSION_MATURITY_V2.ACTIVE) {
870
+ if (getActiveSessionCount(record.ownerId) >= _maxActiveSessionsPerOwnerV2)
871
+ throw new Error(
872
+ `Owner ${record.ownerId} reached active-session cap (${_maxActiveSessionsPerOwnerV2})`,
873
+ );
874
+ }
875
+ record.status = newStatus;
876
+ record.updatedAt = Date.now();
877
+ if (patch.reason !== undefined) record.lastReason = patch.reason;
878
+ if (patch.metadata)
879
+ record.metadata = { ...record.metadata, ...patch.metadata };
880
+ return { ...record, metadata: { ...record.metadata } };
881
+ }
882
+
883
+ export function activateSession(db, sessionId, reason) {
884
+ return setSessionMaturityV2(db, sessionId, SESSION_MATURITY_V2.ACTIVE, {
885
+ reason,
886
+ });
887
+ }
888
+ export function pauseSession(db, sessionId, reason) {
889
+ return setSessionMaturityV2(db, sessionId, SESSION_MATURITY_V2.PAUSED, {
890
+ reason,
891
+ });
892
+ }
893
+ export function completeSessionV2(db, sessionId, reason) {
894
+ return setSessionMaturityV2(db, sessionId, SESSION_MATURITY_V2.COMPLETED, {
895
+ reason,
896
+ });
897
+ }
898
+ export function archiveSession(db, sessionId, reason) {
899
+ return setSessionMaturityV2(db, sessionId, SESSION_MATURITY_V2.ARCHIVED, {
900
+ reason,
901
+ });
902
+ }
903
+
904
+ export function touchSessionActivity(sessionId) {
905
+ const record = _sessionsV2.get(sessionId);
906
+ if (!record) throw new Error(`Unknown session: ${sessionId}`);
907
+ record.lastActivityAt = Date.now();
908
+ record.updatedAt = record.lastActivityAt;
909
+ return { ...record, metadata: { ...record.metadata } };
910
+ }
911
+
912
+ export function registerArtifactV2(
913
+ _db,
914
+ { artifactId, sessionId, modality, size, initialStatus, metadata } = {},
915
+ ) {
916
+ if (!artifactId) throw new Error("artifactId is required");
917
+ if (!sessionId) throw new Error("sessionId is required");
918
+ if (!modality) throw new Error("modality is required");
919
+ if (!MODALITIES.includes(modality))
920
+ throw new Error(`Invalid modality: ${modality}`);
921
+ if (_artifactsV2.has(artifactId))
922
+ throw new Error(`Artifact ${artifactId} already exists`);
923
+ const status = initialStatus || ARTIFACT_LIFECYCLE_V2.PENDING;
924
+ if (!Object.values(ARTIFACT_LIFECYCLE_V2).includes(status))
925
+ throw new Error(`Invalid initial status: ${status}`);
926
+ if (ARTIFACT_TERMINALS_V2.has(status))
927
+ throw new Error(`Cannot register in terminal status: ${status}`);
928
+ if (getArtifactCount(sessionId) >= _maxArtifactsPerSessionV2)
929
+ throw new Error(
930
+ `Session ${sessionId} reached artifact cap (${_maxArtifactsPerSessionV2})`,
931
+ );
932
+ const now = Date.now();
933
+ const record = {
934
+ artifactId,
935
+ sessionId,
936
+ modality,
937
+ size: size || 0,
938
+ status,
939
+ metadata: metadata || {},
940
+ createdAt: now,
941
+ updatedAt: now,
942
+ lastAccessAt: now,
943
+ };
944
+ _artifactsV2.set(artifactId, record);
945
+ return { ...record, metadata: { ...record.metadata } };
946
+ }
947
+
948
+ export function getArtifactV2(artifactId) {
949
+ const r = _artifactsV2.get(artifactId);
950
+ return r ? { ...r, metadata: { ...r.metadata } } : null;
951
+ }
952
+
953
+ export function setArtifactStatusV2(_db, artifactId, newStatus, patch = {}) {
954
+ const record = _artifactsV2.get(artifactId);
955
+ if (!record) throw new Error(`Unknown artifact: ${artifactId}`);
956
+ if (!Object.values(ARTIFACT_LIFECYCLE_V2).includes(newStatus))
957
+ throw new Error(`Invalid status: ${newStatus}`);
958
+ const allowed = ARTIFACT_TRANSITIONS_V2.get(record.status) || new Set();
959
+ if (!allowed.has(newStatus))
960
+ throw new Error(`Invalid transition: ${record.status} -> ${newStatus}`);
961
+ record.status = newStatus;
962
+ record.updatedAt = Date.now();
963
+ if (patch.reason !== undefined) record.lastReason = patch.reason;
964
+ if (patch.metadata)
965
+ record.metadata = { ...record.metadata, ...patch.metadata };
966
+ return { ...record, metadata: { ...record.metadata } };
967
+ }
968
+
969
+ export function markArtifactReady(db, artifactId, reason) {
970
+ return setArtifactStatusV2(db, artifactId, ARTIFACT_LIFECYCLE_V2.READY, {
971
+ reason,
972
+ });
973
+ }
974
+ export function purgeArtifact(db, artifactId, reason) {
975
+ return setArtifactStatusV2(db, artifactId, ARTIFACT_LIFECYCLE_V2.PURGED, {
976
+ reason,
977
+ });
978
+ }
979
+
980
+ export function touchArtifactAccess(artifactId) {
981
+ const record = _artifactsV2.get(artifactId);
982
+ if (!record) throw new Error(`Unknown artifact: ${artifactId}`);
983
+ record.lastAccessAt = Date.now();
984
+ record.updatedAt = record.lastAccessAt;
985
+ return { ...record, metadata: { ...record.metadata } };
986
+ }
987
+
988
+ export function getActiveSessionCount(ownerId) {
989
+ let n = 0;
990
+ for (const r of _sessionsV2.values()) {
991
+ if (r.status !== SESSION_MATURITY_V2.ACTIVE) continue;
992
+ if (ownerId && r.ownerId !== ownerId) continue;
993
+ n++;
994
+ }
995
+ return n;
996
+ }
997
+
998
+ export function getArtifactCount(sessionId) {
999
+ let n = 0;
1000
+ for (const r of _artifactsV2.values()) {
1001
+ if (ARTIFACT_TERMINALS_V2.has(r.status)) continue;
1002
+ if (sessionId && r.sessionId !== sessionId) continue;
1003
+ n++;
1004
+ }
1005
+ return n;
1006
+ }
1007
+
1008
+ export function autoArchiveIdleSessions(_db, nowMs) {
1009
+ const now = nowMs ?? Date.now();
1010
+ const flipped = [];
1011
+ for (const r of _sessionsV2.values()) {
1012
+ if (
1013
+ r.status === SESSION_MATURITY_V2.ACTIVE ||
1014
+ r.status === SESSION_MATURITY_V2.PAUSED ||
1015
+ r.status === SESSION_MATURITY_V2.COMPLETED
1016
+ ) {
1017
+ if (now - r.lastActivityAt > _sessionIdleMsV2) {
1018
+ r.status = SESSION_MATURITY_V2.ARCHIVED;
1019
+ r.updatedAt = now;
1020
+ r.lastReason = "idle";
1021
+ flipped.push(r.sessionId);
1022
+ }
1023
+ }
1024
+ }
1025
+ return { flipped, count: flipped.length };
1026
+ }
1027
+
1028
+ export function autoPurgeStaleArtifacts(_db, nowMs) {
1029
+ const now = nowMs ?? Date.now();
1030
+ const flipped = [];
1031
+ for (const r of _artifactsV2.values()) {
1032
+ if (r.status === ARTIFACT_LIFECYCLE_V2.READY) {
1033
+ if (now - r.lastAccessAt > _artifactStaleMsV2) {
1034
+ r.status = ARTIFACT_LIFECYCLE_V2.PURGED;
1035
+ r.updatedAt = now;
1036
+ r.lastReason = "stale";
1037
+ flipped.push(r.artifactId);
1038
+ }
1039
+ }
1040
+ }
1041
+ return { flipped, count: flipped.length };
1042
+ }
1043
+
1044
+ export function getMultimodalStatsV2() {
1045
+ const sessionsByStatus = {};
1046
+ for (const s of Object.values(SESSION_MATURITY_V2)) sessionsByStatus[s] = 0;
1047
+ const artifactsByStatus = {};
1048
+ for (const s of Object.values(ARTIFACT_LIFECYCLE_V2))
1049
+ artifactsByStatus[s] = 0;
1050
+ for (const r of _sessionsV2.values()) sessionsByStatus[r.status]++;
1051
+ for (const r of _artifactsV2.values()) artifactsByStatus[r.status]++;
1052
+ return {
1053
+ totalSessionsV2: _sessionsV2.size,
1054
+ totalArtifactsV2: _artifactsV2.size,
1055
+ maxActiveSessionsPerOwner: _maxActiveSessionsPerOwnerV2,
1056
+ maxArtifactsPerSession: _maxArtifactsPerSessionV2,
1057
+ sessionIdleMs: _sessionIdleMsV2,
1058
+ artifactStaleMs: _artifactStaleMsV2,
1059
+ sessionsByStatus,
1060
+ artifactsByStatus,
1061
+ };
1062
+ }
1063
+
1064
+ export function _resetStateV2() {
1065
+ _maxActiveSessionsPerOwnerV2 = MM_DEFAULT_MAX_ACTIVE_SESSIONS_PER_OWNER;
1066
+ _maxArtifactsPerSessionV2 = MM_DEFAULT_MAX_ARTIFACTS_PER_SESSION;
1067
+ _sessionIdleMsV2 = MM_DEFAULT_SESSION_IDLE_MS;
1068
+ _artifactStaleMsV2 = MM_DEFAULT_ARTIFACT_STALE_MS;
1069
+ _sessionsV2.clear();
1070
+ _artifactsV2.clear();
1071
+ }