chainlesschain 0.47.8 → 0.49.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 (86) hide show
  1. package/bin/chainlesschain.js +0 -0
  2. package/package.json +10 -8
  3. package/src/assets/web-panel/.build-hash +1 -1
  4. package/src/assets/web-panel/assets/{AppLayout-6SPt_8Y_.js → AppLayout-Rvi759IS.js} +1 -1
  5. package/src/assets/web-panel/assets/Dashboard-BS-tzGNj.css +1 -0
  6. package/src/assets/web-panel/assets/{Dashboard-Br7kCwKJ.js → Dashboard-DBhFxXYQ.js} +2 -2
  7. package/src/assets/web-panel/assets/{index-tN-8TosE.js → index-uL0cZ8N_.js} +2 -2
  8. package/src/assets/web-panel/index.html +2 -2
  9. package/src/commands/activitypub.js +533 -0
  10. package/src/commands/codegen.js +303 -0
  11. package/src/commands/collab.js +482 -0
  12. package/src/commands/compliance.js +597 -6
  13. package/src/commands/crosschain.js +382 -0
  14. package/src/commands/dbevo.js +388 -0
  15. package/src/commands/dev.js +411 -0
  16. package/src/commands/federation.js +427 -0
  17. package/src/commands/fusion.js +332 -0
  18. package/src/commands/governance.js +505 -0
  19. package/src/commands/hardening.js +110 -0
  20. package/src/commands/incentive.js +373 -0
  21. package/src/commands/inference.js +304 -0
  22. package/src/commands/infra.js +361 -0
  23. package/src/commands/kg.js +371 -0
  24. package/src/commands/marketplace.js +326 -0
  25. package/src/commands/matrix.js +283 -0
  26. package/src/commands/mcp.js +441 -18
  27. package/src/commands/nlprog.js +329 -0
  28. package/src/commands/nostr.js +196 -7
  29. package/src/commands/ops.js +408 -0
  30. package/src/commands/perception.js +385 -0
  31. package/src/commands/pqc.js +34 -0
  32. package/src/commands/privacy.js +345 -0
  33. package/src/commands/quantization.js +280 -0
  34. package/src/commands/recommend.js +336 -0
  35. package/src/commands/reputation.js +349 -0
  36. package/src/commands/runtime.js +500 -0
  37. package/src/commands/sla.js +352 -0
  38. package/src/commands/social.js +265 -0
  39. package/src/commands/stress.js +252 -0
  40. package/src/commands/tech.js +268 -0
  41. package/src/commands/tenant.js +576 -0
  42. package/src/commands/trust.js +366 -0
  43. package/src/harness/mcp-client.js +330 -54
  44. package/src/index.js +114 -0
  45. package/src/lib/activitypub-bridge.js +623 -0
  46. package/src/lib/aiops.js +523 -0
  47. package/src/lib/autonomous-developer.js +524 -0
  48. package/src/lib/code-agent.js +442 -0
  49. package/src/lib/collaboration-governance.js +556 -0
  50. package/src/lib/community-governance.js +649 -0
  51. package/src/lib/compliance-framework-reporter.js +600 -0
  52. package/src/lib/content-recommendation.js +600 -0
  53. package/src/lib/cross-chain.js +669 -0
  54. package/src/lib/dbevo.js +669 -0
  55. package/src/lib/decentral-infra.js +445 -0
  56. package/src/lib/federation-hardening.js +587 -0
  57. package/src/lib/hardening-manager.js +409 -0
  58. package/src/lib/inference-network.js +407 -0
  59. package/src/lib/knowledge-graph.js +530 -0
  60. package/src/lib/matrix-bridge.js +252 -0
  61. package/src/lib/mcp-client.js +3 -0
  62. package/src/lib/mcp-registry.js +347 -0
  63. package/src/lib/mcp-scaffold.js +385 -0
  64. package/src/lib/multimodal.js +698 -0
  65. package/src/lib/nl-programming.js +595 -0
  66. package/src/lib/nostr-bridge.js +214 -38
  67. package/src/lib/perception.js +500 -0
  68. package/src/lib/pqc-manager.js +141 -9
  69. package/src/lib/privacy-computing.js +575 -0
  70. package/src/lib/protocol-fusion.js +535 -0
  71. package/src/lib/quantization.js +362 -0
  72. package/src/lib/reputation-optimizer.js +509 -0
  73. package/src/lib/skill-marketplace.js +397 -0
  74. package/src/lib/sla-manager.js +484 -0
  75. package/src/lib/social-graph.js +408 -0
  76. package/src/lib/stix-parser.js +167 -0
  77. package/src/lib/stress-tester.js +383 -0
  78. package/src/lib/tech-learning-engine.js +651 -0
  79. package/src/lib/tenant-saas.js +831 -0
  80. package/src/lib/threat-intel.js +268 -0
  81. package/src/lib/token-incentive.js +513 -0
  82. package/src/lib/topic-classifier.js +400 -0
  83. package/src/lib/trust-security.js +473 -0
  84. package/src/lib/ueba.js +403 -0
  85. package/src/lib/universal-runtime.js +771 -0
  86. package/src/assets/web-panel/assets/Dashboard-CKeMmCoT.css +0 -1
@@ -0,0 +1,509 @@
1
+ /**
2
+ * Reputation Optimizer — observation ingestion, decay models,
3
+ * anomaly detection, and simulated parameter optimization for the
4
+ * reputation algorithm (Phase 60 design, CLI port).
5
+ */
6
+
7
+ import crypto from "crypto";
8
+
9
+ /* ── Constants ─────────────────────────────────────────────── */
10
+
11
+ export const OPTIMIZATION_OBJECTIVES = Object.freeze({
12
+ ACCURACY: "accuracy",
13
+ FAIRNESS: "fairness",
14
+ RESILIENCE: "resilience",
15
+ CONVERGENCE_SPEED: "convergence_speed",
16
+ });
17
+
18
+ export const ANOMALY_DETECTORS = Object.freeze({
19
+ IQR: "iqr",
20
+ Z_SCORE: "z_score",
21
+ });
22
+
23
+ export const DECAY_MODELS = Object.freeze({
24
+ EXPONENTIAL: "exponential",
25
+ LINEAR: "linear",
26
+ STEP: "step",
27
+ NONE: "none",
28
+ });
29
+
30
+ const DAY_MS = 86400000;
31
+
32
+ /* ── In-memory stores ─────────────────────────────────────── */
33
+ const _observations = new Map(); // did → [{ts, score, kind, weight}]
34
+ const _runs = new Map();
35
+ const _analytics = new Map();
36
+ let _seq = 0;
37
+
38
+ /* ── Schema ────────────────────────────────────────────────── */
39
+
40
+ export function ensureReputationTables(db) {
41
+ db.exec(`
42
+ CREATE TABLE IF NOT EXISTS reputation_observations (
43
+ observation_id TEXT PRIMARY KEY,
44
+ did TEXT NOT NULL,
45
+ score REAL NOT NULL,
46
+ kind TEXT,
47
+ weight REAL DEFAULT 1.0,
48
+ recorded_at INTEGER NOT NULL
49
+ )
50
+ `);
51
+ db.exec(`
52
+ CREATE TABLE IF NOT EXISTS reputation_optimization_runs (
53
+ run_id TEXT PRIMARY KEY,
54
+ objective TEXT NOT NULL,
55
+ iterations INTEGER NOT NULL,
56
+ param_space TEXT NOT NULL,
57
+ best_params TEXT,
58
+ best_score REAL,
59
+ status TEXT DEFAULT 'running',
60
+ created_at INTEGER NOT NULL,
61
+ completed_at INTEGER
62
+ )
63
+ `);
64
+ db.exec(`
65
+ CREATE TABLE IF NOT EXISTS reputation_analytics (
66
+ analytics_id TEXT PRIMARY KEY,
67
+ run_id TEXT NOT NULL,
68
+ reputation_distribution TEXT,
69
+ anomalies TEXT,
70
+ recommendations TEXT,
71
+ created_at INTEGER NOT NULL
72
+ )
73
+ `);
74
+ }
75
+
76
+ /* ── Observations ──────────────────────────────────────────── */
77
+
78
+ export function addObservation(db, did, score, opts = {}) {
79
+ if (!did) throw new Error("DID is required");
80
+ const s = Number(score);
81
+ if (!Number.isFinite(s)) throw new Error("score must be a finite number");
82
+ if (s < 0 || s > 1) throw new Error("score must be within [0, 1]");
83
+
84
+ const observationId = crypto.randomUUID();
85
+ const kind = opts.kind || "generic";
86
+ const weight = Number(opts.weight ?? 1);
87
+ const recordedAt = Number(opts.recordedAt ?? Date.now());
88
+
89
+ const obs = { observationId, did, score: s, kind, weight, recordedAt };
90
+
91
+ if (!_observations.has(did)) _observations.set(did, []);
92
+ _observations.get(did).push(obs);
93
+
94
+ db.prepare(
95
+ `INSERT INTO reputation_observations (observation_id, did, score, kind, weight, recorded_at)
96
+ VALUES (?, ?, ?, ?, ?, ?)`,
97
+ ).run(observationId, did, s, kind, weight, recordedAt);
98
+
99
+ return obs;
100
+ }
101
+
102
+ /* ── Decay ─────────────────────────────────────────────────── */
103
+
104
+ function _decayFactor(model, ageDays, params) {
105
+ const lambda = params.lambda ?? 0.1;
106
+ const alpha = params.alpha ?? 0.05;
107
+ const steps = params.steps ?? [
108
+ { atDays: 7, factor: 1 },
109
+ { atDays: 30, factor: 0.7 },
110
+ { atDays: 90, factor: 0.4 },
111
+ { atDays: Infinity, factor: 0.1 },
112
+ ];
113
+
114
+ if (ageDays < 0) ageDays = 0;
115
+ switch (model) {
116
+ case DECAY_MODELS.NONE:
117
+ return 1;
118
+ case DECAY_MODELS.EXPONENTIAL:
119
+ return Math.exp(-lambda * ageDays);
120
+ case DECAY_MODELS.LINEAR:
121
+ return Math.max(0, 1 - alpha * ageDays);
122
+ case DECAY_MODELS.STEP: {
123
+ for (const step of steps) {
124
+ if (ageDays <= step.atDays) return step.factor;
125
+ }
126
+ return 0;
127
+ }
128
+ default:
129
+ throw new Error(`Unknown decay model: ${model}`);
130
+ }
131
+ }
132
+
133
+ export function computeScore(did, opts = {}) {
134
+ const observations = _observations.get(did) || [];
135
+ if (observations.length === 0) {
136
+ return { did, score: 0, observations: 0, decay: opts.decay || "none" };
137
+ }
138
+
139
+ const now = Number(opts.now ?? Date.now());
140
+ const model = opts.decay || DECAY_MODELS.NONE;
141
+ const params = {
142
+ lambda: opts.lambda,
143
+ alpha: opts.alpha,
144
+ steps: opts.steps,
145
+ };
146
+
147
+ let weightedSum = 0;
148
+ let weightTotal = 0;
149
+ for (const obs of observations) {
150
+ const ageDays = Math.max(0, (now - obs.recordedAt) / DAY_MS);
151
+ const decay = _decayFactor(model, ageDays, params);
152
+ const effectiveWeight = obs.weight * decay;
153
+ weightedSum += obs.score * effectiveWeight;
154
+ weightTotal += effectiveWeight;
155
+ }
156
+
157
+ const score = weightTotal > 0 ? weightedSum / weightTotal : 0;
158
+ return {
159
+ did,
160
+ score: Number(score.toFixed(6)),
161
+ observations: observations.length,
162
+ decay: model,
163
+ weightTotal: Number(weightTotal.toFixed(4)),
164
+ };
165
+ }
166
+
167
+ export function listScores(opts = {}) {
168
+ const dids = [..._observations.keys()];
169
+ const model = opts.decay || DECAY_MODELS.NONE;
170
+ const now = Number(opts.now ?? Date.now());
171
+ const rows = dids.map((did) =>
172
+ computeScore(did, {
173
+ decay: model,
174
+ now,
175
+ lambda: opts.lambda,
176
+ alpha: opts.alpha,
177
+ }),
178
+ );
179
+ rows.sort((a, b) => b.score - a.score);
180
+ const limit = opts.limit || 50;
181
+ return rows.slice(0, limit);
182
+ }
183
+
184
+ /* ── Anomaly detection ─────────────────────────────────────── */
185
+
186
+ function _mean(values) {
187
+ return values.reduce((a, b) => a + b, 0) / values.length;
188
+ }
189
+
190
+ function _stddev(values, mean) {
191
+ const m = mean ?? _mean(values);
192
+ const variance =
193
+ values.reduce((acc, v) => acc + (v - m) ** 2, 0) / values.length;
194
+ return Math.sqrt(variance);
195
+ }
196
+
197
+ function _quantile(sorted, q) {
198
+ if (sorted.length === 0) return 0;
199
+ const pos = (sorted.length - 1) * q;
200
+ const base = Math.floor(pos);
201
+ const rest = pos - base;
202
+ if (sorted[base + 1] !== undefined) {
203
+ return sorted[base] + rest * (sorted[base + 1] - sorted[base]);
204
+ }
205
+ return sorted[base];
206
+ }
207
+
208
+ export function detectAnomalies(opts = {}) {
209
+ const method = opts.method || ANOMALY_DETECTORS.Z_SCORE;
210
+ const threshold = opts.threshold ?? (method === "iqr" ? 1.5 : 2.5);
211
+
212
+ const scores = listScores({ decay: opts.decay });
213
+ if (scores.length < 3) {
214
+ return {
215
+ method,
216
+ threshold,
217
+ totalSamples: scores.length,
218
+ anomalies: [],
219
+ message: "Insufficient samples for anomaly detection (<3)",
220
+ };
221
+ }
222
+
223
+ const values = scores.map((s) => s.score);
224
+ const anomalies = [];
225
+
226
+ if (method === ANOMALY_DETECTORS.Z_SCORE) {
227
+ const m = _mean(values);
228
+ const sd = _stddev(values, m);
229
+ if (sd === 0) {
230
+ return {
231
+ method,
232
+ threshold,
233
+ totalSamples: scores.length,
234
+ anomalies: [],
235
+ message: "Zero variance — all scores identical",
236
+ };
237
+ }
238
+ for (const s of scores) {
239
+ const z = (s.score - m) / sd;
240
+ if (Math.abs(z) >= threshold) {
241
+ anomalies.push({
242
+ did: s.did,
243
+ score: s.score,
244
+ zScore: Number(z.toFixed(4)),
245
+ reason: z > 0 ? "unusually high" : "unusually low",
246
+ });
247
+ }
248
+ }
249
+ } else if (method === ANOMALY_DETECTORS.IQR) {
250
+ const sorted = [...values].sort((a, b) => a - b);
251
+ const q1 = _quantile(sorted, 0.25);
252
+ const q3 = _quantile(sorted, 0.75);
253
+ const iqr = q3 - q1;
254
+ const lower = q1 - threshold * iqr;
255
+ const upper = q3 + threshold * iqr;
256
+ for (const s of scores) {
257
+ if (s.score < lower || s.score > upper) {
258
+ anomalies.push({
259
+ did: s.did,
260
+ score: s.score,
261
+ reason: s.score > upper ? "above upper fence" : "below lower fence",
262
+ lower: Number(lower.toFixed(4)),
263
+ upper: Number(upper.toFixed(4)),
264
+ });
265
+ }
266
+ }
267
+ } else {
268
+ throw new Error(`Unknown anomaly detector: ${method}`);
269
+ }
270
+
271
+ return {
272
+ method,
273
+ threshold,
274
+ totalSamples: scores.length,
275
+ anomalies,
276
+ summary: `${anomalies.length} anomal${anomalies.length === 1 ? "y" : "ies"} detected`,
277
+ };
278
+ }
279
+
280
+ /* ── Optimization (simulated) ──────────────────────────────── */
281
+
282
+ const OBJECTIVE_VALUES = new Set(Object.values(OPTIMIZATION_OBJECTIVES));
283
+
284
+ function _seededRand(seed) {
285
+ const v = Math.sin(seed * 78.233) * 43758.5453;
286
+ return v - Math.floor(v);
287
+ }
288
+
289
+ function _evaluateParams(params, objective, iteration) {
290
+ // Simulated objective surfaces. Each returns a score in [0, 1].
291
+ // Same iteration always produces the same score → deterministic tests.
292
+ const jitter = _seededRand(iteration + 1) * 0.1;
293
+ switch (objective) {
294
+ case OPTIMIZATION_OBJECTIVES.ACCURACY: {
295
+ // optimum near kappa=2.5, contamination=0.05
296
+ const d1 = Math.abs(params.kappa - 2.5) / 2.5;
297
+ const d2 = Math.abs(params.contamination - 0.05) / 0.05;
298
+ return Math.max(0, 1 - d1 * 0.4 - d2 * 0.4) * (0.85 + jitter * 0.15);
299
+ }
300
+ case OPTIMIZATION_OBJECTIVES.FAIRNESS: {
301
+ // optimum when lambda is small (low decay) — treats all equally
302
+ return Math.max(0, 1 - params.lambda * 2) * (0.8 + jitter * 0.2);
303
+ }
304
+ case OPTIMIZATION_OBJECTIVES.RESILIENCE: {
305
+ // optimum when contamination high (tolerates more anomalies)
306
+ return Math.min(1, params.contamination * 8) * (0.75 + jitter * 0.25);
307
+ }
308
+ case OPTIMIZATION_OBJECTIVES.CONVERGENCE_SPEED: {
309
+ // optimum when iterations small and kappa high
310
+ return (params.kappa / 3) * (0.7 + jitter * 0.3);
311
+ }
312
+ default:
313
+ throw new Error(`Unknown objective: ${objective}`);
314
+ }
315
+ }
316
+
317
+ function _sampleParams(seed) {
318
+ return {
319
+ lambda: 0.01 + _seededRand(seed) * 0.49,
320
+ kappa: 0.5 + _seededRand(seed + 1) * 2.5,
321
+ contamination: 0.01 + _seededRand(seed + 2) * 0.19,
322
+ };
323
+ }
324
+
325
+ export function startOptimization(db, opts = {}) {
326
+ const objective = opts.objective || OPTIMIZATION_OBJECTIVES.ACCURACY;
327
+ if (!OBJECTIVE_VALUES.has(objective)) {
328
+ throw new Error(`Unknown objective: ${objective}`);
329
+ }
330
+ const rawIter = opts.iterations == null ? 50 : Number(opts.iterations);
331
+ const iterations = Math.max(
332
+ 1,
333
+ Math.min(1000, Number.isFinite(rawIter) ? rawIter : 50),
334
+ );
335
+ const runId = crypto.randomUUID();
336
+ const now = Date.now();
337
+
338
+ const paramSpace = {
339
+ lambda: [0.01, 0.5],
340
+ kappa: [0.5, 3.0],
341
+ contamination: [0.01, 0.2],
342
+ };
343
+
344
+ let bestParams = null;
345
+ let bestScore = -Infinity;
346
+ const history = [];
347
+
348
+ for (let i = 0; i < iterations; i++) {
349
+ const params = _sampleParams(_seq * 101 + i * 17 + 1);
350
+ const score = _evaluateParams(params, objective, i);
351
+ history.push({ iteration: i, params, score });
352
+ if (score > bestScore) {
353
+ bestScore = score;
354
+ bestParams = params;
355
+ }
356
+ }
357
+
358
+ const run = {
359
+ runId,
360
+ objective,
361
+ iterations,
362
+ paramSpace,
363
+ bestParams,
364
+ bestScore: Number(bestScore.toFixed(6)),
365
+ status: "complete",
366
+ createdAt: now,
367
+ completedAt: now,
368
+ history,
369
+ _seq: ++_seq,
370
+ };
371
+
372
+ _runs.set(runId, run);
373
+
374
+ db.prepare(
375
+ `INSERT INTO reputation_optimization_runs (run_id, objective, iterations, param_space, best_params, best_score, status, created_at, completed_at)
376
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
377
+ ).run(
378
+ runId,
379
+ objective,
380
+ iterations,
381
+ JSON.stringify(paramSpace),
382
+ JSON.stringify(bestParams),
383
+ run.bestScore,
384
+ "complete",
385
+ now,
386
+ now,
387
+ );
388
+
389
+ // Auto-generate analytics
390
+ const distribution = _buildDistribution(listScores({ decay: "none" }));
391
+ const anomalies = detectAnomalies({ method: "z_score" });
392
+ const recommendations = _buildRecommendations(objective, bestParams);
393
+ const analyticsId = crypto.randomUUID();
394
+ const analytics = {
395
+ analyticsId,
396
+ runId,
397
+ reputationDistribution: distribution,
398
+ anomalies,
399
+ recommendations,
400
+ createdAt: now,
401
+ };
402
+ _analytics.set(runId, analytics);
403
+
404
+ db.prepare(
405
+ `INSERT INTO reputation_analytics (analytics_id, run_id, reputation_distribution, anomalies, recommendations, created_at)
406
+ VALUES (?, ?, ?, ?, ?, ?)`,
407
+ ).run(
408
+ analyticsId,
409
+ runId,
410
+ JSON.stringify(distribution),
411
+ JSON.stringify(anomalies),
412
+ JSON.stringify(recommendations),
413
+ now,
414
+ );
415
+
416
+ return { ...run, analytics };
417
+ }
418
+
419
+ function _buildDistribution(scores) {
420
+ if (scores.length === 0) {
421
+ return { buckets: [], total: 0, mean: 0 };
422
+ }
423
+ const buckets = [
424
+ { label: "low (<0.3)", count: 0 },
425
+ { label: "mid (0.3-0.7)", count: 0 },
426
+ { label: "high (>0.7)", count: 0 },
427
+ ];
428
+ let sum = 0;
429
+ for (const s of scores) {
430
+ if (s.score < 0.3) buckets[0].count++;
431
+ else if (s.score <= 0.7) buckets[1].count++;
432
+ else buckets[2].count++;
433
+ sum += s.score;
434
+ }
435
+ return {
436
+ buckets,
437
+ total: scores.length,
438
+ mean: Number((sum / scores.length).toFixed(4)),
439
+ };
440
+ }
441
+
442
+ function _buildRecommendations(objective, params) {
443
+ const recs = [];
444
+ if (params.lambda > 0.3) {
445
+ recs.push(
446
+ "High lambda — reputation decays quickly; consider if users have enough time to recover",
447
+ );
448
+ }
449
+ if (params.kappa < 1) {
450
+ recs.push("Low kappa — exploration-heavy; more noise in early iterations");
451
+ }
452
+ if (params.contamination > 0.15) {
453
+ recs.push(
454
+ "High contamination — more samples flagged as anomalies; watch for false positives",
455
+ );
456
+ }
457
+ if (
458
+ objective === OPTIMIZATION_OBJECTIVES.RESILIENCE &&
459
+ params.contamination < 0.05
460
+ ) {
461
+ recs.push(
462
+ "Resilience objective but low contamination tolerance — consider raising",
463
+ );
464
+ }
465
+ if (recs.length === 0) {
466
+ recs.push(`Optimized params are within healthy ranges for ${objective}`);
467
+ }
468
+ return recs;
469
+ }
470
+
471
+ export function getOptimizationStatus(runId) {
472
+ const run = _runs.get(runId);
473
+ if (!run) throw new Error(`Optimization run not found: ${runId}`);
474
+ const { _seq: _omit, ...rest } = run;
475
+ void _omit;
476
+ return rest;
477
+ }
478
+
479
+ export function getAnalytics(runId) {
480
+ const analytics = _analytics.get(runId);
481
+ if (!analytics) throw new Error(`Analytics not found for run: ${runId}`);
482
+ return analytics;
483
+ }
484
+
485
+ export function listOptimizationRuns(opts = {}) {
486
+ const runs = [..._runs.values()];
487
+ runs.sort((a, b) => b.createdAt - a.createdAt || b._seq - a._seq);
488
+ const limit = opts.limit || 10;
489
+ return runs.slice(0, limit).map((r) => {
490
+ const { _seq: _omit, history: _history, ...rest } = r;
491
+ void _omit;
492
+ void _history;
493
+ return rest;
494
+ });
495
+ }
496
+
497
+ export function applyOptimizedParams(runId) {
498
+ const run = _runs.get(runId);
499
+ if (!run) throw new Error(`Optimization run not found: ${runId}`);
500
+ run.status = "applied";
501
+ return { runId, applied: true, params: run.bestParams };
502
+ }
503
+
504
+ export function _resetState() {
505
+ _observations.clear();
506
+ _runs.clear();
507
+ _analytics.clear();
508
+ _seq = 0;
509
+ }