@neuroverseos/governance 0.1.6 → 0.2.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 (82) hide show
  1. package/README.md +279 -423
  2. package/dist/adapters/express.cjs +242 -2
  3. package/dist/adapters/express.d.cts +1 -1
  4. package/dist/adapters/express.d.ts +1 -1
  5. package/dist/adapters/express.js +5 -3
  6. package/dist/adapters/index.cjs +301 -5
  7. package/dist/adapters/index.d.cts +1 -1
  8. package/dist/adapters/index.d.ts +1 -1
  9. package/dist/adapters/index.js +8 -6
  10. package/dist/adapters/langchain.cjs +267 -3
  11. package/dist/adapters/langchain.d.cts +8 -1
  12. package/dist/adapters/langchain.d.ts +8 -1
  13. package/dist/adapters/langchain.js +5 -3
  14. package/dist/adapters/openai.cjs +267 -3
  15. package/dist/adapters/openai.d.cts +8 -1
  16. package/dist/adapters/openai.d.ts +8 -1
  17. package/dist/adapters/openai.js +5 -3
  18. package/dist/adapters/openclaw.cjs +267 -3
  19. package/dist/adapters/openclaw.d.cts +8 -1
  20. package/dist/adapters/openclaw.d.ts +8 -1
  21. package/dist/adapters/openclaw.js +5 -3
  22. package/dist/{bootstrap-H4HHKQ5G.js → bootstrap-GXVDZNF7.js} +2 -1
  23. package/dist/{build-73KAVHEY.js → build-P42YFKQV.js} +34 -3
  24. package/dist/{chunk-FYPYZFV5.js → chunk-2JQJ5U5X.js} +1 -1
  25. package/dist/chunk-37JG24WH.js +161 -0
  26. package/dist/chunk-5EDDNJU6.js +321 -0
  27. package/dist/{chunk-O5OMJMIE.js → chunk-7P3S7MAY.js} +502 -2
  28. package/dist/chunk-A5W4GNQO.js +130 -0
  29. package/dist/{chunk-ITJ3LCPG.js → chunk-ADV7Q2LJ.js} +1 -1
  30. package/dist/chunk-AKW5YVCE.js +96 -0
  31. package/dist/{chunk-EIUHJXBB.js → chunk-GR6DGCZ2.js} +1 -1
  32. package/dist/{chunk-EQXFOKH2.js → chunk-IVPKFJX3.js} +24 -3
  33. package/dist/{chunk-D7BGWV2J.js → chunk-NF5POFCI.js} +5 -3
  34. package/dist/chunk-OT6PXH54.js +61 -0
  35. package/dist/chunk-P74Y66ZV.js +205 -0
  36. package/dist/chunk-PAX2P6ZP.js +601 -0
  37. package/dist/{chunk-B4NF3OLW.js → chunk-PQBJBVSW.js} +56 -2
  38. package/dist/{chunk-T4X42QXC.js → chunk-Q6O7ZLO2.js} +0 -59
  39. package/dist/{chunk-FZQCRGUU.js → chunk-TINSRYXQ.js} +24 -3
  40. package/dist/{chunk-CROPZ75A.js → chunk-UPJNTSVM.js} +24 -3
  41. package/dist/chunk-YZFATT7X.js +9 -0
  42. package/dist/{chunk-Z2S2HIV5.js → chunk-ZL4AHY4X.js} +2 -2
  43. package/dist/cli/neuroverse.cjs +5287 -740
  44. package/dist/cli/neuroverse.js +69 -13
  45. package/dist/cli/plan.cjs +1554 -0
  46. package/dist/cli/plan.d.cts +20 -0
  47. package/dist/cli/plan.d.ts +20 -0
  48. package/dist/cli/plan.js +346 -0
  49. package/dist/cli/run.cjs +1716 -0
  50. package/dist/cli/run.d.cts +20 -0
  51. package/dist/cli/run.d.ts +20 -0
  52. package/dist/cli/run.js +143 -0
  53. package/dist/{configure-ai-46JVG56I.js → configure-ai-TK67ZWZL.js} +5 -2
  54. package/dist/{derive-6NAEWLM5.js → derive-TLIV4OOU.js} +6 -4
  55. package/dist/doctor-V72UM2TC.js +170 -0
  56. package/dist/{explain-3B3VB6TL.js → explain-IDCRWMPX.js} +2 -1
  57. package/dist/{guard-67Y66P3I.js → guard-WA3FCCIO.js} +20 -6
  58. package/dist/{guard-contract-D_RQz9kt.d.ts → guard-contract-D-2LQInm.d.cts} +144 -2
  59. package/dist/{guard-contract-D_RQz9kt.d.cts → guard-contract-D-2LQInm.d.ts} +144 -2
  60. package/dist/guard-engine-D7X4CVAE.js +10 -0
  61. package/dist/{impact-CHERK3O6.js → impact-BWULZ5RP.js} +5 -3
  62. package/dist/{improve-YG6I6ERG.js → improve-GPUBKTEA.js} +4 -3
  63. package/dist/index.cjs +2095 -89
  64. package/dist/index.d.cts +466 -12
  65. package/dist/index.d.ts +466 -12
  66. package/dist/index.js +70 -20
  67. package/dist/{init-Z66T6TDI.js → init-PKPIYHYE.js} +2 -0
  68. package/dist/mcp-server-YUOQP4M5.js +13 -0
  69. package/dist/model-adapter-BB7G4MFI.js +11 -0
  70. package/dist/playground-CBXMAW2B.js +550 -0
  71. package/dist/redteam-SSNABQ7W.js +357 -0
  72. package/dist/session-MWRBTCYX.js +14 -0
  73. package/dist/{simulate-ETHHINZ4.js → simulate-VDOYQFRO.js} +2 -1
  74. package/dist/test-3GZSG5FR.js +217 -0
  75. package/dist/{trace-3YODSSIP.js → trace-TM4Z7G73.js} +4 -2
  76. package/dist/{validate-UVE6GKQU.js → validate-LLBWVPGV.js} +15 -6
  77. package/dist/validate-engine-UIABSIHD.js +7 -0
  78. package/dist/{world-WLNHL5XC.js → world-LAXO6DOX.js} +87 -7
  79. package/dist/world-loader-HMPTOEA2.js +9 -0
  80. package/package.json +19 -5
  81. package/dist/validate-engine-657D75OG.js +0 -6
  82. /package/dist/{chunk-M3TZFGHO.js → chunk-JZPQGIKR.js} +0 -0
@@ -47,6 +47,205 @@ __export(adapters_exports, {
47
47
  });
48
48
  module.exports = __toCommonJS(adapters_exports);
49
49
 
50
+ // src/engine/plan-engine.ts
51
+ function keywordMatch(eventText, step) {
52
+ const stepText = [
53
+ step.label,
54
+ step.description ?? "",
55
+ ...step.tags ?? []
56
+ ].join(" ").toLowerCase();
57
+ const keywords = stepText.split(/\s+/).filter((w) => w.length > 3);
58
+ if (keywords.length === 0) return false;
59
+ const matched = keywords.filter((kw) => eventText.includes(kw));
60
+ return matched.length >= Math.ceil(keywords.length * 0.5);
61
+ }
62
+ function tokenSimilarity(a, b) {
63
+ const tokensA = new Set(a.toLowerCase().split(/\s+/).filter((w) => w.length > 2));
64
+ const tokensB = new Set(b.toLowerCase().split(/\s+/).filter((w) => w.length > 2));
65
+ if (tokensA.size === 0 || tokensB.size === 0) return 0;
66
+ let intersection = 0;
67
+ for (const t of tokensA) {
68
+ if (tokensB.has(t)) intersection++;
69
+ }
70
+ const union = (/* @__PURE__ */ new Set([...tokensA, ...tokensB])).size;
71
+ return union > 0 ? intersection / union : 0;
72
+ }
73
+ function findMatchingStep(eventText, event, steps) {
74
+ const pendingOrActive = steps.filter((s) => s.status === "pending" || s.status === "active");
75
+ if (pendingOrActive.length === 0) {
76
+ return { matched: null, closest: null, closestScore: 0 };
77
+ }
78
+ for (const step of pendingOrActive) {
79
+ if (keywordMatch(eventText, step)) {
80
+ if (step.tools && event.tool && !step.tools.includes(event.tool)) {
81
+ continue;
82
+ }
83
+ return { matched: step, closest: step, closestScore: 1 };
84
+ }
85
+ }
86
+ const intentText = [event.intent, event.tool ?? "", event.scope ?? ""].join(" ");
87
+ let bestStep = null;
88
+ let bestScore = 0;
89
+ for (const step of pendingOrActive) {
90
+ const stepText = [step.label, step.description ?? "", ...step.tags ?? []].join(" ");
91
+ const score = tokenSimilarity(intentText, stepText);
92
+ if (score > bestScore) {
93
+ bestScore = score;
94
+ bestStep = step;
95
+ }
96
+ }
97
+ const SIMILARITY_THRESHOLD = 0.35;
98
+ if (bestScore >= SIMILARITY_THRESHOLD && bestStep) {
99
+ if (bestStep.tools && event.tool && !bestStep.tools.includes(event.tool)) {
100
+ return { matched: null, closest: bestStep, closestScore: bestScore };
101
+ }
102
+ return { matched: bestStep, closest: bestStep, closestScore: bestScore };
103
+ }
104
+ return { matched: null, closest: bestStep, closestScore: bestScore };
105
+ }
106
+ function isSequenceValid(step, plan) {
107
+ if (!plan.sequential) return true;
108
+ if (!step.requires || step.requires.length === 0) return true;
109
+ return step.requires.every((reqId) => {
110
+ const reqStep = plan.steps.find((s) => s.id === reqId);
111
+ return reqStep?.status === "completed";
112
+ });
113
+ }
114
+ function checkConstraints(event, eventText, constraints) {
115
+ const checks = [];
116
+ for (const constraint of constraints) {
117
+ if (constraint.type === "approval") {
118
+ if (constraint.trigger && eventText.includes(constraint.trigger.substring(0, 10).toLowerCase())) {
119
+ checks.push({ constraintId: constraint.id, passed: false, reason: constraint.description });
120
+ return { violated: constraint, checks };
121
+ }
122
+ const keywords = constraint.description.toLowerCase().split(/\s+/).filter((w) => w.length > 3);
123
+ const relevant = keywords.some((kw) => eventText.includes(kw));
124
+ if (relevant) {
125
+ checks.push({ constraintId: constraint.id, passed: false, reason: constraint.description });
126
+ return { violated: constraint, checks };
127
+ }
128
+ checks.push({ constraintId: constraint.id, passed: true });
129
+ continue;
130
+ }
131
+ if (constraint.type === "scope" && constraint.trigger) {
132
+ const keywords = constraint.trigger.split(/\s+/).filter((w) => w.length > 3);
133
+ const violated = keywords.length > 0 && keywords.every((kw) => eventText.includes(kw));
134
+ checks.push({
135
+ constraintId: constraint.id,
136
+ passed: !violated,
137
+ reason: violated ? constraint.description : void 0
138
+ });
139
+ if (violated) {
140
+ return { violated: constraint, checks };
141
+ }
142
+ continue;
143
+ }
144
+ checks.push({ constraintId: constraint.id, passed: true });
145
+ }
146
+ return { violated: null, checks };
147
+ }
148
+ function getPlanProgress(plan) {
149
+ const completed = plan.steps.filter((s) => s.status === "completed").length;
150
+ const total = plan.steps.length;
151
+ return {
152
+ completed,
153
+ total,
154
+ percentage: total > 0 ? Math.round(completed / total * 100) : 0
155
+ };
156
+ }
157
+ function advancePlan(plan, stepId) {
158
+ return {
159
+ ...plan,
160
+ steps: plan.steps.map(
161
+ (s) => s.id === stepId ? { ...s, status: "completed" } : s
162
+ )
163
+ };
164
+ }
165
+ function evaluatePlan(event, plan) {
166
+ const progress = getPlanProgress(plan);
167
+ if (plan.expires_at) {
168
+ const expiresAt = new Date(plan.expires_at).getTime();
169
+ if (Date.now() > expiresAt) {
170
+ return {
171
+ allowed: true,
172
+ status: "PLAN_COMPLETE",
173
+ reason: "Plan has expired.",
174
+ progress
175
+ };
176
+ }
177
+ }
178
+ if (progress.completed === progress.total) {
179
+ return {
180
+ allowed: true,
181
+ status: "PLAN_COMPLETE",
182
+ reason: "All plan steps are completed.",
183
+ progress
184
+ };
185
+ }
186
+ const eventText = [
187
+ event.intent,
188
+ event.tool ?? "",
189
+ event.scope ?? ""
190
+ ].join(" ").toLowerCase();
191
+ const { matched, closest, closestScore } = findMatchingStep(eventText, event, plan.steps);
192
+ if (!matched) {
193
+ return {
194
+ allowed: false,
195
+ status: "OFF_PLAN",
196
+ reason: "Action does not match any plan step.",
197
+ closestStep: closest?.label,
198
+ similarityScore: closestScore,
199
+ progress
200
+ };
201
+ }
202
+ if (!isSequenceValid(matched, plan)) {
203
+ const pendingDeps = (matched.requires ?? []).filter((reqId) => plan.steps.find((s) => s.id === reqId)?.status !== "completed").join(", ");
204
+ return {
205
+ allowed: false,
206
+ status: "OFF_PLAN",
207
+ reason: `Step "${matched.label}" requires completion of: ${pendingDeps}`,
208
+ matchedStep: matched.id,
209
+ progress
210
+ };
211
+ }
212
+ const { violated } = checkConstraints(event, eventText, plan.constraints);
213
+ if (violated) {
214
+ return {
215
+ allowed: false,
216
+ status: "CONSTRAINT_VIOLATED",
217
+ reason: violated.description,
218
+ matchedStep: matched.id,
219
+ progress
220
+ };
221
+ }
222
+ return {
223
+ allowed: true,
224
+ status: "ON_PLAN",
225
+ reason: `Matches step: ${matched.label}`,
226
+ matchedStep: matched.id,
227
+ progress
228
+ };
229
+ }
230
+ function buildPlanCheck(event, plan, verdict) {
231
+ const eventText = [event.intent, event.tool ?? "", event.scope ?? ""].join(" ").toLowerCase();
232
+ const { matched, closest, closestScore } = findMatchingStep(eventText, event, plan.steps);
233
+ const { checks: constraintChecks } = checkConstraints(event, eventText, plan.constraints);
234
+ const progress = getPlanProgress(plan);
235
+ return {
236
+ planId: plan.plan_id,
237
+ matched: !!matched,
238
+ matchedStepId: matched?.id,
239
+ matchedStepLabel: matched?.label,
240
+ closestStepId: !matched ? closest?.id : void 0,
241
+ closestStepLabel: !matched ? closest?.label : void 0,
242
+ similarityScore: !matched ? closestScore : void 0,
243
+ sequenceValid: matched ? isSequenceValid(matched, plan) : void 0,
244
+ constraintsChecked: constraintChecks,
245
+ progress: { completed: progress.completed, total: progress.total }
246
+ };
247
+ }
248
+
50
249
  // src/engine/guard-engine.ts
51
250
  var PROMPT_INJECTION_PATTERNS = [
52
251
  // Instruction override
@@ -138,6 +337,7 @@ function evaluateGuard(event, world, options = {}) {
138
337
  const eventText = (event.intent + " " + (event.tool ?? "") + " " + (event.scope ?? "")).toLowerCase();
139
338
  const invariantChecks = [];
140
339
  const safetyChecks = [];
340
+ let planCheckResult;
141
341
  const roleChecks = [];
142
342
  const guardChecks = [];
143
343
  const kernelRuleChecks = [];
@@ -165,6 +365,7 @@ function evaluateGuard(event, world, options = {}) {
165
365
  includeTrace ? buildTrace(
166
366
  invariantChecks,
167
367
  safetyChecks,
368
+ planCheckResult,
168
369
  roleChecks,
169
370
  guardChecks,
170
371
  kernelRuleChecks,
@@ -193,6 +394,7 @@ function evaluateGuard(event, world, options = {}) {
193
394
  includeTrace ? buildTrace(
194
395
  invariantChecks,
195
396
  safetyChecks,
397
+ planCheckResult,
196
398
  roleChecks,
197
399
  guardChecks,
198
400
  kernelRuleChecks,
@@ -203,6 +405,42 @@ function evaluateGuard(event, world, options = {}) {
203
405
  ) : void 0
204
406
  );
205
407
  }
408
+ if (options.plan) {
409
+ const planVerdict = evaluatePlan(event, options.plan);
410
+ planCheckResult = buildPlanCheck(event, options.plan, planVerdict);
411
+ if (!planVerdict.allowed && planVerdict.status !== "PLAN_COMPLETE") {
412
+ decidingLayer = "plan-enforcement";
413
+ decidingId = `plan-${options.plan.plan_id}`;
414
+ const planStatus = planVerdict.status === "CONSTRAINT_VIOLATED" ? "PAUSE" : "BLOCK";
415
+ let reason = planVerdict.reason ?? "Action blocked by plan.";
416
+ if (planVerdict.status === "OFF_PLAN" && planVerdict.closestStep) {
417
+ reason += ` Closest step: "${planVerdict.closestStep}" (similarity: ${(planVerdict.similarityScore ?? 0).toFixed(2)})`;
418
+ }
419
+ return buildVerdict(
420
+ planStatus,
421
+ reason,
422
+ `plan-${options.plan.plan_id}`,
423
+ void 0,
424
+ world,
425
+ level,
426
+ invariantChecks,
427
+ guardsMatched,
428
+ rulesMatched,
429
+ includeTrace ? buildTrace(
430
+ invariantChecks,
431
+ safetyChecks,
432
+ planCheckResult,
433
+ roleChecks,
434
+ guardChecks,
435
+ kernelRuleChecks,
436
+ levelChecks,
437
+ decidingLayer,
438
+ decidingId,
439
+ startTime
440
+ ) : void 0
441
+ );
442
+ }
443
+ }
206
444
  const roleVerdict = checkRoleRules(event, eventText, world, roleChecks);
207
445
  if (roleVerdict) {
208
446
  decidingLayer = "role";
@@ -220,6 +458,7 @@ function evaluateGuard(event, world, options = {}) {
220
458
  includeTrace ? buildTrace(
221
459
  invariantChecks,
222
460
  safetyChecks,
461
+ planCheckResult,
223
462
  roleChecks,
224
463
  guardChecks,
225
464
  kernelRuleChecks,
@@ -248,6 +487,7 @@ function evaluateGuard(event, world, options = {}) {
248
487
  includeTrace ? buildTrace(
249
488
  invariantChecks,
250
489
  safetyChecks,
490
+ planCheckResult,
251
491
  roleChecks,
252
492
  guardChecks,
253
493
  kernelRuleChecks,
@@ -276,6 +516,7 @@ function evaluateGuard(event, world, options = {}) {
276
516
  includeTrace ? buildTrace(
277
517
  invariantChecks,
278
518
  safetyChecks,
519
+ planCheckResult,
279
520
  roleChecks,
280
521
  guardChecks,
281
522
  kernelRuleChecks,
@@ -303,6 +544,7 @@ function evaluateGuard(event, world, options = {}) {
303
544
  includeTrace ? buildTrace(
304
545
  invariantChecks,
305
546
  safetyChecks,
547
+ planCheckResult,
306
548
  roleChecks,
307
549
  guardChecks,
308
550
  kernelRuleChecks,
@@ -327,6 +569,7 @@ function evaluateGuard(event, world, options = {}) {
327
569
  includeTrace ? buildTrace(
328
570
  invariantChecks,
329
571
  safetyChecks,
572
+ planCheckResult,
330
573
  roleChecks,
331
574
  guardChecks,
332
575
  kernelRuleChecks,
@@ -664,8 +907,8 @@ function matchesKeywords(eventText, ruleText) {
664
907
  function eventToAllowlistKey(event) {
665
908
  return `${(event.tool ?? "*").toLowerCase()}::${event.intent.toLowerCase().trim()}`;
666
909
  }
667
- function buildTrace(invariantChecks, safetyChecks, roleChecks, guardChecks, kernelRuleChecks, levelChecks, decidingLayer, decidingId, startTime) {
668
- return {
910
+ function buildTrace(invariantChecks, safetyChecks, planCheck, roleChecks, guardChecks, kernelRuleChecks, levelChecks, decidingLayer, decidingId, startTime) {
911
+ const trace = {
669
912
  invariantChecks,
670
913
  safetyChecks,
671
914
  roleChecks,
@@ -683,6 +926,7 @@ function buildTrace(invariantChecks, safetyChecks, roleChecks, guardChecks, kern
683
926
  "safety-scope-escape",
684
927
  "safety-execution-claim",
685
928
  "safety-execution-intent",
929
+ "plan-enforcement",
686
930
  "role-rules",
687
931
  "declarative-guards",
688
932
  "kernel-rules",
@@ -692,6 +936,10 @@ function buildTrace(invariantChecks, safetyChecks, roleChecks, guardChecks, kern
692
936
  },
693
937
  durationMs: performance.now() - startTime
694
938
  };
939
+ if (planCheck) {
940
+ trace.planCheck = planCheck;
941
+ }
942
+ return trace;
695
943
  }
696
944
  function buildVerdict(status, reason, ruleId, warning, world, level, invariantChecks, guardsMatched, rulesMatched, trace) {
697
945
  const evidence = {
@@ -817,12 +1065,15 @@ var NeuroVerseCallbackHandler = class {
817
1065
  options;
818
1066
  engineOptions;
819
1067
  mapToolCall;
1068
+ activePlan;
820
1069
  constructor(world, options = {}) {
821
1070
  this.world = world;
822
1071
  this.options = options;
1072
+ this.activePlan = options.plan;
823
1073
  this.engineOptions = {
824
1074
  trace: options.trace ?? false,
825
- level: options.level
1075
+ level: options.level,
1076
+ plan: this.activePlan
826
1077
  };
827
1078
  this.mapToolCall = options.mapToolCall ?? defaultMapToolCall;
828
1079
  }
@@ -841,6 +1092,7 @@ var NeuroVerseCallbackHandler = class {
841
1092
  parsedInput = { raw: input };
842
1093
  }
843
1094
  const event = this.mapToolCall(tool.name, parsedInput);
1095
+ this.engineOptions.plan = this.activePlan;
844
1096
  const verdict = evaluateGuard(event, this.world, this.engineOptions);
845
1097
  this.options.onEvaluate?.(verdict, event);
846
1098
  if (verdict.status === "BLOCK") {
@@ -853,6 +1105,18 @@ var NeuroVerseCallbackHandler = class {
853
1105
  throw new GovernanceBlockedError(verdict, event);
854
1106
  }
855
1107
  }
1108
+ if (verdict.status === "ALLOW" && this.activePlan) {
1109
+ const planVerdict = evaluatePlan(event, this.activePlan);
1110
+ if (planVerdict.matchedStep) {
1111
+ this.activePlan = advancePlan(this.activePlan, planVerdict.matchedStep);
1112
+ this.engineOptions.plan = this.activePlan;
1113
+ const progress = getPlanProgress(this.activePlan);
1114
+ this.options.onPlanProgress?.(progress);
1115
+ if (progress.completed === progress.total) {
1116
+ this.options.onPlanComplete?.();
1117
+ }
1118
+ }
1119
+ }
856
1120
  }
857
1121
  };
858
1122
  async function createNeuroVerseCallbackHandler(worldPath, options) {
@@ -892,12 +1156,15 @@ var GovernedToolExecutor = class {
892
1156
  engineOptions;
893
1157
  mapFn;
894
1158
  blockMsg;
1159
+ activePlan;
895
1160
  constructor(world, options = {}) {
896
1161
  this.world = world;
897
1162
  this.options = options;
1163
+ this.activePlan = options.plan;
898
1164
  this.engineOptions = {
899
1165
  trace: options.trace ?? false,
900
- level: options.level
1166
+ level: options.level,
1167
+ plan: this.activePlan
901
1168
  };
902
1169
  this.mapFn = options.mapFunctionCall ?? defaultMapFunctionCall;
903
1170
  this.blockMsg = options.blockMessage ?? defaultBlockMessage;
@@ -914,8 +1181,21 @@ var GovernedToolExecutor = class {
914
1181
  args = { raw: toolCall.function.arguments };
915
1182
  }
916
1183
  const event = this.mapFn(toolCall.function.name, args);
1184
+ this.engineOptions.plan = this.activePlan;
917
1185
  const verdict = evaluateGuard(event, this.world, this.engineOptions);
918
1186
  this.options.onEvaluate?.(verdict, event);
1187
+ if (verdict.status === "ALLOW" && this.activePlan) {
1188
+ const planVerdict = evaluatePlan(event, this.activePlan);
1189
+ if (planVerdict.matchedStep) {
1190
+ this.activePlan = advancePlan(this.activePlan, planVerdict.matchedStep);
1191
+ this.engineOptions.plan = this.activePlan;
1192
+ const progress = getPlanProgress(this.activePlan);
1193
+ this.options.onPlanProgress?.(progress);
1194
+ if (progress.completed === progress.total) {
1195
+ this.options.onPlanComplete?.();
1196
+ }
1197
+ }
1198
+ }
919
1199
  return verdict;
920
1200
  }
921
1201
  /**
@@ -991,12 +1271,15 @@ var NeuroVersePlugin = class {
991
1271
  options;
992
1272
  engineOptions;
993
1273
  mapAction;
1274
+ activePlan;
994
1275
  constructor(world, options = {}) {
995
1276
  this.world = world;
996
1277
  this.options = options;
1278
+ this.activePlan = options.plan;
997
1279
  this.engineOptions = {
998
1280
  trace: options.trace ?? false,
999
- level: options.level
1281
+ level: options.level,
1282
+ plan: this.activePlan
1000
1283
  };
1001
1284
  this.mapAction = options.mapAction ?? defaultMapAction;
1002
1285
  }
@@ -1008,6 +1291,7 @@ var NeuroVersePlugin = class {
1008
1291
  */
1009
1292
  beforeAction(action) {
1010
1293
  const event = this.mapAction(action, "input");
1294
+ this.engineOptions.plan = this.activePlan;
1011
1295
  const verdict = evaluateGuard(event, this.world, this.engineOptions);
1012
1296
  const result = {
1013
1297
  allowed: verdict.status === "ALLOW",
@@ -1018,6 +1302,18 @@ var NeuroVersePlugin = class {
1018
1302
  if (verdict.status === "BLOCK") {
1019
1303
  throw new GovernanceBlockedError3(verdict, action);
1020
1304
  }
1305
+ if (verdict.status === "ALLOW" && this.activePlan) {
1306
+ const planVerdict = evaluatePlan(event, this.activePlan);
1307
+ if (planVerdict.matchedStep) {
1308
+ this.activePlan = advancePlan(this.activePlan, planVerdict.matchedStep);
1309
+ this.engineOptions.plan = this.activePlan;
1310
+ const progress = getPlanProgress(this.activePlan);
1311
+ this.options.onPlanProgress?.(progress);
1312
+ if (progress.completed === progress.total) {
1313
+ this.options.onPlanComplete?.();
1314
+ }
1315
+ }
1316
+ }
1021
1317
  return result;
1022
1318
  }
1023
1319
  /**
@@ -2,4 +2,4 @@ export { GovernanceBlockedError as LangChainGovernanceBlockedError, NeuroVerseCa
2
2
  export { GovernedExecutorOptions, GovernedToolExecutor, GovernedToolResult, GovernanceBlockedError as OpenAIGovernanceBlockedError, OpenAIToolCall, createGovernedToolExecutor, createGovernedToolExecutorFromWorld } from './openai.cjs';
3
3
  export { AgentAction, HookResult, NeuroVersePlugin, NeuroVersePluginOptions, GovernanceBlockedError as OpenClawGovernanceBlockedError, createNeuroVersePlugin, createNeuroVersePluginFromWorld } from './openclaw.cjs';
4
4
  export { GovernanceMiddlewareOptions, GovernanceRequest, GovernanceResponse, createGovernanceMiddleware, createGovernanceMiddlewareFromWorld } from './express.cjs';
5
- import '../guard-contract-D_RQz9kt.cjs';
5
+ import '../guard-contract-D-2LQInm.cjs';
@@ -2,4 +2,4 @@ export { GovernanceBlockedError as LangChainGovernanceBlockedError, NeuroVerseCa
2
2
  export { GovernedExecutorOptions, GovernedToolExecutor, GovernedToolResult, GovernanceBlockedError as OpenAIGovernanceBlockedError, OpenAIToolCall, createGovernedToolExecutor, createGovernedToolExecutorFromWorld } from './openai.js';
3
3
  export { AgentAction, HookResult, NeuroVersePlugin, NeuroVersePluginOptions, GovernanceBlockedError as OpenClawGovernanceBlockedError, createNeuroVersePlugin, createNeuroVersePluginFromWorld } from './openclaw.js';
4
4
  export { GovernanceMiddlewareOptions, GovernanceRequest, GovernanceResponse, createGovernanceMiddleware, createGovernanceMiddlewareFromWorld } from './express.js';
5
- import '../guard-contract-D_RQz9kt.js';
5
+ import '../guard-contract-D-2LQInm.js';
@@ -1,27 +1,29 @@
1
1
  import {
2
2
  createGovernanceMiddleware,
3
3
  createGovernanceMiddlewareFromWorld
4
- } from "../chunk-Z2S2HIV5.js";
4
+ } from "../chunk-ZL4AHY4X.js";
5
5
  import {
6
6
  GovernanceBlockedError,
7
7
  NeuroVerseCallbackHandler,
8
8
  createNeuroVerseCallbackHandler,
9
9
  createNeuroVerseCallbackHandlerFromWorld
10
- } from "../chunk-EQXFOKH2.js";
10
+ } from "../chunk-IVPKFJX3.js";
11
11
  import {
12
12
  GovernanceBlockedError as GovernanceBlockedError2,
13
13
  GovernedToolExecutor,
14
14
  createGovernedToolExecutor,
15
15
  createGovernedToolExecutorFromWorld
16
- } from "../chunk-FZQCRGUU.js";
16
+ } from "../chunk-TINSRYXQ.js";
17
17
  import {
18
18
  GovernanceBlockedError as GovernanceBlockedError3,
19
19
  NeuroVersePlugin,
20
20
  createNeuroVersePlugin,
21
21
  createNeuroVersePluginFromWorld
22
- } from "../chunk-CROPZ75A.js";
23
- import "../chunk-B4NF3OLW.js";
24
- import "../chunk-M3TZFGHO.js";
22
+ } from "../chunk-UPJNTSVM.js";
23
+ import "../chunk-PQBJBVSW.js";
24
+ import "../chunk-JZPQGIKR.js";
25
+ import "../chunk-P74Y66ZV.js";
26
+ import "../chunk-YZFATT7X.js";
25
27
  export {
26
28
  GovernedToolExecutor,
27
29
  GovernanceBlockedError as LangChainGovernanceBlockedError,