@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.
- package/README.md +376 -66
- package/dist/adapters/mirofish.js +461 -0
- package/dist/adapters/scienceclaw.js +750 -0
- package/dist/assets/index-CHmUN8s0.js +532 -0
- package/dist/assets/index-DWgMnB7I.css +1 -0
- package/dist/assets/mirotir-logo-DUexumBH.svg +185 -0
- package/dist/assets/reportEngine-BVdQ2_nW.js +1 -0
- package/dist/components/ConstraintsPanel.js +11 -0
- package/dist/components/StakeholderBuilder.js +32 -0
- package/dist/components/ui/badge.js +24 -0
- package/dist/components/ui/button.js +70 -0
- package/dist/components/ui/card.js +57 -0
- package/dist/components/ui/input.js +44 -0
- package/dist/components/ui/label.js +45 -0
- package/dist/components/ui/select.js +70 -0
- package/dist/engine/aiProvider.js +681 -0
- package/dist/engine/auditTrace.js +352 -0
- package/dist/engine/behavioralAnalysis.js +605 -0
- package/dist/engine/cli.js +1408 -299
- package/dist/engine/dynamicsGovernance.js +588 -0
- package/dist/engine/fullGovernedLoop.js +367 -0
- package/dist/engine/governance.js +8 -3
- package/dist/engine/governedSimulation.js +114 -17
- package/dist/engine/index.js +56 -1
- package/dist/engine/liveAdapter.js +342 -0
- package/dist/engine/liveVisualizer.js +3063 -0
- package/dist/engine/metrics/science.metrics.js +335 -0
- package/dist/engine/narrativeInjection.js +305 -0
- package/dist/engine/policyEnforcement.js +1611 -0
- package/dist/engine/policyEngine.js +799 -0
- package/dist/engine/primeRadiant.js +540 -0
- package/dist/engine/reasoningEngine.js +57 -3
- package/dist/engine/reportEngine.js +97 -0
- package/dist/engine/scenarioComparison.js +463 -0
- package/dist/engine/scenarioLibrary.js +231 -0
- package/dist/engine/swarmSimulation.js +54 -1
- package/dist/engine/worldComparison.js +358 -0
- package/dist/engine/worldStorage.js +232 -0
- package/dist/favicon.ico +0 -0
- package/dist/index.html +23 -0
- package/dist/lib/reasoningEngine.js +290 -0
- package/dist/lib/simulationAdapter.js +686 -0
- package/dist/lib/swarmParser.js +291 -0
- package/dist/lib/types.js +2 -0
- package/dist/lib/utils.js +8 -0
- package/dist/placeholder.svg +1 -0
- package/dist/robots.txt +14 -0
- package/dist/runtime/govern.js +473 -0
- package/dist/runtime/index.js +75 -0
- package/dist/runtime/types.js +11 -0
- package/package.json +17 -12
- package/variants/.gitkeep +0 -0
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* NeuroverseOS — Persistent Audit Trace System
|
|
4
|
+
*
|
|
5
|
+
* Every governance decision, every rule that fired, every agent action —
|
|
6
|
+
* written to disk as an append-only JSONL audit log.
|
|
7
|
+
*
|
|
8
|
+
* Design principles:
|
|
9
|
+
* - Append-only: never modify or delete entries
|
|
10
|
+
* - Structured: every entry is a typed JSON object
|
|
11
|
+
* - Queryable: filter by session, agent, verdict, time range
|
|
12
|
+
* - Human-readable: each line is valid JSON, can be piped through jq
|
|
13
|
+
* - Evidence chain: each entry links to its session and run context
|
|
14
|
+
*
|
|
15
|
+
* Storage format: JSONL (one JSON object per line)
|
|
16
|
+
* Default location: .neuroverse/audit/ relative to project root
|
|
17
|
+
*/
|
|
18
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
21
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
22
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
23
|
+
}
|
|
24
|
+
Object.defineProperty(o, k2, desc);
|
|
25
|
+
}) : (function(o, m, k, k2) {
|
|
26
|
+
if (k2 === undefined) k2 = k;
|
|
27
|
+
o[k2] = m[k];
|
|
28
|
+
}));
|
|
29
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
30
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
31
|
+
}) : function(o, v) {
|
|
32
|
+
o["default"] = v;
|
|
33
|
+
});
|
|
34
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
35
|
+
var ownKeys = function(o) {
|
|
36
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
37
|
+
var ar = [];
|
|
38
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
39
|
+
return ar;
|
|
40
|
+
};
|
|
41
|
+
return ownKeys(o);
|
|
42
|
+
};
|
|
43
|
+
return function (mod) {
|
|
44
|
+
if (mod && mod.__esModule) return mod;
|
|
45
|
+
var result = {};
|
|
46
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
47
|
+
__setModuleDefault(result, mod);
|
|
48
|
+
return result;
|
|
49
|
+
};
|
|
50
|
+
})();
|
|
51
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
52
|
+
exports.AuditTrail = void 0;
|
|
53
|
+
exports.listAuditSessions = listAuditSessions;
|
|
54
|
+
exports.loadAuditSession = loadAuditSession;
|
|
55
|
+
exports.searchAuditTrails = searchAuditTrails;
|
|
56
|
+
exports.formatAuditTrail = formatAuditTrail;
|
|
57
|
+
const fs = __importStar(require("fs"));
|
|
58
|
+
const path = __importStar(require("path"));
|
|
59
|
+
// ============================================
|
|
60
|
+
// AUDIT STORE
|
|
61
|
+
// ============================================
|
|
62
|
+
const DEFAULT_AUDIT_DIR = ".neuroverse/audit";
|
|
63
|
+
/** Generate a unique entry ID */
|
|
64
|
+
function entryId() {
|
|
65
|
+
return `aud_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Persistent audit trail — appends governance decisions to disk.
|
|
69
|
+
*
|
|
70
|
+
* Usage:
|
|
71
|
+
* const audit = new AuditTrail({ sessionId: "my-session" });
|
|
72
|
+
* audit.logVerdict({ agent: "trader_1", verdict: "BLOCK", ... });
|
|
73
|
+
* const entries = audit.query({ verdict: "BLOCK" });
|
|
74
|
+
*/
|
|
75
|
+
class AuditTrail {
|
|
76
|
+
dir;
|
|
77
|
+
sessionId;
|
|
78
|
+
filePath;
|
|
79
|
+
writeStream = null;
|
|
80
|
+
constructor(options) {
|
|
81
|
+
this.sessionId = options?.sessionId ?? `session_${Date.now().toString(36)}`;
|
|
82
|
+
this.dir = options?.dir ?? DEFAULT_AUDIT_DIR;
|
|
83
|
+
this.filePath = path.join(this.dir, `${this.sessionId}.jsonl`);
|
|
84
|
+
this.ensureDir();
|
|
85
|
+
}
|
|
86
|
+
ensureDir() {
|
|
87
|
+
if (!fs.existsSync(this.dir)) {
|
|
88
|
+
fs.mkdirSync(this.dir, { recursive: true });
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
getStream() {
|
|
92
|
+
if (!this.writeStream) {
|
|
93
|
+
this.writeStream = fs.createWriteStream(this.filePath, { flags: "a" });
|
|
94
|
+
}
|
|
95
|
+
return this.writeStream;
|
|
96
|
+
}
|
|
97
|
+
/** Append a raw audit entry */
|
|
98
|
+
append(entry) {
|
|
99
|
+
const line = JSON.stringify(entry) + "\n";
|
|
100
|
+
this.getStream().write(line);
|
|
101
|
+
}
|
|
102
|
+
/** Log a governance verdict */
|
|
103
|
+
logVerdict(data) {
|
|
104
|
+
this.append({
|
|
105
|
+
id: entryId(),
|
|
106
|
+
timestamp: new Date().toISOString(),
|
|
107
|
+
sessionId: this.sessionId,
|
|
108
|
+
type: "governance_verdict",
|
|
109
|
+
...data,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
/** Log an agent action (pre-governance) */
|
|
113
|
+
logAgentAction(data) {
|
|
114
|
+
this.append({
|
|
115
|
+
id: entryId(),
|
|
116
|
+
timestamp: new Date().toISOString(),
|
|
117
|
+
sessionId: this.sessionId,
|
|
118
|
+
type: "agent_action",
|
|
119
|
+
...data,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
/** Log simulation start/end */
|
|
123
|
+
logSimulation(data) {
|
|
124
|
+
this.append({
|
|
125
|
+
id: entryId(),
|
|
126
|
+
timestamp: new Date().toISOString(),
|
|
127
|
+
sessionId: this.sessionId,
|
|
128
|
+
...data,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
/** Log a rule change */
|
|
132
|
+
logRuleChange(data) {
|
|
133
|
+
this.append({
|
|
134
|
+
id: entryId(),
|
|
135
|
+
timestamp: new Date().toISOString(),
|
|
136
|
+
sessionId: this.sessionId,
|
|
137
|
+
type: "rule_change",
|
|
138
|
+
...data,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
/** Log a behavioral shift */
|
|
142
|
+
logBehavioralShift(data) {
|
|
143
|
+
this.append({
|
|
144
|
+
id: entryId(),
|
|
145
|
+
timestamp: new Date().toISOString(),
|
|
146
|
+
sessionId: this.sessionId,
|
|
147
|
+
type: "behavioral_shift",
|
|
148
|
+
...data,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
/** Log an AI provider call */
|
|
152
|
+
logAICall(data) {
|
|
153
|
+
this.append({
|
|
154
|
+
id: entryId(),
|
|
155
|
+
timestamp: new Date().toISOString(),
|
|
156
|
+
sessionId: this.sessionId,
|
|
157
|
+
type: "ai_call",
|
|
158
|
+
...data,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
/** Close the write stream */
|
|
162
|
+
close() {
|
|
163
|
+
if (this.writeStream) {
|
|
164
|
+
this.writeStream.end();
|
|
165
|
+
this.writeStream = null;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
// ============================================
|
|
169
|
+
// QUERY API
|
|
170
|
+
// ============================================
|
|
171
|
+
/** Read all entries from this session's log file */
|
|
172
|
+
readAll() {
|
|
173
|
+
if (!fs.existsSync(this.filePath))
|
|
174
|
+
return [];
|
|
175
|
+
const content = fs.readFileSync(this.filePath, "utf-8");
|
|
176
|
+
return content
|
|
177
|
+
.split("\n")
|
|
178
|
+
.filter(Boolean)
|
|
179
|
+
.map((line) => {
|
|
180
|
+
try {
|
|
181
|
+
return JSON.parse(line);
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
})
|
|
187
|
+
.filter((e) => e !== null);
|
|
188
|
+
}
|
|
189
|
+
/** Query entries with filters */
|
|
190
|
+
query(filters) {
|
|
191
|
+
let entries = this.readAll();
|
|
192
|
+
if (filters?.type) {
|
|
193
|
+
entries = entries.filter((e) => e.type === filters.type);
|
|
194
|
+
}
|
|
195
|
+
if (filters?.agent) {
|
|
196
|
+
entries = entries.filter((e) => "agent" in e && e.agent === filters.agent);
|
|
197
|
+
}
|
|
198
|
+
if (filters?.verdict) {
|
|
199
|
+
entries = entries.filter((e) => e.type === "governance_verdict" && e.verdict === filters.verdict);
|
|
200
|
+
}
|
|
201
|
+
if (filters?.runId) {
|
|
202
|
+
entries = entries.filter((e) => "runId" in e && e.runId === filters.runId);
|
|
203
|
+
}
|
|
204
|
+
if (filters?.after) {
|
|
205
|
+
entries = entries.filter((e) => e.timestamp >= filters.after);
|
|
206
|
+
}
|
|
207
|
+
if (filters?.before) {
|
|
208
|
+
entries = entries.filter((e) => e.timestamp <= filters.before);
|
|
209
|
+
}
|
|
210
|
+
return entries;
|
|
211
|
+
}
|
|
212
|
+
/** Get summary statistics */
|
|
213
|
+
summary() {
|
|
214
|
+
const entries = this.readAll();
|
|
215
|
+
const verdicts = entries.filter((e) => e.type === "governance_verdict");
|
|
216
|
+
return {
|
|
217
|
+
sessionId: this.sessionId,
|
|
218
|
+
totalEntries: entries.length,
|
|
219
|
+
entryTypes: countBy(entries, (e) => e.type),
|
|
220
|
+
verdictCounts: {
|
|
221
|
+
ALLOW: verdicts.filter((v) => v.verdict === "ALLOW").length,
|
|
222
|
+
BLOCK: verdicts.filter((v) => v.verdict === "BLOCK").length,
|
|
223
|
+
PAUSE: verdicts.filter((v) => v.verdict === "PAUSE").length,
|
|
224
|
+
MODIFY: verdicts.filter((v) => v.verdict === "MODIFY").length,
|
|
225
|
+
},
|
|
226
|
+
uniqueAgents: [...new Set(verdicts.map((v) => v.agent))],
|
|
227
|
+
uniqueRules: [...new Set(verdicts.flatMap((v) => v.rulesFired.map((r) => r.id)))],
|
|
228
|
+
timeRange: entries.length > 0
|
|
229
|
+
? { start: entries[0].timestamp, end: entries[entries.length - 1].timestamp }
|
|
230
|
+
: null,
|
|
231
|
+
filePath: this.filePath,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
/** Get the file path for this audit log */
|
|
235
|
+
getFilePath() {
|
|
236
|
+
return this.filePath;
|
|
237
|
+
}
|
|
238
|
+
/** Get the session ID */
|
|
239
|
+
getSessionId() {
|
|
240
|
+
return this.sessionId;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
exports.AuditTrail = AuditTrail;
|
|
244
|
+
// ============================================
|
|
245
|
+
// CROSS-SESSION QUERIES
|
|
246
|
+
// ============================================
|
|
247
|
+
/**
|
|
248
|
+
* List all audit sessions on disk.
|
|
249
|
+
*/
|
|
250
|
+
function listAuditSessions(dir) {
|
|
251
|
+
const auditDir = dir ?? DEFAULT_AUDIT_DIR;
|
|
252
|
+
if (!fs.existsSync(auditDir))
|
|
253
|
+
return [];
|
|
254
|
+
return fs
|
|
255
|
+
.readdirSync(auditDir)
|
|
256
|
+
.filter((f) => f.endsWith(".jsonl"))
|
|
257
|
+
.map((f) => f.replace(/\.jsonl$/, ""));
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Load a specific session's audit trail.
|
|
261
|
+
*/
|
|
262
|
+
function loadAuditSession(sessionId, dir) {
|
|
263
|
+
return new AuditTrail({ sessionId, dir });
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Search across ALL audit sessions for entries matching filters.
|
|
267
|
+
*/
|
|
268
|
+
function searchAuditTrails(filters, dir) {
|
|
269
|
+
const sessions = listAuditSessions(dir);
|
|
270
|
+
const results = [];
|
|
271
|
+
for (const sessionId of sessions) {
|
|
272
|
+
const trail = loadAuditSession(sessionId, dir);
|
|
273
|
+
results.push(...trail.query(filters));
|
|
274
|
+
}
|
|
275
|
+
return results.sort((a, b) => a.timestamp.localeCompare(b.timestamp));
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Format audit trail for human-readable display.
|
|
279
|
+
*/
|
|
280
|
+
function formatAuditTrail(entries, options) {
|
|
281
|
+
if (entries.length === 0)
|
|
282
|
+
return " No audit entries found.\n";
|
|
283
|
+
const lines = [];
|
|
284
|
+
lines.push(` ╔══════════════════════════════════════════════════════════════╗`);
|
|
285
|
+
lines.push(` ║ NeuroverseOS — AUDIT TRAIL (${entries.length} entries)${" ".repeat(Math.max(0, 24 - String(entries.length).length))}║`);
|
|
286
|
+
lines.push(` ╚══════════════════════════════════════════════════════════════╝\n`);
|
|
287
|
+
for (const entry of entries) {
|
|
288
|
+
const ts = entry.timestamp.replace("T", " ").slice(0, 19);
|
|
289
|
+
switch (entry.type) {
|
|
290
|
+
case "governance_verdict": {
|
|
291
|
+
const v = entry;
|
|
292
|
+
const icon = v.verdict === "BLOCK" ? "⛔" : v.verdict === "ALLOW" ? "✅" : v.verdict === "PAUSE" ? "⏸" : "🔄";
|
|
293
|
+
lines.push(` ${icon} [${ts}] ${v.verdict} — ${v.agent}: ${v.action}`);
|
|
294
|
+
if (options?.verbose) {
|
|
295
|
+
lines.push(` Reason: ${v.reason}`);
|
|
296
|
+
if (v.rulesFired.length > 0) {
|
|
297
|
+
lines.push(` Rules: ${v.rulesFired.map(r => r.id).join(", ")}`);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
case "agent_action": {
|
|
303
|
+
const a = entry;
|
|
304
|
+
lines.push(` 🎯 [${ts}] ACTION — ${a.agent}: ${a.action} (magnitude: ${a.magnitude})`);
|
|
305
|
+
break;
|
|
306
|
+
}
|
|
307
|
+
case "simulation_start":
|
|
308
|
+
case "simulation_end": {
|
|
309
|
+
const s = entry;
|
|
310
|
+
const label = s.type === "simulation_start" ? "▶ START" : "■ END";
|
|
311
|
+
lines.push(` ${label} [${ts}] Run ${s.runId}: ${s.scenario}`);
|
|
312
|
+
if (s.type === "simulation_end" && s.metrics && options?.verbose) {
|
|
313
|
+
lines.push(` Metrics: ${JSON.stringify(s.metrics)}`);
|
|
314
|
+
}
|
|
315
|
+
break;
|
|
316
|
+
}
|
|
317
|
+
case "rule_change": {
|
|
318
|
+
const r = entry;
|
|
319
|
+
const icon = r.changeType === "added" ? "➕" : r.changeType === "removed" ? "➖" : "📝";
|
|
320
|
+
lines.push(` ${icon} [${ts}] RULE ${r.changeType.toUpperCase()}: ${r.ruleId} — ${r.description}`);
|
|
321
|
+
break;
|
|
322
|
+
}
|
|
323
|
+
case "behavioral_shift": {
|
|
324
|
+
const b = entry;
|
|
325
|
+
lines.push(` 🔀 [${ts}] SHIFT — ${b.agent}: ${b.fromBehavior} → ${b.toBehavior} (round ${b.round})`);
|
|
326
|
+
if (options?.verbose) {
|
|
327
|
+
lines.push(` Trigger: ${b.trigger}`);
|
|
328
|
+
}
|
|
329
|
+
break;
|
|
330
|
+
}
|
|
331
|
+
case "ai_call": {
|
|
332
|
+
const ai = entry;
|
|
333
|
+
const status = ai.success ? "✓" : "✗";
|
|
334
|
+
lines.push(` 🤖 [${ts}] AI ${status} — ${ai.provider}/${ai.action}${ai.durationMs ? ` (${ai.durationMs}ms)` : ""}`);
|
|
335
|
+
break;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
lines.push("");
|
|
340
|
+
return lines.join("\n");
|
|
341
|
+
}
|
|
342
|
+
// ============================================
|
|
343
|
+
// HELPERS
|
|
344
|
+
// ============================================
|
|
345
|
+
function countBy(arr, fn) {
|
|
346
|
+
const counts = {};
|
|
347
|
+
for (const item of arr) {
|
|
348
|
+
const key = fn(item);
|
|
349
|
+
counts[key] = (counts[key] ?? 0) + 1;
|
|
350
|
+
}
|
|
351
|
+
return counts;
|
|
352
|
+
}
|