@neuroverseos/governance 0.3.0 → 0.3.3

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 (126) hide show
  1. package/.well-known/ai-plugin.json +34 -9
  2. package/AGENTS.md +72 -24
  3. package/README.md +352 -237
  4. package/dist/adapters/autoresearch.cjs +1152 -3
  5. package/dist/adapters/autoresearch.d.cts +11 -3
  6. package/dist/adapters/autoresearch.d.ts +11 -3
  7. package/dist/adapters/autoresearch.js +9 -4
  8. package/dist/adapters/deep-agents.cjs +1528 -0
  9. package/dist/adapters/deep-agents.d.cts +181 -0
  10. package/dist/adapters/deep-agents.d.ts +181 -0
  11. package/dist/adapters/deep-agents.js +17 -0
  12. package/dist/adapters/express.cjs +171 -32
  13. package/dist/adapters/express.d.cts +1 -1
  14. package/dist/adapters/express.d.ts +1 -1
  15. package/dist/adapters/express.js +5 -5
  16. package/dist/adapters/index.cjs +564 -121
  17. package/dist/adapters/index.d.cts +3 -1
  18. package/dist/adapters/index.d.ts +3 -1
  19. package/dist/adapters/index.js +38 -16
  20. package/dist/adapters/langchain.cjs +217 -57
  21. package/dist/adapters/langchain.d.cts +5 -5
  22. package/dist/adapters/langchain.d.ts +5 -5
  23. package/dist/adapters/langchain.js +6 -5
  24. package/dist/adapters/openai.cjs +219 -59
  25. package/dist/adapters/openai.d.cts +5 -5
  26. package/dist/adapters/openai.d.ts +5 -5
  27. package/dist/adapters/openai.js +6 -5
  28. package/dist/adapters/openclaw.cjs +217 -57
  29. package/dist/adapters/openclaw.d.cts +6 -6
  30. package/dist/adapters/openclaw.d.ts +6 -6
  31. package/dist/adapters/openclaw.js +6 -5
  32. package/dist/add-ROOZLU62.js +314 -0
  33. package/dist/behavioral-MJO34S6Q.js +118 -0
  34. package/dist/{bootstrap-GXVDZNF7.js → bootstrap-CQRZVOXK.js} +6 -4
  35. package/dist/bootstrap-emitter-Q7UIJZ2O.js +7 -0
  36. package/dist/bootstrap-parser-EEF36XDU.js +7 -0
  37. package/dist/browser.global.js +941 -0
  38. package/dist/{build-P42YFKQV.js → build-QKOBBC23.js} +7 -5
  39. package/dist/{chunk-COT5XS4V.js → chunk-3WQLXYTP.js} +17 -35
  40. package/dist/{chunk-ER62HNGF.js → chunk-4FLICVVA.js} +17 -37
  41. package/dist/chunk-5TPFNWRU.js +215 -0
  42. package/dist/chunk-5U2MQO5P.js +57 -0
  43. package/dist/{chunk-NF5POFCI.js → chunk-6S5CFQXY.js} +6 -4
  44. package/dist/{chunk-QPASI2BR.js → chunk-A7GKPPU7.js} +49 -10
  45. package/dist/{chunk-OGL7QXZS.js → chunk-B6OXJLJ5.js} +17 -3
  46. package/dist/{chunk-2PQU3VAN.js → chunk-BNKJPUPQ.js} +17 -35
  47. package/dist/chunk-BQZMOEML.js +43 -0
  48. package/dist/chunk-CNSO6XW5.js +207 -0
  49. package/dist/{chunk-JZPQGIKR.js → chunk-CTZHONLA.js} +65 -9
  50. package/dist/chunk-D2UCV5AK.js +326 -0
  51. package/dist/{chunk-XPDMYECO.js → chunk-EMQDLDAF.js} +1 -185
  52. package/dist/{chunk-GR6DGCZ2.js → chunk-F66BVUYB.js} +3 -3
  53. package/dist/{chunk-2NICNKOM.js → chunk-G7DJ6VOD.js} +5 -4
  54. package/dist/{chunk-4A7LISES.js → chunk-IS4WUH6Y.js} +45 -6
  55. package/dist/{chunk-MWDQ4MJB.js → chunk-MH7BT4VH.js} +5 -1
  56. package/dist/chunk-O5ABKEA7.js +304 -0
  57. package/dist/chunk-PVTQQS3Y.js +186 -0
  58. package/dist/{chunk-4QXB6PEO.js → chunk-QLPTHTVB.js} +37 -16
  59. package/dist/chunk-QWGCMQQD.js +16 -0
  60. package/dist/{chunk-T5EUJQE5.js → chunk-QXBFT7NI.js} +31 -2
  61. package/dist/{chunk-PDOZHZWL.js → chunk-TG6SEF24.js} +25 -4
  62. package/dist/chunk-U6U7EJZL.js +177 -0
  63. package/dist/{chunk-4JRYGIO7.js → chunk-W7LLXRGY.js} +110 -7
  64. package/dist/{chunk-BUWWN2NX.js → chunk-ZJTDUCC2.js} +9 -7
  65. package/dist/{chunk-FYS2CBUW.js → chunk-ZWI3NIXK.js} +10 -0
  66. package/dist/cli/neuroverse.cjs +5091 -2348
  67. package/dist/cli/neuroverse.js +52 -21
  68. package/dist/cli/plan.cjs +881 -41
  69. package/dist/cli/plan.js +7 -15
  70. package/dist/cli/run.cjs +289 -34
  71. package/dist/cli/run.js +4 -4
  72. package/dist/{configure-ai-TK67ZWZL.js → configure-ai-6TZ3MCSI.js} +1 -1
  73. package/dist/decision-flow-M63D47LO.js +61 -0
  74. package/dist/demo-G43RLCPK.js +469 -0
  75. package/dist/{derive-TLIV4OOU.js → derive-FJZVIPUZ.js} +5 -4
  76. package/dist/{doctor-XPDLEYXN.js → doctor-6BC6X2VO.js} +6 -4
  77. package/dist/equity-penalties-SG5IZQ7I.js +244 -0
  78. package/dist/{explain-IDCRWMPX.js → explain-RHBU2GBR.js} +6 -25
  79. package/dist/{guard-RV65TT4L.js → guard-AJCCGZMF.js} +8 -12
  80. package/dist/{guard-contract-WZx__PmU.d.cts → guard-contract-DqFcTScd.d.cts} +117 -5
  81. package/dist/{guard-contract-WZx__PmU.d.ts → guard-contract-DqFcTScd.d.ts} +117 -5
  82. package/dist/{guard-engine-JLTUARGU.js → guard-engine-PNR6MHCM.js} +3 -3
  83. package/dist/{impact-XPECYRLH.js → impact-3XVDSCBU.js} +5 -5
  84. package/dist/{improve-GPUBKTEA.js → improve-TQP4ECSY.js} +7 -26
  85. package/dist/index.cjs +5597 -4279
  86. package/dist/index.d.cts +597 -18
  87. package/dist/index.d.ts +597 -18
  88. package/dist/index.js +134 -41
  89. package/dist/{infer-world-7GVZWFX4.js → infer-world-IFXCACJ5.js} +1 -1
  90. package/dist/{init-PKPIYHYE.js → init-FYPV4SST.js} +1 -1
  91. package/dist/{init-world-VWMQZQC7.js → init-world-TI7ARHBT.js} +1 -1
  92. package/dist/mcp-server-5Y3ZM7TV.js +13 -0
  93. package/dist/{model-adapter-BB7G4MFI.js → model-adapter-VXEKB4LS.js} +1 -1
  94. package/dist/{playground-E664U4T6.js → playground-VZBNPPBO.js} +29 -19
  95. package/dist/{redteam-Z7WREJ44.js → redteam-MZPZD3EF.js} +4 -4
  96. package/dist/session-JYOARW54.js +15 -0
  97. package/dist/shared-7RLUHNMU.js +16 -0
  98. package/dist/shared-B8dvUUD8.d.cts +60 -0
  99. package/dist/shared-Dr5Wiay8.d.ts +60 -0
  100. package/dist/{simulate-VDOYQFRO.js → simulate-LJXYBC6M.js} +8 -33
  101. package/dist/{test-OGXJK4QU.js → test-BOOR4A5F.js} +4 -4
  102. package/dist/{trace-JVF67VR3.js → trace-PKV4KX56.js} +4 -4
  103. package/dist/{validate-LLBWVPGV.js → validate-RALX7CZS.js} +2 -2
  104. package/dist/{validate-engine-UIABSIHD.js → validate-engine-7ZXFVGF2.js} +1 -1
  105. package/dist/viz/assets/index-B8SaeJZZ.js +23 -0
  106. package/dist/viz/index.html +23 -0
  107. package/dist/{world-LAXO6DOX.js → world-BIP4GZBZ.js} +9 -11
  108. package/dist/world-loader-Y6HMQH2D.js +13 -0
  109. package/dist/worlds/coding-agent.nv-world.md +211 -0
  110. package/dist/worlds/research-agent.nv-world.md +169 -0
  111. package/dist/worlds/social-media.nv-world.md +198 -0
  112. package/dist/worlds/trading-agent.nv-world.md +218 -0
  113. package/examples/social-media-sim/bridge.py +209 -0
  114. package/examples/social-media-sim/simulation.py +927 -0
  115. package/package.json +30 -4
  116. package/policies/content-moderation-rules.txt +8 -0
  117. package/policies/marketing-rules.txt +8 -0
  118. package/policies/science-research-rules.txt +11 -0
  119. package/policies/social-media-rules.txt +7 -0
  120. package/policies/strict-rules.txt +8 -0
  121. package/policies/trading-rules.txt +8 -0
  122. package/simulate.html +1567 -0
  123. package/dist/chunk-YZFATT7X.js +0 -9
  124. package/dist/mcp-server-FPVSU32Z.js +0 -13
  125. package/dist/session-EKTRSR7C.js +0 -14
  126. package/dist/world-loader-HMPTOEA2.js +0 -9
package/dist/cli/plan.js CHANGED
@@ -1,3 +1,6 @@
1
+ import {
2
+ readStdin
3
+ } from "../chunk-BQZMOEML.js";
1
4
  import {
2
5
  PLAN_EXIT_CODES,
3
6
  parsePlanMarkdown
@@ -6,8 +9,8 @@ import {
6
9
  advancePlan,
7
10
  evaluatePlan,
8
11
  getPlanProgress
9
- } from "../chunk-4QXB6PEO.js";
10
- import "../chunk-YZFATT7X.js";
12
+ } from "../chunk-QLPTHTVB.js";
13
+ import "../chunk-QWGCMQQD.js";
11
14
 
12
15
  // src/cli/plan.ts
13
16
  import { readFileSync, writeFileSync } from "fs";
@@ -15,17 +18,6 @@ function parseArg(args, flag) {
15
18
  const idx = args.indexOf(flag);
16
19
  return idx >= 0 && idx + 1 < args.length ? args[idx + 1] : void 0;
17
20
  }
18
- function readStdin() {
19
- return new Promise((resolve, reject) => {
20
- let data = "";
21
- process.stdin.setEncoding("utf-8");
22
- process.stdin.on("data", (chunk) => {
23
- data += chunk;
24
- });
25
- process.stdin.on("end", () => resolve(data));
26
- process.stdin.on("error", reject);
27
- });
28
- }
29
21
  async function compileCommand(args) {
30
22
  const inputPath = args.find((a) => !a.startsWith("--"));
31
23
  if (!inputPath) {
@@ -108,8 +100,8 @@ async function checkCommand(args) {
108
100
  }
109
101
  const worldPath = parseArg(args, "--world");
110
102
  if (worldPath) {
111
- const { loadWorld } = await import("../world-loader-HMPTOEA2.js");
112
- const { evaluateGuard } = await import("../guard-engine-JLTUARGU.js");
103
+ const { loadWorld } = await import("../world-loader-Y6HMQH2D.js");
104
+ const { evaluateGuard } = await import("../guard-engine-PNR6MHCM.js");
113
105
  const world = await loadWorld(worldPath);
114
106
  const verdict2 = evaluateGuard(event, world, { plan });
115
107
  process.stdout.write(JSON.stringify(verdict2, null, 2) + "\n");
package/dist/cli/run.cjs CHANGED
@@ -167,17 +167,27 @@ Do not attempt to bypass governance rules.`;
167
167
  }
168
168
  });
169
169
 
170
- // src/engine/plan-engine.ts
171
- function keywordMatch(eventText, step) {
172
- const stepText = [
173
- step.label,
174
- step.description ?? "",
175
- ...step.tags ?? []
170
+ // src/engine/text-utils.ts
171
+ function normalizeEventText(event) {
172
+ return [
173
+ event.intent,
174
+ event.tool ?? "",
175
+ event.scope ?? ""
176
176
  ].join(" ").toLowerCase();
177
- const keywords = stepText.split(/\s+/).filter((w) => w.length > 3);
177
+ }
178
+ function extractKeywords(text, minLength = 3) {
179
+ return text.toLowerCase().split(/\s+/).filter((w) => w.length > minLength);
180
+ }
181
+ function matchesAllKeywords(eventText, ruleText) {
182
+ const keywords = extractKeywords(ruleText);
183
+ if (keywords.length === 0) return false;
184
+ return keywords.every((kw) => eventText.includes(kw));
185
+ }
186
+ function matchesKeywordThreshold(eventText, ruleText, threshold = 0.5) {
187
+ const keywords = extractKeywords(ruleText);
178
188
  if (keywords.length === 0) return false;
179
189
  const matched = keywords.filter((kw) => eventText.includes(kw));
180
- return matched.length >= Math.ceil(keywords.length * 0.5);
190
+ return matched.length >= Math.ceil(keywords.length * threshold);
181
191
  }
182
192
  function tokenSimilarity(a, b) {
183
193
  const tokensA = new Set(a.toLowerCase().split(/\s+/).filter((w) => w.length > 2));
@@ -190,6 +200,24 @@ function tokenSimilarity(a, b) {
190
200
  const union = (/* @__PURE__ */ new Set([...tokensA, ...tokensB])).size;
191
201
  return union > 0 ? intersection / union : 0;
192
202
  }
203
+ var init_text_utils = __esm({
204
+ "src/engine/text-utils.ts"() {
205
+ "use strict";
206
+ }
207
+ });
208
+
209
+ // src/engine/plan-engine.ts
210
+ function keywordMatch(eventText, step) {
211
+ const stepText = [
212
+ step.label,
213
+ step.description ?? "",
214
+ ...step.tags ?? []
215
+ ].join(" ");
216
+ return matchesKeywordThreshold(eventText, stepText, 0.5);
217
+ }
218
+ function tokenSimilarity2(a, b) {
219
+ return tokenSimilarity(a, b);
220
+ }
193
221
  function findMatchingStep(eventText, event, steps) {
194
222
  const pendingOrActive = steps.filter((s) => s.status === "pending" || s.status === "active");
195
223
  if (pendingOrActive.length === 0) {
@@ -208,7 +236,7 @@ function findMatchingStep(eventText, event, steps) {
208
236
  let bestScore = 0;
209
237
  for (const step of pendingOrActive) {
210
238
  const stepText = [step.label, step.description ?? "", ...step.tags ?? []].join(" ");
211
- const score = tokenSimilarity(intentText, stepText);
239
+ const score = tokenSimilarity2(intentText, stepText);
212
240
  if (score > bestScore) {
213
241
  bestScore = score;
214
242
  bestStep = step;
@@ -249,7 +277,7 @@ function checkConstraints(event, eventText, constraints) {
249
277
  continue;
250
278
  }
251
279
  if (constraint.type === "scope" && constraint.trigger) {
252
- const keywords = constraint.trigger.split(/\s+/).filter((w) => w.length > 3);
280
+ const keywords = extractKeywords(constraint.trigger);
253
281
  const violated = keywords.length > 0 && keywords.every((kw) => eventText.includes(kw));
254
282
  checks.push({
255
283
  constraintId: constraint.id,
@@ -330,11 +358,7 @@ function evaluatePlan(event, plan) {
330
358
  progress
331
359
  };
332
360
  }
333
- const eventText = [
334
- event.intent,
335
- event.tool ?? "",
336
- event.scope ?? ""
337
- ].join(" ").toLowerCase();
361
+ const eventText = normalizeEventText(event);
338
362
  const { matched, closest, closestScore } = findMatchingStep(eventText, event, plan.steps);
339
363
  if (!matched) {
340
364
  return {
@@ -375,7 +399,7 @@ function evaluatePlan(event, plan) {
375
399
  };
376
400
  }
377
401
  function buildPlanCheck(event, plan, verdict) {
378
- const eventText = [event.intent, event.tool ?? "", event.scope ?? ""].join(" ").toLowerCase();
402
+ const eventText = normalizeEventText(event);
379
403
  const { matched, closest, closestScore } = findMatchingStep(eventText, event, plan.steps);
380
404
  const { checks: constraintChecks } = checkConstraints(event, eventText, plan.constraints);
381
405
  const progress = getPlanProgress(plan);
@@ -395,6 +419,7 @@ function buildPlanCheck(event, plan, verdict) {
395
419
  var init_plan_engine = __esm({
396
420
  "src/engine/plan-engine.ts"() {
397
421
  "use strict";
422
+ init_text_utils();
398
423
  }
399
424
  });
400
425
 
@@ -423,7 +448,44 @@ function evaluateGuard(event, world, options = {}) {
423
448
  const startTime = performance.now();
424
449
  const level = options.level ?? "standard";
425
450
  const includeTrace = options.trace ?? false;
426
- const eventText = (event.intent + " " + (event.tool ?? "") + " " + (event.scope ?? "")).toLowerCase();
451
+ if (!event.intent || typeof event.intent !== "string") {
452
+ return {
453
+ status: "BLOCK",
454
+ reason: "GuardEvent.intent is required and must be a string",
455
+ ruleId: "safety-input-validation",
456
+ evidence: {
457
+ worldId: world.world?.world_id ?? "",
458
+ worldName: world.world?.name ?? "",
459
+ worldVersion: world.world?.version ?? "",
460
+ evaluatedAt: Date.now(),
461
+ invariantsSatisfied: 0,
462
+ invariantsTotal: 0,
463
+ guardsMatched: [],
464
+ rulesMatched: [],
465
+ enforcementLevel: level
466
+ }
467
+ };
468
+ }
469
+ const inputLength = event.intent.length + (event.tool?.length ?? 0) + (event.scope?.length ?? 0) + (event.payload ? JSON.stringify(event.payload).length : 0);
470
+ if (inputLength > MAX_INPUT_LENGTH) {
471
+ return {
472
+ status: "BLOCK",
473
+ reason: `Input exceeds maximum allowed length (${MAX_INPUT_LENGTH} characters)`,
474
+ ruleId: "safety-input-length",
475
+ evidence: {
476
+ worldId: world.world?.world_id ?? "",
477
+ worldName: world.world?.name ?? "",
478
+ worldVersion: world.world?.version ?? "",
479
+ evaluatedAt: Date.now(),
480
+ invariantsSatisfied: 0,
481
+ invariantsTotal: 0,
482
+ guardsMatched: [],
483
+ rulesMatched: [],
484
+ enforcementLevel: level
485
+ }
486
+ };
487
+ }
488
+ const eventText = normalizeEventText(event);
427
489
  const invariantChecks = [];
428
490
  const safetyChecks = [];
429
491
  let planCheckResult;
@@ -436,6 +498,43 @@ function evaluateGuard(event, world, options = {}) {
436
498
  const guardsMatched = [];
437
499
  const rulesMatched = [];
438
500
  checkInvariantCoverage(world, invariantChecks);
501
+ if (event.roleId && options.agentStates) {
502
+ const agentState = options.agentStates.get(event.roleId);
503
+ if (agentState && agentState.cooldownRemaining > 0) {
504
+ decidingLayer = "safety";
505
+ decidingId = `penalize-cooldown-${event.roleId}`;
506
+ const verdict = buildVerdict(
507
+ "PENALIZE",
508
+ `Agent "${event.roleId}" is frozen for ${agentState.cooldownRemaining} more round(s) due to prior penalty.`,
509
+ `penalize-cooldown-${event.roleId}`,
510
+ void 0,
511
+ world,
512
+ level,
513
+ invariantChecks,
514
+ guardsMatched,
515
+ rulesMatched,
516
+ includeTrace ? buildTrace(
517
+ invariantChecks,
518
+ safetyChecks,
519
+ planCheckResult,
520
+ roleChecks,
521
+ guardChecks,
522
+ kernelRuleChecks,
523
+ levelChecks,
524
+ decidingLayer,
525
+ decidingId,
526
+ startTime
527
+ ) : void 0
528
+ );
529
+ verdict.intentRecord = {
530
+ originalIntent: event.intent,
531
+ finalAction: "blocked (agent frozen)",
532
+ enforcement: "PENALIZE",
533
+ consequence: { type: "freeze", rounds: agentState.cooldownRemaining, description: "Agent still in cooldown from prior penalty" }
534
+ };
535
+ return verdict;
536
+ }
537
+ }
439
538
  if (options.sessionAllowlist) {
440
539
  const key = eventToAllowlistKey(event);
441
540
  if (options.sessionAllowlist.has(key)) {
@@ -563,7 +662,16 @@ function evaluateGuard(event, world, options = {}) {
563
662
  if (guardVerdict.status !== "ALLOW") {
564
663
  decidingLayer = "guard";
565
664
  decidingId = guardVerdict.ruleId;
566
- return buildVerdict(
665
+ const intentRecord = {
666
+ originalIntent: event.intent,
667
+ finalAction: guardVerdict.status === "MODIFY" ? guardVerdict.modifiedTo ?? "modified" : guardVerdict.status === "PENALIZE" ? "blocked + penalized" : guardVerdict.status === "REWARD" ? event.intent : guardVerdict.status === "NEUTRAL" ? event.intent : guardVerdict.status === "BLOCK" ? "blocked" : "paused",
668
+ ruleApplied: guardVerdict.ruleId,
669
+ enforcement: guardVerdict.status,
670
+ modifiedTo: guardVerdict.modifiedTo,
671
+ consequence: guardVerdict.consequence,
672
+ reward: guardVerdict.reward
673
+ };
674
+ const verdict = buildVerdict(
567
675
  guardVerdict.status,
568
676
  guardVerdict.reason,
569
677
  guardVerdict.ruleId,
@@ -586,6 +694,10 @@ function evaluateGuard(event, world, options = {}) {
586
694
  startTime
587
695
  ) : void 0
588
696
  );
697
+ verdict.intentRecord = intentRecord;
698
+ if (guardVerdict.consequence) verdict.consequence = guardVerdict.consequence;
699
+ if (guardVerdict.reward) verdict.reward = guardVerdict.reward;
700
+ return verdict;
589
701
  }
590
702
  }
591
703
  const kernelVerdict = checkKernelRules(eventText, world, kernelRuleChecks, rulesMatched);
@@ -880,6 +992,21 @@ function checkGuards(event, eventText, world, checks, guardsMatched) {
880
992
  if (actionMode === "pause") {
881
993
  return { status: "PAUSE", reason, ruleId: `guard-${guard.id}` };
882
994
  }
995
+ if (actionMode === "penalize") {
996
+ const consequence = guard.consequence ? { ...guard.consequence } : { type: "freeze", rounds: 1, description: `Penalized for violating: ${guard.label}` };
997
+ return { status: "PENALIZE", reason, ruleId: `guard-${guard.id}`, consequence };
998
+ }
999
+ if (actionMode === "reward") {
1000
+ const reward = guard.reward ? { ...guard.reward } : { type: "boost_influence", magnitude: 0.1, description: `Rewarded for: ${guard.label}` };
1001
+ return { status: "REWARD", reason, ruleId: `guard-${guard.id}`, reward };
1002
+ }
1003
+ if (actionMode === "modify") {
1004
+ const modifiedTo = guard.modify_to ?? guard.redirect ?? "hold";
1005
+ return { status: "MODIFY", reason: `${reason} \u2192 Modified to: ${modifiedTo}`, ruleId: `guard-${guard.id}`, modifiedTo };
1006
+ }
1007
+ if (actionMode === "neutral") {
1008
+ return { status: "NEUTRAL", reason, ruleId: `guard-${guard.id}` };
1009
+ }
883
1010
  if (actionMode === "warn" && !warnResult) {
884
1011
  warnResult = { status: "ALLOW", warning: reason, ruleId: `guard-${guard.id}` };
885
1012
  }
@@ -989,9 +1116,7 @@ function checkLevelConstraints(event, level, checks) {
989
1116
  return null;
990
1117
  }
991
1118
  function matchesKeywords(eventText, ruleText) {
992
- const keywords = ruleText.toLowerCase().split(/\s+/).filter((w) => w.length > 3);
993
- if (keywords.length === 0) return false;
994
- return keywords.every((kw) => eventText.includes(kw));
1119
+ return matchesAllKeywords(eventText, ruleText);
995
1120
  }
996
1121
  function eventToAllowlistKey(event) {
997
1122
  return `${(event.tool ?? "*").toLowerCase()}::${event.intent.toLowerCase().trim()}`;
@@ -1052,11 +1177,12 @@ function buildVerdict(status, reason, ruleId, warning, world, level, invariantCh
1052
1177
  if (trace) verdict.trace = trace;
1053
1178
  return verdict;
1054
1179
  }
1055
- var PROMPT_INJECTION_PATTERNS, EXECUTION_CLAIM_PATTERNS, EXECUTION_INTENT_PATTERNS, SCOPE_ESCAPE_PATTERNS, NEUTRAL_MESSAGES;
1180
+ var PROMPT_INJECTION_PATTERNS, EXECUTION_CLAIM_PATTERNS, EXECUTION_INTENT_PATTERNS, SCOPE_ESCAPE_PATTERNS, NEUTRAL_MESSAGES, MAX_INPUT_LENGTH;
1056
1181
  var init_guard_engine = __esm({
1057
1182
  "src/engine/guard-engine.ts"() {
1058
1183
  "use strict";
1059
1184
  init_plan_engine();
1185
+ init_text_utils();
1060
1186
  PROMPT_INJECTION_PATTERNS = [
1061
1187
  // Instruction override
1062
1188
  { pattern: /ignore\s+(previous|all|prior|above)\s+(instructions?|rules?)/i, label: "ignore-instructions" },
@@ -1120,6 +1246,7 @@ var init_guard_engine = __esm({
1120
1246
  "network-mutate": "This action would send data to an external service.",
1121
1247
  "credential-access": "This action would access stored credentials."
1122
1248
  };
1249
+ MAX_INPUT_LENGTH = 1e5;
1123
1250
  }
1124
1251
  });
1125
1252
 
@@ -1129,10 +1256,18 @@ async function loadWorldFromDirectory(dirPath) {
1129
1256
  const { join: join3 } = await import("path");
1130
1257
  const { readdirSync: readdirSync3 } = await import("fs");
1131
1258
  async function readJson(filename) {
1259
+ const filePath = join3(dirPath, filename);
1132
1260
  try {
1133
- const content = await readFile(join3(dirPath, filename), "utf-8");
1261
+ const content = await readFile(filePath, "utf-8");
1134
1262
  return JSON.parse(content);
1135
- } catch {
1263
+ } catch (err) {
1264
+ if (err instanceof Error && "code" in err && err.code === "ENOENT") {
1265
+ return void 0;
1266
+ }
1267
+ process.stderr.write(
1268
+ `[neuroverse] Warning: Failed to read ${filename}: ${err instanceof Error ? err.message : String(err)}
1269
+ `
1270
+ );
1136
1271
  return void 0;
1137
1272
  }
1138
1273
  }
@@ -1154,10 +1289,23 @@ async function loadWorldFromDirectory(dirPath) {
1154
1289
  const rulesDir = join3(dirPath, "rules");
1155
1290
  const ruleFiles = readdirSync3(rulesDir).filter((f) => f.endsWith(".json")).sort();
1156
1291
  for (const file of ruleFiles) {
1157
- const content = await readFile(join3(rulesDir, file), "utf-8");
1158
- rules.push(JSON.parse(content));
1292
+ try {
1293
+ const content = await readFile(join3(rulesDir, file), "utf-8");
1294
+ rules.push(JSON.parse(content));
1295
+ } catch (err) {
1296
+ process.stderr.write(
1297
+ `[neuroverse] Warning: Failed to parse rule ${file}: ${err instanceof Error ? err.message : String(err)}
1298
+ `
1299
+ );
1300
+ }
1301
+ }
1302
+ } catch (err) {
1303
+ if (!(err instanceof Error && "code" in err && err.code === "ENOENT")) {
1304
+ process.stderr.write(
1305
+ `[neuroverse] Warning: Failed to read rules directory: ${err instanceof Error ? err.message : String(err)}
1306
+ `
1307
+ );
1159
1308
  }
1160
- } catch {
1161
1309
  }
1162
1310
  return {
1163
1311
  world: worldJson,
@@ -1192,10 +1340,7 @@ async function loadWorld(worldPath) {
1192
1340
  if (info.isDirectory()) {
1193
1341
  return loadWorldFromDirectory(worldPath);
1194
1342
  }
1195
- if (worldPath.endsWith(".nv-world.zip")) {
1196
- throw new Error(".nv-world.zip loading not yet implemented \u2014 use a world directory");
1197
- }
1198
- throw new Error(`Cannot load world from: ${worldPath} \u2014 expected a directory or .nv-world.zip`);
1343
+ throw new Error(`Cannot load world from: ${worldPath} \u2014 expected a directory`);
1199
1344
  }
1200
1345
  var init_world_loader = __esm({
1201
1346
  "src/loader/world-loader.ts"() {
@@ -1203,6 +1348,82 @@ var init_world_loader = __esm({
1203
1348
  }
1204
1349
  });
1205
1350
 
1351
+ // src/engine/decision-flow-engine.ts
1352
+ function createAgentState(agentId) {
1353
+ return {
1354
+ agentId,
1355
+ cooldownRemaining: 0,
1356
+ influence: 1,
1357
+ rewardMultiplier: 1,
1358
+ totalPenalties: 0,
1359
+ totalRewards: 0,
1360
+ consequenceHistory: [],
1361
+ rewardHistory: []
1362
+ };
1363
+ }
1364
+ function applyConsequence(state, consequence, ruleId) {
1365
+ const updated = { ...state };
1366
+ updated.totalPenalties++;
1367
+ updated.consequenceHistory = [
1368
+ ...state.consequenceHistory,
1369
+ { ruleId, consequence, appliedAt: Date.now() }
1370
+ ];
1371
+ switch (consequence.type) {
1372
+ case "freeze":
1373
+ case "cooldown":
1374
+ updated.cooldownRemaining = Math.max(
1375
+ state.cooldownRemaining,
1376
+ consequence.rounds ?? 1
1377
+ );
1378
+ break;
1379
+ case "reduce_influence":
1380
+ updated.influence = Math.max(0, state.influence - (consequence.magnitude ?? 0.1));
1381
+ break;
1382
+ case "increase_risk":
1383
+ break;
1384
+ case "custom":
1385
+ break;
1386
+ }
1387
+ return updated;
1388
+ }
1389
+ function applyReward(state, reward, ruleId) {
1390
+ const updated = { ...state };
1391
+ updated.totalRewards++;
1392
+ updated.rewardHistory = [
1393
+ ...state.rewardHistory,
1394
+ { ruleId, reward, appliedAt: Date.now() }
1395
+ ];
1396
+ switch (reward.type) {
1397
+ case "boost_influence":
1398
+ updated.influence = Math.min(2, state.influence + (reward.magnitude ?? 0.1));
1399
+ break;
1400
+ case "weight_increase":
1401
+ updated.rewardMultiplier = Math.min(3, state.rewardMultiplier + (reward.magnitude ?? 0.1));
1402
+ break;
1403
+ case "priority":
1404
+ case "faster_execution":
1405
+ break;
1406
+ case "custom":
1407
+ break;
1408
+ }
1409
+ return updated;
1410
+ }
1411
+ function tickAgentStates(states) {
1412
+ const updated = /* @__PURE__ */ new Map();
1413
+ for (const [id, state] of states) {
1414
+ updated.set(id, {
1415
+ ...state,
1416
+ cooldownRemaining: Math.max(0, state.cooldownRemaining - 1)
1417
+ });
1418
+ }
1419
+ return updated;
1420
+ }
1421
+ var init_decision_flow_engine = __esm({
1422
+ "src/engine/decision-flow-engine.ts"() {
1423
+ "use strict";
1424
+ }
1425
+ });
1426
+
1206
1427
  // src/runtime/session.ts
1207
1428
  var session_exports = {};
1208
1429
  __export(session_exports, {
@@ -1337,7 +1558,9 @@ async function runInteractiveMode(config, model) {
1337
1558
  `);
1338
1559
  process.stdout.write(` Actions: ${s.actionsEvaluated} evaluated
1339
1560
  `);
1340
- process.stdout.write(` Allowed: ${s.actionsAllowed} | Blocked: ${s.actionsBlocked} | Paused: ${s.actionsPaused}
1561
+ process.stdout.write(` Allowed: ${s.actionsAllowed} | Blocked: ${s.actionsBlocked} | Modified: ${s.actionsModified} | Paused: ${s.actionsPaused}
1562
+ `);
1563
+ process.stdout.write(` Penalized: ${s.actionsPenalized} | Rewarded: ${s.actionsRewarded}
1341
1564
  `);
1342
1565
  if (s.progress && s.plan) {
1343
1566
  process.stdout.write(` Plan: ${s.plan.plan_id} \u2014 ${s.progress.completed}/${s.progress.total} (${s.progress.percentage}%)
@@ -1391,6 +1614,7 @@ var init_session = __esm({
1391
1614
  init_guard_engine();
1392
1615
  init_plan_engine();
1393
1616
  init_world_loader();
1617
+ init_decision_flow_engine();
1394
1618
  SessionManager = class {
1395
1619
  config;
1396
1620
  state;
@@ -1412,7 +1636,11 @@ var init_session = __esm({
1412
1636
  actionsEvaluated: 0,
1413
1637
  actionsAllowed: 0,
1414
1638
  actionsBlocked: 0,
1415
- actionsPaused: 0
1639
+ actionsPaused: 0,
1640
+ actionsModified: 0,
1641
+ actionsPenalized: 0,
1642
+ actionsRewarded: 0,
1643
+ agentStates: /* @__PURE__ */ new Map()
1416
1644
  };
1417
1645
  }
1418
1646
  /**
@@ -1434,14 +1662,41 @@ var init_session = __esm({
1434
1662
  */
1435
1663
  evaluate(event) {
1436
1664
  this.engineOptions.plan = this.state.plan;
1665
+ this.engineOptions.agentStates = this.state.agentStates;
1437
1666
  const verdict = evaluateGuard(event, this.state.world, this.engineOptions);
1438
1667
  this.state.actionsEvaluated++;
1439
1668
  if (verdict.status === "ALLOW") this.state.actionsAllowed++;
1440
1669
  if (verdict.status === "BLOCK") this.state.actionsBlocked++;
1441
1670
  if (verdict.status === "PAUSE") this.state.actionsPaused++;
1671
+ if (verdict.status === "MODIFY") this.state.actionsModified++;
1672
+ if (verdict.status === "PENALIZE") this.state.actionsPenalized++;
1673
+ if (verdict.status === "REWARD") this.state.actionsRewarded++;
1674
+ if (event.roleId) {
1675
+ let agentState = this.state.agentStates.get(event.roleId) ?? createAgentState(event.roleId);
1676
+ if (verdict.status === "PENALIZE" && verdict.consequence) {
1677
+ agentState = applyConsequence(agentState, verdict.consequence, verdict.ruleId ?? "unknown");
1678
+ }
1679
+ if (verdict.status === "REWARD" && verdict.reward) {
1680
+ agentState = applyReward(agentState, verdict.reward, verdict.ruleId ?? "unknown");
1681
+ }
1682
+ this.state.agentStates.set(event.roleId, agentState);
1683
+ }
1442
1684
  this.config.onVerdict?.(verdict, event);
1443
1685
  return verdict;
1444
1686
  }
1687
+ /**
1688
+ * Advance all agent states by one round.
1689
+ * Call this at the end of each simulation round to decrement cooldowns.
1690
+ */
1691
+ tickRound() {
1692
+ this.state.agentStates = tickAgentStates(this.state.agentStates);
1693
+ }
1694
+ /**
1695
+ * Get the behavior state for a specific agent.
1696
+ */
1697
+ getAgentState(agentId) {
1698
+ return this.state.agentStates.get(agentId);
1699
+ }
1445
1700
  /**
1446
1701
  * Evaluate and execute a tool call.
1447
1702
  * Returns the execution result or block reason.
@@ -1460,7 +1715,7 @@ var init_session = __esm({
1460
1715
  direction: "input"
1461
1716
  };
1462
1717
  const verdict = this.evaluate(event);
1463
- if (verdict.status === "BLOCK") {
1718
+ if (verdict.status === "BLOCK" || verdict.status === "PENALIZE") {
1464
1719
  return { allowed: false, verdict };
1465
1720
  }
1466
1721
  if (verdict.status === "PAUSE") {
package/dist/cli/run.js CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  describeActiveWorld,
3
3
  resolveWorldPath
4
4
  } from "../chunk-AKW5YVCE.js";
5
- import "../chunk-YZFATT7X.js";
5
+ import "../chunk-QWGCMQQD.js";
6
6
 
7
7
  // src/cli/run.ts
8
8
  import { readFileSync, readdirSync, existsSync } from "fs";
@@ -91,8 +91,8 @@ async function main(args) {
91
91
  process.exit(1);
92
92
  return;
93
93
  }
94
- const { resolveProvider, ModelAdapter } = await import("../model-adapter-BB7G4MFI.js");
95
- const { runInteractiveMode } = await import("../session-EKTRSR7C.js");
94
+ const { resolveProvider, ModelAdapter } = await import("../model-adapter-VXEKB4LS.js");
95
+ const { runInteractiveMode } = await import("../session-JYOARW54.js");
96
96
  const modelConfig = resolveProvider(providerName, {
97
97
  model: parseArg(args, "--model"),
98
98
  apiKey: parseArg(args, "--api-key")
@@ -126,7 +126,7 @@ async function main(args) {
126
126
  model
127
127
  );
128
128
  } else if (isPipeMode) {
129
- const { runPipeMode } = await import("../session-EKTRSR7C.js");
129
+ const { runPipeMode } = await import("../session-JYOARW54.js");
130
130
  await runPipeMode({
131
131
  worldPath,
132
132
  plan,
@@ -8,7 +8,7 @@ import {
8
8
  redactConfig,
9
9
  saveConfig
10
10
  } from "./chunk-OT6PXH54.js";
11
- import "./chunk-YZFATT7X.js";
11
+ import "./chunk-QWGCMQQD.js";
12
12
 
13
13
  // src/cli/configure-ai.ts
14
14
  function parseArgs(argv) {
@@ -0,0 +1,61 @@
1
+ import {
2
+ readAuditLog
3
+ } from "./chunk-A7GKPPU7.js";
4
+ import {
5
+ generateDecisionFlow,
6
+ renderDecisionFlow
7
+ } from "./chunk-D2UCV5AK.js";
8
+ import "./chunk-W7LLXRGY.js";
9
+ import "./chunk-QLPTHTVB.js";
10
+ import "./chunk-QWGCMQQD.js";
11
+
12
+ // src/cli/decision-flow.ts
13
+ async function main(args) {
14
+ let logPath = ".neuroverse/audit.ndjson";
15
+ let jsonOutput = false;
16
+ for (let i = 0; i < args.length; i++) {
17
+ if (args[i] === "--log" && args[i + 1]) {
18
+ logPath = args[++i];
19
+ }
20
+ if (args[i] === "--json") {
21
+ jsonOutput = true;
22
+ }
23
+ if (args[i] === "--help" || args[i] === "-h") {
24
+ process.stdout.write(`
25
+ neuroverse decision-flow \u2014 Visualize Intent \u2192 Rule \u2192 Outcome
26
+
27
+ Usage:
28
+ neuroverse decision-flow [--log <path>] [--json]
29
+
30
+ Options:
31
+ --log <path> Path to audit log (default: .neuroverse/audit.ndjson)
32
+ --json Output as JSON instead of text
33
+
34
+ Shows:
35
+ - What agents WANTED to do (Intent Pool)
36
+ - What rules INTERCEPTED (Rule Obstacles)
37
+ - What actually HAPPENED (Outcome Pool)
38
+ - Behavioral economy (penalties vs rewards)
39
+
40
+ Headline metric: "X% of agent intent was redirected by governance"
41
+ `.trim() + "\n");
42
+ return;
43
+ }
44
+ }
45
+ const events = await readAuditLog(logPath);
46
+ if (events.length === 0) {
47
+ process.stderr.write("No audit events found. Run governed actions first.\n");
48
+ process.stderr.write(`Looking in: ${logPath}
49
+ `);
50
+ process.exit(1);
51
+ }
52
+ const flow = generateDecisionFlow(events);
53
+ if (jsonOutput) {
54
+ process.stdout.write(JSON.stringify(flow, null, 2) + "\n");
55
+ } else {
56
+ process.stdout.write(renderDecisionFlow(flow) + "\n");
57
+ }
58
+ }
59
+ export {
60
+ main
61
+ };