@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
@@ -2002,10 +2002,10 @@ __export(world_loader_exports, {
2002
2002
  });
2003
2003
  async function loadWorldFromDirectory(dirPath) {
2004
2004
  const { readFile: readFile3 } = await import("fs/promises");
2005
- const { join: join9 } = await import("path");
2006
- const { readdirSync: readdirSync5 } = await import("fs");
2005
+ const { join: join13 } = await import("path");
2006
+ const { readdirSync: readdirSync6 } = await import("fs");
2007
2007
  async function readJson(filename) {
2008
- const filePath = join9(dirPath, filename);
2008
+ const filePath = join13(dirPath, filename);
2009
2009
  try {
2010
2010
  const content = await readFile3(filePath, "utf-8");
2011
2011
  return JSON.parse(content);
@@ -2035,11 +2035,11 @@ async function loadWorldFromDirectory(dirPath) {
2035
2035
  const metadataJson = await readJson("metadata.json");
2036
2036
  const rules = [];
2037
2037
  try {
2038
- const rulesDir = join9(dirPath, "rules");
2039
- const ruleFiles = readdirSync5(rulesDir).filter((f) => f.endsWith(".json")).sort();
2038
+ const rulesDir = join13(dirPath, "rules");
2039
+ const ruleFiles = readdirSync6(rulesDir).filter((f) => f.endsWith(".json")).sort();
2040
2040
  for (const file of ruleFiles) {
2041
2041
  try {
2042
- const content = await readFile3(join9(rulesDir, file), "utf-8");
2042
+ const content = await readFile3(join13(rulesDir, file), "utf-8");
2043
2043
  rules.push(JSON.parse(content));
2044
2044
  } catch (err) {
2045
2045
  process.stderr.write(
@@ -2093,8 +2093,8 @@ async function loadWorld(worldPath) {
2093
2093
  }
2094
2094
  async function loadBundledWorld(name = DEFAULT_BUNDLED_WORLD) {
2095
2095
  const { readFile: readFile3 } = await import("fs/promises");
2096
- const { join: join9, dirname: dirname3 } = await import("path");
2097
- const { existsSync: existsSync6 } = await import("fs");
2096
+ const { join: join13, dirname: dirname3 } = await import("path");
2097
+ const { existsSync: existsSync9 } = await import("fs");
2098
2098
  const { fileURLToPath: fileURLToPath3 } = await import("url");
2099
2099
  const { parseWorldMarkdown: parseWorldMarkdown2 } = await Promise.resolve().then(() => (init_bootstrap_parser(), bootstrap_parser_exports));
2100
2100
  const { emitWorldDefinition: emitWorldDefinition2 } = await Promise.resolve().then(() => (init_bootstrap_emitter(), bootstrap_emitter_exports));
@@ -2102,16 +2102,16 @@ async function loadBundledWorld(name = DEFAULT_BUNDLED_WORLD) {
2102
2102
  let packageRoot;
2103
2103
  try {
2104
2104
  const thisFile = typeof __dirname !== "undefined" ? __dirname : dirname3(fileURLToPath3(import_meta.url));
2105
- packageRoot = join9(thisFile, "..", "..");
2105
+ packageRoot = join13(thisFile, "..", "..");
2106
2106
  } catch {
2107
2107
  packageRoot = process.cwd();
2108
2108
  }
2109
2109
  const candidates = [
2110
- join9(packageRoot, "dist", "worlds", filename),
2111
- join9(packageRoot, "src", "worlds", filename)
2110
+ join13(packageRoot, "dist", "worlds", filename),
2111
+ join13(packageRoot, "src", "worlds", filename)
2112
2112
  ];
2113
2113
  for (const candidate of candidates) {
2114
- if (existsSync6(candidate)) {
2114
+ if (existsSync9(candidate)) {
2115
2115
  const markdown = await readFile3(candidate, "utf-8");
2116
2116
  const parsed = parseWorldMarkdown2(markdown);
2117
2117
  if (!parsed.world) {
@@ -2141,8 +2141,8 @@ function slugify(text) {
2141
2141
  }
2142
2142
  async function addGuard(worldDir, input) {
2143
2143
  const { readFile: readFile3, writeFile: writeFile5 } = await import("fs/promises");
2144
- const { join: join9 } = await import("path");
2145
- const guardsPath = join9(worldDir, "guards.json");
2144
+ const { join: join13 } = await import("path");
2145
+ const guardsPath = join13(worldDir, "guards.json");
2146
2146
  let config;
2147
2147
  try {
2148
2148
  const raw = await readFile3(guardsPath, "utf-8");
@@ -2182,13 +2182,13 @@ async function addGuard(worldDir, input) {
2182
2182
  }
2183
2183
  async function addRule(worldDir, input) {
2184
2184
  const { readFile: readFile3, writeFile: writeFile5, mkdir: mkdir2 } = await import("fs/promises");
2185
- const { join: join9 } = await import("path");
2186
- const { readdirSync: readdirSync5 } = await import("fs");
2187
- const rulesDir = join9(worldDir, "rules");
2185
+ const { join: join13 } = await import("path");
2186
+ const { readdirSync: readdirSync6 } = await import("fs");
2187
+ const rulesDir = join13(worldDir, "rules");
2188
2188
  await mkdir2(rulesDir, { recursive: true });
2189
2189
  let nextNum = 1;
2190
2190
  try {
2191
- const existing = readdirSync5(rulesDir).filter((f) => f.match(/^rule-\d+\.json$/)).sort();
2191
+ const existing = readdirSync6(rulesDir).filter((f) => f.match(/^rule-\d+\.json$/)).sort();
2192
2192
  if (existing.length > 0) {
2193
2193
  const lastFile = existing[existing.length - 1];
2194
2194
  const match = lastFile.match(/rule-(\d+)\.json/);
@@ -2214,7 +2214,7 @@ async function addRule(worldDir, input) {
2214
2214
  effect_text: input.effects ? input.effects.map((e) => `${e.target} ${e.operation} ${e.value}`).join(", ") : "No direct effects"
2215
2215
  }
2216
2216
  };
2217
- const rulePath = join9(rulesDir, `rule-${ruleNum}.json`);
2217
+ const rulePath = join13(rulesDir, `rule-${ruleNum}.json`);
2218
2218
  await writeFile5(rulePath, JSON.stringify(rule, null, 2) + "\n");
2219
2219
  const { loadWorldFromDirectory: loadWorldFromDirectory3 } = await Promise.resolve().then(() => (init_world_loader(), world_loader_exports));
2220
2220
  const world = await loadWorldFromDirectory3(worldDir);
@@ -2230,8 +2230,8 @@ async function addRule(worldDir, input) {
2230
2230
  }
2231
2231
  async function addInvariant(worldDir, input) {
2232
2232
  const { readFile: readFile3, writeFile: writeFile5 } = await import("fs/promises");
2233
- const { join: join9 } = await import("path");
2234
- const invariantsPath = join9(worldDir, "invariants.json");
2233
+ const { join: join13 } = await import("path");
2234
+ const invariantsPath = join13(worldDir, "invariants.json");
2235
2235
  let config;
2236
2236
  try {
2237
2237
  const raw = await readFile3(invariantsPath, "utf-8");
@@ -2849,27 +2849,27 @@ ${candidates.map((c) => ` - ${c}`).join("\n")}`
2849
2849
  }
2850
2850
  async function collectMarkdownSources(inputPath) {
2851
2851
  const { stat, readFile: rf, readdir } = await import("fs/promises");
2852
- const { join: pathJoin, extname: extname2, basename: basename2 } = await import("path");
2852
+ const { join: pathJoin, extname: extname2, basename: basename3 } = await import("path");
2853
2853
  const stats = await stat(inputPath);
2854
2854
  if (stats.isFile()) {
2855
2855
  const content = await rf(inputPath, "utf-8");
2856
- return [{ filename: basename2(inputPath), content }];
2856
+ return [{ filename: basename3(inputPath), content }];
2857
2857
  }
2858
2858
  if (stats.isDirectory()) {
2859
2859
  const sources = [];
2860
- await collectDir(inputPath, sources, rf, pathJoin, extname2, basename2);
2860
+ await collectDir(inputPath, sources, rf, pathJoin, extname2, basename3);
2861
2861
  sources.sort((a, b) => a.filename.localeCompare(b.filename));
2862
2862
  return sources;
2863
2863
  }
2864
2864
  throw new Error(`Input path is neither a file nor a directory: ${inputPath}`);
2865
2865
  }
2866
- async function collectDir(dir, sources, rf, pathJoin, extname2, basename2) {
2866
+ async function collectDir(dir, sources, rf, pathJoin, extname2, basename3) {
2867
2867
  const { readdir } = await import("fs/promises");
2868
2868
  const entries = await readdir(dir, { withFileTypes: true });
2869
2869
  for (const entry of entries) {
2870
2870
  const fullPath = pathJoin(dir, entry.name);
2871
2871
  if (entry.isDirectory()) {
2872
- await collectDir(fullPath, sources, rf, pathJoin, extname2, basename2);
2872
+ await collectDir(fullPath, sources, rf, pathJoin, extname2, basename3);
2873
2873
  } else if (entry.isFile() && extname2(entry.name).toLowerCase() === ".md") {
2874
2874
  const content = await rf(fullPath, "utf-8");
2875
2875
  sources.push({ filename: entry.name, content });
@@ -3528,21 +3528,21 @@ function parseArgs2(argv) {
3528
3528
  }
3529
3529
  async function writeWorldFiles(outputDir, world) {
3530
3530
  const { writeFile: writeFile5, mkdir: mkdir2 } = await import("fs/promises");
3531
- const { join: join9 } = await import("path");
3531
+ const { join: join13 } = await import("path");
3532
3532
  await mkdir2(outputDir, { recursive: true });
3533
- await writeFile5(join9(outputDir, "world.json"), JSON.stringify(world.world, null, 2));
3534
- await writeFile5(join9(outputDir, "invariants.json"), JSON.stringify({ invariants: world.invariants }, null, 2));
3535
- await writeFile5(join9(outputDir, "assumptions.json"), JSON.stringify(world.assumptions, null, 2));
3536
- await writeFile5(join9(outputDir, "state-schema.json"), JSON.stringify(world.stateSchema, null, 2));
3537
- await writeFile5(join9(outputDir, "gates.json"), JSON.stringify(world.gates, null, 2));
3538
- await writeFile5(join9(outputDir, "outcomes.json"), JSON.stringify(world.outcomes, null, 2));
3539
- await writeFile5(join9(outputDir, "metadata.json"), JSON.stringify(world.metadata, null, 2));
3540
- const rulesDir = join9(outputDir, "rules");
3533
+ await writeFile5(join13(outputDir, "world.json"), JSON.stringify(world.world, null, 2));
3534
+ await writeFile5(join13(outputDir, "invariants.json"), JSON.stringify({ invariants: world.invariants }, null, 2));
3535
+ await writeFile5(join13(outputDir, "assumptions.json"), JSON.stringify(world.assumptions, null, 2));
3536
+ await writeFile5(join13(outputDir, "state-schema.json"), JSON.stringify(world.stateSchema, null, 2));
3537
+ await writeFile5(join13(outputDir, "gates.json"), JSON.stringify(world.gates, null, 2));
3538
+ await writeFile5(join13(outputDir, "outcomes.json"), JSON.stringify(world.outcomes, null, 2));
3539
+ await writeFile5(join13(outputDir, "metadata.json"), JSON.stringify(world.metadata, null, 2));
3540
+ const rulesDir = join13(outputDir, "rules");
3541
3541
  await mkdir2(rulesDir, { recursive: true });
3542
3542
  const sortedRules = [...world.rules].sort((a, b) => a.order - b.order);
3543
3543
  for (let i = 0; i < sortedRules.length; i++) {
3544
3544
  const ruleNum = String(i + 1).padStart(3, "0");
3545
- await writeFile5(join9(rulesDir, `rule-${ruleNum}.json`), JSON.stringify(sortedRules[i], null, 2));
3545
+ await writeFile5(join13(rulesDir, `rule-${ruleNum}.json`), JSON.stringify(sortedRules[i], null, 2));
3546
3546
  }
3547
3547
  }
3548
3548
  function write(msg) {
@@ -3557,12 +3557,12 @@ function printInsight(finding2) {
3557
3557
  async function main2(argv = process.argv.slice(2)) {
3558
3558
  try {
3559
3559
  const args = parseArgs2(argv);
3560
- const { basename: basename2 } = await import("path");
3560
+ const { basename: basename3 } = await import("path");
3561
3561
  write(`
3562
3562
  NeuroVerse World Builder
3563
3563
  `);
3564
3564
  write(`
3565
- Analyzing: ${basename2(args.inputPath)}
3565
+ Analyzing: ${basename3(args.inputPath)}
3566
3566
  `);
3567
3567
  const derivedPath = args.outputDir ? `${args.outputDir}/source.nv-world.md` : ".neuroverse/build-output.nv-world.md";
3568
3568
  const { mkdir: mkdir2 } = await import("fs/promises");
@@ -3673,9 +3673,9 @@ World source written to: ${derivedPath}
3673
3673
  try {
3674
3674
  const emitResult = emitWorldDefinition(parseResult.world);
3675
3675
  await writeWorldFiles(outputDir, emitResult.world);
3676
- const { join: join9 } = await import("path");
3676
+ const { join: join13 } = await import("path");
3677
3677
  const { copyFile } = await import("fs/promises");
3678
- const sourceDest = join9(outputDir, "source.nv-world.md");
3678
+ const sourceDest = join13(outputDir, "source.nv-world.md");
3679
3679
  if (derivedPath !== sourceDest) {
3680
3680
  await copyFile(derivedPath, sourceDest);
3681
3681
  }
@@ -5009,8 +5009,8 @@ async function main6(argv = process.argv.slice(2)) {
5009
5009
  try {
5010
5010
  const args = parseArgs6(argv);
5011
5011
  const { writeFile: writeFile5 } = await import("fs/promises");
5012
- const { existsSync: existsSync6 } = await import("fs");
5013
- if (existsSync6(args.outputPath)) {
5012
+ const { existsSync: existsSync9 } = await import("fs");
5013
+ if (existsSync9(args.outputPath)) {
5014
5014
  process.stderr.write(`File already exists: ${args.outputPath}
5015
5015
  `);
5016
5016
  process.stderr.write("Use a different --output path or remove the existing file.\n");
@@ -5868,22 +5868,22 @@ function parseArgs9(argv) {
5868
5868
  }
5869
5869
  async function writeWorldFiles2(outputDir, world) {
5870
5870
  const { writeFile: writeFile5, mkdir: mkdir2 } = await import("fs/promises");
5871
- const { join: join9 } = await import("path");
5871
+ const { join: join13 } = await import("path");
5872
5872
  await mkdir2(outputDir, { recursive: true });
5873
- await writeFile5(join9(outputDir, "world.json"), JSON.stringify(world.world, null, 2));
5874
- await writeFile5(join9(outputDir, "invariants.json"), JSON.stringify({ invariants: world.invariants }, null, 2));
5875
- await writeFile5(join9(outputDir, "assumptions.json"), JSON.stringify(world.assumptions, null, 2));
5876
- await writeFile5(join9(outputDir, "state-schema.json"), JSON.stringify(world.stateSchema, null, 2));
5877
- const rulesDir = join9(outputDir, "rules");
5873
+ await writeFile5(join13(outputDir, "world.json"), JSON.stringify(world.world, null, 2));
5874
+ await writeFile5(join13(outputDir, "invariants.json"), JSON.stringify({ invariants: world.invariants }, null, 2));
5875
+ await writeFile5(join13(outputDir, "assumptions.json"), JSON.stringify(world.assumptions, null, 2));
5876
+ await writeFile5(join13(outputDir, "state-schema.json"), JSON.stringify(world.stateSchema, null, 2));
5877
+ const rulesDir = join13(outputDir, "rules");
5878
5878
  await mkdir2(rulesDir, { recursive: true });
5879
5879
  const sortedRules = [...world.rules].sort((a, b) => a.order - b.order);
5880
5880
  for (let i = 0; i < sortedRules.length; i++) {
5881
5881
  const ruleNum = String(i + 1).padStart(3, "0");
5882
- await writeFile5(join9(rulesDir, `rule-${ruleNum}.json`), JSON.stringify(sortedRules[i], null, 2));
5882
+ await writeFile5(join13(rulesDir, `rule-${ruleNum}.json`), JSON.stringify(sortedRules[i], null, 2));
5883
5883
  }
5884
- await writeFile5(join9(outputDir, "gates.json"), JSON.stringify(world.gates, null, 2));
5885
- await writeFile5(join9(outputDir, "outcomes.json"), JSON.stringify(world.outcomes, null, 2));
5886
- await writeFile5(join9(outputDir, "metadata.json"), JSON.stringify(world.metadata, null, 2));
5884
+ await writeFile5(join13(outputDir, "gates.json"), JSON.stringify(world.gates, null, 2));
5885
+ await writeFile5(join13(outputDir, "outcomes.json"), JSON.stringify(world.outcomes, null, 2));
5886
+ await writeFile5(join13(outputDir, "metadata.json"), JSON.stringify(world.metadata, null, 2));
5887
5887
  }
5888
5888
  async function main9(argv = process.argv.slice(2)) {
5889
5889
  const startTime = performance.now();
@@ -7364,6 +7364,162 @@ var init_guard_contract = __esm({
7364
7364
  }
7365
7365
  });
7366
7366
 
7367
+ // src/engine/audit-logger.ts
7368
+ function verdictToAuditEvent(event, verdict) {
7369
+ const auditEvent = {
7370
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
7371
+ worldId: verdict.evidence.worldId,
7372
+ worldName: verdict.evidence.worldName,
7373
+ worldVersion: verdict.evidence.worldVersion,
7374
+ intent: event.intent,
7375
+ tool: event.tool,
7376
+ scope: event.scope,
7377
+ actor: event.roleId,
7378
+ direction: event.direction,
7379
+ decision: verdict.status,
7380
+ reason: verdict.reason,
7381
+ ruleId: verdict.ruleId,
7382
+ warning: verdict.warning,
7383
+ guardsMatched: verdict.evidence.guardsMatched,
7384
+ rulesMatched: verdict.evidence.rulesMatched,
7385
+ invariantsSatisfied: verdict.evidence.invariantsSatisfied,
7386
+ invariantsTotal: verdict.evidence.invariantsTotal,
7387
+ enforcementLevel: verdict.evidence.enforcementLevel,
7388
+ durationMs: verdict.trace?.durationMs,
7389
+ args: event.args
7390
+ };
7391
+ if (verdict.consequence) {
7392
+ auditEvent.consequence = verdict.consequence;
7393
+ }
7394
+ if (verdict.reward) {
7395
+ auditEvent.reward = verdict.reward;
7396
+ }
7397
+ if (verdict.intentRecord) {
7398
+ auditEvent.originalIntent = verdict.intentRecord.originalIntent;
7399
+ auditEvent.finalAction = verdict.intentRecord.finalAction;
7400
+ }
7401
+ return auditEvent;
7402
+ }
7403
+ async function readAuditLog(logPath, filter) {
7404
+ const { readFile: readFile3 } = await import("fs/promises");
7405
+ let content;
7406
+ try {
7407
+ content = await readFile3(logPath, "utf-8");
7408
+ } catch {
7409
+ return [];
7410
+ }
7411
+ const events = [];
7412
+ for (const line of content.split("\n")) {
7413
+ const trimmed = line.trim();
7414
+ if (!trimmed) continue;
7415
+ try {
7416
+ const event = JSON.parse(trimmed);
7417
+ if (!filter || filter(event)) {
7418
+ events.push(event);
7419
+ }
7420
+ } catch {
7421
+ }
7422
+ }
7423
+ return events;
7424
+ }
7425
+ function summarizeAuditEvents(events) {
7426
+ const allowed = events.filter((e) => e.decision === "ALLOW").length;
7427
+ const blocked = events.filter((e) => e.decision === "BLOCK").length;
7428
+ const paused = events.filter((e) => e.decision === "PAUSE").length;
7429
+ const modified = events.filter((e) => e.decision === "MODIFY").length;
7430
+ const penalized = events.filter((e) => e.decision === "PENALIZE").length;
7431
+ const rewarded = events.filter((e) => e.decision === "REWARD").length;
7432
+ const neutral = events.filter((e) => e.decision === "NEUTRAL").length;
7433
+ const actorSet = /* @__PURE__ */ new Set();
7434
+ for (const e of events) {
7435
+ if (e.actor) actorSet.add(e.actor);
7436
+ }
7437
+ const intentMap = /* @__PURE__ */ new Map();
7438
+ for (const e of events) {
7439
+ const entry = intentMap.get(e.intent) ?? { count: 0, blocked: 0, paused: 0, penalized: 0, rewarded: 0 };
7440
+ entry.count++;
7441
+ if (e.decision === "BLOCK") entry.blocked++;
7442
+ if (e.decision === "PAUSE") entry.paused++;
7443
+ if (e.decision === "PENALIZE") entry.penalized++;
7444
+ if (e.decision === "REWARD") entry.rewarded++;
7445
+ intentMap.set(e.intent, entry);
7446
+ }
7447
+ const topIntents = [...intentMap.entries()].map(([intent, data]) => ({ intent, ...data })).sort((a, b) => b.count - a.count);
7448
+ const ruleMap = /* @__PURE__ */ new Map();
7449
+ for (const e of events) {
7450
+ if (e.ruleId) {
7451
+ ruleMap.set(e.ruleId, (ruleMap.get(e.ruleId) ?? 0) + 1);
7452
+ }
7453
+ for (const g of e.guardsMatched) {
7454
+ ruleMap.set(g, (ruleMap.get(g) ?? 0) + 1);
7455
+ }
7456
+ }
7457
+ const topRules = [...ruleMap.entries()].map(([ruleId, count]) => ({ ruleId, count })).sort((a, b) => b.count - a.count);
7458
+ const redirected = blocked + paused + modified + penalized;
7459
+ const total = events.length;
7460
+ return {
7461
+ totalActions: total,
7462
+ allowed,
7463
+ blocked,
7464
+ paused,
7465
+ modified,
7466
+ penalized,
7467
+ rewarded,
7468
+ neutral,
7469
+ actors: [...actorSet],
7470
+ topIntents,
7471
+ topRules,
7472
+ firstEvent: events[0]?.timestamp ?? "",
7473
+ lastEvent: events[events.length - 1]?.timestamp ?? "",
7474
+ behavioralEconomy: {
7475
+ totalPenalties: penalized,
7476
+ totalRewards: rewarded,
7477
+ netPressure: rewarded - penalized,
7478
+ redirectionRate: total > 0 ? redirected / total : 0
7479
+ }
7480
+ };
7481
+ }
7482
+ var FileAuditLogger;
7483
+ var init_audit_logger = __esm({
7484
+ "src/engine/audit-logger.ts"() {
7485
+ "use strict";
7486
+ init_guard_engine();
7487
+ FileAuditLogger = class {
7488
+ logPath;
7489
+ buffer = [];
7490
+ flushTimer = null;
7491
+ flushIntervalMs;
7492
+ constructor(logPath, options) {
7493
+ this.logPath = logPath;
7494
+ this.flushIntervalMs = options?.flushIntervalMs ?? 1e3;
7495
+ }
7496
+ log(event) {
7497
+ this.buffer.push(JSON.stringify(event));
7498
+ if (!this.flushTimer) {
7499
+ this.flushTimer = setTimeout(() => {
7500
+ void this.flush();
7501
+ }, this.flushIntervalMs);
7502
+ }
7503
+ }
7504
+ async flush() {
7505
+ if (this.buffer.length === 0) return;
7506
+ if (this.flushTimer) {
7507
+ clearTimeout(this.flushTimer);
7508
+ this.flushTimer = null;
7509
+ }
7510
+ const lines = this.buffer.splice(0).join("\n") + "\n";
7511
+ try {
7512
+ const { appendFile, mkdir: mkdir2 } = await import("fs/promises");
7513
+ const { dirname: dirname3 } = await import("path");
7514
+ await mkdir2(dirname3(this.logPath), { recursive: true });
7515
+ await appendFile(this.logPath, lines, "utf-8");
7516
+ } catch {
7517
+ }
7518
+ }
7519
+ };
7520
+ }
7521
+ });
7522
+
7367
7523
  // src/cli/guard.ts
7368
7524
  var guard_exports = {};
7369
7525
  __export(guard_exports, {
@@ -7374,6 +7530,7 @@ function parseArgs11(argv) {
7374
7530
  let trace = false;
7375
7531
  let level;
7376
7532
  let aiClassify = false;
7533
+ let logPath;
7377
7534
  for (let i = 0; i < argv.length; i++) {
7378
7535
  const arg = argv[i];
7379
7536
  if (arg === "--world" && i + 1 < argv.length) {
@@ -7382,6 +7539,8 @@ function parseArgs11(argv) {
7382
7539
  trace = true;
7383
7540
  } else if (arg === "--ai-classify") {
7384
7541
  aiClassify = true;
7542
+ } else if (arg === "--log" && i + 1 < argv.length) {
7543
+ logPath = argv[++i];
7385
7544
  } else if (arg === "--level" && i + 1 < argv.length) {
7386
7545
  const val = argv[++i];
7387
7546
  if (val === "basic" || val === "standard" || val === "strict") {
@@ -7391,7 +7550,7 @@ function parseArgs11(argv) {
7391
7550
  }
7392
7551
  }
7393
7552
  }
7394
- return { worldPath, trace, level, aiClassify };
7553
+ return { worldPath, trace, level, aiClassify, logPath };
7395
7554
  }
7396
7555
  async function main11(argv = process.argv.slice(2)) {
7397
7556
  try {
@@ -7451,6 +7610,11 @@ async function main11(argv = process.argv.slice(2)) {
7451
7610
  const options = { trace: args.trace, level: args.level };
7452
7611
  verdict = evaluateGuard(event, world, options);
7453
7612
  }
7613
+ if (args.logPath) {
7614
+ const logger = new FileAuditLogger(args.logPath, { flushIntervalMs: 0 });
7615
+ logger.log(verdictToAuditEvent(event, verdict));
7616
+ await logger.flush();
7617
+ }
7454
7618
  process.stdout.write(JSON.stringify(verdict, null, 2) + "\n");
7455
7619
  const exitCode = GUARD_EXIT_CODES[verdict.status];
7456
7620
  process.exit(exitCode);
@@ -7479,6 +7643,7 @@ var init_guard = __esm({
7479
7643
  init_world_resolver();
7480
7644
  init_guard_contract();
7481
7645
  init_cli_utils();
7646
+ init_audit_logger();
7482
7647
  }
7483
7648
  });
7484
7649
 
@@ -8077,13 +8242,13 @@ function handleHealthCheck() {
8077
8242
  }
8078
8243
  async function handleListPresets(policiesDir) {
8079
8244
  const { readdir, readFile: readFile3 } = await import("fs/promises");
8080
- const { join: join9 } = await import("path");
8081
- const dir = policiesDir ?? join9(process.cwd(), "policies");
8245
+ const { join: join13 } = await import("path");
8246
+ const dir = policiesDir ?? join13(process.cwd(), "policies");
8082
8247
  const presets = [];
8083
8248
  try {
8084
8249
  const files = await readdir(dir);
8085
8250
  for (const file of files.filter((f) => f.endsWith(".txt")).sort()) {
8086
- const content = await readFile3(join9(dir, file), "utf-8");
8251
+ const content = await readFile3(join13(dir, file), "utf-8");
8087
8252
  const id = file.replace(".txt", "");
8088
8253
  const name = id.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
8089
8254
  const firstLine = content.split("\n").find((l) => l.trim().length > 0) ?? "";
@@ -8155,7 +8320,7 @@ function govern(action, world, options) {
8155
8320
  }
8156
8321
  async function writeTempWorld(dir, policyLines) {
8157
8322
  const { writeFile: writeFile5, mkdir: mkdir2 } = await import("fs/promises");
8158
- const { join: join9 } = await import("path");
8323
+ const { join: join13 } = await import("path");
8159
8324
  await mkdir2(dir, { recursive: true });
8160
8325
  const worldJson = {
8161
8326
  world_id: "demo-live",
@@ -8197,9 +8362,9 @@ async function writeTempWorld(dir, policyLines) {
8197
8362
  authoring_method: "manual-authoring"
8198
8363
  };
8199
8364
  await Promise.all([
8200
- writeFile5(join9(dir, "world.json"), JSON.stringify(worldJson, null, 2)),
8201
- writeFile5(join9(dir, "kernel.json"), JSON.stringify(kernelJson, null, 2)),
8202
- writeFile5(join9(dir, "metadata.json"), JSON.stringify(metadataJson, null, 2))
8365
+ writeFile5(join13(dir, "world.json"), JSON.stringify(worldJson, null, 2)),
8366
+ writeFile5(join13(dir, "kernel.json"), JSON.stringify(kernelJson, null, 2)),
8367
+ writeFile5(join13(dir, "metadata.json"), JSON.stringify(metadataJson, null, 2))
8203
8368
  ]);
8204
8369
  }
8205
8370
  var init_govern = __esm({
@@ -11310,9 +11475,9 @@ async function main15(argv) {
11310
11475
  }
11311
11476
  if (worldPath) {
11312
11477
  try {
11313
- const { existsSync: existsSync6 } = await import("fs");
11314
- const { join: join9 } = await import("path");
11315
- const hasWorld = existsSync6(join9(worldPath, "world.json"));
11478
+ const { existsSync: existsSync9 } = await import("fs");
11479
+ const { join: join13 } = await import("path");
11480
+ const hasWorld = existsSync9(join13(worldPath, "world.json"));
11316
11481
  checks.push({
11317
11482
  label: "World file detected",
11318
11483
  status: hasWorld ? "pass" : "fail",
@@ -11327,12 +11492,12 @@ async function main15(argv) {
11327
11492
  });
11328
11493
  }
11329
11494
  } else {
11330
- const { existsSync: existsSync6 } = await import("fs");
11331
- const { join: join9 } = await import("path");
11495
+ const { existsSync: existsSync9 } = await import("fs");
11496
+ const { join: join13 } = await import("path");
11332
11497
  const candidates = ["./world", "./.neuroverse", "./worlds"];
11333
11498
  let found;
11334
11499
  for (const dir of candidates) {
11335
- if (existsSync6(join9(dir, "world.json"))) {
11500
+ if (existsSync9(join13(dir, "world.json"))) {
11336
11501
  found = dir;
11337
11502
  break;
11338
11503
  }
@@ -12384,8 +12549,8 @@ async function deriveCommand(args) {
12384
12549
  return;
12385
12550
  }
12386
12551
  const plan = result.plan;
12387
- const { mkdirSync: mkdirSync3 } = await import("fs");
12388
- mkdirSync3(outputDir, { recursive: true });
12552
+ const { mkdirSync: mkdirSync5 } = await import("fs");
12553
+ mkdirSync5(outputDir, { recursive: true });
12389
12554
  const worldJson = {
12390
12555
  world_id: `plan_${plan.plan_id}`,
12391
12556
  name: `Derived: ${plan.objective}`,
@@ -12982,11 +13147,17 @@ async function runPipeMode(config) {
12982
13147
  process.stderr.write(`[neuroverse] Plan: ${state.plan.plan_id} (${state.plan.objective})
12983
13148
  `);
12984
13149
  }
13150
+ const MAX_BUFFER_SIZE = 1e6;
12985
13151
  return new Promise((resolve5, reject) => {
12986
13152
  let buffer = "";
12987
13153
  process.stdin.setEncoding("utf-8");
12988
13154
  process.stdin.on("data", (chunk) => {
12989
13155
  buffer += chunk;
13156
+ if (buffer.length > MAX_BUFFER_SIZE) {
13157
+ process.stderr.write("[neuroverse] Warning: pipe buffer exceeded 1MB, resetting\n");
13158
+ buffer = "";
13159
+ return;
13160
+ }
12990
13161
  const lines = buffer.split("\n");
12991
13162
  buffer = lines.pop() ?? "";
12992
13163
  for (const line of lines) {
@@ -13151,7 +13322,9 @@ var init_session = __esm({
13151
13322
  init_plan_engine();
13152
13323
  init_world_loader();
13153
13324
  init_decision_flow_engine();
13154
- SessionManager = class {
13325
+ SessionManager = class _SessionManager {
13326
+ /** Maximum unique agent IDs tracked before eviction. Prevents unbounded memory growth. */
13327
+ static MAX_AGENTS = 1e4;
13155
13328
  config;
13156
13329
  state;
13157
13330
  engineOptions;
@@ -13215,6 +13388,16 @@ var init_session = __esm({
13215
13388
  if (verdict.status === "REWARD" && verdict.reward) {
13216
13389
  agentState = applyReward(agentState, verdict.reward, verdict.ruleId ?? "unknown");
13217
13390
  }
13391
+ if (this.state.agentStates.size >= _SessionManager.MAX_AGENTS && !this.state.agentStates.has(event.roleId)) {
13392
+ const oldest = this.state.agentStates.keys().next().value;
13393
+ if (oldest !== void 0) {
13394
+ this.state.agentStates.delete(oldest);
13395
+ }
13396
+ process.stderr.write(
13397
+ `[neuroverse] Warning: agent state map at capacity (${_SessionManager.MAX_AGENTS}), evicted oldest entry
13398
+ `
13399
+ );
13400
+ }
13218
13401
  this.state.agentStates.set(event.roleId, agentState);
13219
13402
  }
13220
13403
  this.config.onVerdict?.(verdict, event);
@@ -13368,8 +13551,15 @@ async function main18(args) {
13368
13551
  const plan = planPath ? loadPlan(planPath) : autoDetectPlan();
13369
13552
  const level = parseArg2(args, "--level");
13370
13553
  const trace = hasFlag(args, "--trace");
13554
+ const logPath = parseArg2(args, "--log");
13371
13555
  const isPipeMode = hasFlag(args, "--pipe") || !process.stdin.isTTY;
13372
13556
  const isInteractive = hasFlag(args, "--interactive");
13557
+ let auditLogger;
13558
+ if (logPath) {
13559
+ auditLogger = new FileAuditLogger(logPath);
13560
+ process.stderr.write(`[neuroverse] Audit logging to ${logPath}
13561
+ `);
13562
+ }
13373
13563
  if (isInteractive) {
13374
13564
  const providerName = parseArg2(args, "--provider");
13375
13565
  if (!providerName) {
@@ -13393,6 +13583,9 @@ async function main18(args) {
13393
13583
  level,
13394
13584
  trace,
13395
13585
  onVerdict: (verdict, event) => {
13586
+ if (auditLogger) {
13587
+ auditLogger.log(verdictToAuditEvent(event, verdict));
13588
+ }
13396
13589
  if (verdict.status !== "ALLOW") {
13397
13590
  process.stderr.write(
13398
13591
  ` [${verdict.status}] ${event.intent} \u2014 ${verdict.reason ?? verdict.ruleId ?? "governance rule"}
@@ -13419,8 +13612,12 @@ async function main18(args) {
13419
13612
  worldPath,
13420
13613
  plan,
13421
13614
  level,
13422
- trace
13615
+ trace,
13616
+ onVerdict: auditLogger ? (verdict, event) => {
13617
+ auditLogger.log(verdictToAuditEvent(event, verdict));
13618
+ } : void 0
13423
13619
  });
13620
+ if (auditLogger) await auditLogger.flush();
13424
13621
  } else {
13425
13622
  process.stdout.write(RUN_USAGE + "\n");
13426
13623
  process.exit(0);
@@ -13433,6 +13630,7 @@ var init_run = __esm({
13433
13630
  import_fs5 = require("fs");
13434
13631
  import_path6 = require("path");
13435
13632
  init_world_resolver();
13633
+ init_audit_logger();
13436
13634
  RUN_USAGE = `
13437
13635
  neuroverse run \u2014 Governed runtime for AI agents.
13438
13636
 
@@ -14224,27 +14422,27 @@ function computeWorldDiff(a, b) {
14224
14422
  }
14225
14423
  async function worldSnapshot(worldPath) {
14226
14424
  const { readdir, readFile: readFile3, mkdir: mkdir2, writeFile: writeFile5 } = await import("fs/promises");
14227
- const { join: join9 } = await import("path");
14425
+ const { join: join13 } = await import("path");
14228
14426
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
14229
- const snapshotDir = join9(worldPath, ".snapshots", timestamp);
14427
+ const snapshotDir = join13(worldPath, ".snapshots", timestamp);
14230
14428
  await mkdir2(snapshotDir, { recursive: true });
14231
14429
  const files = await readdir(worldPath);
14232
14430
  let copied = 0;
14233
14431
  for (const file of files) {
14234
14432
  if (file.endsWith(".json")) {
14235
- const content = await readFile3(join9(worldPath, file), "utf-8");
14236
- await writeFile5(join9(snapshotDir, file), content, "utf-8");
14433
+ const content = await readFile3(join13(worldPath, file), "utf-8");
14434
+ await writeFile5(join13(snapshotDir, file), content, "utf-8");
14237
14435
  copied++;
14238
14436
  }
14239
14437
  }
14240
14438
  try {
14241
- const rulesDir = join9(worldPath, "rules");
14439
+ const rulesDir = join13(worldPath, "rules");
14242
14440
  const ruleFiles = await readdir(rulesDir);
14243
- await mkdir2(join9(snapshotDir, "rules"), { recursive: true });
14441
+ await mkdir2(join13(snapshotDir, "rules"), { recursive: true });
14244
14442
  for (const file of ruleFiles) {
14245
14443
  if (file.endsWith(".json")) {
14246
- const content = await readFile3(join9(rulesDir, file), "utf-8");
14247
- await writeFile5(join9(snapshotDir, "rules", file), content, "utf-8");
14444
+ const content = await readFile3(join13(rulesDir, file), "utf-8");
14445
+ await writeFile5(join13(snapshotDir, "rules", file), content, "utf-8");
14248
14446
  copied++;
14249
14447
  }
14250
14448
  }
@@ -14257,8 +14455,8 @@ async function worldSnapshot(worldPath) {
14257
14455
  }
14258
14456
  async function worldRollback(worldPath) {
14259
14457
  const { readdir, readFile: readFile3, writeFile: writeFile5, mkdir: mkdir2 } = await import("fs/promises");
14260
- const { join: join9 } = await import("path");
14261
- const snapshotsDir = join9(worldPath, ".snapshots");
14458
+ const { join: join13 } = await import("path");
14459
+ const snapshotsDir = join13(worldPath, ".snapshots");
14262
14460
  let snapshots;
14263
14461
  try {
14264
14462
  snapshots = (await readdir(snapshotsDir)).sort();
@@ -14273,34 +14471,34 @@ async function worldRollback(worldPath) {
14273
14471
  return;
14274
14472
  }
14275
14473
  const latest = snapshots[snapshots.length - 1];
14276
- const snapshotDir = join9(snapshotsDir, latest);
14474
+ const snapshotDir = join13(snapshotsDir, latest);
14277
14475
  const backupTimestamp = "pre-rollback-" + (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
14278
- const backupDir = join9(snapshotsDir, backupTimestamp);
14476
+ const backupDir = join13(snapshotsDir, backupTimestamp);
14279
14477
  await mkdir2(backupDir, { recursive: true });
14280
14478
  const currentFiles = await readdir(worldPath);
14281
14479
  for (const file of currentFiles) {
14282
14480
  if (file.endsWith(".json")) {
14283
- const content = await readFile3(join9(worldPath, file), "utf-8");
14284
- await writeFile5(join9(backupDir, file), content, "utf-8");
14481
+ const content = await readFile3(join13(worldPath, file), "utf-8");
14482
+ await writeFile5(join13(backupDir, file), content, "utf-8");
14285
14483
  }
14286
14484
  }
14287
14485
  const snapshotFiles = await readdir(snapshotDir);
14288
14486
  let restored = 0;
14289
14487
  for (const file of snapshotFiles) {
14290
14488
  if (file.endsWith(".json")) {
14291
- const content = await readFile3(join9(snapshotDir, file), "utf-8");
14292
- await writeFile5(join9(worldPath, file), content, "utf-8");
14489
+ const content = await readFile3(join13(snapshotDir, file), "utf-8");
14490
+ await writeFile5(join13(worldPath, file), content, "utf-8");
14293
14491
  restored++;
14294
14492
  }
14295
14493
  }
14296
14494
  try {
14297
- const rulesDir = join9(snapshotDir, "rules");
14495
+ const rulesDir = join13(snapshotDir, "rules");
14298
14496
  const ruleFiles = await readdir(rulesDir);
14299
- await mkdir2(join9(worldPath, "rules"), { recursive: true });
14497
+ await mkdir2(join13(worldPath, "rules"), { recursive: true });
14300
14498
  for (const file of ruleFiles) {
14301
14499
  if (file.endsWith(".json")) {
14302
- const content = await readFile3(join9(rulesDir, file), "utf-8");
14303
- await writeFile5(join9(worldPath, "rules", file), content, "utf-8");
14500
+ const content = await readFile3(join13(rulesDir, file), "utf-8");
14501
+ await writeFile5(join13(worldPath, "rules", file), content, "utf-8");
14304
14502
  restored++;
14305
14503
  }
14306
14504
  }
@@ -14451,177 +14649,55 @@ Options:
14451
14649
  }
14452
14650
  });
14453
14651
 
14454
- // src/engine/audit-logger.ts
14455
- function verdictToAuditEvent(event, verdict) {
14456
- const auditEvent = {
14457
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
14458
- worldId: verdict.evidence.worldId,
14459
- worldName: verdict.evidence.worldName,
14460
- worldVersion: verdict.evidence.worldVersion,
14461
- intent: event.intent,
14462
- tool: event.tool,
14463
- scope: event.scope,
14464
- actor: event.roleId,
14465
- direction: event.direction,
14466
- decision: verdict.status,
14467
- reason: verdict.reason,
14468
- ruleId: verdict.ruleId,
14469
- warning: verdict.warning,
14470
- guardsMatched: verdict.evidence.guardsMatched,
14471
- rulesMatched: verdict.evidence.rulesMatched,
14472
- invariantsSatisfied: verdict.evidence.invariantsSatisfied,
14473
- invariantsTotal: verdict.evidence.invariantsTotal,
14474
- enforcementLevel: verdict.evidence.enforcementLevel,
14475
- durationMs: verdict.trace?.durationMs,
14476
- args: event.args
14477
- };
14478
- if (verdict.consequence) {
14479
- auditEvent.consequence = verdict.consequence;
14652
+ // src/cli/trace.ts
14653
+ var trace_exports = {};
14654
+ __export(trace_exports, {
14655
+ main: () => main20
14656
+ });
14657
+ function parseArgs16(argv) {
14658
+ const args = {};
14659
+ for (let i = 0; i < argv.length; i++) {
14660
+ const arg = argv[i];
14661
+ if (arg === "--summary") {
14662
+ args.summary = true;
14663
+ } else if (arg === "--json") {
14664
+ args.json = true;
14665
+ } else if (arg === "--help" || arg === "-h") {
14666
+ args.help = true;
14667
+ } else if (arg === "--log" && argv[i + 1]) {
14668
+ args.log = argv[++i];
14669
+ } else if (arg === "--filter" && argv[i + 1]) {
14670
+ args.filter = argv[++i].toUpperCase();
14671
+ } else if (arg === "--actor" && argv[i + 1]) {
14672
+ args.actor = argv[++i];
14673
+ } else if (arg === "--intent" && argv[i + 1]) {
14674
+ args.intent = argv[++i];
14675
+ } else if (arg === "--last" && argv[i + 1]) {
14676
+ args.last = argv[++i];
14677
+ }
14480
14678
  }
14481
- if (verdict.reward) {
14482
- auditEvent.reward = verdict.reward;
14679
+ return args;
14680
+ }
14681
+ function formatEvent(event) {
14682
+ const ts = event.timestamp.split("T")[1]?.replace("Z", "").slice(0, 8) ?? event.timestamp;
14683
+ const icon = event.decision === "ALLOW" ? " \u2713" : event.decision === "BLOCK" ? " \u2717" : " \u23F8";
14684
+ const parts = [];
14685
+ parts.push(` [${ts}] ${event.actor ?? "unknown"}`);
14686
+ parts.push(` Action: ${event.intent}${event.tool ? ` (tool: ${event.tool})` : ""}`);
14687
+ parts.push(` Result:${icon} ${event.decision}`);
14688
+ if (event.guardsMatched.length > 0) {
14689
+ parts.push(` Guards: ${event.guardsMatched.join(", ")}`);
14483
14690
  }
14484
- if (verdict.intentRecord) {
14485
- auditEvent.originalIntent = verdict.intentRecord.originalIntent;
14486
- auditEvent.finalAction = verdict.intentRecord.finalAction;
14691
+ if (event.rulesMatched.length > 0) {
14692
+ parts.push(` Rules: ${event.rulesMatched.join(", ")}`);
14487
14693
  }
14488
- return auditEvent;
14489
- }
14490
- async function readAuditLog(logPath, filter) {
14491
- const { readFile: readFile3 } = await import("fs/promises");
14492
- let content;
14493
- try {
14494
- content = await readFile3(logPath, "utf-8");
14495
- } catch {
14496
- return [];
14694
+ if (event.reason) {
14695
+ parts.push(` Reason: ${event.reason}`);
14497
14696
  }
14498
- const events = [];
14499
- for (const line of content.split("\n")) {
14500
- const trimmed = line.trim();
14501
- if (!trimmed) continue;
14502
- try {
14503
- const event = JSON.parse(trimmed);
14504
- if (!filter || filter(event)) {
14505
- events.push(event);
14506
- }
14507
- } catch {
14508
- }
14697
+ if (event.warning) {
14698
+ parts.push(` Warning: ${event.warning}`);
14509
14699
  }
14510
- return events;
14511
- }
14512
- function summarizeAuditEvents(events) {
14513
- const allowed = events.filter((e) => e.decision === "ALLOW").length;
14514
- const blocked = events.filter((e) => e.decision === "BLOCK").length;
14515
- const paused = events.filter((e) => e.decision === "PAUSE").length;
14516
- const modified = events.filter((e) => e.decision === "MODIFY").length;
14517
- const penalized = events.filter((e) => e.decision === "PENALIZE").length;
14518
- const rewarded = events.filter((e) => e.decision === "REWARD").length;
14519
- const neutral = events.filter((e) => e.decision === "NEUTRAL").length;
14520
- const actorSet = /* @__PURE__ */ new Set();
14521
- for (const e of events) {
14522
- if (e.actor) actorSet.add(e.actor);
14523
- }
14524
- const intentMap = /* @__PURE__ */ new Map();
14525
- for (const e of events) {
14526
- const entry = intentMap.get(e.intent) ?? { count: 0, blocked: 0, paused: 0, penalized: 0, rewarded: 0 };
14527
- entry.count++;
14528
- if (e.decision === "BLOCK") entry.blocked++;
14529
- if (e.decision === "PAUSE") entry.paused++;
14530
- if (e.decision === "PENALIZE") entry.penalized++;
14531
- if (e.decision === "REWARD") entry.rewarded++;
14532
- intentMap.set(e.intent, entry);
14533
- }
14534
- const topIntents = [...intentMap.entries()].map(([intent, data]) => ({ intent, ...data })).sort((a, b) => b.count - a.count);
14535
- const ruleMap = /* @__PURE__ */ new Map();
14536
- for (const e of events) {
14537
- if (e.ruleId) {
14538
- ruleMap.set(e.ruleId, (ruleMap.get(e.ruleId) ?? 0) + 1);
14539
- }
14540
- for (const g of e.guardsMatched) {
14541
- ruleMap.set(g, (ruleMap.get(g) ?? 0) + 1);
14542
- }
14543
- }
14544
- const topRules = [...ruleMap.entries()].map(([ruleId, count]) => ({ ruleId, count })).sort((a, b) => b.count - a.count);
14545
- const redirected = blocked + paused + modified + penalized;
14546
- const total = events.length;
14547
- return {
14548
- totalActions: total,
14549
- allowed,
14550
- blocked,
14551
- paused,
14552
- modified,
14553
- penalized,
14554
- rewarded,
14555
- neutral,
14556
- actors: [...actorSet],
14557
- topIntents,
14558
- topRules,
14559
- firstEvent: events[0]?.timestamp ?? "",
14560
- lastEvent: events[events.length - 1]?.timestamp ?? "",
14561
- behavioralEconomy: {
14562
- totalPenalties: penalized,
14563
- totalRewards: rewarded,
14564
- netPressure: rewarded - penalized,
14565
- redirectionRate: total > 0 ? redirected / total : 0
14566
- }
14567
- };
14568
- }
14569
- var init_audit_logger = __esm({
14570
- "src/engine/audit-logger.ts"() {
14571
- "use strict";
14572
- init_guard_engine();
14573
- }
14574
- });
14575
-
14576
- // src/cli/trace.ts
14577
- var trace_exports = {};
14578
- __export(trace_exports, {
14579
- main: () => main20
14580
- });
14581
- function parseArgs16(argv) {
14582
- const args = {};
14583
- for (let i = 0; i < argv.length; i++) {
14584
- const arg = argv[i];
14585
- if (arg === "--summary") {
14586
- args.summary = true;
14587
- } else if (arg === "--json") {
14588
- args.json = true;
14589
- } else if (arg === "--help" || arg === "-h") {
14590
- args.help = true;
14591
- } else if (arg === "--log" && argv[i + 1]) {
14592
- args.log = argv[++i];
14593
- } else if (arg === "--filter" && argv[i + 1]) {
14594
- args.filter = argv[++i].toUpperCase();
14595
- } else if (arg === "--actor" && argv[i + 1]) {
14596
- args.actor = argv[++i];
14597
- } else if (arg === "--intent" && argv[i + 1]) {
14598
- args.intent = argv[++i];
14599
- } else if (arg === "--last" && argv[i + 1]) {
14600
- args.last = argv[++i];
14601
- }
14602
- }
14603
- return args;
14604
- }
14605
- function formatEvent(event) {
14606
- const ts = event.timestamp.split("T")[1]?.replace("Z", "").slice(0, 8) ?? event.timestamp;
14607
- const icon = event.decision === "ALLOW" ? " \u2713" : event.decision === "BLOCK" ? " \u2717" : " \u23F8";
14608
- const parts = [];
14609
- parts.push(` [${ts}] ${event.actor ?? "unknown"}`);
14610
- parts.push(` Action: ${event.intent}${event.tool ? ` (tool: ${event.tool})` : ""}`);
14611
- parts.push(` Result:${icon} ${event.decision}`);
14612
- if (event.guardsMatched.length > 0) {
14613
- parts.push(` Guards: ${event.guardsMatched.join(", ")}`);
14614
- }
14615
- if (event.rulesMatched.length > 0) {
14616
- parts.push(` Rules: ${event.rulesMatched.join(", ")}`);
14617
- }
14618
- if (event.reason) {
14619
- parts.push(` Reason: ${event.reason}`);
14620
- }
14621
- if (event.warning) {
14622
- parts.push(` Warning: ${event.warning}`);
14623
- }
14624
- return parts.join("\n");
14700
+ return parts.join("\n");
14625
14701
  }
14626
14702
  function formatSummary(events) {
14627
14703
  const summary2 = summarizeAuditEvents(events);
@@ -15596,12 +15672,590 @@ var init_equity_penalties = __esm({
15596
15672
  }
15597
15673
  });
15598
15674
 
15675
+ // src/cli/keygen.ts
15676
+ var keygen_exports = {};
15677
+ __export(keygen_exports, {
15678
+ main: () => main26
15679
+ });
15680
+ function parseArgs20(argv) {
15681
+ let output = (0, import_path8.join)((0, import_os2.homedir)(), ".neuroverse", "keys");
15682
+ let name = "neuroverse";
15683
+ let force = false;
15684
+ let help = false;
15685
+ for (let i = 0; i < argv.length; i++) {
15686
+ const arg = argv[i];
15687
+ if ((arg === "--output" || arg === "-o") && argv[i + 1]) {
15688
+ output = argv[++i];
15689
+ } else if ((arg === "--name" || arg === "-n") && argv[i + 1]) {
15690
+ name = argv[++i];
15691
+ } else if (arg === "--force") {
15692
+ force = true;
15693
+ } else if (arg === "--help" || arg === "-h") {
15694
+ help = true;
15695
+ }
15696
+ }
15697
+ return { output, name, force, help };
15698
+ }
15699
+ async function main26(argv = process.argv.slice(2)) {
15700
+ const args = parseArgs20(argv);
15701
+ if (args.help) {
15702
+ process.stdout.write(USAGE5 + "\n");
15703
+ return;
15704
+ }
15705
+ const pubPath = (0, import_path8.join)(args.output, `${args.name}.pub`);
15706
+ const keyPath = (0, import_path8.join)(args.output, `${args.name}.key`);
15707
+ if (!args.force && ((0, import_fs7.existsSync)(pubPath) || (0, import_fs7.existsSync)(keyPath))) {
15708
+ process.stderr.write(`Keys already exist at ${args.output}/${args.name}.*
15709
+ `);
15710
+ process.stderr.write("Use --force to overwrite.\n");
15711
+ process.exit(1);
15712
+ }
15713
+ const { publicKey, privateKey } = (0, import_crypto.generateKeyPairSync)("ed25519", {
15714
+ publicKeyEncoding: { type: "spki", format: "pem" },
15715
+ privateKeyEncoding: { type: "pkcs8", format: "pem" }
15716
+ });
15717
+ (0, import_fs7.mkdirSync)(args.output, { recursive: true });
15718
+ (0, import_fs7.writeFileSync)(pubPath, publicKey, "utf-8");
15719
+ (0, import_fs7.writeFileSync)(keyPath, privateKey, { encoding: "utf-8", mode: 384 });
15720
+ process.stdout.write(`Keypair generated:
15721
+ `);
15722
+ process.stdout.write(` Public: ${pubPath}
15723
+ `);
15724
+ process.stdout.write(` Private: ${keyPath}
15725
+ `);
15726
+ process.stdout.write(`
15727
+ Share the .pub file with anyone who needs to verify your worlds.
15728
+ `);
15729
+ process.stdout.write(`Keep the .key file secret.
15730
+ `);
15731
+ }
15732
+ var import_crypto, import_fs7, import_path8, import_os2, USAGE5;
15733
+ var init_keygen = __esm({
15734
+ "src/cli/keygen.ts"() {
15735
+ "use strict";
15736
+ import_crypto = require("crypto");
15737
+ import_fs7 = require("fs");
15738
+ import_path8 = require("path");
15739
+ import_os2 = require("os");
15740
+ USAGE5 = `
15741
+ neuroverse keygen \u2014 Generate Ed25519 signing keypair
15742
+
15743
+ Usage:
15744
+ neuroverse keygen [--output <dir>] [--name <name>]
15745
+
15746
+ Options:
15747
+ --output <dir> Key directory (default: ~/.neuroverse/keys/)
15748
+ --name <name> Key name (default: neuroverse)
15749
+ --force Overwrite existing keys
15750
+
15751
+ Examples:
15752
+ neuroverse keygen
15753
+ neuroverse keygen --name production --output ./keys/
15754
+ `.trim();
15755
+ }
15756
+ });
15757
+
15758
+ // src/cli/sign.ts
15759
+ var sign_exports = {};
15760
+ __export(sign_exports, {
15761
+ buildManifest: () => buildManifest,
15762
+ canonicalManifest: () => canonicalManifest,
15763
+ main: () => main27
15764
+ });
15765
+ function parseArgs21(argv) {
15766
+ let worldPath = "";
15767
+ let keyPath = (0, import_path9.join)((0, import_os3.homedir)(), ".neuroverse", "keys", "neuroverse.key");
15768
+ let help = false;
15769
+ for (let i = 0; i < argv.length; i++) {
15770
+ const arg = argv[i];
15771
+ if (arg === "--world" && argv[i + 1]) {
15772
+ worldPath = argv[++i];
15773
+ } else if (arg === "--key" && argv[i + 1]) {
15774
+ keyPath = argv[++i];
15775
+ } else if (arg === "--help" || arg === "-h") {
15776
+ help = true;
15777
+ }
15778
+ }
15779
+ return { worldPath, keyPath, help };
15780
+ }
15781
+ function collectFiles(dir, base) {
15782
+ const root = base ?? dir;
15783
+ const files = [];
15784
+ for (const entry of (0, import_fs8.readdirSync)(dir)) {
15785
+ if (entry === ".nv-signature.json") continue;
15786
+ const full = (0, import_path9.join)(dir, entry);
15787
+ const stat = (0, import_fs8.statSync)(full);
15788
+ if (stat.isDirectory()) {
15789
+ files.push(...collectFiles(full, root));
15790
+ } else {
15791
+ files.push((0, import_path9.relative)(root, full));
15792
+ }
15793
+ }
15794
+ return files.sort();
15795
+ }
15796
+ function buildManifest(worldPath) {
15797
+ const files = collectFiles(worldPath);
15798
+ const manifest = {};
15799
+ for (const file of files) {
15800
+ const content = (0, import_fs8.readFileSync)((0, import_path9.join)(worldPath, file));
15801
+ manifest[file] = (0, import_crypto2.createHash)("sha256").update(content).digest("hex");
15802
+ }
15803
+ return manifest;
15804
+ }
15805
+ function canonicalManifest(files) {
15806
+ const sorted = Object.keys(files).sort();
15807
+ return sorted.map((k) => `${k}:${files[k]}`).join("\n");
15808
+ }
15809
+ async function main27(argv = process.argv.slice(2)) {
15810
+ const args = parseArgs21(argv);
15811
+ if (args.help) {
15812
+ process.stdout.write(USAGE6 + "\n");
15813
+ return;
15814
+ }
15815
+ if (!args.worldPath) {
15816
+ process.stderr.write("Error: --world <dir> is required.\n");
15817
+ process.exit(1);
15818
+ }
15819
+ let privateKey;
15820
+ try {
15821
+ privateKey = (0, import_fs8.readFileSync)(args.keyPath, "utf-8");
15822
+ } catch {
15823
+ process.stderr.write(`Error: Cannot read private key at ${args.keyPath}
15824
+ `);
15825
+ process.stderr.write('Run "neuroverse keygen" to generate a keypair.\n');
15826
+ process.exit(1);
15827
+ return;
15828
+ }
15829
+ const files = buildManifest(args.worldPath);
15830
+ const canonical = canonicalManifest(files);
15831
+ const manifestHash = (0, import_crypto2.createHash)("sha256").update(canonical).digest("hex");
15832
+ const signature = (0, import_crypto2.sign)(null, Buffer.from(manifestHash), privateKey).toString("base64");
15833
+ const artifact = {
15834
+ signatureVersion: "1.0",
15835
+ signedAt: (/* @__PURE__ */ new Date()).toISOString(),
15836
+ files,
15837
+ manifestHash,
15838
+ signature
15839
+ };
15840
+ const outPath = (0, import_path9.join)(args.worldPath, ".nv-signature.json");
15841
+ (0, import_fs8.writeFileSync)(outPath, JSON.stringify(artifact, null, 2) + "\n", "utf-8");
15842
+ process.stdout.write(`Signed ${Object.keys(files).length} files in ${args.worldPath}
15843
+ `);
15844
+ process.stdout.write(`Signature: ${outPath}
15845
+ `);
15846
+ }
15847
+ var import_crypto2, import_fs8, import_path9, import_os3, USAGE6;
15848
+ var init_sign = __esm({
15849
+ "src/cli/sign.ts"() {
15850
+ "use strict";
15851
+ import_crypto2 = require("crypto");
15852
+ import_fs8 = require("fs");
15853
+ import_path9 = require("path");
15854
+ import_os3 = require("os");
15855
+ USAGE6 = `
15856
+ neuroverse sign \u2014 Sign a world artifact
15857
+
15858
+ Usage:
15859
+ neuroverse sign --world <dir> [--key <path>]
15860
+
15861
+ Options:
15862
+ --world <dir> World directory to sign (required)
15863
+ --key <path> Private key path (default: ~/.neuroverse/keys/neuroverse.key)
15864
+
15865
+ Examples:
15866
+ neuroverse sign --world ./world/
15867
+ neuroverse sign --world ./world/ --key ./keys/production.key
15868
+ `.trim();
15869
+ }
15870
+ });
15871
+
15872
+ // src/cli/verify.ts
15873
+ var verify_exports = {};
15874
+ __export(verify_exports, {
15875
+ main: () => main28
15876
+ });
15877
+ function parseArgs22(argv) {
15878
+ let worldPath = "";
15879
+ let keyPath = (0, import_path10.join)((0, import_os4.homedir)(), ".neuroverse", "keys", "neuroverse.pub");
15880
+ let json = false;
15881
+ let help = false;
15882
+ for (let i = 0; i < argv.length; i++) {
15883
+ const arg = argv[i];
15884
+ if (arg === "--world" && argv[i + 1]) {
15885
+ worldPath = argv[++i];
15886
+ } else if (arg === "--key" && argv[i + 1]) {
15887
+ keyPath = argv[++i];
15888
+ } else if (arg === "--json") {
15889
+ json = true;
15890
+ } else if (arg === "--help" || arg === "-h") {
15891
+ help = true;
15892
+ }
15893
+ }
15894
+ return { worldPath, keyPath, json, help };
15895
+ }
15896
+ async function main28(argv = process.argv.slice(2)) {
15897
+ const args = parseArgs22(argv);
15898
+ if (args.help) {
15899
+ process.stdout.write(USAGE7 + "\n");
15900
+ return;
15901
+ }
15902
+ if (!args.worldPath) {
15903
+ process.stderr.write("Error: --world <dir> is required.\n");
15904
+ process.exit(1);
15905
+ }
15906
+ const result = {
15907
+ valid: false,
15908
+ worldPath: args.worldPath,
15909
+ fileCount: 0,
15910
+ errors: []
15911
+ };
15912
+ const sigPath = (0, import_path10.join)(args.worldPath, ".nv-signature.json");
15913
+ if (!(0, import_fs9.existsSync)(sigPath)) {
15914
+ result.errors.push("No .nv-signature.json found \u2014 world is unsigned.");
15915
+ outputResult(result, args.json);
15916
+ process.exit(1);
15917
+ }
15918
+ let artifact;
15919
+ try {
15920
+ artifact = JSON.parse((0, import_fs9.readFileSync)(sigPath, "utf-8"));
15921
+ } catch {
15922
+ result.errors.push("Cannot parse .nv-signature.json \u2014 file is corrupt.");
15923
+ outputResult(result, args.json);
15924
+ process.exit(1);
15925
+ return;
15926
+ }
15927
+ result.signedAt = artifact.signedAt;
15928
+ result.fileCount = Object.keys(artifact.files).length;
15929
+ let publicKey;
15930
+ try {
15931
+ publicKey = (0, import_fs9.readFileSync)(args.keyPath, "utf-8");
15932
+ } catch {
15933
+ result.errors.push(`Cannot read public key at ${args.keyPath}`);
15934
+ outputResult(result, args.json);
15935
+ process.exit(1);
15936
+ return;
15937
+ }
15938
+ const currentFiles = buildManifest(args.worldPath);
15939
+ for (const file of Object.keys(currentFiles)) {
15940
+ if (!(file in artifact.files)) {
15941
+ result.errors.push(`Added: ${file} (not in signature)`);
15942
+ }
15943
+ }
15944
+ for (const [file, hash] of Object.entries(artifact.files)) {
15945
+ if (!(file in currentFiles)) {
15946
+ result.errors.push(`Missing: ${file} (was in signature)`);
15947
+ } else if (currentFiles[file] !== hash) {
15948
+ result.errors.push(`Changed: ${file} (hash mismatch)`);
15949
+ }
15950
+ }
15951
+ if (result.errors.length > 0) {
15952
+ outputResult(result, args.json);
15953
+ process.exit(1);
15954
+ return;
15955
+ }
15956
+ const canonical = canonicalManifest(artifact.files);
15957
+ const manifestHash = (0, import_crypto3.createHash)("sha256").update(canonical).digest("hex");
15958
+ if (manifestHash !== artifact.manifestHash) {
15959
+ result.errors.push("Manifest hash mismatch \u2014 signature metadata is corrupt.");
15960
+ outputResult(result, args.json);
15961
+ process.exit(1);
15962
+ return;
15963
+ }
15964
+ const isValid = (0, import_crypto3.verify)(null, Buffer.from(manifestHash), publicKey, Buffer.from(artifact.signature, "base64"));
15965
+ if (!isValid) {
15966
+ result.errors.push("Signature verification failed \u2014 wrong key or tampered manifest.");
15967
+ outputResult(result, args.json);
15968
+ process.exit(1);
15969
+ return;
15970
+ }
15971
+ result.valid = true;
15972
+ outputResult(result, args.json);
15973
+ }
15974
+ function outputResult(result, json) {
15975
+ if (json) {
15976
+ process.stdout.write(JSON.stringify(result, null, 2) + "\n");
15977
+ return;
15978
+ }
15979
+ if (result.valid) {
15980
+ process.stdout.write(`VALID \u2014 ${result.fileCount} files verified
15981
+ `);
15982
+ process.stdout.write(` Signed at: ${result.signedAt}
15983
+ `);
15984
+ process.stdout.write(` World: ${result.worldPath}
15985
+ `);
15986
+ } else {
15987
+ process.stdout.write(`INVALID \u2014 signature verification failed
15988
+ `);
15989
+ for (const error of result.errors) {
15990
+ process.stdout.write(` ${error}
15991
+ `);
15992
+ }
15993
+ }
15994
+ }
15995
+ var import_crypto3, import_fs9, import_path10, import_os4, USAGE7;
15996
+ var init_verify = __esm({
15997
+ "src/cli/verify.ts"() {
15998
+ "use strict";
15999
+ import_crypto3 = require("crypto");
16000
+ import_fs9 = require("fs");
16001
+ import_path10 = require("path");
16002
+ import_os4 = require("os");
16003
+ init_sign();
16004
+ USAGE7 = `
16005
+ neuroverse verify \u2014 Verify a signed world artifact
16006
+
16007
+ Usage:
16008
+ neuroverse verify --world <dir> [--key <path>]
16009
+
16010
+ Options:
16011
+ --world <dir> World directory to verify (required)
16012
+ --key <path> Public key path (default: ~/.neuroverse/keys/neuroverse.pub)
16013
+ --json Output result as JSON
16014
+
16015
+ Exit codes:
16016
+ 0 Valid \u2014 world matches signature
16017
+ 1 Invalid \u2014 signature mismatch, tampered files, or missing signature
16018
+
16019
+ Examples:
16020
+ neuroverse verify --world ./world/
16021
+ neuroverse verify --world ./world/ --key ./keys/production.pub
16022
+ `.trim();
16023
+ }
16024
+ });
16025
+
16026
+ // src/cli/migrate.ts
16027
+ var migrate_exports = {};
16028
+ __export(migrate_exports, {
16029
+ LATEST_VERSION: () => LATEST_VERSION,
16030
+ main: () => main29
16031
+ });
16032
+ function detectVersion(worldPath) {
16033
+ const metaPath = (0, import_path11.join)(worldPath, "metadata.json");
16034
+ if ((0, import_fs10.existsSync)(metaPath)) {
16035
+ try {
16036
+ const meta = JSON.parse((0, import_fs10.readFileSync)(metaPath, "utf-8"));
16037
+ if (meta.schema_version) return meta.schema_version;
16038
+ } catch {
16039
+ }
16040
+ }
16041
+ return "1.0.0";
16042
+ }
16043
+ function compareVersions(a, b) {
16044
+ const pa = a.split(".").map(Number);
16045
+ const pb = b.split(".").map(Number);
16046
+ for (let i = 0; i < 3; i++) {
16047
+ if ((pa[i] ?? 0) < (pb[i] ?? 0)) return -1;
16048
+ if ((pa[i] ?? 0) > (pb[i] ?? 0)) return 1;
16049
+ }
16050
+ return 0;
16051
+ }
16052
+ function findMigrationPath(from, to) {
16053
+ const path = [];
16054
+ let current = from;
16055
+ while (compareVersions(current, to) < 0) {
16056
+ const next = MIGRATIONS.find((m) => m.from === current);
16057
+ if (!next) break;
16058
+ path.push(next);
16059
+ current = next.to;
16060
+ }
16061
+ return path;
16062
+ }
16063
+ function parseArgs23(argv) {
16064
+ let worldPath = "";
16065
+ let dryRun = false;
16066
+ let backup = false;
16067
+ let target = LATEST_VERSION;
16068
+ let json = false;
16069
+ let help = false;
16070
+ for (let i = 0; i < argv.length; i++) {
16071
+ const arg = argv[i];
16072
+ if (arg === "--world" && argv[i + 1]) {
16073
+ worldPath = argv[++i];
16074
+ } else if (arg === "--dry-run") {
16075
+ dryRun = true;
16076
+ } else if (arg === "--backup") {
16077
+ backup = true;
16078
+ } else if (arg === "--target" && argv[i + 1]) {
16079
+ target = argv[++i];
16080
+ } else if (arg === "--json") {
16081
+ json = true;
16082
+ } else if (arg === "--help" || arg === "-h") {
16083
+ help = true;
16084
+ }
16085
+ }
16086
+ return { worldPath, dryRun, backup, target, json, help };
16087
+ }
16088
+ async function main29(argv = process.argv.slice(2)) {
16089
+ const args = parseArgs23(argv);
16090
+ if (args.help) {
16091
+ process.stdout.write(USAGE8 + "\n");
16092
+ return;
16093
+ }
16094
+ if (!args.worldPath) {
16095
+ process.stderr.write("Error: --world <dir> is required.\n");
16096
+ process.exit(1);
16097
+ }
16098
+ const currentVersion = detectVersion(args.worldPath);
16099
+ const targetVersion = args.target;
16100
+ if (compareVersions(currentVersion, targetVersion) >= 0) {
16101
+ const plan2 = {
16102
+ currentVersion,
16103
+ targetVersion,
16104
+ migrations: [],
16105
+ changes: []
16106
+ };
16107
+ if (args.json) {
16108
+ process.stdout.write(JSON.stringify(plan2, null, 2) + "\n");
16109
+ } else {
16110
+ process.stdout.write(`World is already at version ${currentVersion} (target: ${targetVersion})
16111
+ `);
16112
+ process.stdout.write("No migrations needed.\n");
16113
+ }
16114
+ return;
16115
+ }
16116
+ const migrationPath = findMigrationPath(currentVersion, targetVersion);
16117
+ if (migrationPath.length === 0) {
16118
+ process.stderr.write(`No migration path from ${currentVersion} to ${targetVersion}
16119
+ `);
16120
+ process.exit(1);
16121
+ return;
16122
+ }
16123
+ if (args.dryRun) {
16124
+ const plan2 = {
16125
+ currentVersion,
16126
+ targetVersion,
16127
+ migrations: migrationPath.map((m) => ({ from: m.from, to: m.to, description: m.description })),
16128
+ changes: []
16129
+ };
16130
+ if (args.json) {
16131
+ process.stdout.write(JSON.stringify(plan2, null, 2) + "\n");
16132
+ } else {
16133
+ process.stdout.write(`Migration plan: ${currentVersion} \u2192 ${targetVersion}
16134
+ `);
16135
+ process.stdout.write(`Steps: ${migrationPath.length}
16136
+
16137
+ `);
16138
+ for (const m of migrationPath) {
16139
+ process.stdout.write(` ${m.from} \u2192 ${m.to}: ${m.description}
16140
+ `);
16141
+ }
16142
+ process.stdout.write("\nRun without --dry-run to apply.\n");
16143
+ }
16144
+ return;
16145
+ }
16146
+ if (args.backup) {
16147
+ const backupPath = args.worldPath + ".backup";
16148
+ (0, import_fs10.cpSync)(args.worldPath, backupPath, { recursive: true });
16149
+ process.stdout.write(`Backup created: ${backupPath}
16150
+ `);
16151
+ }
16152
+ const allChanges = [];
16153
+ for (const migration of migrationPath) {
16154
+ process.stdout.write(`Applying: ${migration.from} \u2192 ${migration.to} (${migration.description})
16155
+ `);
16156
+ const changes = migration.apply(args.worldPath);
16157
+ allChanges.push(...changes);
16158
+ for (const change of changes) {
16159
+ process.stdout.write(` ${change.action}: ${change.file} \u2014 ${change.description}
16160
+ `);
16161
+ }
16162
+ }
16163
+ const plan = {
16164
+ currentVersion,
16165
+ targetVersion,
16166
+ migrations: migrationPath.map((m) => ({ from: m.from, to: m.to, description: m.description })),
16167
+ changes: allChanges
16168
+ };
16169
+ if (args.json) {
16170
+ process.stdout.write(JSON.stringify(plan, null, 2) + "\n");
16171
+ }
16172
+ process.stdout.write(`
16173
+ Migration complete: ${currentVersion} \u2192 ${targetVersion} (${allChanges.length} changes)
16174
+ `);
16175
+ }
16176
+ var import_fs10, import_path11, USAGE8, MIGRATIONS, LATEST_VERSION;
16177
+ var init_migrate = __esm({
16178
+ "src/cli/migrate.ts"() {
16179
+ "use strict";
16180
+ import_fs10 = require("fs");
16181
+ import_path11 = require("path");
16182
+ USAGE8 = `
16183
+ neuroverse migrate \u2014 World schema version migration
16184
+
16185
+ Usage:
16186
+ neuroverse migrate --world <dir> [options]
16187
+
16188
+ Options:
16189
+ --world <dir> World directory to migrate (required)
16190
+ --dry-run Show what would change without modifying files
16191
+ --backup Copy original world to <dir>.backup before migrating
16192
+ --target <version> Target schema version (default: latest)
16193
+ --json Output migration plan as JSON
16194
+
16195
+ Examples:
16196
+ neuroverse migrate --world ./world/ --dry-run
16197
+ neuroverse migrate --world ./world/ --backup
16198
+ neuroverse migrate --world ./world/ --target 1.1.0
16199
+ `.trim();
16200
+ MIGRATIONS = [
16201
+ {
16202
+ from: "1.0.0",
16203
+ to: "1.1.0",
16204
+ description: "Add enforcement_level to world.json, normalize metadata fields",
16205
+ apply: (worldPath) => {
16206
+ const changes = [];
16207
+ const worldJsonPath = (0, import_path11.join)(worldPath, "world.json");
16208
+ if ((0, import_fs10.existsSync)(worldJsonPath)) {
16209
+ const world = JSON.parse((0, import_fs10.readFileSync)(worldJsonPath, "utf-8"));
16210
+ if (!world.enforcement_level) {
16211
+ world.enforcement_level = "standard";
16212
+ (0, import_fs10.writeFileSync)(worldJsonPath, JSON.stringify(world, null, 2) + "\n", "utf-8");
16213
+ changes.push({
16214
+ file: "world.json",
16215
+ action: "modified",
16216
+ description: 'Added enforcement_level: "standard"'
16217
+ });
16218
+ }
16219
+ }
16220
+ const metaPath = (0, import_path11.join)(worldPath, "metadata.json");
16221
+ if ((0, import_fs10.existsSync)(metaPath)) {
16222
+ const meta = JSON.parse((0, import_fs10.readFileSync)(metaPath, "utf-8"));
16223
+ let modified = false;
16224
+ if (meta.configurator_version && !meta.authoring_method) {
16225
+ meta.authoring_method = meta.configurator_version;
16226
+ delete meta.configurator_version;
16227
+ modified = true;
16228
+ }
16229
+ if (!meta.schema_version) {
16230
+ meta.schema_version = "1.1.0";
16231
+ modified = true;
16232
+ } else {
16233
+ meta.schema_version = "1.1.0";
16234
+ modified = true;
16235
+ }
16236
+ if (modified) {
16237
+ (0, import_fs10.writeFileSync)(metaPath, JSON.stringify(meta, null, 2) + "\n", "utf-8");
16238
+ changes.push({
16239
+ file: "metadata.json",
16240
+ action: "modified",
16241
+ description: "Normalized metadata fields, updated schema_version to 1.1.0"
16242
+ });
16243
+ }
16244
+ }
16245
+ return changes;
16246
+ }
16247
+ }
16248
+ ];
16249
+ LATEST_VERSION = MIGRATIONS.length > 0 ? MIGRATIONS[MIGRATIONS.length - 1].to : "1.0.0";
16250
+ }
16251
+ });
16252
+
15599
16253
  // src/cli/configure-ai.ts
15600
16254
  var configure_ai_exports = {};
15601
16255
  __export(configure_ai_exports, {
15602
- main: () => main26
16256
+ main: () => main30
15603
16257
  });
15604
- function parseArgs20(argv) {
16258
+ function parseArgs24(argv) {
15605
16259
  let provider;
15606
16260
  let model;
15607
16261
  let apiKey;
@@ -15626,9 +16280,9 @@ function parseArgs20(argv) {
15626
16280
  }
15627
16281
  return { provider, model, apiKey, endpoint, show, test };
15628
16282
  }
15629
- async function main26(argv = process.argv.slice(2)) {
16283
+ async function main30(argv = process.argv.slice(2)) {
15630
16284
  try {
15631
- const args = parseArgs20(argv);
16285
+ const args = parseArgs24(argv);
15632
16286
  if (args.show) {
15633
16287
  const config2 = await loadConfig();
15634
16288
  if (!config2) {
@@ -15829,7 +16483,7 @@ var init_prompt_utils = __esm({
15829
16483
  // src/cli/configure-world.ts
15830
16484
  var configure_world_exports = {};
15831
16485
  __export(configure_world_exports, {
15832
- main: () => main27
16486
+ main: () => main31
15833
16487
  });
15834
16488
  function metricToStateVariable(metric) {
15835
16489
  const id = metric.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, "");
@@ -16247,15 +16901,15 @@ function generateWorld(state) {
16247
16901
  return { worldJson, stateSchema, guardsJson, rules, gatesJson, invariants, outcomes, metadata };
16248
16902
  }
16249
16903
  async function writeWorld(outputDir, world) {
16250
- const { mkdirSync: mkdirSync3, existsSync: existsSync6 } = await import("fs");
16904
+ const { mkdirSync: mkdirSync5, existsSync: existsSync9 } = await import("fs");
16251
16905
  const { writeFile: writeFile5 } = await import("fs/promises");
16252
- const { join: join9 } = await import("path");
16906
+ const { join: join13 } = await import("path");
16253
16907
  const files = [];
16254
- if (!existsSync6(outputDir)) mkdirSync3(outputDir, { recursive: true });
16255
- const rulesDir = join9(outputDir, "rules");
16256
- if (!existsSync6(rulesDir)) mkdirSync3(rulesDir, { recursive: true });
16908
+ if (!existsSync9(outputDir)) mkdirSync5(outputDir, { recursive: true });
16909
+ const rulesDir = join13(outputDir, "rules");
16910
+ if (!existsSync9(rulesDir)) mkdirSync5(rulesDir, { recursive: true });
16257
16911
  const writeJson = async (name, data) => {
16258
- const path = join9(outputDir, name);
16912
+ const path = join13(outputDir, name);
16259
16913
  await writeFile5(path, JSON.stringify(data, null, 2) + "\n", "utf-8");
16260
16914
  files.push(path);
16261
16915
  };
@@ -16267,13 +16921,13 @@ async function writeWorld(outputDir, world) {
16267
16921
  await writeJson("outcomes.json", world.outcomes);
16268
16922
  await writeJson("metadata.json", world.metadata);
16269
16923
  for (const rule of world.rules) {
16270
- const rulePath = join9(rulesDir, `${rule.id}.json`);
16924
+ const rulePath = join13(rulesDir, `${rule.id}.json`);
16271
16925
  await writeFile5(rulePath, JSON.stringify(rule, null, 2) + "\n", "utf-8");
16272
16926
  files.push(rulePath);
16273
16927
  }
16274
16928
  return files;
16275
16929
  }
16276
- function parseArgs21(argv) {
16930
+ function parseArgs25(argv) {
16277
16931
  let outputDir = "./world/";
16278
16932
  for (let i = 0; i < argv.length; i++) {
16279
16933
  const arg = argv[i];
@@ -16283,9 +16937,9 @@ function parseArgs21(argv) {
16283
16937
  }
16284
16938
  return { outputDir };
16285
16939
  }
16286
- async function main27(argv = process.argv.slice(2)) {
16940
+ async function main31(argv = process.argv.slice(2)) {
16287
16941
  try {
16288
- const args = parseArgs21(argv);
16942
+ const args = parseArgs25(argv);
16289
16943
  const context = await phaseContext();
16290
16944
  const guardState = await phaseGuard(context.domain);
16291
16945
  const systemState = await phaseSystem(context.domain);
@@ -16354,7 +17008,7 @@ async function main27(argv = process.argv.slice(2)) {
16354
17008
  }
16355
17009
  async function phaseRefine(outputDir, world) {
16356
17010
  const { writeFile: writeFile5 } = await import("fs/promises");
16357
- const { join: join9 } = await import("path");
17011
+ const { join: join13 } = await import("path");
16358
17012
  heading("Refinement: Thresholds & Collapse");
16359
17013
  const primaryMetric = world.gatesJson.viability_classification[0]?.field || "system_health";
16360
17014
  info(`
@@ -16371,7 +17025,7 @@ async function phaseRefine(outputDir, world) {
16371
17025
  if (!isNaN(parsed)) gate.value = parsed;
16372
17026
  }
16373
17027
  await writeFile5(
16374
- join9(outputDir, "gates.json"),
17028
+ join13(outputDir, "gates.json"),
16375
17029
  JSON.stringify(world.gatesJson, null, 2) + "\n",
16376
17030
  "utf-8"
16377
17031
  );
@@ -16393,7 +17047,7 @@ async function phaseRefine(outputDir, world) {
16393
17047
  result: "MODEL_COLLAPSES"
16394
17048
  };
16395
17049
  await writeFile5(
16396
- join9(outputDir, "rules", `${rule.id}.json`),
17050
+ join13(outputDir, "rules", `${rule.id}.json`),
16397
17051
  JSON.stringify(rule, null, 2) + "\n",
16398
17052
  "utf-8"
16399
17053
  );
@@ -17127,7 +17781,7 @@ var init_lens = __esm({
17127
17781
  // src/cli/lens.ts
17128
17782
  var lens_exports = {};
17129
17783
  __export(lens_exports, {
17130
- main: () => main28
17784
+ main: () => main32
17131
17785
  });
17132
17786
  async function cmdList(argv) {
17133
17787
  let worldPath = "";
@@ -17387,9 +18041,9 @@ async function cmdAdd(argv) {
17387
18041
  id = name.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, "");
17388
18042
  }
17389
18043
  const { readFile: readFile3, writeFile: writeFile5 } = await import("fs/promises");
17390
- const { join: join9 } = await import("path");
18044
+ const { join: join13 } = await import("path");
17391
18045
  const possiblePaths = [
17392
- join9(worldPath, "world.nv-world.md"),
18046
+ join13(worldPath, "world.nv-world.md"),
17393
18047
  worldPath
17394
18048
  ];
17395
18049
  let mdPath = "";
@@ -17410,7 +18064,7 @@ async function cmdAdd(argv) {
17410
18064
  const files = await readdir(worldPath);
17411
18065
  const mdFile = files.find((f) => f.endsWith(".nv-world.md"));
17412
18066
  if (mdFile) {
17413
- mdPath = join9(worldPath, mdFile);
18067
+ mdPath = join13(worldPath, mdFile);
17414
18068
  mdContent = await readFile3(mdPath, "utf-8");
17415
18069
  }
17416
18070
  } catch {
@@ -17460,7 +18114,7 @@ async function cmdAdd(argv) {
17460
18114
 
17461
18115
  `);
17462
18116
  }
17463
- async function main28(argv = process.argv.slice(2)) {
18117
+ async function main32(argv = process.argv.slice(2)) {
17464
18118
  const subcommand = argv[0];
17465
18119
  const subArgs = argv.slice(1);
17466
18120
  try {
@@ -17538,7 +18192,7 @@ Examples:
17538
18192
  });
17539
18193
 
17540
18194
  // src/cli/neuroverse.ts
17541
- var USAGE5 = `
18195
+ var USAGE9 = `
17542
18196
  neuroverse \u2014 Turn ideas into worlds.
17543
18197
 
17544
18198
  Commands:
@@ -17566,6 +18220,10 @@ Commands:
17566
18220
  decision-flow Intent \u2192 Rule \u2192 Outcome visualization (behavioral governance)
17567
18221
  equity-penalties Fortune 500 equity PENALIZE/REWARD simulation
17568
18222
  world World management (status, diff, snapshot, rollback)
18223
+ keygen Generate Ed25519 signing keypair
18224
+ sign Sign a world artifact (cryptographic manifest)
18225
+ verify Verify a signed world artifact
18226
+ migrate Migrate world schema between versions
17569
18227
  derive AI-assisted synthesis of .nv-world.md from markdown
17570
18228
  bootstrap Compile .nv-world.md \u2192 world JSON files
17571
18229
  configure-ai Configure AI provider credentials
@@ -17603,6 +18261,10 @@ Usage:
17603
18261
  neuroverse equity-penalties --world <dir> [--agents N] [--rounds N] [--json]
17604
18262
  neuroverse configure-ai --provider <name> --model <name> --api-key <key>
17605
18263
  neuroverse configure-world [--output <dir>]
18264
+ neuroverse keygen [--output <dir>] [--name <name>]
18265
+ neuroverse sign --world <dir> [--key <path>]
18266
+ neuroverse verify --world <dir> [--key <path>]
18267
+ neuroverse migrate --world <dir> [--dry-run] [--backup]
17606
18268
  neuroverse lens list [--world <dir>] [--json]
17607
18269
  neuroverse lens preview <id> [--world <dir>]
17608
18270
  neuroverse lens compile <id,...> [--world <dir>] [--role <role>] [--json]
@@ -17631,7 +18293,7 @@ Examples:
17631
18293
  neuroverse doctor
17632
18294
  neuroverse playground --world ./world/
17633
18295
  `.trim();
17634
- async function main29() {
18296
+ async function main33() {
17635
18297
  const args = process.argv.slice(2);
17636
18298
  const command = args[0];
17637
18299
  const subArgs = args.slice(1);
@@ -17744,6 +18406,22 @@ async function main29() {
17744
18406
  const { main: equityPenaltiesMain } = await Promise.resolve().then(() => (init_equity_penalties(), equity_penalties_exports));
17745
18407
  return equityPenaltiesMain(subArgs);
17746
18408
  }
18409
+ case "keygen": {
18410
+ const { main: keygenMain } = await Promise.resolve().then(() => (init_keygen(), keygen_exports));
18411
+ return keygenMain(subArgs);
18412
+ }
18413
+ case "sign": {
18414
+ const { main: signMain } = await Promise.resolve().then(() => (init_sign(), sign_exports));
18415
+ return signMain(subArgs);
18416
+ }
18417
+ case "verify": {
18418
+ const { main: verifyMain } = await Promise.resolve().then(() => (init_verify(), verify_exports));
18419
+ return verifyMain(subArgs);
18420
+ }
18421
+ case "migrate": {
18422
+ const { main: migrateMain } = await Promise.resolve().then(() => (init_migrate(), migrate_exports));
18423
+ return migrateMain(subArgs);
18424
+ }
17747
18425
  case "configure-ai": {
17748
18426
  const { main: configureAiMain } = await Promise.resolve().then(() => (init_configure_ai(), configure_ai_exports));
17749
18427
  return configureAiMain(subArgs);
@@ -17760,7 +18438,7 @@ async function main29() {
17760
18438
  case "-h":
17761
18439
  case "help":
17762
18440
  case void 0: {
17763
- process.stdout.write(USAGE5 + "\n");
18441
+ process.stdout.write(USAGE9 + "\n");
17764
18442
  process.exit(0);
17765
18443
  break;
17766
18444
  }
@@ -17768,12 +18446,12 @@ async function main29() {
17768
18446
  process.stderr.write(`Unknown command: "${command}"
17769
18447
 
17770
18448
  `);
17771
- process.stdout.write(USAGE5 + "\n");
18449
+ process.stdout.write(USAGE9 + "\n");
17772
18450
  process.exit(1);
17773
18451
  }
17774
18452
  }
17775
18453
  }
17776
- main29().catch((e) => {
18454
+ main33().catch((e) => {
17777
18455
  process.stderr.write(`Fatal: ${e}
17778
18456
  `);
17779
18457
  process.exit(3);