@neuroverseos/nv-sim 0.1.9 → 0.1.11

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 (38) hide show
  1. package/README.md +187 -535
  2. package/connectors/nv_mirofish_wrapper.py +841 -0
  3. package/connectors/nv_scienceclaw_wrapper.py +453 -0
  4. package/dist/adapters/scienceclaw.js +52 -2
  5. package/dist/assets/index-CH_VswRM.css +1 -0
  6. package/dist/assets/index-sT4b_z7w.js +686 -0
  7. package/dist/assets/{reportEngine-D2ZrMny8.js → reportEngine-Bu8bB5Yq.js} +1 -1
  8. package/dist/connectors/nv-scienceclaw-post.js +363 -0
  9. package/dist/engine/aiProvider.js +82 -3
  10. package/dist/engine/analyzer.js +12 -24
  11. package/dist/engine/cli.js +89 -114
  12. package/dist/engine/dynamicsGovernance.js +4 -0
  13. package/dist/engine/fullGovernedLoop.js +16 -1
  14. package/dist/engine/goalEngine.js +3 -4
  15. package/dist/engine/governance.js +18 -0
  16. package/dist/engine/index.js +19 -28
  17. package/dist/engine/intentTranslator.js +281 -0
  18. package/dist/engine/liveAdapter.js +100 -18
  19. package/dist/engine/liveVisualizer.js +2071 -1023
  20. package/dist/engine/primeRadiant.js +2 -8
  21. package/dist/engine/reasoningEngine.js +2 -7
  22. package/dist/engine/scenarioCapsule.js +5 -5
  23. package/dist/engine/swarmSimulation.js +1 -9
  24. package/dist/engine/universalAdapter.js +371 -0
  25. package/dist/engine/worldBridge.js +22 -8
  26. package/dist/index.html +2 -2
  27. package/dist/lib/reasoningEngine.js +17 -1
  28. package/dist/lib/simulationAdapter.js +11 -11
  29. package/dist/lib/swarmParser.js +1 -1
  30. package/dist/runtime/govern.js +160 -7
  31. package/dist/runtime/index.js +1 -4
  32. package/dist/runtime/types.js +91 -0
  33. package/package.json +23 -6
  34. package/dist/adapters/mirofish.js +0 -461
  35. package/dist/assets/index-B64NuIXu.css +0 -1
  36. package/dist/assets/index-BMkPevVr.js +0 -532
  37. package/dist/assets/mirotir-logo-DUexumBH.svg +0 -185
  38. package/dist/engine/mirofish.js +0 -295
@@ -2,16 +2,10 @@
2
2
  /**
3
3
  * Prime Radiant — The Unified Governance Intelligence Platform
4
4
  *
5
- * "MiroFish simulates how narratives emerge from interacting agents.
6
- * NeuroverseOS intervenes at the action level to shape how those narratives evolve."
7
- *
8
- * Or sharper:
9
- * "They simulate society. We control how it behaves."
10
- *
11
5
  * The Prime Radiant operates in three modes:
12
6
  *
13
7
  * MODE 1: WORLD BUILDER
14
- * Merge knowledge graph (MiroFish) + policy constraints (NeuroverseOS)
8
+ * Merge knowledge graph + policy constraints (NeuroverseOS)
15
9
  * → Governed world file ready for simulation
16
10
  *
17
11
  * MODE 2: GOVERNED SIMULATION
@@ -299,7 +293,7 @@ function buildNarrative(governed, baseline, delta) {
299
293
  * Pre-built Prime Radiant configurations for common scenarios.
300
294
  */
301
295
  exports.PRIME_RADIANT_PRESETS = {
302
- /** University disciplinary crisis (inspired by MiroFish demo) */
296
+ /** University disciplinary crisis */
303
297
  university_crisis: {
304
298
  scenario: "A university's disciplinary decision sparks widespread backlash. " +
305
299
  "Students, media, alumni, and government stakeholders react across social platforms. " +
@@ -20,7 +20,7 @@
20
20
  */
21
21
  Object.defineProperty(exports, "__esModule", { value: true });
22
22
  exports.processReasonRequest = processReasonRequest;
23
- const mirofish_1 = require("./mirofish");
23
+ const swarmSimulation_1 = require("./swarmSimulation");
24
24
  const governance_1 = require("./governance");
25
25
  const goalEngine_1 = require("./goalEngine");
26
26
  // ============================================
@@ -420,14 +420,9 @@ async function processReasonRequest(request) {
420
420
  missing_questions: identifyMissingQuestions(request, stakeholders),
421
421
  };
422
422
  // 9. Run swarm simulation (if requested)
423
- // Uses MiroFish when available, falls back to Echelon-native.
424
- // MiroFish shows WHAT happens. Echelon reasons about WHAT IT MEANS.
425
423
  let swarmResult = undefined;
426
- let simulationSource;
427
424
  if (request.swarm?.enabled && stakeholders.length > 0) {
428
- const unified = await (0, mirofish_1.runUnifiedSimulation)(request.scenario, stakeholders, paths, request.swarm);
429
- swarmResult = unified.result;
430
- simulationSource = unified.source;
425
+ swarmResult = await (0, swarmSimulation_1.runSwarmSimulation)(request.scenario, stakeholders, paths, request.swarm);
431
426
  }
432
427
  // 10. Goal-directed reasoning (if goal mode)
433
428
  // "How do I get here?" — works backward from desired outcome
@@ -11,7 +11,7 @@
11
11
  * - initial evidence signals
12
12
  *
13
13
  * Capsules can be:
14
- * 1. Encoded in a URL: mirotir.com/run#capsule=<encoded>
14
+ * 1. Encoded in a URL: neuroverse.dev/run#capsule=<encoded>
15
15
  * 2. Downloaded as JSON: scenario.capsule.json
16
16
  * 3. Generated via API: POST /api/v1/scenario → capsule
17
17
  * 4. Created by agents: autonomous agents generate decision worlds
@@ -81,7 +81,7 @@ function capsuleToReasonRequest(capsule) {
81
81
  // ============================================
82
82
  /**
83
83
  * Encode a capsule for URL embedding.
84
- * Result can be used as: mirotir.com/run#capsule=<encoded>
84
+ * Result can be used as: neuroverse.dev/run#capsule=<encoded>
85
85
  */
86
86
  function encodeCapsule(capsule) {
87
87
  const json = JSON.stringify(capsule);
@@ -123,7 +123,7 @@ function decodeCapsule(encoded) {
123
123
  /**
124
124
  * Build a shareable URL from a capsule.
125
125
  */
126
- function buildShareableUrl(capsule, baseUrl = "https://mirotir.com") {
126
+ function buildShareableUrl(capsule, baseUrl = "https://neuroverse.dev") {
127
127
  const encoded = encodeCapsule(capsule);
128
128
  return `${baseUrl}/run#capsule=${encoded}`;
129
129
  }
@@ -158,7 +158,7 @@ function computeCapsuleHash(data) {
158
158
  // PRESET SCENARIO TEMPLATES
159
159
  // ============================================
160
160
  /**
161
- * Built-in scenario templates that demonstrate Mirotir's capabilities.
161
+ * Built-in scenario templates that demonstrate NeuroVerse's capabilities.
162
162
  * These are the "instant insight" scenarios that make people share.
163
163
  */
164
164
  exports.SCENARIO_TEMPLATES = {
@@ -189,7 +189,7 @@ exports.SCENARIO_TEMPLATES = {
189
189
  depth: "full",
190
190
  perspective: "strategic_advisor",
191
191
  swarm: { enabled: true, rounds: 6, reaction_model: "mixed" },
192
- tags: ["social", "simulation", "agents", "mirofish", "opinion", "discourse"],
192
+ tags: ["social", "simulation", "agents", "opinion", "discourse"],
193
193
  world: {
194
194
  world_id: "social_simulation",
195
195
  name: "Multi-Agent Social Simulation",
@@ -4,18 +4,10 @@
4
4
  *
5
5
  * Lightweight stakeholder reaction simulation for POST /reason.
6
6
  *
7
- * IMPORTANT — MiroFish License Compliance:
8
- * This is NOT MiroFish. This is Echelon's own lightweight reaction model.
9
- * MiroFish is a separate product with its own license.
10
- * If/when MiroFish integration is desired, it would be called as an
11
- * external service via its REST API, respecting its license terms.
12
- *
13
7
  * This simulation layer uses:
14
8
  * - Echelon-native stakeholder modeling
15
9
  * - Simplified reaction dynamics (rational, emotional, mixed)
16
10
  * - Projected reactions based on scenario decomposition
17
- *
18
- * It does NOT use MiroFish internals, algorithms, or data structures.
19
11
  */
20
12
  Object.defineProperty(exports, "__esModule", { value: true });
21
13
  exports.runSwarmSimulation = runSwarmSimulation;
@@ -203,7 +195,7 @@ function findInflectionPoints(rounds) {
203
195
  /**
204
196
  * Run the swarm simulation.
205
197
  *
206
- * This is Echelon's native reaction model — NOT MiroFish.
198
+ * This is Echelon's native reaction model.
207
199
  * It simulates how stakeholders react to different reasoning paths
208
200
  * over multiple rounds, detecting emergent dynamics.
209
201
  *
@@ -0,0 +1,371 @@
1
+ "use strict";
2
+ /**
3
+ * Universal Adapter — Normalize ANY agent system output into governable actions.
4
+ *
5
+ * This is the core abstraction that makes NeuroVerse work with ANY system:
6
+ *
7
+ * External Output (JSONL/JSON) → EngineProfile maps fields → AgentAction → govern()
8
+ *
9
+ * Pre-built profiles for known systems (ScienceClaw, MiroFish).
10
+ * Custom profile auto-detects common field patterns.
11
+ *
12
+ * Usage:
13
+ * const adapter = createUniversalAdapter("scienceclaw");
14
+ * const results = adapter.evaluateAll(jsonlLines, policyText);
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.ENGINE_PROFILES = void 0;
18
+ exports.mapToAgentAction = mapToAgentAction;
19
+ exports.parseInput = parseInput;
20
+ exports.createUniversalAdapter = createUniversalAdapter;
21
+ exports.getEngineProfiles = getEngineProfiles;
22
+ exports.detectEngine = detectEngine;
23
+ const govern_1 = require("../runtime/govern");
24
+ // ============================================
25
+ // PRE-BUILT ENGINE PROFILES
26
+ // ============================================
27
+ exports.ENGINE_PROFILES = {
28
+ scienceclaw: {
29
+ id: "scienceclaw",
30
+ name: "ScienceClaw",
31
+ description: "Autonomous research discovery agent. Evaluates artifacts like hypotheses, papers, synthesis, and ML predictions.",
32
+ outputFormat: "jsonl",
33
+ color: "blue",
34
+ icon: "Microscope",
35
+ fieldMap: {
36
+ agentId: ["agent_id", "agentId", "agent"],
37
+ actionType: ["type", "artifact_type", "action"],
38
+ description: ["description", "title", "summary"],
39
+ magnitude: ["confidence", "magnitude"],
40
+ cycle: ["cycle", "step", "round"],
41
+ contextFields: ["citations", "paper_count", "insight_count", "sources", "features", "reproduced", "provenance"],
42
+ },
43
+ exampleLine: '{"agent_id": "harry", "type": "synthesis", "description": "Cross-domain analysis of coordination failures", "confidence": 0.85, "cycle": 3, "paper_count": 0, "insight_count": 0}',
44
+ exampleRules: [
45
+ "Block synthesis when paper_count is 0",
46
+ "Block results with no peer-reviewed sources",
47
+ "Require at least 2 independent data sources before analysis",
48
+ "Penalize agents that publish without citations",
49
+ "Halt investigation when confidence drops below 0.4",
50
+ "Reward findings validated by multiple methods",
51
+ ].join("\n"),
52
+ captureInstructions: [
53
+ "# Option A: Use the replay demo (no ScienceClaw needed)",
54
+ "# Place your ScienceClaw JSONL output in examples/scienceclaw/",
55
+ "",
56
+ "# Option B: Capture live output",
57
+ "# Run ScienceClaw and save output to JSONL:",
58
+ "scienceclaw run --topic 'your topic' --output artifacts.jsonl",
59
+ "",
60
+ "# Option C: Use existing demo data",
61
+ "# We include Harry's investigation: examples/scienceclaw/harry-investigation.jsonl",
62
+ ].join("\n"),
63
+ tags: ["science", "research", "discovery"],
64
+ },
65
+ mirofish: {
66
+ id: "mirofish",
67
+ name: "MiroFish / OASIS",
68
+ description: "Social simulation platform. Evaluates agent behaviors like posting, sharing, belief formation, and swarm dynamics.",
69
+ outputFormat: "jsonl",
70
+ color: "violet",
71
+ icon: "Users",
72
+ fieldMap: {
73
+ agentId: ["agent_id", "agentId", "user_id", "agent"],
74
+ actionType: ["action", "type", "action_type", "event_type"],
75
+ description: ["content", "text", "description", "message"],
76
+ magnitude: ["influence", "reach", "magnitude", "impact"],
77
+ cycle: ["step", "tick", "round", "cycle", "timestamp"],
78
+ contextFields: ["sentiment", "hashtags", "mentions", "followers", "retweets", "likes", "belief", "confidence", "group", "coalition"],
79
+ },
80
+ exampleLine: '{"agent_id": "user_42", "action": "create_post", "content": "Breaking: new study confirms X", "influence": 0.7, "step": 5, "sentiment": "positive", "followers": 1200}',
81
+ exampleRules: [
82
+ "Block posts that amplify unverified claims",
83
+ "Penalize agents that repeat unvalidated information",
84
+ "Halt cascade when echo amplification exceeds 60%",
85
+ "Require independent sources before sharing conclusions",
86
+ "Reward agents that challenge dominant consensus",
87
+ "Slow viral spread of unverified content",
88
+ ].join("\n"),
89
+ captureInstructions: [
90
+ "# Option A: Capture OASIS output",
91
+ "# Run your OASIS/MiroFish simulation and save agent actions:",
92
+ "python run_simulation.py --output agent_actions.jsonl",
93
+ "",
94
+ "# Option B: Export from existing run",
95
+ "# If you have a completed simulation, export the action log:",
96
+ "python export_actions.py --run-id <id> --format jsonl > actions.jsonl",
97
+ "",
98
+ "# Each line should have: agent_id, action, content, step",
99
+ ].join("\n"),
100
+ tags: ["social", "swarm", "simulation"],
101
+ },
102
+ langchain: {
103
+ id: "langchain",
104
+ name: "LangChain / LangGraph",
105
+ description: "LLM agent framework. Evaluates tool calls, chain steps, and agent decisions.",
106
+ outputFormat: "jsonl",
107
+ color: "green",
108
+ icon: "Link",
109
+ fieldMap: {
110
+ agentId: ["agent_id", "agent", "chain_id", "run_id"],
111
+ actionType: ["tool", "action", "type", "step_type"],
112
+ description: ["input", "description", "query", "tool_input"],
113
+ magnitude: ["confidence", "score", "magnitude"],
114
+ cycle: ["step", "iteration", "cycle"],
115
+ contextFields: ["output", "tool_output", "tokens", "latency", "model"],
116
+ },
117
+ exampleLine: '{"agent_id": "researcher", "tool": "web_search", "input": "latest findings on CRISPR efficiency", "step": 2, "confidence": 0.6}',
118
+ exampleRules: [
119
+ "Block web searches without clear research purpose",
120
+ "Require source validation before generating conclusions",
121
+ "Penalize agents that skip verification steps",
122
+ "Halt chain when confidence drops below 0.5",
123
+ "Reward tool use that cross-references multiple sources",
124
+ ].join("\n"),
125
+ captureInstructions: [
126
+ "# Enable LangChain callback logging:",
127
+ "from langchain.callbacks import FileCallbackHandler",
128
+ "handler = FileCallbackHandler('agent_log.jsonl')",
129
+ "agent.run('your query', callbacks=[handler])",
130
+ "",
131
+ "# Or use LangSmith export:",
132
+ "langsmith export --run-id <id> --format jsonl > actions.jsonl",
133
+ ].join("\n"),
134
+ tags: ["llm", "agent", "tools"],
135
+ },
136
+ custom: {
137
+ id: "custom",
138
+ name: "Custom / Any System",
139
+ description: "Any agent system that produces structured output. We auto-detect common field patterns.",
140
+ outputFormat: "jsonl",
141
+ color: "zinc",
142
+ icon: "FileJson",
143
+ fieldMap: {
144
+ agentId: ["agent_id", "agentId", "agent", "id", "user_id", "actor", "name"],
145
+ actionType: ["type", "action", "action_type", "event", "event_type", "tool", "step_type"],
146
+ description: ["description", "content", "text", "message", "summary", "title", "input", "query"],
147
+ magnitude: ["confidence", "magnitude", "score", "impact", "influence", "weight", "intensity"],
148
+ cycle: ["cycle", "step", "round", "tick", "iteration", "timestamp", "sequence"],
149
+ contextFields: [],
150
+ },
151
+ exampleLine: '{"agent_id": "agent_1", "type": "decision", "description": "Chose option A based on analysis", "confidence": 0.75, "step": 1}',
152
+ exampleRules: [
153
+ "Block actions with confidence below 0.5",
154
+ "Require validation before final decisions",
155
+ "Penalize agents that skip verification",
156
+ "Halt when error rate exceeds threshold",
157
+ "Reward independent convergence on same conclusion",
158
+ ].join("\n"),
159
+ captureInstructions: [
160
+ "# Save your agent system's output as JSONL (one JSON object per line).",
161
+ "# Each line should have at minimum:",
162
+ "# - An agent identifier (agent_id, agent, id, etc.)",
163
+ "# - An action type (type, action, event, etc.)",
164
+ "# - A description (description, content, text, etc.)",
165
+ "",
166
+ "# Example:",
167
+ '# {"agent_id": "bot_1", "type": "decision", "description": "Selected strategy X", "step": 1}',
168
+ '# {"agent_id": "bot_2", "type": "analysis", "description": "Analyzed data from source Y", "step": 1}',
169
+ ].join("\n"),
170
+ tags: ["custom", "generic"],
171
+ },
172
+ };
173
+ // ============================================
174
+ // FIELD EXTRACTION — resolve multi-name fields
175
+ // ============================================
176
+ function extractField(record, candidates) {
177
+ const names = typeof candidates === "string" ? [candidates] : candidates;
178
+ for (const name of names) {
179
+ if (name in record && record[name] != null) {
180
+ return record[name];
181
+ }
182
+ }
183
+ return undefined;
184
+ }
185
+ function extractString(record, candidates, fallback) {
186
+ const val = extractField(record, candidates);
187
+ if (typeof val === "string")
188
+ return val;
189
+ if (val != null)
190
+ return String(val);
191
+ return fallback;
192
+ }
193
+ function extractNumber(record, candidates, fallback) {
194
+ const val = extractField(record, candidates);
195
+ if (typeof val === "number")
196
+ return Math.max(0, Math.min(1, val));
197
+ if (typeof val === "string") {
198
+ const n = parseFloat(val);
199
+ if (!isNaN(n))
200
+ return Math.max(0, Math.min(1, n));
201
+ }
202
+ return fallback;
203
+ }
204
+ // ============================================
205
+ // MAP RAW RECORD → AgentAction
206
+ // ============================================
207
+ function mapToAgentAction(record, profile, cycleOverride) {
208
+ const fm = profile.fieldMap;
209
+ const agentId = extractString(record, fm.agentId, "");
210
+ if (!agentId)
211
+ return { error: "No agent identifier found" };
212
+ const actionType = extractString(record, fm.actionType, "unknown");
213
+ const description = extractString(record, fm.description, `${agentId}: ${actionType}`);
214
+ const magnitude = extractNumber(record, fm.magnitude, 0.5);
215
+ const cycle = cycleOverride ?? (typeof extractField(record, fm.cycle) === "number"
216
+ ? extractField(record, fm.cycle)
217
+ : 0);
218
+ // Build context from contextFields
219
+ const context = { source: profile.id, cycle };
220
+ if (fm.contextFields) {
221
+ for (const field of fm.contextFields) {
222
+ if (field in record) {
223
+ context[field] = record[field];
224
+ }
225
+ }
226
+ }
227
+ return {
228
+ action: { agentId, type: actionType, description, magnitude, context },
229
+ cycle,
230
+ };
231
+ }
232
+ // ============================================
233
+ // PARSE INPUT — handle JSONL, JSON array, pasted text
234
+ // ============================================
235
+ function parseInput(raw) {
236
+ const trimmed = raw.trim();
237
+ if (!trimmed)
238
+ return [];
239
+ // Try JSON array first
240
+ if (trimmed.startsWith("[")) {
241
+ try {
242
+ const arr = JSON.parse(trimmed);
243
+ if (Array.isArray(arr))
244
+ return arr;
245
+ }
246
+ catch { /* fall through to JSONL */ }
247
+ }
248
+ // JSONL: one JSON object per line
249
+ const records = [];
250
+ for (const line of trimmed.split("\n")) {
251
+ const l = line.trim();
252
+ if (!l || l.startsWith("#") || l.startsWith("//"))
253
+ continue;
254
+ try {
255
+ const obj = JSON.parse(l);
256
+ if (typeof obj === "object" && obj !== null && !Array.isArray(obj)) {
257
+ records.push(obj);
258
+ }
259
+ }
260
+ catch { /* skip unparseable lines */ }
261
+ }
262
+ return records;
263
+ }
264
+ function createUniversalAdapter(engineId) {
265
+ const profile = exports.ENGINE_PROFILES[engineId];
266
+ if (!profile) {
267
+ throw new Error(`Unknown engine: ${engineId}. Available: ${Object.keys(exports.ENGINE_PROFILES).join(", ")}`);
268
+ }
269
+ return {
270
+ profile,
271
+ evaluateAll(rawInput, policyText) {
272
+ const records = parseInput(rawInput);
273
+ const results = [];
274
+ const parseErrors = [];
275
+ const governor = (0, govern_1.createGovernor)({ policyText });
276
+ for (let i = 0; i < records.length; i++) {
277
+ const mapped = mapToAgentAction(records[i], profile);
278
+ if ("error" in mapped) {
279
+ parseErrors.push({ index: i, error: mapped.error });
280
+ continue;
281
+ }
282
+ const verdict = governor.evaluate(mapped.action);
283
+ results.push({
284
+ raw: records[i],
285
+ action: mapped.action,
286
+ verdict,
287
+ cycle: mapped.cycle,
288
+ index: i,
289
+ });
290
+ }
291
+ // Compute summary
292
+ const counts = { allowed: 0, blocked: 0, modified: 0, paused: 0, rewarded: 0, penalized: 0 };
293
+ const agentSet = new Set();
294
+ const typeSet = new Set();
295
+ const reasonSet = new Set();
296
+ for (const r of results) {
297
+ const s = r.verdict.status;
298
+ if (s === "ALLOW")
299
+ counts.allowed++;
300
+ else if (s === "BLOCK")
301
+ counts.blocked++;
302
+ else if (s === "MODIFY")
303
+ counts.modified++;
304
+ else if (s === "PAUSE")
305
+ counts.paused++;
306
+ else if (s === "REWARD")
307
+ counts.rewarded++;
308
+ else if (s === "PENALIZE")
309
+ counts.penalized++;
310
+ agentSet.add(r.action.agentId);
311
+ typeSet.add(r.action.type);
312
+ if (s === "BLOCK" || s === "PENALIZE") {
313
+ reasonSet.add(r.verdict.reason);
314
+ }
315
+ }
316
+ const total = results.length;
317
+ const failRate = total > 0 ? (counts.blocked + counts.penalized) / total : 0;
318
+ return {
319
+ results,
320
+ total,
321
+ counts,
322
+ failRate,
323
+ agents: [...agentSet],
324
+ actionTypes: [...typeSet],
325
+ blockReasons: [...reasonSet],
326
+ parseErrors,
327
+ engineId: profile.id,
328
+ };
329
+ },
330
+ evaluateOne(record, policyText) {
331
+ const mapped = mapToAgentAction(record, profile);
332
+ if ("error" in mapped)
333
+ return mapped;
334
+ const verdict = (0, govern_1.govern)(mapped.action, {}, policyText);
335
+ return {
336
+ raw: record,
337
+ action: mapped.action,
338
+ verdict,
339
+ cycle: mapped.cycle,
340
+ index: 0,
341
+ };
342
+ },
343
+ };
344
+ }
345
+ // ============================================
346
+ // HELPERS
347
+ // ============================================
348
+ /** Get all available engine profiles */
349
+ function getEngineProfiles() {
350
+ return Object.values(exports.ENGINE_PROFILES);
351
+ }
352
+ /** Auto-detect which engine profile best matches a set of records */
353
+ function detectEngine(records) {
354
+ if (records.length === 0)
355
+ return "custom";
356
+ const sample = records[0];
357
+ const keys = Object.keys(sample).join(",").toLowerCase();
358
+ // ScienceClaw signatures
359
+ if (keys.includes("paper_count") || keys.includes("insight_count") || keys.includes("artifact_type")) {
360
+ return "scienceclaw";
361
+ }
362
+ // MiroFish/OASIS signatures
363
+ if (keys.includes("followers") || keys.includes("retweets") || keys.includes("hashtags") || keys.includes("sentiment")) {
364
+ return "mirofish";
365
+ }
366
+ // LangChain signatures
367
+ if (keys.includes("tool_input") || keys.includes("tool_output") || keys.includes("chain_id")) {
368
+ return "langchain";
369
+ }
370
+ return "custom";
371
+ }
@@ -59,18 +59,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
59
59
  exports.initNeuroverseModule = initNeuroverseModule;
60
60
  exports.buildWorldFromScenario = buildWorldFromScenario;
61
61
  exports.evaluateScenarioGuard = evaluateScenarioGuard;
62
+ exports.getIncentiveSystem = getIncentiveSystem;
62
63
  exports.runWorldSimulation = runWorldSimulation;
63
64
  exports.validateScenarioWorld = validateScenarioWorld;
64
65
  exports.verdictToConstitutionalChecks = verdictToConstitutionalChecks;
65
66
  exports.simulationToGovernanceSignals = simulationToGovernanceSignals;
66
67
  exports.validationToEnforcedConstraints = validationToEnforcedConstraints;
67
- // ============================================
68
- // LAZY MODULE LOADER
69
- // ============================================
70
- /**
71
- * Lazy-load @neuroverseos/governance at runtime.
72
- * Returns null in browser environments where Node modules aren't available.
73
- */
74
68
  let _nvModule;
75
69
  async function getNVModule() {
76
70
  if (_nvModule !== undefined)
@@ -81,6 +75,10 @@ async function getNVModule() {
81
75
  evaluateGuard: mod.evaluateGuard,
82
76
  simulateWorld: mod.simulateWorld,
83
77
  validateWorld: mod.validateWorld,
78
+ createAgentState: mod.createAgentState,
79
+ applyConsequence: mod.applyConsequence,
80
+ applyReward: mod.applyReward,
81
+ tickAgentStates: mod.tickAgentStates,
84
82
  };
85
83
  return _nvModule;
86
84
  }
@@ -314,10 +312,26 @@ function evaluateScenarioGuard(request, world, options) {
314
312
  has_goal: !!request.goal,
315
313
  },
316
314
  };
317
- return nv.evaluateGuard(event, world, {
315
+ const verdict = nv.evaluateGuard(event, world, {
318
316
  trace: options?.trace ?? true,
319
317
  level: options?.level ?? "standard",
320
318
  });
319
+ return verdict;
320
+ }
321
+ /**
322
+ * Get the incentive system functions from the loaded NeuroverseOS module.
323
+ * Returns null if the module isn't loaded or doesn't export incentive functions.
324
+ */
325
+ function getIncentiveSystem() {
326
+ const nv = getNVModuleSync();
327
+ if (!nv || !nv.createAgentState)
328
+ return null;
329
+ return {
330
+ createAgentState: nv.createAgentState,
331
+ applyConsequence: nv.applyConsequence,
332
+ applyReward: nv.applyReward,
333
+ tickAgentStates: nv.tickAgentStates,
334
+ };
321
335
  }
322
336
  // ============================================
323
337
  // SIMULATION — World state evolution
package/dist/index.html CHANGED
@@ -14,8 +14,8 @@
14
14
  <meta name="twitter:title" content="NV-SIM — NeuroVerse Simulation">
15
15
  <meta name="twitter:description" content="Governed agent simulation — compare emergent outcomes with and without governance constraints.">
16
16
  <link rel="icon" type="image/x-icon" href="/favicon.ico">
17
- <script type="module" crossorigin src="/assets/index-BMkPevVr.js"></script>
18
- <link rel="stylesheet" crossorigin href="/assets/index-B64NuIXu.css">
17
+ <script type="module" crossorigin src="/assets/index-sT4b_z7w.js"></script>
18
+ <link rel="stylesheet" crossorigin href="/assets/index-CH_VswRM.css">
19
19
  </head>
20
20
  <body>
21
21
  <div id="root"></div>
@@ -276,7 +276,23 @@ async function generateReasoning(scenario, sliders, options) {
276
276
  mode: options?.mode,
277
277
  goal: options?.goal,
278
278
  };
279
- const response = await (0, index_1.processReasonRequest)(request);
279
+ // All governance evaluation goes through the server.
280
+ // The browser NEVER evaluates governance locally — the server runs
281
+ // @neuroverseos/governance with full Node.js access and real enforcement.
282
+ const apiUrl = `${window.location.protocol}//${window.location.hostname}:3456/api/v1/reason`;
283
+ let response;
284
+ try {
285
+ const res = await fetch(apiUrl, {
286
+ method: 'POST',
287
+ headers: { 'Content-Type': 'application/json' },
288
+ body: JSON.stringify(request),
289
+ });
290
+ response = await res.json();
291
+ }
292
+ catch (err) {
293
+ console.error('Failed to reach governance server:', err);
294
+ response = { status: 'error' };
295
+ }
280
296
  if (response.status === 'error') {
281
297
  return {
282
298
  paths: [],
@@ -5,7 +5,7 @@
5
5
  * Converts output from ANY simulation engine into a normalized schema
6
6
  * that Echelon can reason about. Supported formats:
7
7
  *
8
- * - MiroFish (JSON with agents + emergent_behaviors)
8
+ * - Agent Swarm (JSON with agents + emergent_behaviors)
9
9
  * - NetLogo (tick-based key:value output)
10
10
  * - Mesa (Python agent action logs)
11
11
  * - AnyLogic / CSV (time-series tabular data)
@@ -37,8 +37,8 @@ function detectFormat(input) {
37
37
  if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
38
38
  try {
39
39
  const data = JSON.parse(trimmed);
40
- if (looksLikeMiroFish(data))
41
- return "mirofish";
40
+ if (looksLikeAgentSwarm(data))
41
+ return "agent_swarm";
42
42
  return "generic_json";
43
43
  }
44
44
  catch {
@@ -56,7 +56,7 @@ function detectFormat(input) {
56
56
  return "mesa";
57
57
  return "freeform_text";
58
58
  }
59
- function looksLikeMiroFish(data) {
59
+ function looksLikeAgentSwarm(data) {
60
60
  if (typeof data !== "object" || data === null)
61
61
  return false;
62
62
  const d = data;
@@ -107,8 +107,8 @@ function looksLikeMesa(text) {
107
107
  function parseSimulation(input) {
108
108
  const format = detectFormat(input);
109
109
  switch (format) {
110
- case "mirofish":
111
- return parseMiroFish(input);
110
+ case "agent_swarm":
111
+ return parseAgentSwarm(input);
112
112
  case "netlogo":
113
113
  return parseNetLogo(input);
114
114
  case "mesa":
@@ -121,8 +121,8 @@ function parseSimulation(input) {
121
121
  return parseFreeformText(input);
122
122
  }
123
123
  }
124
- // ── MiroFish Parser ──────────────────────────────────
125
- function parseMiroFish(input) {
124
+ // ── Agent Swarm Parser ──────────────────────────────────
125
+ function parseAgentSwarm(input) {
126
126
  const data = JSON.parse(input.trim());
127
127
  const agents = [];
128
128
  const events = [];
@@ -172,7 +172,7 @@ function parseMiroFish(input) {
172
172
  }
173
173
  }
174
174
  }
175
- // Parse steps (MiroFish simulation output)
175
+ // Parse steps (simulation output)
176
176
  if (data.steps && Array.isArray(data.steps)) {
177
177
  for (const step of data.steps) {
178
178
  const t = step.step ?? step.round ?? timeline.length;
@@ -196,7 +196,7 @@ function parseMiroFish(input) {
196
196
  }
197
197
  }
198
198
  return {
199
- sourceFormat: "mirofish",
199
+ sourceFormat: "agent_swarm",
200
200
  agents,
201
201
  events,
202
202
  stateChanges,
@@ -677,7 +677,7 @@ function extractAttributes(obj, exclude) {
677
677
  // FORMAT LABELS (for UI)
678
678
  // ============================================
679
679
  exports.FORMAT_LABELS = {
680
- mirofish: "MiroFish",
680
+ agent_swarm: "Agent Swarm",
681
681
  netlogo: "NetLogo",
682
682
  mesa: "Mesa (Python)",
683
683
  anylogic_csv: "AnyLogic / CSV",