@neuroverseos/nv-sim 0.1.2 → 0.1.5

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 (53) hide show
  1. package/README.md +562 -68
  2. package/dist/adapters/mirofish.js +461 -0
  3. package/dist/adapters/scienceclaw.js +750 -0
  4. package/dist/assets/index-B64NuIXu.css +1 -0
  5. package/dist/assets/index-DbzSnYxr.js +532 -0
  6. package/dist/assets/mirotir-logo-DUexumBH.svg +185 -0
  7. package/dist/assets/reportEngine-DKWTrP6-.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 +4284 -0
  27. package/dist/engine/metrics/science.metrics.js +335 -0
  28. package/dist/engine/narrativeInjection.js +360 -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/scenarioCapsule.js +56 -0
  35. package/dist/engine/scenarioComparison.js +463 -0
  36. package/dist/engine/scenarioLibrary.js +248 -0
  37. package/dist/engine/swarmSimulation.js +54 -1
  38. package/dist/engine/worldComparison.js +358 -0
  39. package/dist/engine/worldStorage.js +232 -0
  40. package/dist/favicon.ico +0 -0
  41. package/dist/index.html +23 -0
  42. package/dist/lib/reasoningEngine.js +290 -0
  43. package/dist/lib/simulationAdapter.js +686 -0
  44. package/dist/lib/swarmParser.js +291 -0
  45. package/dist/lib/types.js +2 -0
  46. package/dist/lib/utils.js +8 -0
  47. package/dist/placeholder.svg +1 -0
  48. package/dist/robots.txt +14 -0
  49. package/dist/runtime/govern.js +473 -0
  50. package/dist/runtime/index.js +75 -0
  51. package/dist/runtime/types.js +11 -0
  52. package/package.json +17 -12
  53. package/variants/.gitkeep +0 -0
@@ -0,0 +1,232 @@
1
+ "use strict";
2
+ /**
3
+ * World Storage — Decision Memory
4
+ *
5
+ * Save and load custom worlds as JSON. No cloud, no accounts.
6
+ * The world IS the data — portable, shareable, testable.
7
+ *
8
+ * Storage layers:
9
+ * Browser: localStorage (for UI)
10
+ * CLI: JSON files on disk (for dev workflows)
11
+ *
12
+ * A saved world captures:
13
+ * - The base world it was built from (preset ID)
14
+ * - Custom rules the user added
15
+ * - Metadata (name, description, timestamp)
16
+ *
17
+ * This turns transient experiments into reusable decision artifacts.
18
+ *
19
+ * Powered by @neuroverseos/governance world format.
20
+ */
21
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
22
+ if (k2 === undefined) k2 = k;
23
+ var desc = Object.getOwnPropertyDescriptor(m, k);
24
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
25
+ desc = { enumerable: true, get: function() { return m[k]; } };
26
+ }
27
+ Object.defineProperty(o, k2, desc);
28
+ }) : (function(o, m, k, k2) {
29
+ if (k2 === undefined) k2 = k;
30
+ o[k2] = m[k];
31
+ }));
32
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
33
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
34
+ }) : function(o, v) {
35
+ o["default"] = v;
36
+ });
37
+ var __importStar = (this && this.__importStar) || (function () {
38
+ var ownKeys = function(o) {
39
+ ownKeys = Object.getOwnPropertyNames || function (o) {
40
+ var ar = [];
41
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
42
+ return ar;
43
+ };
44
+ return ownKeys(o);
45
+ };
46
+ return function (mod) {
47
+ if (mod && mod.__esModule) return mod;
48
+ var result = {};
49
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
50
+ __setModuleDefault(result, mod);
51
+ return result;
52
+ };
53
+ })();
54
+ Object.defineProperty(exports, "__esModule", { value: true });
55
+ exports.saveWorldToStorage = saveWorldToStorage;
56
+ exports.listWorldsFromStorage = listWorldsFromStorage;
57
+ exports.loadWorldFromStorage = loadWorldFromStorage;
58
+ exports.deleteWorldFromStorage = deleteWorldFromStorage;
59
+ exports.exportWorldToJSON = exportWorldToJSON;
60
+ exports.importWorldFromJSON = importWorldFromJSON;
61
+ exports.createSavedWorld = createSavedWorld;
62
+ exports.forkWorld = forkWorld;
63
+ exports.saveWorldToFile = saveWorldToFile;
64
+ exports.loadWorldFromFile = loadWorldFromFile;
65
+ // ============================================
66
+ // BROWSER STORAGE (localStorage)
67
+ // ============================================
68
+ const STORAGE_KEY = "nv-sim-saved-worlds";
69
+ /**
70
+ * Runtime registry for worlds loaded from files (CLI context).
71
+ * Falls back to this when localStorage is unavailable.
72
+ */
73
+ const runtimeRegistry = [];
74
+ function hasLocalStorage() {
75
+ try {
76
+ return typeof localStorage !== "undefined" && localStorage !== null;
77
+ }
78
+ catch {
79
+ return false;
80
+ }
81
+ }
82
+ /**
83
+ * Save a world to browser localStorage (or runtime registry in CLI).
84
+ */
85
+ function saveWorldToStorage(world) {
86
+ if (!hasLocalStorage()) {
87
+ const idx = runtimeRegistry.findIndex(w => w.id === world.id);
88
+ if (idx >= 0)
89
+ runtimeRegistry[idx] = world;
90
+ else
91
+ runtimeRegistry.push(world);
92
+ return;
93
+ }
94
+ const existing = listWorldsFromStorage();
95
+ const idx = existing.findIndex(w => w.id === world.id);
96
+ if (idx >= 0) {
97
+ existing[idx] = { ...world, modifiedAt: new Date().toISOString() };
98
+ }
99
+ else {
100
+ existing.push(world);
101
+ }
102
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(existing));
103
+ }
104
+ /**
105
+ * List all saved worlds from browser localStorage (or runtime registry).
106
+ */
107
+ function listWorldsFromStorage() {
108
+ if (!hasLocalStorage()) {
109
+ return [...runtimeRegistry];
110
+ }
111
+ try {
112
+ const raw = localStorage.getItem(STORAGE_KEY);
113
+ if (!raw)
114
+ return [];
115
+ return JSON.parse(raw);
116
+ }
117
+ catch {
118
+ return [];
119
+ }
120
+ }
121
+ /**
122
+ * Load a specific saved world by ID from localStorage (or runtime registry).
123
+ */
124
+ function loadWorldFromStorage(id) {
125
+ const worlds = listWorldsFromStorage();
126
+ return worlds.find(w => w.id === id) ?? null;
127
+ }
128
+ /**
129
+ * Delete a saved world from localStorage (or runtime registry).
130
+ */
131
+ function deleteWorldFromStorage(id) {
132
+ if (!hasLocalStorage()) {
133
+ const idx = runtimeRegistry.findIndex(w => w.id === id);
134
+ if (idx < 0)
135
+ return false;
136
+ runtimeRegistry.splice(idx, 1);
137
+ return true;
138
+ }
139
+ const worlds = listWorldsFromStorage();
140
+ const filtered = worlds.filter(w => w.id !== id);
141
+ if (filtered.length === worlds.length)
142
+ return false;
143
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(filtered));
144
+ return true;
145
+ }
146
+ // ============================================
147
+ // JSON EXPORT / IMPORT
148
+ // ============================================
149
+ /**
150
+ * Export a saved world to a JSON string (for file download or CLI).
151
+ */
152
+ function exportWorldToJSON(world) {
153
+ return JSON.stringify(world, null, 2);
154
+ }
155
+ /**
156
+ * Import a saved world from a JSON string.
157
+ * Validates the structure before returning.
158
+ */
159
+ function importWorldFromJSON(json) {
160
+ const parsed = JSON.parse(json);
161
+ if (!parsed.version || !parsed.id || !parsed.name || !parsed.world) {
162
+ throw new Error("Invalid world format: missing required fields (version, id, name, world)");
163
+ }
164
+ if (!parsed.world.thesis || !Array.isArray(parsed.world.invariants)) {
165
+ throw new Error("Invalid world definition: missing thesis or invariants");
166
+ }
167
+ return parsed;
168
+ }
169
+ // ============================================
170
+ // WORLD CREATION HELPERS
171
+ // ============================================
172
+ /**
173
+ * Create a new SavedWorld from a world definition.
174
+ */
175
+ function createSavedWorld(name, world, basePreset, options) {
176
+ const id = `world_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
177
+ const now = new Date().toISOString();
178
+ return {
179
+ version: "1.0",
180
+ id,
181
+ name,
182
+ description: options?.description,
183
+ basePreset,
184
+ world,
185
+ createdAt: now,
186
+ modifiedAt: now,
187
+ tags: options?.tags,
188
+ };
189
+ }
190
+ /**
191
+ * Fork an existing world with modifications.
192
+ */
193
+ function forkWorld(source, name, modifications) {
194
+ const invariants = [
195
+ ...source.world.invariants.filter(i => !modifications.removeInvariantIds?.includes(i.id)),
196
+ ...(modifications.addInvariants ?? []),
197
+ ];
198
+ const gates = [
199
+ ...(source.world.gates ?? []).filter(g => !modifications.removeGateIds?.includes(g.id)),
200
+ ...(modifications.addGates ?? []),
201
+ ];
202
+ const world = {
203
+ ...source.world,
204
+ thesis: modifications.thesis ?? source.world.thesis,
205
+ invariants,
206
+ gates,
207
+ };
208
+ return createSavedWorld(name, world, source.id, {
209
+ description: `Forked from "${source.name}"`,
210
+ tags: [...(source.tags ?? []), "forked"],
211
+ });
212
+ }
213
+ // ============================================
214
+ // FILE I/O (Node.js only — for CLI)
215
+ // ============================================
216
+ /**
217
+ * Save a world to a JSON file on disk.
218
+ * Only works in Node.js (CLI context).
219
+ */
220
+ async function saveWorldToFile(world, filePath) {
221
+ const fs = await Promise.resolve().then(() => __importStar(require("fs")));
222
+ fs.writeFileSync(filePath, exportWorldToJSON(world), "utf-8");
223
+ }
224
+ /**
225
+ * Load a world from a JSON file on disk.
226
+ * Only works in Node.js (CLI context).
227
+ */
228
+ async function loadWorldFromFile(filePath) {
229
+ const fs = await Promise.resolve().then(() => __importStar(require("fs")));
230
+ const content = fs.readFileSync(filePath, "utf-8");
231
+ return importWorldFromJSON(content);
232
+ }
Binary file
@@ -0,0 +1,23 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>NV-SIM — NeuroVerse Simulation</title>
7
+ <meta name="description" content="Governed agent simulation — compare emergent outcomes with and without governance constraints.">
8
+ <meta name="author" content="NeuroverseOS" />
9
+ <meta property="og:type" content="website" />
10
+ <meta property="og:title" content="NV-SIM — NeuroVerse Simulation">
11
+ <meta property="og:description" content="Governed agent simulation — compare emergent outcomes with and without governance constraints.">
12
+ <meta name="twitter:card" content="summary" />
13
+ <meta name="twitter:site" content="@neuroverseos" />
14
+ <meta name="twitter:title" content="NV-SIM — NeuroVerse Simulation">
15
+ <meta name="twitter:description" content="Governed agent simulation — compare emergent outcomes with and without governance constraints.">
16
+ <link rel="icon" type="image/x-icon" href="/favicon.ico">
17
+ <script type="module" crossorigin src="/assets/index-DbzSnYxr.js"></script>
18
+ <link rel="stylesheet" crossorigin href="/assets/index-B64NuIXu.css">
19
+ </head>
20
+ <body>
21
+ <div id="root"></div>
22
+ </body>
23
+ </html>
@@ -0,0 +1,290 @@
1
+ "use strict";
2
+ /**
3
+ * UI Adapter for the Echelon Reasoning Engine
4
+ *
5
+ * Bridges the engine's processReasonRequest() API to the UI component types.
6
+ * Also generates preset scenarios from SCENARIO_TEMPLATES.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.presetScenarios = void 0;
10
+ exports.generateReasoning = generateReasoning;
11
+ const index_1 = require("../engine/index");
12
+ // ============================================
13
+ // PRESET SCENARIOS (from SCENARIO_TEMPLATES)
14
+ // ============================================
15
+ function templateIdToType(id) {
16
+ if (id.includes('hormuz') || id.includes('strait'))
17
+ return 'geopolitical';
18
+ if (id.includes('gas') || id.includes('price'))
19
+ return 'economic';
20
+ if (id.includes('ai') || id.includes('regulation'))
21
+ return 'regulation';
22
+ return 'custom';
23
+ }
24
+ function assumptionsToSliders(assumptions) {
25
+ const severityMap = { low: 20, moderate: 40, high: 70, critical: 90 };
26
+ const hostilityMap = { low: 20, moderate: 50, high: 80 };
27
+ const timeMap = { none: 10, low: 25, moderate: 50, urgent: 75, immediate: 95 };
28
+ const regMap = { permissive: 20, neutral: 40, strict: 70, adversarial: 90 };
29
+ return {
30
+ severity: severityMap[assumptions.severity ?? 'moderate'] ?? 50,
31
+ environmentalHostility: hostilityMap[assumptions.environmental_hostility ?? 'moderate'] ?? 50,
32
+ timePressure: timeMap[assumptions.time_pressure ?? 'moderate'] ?? 50,
33
+ regulatoryClimate: regMap[assumptions.regulatory_climate ?? 'neutral'] ?? 50,
34
+ };
35
+ }
36
+ function slidersToAssumptions(sliders) {
37
+ const severity = sliders.severity >= 80 ? 'critical' : sliders.severity >= 60 ? 'high' : sliders.severity >= 35 ? 'moderate' : 'low';
38
+ const hostility = sliders.environmentalHostility >= 60 ? 'high' : sliders.environmentalHostility >= 35 ? 'moderate' : 'low';
39
+ const time = sliders.timePressure >= 85 ? 'immediate' : sliders.timePressure >= 65 ? 'urgent' : sliders.timePressure >= 40 ? 'moderate' : sliders.timePressure >= 20 ? 'low' : 'none';
40
+ const reg = sliders.regulatoryClimate >= 80 ? 'adversarial' : sliders.regulatoryClimate >= 60 ? 'strict' : sliders.regulatoryClimate >= 35 ? 'neutral' : 'permissive';
41
+ return {
42
+ severity: severity,
43
+ environmental_hostility: hostility,
44
+ time_pressure: time,
45
+ regulatory_climate: reg,
46
+ };
47
+ }
48
+ exports.presetScenarios = Object.entries(index_1.SCENARIO_TEMPLATES).map(([id, template]) => ({
49
+ id,
50
+ title: template.title,
51
+ description: template.scenario.slice(0, 120) + (template.scenario.length > 120 ? '...' : ''),
52
+ tags: [...(template.tags ?? [])],
53
+ stakeholderCount: template.stakeholders.length,
54
+ type: templateIdToType(id),
55
+ defaultSliders: assumptionsToSliders(template.assumptions),
56
+ }));
57
+ // ============================================
58
+ // ENGINE RESPONSE → UI TYPES MAPPING
59
+ // ============================================
60
+ function mapRiskLevel(risk) {
61
+ if (risk === 'critical' || risk === 'high')
62
+ return 'high';
63
+ if (risk === 'moderate')
64
+ return 'medium';
65
+ return 'low';
66
+ }
67
+ function mapPaths(response) {
68
+ const paths = response.analysis.paths;
69
+ const sorted = [...paths].sort((a, b) => {
70
+ const order = { low: 0, moderate: 1, high: 2, critical: 3 };
71
+ return order[a.risk] - order[b.risk];
72
+ });
73
+ const recommendedId = sorted[0]?.id;
74
+ return paths.map(p => ({
75
+ name: p.label,
76
+ description: p.description,
77
+ probability: Math.round(p.probability * 100),
78
+ riskLevel: mapRiskLevel(p.risk),
79
+ tradeoffs: [...p.tradeoffs],
80
+ recommended: p.id === recommendedId,
81
+ }));
82
+ }
83
+ function mapMatrix(response) {
84
+ const paths = response.analysis.paths.slice(0, 3);
85
+ const stakeholderIds = [
86
+ ...new Set([
87
+ ...paths.flatMap(p => [...(p.benefits_stakeholders ?? []), ...(p.harms_stakeholders ?? [])]),
88
+ ]),
89
+ ].slice(0, 6);
90
+ const strategies = paths.map(p => p.label);
91
+ const stakeholders = stakeholderIds.length > 0 ? stakeholderIds : ['Stakeholder A', 'Stakeholder B', 'Stakeholder C'];
92
+ const reactions = stakeholders.map((sh) => paths.map(p => {
93
+ if (p.benefits_stakeholders?.includes(sh))
94
+ return 'positive';
95
+ if (p.harms_stakeholders?.includes(sh))
96
+ return 'negative';
97
+ return 'neutral';
98
+ }));
99
+ return { strategies, stakeholders, reactions };
100
+ }
101
+ function mapOutcomes(response) {
102
+ const impactToRating = {
103
+ very_positive: 2, positive: 4, neutral: 5, negative: 7, very_negative: 9,
104
+ };
105
+ return response.analysis.projected_outcomes.map(o => ({
106
+ label: o.label,
107
+ type: (o.label.toLowerCase().includes('best') ? 'best' :
108
+ o.label.toLowerCase().includes('likely') ? 'likely' :
109
+ o.label.toLowerCase().includes('worst') ? 'worst' : 'tail'),
110
+ conditions: o.conditions,
111
+ description: o.outcome,
112
+ likelihood: Math.round(o.likelihood * 100),
113
+ impactRating: impactToRating[o.impact] ?? 5,
114
+ }));
115
+ }
116
+ function mapChallenges(response) {
117
+ return response.analysis.assumption_challenges.map(c => ({
118
+ assumption: c.assumption,
119
+ whyItMightFail: c.challenge,
120
+ whatChanges: c.impact_if_wrong,
121
+ severity: c.severity === 'critical' ? 'critical' : c.severity,
122
+ }));
123
+ }
124
+ function mapRecommendations(response) {
125
+ return response.analysis.recommendations.map(r => ({
126
+ priority: r.priority,
127
+ action: r.action,
128
+ rationale: r.rationale,
129
+ timeframe: r.timeframe,
130
+ }));
131
+ }
132
+ function mapGovernance(response) {
133
+ const g = response.governance;
134
+ if (!g)
135
+ return undefined;
136
+ return {
137
+ traceId: g.trace_id,
138
+ constitutionalChecks: g.constitutional_checks.map(c => ({
139
+ ruleId: c.rule_id,
140
+ rule: c.rule,
141
+ passed: c.passed,
142
+ detail: c.detail,
143
+ })),
144
+ authorityLevel: g.authority_level,
145
+ enforcedConstraints: [...g.enforced_constraints],
146
+ timestamp: g.timestamp,
147
+ engineVersion: g.engine_version,
148
+ neuroverse: g.neuroverse ? {
149
+ guardStatus: g.neuroverse.guard_status,
150
+ worldViability: g.neuroverse.world_viability,
151
+ worldCollapsed: g.neuroverse.world_collapsed,
152
+ collapseRisk: g.neuroverse.collapse_risk,
153
+ rulesFired: g.neuroverse.rules_fired,
154
+ worldHealthScore: g.neuroverse.world_health_score,
155
+ invariantCoverage: g.neuroverse.invariant_coverage,
156
+ } : undefined,
157
+ };
158
+ }
159
+ function deriveConfidence(response) {
160
+ const paths = response.analysis.paths;
161
+ const challenges = response.analysis.assumption_challenges;
162
+ const highRiskPaths = paths.filter(p => p.risk === 'high' || p.risk === 'critical').length;
163
+ const avgProbability = paths.reduce((s, p) => s + p.probability, 0) / Math.max(paths.length, 1);
164
+ // Factor in governance signals when available
165
+ const nv = response.governance?.neuroverse;
166
+ const worldHealth = nv?.world_health_score;
167
+ const collapseRisk = nv?.collapse_risk;
168
+ let level = 'medium';
169
+ let reason;
170
+ // Adjust thresholds based on simulation dynamics
171
+ const simPenalty = collapseRisk === 'high' ? 0.15 : collapseRisk === 'moderate' ? 0.08 : 0;
172
+ const adjustedAvgProb = avgProbability - simPenalty;
173
+ if (challenges.length <= 1 && highRiskPaths === 0 && adjustedAvgProb > 0.6) {
174
+ level = 'high';
175
+ reason = `Analysis covers ${paths.length} paths with low assumption risk and strong probability signals.`;
176
+ if (worldHealth && worldHealth < 70) {
177
+ level = 'medium';
178
+ reason += ` System stability at ${worldHealth}% — moderate uncertainty from simulation dynamics.`;
179
+ }
180
+ }
181
+ else if (challenges.length >= 4 || highRiskPaths >= 2 || adjustedAvgProb < 0.3) {
182
+ level = 'low';
183
+ reason = `High uncertainty: ${challenges.length} assumptions challenged, ${highRiskPaths} high-risk paths, average probability ${(avgProbability * 100).toFixed(0)}%.`;
184
+ if (collapseRisk === 'high') {
185
+ reason += ` Elevated collapse risk detected in simulation.`;
186
+ }
187
+ }
188
+ else {
189
+ reason = `Moderate confidence: ${paths.length} paths analyzed, ${challenges.length} assumptions challenged.`;
190
+ if (worldHealth) {
191
+ reason += ` System stability: ${worldHealth}%.`;
192
+ }
193
+ else {
194
+ reason += ` Some uncertainty remains.`;
195
+ }
196
+ }
197
+ return { level, reason };
198
+ }
199
+ function deriveKeyAssumptions(request, response) {
200
+ const assumptions = [];
201
+ // Caller-provided assumptions
202
+ if (request.assumptions?.severity) {
203
+ assumptions.push({ text: `Severity is ${request.assumptions.severity}`, source: 'caller' });
204
+ }
205
+ if (request.assumptions?.time_pressure) {
206
+ assumptions.push({ text: `Time pressure is ${request.assumptions.time_pressure}`, source: 'caller' });
207
+ }
208
+ if (request.assumptions?.environmental_hostility) {
209
+ assumptions.push({ text: `Environmental hostility is ${request.assumptions.environmental_hostility}`, source: 'caller' });
210
+ }
211
+ if (request.assumptions?.regulatory_climate) {
212
+ assumptions.push({ text: `Regulatory climate is ${request.assumptions.regulatory_climate}`, source: 'caller' });
213
+ }
214
+ // Inferred assumptions
215
+ if (request.stakeholders && request.stakeholders.length > 0) {
216
+ assumptions.push({ text: `${request.stakeholders.length} stakeholders identified with known dispositions`, source: 'inferred' });
217
+ }
218
+ // Default assumptions
219
+ if (!request.constraints?.time_horizon) {
220
+ assumptions.push({ text: 'No explicit time horizon — using general framework', source: 'default' });
221
+ }
222
+ if (!request.constraints?.risk_tolerance) {
223
+ assumptions.push({ text: 'Risk tolerance not specified — assuming moderate', source: 'default' });
224
+ }
225
+ return assumptions;
226
+ }
227
+ function mapResponseToResult(response, request) {
228
+ return {
229
+ paths: mapPaths(response),
230
+ matrix: mapMatrix(response),
231
+ outcomes: mapOutcomes(response),
232
+ challenges: mapChallenges(response),
233
+ recommendations: mapRecommendations(response),
234
+ governance: mapGovernance(response),
235
+ confidence: deriveConfidence(response),
236
+ keyAssumptions: deriveKeyAssumptions(request, response),
237
+ goalResult: response.goal_reasoning,
238
+ mode: response.mode,
239
+ lastRequest: request,
240
+ };
241
+ }
242
+ /**
243
+ * Generate reasoning using the Echelon engine.
244
+ * Maps UI types (Scenario + SliderValues) → engine ReasonRequest → UI ReasoningResult.
245
+ */
246
+ async function generateReasoning(scenario, sliders, options) {
247
+ const scenarioText = typeof scenario === 'string'
248
+ ? scenario
249
+ : index_1.SCENARIO_TEMPLATES[scenario.id]?.scenario ?? scenario.description;
250
+ const assumptions = slidersToAssumptions(sliders);
251
+ // Get stakeholders from template if available, or from options
252
+ const templateId = typeof scenario === 'object' ? scenario.id : undefined;
253
+ const template = templateId ? index_1.SCENARIO_TEMPLATES[templateId] : undefined;
254
+ let stakeholders;
255
+ if (options?.stakeholders && options.stakeholders.length > 0) {
256
+ stakeholders = options.stakeholders.map(s => ({
257
+ id: s.id,
258
+ disposition: s.disposition,
259
+ }));
260
+ }
261
+ else if (template?.stakeholders) {
262
+ stakeholders = [...template.stakeholders];
263
+ }
264
+ const request = {
265
+ scenario: scenarioText,
266
+ stakeholders,
267
+ assumptions,
268
+ constraints: options?.constraints ? {
269
+ time_horizon: options.constraints.timeHorizon || undefined,
270
+ risk_tolerance: options.constraints.riskTolerance,
271
+ budget: options.constraints.budget || undefined,
272
+ } : template?.constraints,
273
+ depth: options?.depth ?? 'full',
274
+ perspective: 'strategic_advisor',
275
+ swarm: template?.swarm ?? { enabled: true, rounds: 3, reaction_model: 'mixed' },
276
+ mode: options?.mode,
277
+ goal: options?.goal,
278
+ };
279
+ const response = await (0, index_1.processReasonRequest)(request);
280
+ if (response.status === 'error') {
281
+ return {
282
+ paths: [],
283
+ matrix: { strategies: [], stakeholders: [], reactions: [] },
284
+ outcomes: [],
285
+ challenges: [],
286
+ recommendations: [],
287
+ };
288
+ }
289
+ return mapResponseToResult(response, request);
290
+ }