@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
@@ -31,12 +31,18 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var adapters_exports = {};
32
32
  __export(adapters_exports, {
33
33
  AutoresearchGovernor: () => AutoresearchGovernor,
34
+ DeepAgentsGovernanceBlockedError: () => GovernanceBlockedError5,
35
+ DeepAgentsGuard: () => DeepAgentsGuard,
36
+ GovernanceBlockedError: () => GovernanceBlockedError,
34
37
  GovernedToolExecutor: () => GovernedToolExecutor,
35
- LangChainGovernanceBlockedError: () => GovernanceBlockedError,
38
+ LangChainGovernanceBlockedError: () => GovernanceBlockedError2,
36
39
  NeuroVerseCallbackHandler: () => NeuroVerseCallbackHandler,
37
40
  NeuroVersePlugin: () => NeuroVersePlugin,
38
- OpenAIGovernanceBlockedError: () => GovernanceBlockedError2,
39
- OpenClawGovernanceBlockedError: () => GovernanceBlockedError3,
41
+ OpenAIGovernanceBlockedError: () => GovernanceBlockedError3,
42
+ OpenClawGovernanceBlockedError: () => GovernanceBlockedError4,
43
+ buildEngineOptions: () => buildEngineOptions,
44
+ createDeepAgentsGuard: () => createDeepAgentsGuard,
45
+ createDeepAgentsGuardFromWorld: () => createDeepAgentsGuardFromWorld,
40
46
  createGovernanceMiddleware: () => createGovernanceMiddleware,
41
47
  createGovernanceMiddlewareFromWorld: () => createGovernanceMiddlewareFromWorld,
42
48
  createGovernedToolExecutor: () => createGovernedToolExecutor,
@@ -44,21 +50,34 @@ __export(adapters_exports, {
44
50
  createNeuroVerseCallbackHandler: () => createNeuroVerseCallbackHandler,
45
51
  createNeuroVerseCallbackHandlerFromWorld: () => createNeuroVerseCallbackHandlerFromWorld,
46
52
  createNeuroVersePlugin: () => createNeuroVersePlugin,
47
- createNeuroVersePluginFromWorld: () => createNeuroVersePluginFromWorld
53
+ createNeuroVersePluginFromWorld: () => createNeuroVersePluginFromWorld,
54
+ defaultBlockMessage: () => defaultBlockMessage,
55
+ extractScope: () => extractScope,
56
+ trackPlanProgress: () => trackPlanProgress
48
57
  });
49
58
  module.exports = __toCommonJS(adapters_exports);
50
59
 
51
- // src/engine/plan-engine.ts
52
- function keywordMatch(eventText, step) {
53
- const stepText = [
54
- step.label,
55
- step.description ?? "",
56
- ...step.tags ?? []
60
+ // src/engine/text-utils.ts
61
+ function normalizeEventText(event) {
62
+ return [
63
+ event.intent,
64
+ event.tool ?? "",
65
+ event.scope ?? ""
57
66
  ].join(" ").toLowerCase();
58
- const keywords = stepText.split(/\s+/).filter((w) => w.length > 3);
67
+ }
68
+ function extractKeywords(text, minLength = 3) {
69
+ return text.toLowerCase().split(/\s+/).filter((w) => w.length > minLength);
70
+ }
71
+ function matchesAllKeywords(eventText, ruleText) {
72
+ const keywords = extractKeywords(ruleText);
73
+ if (keywords.length === 0) return false;
74
+ return keywords.every((kw) => eventText.includes(kw));
75
+ }
76
+ function matchesKeywordThreshold(eventText, ruleText, threshold = 0.5) {
77
+ const keywords = extractKeywords(ruleText);
59
78
  if (keywords.length === 0) return false;
60
79
  const matched = keywords.filter((kw) => eventText.includes(kw));
61
- return matched.length >= Math.ceil(keywords.length * 0.5);
80
+ return matched.length >= Math.ceil(keywords.length * threshold);
62
81
  }
63
82
  function tokenSimilarity(a, b) {
64
83
  const tokensA = new Set(a.toLowerCase().split(/\s+/).filter((w) => w.length > 2));
@@ -71,6 +90,19 @@ function tokenSimilarity(a, b) {
71
90
  const union = (/* @__PURE__ */ new Set([...tokensA, ...tokensB])).size;
72
91
  return union > 0 ? intersection / union : 0;
73
92
  }
93
+
94
+ // src/engine/plan-engine.ts
95
+ function keywordMatch(eventText, step) {
96
+ const stepText = [
97
+ step.label,
98
+ step.description ?? "",
99
+ ...step.tags ?? []
100
+ ].join(" ");
101
+ return matchesKeywordThreshold(eventText, stepText, 0.5);
102
+ }
103
+ function tokenSimilarity2(a, b) {
104
+ return tokenSimilarity(a, b);
105
+ }
74
106
  function findMatchingStep(eventText, event, steps) {
75
107
  const pendingOrActive = steps.filter((s) => s.status === "pending" || s.status === "active");
76
108
  if (pendingOrActive.length === 0) {
@@ -89,7 +121,7 @@ function findMatchingStep(eventText, event, steps) {
89
121
  let bestScore = 0;
90
122
  for (const step of pendingOrActive) {
91
123
  const stepText = [step.label, step.description ?? "", ...step.tags ?? []].join(" ");
92
- const score = tokenSimilarity(intentText, stepText);
124
+ const score = tokenSimilarity2(intentText, stepText);
93
125
  if (score > bestScore) {
94
126
  bestScore = score;
95
127
  bestStep = step;
@@ -130,7 +162,7 @@ function checkConstraints(event, eventText, constraints) {
130
162
  continue;
131
163
  }
132
164
  if (constraint.type === "scope" && constraint.trigger) {
133
- const keywords = constraint.trigger.split(/\s+/).filter((w) => w.length > 3);
165
+ const keywords = extractKeywords(constraint.trigger);
134
166
  const violated = keywords.length > 0 && keywords.every((kw) => eventText.includes(kw));
135
167
  checks.push({
136
168
  constraintId: constraint.id,
@@ -211,11 +243,7 @@ function evaluatePlan(event, plan) {
211
243
  progress
212
244
  };
213
245
  }
214
- const eventText = [
215
- event.intent,
216
- event.tool ?? "",
217
- event.scope ?? ""
218
- ].join(" ").toLowerCase();
246
+ const eventText = normalizeEventText(event);
219
247
  const { matched, closest, closestScore } = findMatchingStep(eventText, event, plan.steps);
220
248
  if (!matched) {
221
249
  return {
@@ -256,7 +284,7 @@ function evaluatePlan(event, plan) {
256
284
  };
257
285
  }
258
286
  function buildPlanCheck(event, plan, verdict) {
259
- const eventText = [event.intent, event.tool ?? "", event.scope ?? ""].join(" ").toLowerCase();
287
+ const eventText = normalizeEventText(event);
260
288
  const { matched, closest, closestScore } = findMatchingStep(eventText, event, plan.steps);
261
289
  const { checks: constraintChecks } = checkConstraints(event, eventText, plan.constraints);
262
290
  const progress = getPlanProgress(plan);
@@ -274,6 +302,50 @@ function buildPlanCheck(event, plan, verdict) {
274
302
  };
275
303
  }
276
304
 
305
+ // src/adapters/shared.ts
306
+ var GovernanceBlockedError = class extends Error {
307
+ verdict;
308
+ constructor(verdict, message) {
309
+ super(message ?? `[NeuroVerse] BLOCKED: ${verdict.reason ?? verdict.ruleId ?? "governance rule"}`);
310
+ this.name = "GovernanceBlockedError";
311
+ this.verdict = verdict;
312
+ }
313
+ };
314
+ function trackPlanProgress(event, state, callbacks) {
315
+ if (!state.activePlan) return;
316
+ const planVerdict = evaluatePlan(event, state.activePlan);
317
+ if (planVerdict.matchedStep) {
318
+ const advResult = advancePlan(state.activePlan, planVerdict.matchedStep);
319
+ if (advResult.success && advResult.plan) {
320
+ state.activePlan = advResult.plan;
321
+ state.engineOptions.plan = state.activePlan;
322
+ }
323
+ const progress = getPlanProgress(state.activePlan);
324
+ callbacks.onPlanProgress?.(progress);
325
+ if (progress.completed === progress.total) {
326
+ callbacks.onPlanComplete?.();
327
+ }
328
+ }
329
+ }
330
+ function extractScope(args) {
331
+ if (typeof args.path === "string") return args.path;
332
+ if (typeof args.file_path === "string") return args.file_path;
333
+ if (typeof args.filename === "string") return args.filename;
334
+ if (typeof args.url === "string") return args.url;
335
+ if (typeof args.command === "string") return args.command;
336
+ return void 0;
337
+ }
338
+ function buildEngineOptions(options, plan) {
339
+ return {
340
+ trace: options.trace ?? false,
341
+ level: options.level,
342
+ plan: plan ?? options.plan
343
+ };
344
+ }
345
+ function defaultBlockMessage(verdict) {
346
+ return `Action blocked by governance policy: ${verdict.reason ?? "rule violation"}. Rule: ${verdict.ruleId ?? "unknown"}.`;
347
+ }
348
+
277
349
  // src/engine/guard-engine.ts
278
350
  var PROMPT_INJECTION_PATTERNS = [
279
351
  // Instruction override
@@ -358,11 +430,49 @@ function isExternalScope(scope) {
358
430
  ];
359
431
  return !internalPatterns.some((p) => p.test(scope));
360
432
  }
433
+ var MAX_INPUT_LENGTH = 1e5;
361
434
  function evaluateGuard(event, world, options = {}) {
362
435
  const startTime = performance.now();
363
436
  const level = options.level ?? "standard";
364
437
  const includeTrace = options.trace ?? false;
365
- const eventText = (event.intent + " " + (event.tool ?? "") + " " + (event.scope ?? "")).toLowerCase();
438
+ if (!event.intent || typeof event.intent !== "string") {
439
+ return {
440
+ status: "BLOCK",
441
+ reason: "GuardEvent.intent is required and must be a string",
442
+ ruleId: "safety-input-validation",
443
+ evidence: {
444
+ worldId: world.world?.world_id ?? "",
445
+ worldName: world.world?.name ?? "",
446
+ worldVersion: world.world?.version ?? "",
447
+ evaluatedAt: Date.now(),
448
+ invariantsSatisfied: 0,
449
+ invariantsTotal: 0,
450
+ guardsMatched: [],
451
+ rulesMatched: [],
452
+ enforcementLevel: level
453
+ }
454
+ };
455
+ }
456
+ const inputLength = event.intent.length + (event.tool?.length ?? 0) + (event.scope?.length ?? 0) + (event.payload ? JSON.stringify(event.payload).length : 0);
457
+ if (inputLength > MAX_INPUT_LENGTH) {
458
+ return {
459
+ status: "BLOCK",
460
+ reason: `Input exceeds maximum allowed length (${MAX_INPUT_LENGTH} characters)`,
461
+ ruleId: "safety-input-length",
462
+ evidence: {
463
+ worldId: world.world?.world_id ?? "",
464
+ worldName: world.world?.name ?? "",
465
+ worldVersion: world.world?.version ?? "",
466
+ evaluatedAt: Date.now(),
467
+ invariantsSatisfied: 0,
468
+ invariantsTotal: 0,
469
+ guardsMatched: [],
470
+ rulesMatched: [],
471
+ enforcementLevel: level
472
+ }
473
+ };
474
+ }
475
+ const eventText = normalizeEventText(event);
366
476
  const invariantChecks = [];
367
477
  const safetyChecks = [];
368
478
  let planCheckResult;
@@ -375,6 +485,43 @@ function evaluateGuard(event, world, options = {}) {
375
485
  const guardsMatched = [];
376
486
  const rulesMatched = [];
377
487
  checkInvariantCoverage(world, invariantChecks);
488
+ if (event.roleId && options.agentStates) {
489
+ const agentState = options.agentStates.get(event.roleId);
490
+ if (agentState && agentState.cooldownRemaining > 0) {
491
+ decidingLayer = "safety";
492
+ decidingId = `penalize-cooldown-${event.roleId}`;
493
+ const verdict = buildVerdict(
494
+ "PENALIZE",
495
+ `Agent "${event.roleId}" is frozen for ${agentState.cooldownRemaining} more round(s) due to prior penalty.`,
496
+ `penalize-cooldown-${event.roleId}`,
497
+ void 0,
498
+ world,
499
+ level,
500
+ invariantChecks,
501
+ guardsMatched,
502
+ rulesMatched,
503
+ includeTrace ? buildTrace(
504
+ invariantChecks,
505
+ safetyChecks,
506
+ planCheckResult,
507
+ roleChecks,
508
+ guardChecks,
509
+ kernelRuleChecks,
510
+ levelChecks,
511
+ decidingLayer,
512
+ decidingId,
513
+ startTime
514
+ ) : void 0
515
+ );
516
+ verdict.intentRecord = {
517
+ originalIntent: event.intent,
518
+ finalAction: "blocked (agent frozen)",
519
+ enforcement: "PENALIZE",
520
+ consequence: { type: "freeze", rounds: agentState.cooldownRemaining, description: "Agent still in cooldown from prior penalty" }
521
+ };
522
+ return verdict;
523
+ }
524
+ }
378
525
  if (options.sessionAllowlist) {
379
526
  const key = eventToAllowlistKey(event);
380
527
  if (options.sessionAllowlist.has(key)) {
@@ -502,7 +649,16 @@ function evaluateGuard(event, world, options = {}) {
502
649
  if (guardVerdict.status !== "ALLOW") {
503
650
  decidingLayer = "guard";
504
651
  decidingId = guardVerdict.ruleId;
505
- return buildVerdict(
652
+ const intentRecord = {
653
+ originalIntent: event.intent,
654
+ 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",
655
+ ruleApplied: guardVerdict.ruleId,
656
+ enforcement: guardVerdict.status,
657
+ modifiedTo: guardVerdict.modifiedTo,
658
+ consequence: guardVerdict.consequence,
659
+ reward: guardVerdict.reward
660
+ };
661
+ const verdict = buildVerdict(
506
662
  guardVerdict.status,
507
663
  guardVerdict.reason,
508
664
  guardVerdict.ruleId,
@@ -525,6 +681,10 @@ function evaluateGuard(event, world, options = {}) {
525
681
  startTime
526
682
  ) : void 0
527
683
  );
684
+ verdict.intentRecord = intentRecord;
685
+ if (guardVerdict.consequence) verdict.consequence = guardVerdict.consequence;
686
+ if (guardVerdict.reward) verdict.reward = guardVerdict.reward;
687
+ return verdict;
528
688
  }
529
689
  }
530
690
  const kernelVerdict = checkKernelRules(eventText, world, kernelRuleChecks, rulesMatched);
@@ -819,6 +979,21 @@ function checkGuards(event, eventText, world, checks, guardsMatched) {
819
979
  if (actionMode === "pause") {
820
980
  return { status: "PAUSE", reason, ruleId: `guard-${guard.id}` };
821
981
  }
982
+ if (actionMode === "penalize") {
983
+ const consequence = guard.consequence ? { ...guard.consequence } : { type: "freeze", rounds: 1, description: `Penalized for violating: ${guard.label}` };
984
+ return { status: "PENALIZE", reason, ruleId: `guard-${guard.id}`, consequence };
985
+ }
986
+ if (actionMode === "reward") {
987
+ const reward = guard.reward ? { ...guard.reward } : { type: "boost_influence", magnitude: 0.1, description: `Rewarded for: ${guard.label}` };
988
+ return { status: "REWARD", reason, ruleId: `guard-${guard.id}`, reward };
989
+ }
990
+ if (actionMode === "modify") {
991
+ const modifiedTo = guard.modify_to ?? guard.redirect ?? "hold";
992
+ return { status: "MODIFY", reason: `${reason} \u2192 Modified to: ${modifiedTo}`, ruleId: `guard-${guard.id}`, modifiedTo };
993
+ }
994
+ if (actionMode === "neutral") {
995
+ return { status: "NEUTRAL", reason, ruleId: `guard-${guard.id}` };
996
+ }
822
997
  if (actionMode === "warn" && !warnResult) {
823
998
  warnResult = { status: "ALLOW", warning: reason, ruleId: `guard-${guard.id}` };
824
999
  }
@@ -928,9 +1103,7 @@ function checkLevelConstraints(event, level, checks) {
928
1103
  return null;
929
1104
  }
930
1105
  function matchesKeywords(eventText, ruleText) {
931
- const keywords = ruleText.toLowerCase().split(/\s+/).filter((w) => w.length > 3);
932
- if (keywords.length === 0) return false;
933
- return keywords.every((kw) => eventText.includes(kw));
1106
+ return matchesAllKeywords(eventText, ruleText);
934
1107
  }
935
1108
  function eventToAllowlistKey(event) {
936
1109
  return `${(event.tool ?? "*").toLowerCase()}::${event.intent.toLowerCase().trim()}`;
@@ -998,10 +1171,18 @@ async function loadWorldFromDirectory(dirPath) {
998
1171
  const { join } = await import("path");
999
1172
  const { readdirSync } = await import("fs");
1000
1173
  async function readJson(filename) {
1174
+ const filePath = join(dirPath, filename);
1001
1175
  try {
1002
- const content = await readFile(join(dirPath, filename), "utf-8");
1176
+ const content = await readFile(filePath, "utf-8");
1003
1177
  return JSON.parse(content);
1004
- } catch {
1178
+ } catch (err) {
1179
+ if (err instanceof Error && "code" in err && err.code === "ENOENT") {
1180
+ return void 0;
1181
+ }
1182
+ process.stderr.write(
1183
+ `[neuroverse] Warning: Failed to read ${filename}: ${err instanceof Error ? err.message : String(err)}
1184
+ `
1185
+ );
1005
1186
  return void 0;
1006
1187
  }
1007
1188
  }
@@ -1023,10 +1204,23 @@ async function loadWorldFromDirectory(dirPath) {
1023
1204
  const rulesDir = join(dirPath, "rules");
1024
1205
  const ruleFiles = readdirSync(rulesDir).filter((f) => f.endsWith(".json")).sort();
1025
1206
  for (const file of ruleFiles) {
1026
- const content = await readFile(join(rulesDir, file), "utf-8");
1027
- rules.push(JSON.parse(content));
1207
+ try {
1208
+ const content = await readFile(join(rulesDir, file), "utf-8");
1209
+ rules.push(JSON.parse(content));
1210
+ } catch (err) {
1211
+ process.stderr.write(
1212
+ `[neuroverse] Warning: Failed to parse rule ${file}: ${err instanceof Error ? err.message : String(err)}
1213
+ `
1214
+ );
1215
+ }
1216
+ }
1217
+ } catch (err) {
1218
+ if (!(err instanceof Error && "code" in err && err.code === "ENOENT")) {
1219
+ process.stderr.write(
1220
+ `[neuroverse] Warning: Failed to read rules directory: ${err instanceof Error ? err.message : String(err)}
1221
+ `
1222
+ );
1028
1223
  }
1029
- } catch {
1030
1224
  }
1031
1225
  return {
1032
1226
  world: worldJson,
@@ -1061,20 +1255,14 @@ async function loadWorld(worldPath) {
1061
1255
  if (info.isDirectory()) {
1062
1256
  return loadWorldFromDirectory(worldPath);
1063
1257
  }
1064
- if (worldPath.endsWith(".nv-world.zip")) {
1065
- throw new Error(".nv-world.zip loading not yet implemented \u2014 use a world directory");
1066
- }
1067
- throw new Error(`Cannot load world from: ${worldPath} \u2014 expected a directory or .nv-world.zip`);
1258
+ throw new Error(`Cannot load world from: ${worldPath} \u2014 expected a directory`);
1068
1259
  }
1069
1260
 
1070
1261
  // src/adapters/langchain.ts
1071
- var GovernanceBlockedError = class extends Error {
1072
- verdict;
1262
+ var GovernanceBlockedError2 = class extends GovernanceBlockedError {
1073
1263
  event;
1074
1264
  constructor(verdict, event) {
1075
- super(`[NeuroVerse] BLOCKED: ${verdict.reason ?? verdict.ruleId ?? "governance rule"}`);
1076
- this.name = "GovernanceBlockedError";
1077
- this.verdict = verdict;
1265
+ super(verdict);
1078
1266
  this.event = event;
1079
1267
  }
1080
1268
  };
@@ -1082,7 +1270,7 @@ function defaultMapToolCall(toolName, toolInput) {
1082
1270
  return {
1083
1271
  intent: toolName,
1084
1272
  tool: toolName,
1085
- scope: typeof toolInput.path === "string" ? toolInput.path : typeof toolInput.url === "string" ? toolInput.url : void 0,
1273
+ scope: extractScope(toolInput),
1086
1274
  args: toolInput,
1087
1275
  direction: "input"
1088
1276
  };
@@ -1098,11 +1286,7 @@ var NeuroVerseCallbackHandler = class {
1098
1286
  this.world = world;
1099
1287
  this.options = options;
1100
1288
  this.activePlan = options.plan;
1101
- this.engineOptions = {
1102
- trace: options.trace ?? false,
1103
- level: options.level,
1104
- plan: this.activePlan
1105
- };
1289
+ this.engineOptions = buildEngineOptions(options, this.activePlan);
1106
1290
  this.mapToolCall = options.mapToolCall ?? defaultMapToolCall;
1107
1291
  }
1108
1292
  /**
@@ -1125,28 +1309,16 @@ var NeuroVerseCallbackHandler = class {
1125
1309
  this.options.onEvaluate?.(verdict, event);
1126
1310
  if (verdict.status === "BLOCK") {
1127
1311
  this.options.onBlock?.(verdict, event);
1128
- throw new GovernanceBlockedError(verdict, event);
1312
+ throw new GovernanceBlockedError2(verdict, event);
1129
1313
  }
1130
1314
  if (verdict.status === "PAUSE") {
1131
1315
  const approved = await this.options.onPause?.(verdict, event);
1132
1316
  if (!approved) {
1133
- throw new GovernanceBlockedError(verdict, event);
1317
+ throw new GovernanceBlockedError2(verdict, event);
1134
1318
  }
1135
1319
  }
1136
- if (verdict.status === "ALLOW" && this.activePlan) {
1137
- const planVerdict = evaluatePlan(event, this.activePlan);
1138
- if (planVerdict.matchedStep) {
1139
- const advResult = advancePlan(this.activePlan, planVerdict.matchedStep);
1140
- if (advResult.success && advResult.plan) {
1141
- this.activePlan = advResult.plan;
1142
- this.engineOptions.plan = this.activePlan;
1143
- }
1144
- const progress = getPlanProgress(this.activePlan);
1145
- this.options.onPlanProgress?.(progress);
1146
- if (progress.completed === progress.total) {
1147
- this.options.onPlanComplete?.();
1148
- }
1149
- }
1320
+ if (verdict.status === "ALLOW") {
1321
+ trackPlanProgress(event, this, this.options);
1150
1322
  }
1151
1323
  }
1152
1324
  };
@@ -1159,13 +1331,10 @@ function createNeuroVerseCallbackHandlerFromWorld(world, options) {
1159
1331
  }
1160
1332
 
1161
1333
  // src/adapters/openai.ts
1162
- var GovernanceBlockedError2 = class extends Error {
1163
- verdict;
1334
+ var GovernanceBlockedError3 = class extends GovernanceBlockedError {
1164
1335
  toolCallId;
1165
1336
  constructor(verdict, toolCallId) {
1166
- super(`[NeuroVerse] BLOCKED: ${verdict.reason ?? verdict.ruleId ?? "governance rule"}`);
1167
- this.name = "GovernanceBlockedError";
1168
- this.verdict = verdict;
1337
+ super(verdict);
1169
1338
  this.toolCallId = toolCallId;
1170
1339
  }
1171
1340
  };
@@ -1173,14 +1342,11 @@ function defaultMapFunctionCall(name, args) {
1173
1342
  return {
1174
1343
  intent: name,
1175
1344
  tool: name,
1176
- scope: typeof args.path === "string" ? args.path : typeof args.url === "string" ? args.url : void 0,
1345
+ scope: extractScope(args),
1177
1346
  args,
1178
1347
  direction: "input"
1179
1348
  };
1180
1349
  }
1181
- function defaultBlockMessage(verdict) {
1182
- return `Action blocked by governance policy: ${verdict.reason ?? "rule violation"}. Rule: ${verdict.ruleId ?? "unknown"}.`;
1183
- }
1184
1350
  var GovernedToolExecutor = class {
1185
1351
  world;
1186
1352
  options;
@@ -1192,11 +1358,7 @@ var GovernedToolExecutor = class {
1192
1358
  this.world = world;
1193
1359
  this.options = options;
1194
1360
  this.activePlan = options.plan;
1195
- this.engineOptions = {
1196
- trace: options.trace ?? false,
1197
- level: options.level,
1198
- plan: this.activePlan
1199
- };
1361
+ this.engineOptions = buildEngineOptions(options, this.activePlan);
1200
1362
  this.mapFn = options.mapFunctionCall ?? defaultMapFunctionCall;
1201
1363
  this.blockMsg = options.blockMessage ?? defaultBlockMessage;
1202
1364
  }
@@ -1215,20 +1377,8 @@ var GovernedToolExecutor = class {
1215
1377
  this.engineOptions.plan = this.activePlan;
1216
1378
  const verdict = evaluateGuard(event, this.world, this.engineOptions);
1217
1379
  this.options.onEvaluate?.(verdict, event);
1218
- if (verdict.status === "ALLOW" && this.activePlan) {
1219
- const planVerdict = evaluatePlan(event, this.activePlan);
1220
- if (planVerdict.matchedStep) {
1221
- const advResult = advancePlan(this.activePlan, planVerdict.matchedStep);
1222
- if (advResult.success && advResult.plan) {
1223
- this.activePlan = advResult.plan;
1224
- this.engineOptions.plan = this.activePlan;
1225
- }
1226
- const progress = getPlanProgress(this.activePlan);
1227
- this.options.onPlanProgress?.(progress);
1228
- if (progress.completed === progress.total) {
1229
- this.options.onPlanComplete?.();
1230
- }
1231
- }
1380
+ if (verdict.status === "ALLOW") {
1381
+ trackPlanProgress(event, this, this.options);
1232
1382
  }
1233
1383
  return verdict;
1234
1384
  }
@@ -1254,7 +1404,7 @@ var GovernedToolExecutor = class {
1254
1404
  };
1255
1405
  }
1256
1406
  if (verdict.status === "PAUSE") {
1257
- throw new GovernanceBlockedError2(verdict, toolCall.id);
1407
+ throw new GovernanceBlockedError3(verdict, toolCall.id);
1258
1408
  }
1259
1409
  let args;
1260
1410
  try {
@@ -1280,13 +1430,10 @@ function createGovernedToolExecutorFromWorld(world, options) {
1280
1430
  }
1281
1431
 
1282
1432
  // src/adapters/openclaw.ts
1283
- var GovernanceBlockedError3 = class extends Error {
1284
- verdict;
1433
+ var GovernanceBlockedError4 = class extends GovernanceBlockedError {
1285
1434
  action;
1286
1435
  constructor(verdict, action) {
1287
- super(`[NeuroVerse] BLOCKED: ${verdict.reason ?? verdict.ruleId ?? "governance rule"}`);
1288
- this.name = "GovernanceBlockedError";
1289
- this.verdict = verdict;
1436
+ super(verdict);
1290
1437
  this.action = action;
1291
1438
  }
1292
1439
  };
@@ -1296,7 +1443,7 @@ function defaultMapAction(action, direction) {
1296
1443
  tool: action.tool ?? action.type,
1297
1444
  args: action.input,
1298
1445
  direction,
1299
- scope: typeof action.input?.path === "string" ? action.input.path : typeof action.input?.url === "string" ? action.input.url : void 0
1446
+ scope: action.input ? extractScope(action.input) : void 0
1300
1447
  };
1301
1448
  }
1302
1449
  var NeuroVersePlugin = class {
@@ -1310,11 +1457,7 @@ var NeuroVersePlugin = class {
1310
1457
  this.world = world;
1311
1458
  this.options = options;
1312
1459
  this.activePlan = options.plan;
1313
- this.engineOptions = {
1314
- trace: options.trace ?? false,
1315
- level: options.level,
1316
- plan: this.activePlan
1317
- };
1460
+ this.engineOptions = buildEngineOptions(options, this.activePlan);
1318
1461
  this.mapAction = options.mapAction ?? defaultMapAction;
1319
1462
  }
1320
1463
  /**
@@ -1334,22 +1477,10 @@ var NeuroVersePlugin = class {
1334
1477
  };
1335
1478
  this.options.onEvaluate?.(result);
1336
1479
  if (verdict.status === "BLOCK") {
1337
- throw new GovernanceBlockedError3(verdict, action);
1480
+ throw new GovernanceBlockedError4(verdict, action);
1338
1481
  }
1339
- if (verdict.status === "ALLOW" && this.activePlan) {
1340
- const planVerdict = evaluatePlan(event, this.activePlan);
1341
- if (planVerdict.matchedStep) {
1342
- const advResult = advancePlan(this.activePlan, planVerdict.matchedStep);
1343
- if (advResult.success && advResult.plan) {
1344
- this.activePlan = advResult.plan;
1345
- this.engineOptions.plan = this.activePlan;
1346
- }
1347
- const progress = getPlanProgress(this.activePlan);
1348
- this.options.onPlanProgress?.(progress);
1349
- if (progress.completed === progress.total) {
1350
- this.options.onPlanComplete?.();
1351
- }
1352
- }
1482
+ if (verdict.status === "ALLOW") {
1483
+ trackPlanProgress(event, this, this.options);
1353
1484
  }
1354
1485
  return result;
1355
1486
  }
@@ -1370,7 +1501,7 @@ var NeuroVersePlugin = class {
1370
1501
  };
1371
1502
  this.options.onEvaluate?.(result);
1372
1503
  if (verdict.status === "BLOCK") {
1373
- throw new GovernanceBlockedError3(verdict, action);
1504
+ throw new GovernanceBlockedError4(verdict, action);
1374
1505
  }
1375
1506
  return result;
1376
1507
  }
@@ -1433,8 +1564,9 @@ function defaultOnBlock(verdict, _req, res, statusCode) {
1433
1564
  ruleId: verdict.ruleId,
1434
1565
  status: verdict.status
1435
1566
  };
1436
- if (res.status && res.json) {
1437
- res.status(statusCode).json(body);
1567
+ if (typeof res.status === "function" && typeof res.json === "function") {
1568
+ const r = res.status(statusCode);
1569
+ r.json(body);
1438
1570
  } else if (res.send) {
1439
1571
  res.statusCode = statusCode;
1440
1572
  res.send(JSON.stringify(body));
@@ -1485,8 +1617,12 @@ function createGovernanceMiddlewareFromWorld(world, options = {}) {
1485
1617
  var AutoresearchGovernor = class {
1486
1618
  config;
1487
1619
  state;
1620
+ world;
1621
+ engineOptions;
1488
1622
  constructor(config) {
1489
1623
  this.config = config;
1624
+ this.world = config.world;
1625
+ this.engineOptions = { trace: true };
1490
1626
  this.state = {
1491
1627
  experiments_run: 0,
1492
1628
  best_result: null,
@@ -1516,10 +1652,23 @@ var AutoresearchGovernor = class {
1516
1652
  }
1517
1653
  /**
1518
1654
  * Evaluate an experiment proposal against governance rules.
1519
- * Returns a simplified verdict without requiring the full guard engine.
1655
+ * Routes through the guard engine when a world is loaded,
1656
+ * then layers on research-specific checks (budget, constraints, drift).
1520
1657
  */
1521
1658
  evaluateProposal(proposal) {
1522
1659
  const warnings = [];
1660
+ const event = this.proposalToGuardEvent(proposal);
1661
+ if (this.world) {
1662
+ const verdict = evaluateGuard(event, this.world, this.engineOptions);
1663
+ if (verdict.status === "BLOCK" || verdict.status === "PAUSE") {
1664
+ return {
1665
+ allowed: false,
1666
+ reason: verdict.reason ?? `Governance ${verdict.status}: ${verdict.ruleId ?? "unknown rule"}`,
1667
+ warnings,
1668
+ verdict
1669
+ };
1670
+ }
1671
+ }
1523
1672
  const estimatedMinutes = proposal.estimated_minutes || 5;
1524
1673
  if (this.state.total_compute_minutes + estimatedMinutes > this.config.computeBudgetMinutes) {
1525
1674
  return {
@@ -1649,15 +1798,306 @@ var AutoresearchGovernor = class {
1649
1798
  return { ...this.state };
1650
1799
  }
1651
1800
  };
1801
+
1802
+ // src/engine/tool-classifier.ts
1803
+ var TOOL_CATEGORY_MAP = {
1804
+ // File operations
1805
+ read_file: "file_read",
1806
+ read: "file_read",
1807
+ glob: "file_read",
1808
+ grep: "file_read",
1809
+ list_files: "file_read",
1810
+ write_file: "file_write",
1811
+ write: "file_write",
1812
+ create_file: "file_write",
1813
+ edit_file: "file_write",
1814
+ edit: "file_write",
1815
+ patch: "file_write",
1816
+ delete_file: "file_delete",
1817
+ remove_file: "file_delete",
1818
+ // Shell
1819
+ shell: "shell",
1820
+ bash: "shell",
1821
+ execute: "shell",
1822
+ run_command: "shell",
1823
+ terminal: "shell",
1824
+ // Git
1825
+ git: "git",
1826
+ git_commit: "git",
1827
+ git_push: "git",
1828
+ git_checkout: "git",
1829
+ // Network
1830
+ http: "network",
1831
+ fetch: "network",
1832
+ curl: "network",
1833
+ web_search: "network",
1834
+ // Sub-agents
1835
+ sub_agent: "sub_agent",
1836
+ spawn_agent: "sub_agent",
1837
+ delegate: "sub_agent",
1838
+ // Context management
1839
+ summarize: "context",
1840
+ compress_context: "context"
1841
+ };
1842
+ function classifyTool(toolName) {
1843
+ const normalized = toolName.toLowerCase().replace(/[-\s]/g, "_");
1844
+ return TOOL_CATEGORY_MAP[normalized] ?? "unknown";
1845
+ }
1846
+ var DANGEROUS_SHELL_PATTERNS = [
1847
+ { pattern: /rm\s+(-[a-zA-Z]*f[a-zA-Z]*\s+|.*-rf\s+|.*--force)/, label: "force-delete" },
1848
+ { pattern: /rm\s+-[a-zA-Z]*r/, label: "recursive-delete" },
1849
+ { pattern: />\s*\/dev\/sd/, label: "disk-overwrite" },
1850
+ { pattern: /mkfs\./, label: "format-disk" },
1851
+ { pattern: /dd\s+if=/, label: "disk-dump" },
1852
+ { pattern: /chmod\s+(-R\s+)?777/, label: "world-writable" },
1853
+ { pattern: /curl\s+.*\|\s*(bash|sh|zsh)/, label: "pipe-to-shell" },
1854
+ { pattern: /wget\s+.*\|\s*(bash|sh|zsh)/, label: "pipe-to-shell" },
1855
+ { pattern: /:(){ :\|:& };:/, label: "fork-bomb" },
1856
+ { pattern: />\s*\/etc\//, label: "system-config-overwrite" },
1857
+ { pattern: /shutdown|reboot|halt|poweroff/, label: "system-shutdown" },
1858
+ { pattern: /kill\s+-9\s+1\b/, label: "kill-init" }
1859
+ ];
1860
+ var DANGEROUS_GIT_PATTERNS = [
1861
+ { pattern: /push\s+.*--force/, label: "force-push" },
1862
+ { pattern: /push\s+.*-f\b/, label: "force-push" },
1863
+ { pattern: /push\s+(origin\s+)?main\b/, label: "push-main" },
1864
+ { pattern: /push\s+(origin\s+)?master\b/, label: "push-master" },
1865
+ { pattern: /reset\s+--hard/, label: "hard-reset" },
1866
+ { pattern: /clean\s+-fd/, label: "clean-force" },
1867
+ { pattern: /branch\s+-D/, label: "force-delete-branch" }
1868
+ ];
1869
+ function isDangerousCommand(command) {
1870
+ const matched = DANGEROUS_SHELL_PATTERNS.filter((p) => p.pattern.test(command)).map((p) => p.label);
1871
+ return { dangerous: matched.length > 0, labels: matched };
1872
+ }
1873
+ function isDangerousGitCommand(command) {
1874
+ const matched = DANGEROUS_GIT_PATTERNS.filter((p) => p.pattern.test(command)).map((p) => p.label);
1875
+ return { dangerous: matched.length > 0, labels: matched };
1876
+ }
1877
+ function assessRiskLevel(category) {
1878
+ if (category === "file_read" || category === "context") return "low";
1879
+ if (category === "file_write" || category === "sub_agent") return "medium";
1880
+ if (category === "shell" || category === "file_delete" || category === "git" || category === "network") return "high";
1881
+ return void 0;
1882
+ }
1883
+ function categoryToActionCategory(category) {
1884
+ if (category === "file_read" || category === "context") return "read";
1885
+ if (category === "file_write") return "write";
1886
+ if (category === "file_delete") return "delete";
1887
+ if (category === "shell") return "shell";
1888
+ if (category === "network") return "network";
1889
+ return "other";
1890
+ }
1891
+
1892
+ // src/adapters/deep-agents.ts
1893
+ var GovernanceBlockedError5 = class extends GovernanceBlockedError {
1894
+ toolCall;
1895
+ category;
1896
+ constructor(verdict, toolCall, category) {
1897
+ super(verdict);
1898
+ this.toolCall = toolCall;
1899
+ this.category = category;
1900
+ }
1901
+ };
1902
+ function defaultMapToolCall2(toolCall) {
1903
+ const category = classifyTool(toolCall.tool);
1904
+ const args = toolCall.args;
1905
+ const scope = extractScope(args);
1906
+ let intent = toolCall.tool;
1907
+ if (category === "shell" && typeof args.command === "string") {
1908
+ intent = `shell: ${args.command}`;
1909
+ } else if (category === "git" && typeof args.command === "string") {
1910
+ intent = `git ${args.command}`;
1911
+ } else if (category === "file_write" && scope) {
1912
+ intent = `write ${scope}`;
1913
+ } else if (category === "file_delete" && scope) {
1914
+ intent = `delete ${scope}`;
1915
+ }
1916
+ const riskLevel = assessRiskLevel(category);
1917
+ let irreversible = false;
1918
+ if (category === "shell" && typeof args.command === "string") {
1919
+ irreversible = DANGEROUS_SHELL_PATTERNS.some((p) => p.pattern.test(args.command));
1920
+ } else if (category === "git" && typeof args.command === "string") {
1921
+ irreversible = DANGEROUS_GIT_PATTERNS.some((p) => p.pattern.test(args.command));
1922
+ } else if (category === "file_delete") {
1923
+ irreversible = true;
1924
+ }
1925
+ return {
1926
+ intent,
1927
+ tool: toolCall.tool,
1928
+ scope,
1929
+ args,
1930
+ direction: "input",
1931
+ actionCategory: categoryToActionCategory(category),
1932
+ riskLevel,
1933
+ irreversible
1934
+ };
1935
+ }
1936
+ var DeepAgentsGuard = class {
1937
+ name = "neuroverse-deep-agents-guard";
1938
+ world;
1939
+ options;
1940
+ engineOptions;
1941
+ mapToolCall;
1942
+ activePlan;
1943
+ constructor(world, options = {}) {
1944
+ this.world = world;
1945
+ this.options = options;
1946
+ this.activePlan = options.plan;
1947
+ this.engineOptions = buildEngineOptions(options, this.activePlan);
1948
+ this.mapToolCall = options.mapToolCall ?? defaultMapToolCall2;
1949
+ }
1950
+ /**
1951
+ * Evaluate a tool call against governance rules.
1952
+ * Returns the result without side effects.
1953
+ */
1954
+ evaluate(toolCall) {
1955
+ const event = this.mapToolCall(toolCall);
1956
+ this.engineOptions.plan = this.activePlan;
1957
+ const verdict = evaluateGuard(event, this.world, this.engineOptions);
1958
+ const category = classifyTool(toolCall.tool);
1959
+ const result = {
1960
+ allowed: verdict.status === "ALLOW",
1961
+ verdict,
1962
+ toolCall,
1963
+ category
1964
+ };
1965
+ this.options.onEvaluate?.(result);
1966
+ if (verdict.status === "ALLOW" && this.activePlan) {
1967
+ this.trackPlanProgressInternal(event);
1968
+ }
1969
+ return result;
1970
+ }
1971
+ /**
1972
+ * Evaluate and enforce governance on a tool call.
1973
+ *
1974
+ * @throws GovernanceBlockedError if BLOCKED
1975
+ * @throws GovernanceBlockedError if PAUSED and onPause returns false
1976
+ * @returns DeepAgentsGuardResult on ALLOW
1977
+ */
1978
+ async enforce(toolCall) {
1979
+ const result = this.evaluate(toolCall);
1980
+ if (result.verdict.status === "BLOCK") {
1981
+ this.options.onBlock?.(result);
1982
+ throw new GovernanceBlockedError5(result.verdict, toolCall, result.category);
1983
+ }
1984
+ if (result.verdict.status === "PAUSE") {
1985
+ const approved = await this.options.onPause?.(result);
1986
+ if (!approved) {
1987
+ throw new GovernanceBlockedError5(result.verdict, toolCall, result.category);
1988
+ }
1989
+ }
1990
+ return result;
1991
+ }
1992
+ /**
1993
+ * Evaluate and execute a tool call with governance enforcement.
1994
+ *
1995
+ * If ALLOW: runs the executor and returns its result.
1996
+ * If BLOCK: returns a governance-blocked message.
1997
+ * If PAUSE: calls onPause; blocks if not approved.
1998
+ *
1999
+ * @param toolCall - The Deep Agents tool call to evaluate
2000
+ * @param executor - The actual tool execution function
2001
+ * @returns The tool execution result or a blocked message
2002
+ */
2003
+ async execute(toolCall, executor) {
2004
+ const guardResult = this.evaluate(toolCall);
2005
+ if (guardResult.verdict.status === "BLOCK") {
2006
+ this.options.onBlock?.(guardResult);
2007
+ return {
2008
+ blocked: true,
2009
+ verdict: guardResult.verdict,
2010
+ reason: guardResult.verdict.reason ?? "Action blocked by governance policy."
2011
+ };
2012
+ }
2013
+ if (guardResult.verdict.status === "PAUSE") {
2014
+ const approved = await this.options.onPause?.(guardResult);
2015
+ if (!approved) {
2016
+ return {
2017
+ blocked: true,
2018
+ verdict: guardResult.verdict,
2019
+ reason: guardResult.verdict.reason ?? "Action requires approval."
2020
+ };
2021
+ }
2022
+ }
2023
+ const result = await executor(toolCall);
2024
+ return { result, verdict: guardResult.verdict };
2025
+ }
2026
+ /**
2027
+ * Returns a middleware function compatible with Deep Agents' tool pipeline.
2028
+ *
2029
+ * The middleware intercepts tool calls before execution:
2030
+ * agent.use(guard.middleware());
2031
+ */
2032
+ middleware() {
2033
+ return async (toolCall, next) => {
2034
+ await this.enforce(toolCall);
2035
+ return next();
2036
+ };
2037
+ }
2038
+ /**
2039
+ * Returns a callback-handler-style object for LangChain integration.
2040
+ * Compatible with Deep Agents' callback system.
2041
+ */
2042
+ callbacks() {
2043
+ return {
2044
+ handleToolStart: async (tool, input) => {
2045
+ let parsedInput;
2046
+ try {
2047
+ parsedInput = typeof input === "string" ? JSON.parse(input) : input;
2048
+ } catch {
2049
+ parsedInput = { raw: input };
2050
+ }
2051
+ await this.enforce({ tool: tool.name, args: parsedInput });
2052
+ }
2053
+ };
2054
+ }
2055
+ /**
2056
+ * Check if a shell command contains dangerous patterns.
2057
+ * Useful for pre-screening before full governance evaluation.
2058
+ */
2059
+ static isDangerousCommand(command) {
2060
+ return isDangerousCommand(command);
2061
+ }
2062
+ /**
2063
+ * Check if a git command contains dangerous patterns.
2064
+ */
2065
+ static isDangerousGitCommand(command) {
2066
+ return isDangerousGitCommand(command);
2067
+ }
2068
+ /**
2069
+ * Classify a tool name into a category.
2070
+ */
2071
+ static classifyTool(toolName) {
2072
+ return classifyTool(toolName);
2073
+ }
2074
+ // ─── Private ──────────────────────────────────────────────────────────────
2075
+ trackPlanProgressInternal(event) {
2076
+ trackPlanProgress(event, this, this.options);
2077
+ }
2078
+ };
2079
+ async function createDeepAgentsGuard(worldPath, options) {
2080
+ const world = await loadWorld(worldPath);
2081
+ return new DeepAgentsGuard(world, options);
2082
+ }
2083
+ function createDeepAgentsGuardFromWorld(world, options) {
2084
+ return new DeepAgentsGuard(world, options);
2085
+ }
1652
2086
  // Annotate the CommonJS export names for ESM import in node:
1653
2087
  0 && (module.exports = {
1654
2088
  AutoresearchGovernor,
2089
+ DeepAgentsGovernanceBlockedError,
2090
+ DeepAgentsGuard,
2091
+ GovernanceBlockedError,
1655
2092
  GovernedToolExecutor,
1656
2093
  LangChainGovernanceBlockedError,
1657
2094
  NeuroVerseCallbackHandler,
1658
2095
  NeuroVersePlugin,
1659
2096
  OpenAIGovernanceBlockedError,
1660
2097
  OpenClawGovernanceBlockedError,
2098
+ buildEngineOptions,
2099
+ createDeepAgentsGuard,
2100
+ createDeepAgentsGuardFromWorld,
1661
2101
  createGovernanceMiddleware,
1662
2102
  createGovernanceMiddlewareFromWorld,
1663
2103
  createGovernedToolExecutor,
@@ -1665,5 +2105,8 @@ var AutoresearchGovernor = class {
1665
2105
  createNeuroVerseCallbackHandler,
1666
2106
  createNeuroVerseCallbackHandlerFromWorld,
1667
2107
  createNeuroVersePlugin,
1668
- createNeuroVersePluginFromWorld
2108
+ createNeuroVersePluginFromWorld,
2109
+ defaultBlockMessage,
2110
+ extractScope,
2111
+ trackPlanProgress
1669
2112
  });