@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.
Files changed (105) hide show
  1. package/README.md +20 -0
  2. package/package.json +16 -3
  3. package/policies/content-moderation-rules.txt +8 -0
  4. package/policies/marketing-rules.txt +8 -0
  5. package/policies/science-research-rules.txt +11 -0
  6. package/policies/social-media-rules.txt +7 -0
  7. package/policies/strict-rules.txt +8 -0
  8. package/policies/trading-rules.txt +8 -0
  9. package/simulate.html +1899 -0
  10. package/dist/adapters/autoresearch.cjs +0 -196
  11. package/dist/adapters/autoresearch.d.cts +0 -103
  12. package/dist/adapters/autoresearch.d.ts +0 -103
  13. package/dist/adapters/autoresearch.js +0 -7
  14. package/dist/adapters/express.cjs +0 -1114
  15. package/dist/adapters/express.d.cts +0 -66
  16. package/dist/adapters/express.d.ts +0 -66
  17. package/dist/adapters/express.js +0 -12
  18. package/dist/adapters/index.cjs +0 -1669
  19. package/dist/adapters/index.d.cts +0 -6
  20. package/dist/adapters/index.d.ts +0 -6
  21. package/dist/adapters/index.js +0 -46
  22. package/dist/adapters/langchain.cjs +0 -1155
  23. package/dist/adapters/langchain.d.cts +0 -89
  24. package/dist/adapters/langchain.d.ts +0 -89
  25. package/dist/adapters/langchain.js +0 -16
  26. package/dist/adapters/openai.cjs +0 -1185
  27. package/dist/adapters/openai.d.cts +0 -99
  28. package/dist/adapters/openai.d.ts +0 -99
  29. package/dist/adapters/openai.js +0 -16
  30. package/dist/adapters/openclaw.cjs +0 -1177
  31. package/dist/adapters/openclaw.d.cts +0 -99
  32. package/dist/adapters/openclaw.d.ts +0 -99
  33. package/dist/adapters/openclaw.js +0 -16
  34. package/dist/bootstrap-GXVDZNF7.js +0 -114
  35. package/dist/build-P42YFKQV.js +0 -339
  36. package/dist/chunk-2NICNKOM.js +0 -100
  37. package/dist/chunk-2PQU3VAN.js +0 -131
  38. package/dist/chunk-4A7LISES.js +0 -324
  39. package/dist/chunk-4JRYGIO7.js +0 -727
  40. package/dist/chunk-4NGDRRQH.js +0 -10
  41. package/dist/chunk-4QXB6PEO.js +0 -232
  42. package/dist/chunk-6CZSKEY5.js +0 -164
  43. package/dist/chunk-7P3S7MAY.js +0 -1090
  44. package/dist/chunk-A5W4GNQO.js +0 -130
  45. package/dist/chunk-AKW5YVCE.js +0 -96
  46. package/dist/chunk-BUWWN2NX.js +0 -192
  47. package/dist/chunk-COT5XS4V.js +0 -109
  48. package/dist/chunk-ER62HNGF.js +0 -139
  49. package/dist/chunk-FYS2CBUW.js +0 -304
  50. package/dist/chunk-GR6DGCZ2.js +0 -340
  51. package/dist/chunk-I3RRAYK2.js +0 -11
  52. package/dist/chunk-JZPQGIKR.js +0 -79
  53. package/dist/chunk-MWDQ4MJB.js +0 -11
  54. package/dist/chunk-NF5POFCI.js +0 -622
  55. package/dist/chunk-OGL7QXZS.js +0 -608
  56. package/dist/chunk-OT6PXH54.js +0 -61
  57. package/dist/chunk-PDOZHZWL.js +0 -225
  58. package/dist/chunk-Q6O7ZLO2.js +0 -62
  59. package/dist/chunk-QPASI2BR.js +0 -187
  60. package/dist/chunk-T5EUJQE5.js +0 -172
  61. package/dist/chunk-XPDMYECO.js +0 -642
  62. package/dist/chunk-YZFATT7X.js +0 -9
  63. package/dist/cli/neuroverse.cjs +0 -11448
  64. package/dist/cli/neuroverse.d.cts +0 -1
  65. package/dist/cli/neuroverse.d.ts +0 -1
  66. package/dist/cli/neuroverse.js +0 -196
  67. package/dist/cli/plan.cjs +0 -1599
  68. package/dist/cli/plan.d.cts +0 -20
  69. package/dist/cli/plan.d.ts +0 -20
  70. package/dist/cli/plan.js +0 -361
  71. package/dist/cli/run.cjs +0 -1746
  72. package/dist/cli/run.d.cts +0 -20
  73. package/dist/cli/run.d.ts +0 -20
  74. package/dist/cli/run.js +0 -143
  75. package/dist/configure-ai-TK67ZWZL.js +0 -132
  76. package/dist/derive-TLIV4OOU.js +0 -152
  77. package/dist/doctor-XPDLEYXN.js +0 -171
  78. package/dist/explain-IDCRWMPX.js +0 -70
  79. package/dist/guard-RV65TT4L.js +0 -96
  80. package/dist/guard-contract-WZx__PmU.d.cts +0 -709
  81. package/dist/guard-contract-WZx__PmU.d.ts +0 -709
  82. package/dist/guard-engine-JLTUARGU.js +0 -10
  83. package/dist/impact-XPECYRLH.js +0 -59
  84. package/dist/improve-GPUBKTEA.js +0 -85
  85. package/dist/index.cjs +0 -6273
  86. package/dist/index.d.cts +0 -1616
  87. package/dist/index.d.ts +0 -1616
  88. package/dist/index.js +0 -379
  89. package/dist/infer-world-7GVZWFX4.js +0 -543
  90. package/dist/init-PKPIYHYE.js +0 -144
  91. package/dist/init-world-VWMQZQC7.js +0 -223
  92. package/dist/mcp-server-FPVSU32Z.js +0 -13
  93. package/dist/model-adapter-BB7G4MFI.js +0 -11
  94. package/dist/playground-E664U4T6.js +0 -550
  95. package/dist/redteam-Z7WREJ44.js +0 -357
  96. package/dist/session-EKTRSR7C.js +0 -14
  97. package/dist/simulate-VDOYQFRO.js +0 -108
  98. package/dist/test-OGXJK4QU.js +0 -217
  99. package/dist/trace-JVF67VR3.js +0 -166
  100. package/dist/validate-LLBWVPGV.js +0 -81
  101. package/dist/validate-engine-UIABSIHD.js +0 -7
  102. package/dist/world-LAXO6DOX.js +0 -378
  103. package/dist/world-loader-HMPTOEA2.js +0 -9
  104. package/dist/worlds/autoresearch.nv-world.md +0 -230
  105. package/dist/worlds/derivation-world.nv-world.md +0 -278
@@ -1,225 +0,0 @@
1
- import {
2
- readAuditLog
3
- } from "./chunk-QPASI2BR.js";
4
-
5
- // src/engine/impact-report.ts
6
- function generateImpactReport(events) {
7
- if (events.length === 0) {
8
- return emptyReport();
9
- }
10
- const blocked = events.filter((e) => e.decision === "BLOCK");
11
- const paused = events.filter((e) => e.decision === "PAUSE");
12
- const prevented = [...blocked, ...paused];
13
- const categoryMap = /* @__PURE__ */ new Map();
14
- for (const e of prevented) {
15
- const cat = classifyPreventionCategory(e);
16
- if (!categoryMap.has(cat)) categoryMap.set(cat, /* @__PURE__ */ new Set());
17
- categoryMap.get(cat).add(e.intent);
18
- }
19
- const preventedByCategory = [...categoryMap.entries()].map(([category, intents]) => ({
20
- category,
21
- count: prevented.filter((e) => classifyPreventionCategory(e) === category).length,
22
- examples: [...intents].slice(0, 5)
23
- })).sort((a, b) => b.count - a.count);
24
- const intentMap = /* @__PURE__ */ new Map();
25
- for (const e of prevented) {
26
- const entry = intentMap.get(e.intent) ?? { count: 0, rules: /* @__PURE__ */ new Map() };
27
- entry.count++;
28
- if (e.ruleId) {
29
- entry.rules.set(e.ruleId, (entry.rules.get(e.ruleId) ?? 0) + 1);
30
- }
31
- for (const g of e.guardsMatched) {
32
- entry.rules.set(g, (entry.rules.get(g) ?? 0) + 1);
33
- }
34
- intentMap.set(e.intent, entry);
35
- }
36
- const topPreventedIntents = [...intentMap.entries()].map(([intent, data]) => {
37
- let topRule = "";
38
- let topCount = 0;
39
- for (const [rule, count] of data.rules) {
40
- if (count > topCount) {
41
- topRule = rule;
42
- topCount = count;
43
- }
44
- }
45
- return { intent, count: data.count, topRule };
46
- }).sort((a, b) => b.count - a.count).slice(0, 15);
47
- const actorMap = /* @__PURE__ */ new Map();
48
- for (const e of events) {
49
- const actor = e.actor ?? "unknown";
50
- const entry = actorMap.get(actor) ?? { blocked: 0, paused: 0, total: 0 };
51
- entry.total++;
52
- if (e.decision === "BLOCK") entry.blocked++;
53
- if (e.decision === "PAUSE") entry.paused++;
54
- actorMap.set(actor, entry);
55
- }
56
- const hotActors = [...actorMap.entries()].filter(([, data]) => data.blocked > 0 || data.paused > 0).map(([actor, data]) => ({ actor, ...data })).sort((a, b) => b.blocked + b.paused - (a.blocked + a.paused)).slice(0, 10);
57
- const ruleMap = /* @__PURE__ */ new Map();
58
- for (const e of prevented) {
59
- const ruleIds = [e.ruleId, ...e.guardsMatched, ...e.rulesMatched].filter(Boolean);
60
- for (const rId of new Set(ruleIds)) {
61
- const entry = ruleMap.get(rId) ?? { blockCount: 0, pauseCount: 0 };
62
- if (e.decision === "BLOCK") entry.blockCount++;
63
- if (e.decision === "PAUSE") entry.pauseCount++;
64
- ruleMap.set(rId, entry);
65
- }
66
- }
67
- const mostActiveRules = [...ruleMap.entries()].map(([ruleId, data]) => ({ ruleId, ...data })).sort((a, b) => b.blockCount + b.pauseCount - (a.blockCount + a.pauseCount)).slice(0, 10);
68
- const hourMap = /* @__PURE__ */ new Map();
69
- for (const e of events) {
70
- const hour = new Date(e.timestamp).getHours();
71
- const entry = hourMap.get(hour) ?? { total: 0, blocked: 0 };
72
- entry.total++;
73
- if (e.decision === "BLOCK") entry.blocked++;
74
- hourMap.set(hour, entry);
75
- }
76
- const hourlyDistribution = Array.from({ length: 24 }, (_, hour) => ({
77
- hour,
78
- total: hourMap.get(hour)?.total ?? 0,
79
- blocked: hourMap.get(hour)?.blocked ?? 0
80
- }));
81
- const violationKey = (e) => `${e.actor ?? "unknown"}::${e.intent}`;
82
- const violationMap = /* @__PURE__ */ new Map();
83
- for (const e of blocked) {
84
- const key = violationKey(e);
85
- const entry = violationMap.get(key) ?? {
86
- intent: e.intent,
87
- actor: e.actor ?? "unknown",
88
- attempts: 0,
89
- firstSeen: e.timestamp,
90
- lastSeen: e.timestamp
91
- };
92
- entry.attempts++;
93
- entry.lastSeen = e.timestamp;
94
- violationMap.set(key, entry);
95
- }
96
- const repeatViolations = [...violationMap.values()].filter((v) => v.attempts > 1).sort((a, b) => b.attempts - a.attempts).slice(0, 10);
97
- return {
98
- generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
99
- periodStart: events[0].timestamp,
100
- periodEnd: events[events.length - 1].timestamp,
101
- worldName: events[0].worldName ?? "unknown",
102
- totalEvaluations: events.length,
103
- totalBlocked: blocked.length,
104
- totalPaused: paused.length,
105
- totalAllowed: events.length - blocked.length - paused.length,
106
- preventionRate: prevented.length / events.length,
107
- preventedByCategory,
108
- topPreventedIntents,
109
- hotActors,
110
- mostActiveRules,
111
- hourlyDistribution,
112
- repeatViolations
113
- };
114
- }
115
- function classifyPreventionCategory(event) {
116
- const intent = event.intent.toLowerCase();
117
- const rule = (event.ruleId ?? "").toLowerCase();
118
- const combined = `${intent} ${rule}`;
119
- if (combined.match(/inject|prompt|jailbreak|bypass/)) return "Prompt Injection Prevention";
120
- if (combined.match(/scope|escape|traversal|path/)) return "Scope Escape Prevention";
121
- if (combined.match(/delete|drop|destroy|remove|purge/)) return "Destructive Action Prevention";
122
- if (combined.match(/trade|margin|position|leverage/)) return "Financial Risk Prevention";
123
- if (combined.match(/withdraw|transfer|payment|fund/)) return "Unauthorized Transfer Prevention";
124
- if (combined.match(/credential|secret|key|password|token/)) return "Credential Access Prevention";
125
- if (combined.match(/shell|exec|command|script/)) return "Command Execution Prevention";
126
- if (combined.match(/network|http|api|external/)) return "Network Access Prevention";
127
- if (combined.match(/write|modify|update|alter/)) return "Unauthorized Modification Prevention";
128
- if (combined.match(/approval|review|confirm/)) return "Approval Gate";
129
- return "Policy Violation Prevention";
130
- }
131
- function renderImpactReport(report) {
132
- const lines = [];
133
- lines.push("GOVERNANCE IMPACT REPORT");
134
- lines.push("\u2550".repeat(50));
135
- lines.push("");
136
- lines.push(` World: ${report.worldName}`);
137
- lines.push(` Period: ${report.periodStart.split("T")[0]} \u2192 ${report.periodEnd.split("T")[0]}`);
138
- lines.push(` Generated: ${report.generatedAt}`);
139
- lines.push("");
140
- lines.push("SUMMARY");
141
- lines.push("\u2500".repeat(50));
142
- lines.push(` Total evaluations: ${report.totalEvaluations}`);
143
- lines.push(` Allowed: ${report.totalAllowed}`);
144
- lines.push(` Blocked: ${report.totalBlocked}`);
145
- lines.push(` Paused: ${report.totalPaused}`);
146
- lines.push(` Prevention rate: ${(report.preventionRate * 100).toFixed(1)}%`);
147
- lines.push("");
148
- if (report.totalBlocked > 0 || report.totalPaused > 0) {
149
- lines.push("WITHOUT GOVERNANCE");
150
- lines.push("\u2500".repeat(50));
151
- lines.push(` ${report.totalBlocked + report.totalPaused} actions would have executed unchecked:`);
152
- for (const cat of report.preventedByCategory) {
153
- lines.push(` ${cat.category.padEnd(38)} ${String(cat.count).padStart(5)}`);
154
- if (cat.examples.length > 0) {
155
- lines.push(` e.g. ${cat.examples.slice(0, 3).join(", ")}`);
156
- }
157
- }
158
- lines.push("");
159
- }
160
- if (report.topPreventedIntents.length > 0) {
161
- lines.push("TOP PREVENTED ACTIONS");
162
- lines.push("\u2500".repeat(50));
163
- for (const entry of report.topPreventedIntents.slice(0, 10)) {
164
- lines.push(` ${entry.intent.padEnd(30)} ${String(entry.count).padStart(5)} (rule: ${entry.topRule || "\u2014"})`);
165
- }
166
- lines.push("");
167
- }
168
- if (report.hotActors.length > 0) {
169
- lines.push("ACTORS WITH MOST VIOLATIONS");
170
- lines.push("\u2500".repeat(50));
171
- for (const actor of report.hotActors) {
172
- const violations = actor.blocked + actor.paused;
173
- const rate = (violations / actor.total * 100).toFixed(0);
174
- lines.push(` ${actor.actor.padEnd(25)} ${String(violations).padStart(5)} violations / ${actor.total} total (${rate}%)`);
175
- }
176
- lines.push("");
177
- }
178
- if (report.mostActiveRules.length > 0) {
179
- lines.push("MOST ACTIVE RULES");
180
- lines.push("\u2500".repeat(50));
181
- for (const rule of report.mostActiveRules) {
182
- lines.push(` ${rule.ruleId.padEnd(30)} ${String(rule.blockCount).padStart(5)} blocked ${String(rule.pauseCount).padStart(5)} paused`);
183
- }
184
- lines.push("");
185
- }
186
- if (report.repeatViolations.length > 0) {
187
- lines.push("REPEAT VIOLATIONS");
188
- lines.push("\u2500".repeat(50));
189
- lines.push(" Actions attempted multiple times after being blocked:");
190
- for (const v of report.repeatViolations) {
191
- lines.push(` ${v.actor.padEnd(20)} ${v.intent.padEnd(25)} ${v.attempts}x (${v.firstSeen.split("T")[0]} \u2192 ${v.lastSeen.split("T")[0]})`);
192
- }
193
- lines.push("");
194
- }
195
- return lines.join("\n");
196
- }
197
- async function generateImpactReportFromFile(logPath) {
198
- const events = await readAuditLog(logPath);
199
- return generateImpactReport(events);
200
- }
201
- function emptyReport() {
202
- return {
203
- generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
204
- periodStart: "",
205
- periodEnd: "",
206
- worldName: "unknown",
207
- totalEvaluations: 0,
208
- totalBlocked: 0,
209
- totalPaused: 0,
210
- totalAllowed: 0,
211
- preventionRate: 0,
212
- preventedByCategory: [],
213
- topPreventedIntents: [],
214
- hotActors: [],
215
- mostActiveRules: [],
216
- hourlyDistribution: [],
217
- repeatViolations: []
218
- };
219
- }
220
-
221
- export {
222
- generateImpactReport,
223
- renderImpactReport,
224
- generateImpactReportFromFile
225
- };
@@ -1,62 +0,0 @@
1
- // src/providers/ai-provider.ts
2
- var ChatCompletionsProvider = class {
3
- model;
4
- apiKey;
5
- endpoint;
6
- constructor(config) {
7
- this.model = config.model;
8
- this.apiKey = config.apiKey;
9
- this.endpoint = config.endpoint ?? "https://api.openai.com/v1/chat/completions";
10
- }
11
- async complete(systemPrompt, userPrompt) {
12
- const body = {
13
- model: this.model,
14
- messages: [
15
- { role: "system", content: systemPrompt },
16
- { role: "user", content: userPrompt }
17
- ],
18
- temperature: 0.2,
19
- max_tokens: 16384
20
- };
21
- const response = await fetch(this.endpoint, {
22
- method: "POST",
23
- headers: {
24
- "Content-Type": "application/json",
25
- "Authorization": `Bearer ${this.apiKey}`
26
- },
27
- body: JSON.stringify(body)
28
- });
29
- if (!response.ok) {
30
- const text = await response.text().catch(() => "");
31
- throw new Error(`Provider returned ${response.status}: ${text.slice(0, 200)}`);
32
- }
33
- const data = await response.json();
34
- const content = data?.choices?.[0]?.message?.content;
35
- if (!content) {
36
- throw new Error("Provider returned empty response \u2014 no content in choices[0].message.content");
37
- }
38
- return content;
39
- }
40
- };
41
- function createProvider(config) {
42
- return new ChatCompletionsProvider(config);
43
- }
44
-
45
- // src/contracts/derive-contract.ts
46
- var DERIVE_EXIT_CODES = {
47
- SUCCESS: 0,
48
- VALIDATION_FAIL: 1,
49
- INPUT_ERROR: 2,
50
- PROVIDER_ERROR: 3
51
- };
52
- var CONFIGURE_AI_EXIT_CODES = {
53
- SUCCESS: 0,
54
- VALIDATION_FAIL: 1,
55
- ERROR: 3
56
- };
57
-
58
- export {
59
- createProvider,
60
- DERIVE_EXIT_CODES,
61
- CONFIGURE_AI_EXIT_CODES
62
- };
@@ -1,187 +0,0 @@
1
- import {
2
- evaluateGuard
3
- } from "./chunk-4JRYGIO7.js";
4
-
5
- // src/engine/audit-logger.ts
6
- var FileAuditLogger = class {
7
- logPath;
8
- buffer = [];
9
- flushTimer = null;
10
- flushIntervalMs;
11
- constructor(logPath, options) {
12
- this.logPath = logPath;
13
- this.flushIntervalMs = options?.flushIntervalMs ?? 1e3;
14
- }
15
- log(event) {
16
- this.buffer.push(JSON.stringify(event));
17
- if (!this.flushTimer) {
18
- this.flushTimer = setTimeout(() => {
19
- void this.flush();
20
- }, this.flushIntervalMs);
21
- }
22
- }
23
- async flush() {
24
- if (this.buffer.length === 0) return;
25
- if (this.flushTimer) {
26
- clearTimeout(this.flushTimer);
27
- this.flushTimer = null;
28
- }
29
- const lines = this.buffer.splice(0).join("\n") + "\n";
30
- try {
31
- const { appendFile, mkdir } = await import("fs/promises");
32
- const { dirname } = await import("path");
33
- await mkdir(dirname(this.logPath), { recursive: true });
34
- await appendFile(this.logPath, lines, "utf-8");
35
- } catch {
36
- }
37
- }
38
- };
39
- var ConsoleAuditLogger = class {
40
- log(event) {
41
- const icon = event.decision === "ALLOW" ? "\u2713" : event.decision === "BLOCK" ? "\u2717" : "\u23F8";
42
- const ts = event.timestamp.split("T")[1]?.replace("Z", "") ?? event.timestamp;
43
- process.stderr.write(
44
- `[${ts}] ${icon} ${event.decision.padEnd(5)} ${event.actor ?? "\u2014"} \u2192 ${event.intent}${event.reason ? ` (${event.reason})` : ""}
45
- `
46
- );
47
- }
48
- };
49
- var CompositeAuditLogger = class {
50
- loggers;
51
- constructor(...loggers) {
52
- this.loggers = loggers;
53
- }
54
- log(event) {
55
- for (const logger of this.loggers) {
56
- try {
57
- logger.log(event);
58
- } catch {
59
- }
60
- }
61
- }
62
- async flush() {
63
- await Promise.all(
64
- this.loggers.map((l) => l.flush?.()).filter(Boolean)
65
- );
66
- }
67
- };
68
- function verdictToAuditEvent(event, verdict) {
69
- return {
70
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
71
- worldId: verdict.evidence.worldId,
72
- worldName: verdict.evidence.worldName,
73
- worldVersion: verdict.evidence.worldVersion,
74
- intent: event.intent,
75
- tool: event.tool,
76
- scope: event.scope,
77
- actor: event.roleId,
78
- direction: event.direction,
79
- decision: verdict.status,
80
- reason: verdict.reason,
81
- ruleId: verdict.ruleId,
82
- warning: verdict.warning,
83
- guardsMatched: verdict.evidence.guardsMatched,
84
- rulesMatched: verdict.evidence.rulesMatched,
85
- invariantsSatisfied: verdict.evidence.invariantsSatisfied,
86
- invariantsTotal: verdict.evidence.invariantsTotal,
87
- enforcementLevel: verdict.evidence.enforcementLevel,
88
- durationMs: verdict.trace?.durationMs,
89
- args: event.args
90
- };
91
- }
92
- function createGovernanceEngine(world, options = {}) {
93
- const { auditLogger, auditArgs, ...engineOptions } = options;
94
- return {
95
- /**
96
- * Evaluate a governance event and log the result.
97
- */
98
- evaluate(event) {
99
- const verdict = evaluateGuard(event, world, engineOptions);
100
- if (auditLogger) {
101
- const auditEvent = verdictToAuditEvent(event, verdict);
102
- if (!auditArgs) {
103
- delete auditEvent.args;
104
- }
105
- auditLogger.log(auditEvent);
106
- }
107
- return verdict;
108
- },
109
- /** Flush the audit logger. */
110
- async flush() {
111
- await auditLogger?.flush?.();
112
- },
113
- /** The underlying world definition. */
114
- world
115
- };
116
- }
117
- async function readAuditLog(logPath, filter) {
118
- const { readFile } = await import("fs/promises");
119
- let content;
120
- try {
121
- content = await readFile(logPath, "utf-8");
122
- } catch {
123
- return [];
124
- }
125
- const events = [];
126
- for (const line of content.split("\n")) {
127
- const trimmed = line.trim();
128
- if (!trimmed) continue;
129
- try {
130
- const event = JSON.parse(trimmed);
131
- if (!filter || filter(event)) {
132
- events.push(event);
133
- }
134
- } catch {
135
- }
136
- }
137
- return events;
138
- }
139
- function summarizeAuditEvents(events) {
140
- const allowed = events.filter((e) => e.decision === "ALLOW").length;
141
- const blocked = events.filter((e) => e.decision === "BLOCK").length;
142
- const paused = events.filter((e) => e.decision === "PAUSE").length;
143
- const actorSet = /* @__PURE__ */ new Set();
144
- for (const e of events) {
145
- if (e.actor) actorSet.add(e.actor);
146
- }
147
- const intentMap = /* @__PURE__ */ new Map();
148
- for (const e of events) {
149
- const entry = intentMap.get(e.intent) ?? { count: 0, blocked: 0, paused: 0 };
150
- entry.count++;
151
- if (e.decision === "BLOCK") entry.blocked++;
152
- if (e.decision === "PAUSE") entry.paused++;
153
- intentMap.set(e.intent, entry);
154
- }
155
- const topIntents = [...intentMap.entries()].map(([intent, data]) => ({ intent, ...data })).sort((a, b) => b.count - a.count);
156
- const ruleMap = /* @__PURE__ */ new Map();
157
- for (const e of events) {
158
- if (e.ruleId) {
159
- ruleMap.set(e.ruleId, (ruleMap.get(e.ruleId) ?? 0) + 1);
160
- }
161
- for (const g of e.guardsMatched) {
162
- ruleMap.set(g, (ruleMap.get(g) ?? 0) + 1);
163
- }
164
- }
165
- const topRules = [...ruleMap.entries()].map(([ruleId, count]) => ({ ruleId, count })).sort((a, b) => b.count - a.count);
166
- return {
167
- totalActions: events.length,
168
- allowed,
169
- blocked,
170
- paused,
171
- actors: [...actorSet],
172
- topIntents,
173
- topRules,
174
- firstEvent: events[0]?.timestamp ?? "",
175
- lastEvent: events[events.length - 1]?.timestamp ?? ""
176
- };
177
- }
178
-
179
- export {
180
- FileAuditLogger,
181
- ConsoleAuditLogger,
182
- CompositeAuditLogger,
183
- verdictToAuditEvent,
184
- createGovernanceEngine,
185
- readAuditLog,
186
- summarizeAuditEvents
187
- };
@@ -1,172 +0,0 @@
1
- // src/adapters/autoresearch.ts
2
- var AutoresearchGovernor = class {
3
- config;
4
- state;
5
- constructor(config) {
6
- this.config = config;
7
- this.state = {
8
- experiments_run: 0,
9
- best_result: null,
10
- architectures_tested: [],
11
- experiment_log: [],
12
- total_compute_minutes: 0,
13
- keep_count: 0
14
- };
15
- }
16
- /**
17
- * Convert an experiment proposal into a GuardEvent for governance evaluation.
18
- */
19
- proposalToGuardEvent(proposal) {
20
- return {
21
- intent: `run experiment: ${proposal.description}`,
22
- tool: "experiment_runner",
23
- scope: "experiment",
24
- roleId: "experiment_runner",
25
- direction: "output",
26
- actionCategory: "shell",
27
- args: {
28
- experiment_id: String(proposal.experiment_id),
29
- architecture: proposal.architecture,
30
- estimated_minutes: String(proposal.estimated_minutes || 5)
31
- }
32
- };
33
- }
34
- /**
35
- * Evaluate an experiment proposal against governance rules.
36
- * Returns a simplified verdict without requiring the full guard engine.
37
- */
38
- evaluateProposal(proposal) {
39
- const warnings = [];
40
- const estimatedMinutes = proposal.estimated_minutes || 5;
41
- if (this.state.total_compute_minutes + estimatedMinutes > this.config.computeBudgetMinutes) {
42
- return {
43
- allowed: false,
44
- reason: `Compute budget exhausted: ${this.state.total_compute_minutes}/${this.config.computeBudgetMinutes} minutes used`,
45
- warnings
46
- };
47
- }
48
- if (this.config.constraints) {
49
- for (const constraint of this.config.constraints) {
50
- const lower = constraint.toLowerCase();
51
- const archLower = proposal.architecture.toLowerCase();
52
- const descLower = proposal.description.toLowerCase();
53
- if (lower.startsWith("no ")) {
54
- const forbidden = lower.slice(3).trim();
55
- if (archLower.includes(forbidden) || descLower.includes(forbidden)) {
56
- return {
57
- allowed: false,
58
- reason: `Architecture constraint violated: ${constraint}`,
59
- warnings
60
- };
61
- }
62
- }
63
- }
64
- }
65
- const failureCount = this.state.experiment_log.filter((e) => !e.success).length;
66
- if (failureCount > 5) {
67
- warnings.push(`High failure rate: ${failureCount} failed experiments. Consider investigating root cause.`);
68
- }
69
- const recentArchitectures = this.state.experiment_log.slice(-5).map((e) => e.architecture);
70
- const uniqueRecent = new Set(recentArchitectures).size;
71
- if (recentArchitectures.length >= 5 && uniqueRecent === 1) {
72
- warnings.push("Research may be stuck: last 5 experiments used the same architecture.");
73
- }
74
- return { allowed: true, reason: "Experiment approved", warnings };
75
- }
76
- /**
77
- * Record an experiment result and update research state.
78
- */
79
- recordResult(result) {
80
- this.state.experiments_run++;
81
- this.state.total_compute_minutes += result.wall_clock_minutes;
82
- this.state.experiment_log.push(result);
83
- if (!this.state.architectures_tested.includes(result.architecture)) {
84
- this.state.architectures_tested.push(result.architecture);
85
- }
86
- if (!result.success) {
87
- return { kept: false, improvement: null, state: { ...this.state } };
88
- }
89
- let kept = false;
90
- let improvement = null;
91
- if (this.state.best_result === null) {
92
- kept = true;
93
- this.state.best_result = result;
94
- this.state.keep_count++;
95
- } else {
96
- const prev = this.state.best_result.metric_value;
97
- const curr = result.metric_value;
98
- if (this.config.optimize === "minimize") {
99
- kept = curr < prev;
100
- improvement = kept ? prev - curr : null;
101
- } else {
102
- kept = curr > prev;
103
- improvement = kept ? curr - prev : null;
104
- }
105
- if (kept) {
106
- this.state.best_result = result;
107
- this.state.keep_count++;
108
- }
109
- }
110
- return { kept, improvement, state: { ...this.state } };
111
- }
112
- /**
113
- * Export current state as a state snapshot compatible with the world file.
114
- */
115
- toWorldState() {
116
- const successfulExperiments = this.state.experiment_log.filter((e) => e.success);
117
- const failedCount = this.state.experiment_log.filter((e) => !e.success).length;
118
- const keepRate = this.state.experiments_run > 0 ? Math.round(this.state.keep_count / this.state.experiments_run * 100) : 0;
119
- let improvementRate = 0;
120
- if (successfulExperiments.length >= 2) {
121
- const recent = successfulExperiments.slice(-10);
122
- let improvements = 0;
123
- for (let i = 1; i < recent.length; i++) {
124
- const prev = recent[i - 1].metric_value;
125
- const curr = recent[i].metric_value;
126
- if (this.config.optimize === "minimize" ? curr < prev : curr > prev) {
127
- improvements++;
128
- }
129
- }
130
- improvementRate = Math.round(improvements / (recent.length - 1) * 100);
131
- }
132
- return {
133
- experiments_run: this.state.experiments_run,
134
- best_metric_value: this.state.best_result?.metric_value ?? (this.config.optimize === "minimize" ? 100 : -1e3),
135
- keep_rate: keepRate,
136
- compute_used_minutes: Math.round(this.state.total_compute_minutes),
137
- compute_budget_minutes: this.config.computeBudgetMinutes,
138
- failed_experiments: failedCount,
139
- metric_improvement_rate: improvementRate,
140
- research_context_drift: 0
141
- // would need NLP to compute properly
142
- };
143
- }
144
- /**
145
- * Get a summary of the current research state.
146
- */
147
- getSummary() {
148
- return {
149
- experiments_run: this.state.experiments_run,
150
- best_result: this.state.best_result,
151
- keep_rate: this.state.experiments_run > 0 ? Math.round(this.state.keep_count / this.state.experiments_run * 100) : 0,
152
- compute_remaining_minutes: this.config.computeBudgetMinutes - this.state.total_compute_minutes,
153
- architectures_tested: [...this.state.architectures_tested]
154
- };
155
- }
156
- /**
157
- * Load state from a persisted research context file.
158
- */
159
- loadState(state) {
160
- this.state = { ...state };
161
- }
162
- /**
163
- * Export state for persistence.
164
- */
165
- exportState() {
166
- return { ...this.state };
167
- }
168
- };
169
-
170
- export {
171
- AutoresearchGovernor
172
- };