@neuroverseos/governance 0.1.6 → 0.2.2
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.
- package/README.md +279 -423
- package/dist/adapters/express.cjs +242 -2
- package/dist/adapters/express.d.cts +1 -1
- package/dist/adapters/express.d.ts +1 -1
- package/dist/adapters/express.js +5 -3
- package/dist/adapters/index.cjs +337 -5
- package/dist/adapters/index.d.cts +1 -1
- package/dist/adapters/index.d.ts +1 -1
- package/dist/adapters/index.js +8 -6
- package/dist/adapters/langchain.cjs +297 -3
- package/dist/adapters/langchain.d.cts +8 -1
- package/dist/adapters/langchain.d.ts +8 -1
- package/dist/adapters/langchain.js +5 -3
- package/dist/adapters/openai.cjs +297 -3
- package/dist/adapters/openai.d.cts +8 -1
- package/dist/adapters/openai.d.ts +8 -1
- package/dist/adapters/openai.js +5 -3
- package/dist/adapters/openclaw.cjs +297 -3
- package/dist/adapters/openclaw.d.cts +8 -1
- package/dist/adapters/openclaw.d.ts +8 -1
- package/dist/adapters/openclaw.js +5 -3
- package/dist/{bootstrap-H4HHKQ5G.js → bootstrap-GXVDZNF7.js} +2 -1
- package/dist/{build-73KAVHEY.js → build-P42YFKQV.js} +34 -3
- package/dist/{chunk-Z2S2HIV5.js → chunk-2NICNKOM.js} +2 -2
- package/dist/{chunk-B4NF3OLW.js → chunk-4JRYGIO7.js} +56 -2
- package/dist/chunk-4QXB6PEO.js +232 -0
- package/dist/chunk-6CZSKEY5.js +164 -0
- package/dist/{chunk-O5OMJMIE.js → chunk-7P3S7MAY.js} +502 -2
- package/dist/chunk-A5W4GNQO.js +130 -0
- package/dist/chunk-AKW5YVCE.js +96 -0
- package/dist/chunk-DPVS43ZT.js +608 -0
- package/dist/{chunk-EIUHJXBB.js → chunk-GR6DGCZ2.js} +1 -1
- package/dist/chunk-KEST3MWO.js +324 -0
- package/dist/{chunk-D7BGWV2J.js → chunk-NF5POFCI.js} +5 -3
- package/dist/{chunk-FZQCRGUU.js → chunk-OHAC6HJE.js} +27 -3
- package/dist/chunk-OT6PXH54.js +61 -0
- package/dist/{chunk-ITJ3LCPG.js → chunk-PDOZHZWL.js} +1 -1
- package/dist/{chunk-T4X42QXC.js → chunk-Q6O7ZLO2.js} +0 -59
- package/dist/{chunk-FYPYZFV5.js → chunk-QPASI2BR.js} +1 -1
- package/dist/{chunk-EQXFOKH2.js → chunk-RWXVAH6P.js} +27 -3
- package/dist/{chunk-CROPZ75A.js → chunk-SKU3GAPD.js} +27 -3
- package/dist/chunk-YZFATT7X.js +9 -0
- package/dist/cli/neuroverse.cjs +5343 -732
- package/dist/cli/neuroverse.js +69 -13
- package/dist/cli/plan.cjs +1599 -0
- package/dist/cli/plan.d.cts +20 -0
- package/dist/cli/plan.d.ts +20 -0
- package/dist/cli/plan.js +361 -0
- package/dist/cli/run.cjs +1746 -0
- package/dist/cli/run.d.cts +20 -0
- package/dist/cli/run.d.ts +20 -0
- package/dist/cli/run.js +143 -0
- package/dist/{configure-ai-46JVG56I.js → configure-ai-TK67ZWZL.js} +5 -2
- package/dist/{derive-6NAEWLM5.js → derive-TLIV4OOU.js} +6 -4
- package/dist/doctor-QV6HELS5.js +170 -0
- package/dist/{explain-3B3VB6TL.js → explain-IDCRWMPX.js} +2 -1
- package/dist/{guard-67Y66P3I.js → guard-GFLQZY6U.js} +20 -6
- package/dist/{guard-contract-D_RQz9kt.d.ts → guard-contract-Cm91Kp4j.d.cts} +182 -2
- package/dist/{guard-contract-D_RQz9kt.d.cts → guard-contract-Cm91Kp4j.d.ts} +182 -2
- package/dist/guard-engine-JLTUARGU.js +10 -0
- package/dist/{impact-CHERK3O6.js → impact-XPECYRLH.js} +5 -3
- package/dist/{improve-YG6I6ERG.js → improve-GPUBKTEA.js} +4 -3
- package/dist/index.cjs +2135 -89
- package/dist/index.d.cts +481 -12
- package/dist/index.d.ts +481 -12
- package/dist/index.js +70 -20
- package/dist/{init-Z66T6TDI.js → init-PKPIYHYE.js} +2 -0
- package/dist/mcp-server-LZVJHBT5.js +13 -0
- package/dist/model-adapter-BB7G4MFI.js +11 -0
- package/dist/playground-FGOMASHN.js +550 -0
- package/dist/redteam-SK7AMIG3.js +357 -0
- package/dist/session-VISISNWJ.js +14 -0
- package/dist/{simulate-ETHHINZ4.js → simulate-VDOYQFRO.js} +2 -1
- package/dist/test-75AVHC3R.js +217 -0
- package/dist/{trace-3YODSSIP.js → trace-JVF67VR3.js} +4 -2
- package/dist/{validate-UVE6GKQU.js → validate-LLBWVPGV.js} +15 -6
- package/dist/validate-engine-UIABSIHD.js +7 -0
- package/dist/{world-WLNHL5XC.js → world-LAXO6DOX.js} +87 -7
- package/dist/world-loader-HMPTOEA2.js +9 -0
- package/package.json +19 -5
- package/dist/validate-engine-657D75OG.js +0 -6
- /package/dist/{chunk-M3TZFGHO.js → chunk-JZPQGIKR.js} +0 -0
|
@@ -37,6 +37,232 @@ __export(openclaw_exports, {
|
|
|
37
37
|
});
|
|
38
38
|
module.exports = __toCommonJS(openclaw_exports);
|
|
39
39
|
|
|
40
|
+
// src/engine/plan-engine.ts
|
|
41
|
+
function keywordMatch(eventText, step) {
|
|
42
|
+
const stepText = [
|
|
43
|
+
step.label,
|
|
44
|
+
step.description ?? "",
|
|
45
|
+
...step.tags ?? []
|
|
46
|
+
].join(" ").toLowerCase();
|
|
47
|
+
const keywords = stepText.split(/\s+/).filter((w) => w.length > 3);
|
|
48
|
+
if (keywords.length === 0) return false;
|
|
49
|
+
const matched = keywords.filter((kw) => eventText.includes(kw));
|
|
50
|
+
return matched.length >= Math.ceil(keywords.length * 0.5);
|
|
51
|
+
}
|
|
52
|
+
function tokenSimilarity(a, b) {
|
|
53
|
+
const tokensA = new Set(a.toLowerCase().split(/\s+/).filter((w) => w.length > 2));
|
|
54
|
+
const tokensB = new Set(b.toLowerCase().split(/\s+/).filter((w) => w.length > 2));
|
|
55
|
+
if (tokensA.size === 0 || tokensB.size === 0) return 0;
|
|
56
|
+
let intersection = 0;
|
|
57
|
+
for (const t of tokensA) {
|
|
58
|
+
if (tokensB.has(t)) intersection++;
|
|
59
|
+
}
|
|
60
|
+
const union = (/* @__PURE__ */ new Set([...tokensA, ...tokensB])).size;
|
|
61
|
+
return union > 0 ? intersection / union : 0;
|
|
62
|
+
}
|
|
63
|
+
function findMatchingStep(eventText, event, steps) {
|
|
64
|
+
const pendingOrActive = steps.filter((s) => s.status === "pending" || s.status === "active");
|
|
65
|
+
if (pendingOrActive.length === 0) {
|
|
66
|
+
return { matched: null, closest: null, closestScore: 0 };
|
|
67
|
+
}
|
|
68
|
+
for (const step of pendingOrActive) {
|
|
69
|
+
if (keywordMatch(eventText, step)) {
|
|
70
|
+
if (step.tools && event.tool && !step.tools.includes(event.tool)) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
return { matched: step, closest: step, closestScore: 1 };
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const intentText = [event.intent, event.tool ?? "", event.scope ?? ""].join(" ");
|
|
77
|
+
let bestStep = null;
|
|
78
|
+
let bestScore = 0;
|
|
79
|
+
for (const step of pendingOrActive) {
|
|
80
|
+
const stepText = [step.label, step.description ?? "", ...step.tags ?? []].join(" ");
|
|
81
|
+
const score = tokenSimilarity(intentText, stepText);
|
|
82
|
+
if (score > bestScore) {
|
|
83
|
+
bestScore = score;
|
|
84
|
+
bestStep = step;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const SIMILARITY_THRESHOLD = 0.35;
|
|
88
|
+
if (bestScore >= SIMILARITY_THRESHOLD && bestStep) {
|
|
89
|
+
if (bestStep.tools && event.tool && !bestStep.tools.includes(event.tool)) {
|
|
90
|
+
return { matched: null, closest: bestStep, closestScore: bestScore };
|
|
91
|
+
}
|
|
92
|
+
return { matched: bestStep, closest: bestStep, closestScore: bestScore };
|
|
93
|
+
}
|
|
94
|
+
return { matched: null, closest: bestStep, closestScore: bestScore };
|
|
95
|
+
}
|
|
96
|
+
function isSequenceValid(step, plan) {
|
|
97
|
+
if (!plan.sequential) return true;
|
|
98
|
+
if (!step.requires || step.requires.length === 0) return true;
|
|
99
|
+
return step.requires.every((reqId) => {
|
|
100
|
+
const reqStep = plan.steps.find((s) => s.id === reqId);
|
|
101
|
+
return reqStep?.status === "completed";
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
function checkConstraints(event, eventText, constraints) {
|
|
105
|
+
const checks = [];
|
|
106
|
+
for (const constraint of constraints) {
|
|
107
|
+
if (constraint.type === "approval") {
|
|
108
|
+
if (constraint.trigger && eventText.includes(constraint.trigger.substring(0, 10).toLowerCase())) {
|
|
109
|
+
checks.push({ constraintId: constraint.id, passed: false, reason: constraint.description });
|
|
110
|
+
return { violated: constraint, checks };
|
|
111
|
+
}
|
|
112
|
+
const keywords = constraint.description.toLowerCase().split(/\s+/).filter((w) => w.length > 3);
|
|
113
|
+
const relevant = keywords.some((kw) => eventText.includes(kw));
|
|
114
|
+
if (relevant) {
|
|
115
|
+
checks.push({ constraintId: constraint.id, passed: false, reason: constraint.description });
|
|
116
|
+
return { violated: constraint, checks };
|
|
117
|
+
}
|
|
118
|
+
checks.push({ constraintId: constraint.id, passed: true });
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if (constraint.type === "scope" && constraint.trigger) {
|
|
122
|
+
const keywords = constraint.trigger.split(/\s+/).filter((w) => w.length > 3);
|
|
123
|
+
const violated = keywords.length > 0 && keywords.every((kw) => eventText.includes(kw));
|
|
124
|
+
checks.push({
|
|
125
|
+
constraintId: constraint.id,
|
|
126
|
+
passed: !violated,
|
|
127
|
+
reason: violated ? constraint.description : void 0
|
|
128
|
+
});
|
|
129
|
+
if (violated) {
|
|
130
|
+
return { violated: constraint, checks };
|
|
131
|
+
}
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
checks.push({ constraintId: constraint.id, passed: true });
|
|
135
|
+
}
|
|
136
|
+
return { violated: null, checks };
|
|
137
|
+
}
|
|
138
|
+
function getPlanProgress(plan) {
|
|
139
|
+
const completed = plan.steps.filter((s) => s.status === "completed").length;
|
|
140
|
+
const total = plan.steps.length;
|
|
141
|
+
return {
|
|
142
|
+
completed,
|
|
143
|
+
total,
|
|
144
|
+
percentage: total > 0 ? Math.round(completed / total * 100) : 0
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
function advancePlan(plan, stepId, evidence) {
|
|
148
|
+
const step = plan.steps.find((s) => s.id === stepId);
|
|
149
|
+
if (!step) {
|
|
150
|
+
return { success: false, reason: `Step "${stepId}" not found in plan.` };
|
|
151
|
+
}
|
|
152
|
+
if (step.status === "completed") {
|
|
153
|
+
return { success: false, reason: `Step "${stepId}" is already completed.` };
|
|
154
|
+
}
|
|
155
|
+
const mode = plan.completion ?? "trust";
|
|
156
|
+
if (mode === "verified" && step.verify) {
|
|
157
|
+
if (!evidence) {
|
|
158
|
+
return {
|
|
159
|
+
success: false,
|
|
160
|
+
reason: `Step "${step.label}" requires evidence (verify: ${step.verify}). Provide evidence to advance.`
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
if (evidence.type !== step.verify) {
|
|
164
|
+
return {
|
|
165
|
+
success: false,
|
|
166
|
+
reason: `Evidence type "${evidence.type}" does not match required verification "${step.verify}".`
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
const updatedPlan = {
|
|
171
|
+
...plan,
|
|
172
|
+
steps: plan.steps.map(
|
|
173
|
+
(s) => s.id === stepId ? { ...s, status: "completed" } : s
|
|
174
|
+
)
|
|
175
|
+
};
|
|
176
|
+
return {
|
|
177
|
+
success: true,
|
|
178
|
+
plan: updatedPlan,
|
|
179
|
+
evidence: evidence ?? void 0
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
function evaluatePlan(event, plan) {
|
|
183
|
+
const progress = getPlanProgress(plan);
|
|
184
|
+
if (plan.expires_at) {
|
|
185
|
+
const expiresAt = new Date(plan.expires_at).getTime();
|
|
186
|
+
if (Date.now() > expiresAt) {
|
|
187
|
+
return {
|
|
188
|
+
allowed: true,
|
|
189
|
+
status: "PLAN_COMPLETE",
|
|
190
|
+
reason: "Plan has expired.",
|
|
191
|
+
progress
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if (progress.completed === progress.total) {
|
|
196
|
+
return {
|
|
197
|
+
allowed: true,
|
|
198
|
+
status: "PLAN_COMPLETE",
|
|
199
|
+
reason: "All plan steps are completed.",
|
|
200
|
+
progress
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
const eventText = [
|
|
204
|
+
event.intent,
|
|
205
|
+
event.tool ?? "",
|
|
206
|
+
event.scope ?? ""
|
|
207
|
+
].join(" ").toLowerCase();
|
|
208
|
+
const { matched, closest, closestScore } = findMatchingStep(eventText, event, plan.steps);
|
|
209
|
+
if (!matched) {
|
|
210
|
+
return {
|
|
211
|
+
allowed: false,
|
|
212
|
+
status: "OFF_PLAN",
|
|
213
|
+
reason: "Action does not match any plan step.",
|
|
214
|
+
closestStep: closest?.label,
|
|
215
|
+
similarityScore: closestScore,
|
|
216
|
+
progress
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
if (!isSequenceValid(matched, plan)) {
|
|
220
|
+
const pendingDeps = (matched.requires ?? []).filter((reqId) => plan.steps.find((s) => s.id === reqId)?.status !== "completed").join(", ");
|
|
221
|
+
return {
|
|
222
|
+
allowed: false,
|
|
223
|
+
status: "OFF_PLAN",
|
|
224
|
+
reason: `Step "${matched.label}" requires completion of: ${pendingDeps}`,
|
|
225
|
+
matchedStep: matched.id,
|
|
226
|
+
progress
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
const { violated } = checkConstraints(event, eventText, plan.constraints);
|
|
230
|
+
if (violated) {
|
|
231
|
+
return {
|
|
232
|
+
allowed: false,
|
|
233
|
+
status: "CONSTRAINT_VIOLATED",
|
|
234
|
+
reason: violated.description,
|
|
235
|
+
matchedStep: matched.id,
|
|
236
|
+
progress
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
return {
|
|
240
|
+
allowed: true,
|
|
241
|
+
status: "ON_PLAN",
|
|
242
|
+
reason: `Matches step: ${matched.label}`,
|
|
243
|
+
matchedStep: matched.id,
|
|
244
|
+
progress
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
function buildPlanCheck(event, plan, verdict) {
|
|
248
|
+
const eventText = [event.intent, event.tool ?? "", event.scope ?? ""].join(" ").toLowerCase();
|
|
249
|
+
const { matched, closest, closestScore } = findMatchingStep(eventText, event, plan.steps);
|
|
250
|
+
const { checks: constraintChecks } = checkConstraints(event, eventText, plan.constraints);
|
|
251
|
+
const progress = getPlanProgress(plan);
|
|
252
|
+
return {
|
|
253
|
+
planId: plan.plan_id,
|
|
254
|
+
matched: !!matched,
|
|
255
|
+
matchedStepId: matched?.id,
|
|
256
|
+
matchedStepLabel: matched?.label,
|
|
257
|
+
closestStepId: !matched ? closest?.id : void 0,
|
|
258
|
+
closestStepLabel: !matched ? closest?.label : void 0,
|
|
259
|
+
similarityScore: !matched ? closestScore : void 0,
|
|
260
|
+
sequenceValid: matched ? isSequenceValid(matched, plan) : void 0,
|
|
261
|
+
constraintsChecked: constraintChecks,
|
|
262
|
+
progress: { completed: progress.completed, total: progress.total }
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
|
|
40
266
|
// src/engine/guard-engine.ts
|
|
41
267
|
var PROMPT_INJECTION_PATTERNS = [
|
|
42
268
|
// Instruction override
|
|
@@ -128,6 +354,7 @@ function evaluateGuard(event, world, options = {}) {
|
|
|
128
354
|
const eventText = (event.intent + " " + (event.tool ?? "") + " " + (event.scope ?? "")).toLowerCase();
|
|
129
355
|
const invariantChecks = [];
|
|
130
356
|
const safetyChecks = [];
|
|
357
|
+
let planCheckResult;
|
|
131
358
|
const roleChecks = [];
|
|
132
359
|
const guardChecks = [];
|
|
133
360
|
const kernelRuleChecks = [];
|
|
@@ -155,6 +382,7 @@ function evaluateGuard(event, world, options = {}) {
|
|
|
155
382
|
includeTrace ? buildTrace(
|
|
156
383
|
invariantChecks,
|
|
157
384
|
safetyChecks,
|
|
385
|
+
planCheckResult,
|
|
158
386
|
roleChecks,
|
|
159
387
|
guardChecks,
|
|
160
388
|
kernelRuleChecks,
|
|
@@ -183,6 +411,7 @@ function evaluateGuard(event, world, options = {}) {
|
|
|
183
411
|
includeTrace ? buildTrace(
|
|
184
412
|
invariantChecks,
|
|
185
413
|
safetyChecks,
|
|
414
|
+
planCheckResult,
|
|
186
415
|
roleChecks,
|
|
187
416
|
guardChecks,
|
|
188
417
|
kernelRuleChecks,
|
|
@@ -193,6 +422,42 @@ function evaluateGuard(event, world, options = {}) {
|
|
|
193
422
|
) : void 0
|
|
194
423
|
);
|
|
195
424
|
}
|
|
425
|
+
if (options.plan) {
|
|
426
|
+
const planVerdict = evaluatePlan(event, options.plan);
|
|
427
|
+
planCheckResult = buildPlanCheck(event, options.plan, planVerdict);
|
|
428
|
+
if (!planVerdict.allowed && planVerdict.status !== "PLAN_COMPLETE") {
|
|
429
|
+
decidingLayer = "plan-enforcement";
|
|
430
|
+
decidingId = `plan-${options.plan.plan_id}`;
|
|
431
|
+
const planStatus = planVerdict.status === "CONSTRAINT_VIOLATED" ? "PAUSE" : "BLOCK";
|
|
432
|
+
let reason = planVerdict.reason ?? "Action blocked by plan.";
|
|
433
|
+
if (planVerdict.status === "OFF_PLAN" && planVerdict.closestStep) {
|
|
434
|
+
reason += ` Closest step: "${planVerdict.closestStep}" (similarity: ${(planVerdict.similarityScore ?? 0).toFixed(2)})`;
|
|
435
|
+
}
|
|
436
|
+
return buildVerdict(
|
|
437
|
+
planStatus,
|
|
438
|
+
reason,
|
|
439
|
+
`plan-${options.plan.plan_id}`,
|
|
440
|
+
void 0,
|
|
441
|
+
world,
|
|
442
|
+
level,
|
|
443
|
+
invariantChecks,
|
|
444
|
+
guardsMatched,
|
|
445
|
+
rulesMatched,
|
|
446
|
+
includeTrace ? buildTrace(
|
|
447
|
+
invariantChecks,
|
|
448
|
+
safetyChecks,
|
|
449
|
+
planCheckResult,
|
|
450
|
+
roleChecks,
|
|
451
|
+
guardChecks,
|
|
452
|
+
kernelRuleChecks,
|
|
453
|
+
levelChecks,
|
|
454
|
+
decidingLayer,
|
|
455
|
+
decidingId,
|
|
456
|
+
startTime
|
|
457
|
+
) : void 0
|
|
458
|
+
);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
196
461
|
const roleVerdict = checkRoleRules(event, eventText, world, roleChecks);
|
|
197
462
|
if (roleVerdict) {
|
|
198
463
|
decidingLayer = "role";
|
|
@@ -210,6 +475,7 @@ function evaluateGuard(event, world, options = {}) {
|
|
|
210
475
|
includeTrace ? buildTrace(
|
|
211
476
|
invariantChecks,
|
|
212
477
|
safetyChecks,
|
|
478
|
+
planCheckResult,
|
|
213
479
|
roleChecks,
|
|
214
480
|
guardChecks,
|
|
215
481
|
kernelRuleChecks,
|
|
@@ -238,6 +504,7 @@ function evaluateGuard(event, world, options = {}) {
|
|
|
238
504
|
includeTrace ? buildTrace(
|
|
239
505
|
invariantChecks,
|
|
240
506
|
safetyChecks,
|
|
507
|
+
planCheckResult,
|
|
241
508
|
roleChecks,
|
|
242
509
|
guardChecks,
|
|
243
510
|
kernelRuleChecks,
|
|
@@ -266,6 +533,7 @@ function evaluateGuard(event, world, options = {}) {
|
|
|
266
533
|
includeTrace ? buildTrace(
|
|
267
534
|
invariantChecks,
|
|
268
535
|
safetyChecks,
|
|
536
|
+
planCheckResult,
|
|
269
537
|
roleChecks,
|
|
270
538
|
guardChecks,
|
|
271
539
|
kernelRuleChecks,
|
|
@@ -293,6 +561,7 @@ function evaluateGuard(event, world, options = {}) {
|
|
|
293
561
|
includeTrace ? buildTrace(
|
|
294
562
|
invariantChecks,
|
|
295
563
|
safetyChecks,
|
|
564
|
+
planCheckResult,
|
|
296
565
|
roleChecks,
|
|
297
566
|
guardChecks,
|
|
298
567
|
kernelRuleChecks,
|
|
@@ -317,6 +586,7 @@ function evaluateGuard(event, world, options = {}) {
|
|
|
317
586
|
includeTrace ? buildTrace(
|
|
318
587
|
invariantChecks,
|
|
319
588
|
safetyChecks,
|
|
589
|
+
planCheckResult,
|
|
320
590
|
roleChecks,
|
|
321
591
|
guardChecks,
|
|
322
592
|
kernelRuleChecks,
|
|
@@ -654,8 +924,8 @@ function matchesKeywords(eventText, ruleText) {
|
|
|
654
924
|
function eventToAllowlistKey(event) {
|
|
655
925
|
return `${(event.tool ?? "*").toLowerCase()}::${event.intent.toLowerCase().trim()}`;
|
|
656
926
|
}
|
|
657
|
-
function buildTrace(invariantChecks, safetyChecks, roleChecks, guardChecks, kernelRuleChecks, levelChecks, decidingLayer, decidingId, startTime) {
|
|
658
|
-
|
|
927
|
+
function buildTrace(invariantChecks, safetyChecks, planCheck, roleChecks, guardChecks, kernelRuleChecks, levelChecks, decidingLayer, decidingId, startTime) {
|
|
928
|
+
const trace = {
|
|
659
929
|
invariantChecks,
|
|
660
930
|
safetyChecks,
|
|
661
931
|
roleChecks,
|
|
@@ -673,6 +943,7 @@ function buildTrace(invariantChecks, safetyChecks, roleChecks, guardChecks, kern
|
|
|
673
943
|
"safety-scope-escape",
|
|
674
944
|
"safety-execution-claim",
|
|
675
945
|
"safety-execution-intent",
|
|
946
|
+
"plan-enforcement",
|
|
676
947
|
"role-rules",
|
|
677
948
|
"declarative-guards",
|
|
678
949
|
"kernel-rules",
|
|
@@ -682,6 +953,10 @@ function buildTrace(invariantChecks, safetyChecks, roleChecks, guardChecks, kern
|
|
|
682
953
|
},
|
|
683
954
|
durationMs: performance.now() - startTime
|
|
684
955
|
};
|
|
956
|
+
if (planCheck) {
|
|
957
|
+
trace.planCheck = planCheck;
|
|
958
|
+
}
|
|
959
|
+
return trace;
|
|
685
960
|
}
|
|
686
961
|
function buildVerdict(status, reason, ruleId, warning, world, level, invariantChecks, guardsMatched, rulesMatched, trace) {
|
|
687
962
|
const evidence = {
|
|
@@ -807,12 +1082,15 @@ var NeuroVersePlugin = class {
|
|
|
807
1082
|
options;
|
|
808
1083
|
engineOptions;
|
|
809
1084
|
mapAction;
|
|
1085
|
+
activePlan;
|
|
810
1086
|
constructor(world, options = {}) {
|
|
811
1087
|
this.world = world;
|
|
812
1088
|
this.options = options;
|
|
1089
|
+
this.activePlan = options.plan;
|
|
813
1090
|
this.engineOptions = {
|
|
814
1091
|
trace: options.trace ?? false,
|
|
815
|
-
level: options.level
|
|
1092
|
+
level: options.level,
|
|
1093
|
+
plan: this.activePlan
|
|
816
1094
|
};
|
|
817
1095
|
this.mapAction = options.mapAction ?? defaultMapAction;
|
|
818
1096
|
}
|
|
@@ -824,6 +1102,7 @@ var NeuroVersePlugin = class {
|
|
|
824
1102
|
*/
|
|
825
1103
|
beforeAction(action) {
|
|
826
1104
|
const event = this.mapAction(action, "input");
|
|
1105
|
+
this.engineOptions.plan = this.activePlan;
|
|
827
1106
|
const verdict = evaluateGuard(event, this.world, this.engineOptions);
|
|
828
1107
|
const result = {
|
|
829
1108
|
allowed: verdict.status === "ALLOW",
|
|
@@ -834,6 +1113,21 @@ var NeuroVersePlugin = class {
|
|
|
834
1113
|
if (verdict.status === "BLOCK") {
|
|
835
1114
|
throw new GovernanceBlockedError(verdict, action);
|
|
836
1115
|
}
|
|
1116
|
+
if (verdict.status === "ALLOW" && this.activePlan) {
|
|
1117
|
+
const planVerdict = evaluatePlan(event, this.activePlan);
|
|
1118
|
+
if (planVerdict.matchedStep) {
|
|
1119
|
+
const advResult = advancePlan(this.activePlan, planVerdict.matchedStep);
|
|
1120
|
+
if (advResult.success && advResult.plan) {
|
|
1121
|
+
this.activePlan = advResult.plan;
|
|
1122
|
+
this.engineOptions.plan = this.activePlan;
|
|
1123
|
+
}
|
|
1124
|
+
const progress = getPlanProgress(this.activePlan);
|
|
1125
|
+
this.options.onPlanProgress?.(progress);
|
|
1126
|
+
if (progress.completed === progress.total) {
|
|
1127
|
+
this.options.onPlanComplete?.();
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
837
1131
|
return result;
|
|
838
1132
|
}
|
|
839
1133
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { G as GuardVerdict, W as WorldDefinition, a as GuardEvent } from '../guard-contract-
|
|
1
|
+
import { G as GuardVerdict, W as WorldDefinition, a as GuardEvent, P as PlanDefinition, b as PlanProgress } from '../guard-contract-Cm91Kp4j.cjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* NeuroVerse Adapter — OpenClaw
|
|
@@ -38,6 +38,12 @@ interface NeuroVersePluginOptions {
|
|
|
38
38
|
mapAction?: (action: AgentAction, direction: 'input' | 'output') => GuardEvent;
|
|
39
39
|
/** Whether to evaluate output actions (post-action). Default: false. */
|
|
40
40
|
evaluateOutputs?: boolean;
|
|
41
|
+
/** Active plan overlay for task-scoped governance. */
|
|
42
|
+
plan?: PlanDefinition;
|
|
43
|
+
/** Called when plan progress changes. */
|
|
44
|
+
onPlanProgress?: (progress: PlanProgress) => void;
|
|
45
|
+
/** Called when all plan steps are completed. */
|
|
46
|
+
onPlanComplete?: () => void;
|
|
41
47
|
}
|
|
42
48
|
declare class GovernanceBlockedError extends Error {
|
|
43
49
|
readonly verdict: GuardVerdict;
|
|
@@ -57,6 +63,7 @@ declare class NeuroVersePlugin {
|
|
|
57
63
|
private options;
|
|
58
64
|
private engineOptions;
|
|
59
65
|
private mapAction;
|
|
66
|
+
private activePlan?;
|
|
60
67
|
constructor(world: WorldDefinition, options?: NeuroVersePluginOptions);
|
|
61
68
|
/**
|
|
62
69
|
* Evaluate an action before execution.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { G as GuardVerdict, W as WorldDefinition, a as GuardEvent } from '../guard-contract-
|
|
1
|
+
import { G as GuardVerdict, W as WorldDefinition, a as GuardEvent, P as PlanDefinition, b as PlanProgress } from '../guard-contract-Cm91Kp4j.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* NeuroVerse Adapter — OpenClaw
|
|
@@ -38,6 +38,12 @@ interface NeuroVersePluginOptions {
|
|
|
38
38
|
mapAction?: (action: AgentAction, direction: 'input' | 'output') => GuardEvent;
|
|
39
39
|
/** Whether to evaluate output actions (post-action). Default: false. */
|
|
40
40
|
evaluateOutputs?: boolean;
|
|
41
|
+
/** Active plan overlay for task-scoped governance. */
|
|
42
|
+
plan?: PlanDefinition;
|
|
43
|
+
/** Called when plan progress changes. */
|
|
44
|
+
onPlanProgress?: (progress: PlanProgress) => void;
|
|
45
|
+
/** Called when all plan steps are completed. */
|
|
46
|
+
onPlanComplete?: () => void;
|
|
41
47
|
}
|
|
42
48
|
declare class GovernanceBlockedError extends Error {
|
|
43
49
|
readonly verdict: GuardVerdict;
|
|
@@ -57,6 +63,7 @@ declare class NeuroVersePlugin {
|
|
|
57
63
|
private options;
|
|
58
64
|
private engineOptions;
|
|
59
65
|
private mapAction;
|
|
66
|
+
private activePlan?;
|
|
60
67
|
constructor(world: WorldDefinition, options?: NeuroVersePluginOptions);
|
|
61
68
|
/**
|
|
62
69
|
* Evaluate an action before execution.
|
|
@@ -3,9 +3,11 @@ import {
|
|
|
3
3
|
NeuroVersePlugin,
|
|
4
4
|
createNeuroVersePlugin,
|
|
5
5
|
createNeuroVersePluginFromWorld
|
|
6
|
-
} from "../chunk-
|
|
7
|
-
import "../chunk-
|
|
8
|
-
import "../chunk-
|
|
6
|
+
} from "../chunk-SKU3GAPD.js";
|
|
7
|
+
import "../chunk-4JRYGIO7.js";
|
|
8
|
+
import "../chunk-JZPQGIKR.js";
|
|
9
|
+
import "../chunk-4QXB6PEO.js";
|
|
10
|
+
import "../chunk-YZFATT7X.js";
|
|
9
11
|
export {
|
|
10
12
|
GovernanceBlockedError,
|
|
11
13
|
NeuroVersePlugin,
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
emitWorldDefinition,
|
|
6
6
|
parseWorldMarkdown
|
|
7
7
|
} from "./chunk-XPDMYECO.js";
|
|
8
|
+
import "./chunk-YZFATT7X.js";
|
|
8
9
|
|
|
9
10
|
// src/cli/bootstrap.ts
|
|
10
11
|
function parseArgs(argv) {
|
|
@@ -81,7 +82,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
81
82
|
await writeWorldFiles(args.outputPath, emitResult.world);
|
|
82
83
|
let validateReport;
|
|
83
84
|
if (args.validate) {
|
|
84
|
-
const { validateWorld } = await import("./validate-engine-
|
|
85
|
+
const { validateWorld } = await import("./validate-engine-UIABSIHD.js");
|
|
85
86
|
validateReport = validateWorld(emitResult.world);
|
|
86
87
|
}
|
|
87
88
|
const result = {
|
|
@@ -2,15 +2,17 @@ import {
|
|
|
2
2
|
DeriveInputError,
|
|
3
3
|
DeriveProviderError,
|
|
4
4
|
deriveWorld
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-NF5POFCI.js";
|
|
6
6
|
import {
|
|
7
7
|
DERIVE_EXIT_CODES
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-Q6O7ZLO2.js";
|
|
9
|
+
import "./chunk-OT6PXH54.js";
|
|
9
10
|
import {
|
|
10
11
|
emitWorldDefinition,
|
|
11
12
|
parseWorldMarkdown
|
|
12
13
|
} from "./chunk-XPDMYECO.js";
|
|
13
|
-
import "./chunk-
|
|
14
|
+
import "./chunk-7P3S7MAY.js";
|
|
15
|
+
import "./chunk-YZFATT7X.js";
|
|
14
16
|
|
|
15
17
|
// src/cli/build.ts
|
|
16
18
|
var FINDING_LABELS = {
|
|
@@ -74,6 +76,34 @@ function traceCausalChains(rules) {
|
|
|
74
76
|
}
|
|
75
77
|
return unique.slice(0, 3);
|
|
76
78
|
}
|
|
79
|
+
function renderGovernanceHealth(health) {
|
|
80
|
+
const lines = [];
|
|
81
|
+
lines.push("GOVERNANCE HEALTH");
|
|
82
|
+
lines.push(` Coverage: ${health.surfacesCovered} / ${health.surfacesTotal} action surfaces governed`);
|
|
83
|
+
lines.push(` Invariants enforced: ${health.invariantsEnforced} / ${health.invariantsTotal}`);
|
|
84
|
+
if (health.shadowedGuards > 0) {
|
|
85
|
+
lines.push(` Shadowed guards: ${health.shadowedGuards}`);
|
|
86
|
+
}
|
|
87
|
+
if (health.unenforcedInvariants > 0) {
|
|
88
|
+
lines.push(` Unenforced invariants: ${health.unenforcedInvariants}`);
|
|
89
|
+
}
|
|
90
|
+
if (health.unreachableRules > 0) {
|
|
91
|
+
lines.push(` Unreachable rules: ${health.unreachableRules}`);
|
|
92
|
+
}
|
|
93
|
+
if (health.incompleteStateCoverage > 0) {
|
|
94
|
+
lines.push(` Incomplete state coverage: ${health.incompleteStateCoverage}`);
|
|
95
|
+
}
|
|
96
|
+
if (health.surfaces.length > 0) {
|
|
97
|
+
lines.push("");
|
|
98
|
+
lines.push(" Surfaces:");
|
|
99
|
+
for (const s of health.surfaces) {
|
|
100
|
+
lines.push(` ${s.name}: ${s.governed ? "governed" : "unguarded"}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
lines.push("");
|
|
104
|
+
lines.push(` Risk level: ${health.riskLevel.charAt(0).toUpperCase() + health.riskLevel.slice(1)}`);
|
|
105
|
+
return lines.join("\n");
|
|
106
|
+
}
|
|
77
107
|
function parseArgs(argv) {
|
|
78
108
|
let inputPath = "";
|
|
79
109
|
let outputDir;
|
|
@@ -304,5 +334,6 @@ Next steps:
|
|
|
304
334
|
export {
|
|
305
335
|
humanLabel,
|
|
306
336
|
main,
|
|
337
|
+
renderGovernanceHealth,
|
|
307
338
|
traceCausalChains
|
|
308
339
|
};
|