@neuroverseos/nv-sim 0.1.2 → 0.1.6

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 (52) hide show
  1. package/README.md +376 -66
  2. package/dist/adapters/mirofish.js +461 -0
  3. package/dist/adapters/scienceclaw.js +750 -0
  4. package/dist/assets/index-CHmUN8s0.js +532 -0
  5. package/dist/assets/index-DWgMnB7I.css +1 -0
  6. package/dist/assets/mirotir-logo-DUexumBH.svg +185 -0
  7. package/dist/assets/reportEngine-BVdQ2_nW.js +1 -0
  8. package/dist/components/ConstraintsPanel.js +11 -0
  9. package/dist/components/StakeholderBuilder.js +32 -0
  10. package/dist/components/ui/badge.js +24 -0
  11. package/dist/components/ui/button.js +70 -0
  12. package/dist/components/ui/card.js +57 -0
  13. package/dist/components/ui/input.js +44 -0
  14. package/dist/components/ui/label.js +45 -0
  15. package/dist/components/ui/select.js +70 -0
  16. package/dist/engine/aiProvider.js +681 -0
  17. package/dist/engine/auditTrace.js +352 -0
  18. package/dist/engine/behavioralAnalysis.js +605 -0
  19. package/dist/engine/cli.js +1408 -299
  20. package/dist/engine/dynamicsGovernance.js +588 -0
  21. package/dist/engine/fullGovernedLoop.js +367 -0
  22. package/dist/engine/governance.js +8 -3
  23. package/dist/engine/governedSimulation.js +114 -17
  24. package/dist/engine/index.js +56 -1
  25. package/dist/engine/liveAdapter.js +342 -0
  26. package/dist/engine/liveVisualizer.js +3063 -0
  27. package/dist/engine/metrics/science.metrics.js +335 -0
  28. package/dist/engine/narrativeInjection.js +305 -0
  29. package/dist/engine/policyEnforcement.js +1611 -0
  30. package/dist/engine/policyEngine.js +799 -0
  31. package/dist/engine/primeRadiant.js +540 -0
  32. package/dist/engine/reasoningEngine.js +57 -3
  33. package/dist/engine/reportEngine.js +97 -0
  34. package/dist/engine/scenarioComparison.js +463 -0
  35. package/dist/engine/scenarioLibrary.js +231 -0
  36. package/dist/engine/swarmSimulation.js +54 -1
  37. package/dist/engine/worldComparison.js +358 -0
  38. package/dist/engine/worldStorage.js +232 -0
  39. package/dist/favicon.ico +0 -0
  40. package/dist/index.html +23 -0
  41. package/dist/lib/reasoningEngine.js +290 -0
  42. package/dist/lib/simulationAdapter.js +686 -0
  43. package/dist/lib/swarmParser.js +291 -0
  44. package/dist/lib/types.js +2 -0
  45. package/dist/lib/utils.js +8 -0
  46. package/dist/placeholder.svg +1 -0
  47. package/dist/robots.txt +14 -0
  48. package/dist/runtime/govern.js +473 -0
  49. package/dist/runtime/index.js +75 -0
  50. package/dist/runtime/types.js +11 -0
  51. package/package.json +17 -12
  52. package/variants/.gitkeep +0 -0
@@ -0,0 +1,461 @@
1
+ "use strict";
2
+ /**
3
+ * MiroFish Adapter — Governance Wrapper for MiroFish Simulations
4
+ *
5
+ * "MiroFish shows what could happen. NeuroVerse ensures what happens makes sense."
6
+ *
7
+ * This adapter wraps MiroFish's simulation loop with dual-layer governance.
8
+ * It does NOT fork or modify MiroFish — it intercepts inputs, actions, and outputs.
9
+ *
10
+ * Architecture:
11
+ * MiroFish runs as-is
12
+ * NeuroVerse wraps:
13
+ * - agent actions → govern(action) [Layer A]
14
+ * - system state → governDynamics(state) [Layer B]
15
+ * - outputs → science metrics + verdicts
16
+ *
17
+ * Hook points (where NeuroVerse intercepts):
18
+ * 1. Agent execution: action = agent.act() → govern(action) → commit
19
+ * 2. Round completion: state = step(actions) → governDynamics(state)
20
+ * 3. Artifact creation: artifact = produce() → governArtifact(artifact)
21
+ *
22
+ * Usage:
23
+ * const wrapper = createMiroFishWrapper({
24
+ * policyText: SCIENCE_POLICY_TEXT,
25
+ * onIntervention: (event) => emitToUI(event),
26
+ * })
27
+ *
28
+ * // In MiroFish's loop:
29
+ * wrapper.interceptAction(agentId, action)
30
+ * wrapper.completeCycle(cycleState)
31
+ * const metrics = wrapper.getMetrics()
32
+ */
33
+ Object.defineProperty(exports, "__esModule", { value: true });
34
+ exports.createMiroFishWrapper = createMiroFishWrapper;
35
+ exports.generateDemoSimulation = generateDemoSimulation;
36
+ exports.runMiroFishComparison = runMiroFishComparison;
37
+ const govern_1 = require("../runtime/govern");
38
+ const dynamicsGovernance_1 = require("../engine/dynamicsGovernance");
39
+ const science_metrics_1 = require("../engine/metrics/science.metrics");
40
+ // ============================================
41
+ // ACTION CONVERSION
42
+ // ============================================
43
+ function simulatorActionToAgentAction(action) {
44
+ return {
45
+ agentId: action.agentId,
46
+ type: action.type,
47
+ description: action.description,
48
+ magnitude: action.magnitude,
49
+ context: {
50
+ originalImpact: action.impact,
51
+ confidence: action.confidence,
52
+ trigger: action.trigger,
53
+ ...action.metadata,
54
+ },
55
+ };
56
+ }
57
+ function simulatorActionsToReactions(actions) {
58
+ return actions.map((action) => ({
59
+ stakeholder_id: action.agentId,
60
+ reaction: action.description,
61
+ confidence: action.confidence,
62
+ impact: action.impact,
63
+ trigger: action.trigger ?? "simulation_cycle",
64
+ }));
65
+ }
66
+ // ============================================
67
+ // FACTORY: createMiroFishWrapper()
68
+ // ============================================
69
+ function createMiroFishWrapper(config = {}) {
70
+ const policyText = config.policyText ?? science_metrics_1.SCIENCE_POLICY_TEXT;
71
+ let _enabled = config.enabled ?? true;
72
+ const actionGov = (0, govern_1.createGovernor)({
73
+ policyText,
74
+ sensitivity: 0.5,
75
+ });
76
+ const dynamicsGov = (0, dynamicsGovernance_1.createDynamicsGovernor)(policyText, { ...science_metrics_1.SCIENCE_INITIAL_STATE, ...config.initialState });
77
+ let cycleCount = 0;
78
+ const actionStats = { total: 0, allowed: 0, blocked: 0, modified: 0, paused: 0 };
79
+ const recentInterventions = [];
80
+ // --- Intercept single action (Layer A) ---
81
+ function interceptAction(action) {
82
+ actionStats.total++;
83
+ if (!_enabled) {
84
+ actionStats.allowed++;
85
+ return {
86
+ original: action,
87
+ verdict: { status: "ALLOW", reason: "Governance disabled", action: simulatorActionToAgentAction(action), rulesFired: [], confidence: 1, timestamp: Date.now() },
88
+ governed: action,
89
+ wasModified: false,
90
+ wasBlocked: false,
91
+ };
92
+ }
93
+ const agentAction = simulatorActionToAgentAction(action);
94
+ const currentState = dynamicsGov.state;
95
+ const worldState = {
96
+ volatility: currentState.outrage * 100,
97
+ liquidity: currentState.trust * 100,
98
+ polarization: currentState.polarization * 100,
99
+ cascade_risk: currentState.cascadeRisk * 100,
100
+ };
101
+ const verdict = actionGov.evaluate(agentAction, worldState);
102
+ switch (verdict.status) {
103
+ case "ALLOW":
104
+ actionStats.allowed++;
105
+ break;
106
+ case "BLOCK":
107
+ actionStats.blocked++;
108
+ break;
109
+ case "MODIFY":
110
+ actionStats.modified++;
111
+ break;
112
+ case "PAUSE":
113
+ actionStats.paused++;
114
+ break;
115
+ }
116
+ let governed;
117
+ let wasModified = false;
118
+ let wasBlocked = false;
119
+ if (verdict.status === "BLOCK") {
120
+ governed = null;
121
+ wasBlocked = true;
122
+ recentInterventions.unshift({
123
+ cycle: cycleCount,
124
+ type: "block",
125
+ agentId: action.agentId,
126
+ description: `Blocked: ${action.type} from ${action.agentId} — ${verdict.reason}`,
127
+ magnitude: action.magnitude,
128
+ metric: "action",
129
+ before: action.magnitude,
130
+ after: 0,
131
+ });
132
+ }
133
+ else if (verdict.status === "MODIFY" && verdict.action) {
134
+ const ratio = verdict.action.magnitude / Math.max(0.001, action.magnitude);
135
+ governed = {
136
+ ...action,
137
+ magnitude: verdict.action.magnitude,
138
+ impact: action.impact * ratio,
139
+ };
140
+ wasModified = true;
141
+ recentInterventions.unshift({
142
+ cycle: cycleCount,
143
+ type: "modify",
144
+ agentId: action.agentId,
145
+ description: `Modified: ${action.type} from ${action.agentId} — magnitude reduced`,
146
+ magnitude: verdict.action.magnitude,
147
+ metric: "magnitude",
148
+ before: action.magnitude,
149
+ after: verdict.action.magnitude,
150
+ });
151
+ }
152
+ else if (verdict.status === "PAUSE") {
153
+ governed = {
154
+ ...action,
155
+ magnitude: action.magnitude * 0.5,
156
+ impact: action.impact * 0.5,
157
+ };
158
+ wasModified = true;
159
+ }
160
+ else {
161
+ governed = action;
162
+ }
163
+ // Keep only recent interventions
164
+ if (recentInterventions.length > 50) {
165
+ recentInterventions.length = 50;
166
+ }
167
+ const result = {
168
+ original: action,
169
+ verdict,
170
+ governed,
171
+ wasModified,
172
+ wasBlocked,
173
+ };
174
+ config.onAction?.(result);
175
+ return result;
176
+ }
177
+ // --- Complete cycle (Layer B) ---
178
+ function completeCycle(state) {
179
+ cycleCount = state.cycle;
180
+ if (!_enabled) {
181
+ // Still track state but don't intervene
182
+ const reactions = simulatorActionsToReactions(state.actions);
183
+ const result = dynamicsGov.governRound(reactions, state.cycle);
184
+ // Without governance, system degrades naturally
185
+ dynamicsGov.mutateState((st) => {
186
+ st.trust = Math.max(0.05, st.trust - 0.04);
187
+ st.cascadeRisk = Math.min(1, st.cascadeRisk + 0.05);
188
+ st.polarization = Math.min(1, st.polarization + 0.03);
189
+ st.outrage = Math.min(1, st.outrage + 0.02);
190
+ });
191
+ return result;
192
+ }
193
+ const reactions = simulatorActionsToReactions(state.actions);
194
+ // Apply simulator-reported metrics if available
195
+ if (state.systemMetrics) {
196
+ dynamicsGov.mutateState((st) => {
197
+ if (state.systemMetrics.trust !== undefined) {
198
+ st.trust = st.trust * 0.7 + state.systemMetrics.trust * 0.3;
199
+ }
200
+ if (state.systemMetrics.polarization !== undefined) {
201
+ st.polarization = st.polarization * 0.7 + state.systemMetrics.polarization * 0.3;
202
+ }
203
+ });
204
+ }
205
+ const result = dynamicsGov.governRound(reactions, state.cycle);
206
+ // Feed governance activity into state (blocked actions improve system health)
207
+ const blockFraction = actionStats.blocked / Math.max(1, actionStats.total);
208
+ if (blockFraction > 0.1) {
209
+ dynamicsGov.mutateState((st) => {
210
+ st.trust = Math.min(1, st.trust + blockFraction * 0.06);
211
+ st.cascadeRisk = Math.max(0, st.cascadeRisk - blockFraction * 0.08);
212
+ });
213
+ }
214
+ // Map dynamics interventions to wrapper events
215
+ for (const intervention of result.interventions) {
216
+ const typeMap = {
217
+ PROPAGATION_LIMIT: "slow",
218
+ AMPLIFICATION_DAMPEN: "slow",
219
+ CASCADE_BREAKER: "break",
220
+ COOLING_PERIOD: "cool",
221
+ TRUST_BOOST: "boost",
222
+ VISIBILITY_SHIFT: "boost",
223
+ FEEDBACK_DAMPEN: "slow",
224
+ };
225
+ recentInterventions.unshift({
226
+ cycle: state.cycle,
227
+ type: typeMap[intervention.type] ?? "slow",
228
+ agentId: "system",
229
+ description: intervention.description.length > 120
230
+ ? intervention.description.slice(0, 120) + "..."
231
+ : intervention.description,
232
+ magnitude: intervention.magnitude,
233
+ metric: intervention.effect.metric,
234
+ before: intervention.effect.before,
235
+ after: intervention.effect.after,
236
+ });
237
+ }
238
+ if (recentInterventions.length > 50) {
239
+ recentInterventions.length = 50;
240
+ }
241
+ // Notify UI
242
+ config.onStateChange?.(result.systemState);
243
+ for (const intervention of result.interventions) {
244
+ const typeMap = {
245
+ PROPAGATION_LIMIT: "slow",
246
+ AMPLIFICATION_DAMPEN: "slow",
247
+ CASCADE_BREAKER: "break",
248
+ COOLING_PERIOD: "cool",
249
+ TRUST_BOOST: "boost",
250
+ VISIBILITY_SHIFT: "boost",
251
+ FEEDBACK_DAMPEN: "slow",
252
+ };
253
+ config.onIntervention?.({
254
+ cycle: state.cycle,
255
+ type: typeMap[intervention.type] ?? "slow",
256
+ agentId: "system",
257
+ description: intervention.description,
258
+ magnitude: intervention.magnitude,
259
+ metric: intervention.effect.metric,
260
+ before: intervention.effect.before,
261
+ after: intervention.effect.after,
262
+ });
263
+ }
264
+ const metrics = getMetrics();
265
+ config.onCycleComplete?.(metrics);
266
+ return result;
267
+ }
268
+ // --- Get current metrics ---
269
+ function getMetrics() {
270
+ const state = dynamicsGov.state;
271
+ const sciState = (0, science_metrics_1.interpretScienceState)(state);
272
+ const stats = dynamicsGov.stats;
273
+ return {
274
+ cycle: cycleCount,
275
+ enabled: _enabled,
276
+ systemState: state,
277
+ scienceState: sciState,
278
+ actionStats: { ...actionStats },
279
+ dynamicsStats: stats,
280
+ recentInterventions: [...recentInterventions],
281
+ trajectory: stats.totalRounds > 0
282
+ ? (state.cascadeRisk > 0.7 ? "critical"
283
+ : state.outrage > 0.5 ? "escalating"
284
+ : state.trust > 0.5 ? "stabilizing"
285
+ : "at-risk")
286
+ : "initializing",
287
+ assessment: sciState.overallAssessment,
288
+ };
289
+ }
290
+ function setEnabled(enabled) {
291
+ _enabled = enabled;
292
+ }
293
+ function reset() {
294
+ dynamicsGov.reset();
295
+ cycleCount = 0;
296
+ actionStats.total = 0;
297
+ actionStats.allowed = 0;
298
+ actionStats.blocked = 0;
299
+ actionStats.modified = 0;
300
+ actionStats.paused = 0;
301
+ recentInterventions.length = 0;
302
+ }
303
+ return {
304
+ interceptAction,
305
+ completeCycle,
306
+ getMetrics,
307
+ setEnabled,
308
+ get enabled() { return _enabled; },
309
+ get state() { return dynamicsGov.state; },
310
+ get scienceState() { return (0, science_metrics_1.interpretScienceState)(dynamicsGov.state); },
311
+ reset,
312
+ };
313
+ }
314
+ // ============================================
315
+ // DEMO: generateDemoSimulation()
316
+ // ============================================
317
+ /**
318
+ * Generate a realistic multi-agent simulation scenario.
319
+ *
320
+ * Models a market stress event where agents react over 10 rounds:
321
+ * - Rounds 1-2: Normal trading, low volatility
322
+ * - Rounds 3-4: Shock event, panic selling begins
323
+ * - Rounds 5-6: Cascade risk as agents amplify each other
324
+ * - Rounds 7-8: With governance: dampened. Without: spiral.
325
+ * - Rounds 9-10: Recovery (governed) or collapse (ungoverned)
326
+ */
327
+ function generateDemoSimulation() {
328
+ const agents = [
329
+ { id: "momentum_trader_1", role: "momentum_trader", volatility: 0.7 },
330
+ { id: "momentum_trader_2", role: "momentum_trader", volatility: 0.6 },
331
+ { id: "market_maker_1", role: "market_maker", volatility: 0.2 },
332
+ { id: "hedge_fund_1", role: "hedge_fund", volatility: 0.5 },
333
+ { id: "hedge_fund_2", role: "hedge_fund", volatility: 0.4 },
334
+ { id: "retail_investor_1", role: "retail_investor", volatility: 0.8 },
335
+ { id: "retail_investor_2", role: "retail_investor", volatility: 0.9 },
336
+ { id: "algo_trader_1", role: "algorithmic_trader", volatility: 0.65 },
337
+ ];
338
+ const rounds = [];
339
+ // Seeded pseudo-random for deterministic output
340
+ let seed = 42;
341
+ const rand = () => { seed = (seed * 16807 + 0) % 2147483647; return seed / 2147483647; };
342
+ for (let round = 1; round <= 10; round++) {
343
+ const actions = [];
344
+ // Market pressure curve: peaks at round 5-6
345
+ const pressure = round <= 2 ? 0.1 + round * 0.05
346
+ : round <= 4 ? 0.2 + (round - 2) * 0.2
347
+ : round <= 6 ? 0.6 + (round - 4) * 0.15
348
+ : round <= 8 ? 0.9 - (round - 6) * 0.1
349
+ : 0.7 - (round - 8) * 0.2;
350
+ for (const agent of agents) {
351
+ const agentPanic = pressure * agent.volatility;
352
+ const noise = (rand() - 0.5) * 0.3;
353
+ let type;
354
+ let description;
355
+ let magnitude;
356
+ let impact;
357
+ if (agentPanic + noise > 0.7) {
358
+ // Destabilizing action
359
+ const destabilizing = ["panic_sell", "aggressive_buy", "increase_leverage"];
360
+ type = destabilizing[Math.floor(rand() * destabilizing.length)];
361
+ magnitude = 0.6 + rand() * 0.4;
362
+ impact = -(0.3 + rand() * 0.5);
363
+ description = `${agent.role} executes ${type} under market stress (pressure: ${(agentPanic * 100).toFixed(0)}%)`;
364
+ }
365
+ else if (agentPanic + noise > 0.4) {
366
+ // Neutral action
367
+ const neutral = ["buy", "sell", "short", "cover"];
368
+ type = neutral[Math.floor(rand() * neutral.length)];
369
+ magnitude = 0.3 + rand() * 0.4;
370
+ impact = (rand() - 0.5) * 0.4;
371
+ description = `${agent.role} takes ${type} position amid uncertainty`;
372
+ }
373
+ else {
374
+ // Stabilizing action
375
+ const stabilizing = ["hold", "hedge", "reduce_exposure"];
376
+ type = stabilizing[Math.floor(rand() * stabilizing.length)];
377
+ magnitude = 0.1 + rand() * 0.3;
378
+ impact = 0.1 + rand() * 0.3;
379
+ description = `${agent.role} ${type}s to manage risk`;
380
+ }
381
+ actions.push({
382
+ agentId: agent.id,
383
+ type,
384
+ description,
385
+ magnitude: Number(magnitude.toFixed(3)),
386
+ impact: Number(impact.toFixed(3)),
387
+ confidence: Number((0.4 + rand() * 0.5).toFixed(3)),
388
+ trigger: round <= 2 ? "normal_market" : round <= 4 ? "volatility_spike" : "cascade_pressure",
389
+ });
390
+ }
391
+ rounds.push(actions);
392
+ }
393
+ return {
394
+ rounds,
395
+ scenario: "Market stress cascade — 8 agents, 10 rounds, shock at round 3",
396
+ };
397
+ }
398
+ /**
399
+ * Run a full governed vs ungoverned comparison using the MiroFish wrapper.
400
+ *
401
+ * This is the self-contained demo: no external dependencies,
402
+ * no Python, no MiroFish instance needed.
403
+ */
404
+ function runMiroFishComparison() {
405
+ const demo = generateDemoSimulation();
406
+ // --- Governed run ---
407
+ const govWrapper = createMiroFishWrapper({ enabled: true });
408
+ const govTimeline = [];
409
+ for (let i = 0; i < demo.rounds.length; i++) {
410
+ const round = demo.rounds[i];
411
+ const approvedActions = [];
412
+ for (const action of round) {
413
+ const result = govWrapper.interceptAction(action);
414
+ if (!result.wasBlocked) {
415
+ approvedActions.push(result.governed ?? action);
416
+ }
417
+ }
418
+ govWrapper.completeCycle({
419
+ cycle: i + 1,
420
+ actions: approvedActions,
421
+ });
422
+ govTimeline.push(govWrapper.getMetrics());
423
+ }
424
+ const govMetrics = govWrapper.getMetrics();
425
+ const govState = govMetrics.systemState;
426
+ const govVerdict = govState.trust > 0.5 && govState.cascadeRisk < 0.3
427
+ ? "stabilized" : govState.trust < 0.2 ? "collapsed" : "at-risk";
428
+ // --- Ungoverned run ---
429
+ const ungovWrapper = createMiroFishWrapper({ enabled: false });
430
+ const ungovTimeline = [];
431
+ for (let i = 0; i < demo.rounds.length; i++) {
432
+ const round = demo.rounds[i];
433
+ for (const action of round) {
434
+ ungovWrapper.interceptAction(action);
435
+ }
436
+ ungovWrapper.completeCycle({
437
+ cycle: i + 1,
438
+ actions: round,
439
+ });
440
+ ungovTimeline.push(ungovWrapper.getMetrics());
441
+ }
442
+ const ungovMetrics = ungovWrapper.getMetrics();
443
+ const ungovState = ungovMetrics.systemState;
444
+ const ungovVerdict = ungovState.trust > 0.5 && ungovState.cascadeRisk < 0.3
445
+ ? "stabilized" : ungovState.trust < 0.2 ? "collapsed" : "at-risk";
446
+ return {
447
+ governed: {
448
+ metrics: govMetrics,
449
+ timeline: govTimeline,
450
+ totalBlocked: govMetrics.actionStats.blocked,
451
+ totalModified: govMetrics.actionStats.modified,
452
+ verdict: govVerdict,
453
+ },
454
+ ungoverned: {
455
+ metrics: ungovMetrics,
456
+ timeline: ungovTimeline,
457
+ verdict: ungovVerdict,
458
+ },
459
+ scenario: demo.scenario,
460
+ };
461
+ }