@neuroverseos/governance 0.3.0 → 0.3.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 +20 -0
- package/package.json +16 -3
- 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 +1899 -0
- package/dist/adapters/autoresearch.cjs +0 -196
- package/dist/adapters/autoresearch.d.cts +0 -103
- package/dist/adapters/autoresearch.d.ts +0 -103
- package/dist/adapters/autoresearch.js +0 -7
- package/dist/adapters/express.cjs +0 -1114
- package/dist/adapters/express.d.cts +0 -66
- package/dist/adapters/express.d.ts +0 -66
- package/dist/adapters/express.js +0 -12
- package/dist/adapters/index.cjs +0 -1669
- package/dist/adapters/index.d.cts +0 -6
- package/dist/adapters/index.d.ts +0 -6
- package/dist/adapters/index.js +0 -46
- package/dist/adapters/langchain.cjs +0 -1155
- package/dist/adapters/langchain.d.cts +0 -89
- package/dist/adapters/langchain.d.ts +0 -89
- package/dist/adapters/langchain.js +0 -16
- package/dist/adapters/openai.cjs +0 -1185
- package/dist/adapters/openai.d.cts +0 -99
- package/dist/adapters/openai.d.ts +0 -99
- package/dist/adapters/openai.js +0 -16
- package/dist/adapters/openclaw.cjs +0 -1177
- package/dist/adapters/openclaw.d.cts +0 -99
- package/dist/adapters/openclaw.d.ts +0 -99
- package/dist/adapters/openclaw.js +0 -16
- package/dist/bootstrap-GXVDZNF7.js +0 -114
- package/dist/build-P42YFKQV.js +0 -339
- package/dist/chunk-2NICNKOM.js +0 -100
- package/dist/chunk-2PQU3VAN.js +0 -131
- package/dist/chunk-4A7LISES.js +0 -324
- package/dist/chunk-4JRYGIO7.js +0 -727
- package/dist/chunk-4NGDRRQH.js +0 -10
- package/dist/chunk-4QXB6PEO.js +0 -232
- package/dist/chunk-6CZSKEY5.js +0 -164
- package/dist/chunk-7P3S7MAY.js +0 -1090
- package/dist/chunk-A5W4GNQO.js +0 -130
- package/dist/chunk-AKW5YVCE.js +0 -96
- package/dist/chunk-BUWWN2NX.js +0 -192
- package/dist/chunk-COT5XS4V.js +0 -109
- package/dist/chunk-ER62HNGF.js +0 -139
- package/dist/chunk-FYS2CBUW.js +0 -304
- package/dist/chunk-GR6DGCZ2.js +0 -340
- package/dist/chunk-I3RRAYK2.js +0 -11
- package/dist/chunk-JZPQGIKR.js +0 -79
- package/dist/chunk-MWDQ4MJB.js +0 -11
- package/dist/chunk-NF5POFCI.js +0 -622
- package/dist/chunk-OGL7QXZS.js +0 -608
- package/dist/chunk-OT6PXH54.js +0 -61
- package/dist/chunk-PDOZHZWL.js +0 -225
- package/dist/chunk-Q6O7ZLO2.js +0 -62
- package/dist/chunk-QPASI2BR.js +0 -187
- package/dist/chunk-T5EUJQE5.js +0 -172
- package/dist/chunk-XPDMYECO.js +0 -642
- package/dist/chunk-YZFATT7X.js +0 -9
- package/dist/cli/neuroverse.cjs +0 -11448
- package/dist/cli/neuroverse.d.cts +0 -1
- package/dist/cli/neuroverse.d.ts +0 -1
- package/dist/cli/neuroverse.js +0 -196
- package/dist/cli/plan.cjs +0 -1599
- package/dist/cli/plan.d.cts +0 -20
- package/dist/cli/plan.d.ts +0 -20
- package/dist/cli/plan.js +0 -361
- package/dist/cli/run.cjs +0 -1746
- package/dist/cli/run.d.cts +0 -20
- package/dist/cli/run.d.ts +0 -20
- package/dist/cli/run.js +0 -143
- package/dist/configure-ai-TK67ZWZL.js +0 -132
- package/dist/derive-TLIV4OOU.js +0 -152
- package/dist/doctor-XPDLEYXN.js +0 -171
- package/dist/explain-IDCRWMPX.js +0 -70
- package/dist/guard-RV65TT4L.js +0 -96
- package/dist/guard-contract-WZx__PmU.d.cts +0 -709
- package/dist/guard-contract-WZx__PmU.d.ts +0 -709
- package/dist/guard-engine-JLTUARGU.js +0 -10
- package/dist/impact-XPECYRLH.js +0 -59
- package/dist/improve-GPUBKTEA.js +0 -85
- package/dist/index.cjs +0 -6273
- package/dist/index.d.cts +0 -1616
- package/dist/index.d.ts +0 -1616
- package/dist/index.js +0 -379
- package/dist/infer-world-7GVZWFX4.js +0 -543
- package/dist/init-PKPIYHYE.js +0 -144
- package/dist/init-world-VWMQZQC7.js +0 -223
- package/dist/mcp-server-FPVSU32Z.js +0 -13
- package/dist/model-adapter-BB7G4MFI.js +0 -11
- package/dist/playground-E664U4T6.js +0 -550
- package/dist/redteam-Z7WREJ44.js +0 -357
- package/dist/session-EKTRSR7C.js +0 -14
- package/dist/simulate-VDOYQFRO.js +0 -108
- package/dist/test-OGXJK4QU.js +0 -217
- package/dist/trace-JVF67VR3.js +0 -166
- package/dist/validate-LLBWVPGV.js +0 -81
- package/dist/validate-engine-UIABSIHD.js +0 -7
- package/dist/world-LAXO6DOX.js +0 -378
- package/dist/world-loader-HMPTOEA2.js +0 -9
- package/dist/worlds/autoresearch.nv-world.md +0 -230
- package/dist/worlds/derivation-world.nv-world.md +0 -278
package/dist/trace-JVF67VR3.js
DELETED
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
readAuditLog,
|
|
3
|
-
summarizeAuditEvents
|
|
4
|
-
} from "./chunk-QPASI2BR.js";
|
|
5
|
-
import "./chunk-4JRYGIO7.js";
|
|
6
|
-
import "./chunk-4QXB6PEO.js";
|
|
7
|
-
import "./chunk-YZFATT7X.js";
|
|
8
|
-
|
|
9
|
-
// src/cli/trace.ts
|
|
10
|
-
function parseArgs(argv) {
|
|
11
|
-
const args = {};
|
|
12
|
-
for (let i = 0; i < argv.length; i++) {
|
|
13
|
-
const arg = argv[i];
|
|
14
|
-
if (arg === "--summary") {
|
|
15
|
-
args.summary = true;
|
|
16
|
-
} else if (arg === "--json") {
|
|
17
|
-
args.json = true;
|
|
18
|
-
} else if (arg === "--help" || arg === "-h") {
|
|
19
|
-
args.help = true;
|
|
20
|
-
} else if (arg === "--log" && argv[i + 1]) {
|
|
21
|
-
args.log = argv[++i];
|
|
22
|
-
} else if (arg === "--filter" && argv[i + 1]) {
|
|
23
|
-
args.filter = argv[++i].toUpperCase();
|
|
24
|
-
} else if (arg === "--actor" && argv[i + 1]) {
|
|
25
|
-
args.actor = argv[++i];
|
|
26
|
-
} else if (arg === "--intent" && argv[i + 1]) {
|
|
27
|
-
args.intent = argv[++i];
|
|
28
|
-
} else if (arg === "--last" && argv[i + 1]) {
|
|
29
|
-
args.last = argv[++i];
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
return args;
|
|
33
|
-
}
|
|
34
|
-
var USAGE = `
|
|
35
|
-
neuroverse trace \u2014 Runtime action audit log
|
|
36
|
-
|
|
37
|
-
Usage:
|
|
38
|
-
neuroverse trace [options]
|
|
39
|
-
|
|
40
|
-
Options:
|
|
41
|
-
--log <path> Path to audit log (default: .neuroverse/audit.ndjson)
|
|
42
|
-
--summary Show aggregate summary
|
|
43
|
-
--filter <decision> Filter: ALLOW, BLOCK, or PAUSE
|
|
44
|
-
--actor <id> Filter by actor/role ID
|
|
45
|
-
--intent <pattern> Filter by intent (substring)
|
|
46
|
-
--last <n> Show last N events
|
|
47
|
-
--json Raw JSON output
|
|
48
|
-
`.trim();
|
|
49
|
-
function formatEvent(event) {
|
|
50
|
-
const ts = event.timestamp.split("T")[1]?.replace("Z", "").slice(0, 8) ?? event.timestamp;
|
|
51
|
-
const icon = event.decision === "ALLOW" ? " \u2713" : event.decision === "BLOCK" ? " \u2717" : " \u23F8";
|
|
52
|
-
const parts = [];
|
|
53
|
-
parts.push(` [${ts}] ${event.actor ?? "unknown"}`);
|
|
54
|
-
parts.push(` Action: ${event.intent}${event.tool ? ` (tool: ${event.tool})` : ""}`);
|
|
55
|
-
parts.push(` Result:${icon} ${event.decision}`);
|
|
56
|
-
if (event.guardsMatched.length > 0) {
|
|
57
|
-
parts.push(` Guards: ${event.guardsMatched.join(", ")}`);
|
|
58
|
-
}
|
|
59
|
-
if (event.rulesMatched.length > 0) {
|
|
60
|
-
parts.push(` Rules: ${event.rulesMatched.join(", ")}`);
|
|
61
|
-
}
|
|
62
|
-
if (event.reason) {
|
|
63
|
-
parts.push(` Reason: ${event.reason}`);
|
|
64
|
-
}
|
|
65
|
-
if (event.warning) {
|
|
66
|
-
parts.push(` Warning: ${event.warning}`);
|
|
67
|
-
}
|
|
68
|
-
return parts.join("\n");
|
|
69
|
-
}
|
|
70
|
-
function formatSummary(events) {
|
|
71
|
-
const summary = summarizeAuditEvents(events);
|
|
72
|
-
const lines = [];
|
|
73
|
-
lines.push("GOVERNANCE SUMMARY");
|
|
74
|
-
lines.push("\u2500".repeat(40));
|
|
75
|
-
lines.push("");
|
|
76
|
-
lines.push(` Total actions: ${summary.totalActions}`);
|
|
77
|
-
lines.push(` Allowed: ${summary.allowed}`);
|
|
78
|
-
lines.push(` Blocked: ${summary.blocked}`);
|
|
79
|
-
lines.push(` Paused: ${summary.paused}`);
|
|
80
|
-
if (summary.actors.length > 0) {
|
|
81
|
-
lines.push("");
|
|
82
|
-
lines.push(` Actors: ${summary.actors.join(", ")}`);
|
|
83
|
-
}
|
|
84
|
-
if (summary.firstEvent) {
|
|
85
|
-
lines.push("");
|
|
86
|
-
lines.push(` First event: ${summary.firstEvent}`);
|
|
87
|
-
lines.push(` Last event: ${summary.lastEvent}`);
|
|
88
|
-
}
|
|
89
|
-
if (summary.topIntents.length > 0) {
|
|
90
|
-
lines.push("");
|
|
91
|
-
lines.push(" Top actions:");
|
|
92
|
-
for (const entry of summary.topIntents.slice(0, 10)) {
|
|
93
|
-
const extra = [];
|
|
94
|
-
if (entry.blocked > 0) extra.push(`${entry.blocked} blocked`);
|
|
95
|
-
if (entry.paused > 0) extra.push(`${entry.paused} paused`);
|
|
96
|
-
const suffix = extra.length > 0 ? ` (${extra.join(", ")})` : "";
|
|
97
|
-
lines.push(` ${entry.intent.padEnd(30)} ${String(entry.count).padStart(5)}${suffix}`);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
if (summary.topRules.length > 0) {
|
|
101
|
-
lines.push("");
|
|
102
|
-
lines.push(" Top triggered rules/guards:");
|
|
103
|
-
for (const entry of summary.topRules.slice(0, 10)) {
|
|
104
|
-
lines.push(` ${entry.ruleId.padEnd(30)} ${String(entry.count).padStart(5)}`);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
return lines.join("\n");
|
|
108
|
-
}
|
|
109
|
-
async function main(argv = process.argv.slice(2)) {
|
|
110
|
-
const args = parseArgs(argv);
|
|
111
|
-
if (args.help) {
|
|
112
|
-
process.stdout.write(USAGE + "\n");
|
|
113
|
-
process.exit(0);
|
|
114
|
-
}
|
|
115
|
-
const logPath = args.log ?? ".neuroverse/audit.ndjson";
|
|
116
|
-
const filterFn = (event) => {
|
|
117
|
-
if (args.filter && event.decision !== args.filter) return false;
|
|
118
|
-
if (args.actor && event.actor !== args.actor) return false;
|
|
119
|
-
if (args.intent && !event.intent.includes(args.intent)) return false;
|
|
120
|
-
return true;
|
|
121
|
-
};
|
|
122
|
-
let events = await readAuditLog(logPath, filterFn);
|
|
123
|
-
if (events.length === 0) {
|
|
124
|
-
process.stderr.write(`No audit events found in ${logPath}
|
|
125
|
-
`);
|
|
126
|
-
process.stderr.write("Run governance evaluations with audit logging enabled to generate events.\n");
|
|
127
|
-
process.exit(0);
|
|
128
|
-
}
|
|
129
|
-
if (args.last) {
|
|
130
|
-
const n = parseInt(args.last, 10);
|
|
131
|
-
if (n > 0 && n < events.length) {
|
|
132
|
-
events = events.slice(-n);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
if (args.summary) {
|
|
136
|
-
if (args.json) {
|
|
137
|
-
process.stdout.write(JSON.stringify(summarizeAuditEvents(events), null, 2) + "\n");
|
|
138
|
-
} else {
|
|
139
|
-
process.stdout.write(formatSummary(events) + "\n");
|
|
140
|
-
}
|
|
141
|
-
process.exit(0);
|
|
142
|
-
}
|
|
143
|
-
if (args.json) {
|
|
144
|
-
process.stdout.write(JSON.stringify(events, null, 2) + "\n");
|
|
145
|
-
process.exit(0);
|
|
146
|
-
}
|
|
147
|
-
process.stdout.write("ACTION TRACE\n");
|
|
148
|
-
process.stdout.write("\u2500".repeat(40) + "\n");
|
|
149
|
-
for (const event of events) {
|
|
150
|
-
process.stdout.write("\n" + formatEvent(event) + "\n");
|
|
151
|
-
}
|
|
152
|
-
process.stdout.write("\n");
|
|
153
|
-
process.stdout.write(`Total: ${events.length} events`);
|
|
154
|
-
const blocked = events.filter((e) => e.decision === "BLOCK").length;
|
|
155
|
-
const paused = events.filter((e) => e.decision === "PAUSE").length;
|
|
156
|
-
if (blocked > 0 || paused > 0) {
|
|
157
|
-
const parts = [];
|
|
158
|
-
if (blocked > 0) parts.push(`${blocked} blocked`);
|
|
159
|
-
if (paused > 0) parts.push(`${paused} paused`);
|
|
160
|
-
process.stdout.write(` (${parts.join(", ")})`);
|
|
161
|
-
}
|
|
162
|
-
process.stdout.write("\n");
|
|
163
|
-
}
|
|
164
|
-
export {
|
|
165
|
-
main
|
|
166
|
-
};
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
VALIDATE_EXIT_CODES
|
|
3
|
-
} from "./chunk-I3RRAYK2.js";
|
|
4
|
-
import {
|
|
5
|
-
validateWorld
|
|
6
|
-
} from "./chunk-7P3S7MAY.js";
|
|
7
|
-
import {
|
|
8
|
-
loadWorld
|
|
9
|
-
} from "./chunk-JZPQGIKR.js";
|
|
10
|
-
import "./chunk-YZFATT7X.js";
|
|
11
|
-
|
|
12
|
-
// src/cli/validate.ts
|
|
13
|
-
function parseArgs(argv) {
|
|
14
|
-
let worldPath = "";
|
|
15
|
-
let format = "full";
|
|
16
|
-
let mode = "standard";
|
|
17
|
-
for (let i = 0; i < argv.length; i++) {
|
|
18
|
-
const arg = argv[i];
|
|
19
|
-
if (arg === "--world" && i + 1 < argv.length) {
|
|
20
|
-
worldPath = argv[++i];
|
|
21
|
-
} else if (arg === "--format" && i + 1 < argv.length) {
|
|
22
|
-
const val = argv[++i];
|
|
23
|
-
if (val === "full" || val === "summary" || val === "findings") {
|
|
24
|
-
format = val;
|
|
25
|
-
} else {
|
|
26
|
-
throw new Error(`Invalid format: "${val}". Must be full, summary, or findings.`);
|
|
27
|
-
}
|
|
28
|
-
} else if (arg === "--mode" && i + 1 < argv.length) {
|
|
29
|
-
const val = argv[++i];
|
|
30
|
-
if (val === "dev" || val === "standard" || val === "strict") {
|
|
31
|
-
mode = val;
|
|
32
|
-
} else {
|
|
33
|
-
throw new Error(`Invalid mode: "${val}". Must be dev, standard, or strict.`);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
if (!worldPath) {
|
|
38
|
-
throw new Error("--world <path> is required");
|
|
39
|
-
}
|
|
40
|
-
return { worldPath, format, mode };
|
|
41
|
-
}
|
|
42
|
-
function formatOutput(report, format) {
|
|
43
|
-
if (format === "summary") {
|
|
44
|
-
return JSON.stringify({
|
|
45
|
-
worldName: report.worldName,
|
|
46
|
-
worldVersion: report.worldVersion,
|
|
47
|
-
summary: report.summary
|
|
48
|
-
}, null, 2);
|
|
49
|
-
}
|
|
50
|
-
if (format === "findings") {
|
|
51
|
-
return JSON.stringify({
|
|
52
|
-
worldName: report.worldName,
|
|
53
|
-
findings: report.findings
|
|
54
|
-
}, null, 2);
|
|
55
|
-
}
|
|
56
|
-
return JSON.stringify(report, null, 2);
|
|
57
|
-
}
|
|
58
|
-
async function main(argv = process.argv.slice(2)) {
|
|
59
|
-
try {
|
|
60
|
-
const args = parseArgs(argv);
|
|
61
|
-
const world = await loadWorld(args.worldPath);
|
|
62
|
-
const report = validateWorld(world, args.mode);
|
|
63
|
-
process.stdout.write(formatOutput(report, args.format) + "\n");
|
|
64
|
-
let exitCode;
|
|
65
|
-
if (report.summary.errors > 0) {
|
|
66
|
-
exitCode = VALIDATE_EXIT_CODES.FAIL;
|
|
67
|
-
} else if (report.summary.warnings > 0) {
|
|
68
|
-
exitCode = VALIDATE_EXIT_CODES.WARN;
|
|
69
|
-
} else {
|
|
70
|
-
exitCode = VALIDATE_EXIT_CODES.PASS;
|
|
71
|
-
}
|
|
72
|
-
process.exit(exitCode);
|
|
73
|
-
} catch (e) {
|
|
74
|
-
const errorResult = { error: "Validation failed", detail: String(e) };
|
|
75
|
-
process.stderr.write(JSON.stringify(errorResult, null, 2) + "\n");
|
|
76
|
-
process.exit(VALIDATE_EXIT_CODES.ERROR);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
export {
|
|
80
|
-
main
|
|
81
|
-
};
|
package/dist/world-LAXO6DOX.js
DELETED
|
@@ -1,378 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
describeActiveWorld,
|
|
3
|
-
getActiveWorldName,
|
|
4
|
-
listWorlds,
|
|
5
|
-
resolveWorldPath,
|
|
6
|
-
setActiveWorld
|
|
7
|
-
} from "./chunk-AKW5YVCE.js";
|
|
8
|
-
import {
|
|
9
|
-
validateWorld
|
|
10
|
-
} from "./chunk-7P3S7MAY.js";
|
|
11
|
-
import {
|
|
12
|
-
loadWorld
|
|
13
|
-
} from "./chunk-JZPQGIKR.js";
|
|
14
|
-
import "./chunk-YZFATT7X.js";
|
|
15
|
-
|
|
16
|
-
// src/cli/world.ts
|
|
17
|
-
var USAGE = `
|
|
18
|
-
neuroverse world \u2014 World management
|
|
19
|
-
|
|
20
|
-
Usage:
|
|
21
|
-
neuroverse world list List available worlds
|
|
22
|
-
neuroverse world use <name> Set the active world
|
|
23
|
-
neuroverse world current Show which world is active and why
|
|
24
|
-
neuroverse world status [path|name] Show world identity and health
|
|
25
|
-
neuroverse world diff <path1> <path2> Compare two world versions
|
|
26
|
-
neuroverse world snapshot <path> Save a timestamped snapshot
|
|
27
|
-
neuroverse world rollback <path> Restore the previous snapshot
|
|
28
|
-
|
|
29
|
-
Environment:
|
|
30
|
-
NEUROVERSE_WORLD=<name> Override active world (for CI/agents)
|
|
31
|
-
|
|
32
|
-
Options:
|
|
33
|
-
--json Output as JSON
|
|
34
|
-
`.trim();
|
|
35
|
-
function parseArgs(argv) {
|
|
36
|
-
const subcommand = argv[0];
|
|
37
|
-
const paths = [];
|
|
38
|
-
const flags = {};
|
|
39
|
-
for (let i = 1; i < argv.length; i++) {
|
|
40
|
-
const arg = argv[i];
|
|
41
|
-
if (arg === "--json") flags.json = true;
|
|
42
|
-
else if (arg === "--help" || arg === "-h") flags.help = true;
|
|
43
|
-
else paths.push(arg);
|
|
44
|
-
}
|
|
45
|
-
return { subcommand, paths, flags };
|
|
46
|
-
}
|
|
47
|
-
async function worldStatus(worldPath, json) {
|
|
48
|
-
const world = await loadWorld(worldPath);
|
|
49
|
-
const report = validateWorld(world);
|
|
50
|
-
if (json) {
|
|
51
|
-
process.stdout.write(JSON.stringify({
|
|
52
|
-
world: world.world,
|
|
53
|
-
metadata: world.metadata,
|
|
54
|
-
guards: world.guards?.guards.length ?? 0,
|
|
55
|
-
invariants: world.invariants.length,
|
|
56
|
-
rules: world.rules.length,
|
|
57
|
-
roles: world.roles?.roles.length ?? 0,
|
|
58
|
-
kernel: world.kernel ? {
|
|
59
|
-
allowedInputs: world.kernel.allowed_inputs?.length ?? 0,
|
|
60
|
-
forbiddenInputs: world.kernel.forbidden_inputs?.length ?? 0,
|
|
61
|
-
allowedOutputs: world.kernel.allowed_outputs?.length ?? 0,
|
|
62
|
-
forbiddenOutputs: world.kernel.forbidden_outputs?.length ?? 0
|
|
63
|
-
} : null,
|
|
64
|
-
validation: report.summary
|
|
65
|
-
}, null, 2) + "\n");
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
const lines = [];
|
|
69
|
-
lines.push("WORLD STATUS");
|
|
70
|
-
lines.push("\u2500".repeat(40));
|
|
71
|
-
lines.push(` Name: ${world.world.name}`);
|
|
72
|
-
lines.push(` ID: ${world.world.id}`);
|
|
73
|
-
lines.push(` Version: ${world.world.version}`);
|
|
74
|
-
lines.push(` Created: ${world.metadata.created_at || "\u2014"}`);
|
|
75
|
-
lines.push(` Modified: ${world.metadata.last_modified || "\u2014"}`);
|
|
76
|
-
lines.push(` Authoring: ${world.metadata.authoring_method}`);
|
|
77
|
-
lines.push("");
|
|
78
|
-
lines.push("COMPONENTS");
|
|
79
|
-
lines.push("\u2500".repeat(40));
|
|
80
|
-
lines.push(` Invariants: ${world.invariants.length}`);
|
|
81
|
-
lines.push(` Guards: ${world.guards?.guards.length ?? 0}`);
|
|
82
|
-
lines.push(` Rules: ${world.rules.length}`);
|
|
83
|
-
lines.push(` Roles: ${world.roles?.roles.length ?? 0}`);
|
|
84
|
-
if (world.kernel) {
|
|
85
|
-
const k = world.kernel;
|
|
86
|
-
const totalRules = (k.allowed_inputs?.length ?? 0) + (k.forbidden_inputs?.length ?? 0) + (k.allowed_outputs?.length ?? 0) + (k.forbidden_outputs?.length ?? 0);
|
|
87
|
-
lines.push(` Kernel: ${totalRules} rules`);
|
|
88
|
-
}
|
|
89
|
-
lines.push("");
|
|
90
|
-
lines.push("HEALTH");
|
|
91
|
-
lines.push("\u2500".repeat(40));
|
|
92
|
-
const sev = report.summary;
|
|
93
|
-
const healthIcon = sev.errors === 0 && sev.warnings === 0 ? "HEALTHY" : sev.errors > 0 ? "ISSUES FOUND" : "WARNINGS";
|
|
94
|
-
lines.push(` Status: ${healthIcon}`);
|
|
95
|
-
lines.push(` Errors: ${sev.errors}`);
|
|
96
|
-
lines.push(` Warnings: ${sev.warnings}`);
|
|
97
|
-
lines.push(` Info: ${sev.info}`);
|
|
98
|
-
if (report.findings.length > 0) {
|
|
99
|
-
lines.push("");
|
|
100
|
-
lines.push(" Top findings:");
|
|
101
|
-
for (const f of report.findings.slice(0, 5)) {
|
|
102
|
-
const icon = f.severity === "error" ? "!" : f.severity === "warning" ? "?" : "-";
|
|
103
|
-
lines.push(` [${icon}] ${f.message}`);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
process.stdout.write(lines.join("\n") + "\n");
|
|
107
|
-
}
|
|
108
|
-
async function worldDiff(path1, path2, json) {
|
|
109
|
-
const world1 = await loadWorld(path1);
|
|
110
|
-
const world2 = await loadWorld(path2);
|
|
111
|
-
const diff = computeWorldDiff(world1, world2);
|
|
112
|
-
if (json) {
|
|
113
|
-
process.stdout.write(JSON.stringify(diff, null, 2) + "\n");
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
const lines = [];
|
|
117
|
-
lines.push("WORLD DIFF");
|
|
118
|
-
lines.push("\u2550".repeat(50));
|
|
119
|
-
lines.push(` A: ${world1.world.name} v${world1.world.version}`);
|
|
120
|
-
lines.push(` B: ${world2.world.name} v${world2.world.version}`);
|
|
121
|
-
lines.push("");
|
|
122
|
-
for (const change of diff.changes) {
|
|
123
|
-
const icon = change.type === "added" ? "+" : change.type === "removed" ? "-" : "~";
|
|
124
|
-
lines.push(` [${icon}] ${change.component}: ${change.description}`);
|
|
125
|
-
}
|
|
126
|
-
if (diff.changes.length === 0) {
|
|
127
|
-
lines.push(" No differences found.");
|
|
128
|
-
}
|
|
129
|
-
process.stdout.write(lines.join("\n") + "\n");
|
|
130
|
-
}
|
|
131
|
-
function computeWorldDiff(a, b) {
|
|
132
|
-
const changes = [];
|
|
133
|
-
if (a.world.version !== b.world.version) {
|
|
134
|
-
changes.push({ type: "changed", component: "version", description: `${a.world.version} \u2192 ${b.world.version}` });
|
|
135
|
-
}
|
|
136
|
-
const aInvIds = new Set(a.invariants.map((i) => i.id));
|
|
137
|
-
const bInvIds = new Set(b.invariants.map((i) => i.id));
|
|
138
|
-
for (const id of bInvIds) {
|
|
139
|
-
if (!aInvIds.has(id)) changes.push({ type: "added", component: "invariant", description: id });
|
|
140
|
-
}
|
|
141
|
-
for (const id of aInvIds) {
|
|
142
|
-
if (!bInvIds.has(id)) changes.push({ type: "removed", component: "invariant", description: id });
|
|
143
|
-
}
|
|
144
|
-
const aGuardIds = new Set((a.guards?.guards ?? []).map((g) => g.id));
|
|
145
|
-
const bGuardIds = new Set((b.guards?.guards ?? []).map((g) => g.id));
|
|
146
|
-
for (const id of bGuardIds) {
|
|
147
|
-
if (!aGuardIds.has(id)) changes.push({ type: "added", component: "guard", description: id });
|
|
148
|
-
}
|
|
149
|
-
for (const id of aGuardIds) {
|
|
150
|
-
if (!bGuardIds.has(id)) changes.push({ type: "removed", component: "guard", description: id });
|
|
151
|
-
}
|
|
152
|
-
const aRuleIds = new Set(a.rules.map((r) => r.id));
|
|
153
|
-
const bRuleIds = new Set(b.rules.map((r) => r.id));
|
|
154
|
-
for (const id of bRuleIds) {
|
|
155
|
-
if (!aRuleIds.has(id)) changes.push({ type: "added", component: "rule", description: id });
|
|
156
|
-
}
|
|
157
|
-
for (const id of aRuleIds) {
|
|
158
|
-
if (!bRuleIds.has(id)) changes.push({ type: "removed", component: "rule", description: id });
|
|
159
|
-
}
|
|
160
|
-
const aRoleIds = new Set((a.roles?.roles ?? []).map((r) => r.id));
|
|
161
|
-
const bRoleIds = new Set((b.roles?.roles ?? []).map((r) => r.id));
|
|
162
|
-
for (const id of bRoleIds) {
|
|
163
|
-
if (!aRoleIds.has(id)) changes.push({ type: "added", component: "role", description: id });
|
|
164
|
-
}
|
|
165
|
-
for (const id of aRoleIds) {
|
|
166
|
-
if (!bRoleIds.has(id)) changes.push({ type: "removed", component: "role", description: id });
|
|
167
|
-
}
|
|
168
|
-
const aGuardCount = a.guards?.guards.length ?? 0;
|
|
169
|
-
const bGuardCount = b.guards?.guards.length ?? 0;
|
|
170
|
-
if (aGuardCount !== bGuardCount && changes.filter((c) => c.component === "guard").length === 0) {
|
|
171
|
-
changes.push({ type: "changed", component: "guards", description: `${aGuardCount} \u2192 ${bGuardCount}` });
|
|
172
|
-
}
|
|
173
|
-
return { changes };
|
|
174
|
-
}
|
|
175
|
-
async function worldSnapshot(worldPath) {
|
|
176
|
-
const { readdir, readFile, mkdir, writeFile } = await import("fs/promises");
|
|
177
|
-
const { join } = await import("path");
|
|
178
|
-
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
179
|
-
const snapshotDir = join(worldPath, ".snapshots", timestamp);
|
|
180
|
-
await mkdir(snapshotDir, { recursive: true });
|
|
181
|
-
const files = await readdir(worldPath);
|
|
182
|
-
let copied = 0;
|
|
183
|
-
for (const file of files) {
|
|
184
|
-
if (file.endsWith(".json")) {
|
|
185
|
-
const content = await readFile(join(worldPath, file), "utf-8");
|
|
186
|
-
await writeFile(join(snapshotDir, file), content, "utf-8");
|
|
187
|
-
copied++;
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
try {
|
|
191
|
-
const rulesDir = join(worldPath, "rules");
|
|
192
|
-
const ruleFiles = await readdir(rulesDir);
|
|
193
|
-
await mkdir(join(snapshotDir, "rules"), { recursive: true });
|
|
194
|
-
for (const file of ruleFiles) {
|
|
195
|
-
if (file.endsWith(".json")) {
|
|
196
|
-
const content = await readFile(join(rulesDir, file), "utf-8");
|
|
197
|
-
await writeFile(join(snapshotDir, "rules", file), content, "utf-8");
|
|
198
|
-
copied++;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
} catch {
|
|
202
|
-
}
|
|
203
|
-
process.stdout.write(`Snapshot saved: ${snapshotDir}
|
|
204
|
-
`);
|
|
205
|
-
process.stdout.write(`Files: ${copied}
|
|
206
|
-
`);
|
|
207
|
-
}
|
|
208
|
-
async function worldRollback(worldPath) {
|
|
209
|
-
const { readdir, readFile, writeFile, mkdir } = await import("fs/promises");
|
|
210
|
-
const { join } = await import("path");
|
|
211
|
-
const snapshotsDir = join(worldPath, ".snapshots");
|
|
212
|
-
let snapshots;
|
|
213
|
-
try {
|
|
214
|
-
snapshots = (await readdir(snapshotsDir)).sort();
|
|
215
|
-
} catch {
|
|
216
|
-
process.stderr.write("No snapshots found. Run `neuroverse world snapshot` first.\n");
|
|
217
|
-
process.exit(1);
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
|
-
if (snapshots.length === 0) {
|
|
221
|
-
process.stderr.write("No snapshots found. Run `neuroverse world snapshot` first.\n");
|
|
222
|
-
process.exit(1);
|
|
223
|
-
return;
|
|
224
|
-
}
|
|
225
|
-
const latest = snapshots[snapshots.length - 1];
|
|
226
|
-
const snapshotDir = join(snapshotsDir, latest);
|
|
227
|
-
const backupTimestamp = "pre-rollback-" + (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
228
|
-
const backupDir = join(snapshotsDir, backupTimestamp);
|
|
229
|
-
await mkdir(backupDir, { recursive: true });
|
|
230
|
-
const currentFiles = await readdir(worldPath);
|
|
231
|
-
for (const file of currentFiles) {
|
|
232
|
-
if (file.endsWith(".json")) {
|
|
233
|
-
const content = await readFile(join(worldPath, file), "utf-8");
|
|
234
|
-
await writeFile(join(backupDir, file), content, "utf-8");
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
const snapshotFiles = await readdir(snapshotDir);
|
|
238
|
-
let restored = 0;
|
|
239
|
-
for (const file of snapshotFiles) {
|
|
240
|
-
if (file.endsWith(".json")) {
|
|
241
|
-
const content = await readFile(join(snapshotDir, file), "utf-8");
|
|
242
|
-
await writeFile(join(worldPath, file), content, "utf-8");
|
|
243
|
-
restored++;
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
try {
|
|
247
|
-
const rulesDir = join(snapshotDir, "rules");
|
|
248
|
-
const ruleFiles = await readdir(rulesDir);
|
|
249
|
-
await mkdir(join(worldPath, "rules"), { recursive: true });
|
|
250
|
-
for (const file of ruleFiles) {
|
|
251
|
-
if (file.endsWith(".json")) {
|
|
252
|
-
const content = await readFile(join(rulesDir, file), "utf-8");
|
|
253
|
-
await writeFile(join(worldPath, "rules", file), content, "utf-8");
|
|
254
|
-
restored++;
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
} catch {
|
|
258
|
-
}
|
|
259
|
-
process.stdout.write(`Rolled back to: ${latest}
|
|
260
|
-
`);
|
|
261
|
-
process.stdout.write(`Restored: ${restored} files
|
|
262
|
-
`);
|
|
263
|
-
process.stdout.write(`Backup saved: ${backupDir}
|
|
264
|
-
`);
|
|
265
|
-
}
|
|
266
|
-
function worldList(json) {
|
|
267
|
-
const worlds = listWorlds();
|
|
268
|
-
if (json) {
|
|
269
|
-
process.stdout.write(JSON.stringify({ worlds, activeWorld: getActiveWorldName() }, null, 2) + "\n");
|
|
270
|
-
return;
|
|
271
|
-
}
|
|
272
|
-
if (worlds.length === 0) {
|
|
273
|
-
process.stdout.write("No worlds found.\n");
|
|
274
|
-
process.stdout.write("Run `neuroverse build <input.md>` to create one.\n");
|
|
275
|
-
return;
|
|
276
|
-
}
|
|
277
|
-
const lines = [];
|
|
278
|
-
lines.push("AVAILABLE WORLDS");
|
|
279
|
-
lines.push("\u2500".repeat(40));
|
|
280
|
-
for (const w of worlds) {
|
|
281
|
-
const marker = w.active ? "\u2192" : " ";
|
|
282
|
-
const activeLabel = w.active ? " (active)" : "";
|
|
283
|
-
lines.push(` ${marker} ${w.name}${activeLabel}`);
|
|
284
|
-
}
|
|
285
|
-
const envWorld = process.env.NEUROVERSE_WORLD;
|
|
286
|
-
if (envWorld) {
|
|
287
|
-
lines.push("");
|
|
288
|
-
lines.push(` env: NEUROVERSE_WORLD=${envWorld}`);
|
|
289
|
-
}
|
|
290
|
-
lines.push("");
|
|
291
|
-
lines.push("Switch: neuroverse world use <name>");
|
|
292
|
-
process.stdout.write(lines.join("\n") + "\n");
|
|
293
|
-
}
|
|
294
|
-
function worldUse(name) {
|
|
295
|
-
setActiveWorld(name);
|
|
296
|
-
process.stdout.write(`Active world: ${name}
|
|
297
|
-
`);
|
|
298
|
-
}
|
|
299
|
-
function worldCurrent(json) {
|
|
300
|
-
const info = describeActiveWorld();
|
|
301
|
-
if (json) {
|
|
302
|
-
process.stdout.write(JSON.stringify(info ?? { name: null, source: null }, null, 2) + "\n");
|
|
303
|
-
return;
|
|
304
|
-
}
|
|
305
|
-
if (!info) {
|
|
306
|
-
process.stdout.write("No active world.\n");
|
|
307
|
-
process.stdout.write("Set one with: neuroverse world use <name>\n");
|
|
308
|
-
return;
|
|
309
|
-
}
|
|
310
|
-
process.stdout.write(`Active world: ${info.name}
|
|
311
|
-
`);
|
|
312
|
-
process.stdout.write(`Source: ${info.source}
|
|
313
|
-
`);
|
|
314
|
-
}
|
|
315
|
-
async function main(argv = process.argv.slice(2)) {
|
|
316
|
-
const { subcommand, paths, flags } = parseArgs(argv);
|
|
317
|
-
if (flags.help || !subcommand) {
|
|
318
|
-
process.stdout.write(USAGE + "\n");
|
|
319
|
-
process.exit(0);
|
|
320
|
-
}
|
|
321
|
-
switch (subcommand) {
|
|
322
|
-
case "list":
|
|
323
|
-
case "ls": {
|
|
324
|
-
return worldList(!!flags.json);
|
|
325
|
-
}
|
|
326
|
-
case "use": {
|
|
327
|
-
if (!paths[0]) {
|
|
328
|
-
process.stderr.write("Usage: neuroverse world use <name>\n");
|
|
329
|
-
process.exit(1);
|
|
330
|
-
}
|
|
331
|
-
return worldUse(paths[0]);
|
|
332
|
-
}
|
|
333
|
-
case "current": {
|
|
334
|
-
return worldCurrent(!!flags.json);
|
|
335
|
-
}
|
|
336
|
-
case "status": {
|
|
337
|
-
const ref = paths[0];
|
|
338
|
-
const resolved = ref ? resolveWorldPath(ref) : resolveWorldPath();
|
|
339
|
-
if (!resolved) {
|
|
340
|
-
process.stderr.write("Usage: neuroverse world status <path|name>\n");
|
|
341
|
-
process.stderr.write("Or set an active world: neuroverse world use <name>\n");
|
|
342
|
-
process.exit(1);
|
|
343
|
-
}
|
|
344
|
-
return worldStatus(resolved, !!flags.json);
|
|
345
|
-
}
|
|
346
|
-
case "diff": {
|
|
347
|
-
if (!paths[0] || !paths[1]) {
|
|
348
|
-
process.stderr.write("Usage: neuroverse world diff <path1> <path2>\n");
|
|
349
|
-
process.exit(1);
|
|
350
|
-
}
|
|
351
|
-
return worldDiff(paths[0], paths[1], !!flags.json);
|
|
352
|
-
}
|
|
353
|
-
case "snapshot": {
|
|
354
|
-
if (!paths[0]) {
|
|
355
|
-
process.stderr.write("Usage: neuroverse world snapshot <path>\n");
|
|
356
|
-
process.exit(1);
|
|
357
|
-
}
|
|
358
|
-
return worldSnapshot(paths[0]);
|
|
359
|
-
}
|
|
360
|
-
case "rollback": {
|
|
361
|
-
if (!paths[0]) {
|
|
362
|
-
process.stderr.write("Usage: neuroverse world rollback <path>\n");
|
|
363
|
-
process.exit(1);
|
|
364
|
-
}
|
|
365
|
-
return worldRollback(paths[0]);
|
|
366
|
-
}
|
|
367
|
-
default: {
|
|
368
|
-
process.stderr.write(`Unknown world subcommand: "${subcommand}"
|
|
369
|
-
|
|
370
|
-
`);
|
|
371
|
-
process.stdout.write(USAGE + "\n");
|
|
372
|
-
process.exit(1);
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
export {
|
|
377
|
-
main
|
|
378
|
-
};
|