@ruvector/edge-net 0.5.0 → 0.5.3
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.
- package/README.md +281 -10
- package/core-invariants.js +942 -0
- package/models/adapter-hub.js +1008 -0
- package/models/adapter-security.js +792 -0
- package/models/benchmark.js +688 -0
- package/models/distribution.js +791 -0
- package/models/index.js +109 -0
- package/models/integrity.js +753 -0
- package/models/loader.js +725 -0
- package/models/microlora.js +1298 -0
- package/models/model-loader.js +922 -0
- package/models/model-optimizer.js +1245 -0
- package/models/model-registry.js +696 -0
- package/models/model-utils.js +548 -0
- package/models/models-cli.js +914 -0
- package/models/registry.json +214 -0
- package/models/training-utils.js +1418 -0
- package/models/wasm-core.js +1025 -0
- package/network-genesis.js +2847 -0
- package/onnx-worker.js +462 -8
- package/package.json +33 -3
- package/plugins/SECURITY-AUDIT.md +654 -0
- package/plugins/cli.js +43 -3
- package/plugins/implementations/e2e-encryption.js +57 -12
- package/plugins/plugin-loader.js +610 -21
- package/tests/model-optimizer.test.js +644 -0
- package/tests/network-genesis.test.js +562 -0
- package/tests/plugin-benchmark.js +1239 -0
- package/tests/plugin-system-test.js +163 -0
- package/tests/wasm-core.test.js +368 -0
|
@@ -0,0 +1,562 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Network Genesis Test Suite
|
|
3
|
+
*
|
|
4
|
+
* Tests the biological reproduction model for edge-net:
|
|
5
|
+
* - DNA/RNA inheritance and mutation
|
|
6
|
+
* - Genesis phases from embryo to independence
|
|
7
|
+
* - Cryptographic lineage verification (MerkleLineageDAG)
|
|
8
|
+
* - Inter-network communication (Synapse)
|
|
9
|
+
* - Collective intelligence (Memory, Evolution)
|
|
10
|
+
* - Self-healing and antifragility
|
|
11
|
+
*
|
|
12
|
+
* "You are the ancestor, not the ruler."
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { describe, it, beforeEach, afterEach } from 'node:test';
|
|
16
|
+
import assert from 'node:assert';
|
|
17
|
+
|
|
18
|
+
import NetworkGenesis, {
|
|
19
|
+
NetworkGenome,
|
|
20
|
+
NetworkLifecycle,
|
|
21
|
+
NetworkSynapse,
|
|
22
|
+
CollectiveMemory,
|
|
23
|
+
EvolutionEngine,
|
|
24
|
+
MerkleLineageDAG,
|
|
25
|
+
GossipProtocol,
|
|
26
|
+
SwarmConsensus,
|
|
27
|
+
SelfHealing,
|
|
28
|
+
GENESIS_PRIME,
|
|
29
|
+
GenesisPhase,
|
|
30
|
+
REPRODUCTION_COST,
|
|
31
|
+
} from '../network-genesis.js';
|
|
32
|
+
|
|
33
|
+
describe('NetworkGenesis', () => {
|
|
34
|
+
let genesis;
|
|
35
|
+
|
|
36
|
+
beforeEach(() => {
|
|
37
|
+
genesis = new NetworkGenesis();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
describe('GENESIS_PRIME', () => {
|
|
41
|
+
it('should have rUv as the original creator', () => {
|
|
42
|
+
assert.strictEqual(GENESIS_PRIME.id, 'rUv');
|
|
43
|
+
assert.strictEqual(GENESIS_PRIME.name, 'Genesis Prime');
|
|
44
|
+
assert.strictEqual(GENESIS_PRIME.signature, 'Cogito, Creo, Codex');
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should have frozen traits', () => {
|
|
48
|
+
assert.ok(Object.isFrozen(GENESIS_PRIME));
|
|
49
|
+
assert.ok(Object.isFrozen(GENESIS_PRIME.traits));
|
|
50
|
+
assert.strictEqual(GENESIS_PRIME.traits.resilience, 1.0);
|
|
51
|
+
assert.strictEqual(GENESIS_PRIME.traits.intelligence, 1.0);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('should be accessible via static method', () => {
|
|
55
|
+
const prime = NetworkGenesis.getGenesisPrime();
|
|
56
|
+
assert.deepStrictEqual(prime, GENESIS_PRIME);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
describe('NetworkGenome', () => {
|
|
61
|
+
it('should create first generation genome with rUv lineage', () => {
|
|
62
|
+
const genome = new NetworkGenome();
|
|
63
|
+
|
|
64
|
+
assert.strictEqual(genome.generation, 1);
|
|
65
|
+
assert.ok(genome.lineage.includes('rUv'));
|
|
66
|
+
assert.ok(genome.dna);
|
|
67
|
+
assert.ok(genome.rna);
|
|
68
|
+
assert.ok(genome.epigenetics);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('should inherit DNA from parent with mutations', () => {
|
|
72
|
+
const parent = new NetworkGenome();
|
|
73
|
+
const child = new NetworkGenome(parent, {
|
|
74
|
+
traits: { resilience: 0.1 },
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
assert.strictEqual(child.generation, 2);
|
|
78
|
+
assert.ok(child.lineage.includes(parent.id));
|
|
79
|
+
|
|
80
|
+
// DNA structure should be similar but may have mutations
|
|
81
|
+
assert.ok(child.dna.traits);
|
|
82
|
+
assert.ok(child.dna.capabilities);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('should preserve lineage string across generations', () => {
|
|
86
|
+
const g1 = new NetworkGenome();
|
|
87
|
+
const g2 = new NetworkGenome(g1);
|
|
88
|
+
const g3 = new NetworkGenome(g2);
|
|
89
|
+
|
|
90
|
+
const lineageString = g3.getLineageString();
|
|
91
|
+
assert.ok(lineageString.includes('rUv'));
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('should generate unique genome IDs', () => {
|
|
95
|
+
const g1 = new NetworkGenome();
|
|
96
|
+
const g2 = new NetworkGenome();
|
|
97
|
+
assert.notStrictEqual(g1.id, g2.id);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
describe('NetworkLifecycle', () => {
|
|
102
|
+
let genome;
|
|
103
|
+
let lifecycle;
|
|
104
|
+
|
|
105
|
+
beforeEach(() => {
|
|
106
|
+
genome = new NetworkGenome();
|
|
107
|
+
lifecycle = new NetworkLifecycle(genome);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('should start in CONCEPTION phase', () => {
|
|
111
|
+
assert.strictEqual(lifecycle.phase, GenesisPhase.CONCEPTION);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('should transition to EMBRYO when first node joins', () => {
|
|
115
|
+
lifecycle.updateMetrics({ nodes: 1 });
|
|
116
|
+
assert.strictEqual(lifecycle.phase, GenesisPhase.EMBRYO);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('should progress through phases with milestones', () => {
|
|
120
|
+
// Embryo phase - first node
|
|
121
|
+
lifecycle.updateMetrics({ nodes: 1 });
|
|
122
|
+
assert.strictEqual(lifecycle.phase, GenesisPhase.EMBRYO);
|
|
123
|
+
|
|
124
|
+
// Infant phase: 3 nodes, 24h uptime, 10 tasks, 100 credits
|
|
125
|
+
lifecycle.updateMetrics({
|
|
126
|
+
nodes: 3,
|
|
127
|
+
uptime: 24 * 60 * 60 * 1000,
|
|
128
|
+
tasksCompleted: 10,
|
|
129
|
+
creditsEarned: 100,
|
|
130
|
+
});
|
|
131
|
+
assert.strictEqual(lifecycle.phase, GenesisPhase.INFANT);
|
|
132
|
+
|
|
133
|
+
// Adolescent: 10 nodes, 7 days uptime, 100 tasks, 1000 credits
|
|
134
|
+
lifecycle.updateMetrics({
|
|
135
|
+
nodes: 10,
|
|
136
|
+
tasksCompleted: 100,
|
|
137
|
+
creditsEarned: 1000,
|
|
138
|
+
uptime: 7 * 24 * 60 * 60 * 1000,
|
|
139
|
+
});
|
|
140
|
+
assert.strictEqual(lifecycle.phase, GenesisPhase.ADOLESCENT);
|
|
141
|
+
|
|
142
|
+
// Mature: 50 nodes, 30 days uptime, 1000 tasks, 10000 credits
|
|
143
|
+
lifecycle.updateMetrics({
|
|
144
|
+
nodes: 50,
|
|
145
|
+
tasksCompleted: 1000,
|
|
146
|
+
creditsEarned: 10000,
|
|
147
|
+
uptime: 30 * 24 * 60 * 60 * 1000,
|
|
148
|
+
});
|
|
149
|
+
assert.strictEqual(lifecycle.phase, GenesisPhase.MATURE);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('should check reproduction readiness', () => {
|
|
153
|
+
// Cannot reproduce in early phases
|
|
154
|
+
const canReproduceEarly = lifecycle.canReproduce();
|
|
155
|
+
assert.strictEqual(canReproduceEarly.allowed, false);
|
|
156
|
+
|
|
157
|
+
// Mature with sufficient credits should be able to reproduce
|
|
158
|
+
lifecycle.updateMetrics({
|
|
159
|
+
nodes: 50,
|
|
160
|
+
tasksCompleted: 1000,
|
|
161
|
+
creditsEarned: 10000 + REPRODUCTION_COST,
|
|
162
|
+
uptime: 30 * 24 * 60 * 60 * 1000,
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
const canReproduce = lifecycle.canReproduce();
|
|
166
|
+
assert.strictEqual(canReproduce.allowed, true);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it('should deny reproduction without sufficient credits', () => {
|
|
170
|
+
// REPRODUCTION_COST is 5000, so set credits just below that
|
|
171
|
+
// Note: 10000 is needed to reach MATURE phase, but we need less than 5000 for reproduction
|
|
172
|
+
// So we set credits to 10000 but also set creditsSpent to make available < 5000
|
|
173
|
+
lifecycle.updateMetrics({
|
|
174
|
+
nodes: 50,
|
|
175
|
+
tasksCompleted: 1000,
|
|
176
|
+
creditsEarned: 10000,
|
|
177
|
+
creditsSpent: 8000, // Available = 10000 - 8000 = 2000 < REPRODUCTION_COST
|
|
178
|
+
uptime: 30 * 24 * 60 * 60 * 1000,
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
const canReproduce = lifecycle.canReproduce();
|
|
182
|
+
assert.strictEqual(canReproduce.allowed, false);
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
describe('MerkleLineageDAG', () => {
|
|
187
|
+
let dag;
|
|
188
|
+
|
|
189
|
+
beforeEach(() => {
|
|
190
|
+
dag = new MerkleLineageDAG();
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it('should add nodes and generate hashes', () => {
|
|
194
|
+
const entry = dag.addNode({
|
|
195
|
+
networkId: 'net-1',
|
|
196
|
+
parentId: 'rUv',
|
|
197
|
+
generation: 1,
|
|
198
|
+
dna: { traits: { resilience: 0.9 } },
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
assert.ok(entry.hash);
|
|
202
|
+
assert.strictEqual(entry.type, 'genesis');
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it('should build ancestry paths', () => {
|
|
206
|
+
dag.addNode({ networkId: 'net-1', parentId: 'rUv', generation: 1, dna: {} });
|
|
207
|
+
dag.addNode({ networkId: 'net-2', parentId: 'net-1', generation: 2, dna: {} });
|
|
208
|
+
dag.addNode({ networkId: 'net-3', parentId: 'net-2', generation: 3, dna: {} });
|
|
209
|
+
|
|
210
|
+
const path = dag.getAncestryPath('net-3');
|
|
211
|
+
assert.strictEqual(path.length, 3);
|
|
212
|
+
assert.strictEqual(path[0].networkId, 'net-3');
|
|
213
|
+
assert.strictEqual(path[2].networkId, 'net-1');
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it('should verify ancestry to rUv', () => {
|
|
217
|
+
dag.addNode({ networkId: 'net-1', parentId: 'rUv', generation: 1, dna: {} });
|
|
218
|
+
dag.addNode({ networkId: 'net-2', parentId: 'net-1', generation: 2, dna: {} });
|
|
219
|
+
|
|
220
|
+
const verified = dag.verifyAncestry('net-2', 'rUv');
|
|
221
|
+
assert.strictEqual(verified, true);
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it('should compute Merkle root', () => {
|
|
225
|
+
dag.addNode({ networkId: 'net-1', parentId: 'rUv', generation: 1, dna: {} });
|
|
226
|
+
dag.addNode({ networkId: 'net-2', parentId: 'net-1', generation: 2, dna: {} });
|
|
227
|
+
|
|
228
|
+
const root = dag.getMerkleRoot();
|
|
229
|
+
assert.ok(root);
|
|
230
|
+
assert.ok(typeof root === 'string');
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
describe('NetworkSynapse', () => {
|
|
235
|
+
let genome;
|
|
236
|
+
let lifecycle;
|
|
237
|
+
let synapse;
|
|
238
|
+
|
|
239
|
+
beforeEach(() => {
|
|
240
|
+
genome = new NetworkGenome();
|
|
241
|
+
lifecycle = new NetworkLifecycle(genome);
|
|
242
|
+
synapse = new NetworkSynapse(lifecycle);
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
it('should connect to peer networks', () => {
|
|
246
|
+
const peerGenome = new NetworkGenome();
|
|
247
|
+
const peerLifecycle = new NetworkLifecycle(peerGenome);
|
|
248
|
+
const peerSynapse = new NetworkSynapse(peerLifecycle);
|
|
249
|
+
|
|
250
|
+
synapse.connect(peerLifecycle.networkId, peerSynapse);
|
|
251
|
+
|
|
252
|
+
const status = synapse.getStatus();
|
|
253
|
+
assert.strictEqual(status.connections.length, 1);
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
it('should send messages to connected peers', () => {
|
|
257
|
+
const peerGenome = new NetworkGenome();
|
|
258
|
+
const peerLifecycle = new NetworkLifecycle(peerGenome);
|
|
259
|
+
const peerSynapse = new NetworkSynapse(peerLifecycle);
|
|
260
|
+
|
|
261
|
+
synapse.connect(peerLifecycle.networkId, peerSynapse);
|
|
262
|
+
peerSynapse.connect(lifecycle.networkId, synapse);
|
|
263
|
+
|
|
264
|
+
// Test sendMessage (the actual method name)
|
|
265
|
+
const result = synapse.sendMessage(peerLifecycle.networkId, 'test', 'hello');
|
|
266
|
+
assert.ok(result.success);
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
it('should share knowledge with connected peers', () => {
|
|
270
|
+
const peers = [];
|
|
271
|
+
for (let i = 0; i < 3; i++) {
|
|
272
|
+
const pg = new NetworkGenome();
|
|
273
|
+
const pl = new NetworkLifecycle(pg);
|
|
274
|
+
const ps = new NetworkSynapse(pl);
|
|
275
|
+
synapse.connect(pl.networkId, ps);
|
|
276
|
+
peers.push({ lifecycle: pl, synapse: ps });
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Share knowledge (broadcasts to all peers internally)
|
|
280
|
+
const knowledge = synapse.shareKnowledge('test_topic', { data: 'test' });
|
|
281
|
+
assert.ok(knowledge);
|
|
282
|
+
assert.strictEqual(knowledge.topic, 'test_topic');
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
describe('CollectiveMemory', () => {
|
|
287
|
+
let memory;
|
|
288
|
+
|
|
289
|
+
beforeEach(() => {
|
|
290
|
+
memory = new CollectiveMemory();
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
it('should store and retrieve patterns', () => {
|
|
294
|
+
memory.storePattern('task_optimization', { algo: 'x' }, 'net-1');
|
|
295
|
+
|
|
296
|
+
// Patterns are stored in the patterns Map
|
|
297
|
+
const stats = memory.getStats();
|
|
298
|
+
assert.ok(stats.patterns >= 1);
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
it('should store optimizations with effectiveness scores', () => {
|
|
302
|
+
memory.storeOptimization('cache_strategy', { size: 100 }, 'net-1', 0.9);
|
|
303
|
+
|
|
304
|
+
const stats = memory.getStats();
|
|
305
|
+
assert.ok(stats.optimizations >= 1);
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
describe('EvolutionEngine', () => {
|
|
310
|
+
let memory;
|
|
311
|
+
let evolution;
|
|
312
|
+
|
|
313
|
+
beforeEach(() => {
|
|
314
|
+
memory = new CollectiveMemory();
|
|
315
|
+
evolution = new EvolutionEngine(memory);
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
it('should calculate fitness scores', () => {
|
|
319
|
+
const genome = new NetworkGenome();
|
|
320
|
+
const lifecycle = new NetworkLifecycle(genome);
|
|
321
|
+
|
|
322
|
+
lifecycle.updateMetrics({
|
|
323
|
+
nodes: 50,
|
|
324
|
+
tasksCompleted: 100,
|
|
325
|
+
tasksFailed: 10,
|
|
326
|
+
creditsEarned: 1000,
|
|
327
|
+
creditsSpent: 500,
|
|
328
|
+
uptime: 86400000 * 15, // 15 days
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
const fitness = evolution.calculateFitness(lifecycle);
|
|
332
|
+
|
|
333
|
+
assert.ok(fitness.overall >= 0 && fitness.overall <= 1);
|
|
334
|
+
assert.ok(fitness.components.taskSuccess >= 0);
|
|
335
|
+
assert.ok(fitness.components.creditEfficiency >= 0);
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
it('should suggest mutations based on performance', () => {
|
|
339
|
+
const genome = new NetworkGenome();
|
|
340
|
+
const lifecycle = new NetworkLifecycle(genome);
|
|
341
|
+
|
|
342
|
+
lifecycle.updateMetrics({
|
|
343
|
+
nodes: 10,
|
|
344
|
+
tasksCompleted: 100,
|
|
345
|
+
tasksFailed: 50, // High failure rate
|
|
346
|
+
creditsEarned: 100,
|
|
347
|
+
uptime: 86400000,
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
const mutations = evolution.suggestMutations(lifecycle);
|
|
351
|
+
|
|
352
|
+
assert.ok(mutations.traits);
|
|
353
|
+
assert.ok(mutations.behaviors);
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
it('should record evolution events', () => {
|
|
357
|
+
evolution.recordEvolution('net-1', 'birth', { generation: 1 });
|
|
358
|
+
evolution.recordEvolution('net-2', 'mutation', { trait: 'resilience' });
|
|
359
|
+
|
|
360
|
+
const stats = evolution.getStats();
|
|
361
|
+
assert.strictEqual(stats.totalEvents, 2);
|
|
362
|
+
});
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
describe('GossipProtocol', () => {
|
|
366
|
+
let gossip;
|
|
367
|
+
|
|
368
|
+
beforeEach(() => {
|
|
369
|
+
gossip = new GossipProtocol('node-1', { gossipIntervalMs: 10000 });
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
afterEach(() => {
|
|
373
|
+
if (gossip.stop) gossip.stop();
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
it('should add and track peers', () => {
|
|
377
|
+
gossip.addPeer('node-2', {});
|
|
378
|
+
gossip.addPeer('node-3', {});
|
|
379
|
+
|
|
380
|
+
assert.strictEqual(gossip.peers.size, 2);
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
it('should spread rumors', () => {
|
|
384
|
+
gossip.addPeer('node-2', {});
|
|
385
|
+
|
|
386
|
+
// Use spreadRumor (the actual method name)
|
|
387
|
+
gossip.spreadRumor('test_event', { data: 1 });
|
|
388
|
+
|
|
389
|
+
assert.ok(gossip.rumors.size >= 1);
|
|
390
|
+
});
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
describe('SwarmConsensus', () => {
|
|
394
|
+
let consensus;
|
|
395
|
+
|
|
396
|
+
beforeEach(() => {
|
|
397
|
+
consensus = new SwarmConsensus('node-1');
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
it('should create proposals', () => {
|
|
401
|
+
const proposal = consensus.createProposal(
|
|
402
|
+
'prop-1',
|
|
403
|
+
'evolution',
|
|
404
|
+
{ trait: 'resilience' },
|
|
405
|
+
['voter-1', 'voter-2', 'voter-3']
|
|
406
|
+
);
|
|
407
|
+
|
|
408
|
+
assert.strictEqual(proposal.id, 'prop-1');
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
it('should collect votes and check consensus', () => {
|
|
412
|
+
consensus.createProposal(
|
|
413
|
+
'prop-1',
|
|
414
|
+
'evolution',
|
|
415
|
+
{ trait: 'resilience' },
|
|
416
|
+
['voter-1', 'voter-2', 'voter-3']
|
|
417
|
+
);
|
|
418
|
+
|
|
419
|
+
// vote() takes (proposalId, option, signature)
|
|
420
|
+
consensus.vote('prop-1', true, null);
|
|
421
|
+
|
|
422
|
+
const result = consensus.checkConsensus('prop-1');
|
|
423
|
+
assert.ok('accepted' in result || 'pending' in result || 'phase' in result);
|
|
424
|
+
});
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
describe('SelfHealing', () => {
|
|
428
|
+
let genome;
|
|
429
|
+
let lifecycle;
|
|
430
|
+
let healing;
|
|
431
|
+
|
|
432
|
+
beforeEach(() => {
|
|
433
|
+
genome = new NetworkGenome();
|
|
434
|
+
lifecycle = new NetworkLifecycle(genome);
|
|
435
|
+
healing = new SelfHealing(lifecycle, { isolationThresholdErrors: 3 });
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
it('should track errors', () => {
|
|
439
|
+
healing.reportError('component-a', new Error('Test error'));
|
|
440
|
+
|
|
441
|
+
const stats = healing.getStats();
|
|
442
|
+
assert.ok(stats.totalErrors >= 1);
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
it('should isolate failing components after threshold', () => {
|
|
446
|
+
healing.reportError('component-a', new Error('Error 1'));
|
|
447
|
+
healing.reportError('component-a', new Error('Error 2'));
|
|
448
|
+
healing.reportError('component-a', new Error('Error 3'));
|
|
449
|
+
|
|
450
|
+
const stats = healing.getStats();
|
|
451
|
+
assert.strictEqual(stats.isolatedComponents, 1);
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
it('should clear errors on recovery', () => {
|
|
455
|
+
healing.reportError('component-b', new Error('Error'));
|
|
456
|
+
healing.clearErrors('component-b');
|
|
457
|
+
|
|
458
|
+
const stats = healing.getStats();
|
|
459
|
+
// Component should no longer be tracked
|
|
460
|
+
assert.ok(!healing.isolated.has('component-b'));
|
|
461
|
+
});
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
describe('Full Genesis Lifecycle', () => {
|
|
465
|
+
it('should spawn a genesis network with rUv lineage', () => {
|
|
466
|
+
const result = genesis.spawnGenesisNetwork('TestNet-Alpha');
|
|
467
|
+
|
|
468
|
+
assert.ok(result.networkId);
|
|
469
|
+
assert.strictEqual(result.genome.generation, 1);
|
|
470
|
+
assert.ok(result.genome.lineage.includes('rUv'));
|
|
471
|
+
assert.ok(result.lineageProof);
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
it('should reproduce when conditions are met', () => {
|
|
475
|
+
const parent = genesis.spawnGenesisNetwork('ParentNet');
|
|
476
|
+
|
|
477
|
+
// Mature the parent (50 nodes, 30 days, 1000 tasks, 10000 credits + REPRODUCTION_COST)
|
|
478
|
+
const parentRecord = genesis.networks.get(parent.networkId);
|
|
479
|
+
parentRecord.lifecycle.updateMetrics({
|
|
480
|
+
nodes: 50,
|
|
481
|
+
tasksCompleted: 1000,
|
|
482
|
+
creditsEarned: 10000 + REPRODUCTION_COST + 5000,
|
|
483
|
+
uptime: 30 * 24 * 60 * 60 * 1000,
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
const child = genesis.reproduce(parent.networkId, 'ChildNet');
|
|
487
|
+
|
|
488
|
+
assert.ok(child.networkId);
|
|
489
|
+
assert.strictEqual(child.genome.generation, 2);
|
|
490
|
+
assert.strictEqual(child.parentId, parent.networkId);
|
|
491
|
+
assert.ok(child.lineageProof);
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
it('should verify lineage back to rUv', () => {
|
|
495
|
+
const g1 = genesis.spawnGenesisNetwork('Gen1');
|
|
496
|
+
|
|
497
|
+
// Mature and reproduce
|
|
498
|
+
const g1Record = genesis.networks.get(g1.networkId);
|
|
499
|
+
g1Record.lifecycle.updateMetrics({
|
|
500
|
+
nodes: 50,
|
|
501
|
+
tasksCompleted: 1000,
|
|
502
|
+
creditsEarned: 10000 + REPRODUCTION_COST * 3,
|
|
503
|
+
uptime: 30 * 24 * 60 * 60 * 1000,
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
const g2 = genesis.reproduce(g1.networkId, 'Gen2');
|
|
507
|
+
|
|
508
|
+
// Verify lineage
|
|
509
|
+
const verified = genesis.verifyLineage(g2.networkId);
|
|
510
|
+
assert.strictEqual(verified, true);
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
it('should get ecosystem health', () => {
|
|
514
|
+
genesis.spawnGenesisNetwork('Net1');
|
|
515
|
+
genesis.spawnGenesisNetwork('Net2');
|
|
516
|
+
genesis.spawnGenesisNetwork('Net3');
|
|
517
|
+
|
|
518
|
+
const health = genesis.getEcosystemHealth();
|
|
519
|
+
|
|
520
|
+
assert.ok('averageHealth' in health);
|
|
521
|
+
assert.strictEqual(health.networkCount, 3);
|
|
522
|
+
assert.ok(health.lineageIntegrity);
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
it('should get comprehensive stats', () => {
|
|
526
|
+
genesis.spawnGenesisNetwork('StatNet');
|
|
527
|
+
|
|
528
|
+
const stats = genesis.getStats();
|
|
529
|
+
|
|
530
|
+
assert.strictEqual(stats.totalNetworksSpawned, 1);
|
|
531
|
+
assert.strictEqual(stats.activeNetworks, 1);
|
|
532
|
+
assert.ok(stats.collectiveMemory);
|
|
533
|
+
assert.ok(stats.evolution);
|
|
534
|
+
});
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
describe('Federation Features', () => {
|
|
538
|
+
it('should create gossip network for discovery', () => {
|
|
539
|
+
const gossip = genesis.createGossipNetwork();
|
|
540
|
+
assert.ok(gossip);
|
|
541
|
+
assert.ok(gossip instanceof GossipProtocol);
|
|
542
|
+
if (gossip.stop) gossip.stop();
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
it('should create consensus for collective decisions', () => {
|
|
546
|
+
const consensus = genesis.createConsensus();
|
|
547
|
+
assert.ok(consensus);
|
|
548
|
+
assert.ok(consensus instanceof SwarmConsensus);
|
|
549
|
+
});
|
|
550
|
+
|
|
551
|
+
it('should create self-healing for networks', () => {
|
|
552
|
+
const net = genesis.spawnGenesisNetwork('HealNet');
|
|
553
|
+
const healing = genesis.createSelfHealing(net.networkId);
|
|
554
|
+
|
|
555
|
+
assert.ok(healing);
|
|
556
|
+
assert.ok(healing instanceof SelfHealing);
|
|
557
|
+
});
|
|
558
|
+
});
|
|
559
|
+
});
|
|
560
|
+
|
|
561
|
+
console.log('Network Genesis Test Suite loaded');
|
|
562
|
+
console.log('Run with: node --test tests/network-genesis.test.js');
|