@neuroverseos/governance 0.1.5 → 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.
- 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 +301 -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 +267 -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 +267 -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 +267 -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-FYPYZFV5.js → chunk-2JQJ5U5X.js} +1 -1
- package/dist/chunk-37JG24WH.js +161 -0
- package/dist/chunk-5EDDNJU6.js +321 -0
- package/dist/{chunk-O5OMJMIE.js → chunk-7P3S7MAY.js} +502 -2
- package/dist/chunk-A5W4GNQO.js +130 -0
- package/dist/{chunk-ITJ3LCPG.js → chunk-ADV7Q2LJ.js} +1 -1
- package/dist/chunk-AKW5YVCE.js +96 -0
- package/dist/{chunk-EIUHJXBB.js → chunk-GR6DGCZ2.js} +1 -1
- package/dist/{chunk-EQXFOKH2.js → chunk-IVPKFJX3.js} +24 -3
- package/dist/{chunk-D7BGWV2J.js → chunk-NF5POFCI.js} +5 -3
- package/dist/chunk-OT6PXH54.js +61 -0
- package/dist/chunk-P74Y66ZV.js +205 -0
- package/dist/chunk-PAX2P6ZP.js +601 -0
- package/dist/{chunk-B4NF3OLW.js → chunk-PQBJBVSW.js} +56 -2
- package/dist/{chunk-T4X42QXC.js → chunk-Q6O7ZLO2.js} +0 -59
- package/dist/{chunk-FZQCRGUU.js → chunk-TINSRYXQ.js} +24 -3
- package/dist/{chunk-CROPZ75A.js → chunk-UPJNTSVM.js} +24 -3
- package/dist/chunk-YZFATT7X.js +9 -0
- package/dist/{chunk-Z2S2HIV5.js → chunk-ZL4AHY4X.js} +2 -2
- package/dist/cli/neuroverse.cjs +5287 -740
- package/dist/cli/neuroverse.js +69 -13
- package/dist/cli/plan.cjs +1554 -0
- package/dist/cli/plan.d.cts +20 -0
- package/dist/cli/plan.d.ts +20 -0
- package/dist/cli/plan.js +346 -0
- package/dist/cli/run.cjs +1716 -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-V72UM2TC.js +170 -0
- package/dist/{explain-3B3VB6TL.js → explain-IDCRWMPX.js} +2 -1
- package/dist/{guard-67Y66P3I.js → guard-WA3FCCIO.js} +20 -6
- package/dist/{guard-contract-D_RQz9kt.d.ts → guard-contract-D-2LQInm.d.cts} +144 -2
- package/dist/{guard-contract-D_RQz9kt.d.cts → guard-contract-D-2LQInm.d.ts} +144 -2
- package/dist/guard-engine-D7X4CVAE.js +10 -0
- package/dist/{impact-CHERK3O6.js → impact-BWULZ5RP.js} +5 -3
- package/dist/{improve-YG6I6ERG.js → improve-GPUBKTEA.js} +4 -3
- package/dist/index.cjs +2095 -89
- package/dist/index.d.cts +466 -12
- package/dist/index.d.ts +466 -12
- package/dist/index.js +70 -20
- package/dist/{init-Z66T6TDI.js → init-PKPIYHYE.js} +2 -0
- package/dist/mcp-server-YUOQP4M5.js +13 -0
- package/dist/model-adapter-BB7G4MFI.js +11 -0
- package/dist/playground-CBXMAW2B.js +550 -0
- package/dist/redteam-SSNABQ7W.js +357 -0
- package/dist/session-MWRBTCYX.js +14 -0
- package/dist/{simulate-ETHHINZ4.js → simulate-VDOYQFRO.js} +2 -1
- package/dist/test-3GZSG5FR.js +217 -0
- package/dist/{trace-3YODSSIP.js → trace-TM4Z7G73.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
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* neuroverse run — Governed Runtime
|
|
3
|
+
*
|
|
4
|
+
* Modes:
|
|
5
|
+
* --pipe Pipe mode: JSON lines in → verdicts out (default if stdin is piped)
|
|
6
|
+
* --interactive Interactive chat session with a model
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* # Pipe mode — works with any language/framework
|
|
10
|
+
* my_agent | neuroverse run --world ./world/ --plan plan.json
|
|
11
|
+
*
|
|
12
|
+
* # Interactive mode — governed chat session
|
|
13
|
+
* neuroverse run --world ./world/ --plan plan.json --provider openai
|
|
14
|
+
*
|
|
15
|
+
* # Quick start — auto-detect world and plan
|
|
16
|
+
* neuroverse run
|
|
17
|
+
*/
|
|
18
|
+
declare function main(args: string[]): Promise<void>;
|
|
19
|
+
|
|
20
|
+
export { main };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* neuroverse run — Governed Runtime
|
|
3
|
+
*
|
|
4
|
+
* Modes:
|
|
5
|
+
* --pipe Pipe mode: JSON lines in → verdicts out (default if stdin is piped)
|
|
6
|
+
* --interactive Interactive chat session with a model
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* # Pipe mode — works with any language/framework
|
|
10
|
+
* my_agent | neuroverse run --world ./world/ --plan plan.json
|
|
11
|
+
*
|
|
12
|
+
* # Interactive mode — governed chat session
|
|
13
|
+
* neuroverse run --world ./world/ --plan plan.json --provider openai
|
|
14
|
+
*
|
|
15
|
+
* # Quick start — auto-detect world and plan
|
|
16
|
+
* neuroverse run
|
|
17
|
+
*/
|
|
18
|
+
declare function main(args: string[]): Promise<void>;
|
|
19
|
+
|
|
20
|
+
export { main };
|
package/dist/cli/run.js
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import {
|
|
2
|
+
describeActiveWorld,
|
|
3
|
+
resolveWorldPath
|
|
4
|
+
} from "../chunk-AKW5YVCE.js";
|
|
5
|
+
import "../chunk-YZFATT7X.js";
|
|
6
|
+
|
|
7
|
+
// src/cli/run.ts
|
|
8
|
+
import { readFileSync, readdirSync, existsSync } from "fs";
|
|
9
|
+
import { join } from "path";
|
|
10
|
+
function parseArg(args, flag) {
|
|
11
|
+
const idx = args.indexOf(flag);
|
|
12
|
+
return idx >= 0 && idx + 1 < args.length ? args[idx + 1] : void 0;
|
|
13
|
+
}
|
|
14
|
+
function hasFlag(args, flag) {
|
|
15
|
+
return args.includes(flag);
|
|
16
|
+
}
|
|
17
|
+
function autoDetectPlan() {
|
|
18
|
+
const nvDir = ".neuroverse/plans";
|
|
19
|
+
if (!existsSync(nvDir)) return void 0;
|
|
20
|
+
const entries = readdirSync(nvDir).filter((e) => e.endsWith(".json"));
|
|
21
|
+
if (entries.length === 1) {
|
|
22
|
+
try {
|
|
23
|
+
return JSON.parse(readFileSync(join(nvDir, entries[0]), "utf-8"));
|
|
24
|
+
} catch {
|
|
25
|
+
return void 0;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return void 0;
|
|
29
|
+
}
|
|
30
|
+
function loadPlan(path) {
|
|
31
|
+
return JSON.parse(readFileSync(path, "utf-8"));
|
|
32
|
+
}
|
|
33
|
+
var RUN_USAGE = `
|
|
34
|
+
neuroverse run \u2014 Governed runtime for AI agents.
|
|
35
|
+
|
|
36
|
+
Modes:
|
|
37
|
+
--pipe JSON lines in \u2192 verdicts out (default if stdin is piped)
|
|
38
|
+
--interactive Chat session with model + governance
|
|
39
|
+
|
|
40
|
+
Options:
|
|
41
|
+
--world <path> Path to world directory
|
|
42
|
+
--plan <path> Path to plan.json
|
|
43
|
+
--level <level> Enforcement level (basic|standard|strict)
|
|
44
|
+
--trace Include evaluation trace in verdicts
|
|
45
|
+
--provider <name> Model provider (openai|anthropic|ollama)
|
|
46
|
+
--model <name> Model name override
|
|
47
|
+
--api-key <key> API key (or set via env var)
|
|
48
|
+
|
|
49
|
+
Usage:
|
|
50
|
+
# Pipe mode \u2014 works with any agent
|
|
51
|
+
my_agent | neuroverse run --world ./world/ --plan plan.json
|
|
52
|
+
|
|
53
|
+
# Interactive mode \u2014 governed chat session
|
|
54
|
+
neuroverse run --interactive --world ./world/ --provider openai
|
|
55
|
+
|
|
56
|
+
# Auto-detect world and plan
|
|
57
|
+
neuroverse run
|
|
58
|
+
`.trim();
|
|
59
|
+
async function main(args) {
|
|
60
|
+
if (hasFlag(args, "--help") || hasFlag(args, "-h")) {
|
|
61
|
+
process.stdout.write(RUN_USAGE + "\n");
|
|
62
|
+
process.exit(0);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const worldPath = resolveWorldPath(parseArg(args, "--world"));
|
|
66
|
+
if (!worldPath) {
|
|
67
|
+
process.stderr.write(
|
|
68
|
+
"Error: No world found.\nUse --world <path>, set NEUROVERSE_WORLD, or run `neuroverse world use <name>`\n"
|
|
69
|
+
);
|
|
70
|
+
process.exit(1);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const explicitWorld = parseArg(args, "--world");
|
|
74
|
+
const worldInfo = describeActiveWorld(explicitWorld);
|
|
75
|
+
if (worldInfo) {
|
|
76
|
+
process.stderr.write(`Using world: ${worldInfo.name}
|
|
77
|
+
`);
|
|
78
|
+
}
|
|
79
|
+
const planPath = parseArg(args, "--plan");
|
|
80
|
+
const plan = planPath ? loadPlan(planPath) : autoDetectPlan();
|
|
81
|
+
const level = parseArg(args, "--level");
|
|
82
|
+
const trace = hasFlag(args, "--trace");
|
|
83
|
+
const isPipeMode = hasFlag(args, "--pipe") || !process.stdin.isTTY;
|
|
84
|
+
const isInteractive = hasFlag(args, "--interactive");
|
|
85
|
+
if (isInteractive) {
|
|
86
|
+
const providerName = parseArg(args, "--provider");
|
|
87
|
+
if (!providerName) {
|
|
88
|
+
process.stderr.write(
|
|
89
|
+
"Error: Interactive mode requires --provider (openai|anthropic|ollama)\n"
|
|
90
|
+
);
|
|
91
|
+
process.exit(1);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const { resolveProvider, ModelAdapter } = await import("../model-adapter-BB7G4MFI.js");
|
|
95
|
+
const { runInteractiveMode } = await import("../session-MWRBTCYX.js");
|
|
96
|
+
const modelConfig = resolveProvider(providerName, {
|
|
97
|
+
model: parseArg(args, "--model"),
|
|
98
|
+
apiKey: parseArg(args, "--api-key")
|
|
99
|
+
});
|
|
100
|
+
const model = new ModelAdapter(modelConfig);
|
|
101
|
+
await runInteractiveMode(
|
|
102
|
+
{
|
|
103
|
+
worldPath,
|
|
104
|
+
plan,
|
|
105
|
+
level,
|
|
106
|
+
trace,
|
|
107
|
+
onVerdict: (verdict, event) => {
|
|
108
|
+
if (verdict.status !== "ALLOW") {
|
|
109
|
+
process.stderr.write(
|
|
110
|
+
` [${verdict.status}] ${event.intent} \u2014 ${verdict.reason ?? verdict.ruleId ?? "governance rule"}
|
|
111
|
+
`
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
onPlanProgress: (progress) => {
|
|
116
|
+
process.stderr.write(
|
|
117
|
+
` [plan] ${progress.completed}/${progress.total} (${progress.percentage}%)
|
|
118
|
+
`
|
|
119
|
+
);
|
|
120
|
+
},
|
|
121
|
+
onPlanComplete: () => {
|
|
122
|
+
process.stderr.write(` [plan] Complete!
|
|
123
|
+
`);
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
model
|
|
127
|
+
);
|
|
128
|
+
} else if (isPipeMode) {
|
|
129
|
+
const { runPipeMode } = await import("../session-MWRBTCYX.js");
|
|
130
|
+
await runPipeMode({
|
|
131
|
+
worldPath,
|
|
132
|
+
plan,
|
|
133
|
+
level,
|
|
134
|
+
trace
|
|
135
|
+
});
|
|
136
|
+
} else {
|
|
137
|
+
process.stdout.write(RUN_USAGE + "\n");
|
|
138
|
+
process.exit(0);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
export {
|
|
142
|
+
main
|
|
143
|
+
};
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CONFIGURE_AI_EXIT_CODES,
|
|
3
|
-
createProvider
|
|
3
|
+
createProvider
|
|
4
|
+
} from "./chunk-Q6O7ZLO2.js";
|
|
5
|
+
import {
|
|
4
6
|
getConfigPath,
|
|
5
7
|
loadConfig,
|
|
6
8
|
redactConfig,
|
|
7
9
|
saveConfig
|
|
8
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-OT6PXH54.js";
|
|
11
|
+
import "./chunk-YZFATT7X.js";
|
|
9
12
|
|
|
10
13
|
// src/cli/configure-ai.ts
|
|
11
14
|
function parseArgs(argv) {
|
|
@@ -2,12 +2,14 @@ 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 "./chunk-XPDMYECO.js";
|
|
10
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-7P3S7MAY.js";
|
|
12
|
+
import "./chunk-YZFATT7X.js";
|
|
11
13
|
|
|
12
14
|
// src/cli/derive.ts
|
|
13
15
|
function parseArgs(argv) {
|
|
@@ -117,7 +119,7 @@ Normalization: ${n.fixCount} fix(es) applied
|
|
|
117
119
|
process.stderr.write(`
|
|
118
120
|
Bootstrapping to ${args.bootstrapDir}...
|
|
119
121
|
`);
|
|
120
|
-
const { main: bootstrapMain } = await import("./bootstrap-
|
|
122
|
+
const { main: bootstrapMain } = await import("./bootstrap-GXVDZNF7.js");
|
|
121
123
|
await bootstrapMain([
|
|
122
124
|
"--input",
|
|
123
125
|
result.outputPath,
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import {
|
|
2
|
+
loadConfig
|
|
3
|
+
} from "./chunk-OT6PXH54.js";
|
|
4
|
+
import {
|
|
5
|
+
__glob
|
|
6
|
+
} from "./chunk-YZFATT7X.js";
|
|
7
|
+
|
|
8
|
+
// import("../adapters/**/*") in src/cli/doctor.ts
|
|
9
|
+
var globImport_adapters = __glob({
|
|
10
|
+
"../adapters/express.ts": () => import("./adapters/express.js"),
|
|
11
|
+
"../adapters/index.ts": () => import("./adapters/index.js"),
|
|
12
|
+
"../adapters/langchain.ts": () => import("./adapters/langchain.js"),
|
|
13
|
+
"../adapters/openai.ts": () => import("./adapters/openai.js"),
|
|
14
|
+
"../adapters/openclaw.ts": () => import("./adapters/openclaw.js")
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
// src/cli/doctor.ts
|
|
18
|
+
var PACKAGE_VERSION = "0.2.0";
|
|
19
|
+
var MIN_NODE_VERSION = 18;
|
|
20
|
+
async function main(argv) {
|
|
21
|
+
const json = argv.includes("--json");
|
|
22
|
+
let worldPath;
|
|
23
|
+
for (let i = 0; i < argv.length; i++) {
|
|
24
|
+
if (argv[i] === "--world" && i + 1 < argv.length) {
|
|
25
|
+
worldPath = argv[++i];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const checks = [];
|
|
29
|
+
const nodeVersion = process.version;
|
|
30
|
+
const major = parseInt(nodeVersion.slice(1), 10);
|
|
31
|
+
checks.push({
|
|
32
|
+
label: "Node version",
|
|
33
|
+
status: major >= MIN_NODE_VERSION ? "pass" : "fail",
|
|
34
|
+
value: nodeVersion,
|
|
35
|
+
detail: major < MIN_NODE_VERSION ? `Requires Node >= ${MIN_NODE_VERSION}` : void 0
|
|
36
|
+
});
|
|
37
|
+
checks.push({
|
|
38
|
+
label: "NeuroVerse version",
|
|
39
|
+
status: "pass",
|
|
40
|
+
value: PACKAGE_VERSION
|
|
41
|
+
});
|
|
42
|
+
try {
|
|
43
|
+
const config = await loadConfig();
|
|
44
|
+
if (config?.provider && config?.apiKey) {
|
|
45
|
+
checks.push({
|
|
46
|
+
label: "AI provider configured",
|
|
47
|
+
status: "pass",
|
|
48
|
+
value: `${config.provider}${config.model ? ` (${config.model})` : ""}`
|
|
49
|
+
});
|
|
50
|
+
} else {
|
|
51
|
+
checks.push({
|
|
52
|
+
label: "AI provider configured",
|
|
53
|
+
status: "warn",
|
|
54
|
+
value: "not configured",
|
|
55
|
+
detail: "Run: neuroverse configure-ai --provider openai --model gpt-4.1-mini --api-key <key>"
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
} catch {
|
|
59
|
+
checks.push({
|
|
60
|
+
label: "AI provider configured",
|
|
61
|
+
status: "warn",
|
|
62
|
+
value: "not configured",
|
|
63
|
+
detail: "Run: neuroverse configure-ai"
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
if (worldPath) {
|
|
67
|
+
try {
|
|
68
|
+
const { existsSync } = await import("fs");
|
|
69
|
+
const { join } = await import("path");
|
|
70
|
+
const hasWorld = existsSync(join(worldPath, "world.json"));
|
|
71
|
+
checks.push({
|
|
72
|
+
label: "World file detected",
|
|
73
|
+
status: hasWorld ? "pass" : "fail",
|
|
74
|
+
value: hasWorld ? worldPath : "not found",
|
|
75
|
+
detail: hasWorld ? void 0 : `No world.json found in ${worldPath}`
|
|
76
|
+
});
|
|
77
|
+
} catch {
|
|
78
|
+
checks.push({
|
|
79
|
+
label: "World file detected",
|
|
80
|
+
status: "fail",
|
|
81
|
+
value: "error reading path"
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
} else {
|
|
85
|
+
const { existsSync } = await import("fs");
|
|
86
|
+
const { join } = await import("path");
|
|
87
|
+
const candidates = ["./world", "./.neuroverse", "./worlds"];
|
|
88
|
+
let found;
|
|
89
|
+
for (const dir of candidates) {
|
|
90
|
+
if (existsSync(join(dir, "world.json"))) {
|
|
91
|
+
found = dir;
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
checks.push({
|
|
96
|
+
label: "World file detected",
|
|
97
|
+
status: found ? "pass" : "warn",
|
|
98
|
+
value: found ?? "none found",
|
|
99
|
+
detail: found ? void 0 : "Build a world: neuroverse build <input.md>"
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
try {
|
|
103
|
+
const { evaluateGuard } = await import("./guard-engine-D7X4CVAE.js");
|
|
104
|
+
checks.push({
|
|
105
|
+
label: "Guard engine",
|
|
106
|
+
status: typeof evaluateGuard === "function" ? "pass" : "fail",
|
|
107
|
+
value: "loaded"
|
|
108
|
+
});
|
|
109
|
+
} catch {
|
|
110
|
+
checks.push({ label: "Guard engine", status: "fail", value: "failed to load" });
|
|
111
|
+
}
|
|
112
|
+
try {
|
|
113
|
+
const { validateWorld } = await import("./validate-engine-UIABSIHD.js");
|
|
114
|
+
checks.push({
|
|
115
|
+
label: "Validation engine",
|
|
116
|
+
status: typeof validateWorld === "function" ? "pass" : "fail",
|
|
117
|
+
value: "loaded"
|
|
118
|
+
});
|
|
119
|
+
} catch {
|
|
120
|
+
checks.push({ label: "Validation engine", status: "fail", value: "failed to load" });
|
|
121
|
+
}
|
|
122
|
+
const adapterNames = ["openai", "express", "langchain", "openclaw"];
|
|
123
|
+
const loadedAdapters = [];
|
|
124
|
+
for (const name of adapterNames) {
|
|
125
|
+
try {
|
|
126
|
+
await globImport_adapters(`../adapters/${name}`);
|
|
127
|
+
loadedAdapters.push(name);
|
|
128
|
+
} catch {
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
checks.push({
|
|
132
|
+
label: "Adapters",
|
|
133
|
+
status: loadedAdapters.length > 0 ? "pass" : "warn",
|
|
134
|
+
value: loadedAdapters.length > 0 ? loadedAdapters.join(", ") : "none"
|
|
135
|
+
});
|
|
136
|
+
if (json) {
|
|
137
|
+
const hasFailure2 = checks.some((c) => c.status === "fail");
|
|
138
|
+
process.stdout.write(JSON.stringify({
|
|
139
|
+
status: hasFailure2 ? "fail" : "pass",
|
|
140
|
+
checks
|
|
141
|
+
}, null, 2) + "\n");
|
|
142
|
+
process.exit(hasFailure2 ? 1 : 0);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
process.stderr.write("\nNeuroVerse Environment Check\n");
|
|
146
|
+
process.stderr.write("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n");
|
|
147
|
+
const maxLabel = Math.max(...checks.map((c) => c.label.length));
|
|
148
|
+
for (const check of checks) {
|
|
149
|
+
const icon = check.status === "pass" ? "ok" : check.status === "warn" ? "!!" : "FAIL";
|
|
150
|
+
const pad = " ".repeat(maxLabel - check.label.length);
|
|
151
|
+
process.stderr.write(` ${check.label}${pad} ${icon} ${check.value}
|
|
152
|
+
`);
|
|
153
|
+
if (check.detail) {
|
|
154
|
+
process.stderr.write(` ${" ".repeat(maxLabel)} ${check.detail}
|
|
155
|
+
`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
const hasFailure = checks.some((c) => c.status === "fail");
|
|
159
|
+
process.stderr.write("\n");
|
|
160
|
+
if (hasFailure) {
|
|
161
|
+
process.stderr.write("Some checks failed. Fix the issues above and re-run.\n");
|
|
162
|
+
} else {
|
|
163
|
+
process.stderr.write("System ready.\n");
|
|
164
|
+
}
|
|
165
|
+
process.stderr.write("\n");
|
|
166
|
+
process.exit(hasFailure ? 1 : 0);
|
|
167
|
+
}
|
|
168
|
+
export {
|
|
169
|
+
main
|
|
170
|
+
};
|
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
2
|
GUARD_EXIT_CODES
|
|
3
3
|
} from "./chunk-MWDQ4MJB.js";
|
|
4
|
+
import {
|
|
5
|
+
describeActiveWorld,
|
|
6
|
+
resolveWorldPath
|
|
7
|
+
} from "./chunk-AKW5YVCE.js";
|
|
4
8
|
import {
|
|
5
9
|
evaluateGuard
|
|
6
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-PQBJBVSW.js";
|
|
7
11
|
import {
|
|
8
12
|
loadWorld
|
|
9
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-JZPQGIKR.js";
|
|
14
|
+
import "./chunk-P74Y66ZV.js";
|
|
15
|
+
import "./chunk-YZFATT7X.js";
|
|
10
16
|
|
|
11
17
|
// src/cli/guard.ts
|
|
12
18
|
function parseArgs(argv) {
|
|
@@ -28,9 +34,6 @@ function parseArgs(argv) {
|
|
|
28
34
|
}
|
|
29
35
|
}
|
|
30
36
|
}
|
|
31
|
-
if (!worldPath) {
|
|
32
|
-
throw new Error("--world <path> is required");
|
|
33
|
-
}
|
|
34
37
|
return { worldPath, trace, level };
|
|
35
38
|
}
|
|
36
39
|
async function readStdin() {
|
|
@@ -43,6 +46,17 @@ async function readStdin() {
|
|
|
43
46
|
async function main(argv = process.argv.slice(2)) {
|
|
44
47
|
try {
|
|
45
48
|
const args = parseArgs(argv);
|
|
49
|
+
const worldPath = resolveWorldPath(args.worldPath);
|
|
50
|
+
if (!worldPath) {
|
|
51
|
+
throw new Error(
|
|
52
|
+
"No world specified. Use --world <path>, set NEUROVERSE_WORLD, or run `neuroverse world use <name>`"
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
const worldInfo = describeActiveWorld(args.worldPath);
|
|
56
|
+
if (worldInfo) {
|
|
57
|
+
process.stderr.write(`Using world: ${worldInfo.name}
|
|
58
|
+
`);
|
|
59
|
+
}
|
|
46
60
|
const input = await readStdin();
|
|
47
61
|
if (!input.trim()) {
|
|
48
62
|
const errorResult = {
|
|
@@ -65,7 +79,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
65
79
|
process.stdout.write(JSON.stringify(errorResult, null, 2) + "\n");
|
|
66
80
|
process.exit(GUARD_EXIT_CODES.ERROR);
|
|
67
81
|
}
|
|
68
|
-
const world = await loadWorld(
|
|
82
|
+
const world = await loadWorld(worldPath);
|
|
69
83
|
const options = { trace: args.trace, level: args.level };
|
|
70
84
|
const verdict = evaluateGuard(event, world, options);
|
|
71
85
|
process.stdout.write(JSON.stringify(verdict, null, 2) + "\n");
|
|
@@ -271,6 +271,10 @@ interface IntentPattern {
|
|
|
271
271
|
interface GuardsConfig {
|
|
272
272
|
guards: Guard[];
|
|
273
273
|
intent_vocabulary: Record<string, IntentPattern>;
|
|
274
|
+
/** All known action surfaces (e.g. "shell", "http", "db", "email", "deploy").
|
|
275
|
+
* When declared, the validator checks that every surface has at least one
|
|
276
|
+
* governing guard — surfaces without guards are reported as fail-open. */
|
|
277
|
+
tool_surfaces?: string[];
|
|
274
278
|
}
|
|
275
279
|
interface WorldDefinition {
|
|
276
280
|
world: WorldIdentity;
|
|
@@ -287,6 +291,136 @@ interface WorldDefinition {
|
|
|
287
291
|
metadata: WorldMetadata;
|
|
288
292
|
}
|
|
289
293
|
|
|
294
|
+
/**
|
|
295
|
+
* Plan Contract — Plan Enforcement Types
|
|
296
|
+
*
|
|
297
|
+
* Defines the input/output contract for plan-based governance.
|
|
298
|
+
*
|
|
299
|
+
* Plans are temporary guard overlays — "mom's rules for this trip."
|
|
300
|
+
* They define what an agent should do (steps) and what it must not
|
|
301
|
+
* exceed (constraints). Plans layer on top of worlds, narrowing
|
|
302
|
+
* behavior without overriding safety or world-level governance.
|
|
303
|
+
*
|
|
304
|
+
* INVARIANTS:
|
|
305
|
+
* - Plans can only restrict, never expand. A plan cannot override a world BLOCK.
|
|
306
|
+
* - Plan enforcement is deterministic: same event + same plan → same verdict.
|
|
307
|
+
* - No AI in the evaluation loop. Parsing and evaluation are pure functions.
|
|
308
|
+
*/
|
|
309
|
+
interface PlanStep {
|
|
310
|
+
/** Auto-generated slug from label (e.g., "write_announcement_blog_post"). */
|
|
311
|
+
id: string;
|
|
312
|
+
/** Human-readable step name. */
|
|
313
|
+
label: string;
|
|
314
|
+
/** Optional detail about the step. */
|
|
315
|
+
description?: string;
|
|
316
|
+
/** Restrict this step to specific tools (optional). */
|
|
317
|
+
tools?: string[];
|
|
318
|
+
/** Step IDs that must complete first (optional). */
|
|
319
|
+
requires?: string[];
|
|
320
|
+
/** Semantic tags for action mapping (e.g., ["deploy", "marketing"]). */
|
|
321
|
+
tags?: string[];
|
|
322
|
+
/** Completion condition name (optional). */
|
|
323
|
+
verify?: string;
|
|
324
|
+
/** Current step status. */
|
|
325
|
+
status: 'pending' | 'active' | 'completed' | 'skipped';
|
|
326
|
+
}
|
|
327
|
+
interface PlanConstraint {
|
|
328
|
+
/** Auto-generated constraint ID. */
|
|
329
|
+
id: string;
|
|
330
|
+
/** Constraint type. 'approval' always returns PAUSE until human confirms. */
|
|
331
|
+
type: 'budget' | 'time' | 'scope' | 'approval' | 'custom';
|
|
332
|
+
/** Human-readable description. */
|
|
333
|
+
description: string;
|
|
334
|
+
/** Enforcement mode. */
|
|
335
|
+
enforcement: 'block' | 'pause';
|
|
336
|
+
/** Numeric limit (for budget/time). */
|
|
337
|
+
limit?: number;
|
|
338
|
+
/** Unit for the limit (e.g., "USD", "minutes"). */
|
|
339
|
+
unit?: string;
|
|
340
|
+
/** Pattern that activates this constraint. */
|
|
341
|
+
trigger?: string;
|
|
342
|
+
}
|
|
343
|
+
interface PlanDefinition {
|
|
344
|
+
/** Unique plan identifier. */
|
|
345
|
+
plan_id: string;
|
|
346
|
+
/** Human-readable objective. */
|
|
347
|
+
objective: string;
|
|
348
|
+
/** Whether steps must run in order. */
|
|
349
|
+
sequential: boolean;
|
|
350
|
+
/** The steps in this plan. */
|
|
351
|
+
steps: PlanStep[];
|
|
352
|
+
/** Constraints that apply to this plan. */
|
|
353
|
+
constraints: PlanConstraint[];
|
|
354
|
+
/** Optional parent world ID. */
|
|
355
|
+
world_id?: string;
|
|
356
|
+
/** When this plan was created. */
|
|
357
|
+
created_at: string;
|
|
358
|
+
/** Optional expiry time. */
|
|
359
|
+
expires_at?: string;
|
|
360
|
+
}
|
|
361
|
+
type PlanStatus = 'ON_PLAN' | 'OFF_PLAN' | 'CONSTRAINT_VIOLATED' | 'PLAN_COMPLETE';
|
|
362
|
+
interface PlanVerdict {
|
|
363
|
+
/** Whether the action is allowed by this plan. */
|
|
364
|
+
allowed: boolean;
|
|
365
|
+
/** Plan verdict status. */
|
|
366
|
+
status: PlanStatus;
|
|
367
|
+
/** Why the action was blocked or paused. */
|
|
368
|
+
reason?: string;
|
|
369
|
+
/** Which step this action matched (if any). */
|
|
370
|
+
matchedStep?: string;
|
|
371
|
+
/** Nearest step when OFF_PLAN (for agent self-correction). */
|
|
372
|
+
closestStep?: string;
|
|
373
|
+
/** How close the action was to the nearest step (0-1). */
|
|
374
|
+
similarityScore?: number;
|
|
375
|
+
/** Current plan progress. */
|
|
376
|
+
progress: PlanProgress;
|
|
377
|
+
}
|
|
378
|
+
interface PlanProgress {
|
|
379
|
+
/** Number of completed steps. */
|
|
380
|
+
completed: number;
|
|
381
|
+
/** Total number of steps. */
|
|
382
|
+
total: number;
|
|
383
|
+
/** Completion percentage. */
|
|
384
|
+
percentage: number;
|
|
385
|
+
}
|
|
386
|
+
interface PlanCheck {
|
|
387
|
+
/** The plan being enforced. */
|
|
388
|
+
planId: string;
|
|
389
|
+
/** Whether the action matched a plan step. */
|
|
390
|
+
matched: boolean;
|
|
391
|
+
/** Which step was matched. */
|
|
392
|
+
matchedStepId?: string;
|
|
393
|
+
/** Label of the matched step. */
|
|
394
|
+
matchedStepLabel?: string;
|
|
395
|
+
/** Nearest step when no match (for self-correction). */
|
|
396
|
+
closestStepId?: string;
|
|
397
|
+
/** Label of the nearest step. */
|
|
398
|
+
closestStepLabel?: string;
|
|
399
|
+
/** Similarity score to the nearest step. */
|
|
400
|
+
similarityScore?: number;
|
|
401
|
+
/** Whether step sequence requirements are satisfied. */
|
|
402
|
+
sequenceValid?: boolean;
|
|
403
|
+
/** Results of constraint checks. */
|
|
404
|
+
constraintsChecked: Array<{
|
|
405
|
+
constraintId: string;
|
|
406
|
+
passed: boolean;
|
|
407
|
+
reason?: string;
|
|
408
|
+
}>;
|
|
409
|
+
/** Current progress. */
|
|
410
|
+
progress: {
|
|
411
|
+
completed: number;
|
|
412
|
+
total: number;
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
declare const PLAN_EXIT_CODES: {
|
|
416
|
+
readonly ON_PLAN: 0;
|
|
417
|
+
readonly OFF_PLAN: 1;
|
|
418
|
+
readonly CONSTRAINT_VIOLATED: 2;
|
|
419
|
+
readonly ERROR: 3;
|
|
420
|
+
readonly PLAN_COMPLETE: 4;
|
|
421
|
+
};
|
|
422
|
+
type PlanExitCode = (typeof PLAN_EXIT_CODES)[keyof typeof PLAN_EXIT_CODES];
|
|
423
|
+
|
|
290
424
|
/**
|
|
291
425
|
* Guard Contract — CLI Governance Evaluation Types
|
|
292
426
|
*
|
|
@@ -406,6 +540,8 @@ interface EvaluationTrace {
|
|
|
406
540
|
invariantChecks: InvariantCheck[];
|
|
407
541
|
/** Safety checks (injection, scope escape) */
|
|
408
542
|
safetyChecks: SafetyCheck[];
|
|
543
|
+
/** Plan enforcement check (Phase 1.5) — present when a plan is active */
|
|
544
|
+
planCheck?: PlanCheck;
|
|
409
545
|
/** Every role rule checked */
|
|
410
546
|
roleChecks: RoleCheck[];
|
|
411
547
|
/** Every declarative guard checked */
|
|
@@ -490,7 +626,7 @@ interface LevelCheck {
|
|
|
490
626
|
*/
|
|
491
627
|
interface PrecedenceResolution {
|
|
492
628
|
/** Which check category produced the final verdict */
|
|
493
|
-
decidingLayer: 'session-allowlist' | 'safety' | 'role' | 'guard' | 'kernel-rule' | 'level-constraint' | 'default-allow';
|
|
629
|
+
decidingLayer: 'session-allowlist' | 'safety' | 'plan-enforcement' | 'role' | 'guard' | 'kernel-rule' | 'level-constraint' | 'default-allow';
|
|
494
630
|
/** Specific ID of the deciding check (guard ID, rule ID, etc.) */
|
|
495
631
|
decidingId?: string;
|
|
496
632
|
/** Resolution strategy used */
|
|
@@ -517,6 +653,12 @@ interface GuardEngineOptions {
|
|
|
517
653
|
* The caller owns persistence (allow-once, allow-always, etc.).
|
|
518
654
|
*/
|
|
519
655
|
sessionAllowlist?: Set<string>;
|
|
656
|
+
/**
|
|
657
|
+
* Active plan overlay — temporary task-scoped governance.
|
|
658
|
+
* When set, plan enforcement runs at Phase 1.5 (after safety, before roles).
|
|
659
|
+
* Plans can only restrict, never expand.
|
|
660
|
+
*/
|
|
661
|
+
plan?: PlanDefinition;
|
|
520
662
|
}
|
|
521
663
|
declare const GUARD_EXIT_CODES: {
|
|
522
664
|
readonly ALLOW: 0;
|
|
@@ -526,4 +668,4 @@ declare const GUARD_EXIT_CODES: {
|
|
|
526
668
|
};
|
|
527
669
|
type GuardExitCode = (typeof GUARD_EXIT_CODES)[keyof typeof GUARD_EXIT_CODES];
|
|
528
670
|
|
|
529
|
-
export { type EvaluationTrace as E, type GuardVerdict as G, type InvariantCheck as I, type KernelRuleCheck as K, type LevelCheck as L, type
|
|
671
|
+
export { type EvaluationTrace as E, type GuardVerdict as G, type InvariantCheck as I, type KernelRuleCheck as K, type LevelCheck as L, type PlanDefinition as P, type RoleCheck as R, type SafetyCheck as S, type ViabilityStatus as V, type WorldDefinition as W, type GuardEvent as a, type PlanProgress as b, type GuardEngineOptions as c, type PlanVerdict as d, type PlanCheck as e, GUARD_EXIT_CODES as f, type GuardCheck as g, type GuardExitCode as h, type GuardStatus as i, PLAN_EXIT_CODES as j, type PlanConstraint as k, type PlanExitCode as l, type PlanStatus as m, type PlanStep as n, type PrecedenceResolution as o, type VerdictEvidence as p };
|