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