@neuroverseos/governance 0.4.3 → 0.5.1

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 (68) hide show
  1. package/README.md +189 -0
  2. package/dist/adapters/autoresearch.js +2 -2
  3. package/dist/adapters/deep-agents.js +2 -2
  4. package/dist/adapters/express.js +2 -2
  5. package/dist/adapters/github.js +2 -2
  6. package/dist/adapters/index.js +23 -21
  7. package/dist/adapters/langchain.js +2 -2
  8. package/dist/adapters/mentraos.js +8 -6
  9. package/dist/adapters/openai.js +2 -2
  10. package/dist/adapters/openclaw.js +2 -2
  11. package/dist/{add-XSANI3FK.js → add-JP7TC2K3.js} +1 -1
  12. package/dist/admin/index.cjs +2214 -0
  13. package/dist/admin/index.d.cts +362 -0
  14. package/dist/admin/index.d.ts +362 -0
  15. package/dist/admin/index.js +703 -0
  16. package/dist/{build-EGBGZFIJ.js → build-THUEYMVT.js} +5 -5
  17. package/dist/{chunk-YJ34R5NB.js → chunk-5RAQ5DZW.js} +3 -3
  18. package/dist/{chunk-RDA7ISWC.js → chunk-6UPEUMJ2.js} +3 -3
  19. package/dist/chunk-7UU7V3AD.js +447 -0
  20. package/dist/{chunk-ZEIT2QLM.js → chunk-EK77AJAH.js} +22 -4
  21. package/dist/{chunk-3S5AD4AB.js → chunk-FGOSKQDE.js} +3 -3
  22. package/dist/{chunk-GTPV2XGO.js → chunk-GJ6LM4JZ.js} +1 -441
  23. package/dist/chunk-H3REGQRI.js +107 -0
  24. package/dist/{chunk-J2IZBHXJ.js → chunk-LAKUB76X.js} +3 -3
  25. package/dist/{chunk-FVOGUCB6.js → chunk-R23T5SZG.js} +3 -3
  26. package/dist/{chunk-A7SHG75T.js → chunk-RF2L5SYG.js} +3 -3
  27. package/dist/{chunk-QMVQ6KPL.js → chunk-TL4DLMMW.js} +3 -3
  28. package/dist/{chunk-AV7XJJWK.js → chunk-TZBERHFM.js} +3 -3
  29. package/dist/{chunk-3AYKQHYI.js → chunk-UZBW44KD.js} +3 -3
  30. package/dist/{chunk-FS2UUJJO.js → chunk-XPMZB46F.js} +3 -3
  31. package/dist/cli/neuroverse.cjs +962 -284
  32. package/dist/cli/neuroverse.js +46 -22
  33. package/dist/cli/plan.js +1 -1
  34. package/dist/cli/run.cjs +242 -139
  35. package/dist/cli/run.js +23 -3
  36. package/dist/{demo-6OQYWRR6.js → demo-N5K4VXJW.js} +3 -3
  37. package/dist/{derive-7Y7YWVLU.js → derive-5LOMN7GO.js} +4 -4
  38. package/dist/{equity-penalties-NVBAB5WL.js → equity-penalties-PYCJ3Q4U.js} +6 -6
  39. package/dist/{explain-HDFN4ION.js → explain-42TVC3QD.js} +1 -1
  40. package/dist/{guard-6KSCWT2W.js → guard-TPYDFG6V.js} +16 -4
  41. package/dist/{improve-2PWGGO5B.js → improve-HLZGJ54Z.js} +3 -3
  42. package/dist/index.cjs +19 -1
  43. package/dist/index.d.cts +2 -0
  44. package/dist/index.d.ts +2 -0
  45. package/dist/index.js +27 -27
  46. package/dist/keygen-BSZH3NM2.js +77 -0
  47. package/dist/{lens-MHMUDCMQ.js → lens-NFGZHD76.js} +1 -1
  48. package/dist/{mcp-server-TNIWZ7B5.js → mcp-server-5XXNG6VC.js} +2 -2
  49. package/dist/migrate-NH5PVMX4.js +221 -0
  50. package/dist/{playground-3FLDGBET.js → playground-2EU5CFIH.js} +4 -4
  51. package/dist/{redteam-HV6LMKEH.js → redteam-VK6OVHAE.js} +3 -3
  52. package/dist/{session-XZP2754M.js → session-NGA4DUPL.js} +2 -2
  53. package/dist/sign-RRELHKWM.js +11 -0
  54. package/dist/{simulate-VT437EEL.js → simulate-4YNOBMES.js} +1 -1
  55. package/dist/{test-4WTX6RKQ.js → test-HDBPMQTG.js} +3 -3
  56. package/dist/{validate-M52DX22Y.js → validate-6MFQZ2EG.js} +1 -1
  57. package/dist/verify-6AVTWX75.js +151 -0
  58. package/dist/{world-O4HTQPDP.js → world-H5WVURKU.js} +1 -1
  59. package/dist/{world-loader-YTYFOP7D.js → world-loader-J47PCPDZ.js} +1 -1
  60. package/package.json +22 -10
  61. package/dist/{behavioral-SLW7ALEK.js → behavioral-SPWPGYXL.js} +3 -3
  62. package/dist/{bootstrap-2OW5ZLBL.js → bootstrap-IP5QMC3Q.js} +3 -3
  63. package/dist/{chunk-I4RTIMLX.js → chunk-EQUAWNXW.js} +0 -0
  64. package/dist/{chunk-DA5MHFRR.js → chunk-NTHXZAW4.js} +3 -3
  65. package/dist/{chunk-FHXXD2TI.js → chunk-QZ666FCV.js} +6 -6
  66. package/dist/{configure-ai-LL3VAPQW.js → configure-ai-5MP5DWTT.js} +3 -3
  67. package/dist/{decision-flow-3K4D72G4.js → decision-flow-IJPNMVQK.js} +3 -3
  68. /package/dist/{doctor-EC5OYTI3.js → doctor-Q5APJOTS.js} +0 -0
@@ -29,6 +29,10 @@ Commands:
29
29
  decision-flow Intent \u2192 Rule \u2192 Outcome visualization (behavioral governance)
30
30
  equity-penalties Fortune 500 equity PENALIZE/REWARD simulation
31
31
  world World management (status, diff, snapshot, rollback)
32
+ keygen Generate Ed25519 signing keypair
33
+ sign Sign a world artifact (cryptographic manifest)
34
+ verify Verify a signed world artifact
35
+ migrate Migrate world schema between versions
32
36
  derive AI-assisted synthesis of .nv-world.md from markdown
33
37
  bootstrap Compile .nv-world.md \u2192 world JSON files
34
38
  configure-ai Configure AI provider credentials
@@ -66,6 +70,10 @@ Usage:
66
70
  neuroverse equity-penalties --world <dir> [--agents N] [--rounds N] [--json]
67
71
  neuroverse configure-ai --provider <name> --model <name> --api-key <key>
68
72
  neuroverse configure-world [--output <dir>]
73
+ neuroverse keygen [--output <dir>] [--name <name>]
74
+ neuroverse sign --world <dir> [--key <path>]
75
+ neuroverse verify --world <dir> [--key <path>]
76
+ neuroverse migrate --world <dir> [--dry-run] [--backup]
69
77
  neuroverse lens list [--world <dir>] [--json]
70
78
  neuroverse lens preview <id> [--world <dir>]
71
79
  neuroverse lens compile <id,...> [--world <dir>] [--role <role>] [--json]
@@ -100,23 +108,23 @@ async function main() {
100
108
  const subArgs = args.slice(1);
101
109
  switch (command) {
102
110
  case "add": {
103
- const { main: addMain } = await import("../add-XSANI3FK.js");
111
+ const { main: addMain } = await import("../add-JP7TC2K3.js");
104
112
  return addMain(subArgs);
105
113
  }
106
114
  case "build": {
107
- const { main: buildMain } = await import("../build-EGBGZFIJ.js");
115
+ const { main: buildMain } = await import("../build-THUEYMVT.js");
108
116
  return buildMain(subArgs);
109
117
  }
110
118
  case "explain": {
111
- const { main: explainMain } = await import("../explain-HDFN4ION.js");
119
+ const { main: explainMain } = await import("../explain-42TVC3QD.js");
112
120
  return explainMain(subArgs);
113
121
  }
114
122
  case "simulate": {
115
- const { main: simulateMain } = await import("../simulate-VT437EEL.js");
123
+ const { main: simulateMain } = await import("../simulate-4YNOBMES.js");
116
124
  return simulateMain(subArgs);
117
125
  }
118
126
  case "improve": {
119
- const { main: improveMain } = await import("../improve-2PWGGO5B.js");
127
+ const { main: improveMain } = await import("../improve-HLZGJ54Z.js");
120
128
  return improveMain(subArgs);
121
129
  }
122
130
  case "init": {
@@ -132,35 +140,35 @@ async function main() {
132
140
  return inferWorldMain(subArgs);
133
141
  }
134
142
  case "bootstrap": {
135
- const { main: bootstrapMain } = await import("../bootstrap-2OW5ZLBL.js");
143
+ const { main: bootstrapMain } = await import("../bootstrap-IP5QMC3Q.js");
136
144
  return bootstrapMain(subArgs);
137
145
  }
138
146
  case "validate": {
139
- const { main: validateMain } = await import("../validate-M52DX22Y.js");
147
+ const { main: validateMain } = await import("../validate-6MFQZ2EG.js");
140
148
  return validateMain(subArgs);
141
149
  }
142
150
  case "guard": {
143
- const { main: guardMain } = await import("../guard-6KSCWT2W.js");
151
+ const { main: guardMain } = await import("../guard-TPYDFG6V.js");
144
152
  return guardMain(subArgs);
145
153
  }
146
154
  case "test": {
147
- const { main: testMain } = await import("../test-4WTX6RKQ.js");
155
+ const { main: testMain } = await import("../test-HDBPMQTG.js");
148
156
  return testMain(subArgs);
149
157
  }
150
158
  case "redteam": {
151
- const { main: redteamMain } = await import("../redteam-HV6LMKEH.js");
159
+ const { main: redteamMain } = await import("../redteam-VK6OVHAE.js");
152
160
  return redteamMain(subArgs);
153
161
  }
154
162
  case "demo": {
155
- const { main: demoMain } = await import("../demo-6OQYWRR6.js");
163
+ const { main: demoMain } = await import("../demo-N5K4VXJW.js");
156
164
  return demoMain(subArgs);
157
165
  }
158
166
  case "doctor": {
159
- const { main: doctorMain } = await import("../doctor-EC5OYTI3.js");
167
+ const { main: doctorMain } = await import("../doctor-Q5APJOTS.js");
160
168
  return doctorMain(subArgs);
161
169
  }
162
170
  case "playground": {
163
- const { main: playgroundMain } = await import("../playground-3FLDGBET.js");
171
+ const { main: playgroundMain } = await import("../playground-2EU5CFIH.js");
164
172
  return playgroundMain(subArgs);
165
173
  }
166
174
  case "plan": {
@@ -172,11 +180,11 @@ async function main() {
172
180
  return runMain(subArgs);
173
181
  }
174
182
  case "mcp": {
175
- const { startMcpServer } = await import("../mcp-server-TNIWZ7B5.js");
183
+ const { startMcpServer } = await import("../mcp-server-5XXNG6VC.js");
176
184
  return startMcpServer(subArgs);
177
185
  }
178
186
  case "worlds": {
179
- const { main: worldMain } = await import("../world-O4HTQPDP.js");
187
+ const { main: worldMain } = await import("../world-H5WVURKU.js");
180
188
  return worldMain(["list", ...subArgs]);
181
189
  }
182
190
  case "trace": {
@@ -188,27 +196,43 @@ async function main() {
188
196
  return impactMain(subArgs);
189
197
  }
190
198
  case "behavioral": {
191
- const { main: behavioralMain } = await import("../behavioral-SLW7ALEK.js");
199
+ const { main: behavioralMain } = await import("../behavioral-SPWPGYXL.js");
192
200
  return behavioralMain(subArgs);
193
201
  }
194
202
  case "world": {
195
- const { main: worldMain } = await import("../world-O4HTQPDP.js");
203
+ const { main: worldMain } = await import("../world-H5WVURKU.js");
196
204
  return worldMain(subArgs);
197
205
  }
198
206
  case "derive": {
199
- const { main: deriveMain } = await import("../derive-7Y7YWVLU.js");
207
+ const { main: deriveMain } = await import("../derive-5LOMN7GO.js");
200
208
  return deriveMain(subArgs);
201
209
  }
202
210
  case "decision-flow": {
203
- const { main: decisionFlowMain } = await import("../decision-flow-3K4D72G4.js");
211
+ const { main: decisionFlowMain } = await import("../decision-flow-IJPNMVQK.js");
204
212
  return decisionFlowMain(subArgs);
205
213
  }
206
214
  case "equity-penalties": {
207
- const { main: equityPenaltiesMain } = await import("../equity-penalties-NVBAB5WL.js");
215
+ const { main: equityPenaltiesMain } = await import("../equity-penalties-PYCJ3Q4U.js");
208
216
  return equityPenaltiesMain(subArgs);
209
217
  }
218
+ case "keygen": {
219
+ const { main: keygenMain } = await import("../keygen-BSZH3NM2.js");
220
+ return keygenMain(subArgs);
221
+ }
222
+ case "sign": {
223
+ const { main: signMain } = await import("../sign-RRELHKWM.js");
224
+ return signMain(subArgs);
225
+ }
226
+ case "verify": {
227
+ const { main: verifyMain } = await import("../verify-6AVTWX75.js");
228
+ return verifyMain(subArgs);
229
+ }
230
+ case "migrate": {
231
+ const { main: migrateMain } = await import("../migrate-NH5PVMX4.js");
232
+ return migrateMain(subArgs);
233
+ }
210
234
  case "configure-ai": {
211
- const { main: configureAiMain } = await import("../configure-ai-LL3VAPQW.js");
235
+ const { main: configureAiMain } = await import("../configure-ai-5MP5DWTT.js");
212
236
  return configureAiMain(subArgs);
213
237
  }
214
238
  case "configure-world": {
@@ -216,7 +240,7 @@ async function main() {
216
240
  return configureWorldMain(subArgs);
217
241
  }
218
242
  case "lens": {
219
- const { main: lensMain } = await import("../lens-MHMUDCMQ.js");
243
+ const { main: lensMain } = await import("../lens-NFGZHD76.js");
220
244
  return lensMain(subArgs);
221
245
  }
222
246
  case "--help":
package/dist/cli/plan.js CHANGED
@@ -100,7 +100,7 @@ async function checkCommand(args) {
100
100
  }
101
101
  const worldPath = parseArg(args, "--world");
102
102
  if (worldPath) {
103
- const { loadWorld } = await import("../world-loader-YTYFOP7D.js");
103
+ const { loadWorld } = await import("../world-loader-J47PCPDZ.js");
104
104
  const { evaluateGuard } = await import("../engine/guard-engine.js");
105
105
  const world = await loadWorld(worldPath);
106
106
  const verdict2 = evaluateGuard(event, world, { plan });
package/dist/cli/run.cjs CHANGED
@@ -30,143 +30,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
30
30
  ));
31
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
32
 
33
- // src/runtime/model-adapter.ts
34
- var model_adapter_exports = {};
35
- __export(model_adapter_exports, {
36
- ModelAdapter: () => ModelAdapter,
37
- PROVIDERS: () => PROVIDERS,
38
- resolveProvider: () => resolveProvider
39
- });
40
- function resolveProvider(provider, overrides) {
41
- const preset = PROVIDERS[provider];
42
- if (!preset) {
43
- throw new Error(
44
- `Unknown provider: "${provider}". Available: ${Object.keys(PROVIDERS).join(", ")}`
45
- );
46
- }
47
- const apiKey = overrides?.apiKey ?? (preset.envVar ? process.env[preset.envVar] : "") ?? "";
48
- if (!apiKey && preset.envVar) {
49
- throw new Error(
50
- `Missing API key. Set ${preset.envVar} or pass --api-key.`
51
- );
52
- }
53
- return {
54
- baseUrl: overrides?.baseUrl ?? preset.baseUrl,
55
- apiKey,
56
- model: overrides?.model ?? preset.defaultModel,
57
- systemPrompt: overrides?.systemPrompt,
58
- maxTokens: overrides?.maxTokens
59
- };
60
- }
61
- var DEFAULT_SYSTEM_PROMPT, ModelAdapter, PROVIDERS;
62
- var init_model_adapter = __esm({
63
- "src/runtime/model-adapter.ts"() {
64
- "use strict";
65
- DEFAULT_SYSTEM_PROMPT = `You are an AI assistant operating under NeuroVerse governance.
66
- All your tool calls are evaluated against governance rules before execution.
67
- If an action is blocked, you will be told why. Adjust your approach accordingly.
68
- Do not attempt to bypass governance rules.`;
69
- ModelAdapter = class {
70
- config;
71
- messages;
72
- tools;
73
- constructor(config, tools = []) {
74
- this.config = config;
75
- this.tools = tools;
76
- this.messages = [];
77
- const systemPrompt = config.systemPrompt ?? DEFAULT_SYSTEM_PROMPT;
78
- this.messages.push({ role: "system", content: systemPrompt });
79
- }
80
- /**
81
- * Send a user message and get the model's response.
82
- */
83
- async chat(userMessage) {
84
- this.messages.push({ role: "user", content: userMessage });
85
- return this.complete();
86
- }
87
- /**
88
- * Send a tool result back to the model and get the next response.
89
- */
90
- async sendToolResult(toolCallId, result) {
91
- this.messages.push({
92
- role: "tool",
93
- content: result,
94
- tool_call_id: toolCallId
95
- });
96
- return this.complete();
97
- }
98
- /**
99
- * Send a governance block message as a tool result.
100
- */
101
- async sendBlockedResult(toolCallId, reason) {
102
- return this.sendToolResult(
103
- toolCallId,
104
- `[GOVERNANCE BLOCKED] ${reason}. Please adjust your approach.`
105
- );
106
- }
107
- /**
108
- * Call the model API and parse the response.
109
- */
110
- async complete() {
111
- const url = `${this.config.baseUrl}/chat/completions`;
112
- const body = {
113
- model: this.config.model,
114
- messages: this.messages,
115
- max_tokens: this.config.maxTokens ?? 4096
116
- };
117
- if (this.tools.length > 0) {
118
- body.tools = this.tools;
119
- }
120
- const response = await fetch(url, {
121
- method: "POST",
122
- headers: {
123
- "Content-Type": "application/json",
124
- "Authorization": `Bearer ${this.config.apiKey}`
125
- },
126
- body: JSON.stringify(body)
127
- });
128
- if (!response.ok) {
129
- const text = await response.text();
130
- throw new Error(`Model API error ${response.status}: ${text}`);
131
- }
132
- const data = await response.json();
133
- const choice = data.choices?.[0];
134
- if (!choice) {
135
- throw new Error("Model returned no choices");
136
- }
137
- const message = choice.message;
138
- this.messages.push(message);
139
- return {
140
- content: message.content ?? null,
141
- toolCalls: message.tool_calls ?? [],
142
- finishReason: choice.finish_reason ?? "stop"
143
- };
144
- }
145
- /** Get current message count (for context tracking). */
146
- get messageCount() {
147
- return this.messages.length;
148
- }
149
- };
150
- PROVIDERS = {
151
- openai: {
152
- baseUrl: "https://api.openai.com/v1",
153
- defaultModel: "gpt-4o",
154
- envVar: "OPENAI_API_KEY"
155
- },
156
- anthropic: {
157
- baseUrl: "https://api.anthropic.com/v1",
158
- defaultModel: "claude-sonnet-4-20250514",
159
- envVar: "ANTHROPIC_API_KEY"
160
- },
161
- ollama: {
162
- baseUrl: "http://localhost:11434/v1",
163
- defaultModel: "llama3",
164
- envVar: ""
165
- }
166
- };
167
- }
168
- });
169
-
170
33
  // src/engine/text-utils.ts
171
34
  function normalizeEventText(event) {
172
35
  return [
@@ -1304,6 +1167,143 @@ var init_guard_engine = __esm({
1304
1167
  }
1305
1168
  });
1306
1169
 
1170
+ // src/runtime/model-adapter.ts
1171
+ var model_adapter_exports = {};
1172
+ __export(model_adapter_exports, {
1173
+ ModelAdapter: () => ModelAdapter,
1174
+ PROVIDERS: () => PROVIDERS,
1175
+ resolveProvider: () => resolveProvider
1176
+ });
1177
+ function resolveProvider(provider, overrides) {
1178
+ const preset = PROVIDERS[provider];
1179
+ if (!preset) {
1180
+ throw new Error(
1181
+ `Unknown provider: "${provider}". Available: ${Object.keys(PROVIDERS).join(", ")}`
1182
+ );
1183
+ }
1184
+ const apiKey = overrides?.apiKey ?? (preset.envVar ? process.env[preset.envVar] : "") ?? "";
1185
+ if (!apiKey && preset.envVar) {
1186
+ throw new Error(
1187
+ `Missing API key. Set ${preset.envVar} or pass --api-key.`
1188
+ );
1189
+ }
1190
+ return {
1191
+ baseUrl: overrides?.baseUrl ?? preset.baseUrl,
1192
+ apiKey,
1193
+ model: overrides?.model ?? preset.defaultModel,
1194
+ systemPrompt: overrides?.systemPrompt,
1195
+ maxTokens: overrides?.maxTokens
1196
+ };
1197
+ }
1198
+ var DEFAULT_SYSTEM_PROMPT, ModelAdapter, PROVIDERS;
1199
+ var init_model_adapter = __esm({
1200
+ "src/runtime/model-adapter.ts"() {
1201
+ "use strict";
1202
+ DEFAULT_SYSTEM_PROMPT = `You are an AI assistant operating under NeuroVerse governance.
1203
+ All your tool calls are evaluated against governance rules before execution.
1204
+ If an action is blocked, you will be told why. Adjust your approach accordingly.
1205
+ Do not attempt to bypass governance rules.`;
1206
+ ModelAdapter = class {
1207
+ config;
1208
+ messages;
1209
+ tools;
1210
+ constructor(config, tools = []) {
1211
+ this.config = config;
1212
+ this.tools = tools;
1213
+ this.messages = [];
1214
+ const systemPrompt = config.systemPrompt ?? DEFAULT_SYSTEM_PROMPT;
1215
+ this.messages.push({ role: "system", content: systemPrompt });
1216
+ }
1217
+ /**
1218
+ * Send a user message and get the model's response.
1219
+ */
1220
+ async chat(userMessage) {
1221
+ this.messages.push({ role: "user", content: userMessage });
1222
+ return this.complete();
1223
+ }
1224
+ /**
1225
+ * Send a tool result back to the model and get the next response.
1226
+ */
1227
+ async sendToolResult(toolCallId, result) {
1228
+ this.messages.push({
1229
+ role: "tool",
1230
+ content: result,
1231
+ tool_call_id: toolCallId
1232
+ });
1233
+ return this.complete();
1234
+ }
1235
+ /**
1236
+ * Send a governance block message as a tool result.
1237
+ */
1238
+ async sendBlockedResult(toolCallId, reason) {
1239
+ return this.sendToolResult(
1240
+ toolCallId,
1241
+ `[GOVERNANCE BLOCKED] ${reason}. Please adjust your approach.`
1242
+ );
1243
+ }
1244
+ /**
1245
+ * Call the model API and parse the response.
1246
+ */
1247
+ async complete() {
1248
+ const url = `${this.config.baseUrl}/chat/completions`;
1249
+ const body = {
1250
+ model: this.config.model,
1251
+ messages: this.messages,
1252
+ max_tokens: this.config.maxTokens ?? 4096
1253
+ };
1254
+ if (this.tools.length > 0) {
1255
+ body.tools = this.tools;
1256
+ }
1257
+ const response = await fetch(url, {
1258
+ method: "POST",
1259
+ headers: {
1260
+ "Content-Type": "application/json",
1261
+ "Authorization": `Bearer ${this.config.apiKey}`
1262
+ },
1263
+ body: JSON.stringify(body)
1264
+ });
1265
+ if (!response.ok) {
1266
+ const text = await response.text();
1267
+ throw new Error(`Model API error ${response.status}: ${text}`);
1268
+ }
1269
+ const data = await response.json();
1270
+ const choice = data.choices?.[0];
1271
+ if (!choice) {
1272
+ throw new Error("Model returned no choices");
1273
+ }
1274
+ const message = choice.message;
1275
+ this.messages.push(message);
1276
+ return {
1277
+ content: message.content ?? null,
1278
+ toolCalls: message.tool_calls ?? [],
1279
+ finishReason: choice.finish_reason ?? "stop"
1280
+ };
1281
+ }
1282
+ /** Get current message count (for context tracking). */
1283
+ get messageCount() {
1284
+ return this.messages.length;
1285
+ }
1286
+ };
1287
+ PROVIDERS = {
1288
+ openai: {
1289
+ baseUrl: "https://api.openai.com/v1",
1290
+ defaultModel: "gpt-4o",
1291
+ envVar: "OPENAI_API_KEY"
1292
+ },
1293
+ anthropic: {
1294
+ baseUrl: "https://api.anthropic.com/v1",
1295
+ defaultModel: "claude-sonnet-4-20250514",
1296
+ envVar: "ANTHROPIC_API_KEY"
1297
+ },
1298
+ ollama: {
1299
+ baseUrl: "http://localhost:11434/v1",
1300
+ defaultModel: "llama3",
1301
+ envVar: ""
1302
+ }
1303
+ };
1304
+ }
1305
+ });
1306
+
1307
1307
  // src/loader/world-loader.ts
1308
1308
  async function loadWorldFromDirectory(dirPath) {
1309
1309
  const { readFile } = await import("fs/promises");
@@ -1500,11 +1500,17 @@ async function runPipeMode(config) {
1500
1500
  process.stderr.write(`[neuroverse] Plan: ${state.plan.plan_id} (${state.plan.objective})
1501
1501
  `);
1502
1502
  }
1503
+ const MAX_BUFFER_SIZE = 1e6;
1503
1504
  return new Promise((resolve2, reject) => {
1504
1505
  let buffer = "";
1505
1506
  process.stdin.setEncoding("utf-8");
1506
1507
  process.stdin.on("data", (chunk) => {
1507
1508
  buffer += chunk;
1509
+ if (buffer.length > MAX_BUFFER_SIZE) {
1510
+ process.stderr.write("[neuroverse] Warning: pipe buffer exceeded 1MB, resetting\n");
1511
+ buffer = "";
1512
+ return;
1513
+ }
1508
1514
  const lines = buffer.split("\n");
1509
1515
  buffer = lines.pop() ?? "";
1510
1516
  for (const line of lines) {
@@ -1669,7 +1675,9 @@ var init_session = __esm({
1669
1675
  init_plan_engine();
1670
1676
  init_world_loader();
1671
1677
  init_decision_flow_engine();
1672
- SessionManager = class {
1678
+ SessionManager = class _SessionManager {
1679
+ /** Maximum unique agent IDs tracked before eviction. Prevents unbounded memory growth. */
1680
+ static MAX_AGENTS = 1e4;
1673
1681
  config;
1674
1682
  state;
1675
1683
  engineOptions;
@@ -1733,6 +1741,16 @@ var init_session = __esm({
1733
1741
  if (verdict.status === "REWARD" && verdict.reward) {
1734
1742
  agentState = applyReward(agentState, verdict.reward, verdict.ruleId ?? "unknown");
1735
1743
  }
1744
+ if (this.state.agentStates.size >= _SessionManager.MAX_AGENTS && !this.state.agentStates.has(event.roleId)) {
1745
+ const oldest = this.state.agentStates.keys().next().value;
1746
+ if (oldest !== void 0) {
1747
+ this.state.agentStates.delete(oldest);
1748
+ }
1749
+ process.stderr.write(
1750
+ `[neuroverse] Warning: agent state map at capacity (${_SessionManager.MAX_AGENTS}), evicted oldest entry
1751
+ `
1752
+ );
1753
+ }
1736
1754
  this.state.agentStates.set(event.roleId, agentState);
1737
1755
  }
1738
1756
  this.config.onVerdict?.(verdict, event);
@@ -1917,6 +1935,77 @@ function resolveNameOrPath(ref, cwd) {
1917
1935
  return (0, import_path.resolve)(cwd, ref);
1918
1936
  }
1919
1937
 
1938
+ // src/engine/audit-logger.ts
1939
+ init_guard_engine();
1940
+ var FileAuditLogger = class {
1941
+ logPath;
1942
+ buffer = [];
1943
+ flushTimer = null;
1944
+ flushIntervalMs;
1945
+ constructor(logPath, options) {
1946
+ this.logPath = logPath;
1947
+ this.flushIntervalMs = options?.flushIntervalMs ?? 1e3;
1948
+ }
1949
+ log(event) {
1950
+ this.buffer.push(JSON.stringify(event));
1951
+ if (!this.flushTimer) {
1952
+ this.flushTimer = setTimeout(() => {
1953
+ void this.flush();
1954
+ }, this.flushIntervalMs);
1955
+ }
1956
+ }
1957
+ async flush() {
1958
+ if (this.buffer.length === 0) return;
1959
+ if (this.flushTimer) {
1960
+ clearTimeout(this.flushTimer);
1961
+ this.flushTimer = null;
1962
+ }
1963
+ const lines = this.buffer.splice(0).join("\n") + "\n";
1964
+ try {
1965
+ const { appendFile, mkdir } = await import("fs/promises");
1966
+ const { dirname } = await import("path");
1967
+ await mkdir(dirname(this.logPath), { recursive: true });
1968
+ await appendFile(this.logPath, lines, "utf-8");
1969
+ } catch {
1970
+ }
1971
+ }
1972
+ };
1973
+ function verdictToAuditEvent(event, verdict) {
1974
+ const auditEvent = {
1975
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1976
+ worldId: verdict.evidence.worldId,
1977
+ worldName: verdict.evidence.worldName,
1978
+ worldVersion: verdict.evidence.worldVersion,
1979
+ intent: event.intent,
1980
+ tool: event.tool,
1981
+ scope: event.scope,
1982
+ actor: event.roleId,
1983
+ direction: event.direction,
1984
+ decision: verdict.status,
1985
+ reason: verdict.reason,
1986
+ ruleId: verdict.ruleId,
1987
+ warning: verdict.warning,
1988
+ guardsMatched: verdict.evidence.guardsMatched,
1989
+ rulesMatched: verdict.evidence.rulesMatched,
1990
+ invariantsSatisfied: verdict.evidence.invariantsSatisfied,
1991
+ invariantsTotal: verdict.evidence.invariantsTotal,
1992
+ enforcementLevel: verdict.evidence.enforcementLevel,
1993
+ durationMs: verdict.trace?.durationMs,
1994
+ args: event.args
1995
+ };
1996
+ if (verdict.consequence) {
1997
+ auditEvent.consequence = verdict.consequence;
1998
+ }
1999
+ if (verdict.reward) {
2000
+ auditEvent.reward = verdict.reward;
2001
+ }
2002
+ if (verdict.intentRecord) {
2003
+ auditEvent.originalIntent = verdict.intentRecord.originalIntent;
2004
+ auditEvent.finalAction = verdict.intentRecord.finalAction;
2005
+ }
2006
+ return auditEvent;
2007
+ }
2008
+
1920
2009
  // src/cli/run.ts
1921
2010
  function parseArg(args, flag) {
1922
2011
  const idx = args.indexOf(flag);
@@ -1991,8 +2080,15 @@ async function main(args) {
1991
2080
  const plan = planPath ? loadPlan(planPath) : autoDetectPlan();
1992
2081
  const level = parseArg(args, "--level");
1993
2082
  const trace = hasFlag(args, "--trace");
2083
+ const logPath = parseArg(args, "--log");
1994
2084
  const isPipeMode = hasFlag(args, "--pipe") || !process.stdin.isTTY;
1995
2085
  const isInteractive = hasFlag(args, "--interactive");
2086
+ let auditLogger;
2087
+ if (logPath) {
2088
+ auditLogger = new FileAuditLogger(logPath);
2089
+ process.stderr.write(`[neuroverse] Audit logging to ${logPath}
2090
+ `);
2091
+ }
1996
2092
  if (isInteractive) {
1997
2093
  const providerName = parseArg(args, "--provider");
1998
2094
  if (!providerName) {
@@ -2016,6 +2112,9 @@ async function main(args) {
2016
2112
  level,
2017
2113
  trace,
2018
2114
  onVerdict: (verdict, event) => {
2115
+ if (auditLogger) {
2116
+ auditLogger.log(verdictToAuditEvent(event, verdict));
2117
+ }
2019
2118
  if (verdict.status !== "ALLOW") {
2020
2119
  process.stderr.write(
2021
2120
  ` [${verdict.status}] ${event.intent} \u2014 ${verdict.reason ?? verdict.ruleId ?? "governance rule"}
@@ -2042,8 +2141,12 @@ async function main(args) {
2042
2141
  worldPath,
2043
2142
  plan,
2044
2143
  level,
2045
- trace
2144
+ trace,
2145
+ onVerdict: auditLogger ? (verdict, event) => {
2146
+ auditLogger.log(verdictToAuditEvent(event, verdict));
2147
+ } : void 0
2046
2148
  });
2149
+ if (auditLogger) await auditLogger.flush();
2047
2150
  } else {
2048
2151
  process.stdout.write(RUN_USAGE + "\n");
2049
2152
  process.exit(0);
package/dist/cli/run.js CHANGED
@@ -1,7 +1,13 @@
1
+ import {
2
+ FileAuditLogger,
3
+ verdictToAuditEvent
4
+ } from "../chunk-2VAWP6FI.js";
1
5
  import {
2
6
  describeActiveWorld,
3
7
  resolveWorldPath
4
8
  } from "../chunk-AKW5YVCE.js";
9
+ import "../chunk-ZAF6JH23.js";
10
+ import "../chunk-QLPTHTVB.js";
5
11
  import "../chunk-QWGCMQQD.js";
6
12
 
7
13
  // src/cli/run.ts
@@ -80,8 +86,15 @@ async function main(args) {
80
86
  const plan = planPath ? loadPlan(planPath) : autoDetectPlan();
81
87
  const level = parseArg(args, "--level");
82
88
  const trace = hasFlag(args, "--trace");
89
+ const logPath = parseArg(args, "--log");
83
90
  const isPipeMode = hasFlag(args, "--pipe") || !process.stdin.isTTY;
84
91
  const isInteractive = hasFlag(args, "--interactive");
92
+ let auditLogger;
93
+ if (logPath) {
94
+ auditLogger = new FileAuditLogger(logPath);
95
+ process.stderr.write(`[neuroverse] Audit logging to ${logPath}
96
+ `);
97
+ }
85
98
  if (isInteractive) {
86
99
  const providerName = parseArg(args, "--provider");
87
100
  if (!providerName) {
@@ -92,7 +105,7 @@ async function main(args) {
92
105
  return;
93
106
  }
94
107
  const { resolveProvider, ModelAdapter } = await import("../model-adapter-VXEKB4LS.js");
95
- const { runInteractiveMode } = await import("../session-XZP2754M.js");
108
+ const { runInteractiveMode } = await import("../session-NGA4DUPL.js");
96
109
  const modelConfig = resolveProvider(providerName, {
97
110
  model: parseArg(args, "--model"),
98
111
  apiKey: parseArg(args, "--api-key")
@@ -105,6 +118,9 @@ async function main(args) {
105
118
  level,
106
119
  trace,
107
120
  onVerdict: (verdict, event) => {
121
+ if (auditLogger) {
122
+ auditLogger.log(verdictToAuditEvent(event, verdict));
123
+ }
108
124
  if (verdict.status !== "ALLOW") {
109
125
  process.stderr.write(
110
126
  ` [${verdict.status}] ${event.intent} \u2014 ${verdict.reason ?? verdict.ruleId ?? "governance rule"}
@@ -126,13 +142,17 @@ async function main(args) {
126
142
  model
127
143
  );
128
144
  } else if (isPipeMode) {
129
- const { runPipeMode } = await import("../session-XZP2754M.js");
145
+ const { runPipeMode } = await import("../session-NGA4DUPL.js");
130
146
  await runPipeMode({
131
147
  worldPath,
132
148
  plan,
133
149
  level,
134
- trace
150
+ trace,
151
+ onVerdict: auditLogger ? (verdict, event) => {
152
+ auditLogger.log(verdictToAuditEvent(event, verdict));
153
+ } : void 0
135
154
  });
155
+ if (auditLogger) await auditLogger.flush();
136
156
  } else {
137
157
  process.stdout.write(RUN_USAGE + "\n");
138
158
  process.exit(0);