noormme 1.2.0 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -6
- package/dist/cjs/agentic/ActionJournal.d.ts +5 -2
- package/dist/cjs/agentic/ActionJournal.js +13 -5
- package/dist/cjs/agentic/CapabilityManager.d.ts +7 -0
- package/dist/cjs/agentic/CapabilityManager.js +84 -7
- package/dist/cjs/agentic/CognitiveRepository.js +3 -6
- package/dist/cjs/agentic/Cortex.d.ts +4 -0
- package/dist/cjs/agentic/Cortex.js +38 -17
- package/dist/cjs/agentic/EpisodicMemory.d.ts +5 -1
- package/dist/cjs/agentic/EpisodicMemory.js +11 -4
- package/dist/cjs/agentic/PersonaManager.js +37 -31
- package/dist/cjs/agentic/PolicyEnforcer.d.ts +6 -1
- package/dist/cjs/agentic/PolicyEnforcer.js +74 -17
- package/dist/cjs/agentic/ResourceMonitor.d.ts +9 -0
- package/dist/cjs/agentic/ResourceMonitor.js +36 -2
- package/dist/cjs/agentic/SessionManager.js +24 -17
- package/dist/cjs/agentic/VectorIndexer.d.ts +1 -0
- package/dist/cjs/agentic/VectorIndexer.js +26 -17
- package/dist/cjs/agentic/improvement/AblationEngine.d.ts +4 -6
- package/dist/cjs/agentic/improvement/AblationEngine.js +57 -37
- package/dist/cjs/agentic/improvement/ActionRefiner.js +30 -14
- package/dist/cjs/agentic/improvement/ConflictResolver.d.ts +3 -1
- package/dist/cjs/agentic/improvement/ConflictResolver.js +59 -47
- package/dist/cjs/agentic/improvement/CortexJanitor.js +11 -0
- package/dist/cjs/agentic/improvement/CuriosityEngine.d.ts +1 -1
- package/dist/cjs/agentic/improvement/CuriosityEngine.js +48 -21
- package/dist/cjs/agentic/improvement/EvolutionRitual.js +26 -14
- package/dist/cjs/agentic/improvement/EvolutionaryPilot.js +16 -4
- package/dist/cjs/agentic/improvement/GoalArchitect.d.ts +6 -2
- package/dist/cjs/agentic/improvement/GoalArchitect.js +72 -34
- package/dist/cjs/agentic/improvement/GovernanceManager.d.ts +20 -6
- package/dist/cjs/agentic/improvement/GovernanceManager.js +134 -155
- package/dist/cjs/agentic/improvement/HiveLink.d.ts +7 -3
- package/dist/cjs/agentic/improvement/HiveLink.js +135 -113
- package/dist/cjs/agentic/improvement/KnowledgeDistiller.js +43 -35
- package/dist/cjs/agentic/improvement/QuotaManager.d.ts +41 -0
- package/dist/cjs/agentic/improvement/QuotaManager.js +185 -0
- package/dist/cjs/agentic/improvement/RecursiveReasoner.js +50 -25
- package/dist/cjs/agentic/improvement/ReflectionEngine.d.ts +4 -1
- package/dist/cjs/agentic/improvement/ReflectionEngine.js +3 -1
- package/dist/cjs/agentic/improvement/RitualOrchestrator.js +27 -16
- package/dist/cjs/agentic/improvement/RuleEngine.d.ts +1 -1
- package/dist/cjs/agentic/improvement/RuleEngine.js +10 -4
- package/dist/cjs/agentic/improvement/SelfEvolution.js +22 -17
- package/dist/cjs/agentic/improvement/SelfTestRegistry.d.ts +5 -0
- package/dist/cjs/agentic/improvement/SelfTestRegistry.js +129 -109
- package/dist/cjs/agentic/improvement/SkillSynthesizer.d.ts +1 -0
- package/dist/cjs/agentic/improvement/SkillSynthesizer.js +22 -13
- package/dist/cjs/agentic/improvement/StrategicPlanner.d.ts +1 -0
- package/dist/cjs/agentic/improvement/StrategicPlanner.js +26 -19
- package/dist/cjs/agentic/improvement/governance/AuditContext.d.ts +17 -0
- package/dist/cjs/agentic/improvement/governance/AuditContext.js +2 -0
- package/dist/cjs/agentic/improvement/governance/BudgetAuditor.d.ts +4 -0
- package/dist/cjs/agentic/improvement/governance/BudgetAuditor.js +50 -0
- package/dist/cjs/agentic/improvement/governance/EmergenceAuditor.d.ts +4 -0
- package/dist/cjs/agentic/improvement/governance/EmergenceAuditor.js +37 -0
- package/dist/cjs/agentic/improvement/governance/MaintenanceOracle.d.ts +4 -0
- package/dist/cjs/agentic/improvement/governance/MaintenanceOracle.js +67 -0
- package/dist/cjs/agentic/improvement/governance/PerformanceAuditor.d.ts +4 -0
- package/dist/cjs/agentic/improvement/governance/PerformanceAuditor.js +43 -0
- package/dist/cjs/agentic/improvement/governance/PersonaAuditor.d.ts +6 -0
- package/dist/cjs/agentic/improvement/governance/PersonaAuditor.js +74 -0
- package/dist/cjs/agentic/improvement/governance/RemediationEngine.d.ts +5 -0
- package/dist/cjs/agentic/improvement/governance/RemediationEngine.js +43 -0
- package/dist/cjs/agentic/improvement/governance/SkillAuditor.d.ts +5 -0
- package/dist/cjs/agentic/improvement/governance/SkillAuditor.js +52 -0
- package/dist/cjs/agentic/telemetry/CognitiveSynthesizer.d.ts +5 -0
- package/dist/cjs/agentic/telemetry/CognitiveSynthesizer.js +54 -12
- package/dist/cjs/agentic/telemetry/EventHarvester.d.ts +1 -1
- package/dist/cjs/agentic/telemetry/EventHarvester.js +10 -3
- package/dist/cjs/agentic/telemetry/ResearchAlchemist.d.ts +7 -2
- package/dist/cjs/agentic/telemetry/ResearchAlchemist.js +49 -8
- package/dist/cjs/agentic/telemetry/TelemetryOrchestrator.d.ts +4 -1
- package/dist/cjs/agentic/telemetry/TelemetryOrchestrator.js +38 -11
- package/dist/cjs/cli/commands/inspect.js +40 -1
- package/dist/cjs/cli/commands/watch.js +31 -25
- package/dist/cjs/cli/index.js +0 -0
- package/dist/cjs/dialect/sqlite/sqlite-introspector.js +15 -5
- package/dist/cjs/helpers/agent-schema.js +15 -14
- package/dist/cjs/migration/data_migrator.js +4 -4
- package/dist/cjs/migration/schema_differ.js +37 -15
- package/dist/cjs/types/index.d.ts +12 -0
- package/dist/cjs/util/safe-sql-helpers.js +7 -10
- package/dist/esm/agentic/ActionJournal.d.ts +5 -2
- package/dist/esm/agentic/ActionJournal.js +13 -5
- package/dist/esm/agentic/CapabilityManager.d.ts +7 -0
- package/dist/esm/agentic/CapabilityManager.js +84 -7
- package/dist/esm/agentic/CognitiveRepository.js +3 -6
- package/dist/esm/agentic/Cortex.d.ts +4 -0
- package/dist/esm/agentic/Cortex.js +38 -17
- package/dist/esm/agentic/EpisodicMemory.d.ts +5 -1
- package/dist/esm/agentic/EpisodicMemory.js +11 -4
- package/dist/esm/agentic/PersonaManager.js +37 -31
- package/dist/esm/agentic/PolicyEnforcer.d.ts +6 -1
- package/dist/esm/agentic/PolicyEnforcer.js +74 -17
- package/dist/esm/agentic/ResourceMonitor.d.ts +9 -0
- package/dist/esm/agentic/ResourceMonitor.js +36 -2
- package/dist/esm/agentic/SessionManager.js +24 -17
- package/dist/esm/agentic/VectorIndexer.d.ts +1 -0
- package/dist/esm/agentic/VectorIndexer.js +26 -17
- package/dist/esm/agentic/improvement/AblationEngine.d.ts +4 -6
- package/dist/esm/agentic/improvement/AblationEngine.js +57 -37
- package/dist/esm/agentic/improvement/ActionRefiner.js +30 -14
- package/dist/esm/agentic/improvement/ConflictResolver.d.ts +3 -1
- package/dist/esm/agentic/improvement/ConflictResolver.js +59 -47
- package/dist/esm/agentic/improvement/CortexJanitor.js +11 -0
- package/dist/esm/agentic/improvement/CuriosityEngine.d.ts +1 -1
- package/dist/esm/agentic/improvement/CuriosityEngine.js +48 -21
- package/dist/esm/agentic/improvement/EvolutionRitual.js +26 -14
- package/dist/esm/agentic/improvement/EvolutionaryPilot.js +16 -4
- package/dist/esm/agentic/improvement/GoalArchitect.d.ts +6 -2
- package/dist/esm/agentic/improvement/GoalArchitect.js +72 -34
- package/dist/esm/agentic/improvement/GovernanceManager.d.ts +20 -6
- package/dist/esm/agentic/improvement/GovernanceManager.js +134 -155
- package/dist/esm/agentic/improvement/HiveLink.d.ts +7 -3
- package/dist/esm/agentic/improvement/HiveLink.js +135 -113
- package/dist/esm/agentic/improvement/KnowledgeDistiller.js +43 -35
- package/dist/esm/agentic/improvement/QuotaManager.d.ts +41 -0
- package/dist/esm/agentic/improvement/QuotaManager.js +182 -0
- package/dist/esm/agentic/improvement/RecursiveReasoner.js +50 -25
- package/dist/esm/agentic/improvement/ReflectionEngine.d.ts +4 -1
- package/dist/esm/agentic/improvement/ReflectionEngine.js +3 -1
- package/dist/esm/agentic/improvement/RitualOrchestrator.js +27 -16
- package/dist/esm/agentic/improvement/RuleEngine.d.ts +1 -1
- package/dist/esm/agentic/improvement/RuleEngine.js +10 -4
- package/dist/esm/agentic/improvement/SelfEvolution.js +22 -17
- package/dist/esm/agentic/improvement/SelfTestRegistry.d.ts +5 -0
- package/dist/esm/agentic/improvement/SelfTestRegistry.js +129 -109
- package/dist/esm/agentic/improvement/SkillSynthesizer.d.ts +1 -0
- package/dist/esm/agentic/improvement/SkillSynthesizer.js +22 -13
- package/dist/esm/agentic/improvement/StrategicPlanner.d.ts +1 -0
- package/dist/esm/agentic/improvement/StrategicPlanner.js +26 -19
- package/dist/esm/agentic/improvement/governance/AuditContext.d.ts +17 -0
- package/dist/esm/agentic/improvement/governance/AuditContext.js +2 -0
- package/dist/esm/agentic/improvement/governance/BudgetAuditor.d.ts +4 -0
- package/dist/esm/agentic/improvement/governance/BudgetAuditor.js +47 -0
- package/dist/esm/agentic/improvement/governance/EmergenceAuditor.d.ts +4 -0
- package/dist/esm/agentic/improvement/governance/EmergenceAuditor.js +34 -0
- package/dist/esm/agentic/improvement/governance/MaintenanceOracle.d.ts +4 -0
- package/dist/esm/agentic/improvement/governance/MaintenanceOracle.js +64 -0
- package/dist/esm/agentic/improvement/governance/PerformanceAuditor.d.ts +4 -0
- package/dist/esm/agentic/improvement/governance/PerformanceAuditor.js +40 -0
- package/dist/esm/agentic/improvement/governance/PersonaAuditor.d.ts +6 -0
- package/dist/esm/agentic/improvement/governance/PersonaAuditor.js +71 -0
- package/dist/esm/agentic/improvement/governance/RemediationEngine.d.ts +5 -0
- package/dist/esm/agentic/improvement/governance/RemediationEngine.js +40 -0
- package/dist/esm/agentic/improvement/governance/SkillAuditor.d.ts +5 -0
- package/dist/esm/agentic/improvement/governance/SkillAuditor.js +49 -0
- package/dist/esm/agentic/telemetry/CognitiveSynthesizer.d.ts +5 -0
- package/dist/esm/agentic/telemetry/CognitiveSynthesizer.js +54 -12
- package/dist/esm/agentic/telemetry/EventHarvester.d.ts +1 -1
- package/dist/esm/agentic/telemetry/EventHarvester.js +10 -3
- package/dist/esm/agentic/telemetry/ResearchAlchemist.d.ts +7 -2
- package/dist/esm/agentic/telemetry/ResearchAlchemist.js +49 -8
- package/dist/esm/agentic/telemetry/TelemetryOrchestrator.d.ts +4 -1
- package/dist/esm/agentic/telemetry/TelemetryOrchestrator.js +38 -11
- package/dist/esm/cli/commands/inspect.js +40 -1
- package/dist/esm/cli/commands/watch.js +31 -25
- package/dist/esm/dialect/sqlite/sqlite-introspector.js +15 -5
- package/dist/esm/helpers/agent-schema.js +15 -14
- package/dist/esm/migration/data_migrator.js +4 -4
- package/dist/esm/migration/schema_differ.js +37 -15
- package/dist/esm/types/index.d.ts +12 -0
- package/dist/esm/util/safe-sql-helpers.js +7 -10
- package/package.json +44 -40
|
@@ -8,6 +8,7 @@ export class PolicyEnforcer {
|
|
|
8
8
|
config;
|
|
9
9
|
policiesTable;
|
|
10
10
|
metricsTable;
|
|
11
|
+
metricCache = new Map();
|
|
11
12
|
constructor(db, config = {}) {
|
|
12
13
|
this.db = db;
|
|
13
14
|
this.config = config;
|
|
@@ -22,11 +23,15 @@ export class PolicyEnforcer {
|
|
|
22
23
|
*/
|
|
23
24
|
async definePolicy(name, type, definition, isEnabled = true) {
|
|
24
25
|
return await this.db.transaction().execute(async (trx) => {
|
|
25
|
-
|
|
26
|
+
let query = trx
|
|
26
27
|
.selectFrom(this.policiesTable)
|
|
27
28
|
.select('id')
|
|
28
|
-
.where('name', '=', name)
|
|
29
|
-
|
|
29
|
+
.where('name', '=', name);
|
|
30
|
+
// Audit Phase 16: Exclusive lock for provisioning (Skip for SQLite)
|
|
31
|
+
if (this.db.getExecutor().adapter?.constructor.name !== 'SqliteAdapter') {
|
|
32
|
+
query = query.forUpdate();
|
|
33
|
+
}
|
|
34
|
+
const existing = await query.executeTakeFirst();
|
|
30
35
|
if (existing) {
|
|
31
36
|
const updated = await trx
|
|
32
37
|
.updateTable(this.policiesTable)
|
|
@@ -60,7 +65,19 @@ export class PolicyEnforcer {
|
|
|
60
65
|
* Comprehensive policy evaluation against a context value.
|
|
61
66
|
* Supports thresholds, regex patterns, and cumulative budgets.
|
|
62
67
|
*/
|
|
63
|
-
|
|
68
|
+
/**
|
|
69
|
+
* Comprehensive policy evaluation against a context value.
|
|
70
|
+
* Supports thresholds, regex patterns, and cumulative budgets.
|
|
71
|
+
*/
|
|
72
|
+
async checkPolicy(name, value, visited = new Set()) {
|
|
73
|
+
// Audit Pass 6: Re-entrancy / Circular Dependency Detection
|
|
74
|
+
if (visited.has(name)) {
|
|
75
|
+
return {
|
|
76
|
+
allowed: false,
|
|
77
|
+
reason: `Circular policy dependency detected: ${Array.from(visited).join(' -> ')} -> ${name}`,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
visited.add(name);
|
|
64
81
|
const policy = await this.typedDb
|
|
65
82
|
.selectFrom(this.policiesTable)
|
|
66
83
|
.selectAll()
|
|
@@ -87,18 +104,33 @@ export class PolicyEnforcer {
|
|
|
87
104
|
}
|
|
88
105
|
// 2. Pattern Check (String/Regex)
|
|
89
106
|
if (typeof value === 'string' && def.pattern) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
reason: `Value does not match required pattern for policy '${name}'`,
|
|
95
|
-
};
|
|
107
|
+
// PRODUCTION HARDENING: ReDoS Prevention
|
|
108
|
+
// Sanitize regex: check for dangerous nested quantifiers and length
|
|
109
|
+
if (def.pattern.length > 500) {
|
|
110
|
+
return { allowed: false, reason: `Policy '${name}' regex pattern too long (potential ReDoS risk)` };
|
|
96
111
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
112
|
+
const dangerousPatterns = /(\*|\+)\1|\(\.\*\)\*/;
|
|
113
|
+
if (dangerousPatterns.test(def.pattern)) {
|
|
114
|
+
return { allowed: false, reason: `Policy '${name}' contains potentially dangerous ReDoS pattern` };
|
|
115
|
+
}
|
|
116
|
+
const flags = def.flags || 'i';
|
|
117
|
+
try {
|
|
118
|
+
const regex = new RegExp(def.pattern, flags);
|
|
119
|
+
if (def.mustMatch && !regex.test(value)) {
|
|
120
|
+
return {
|
|
121
|
+
allowed: false,
|
|
122
|
+
reason: `Value does not match required pattern for policy '${name}'`,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
if (!def.mustMatch && regex.test(value)) {
|
|
126
|
+
return {
|
|
127
|
+
allowed: false,
|
|
128
|
+
reason: `Value contains forbidden pattern for policy '${name}'`,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
catch (e) {
|
|
133
|
+
return { allowed: false, reason: `Invalid regex in policy '${name}': ${String(e)}` };
|
|
102
134
|
}
|
|
103
135
|
}
|
|
104
136
|
// 3. Budget Check (Cumulative)
|
|
@@ -113,6 +145,16 @@ export class PolicyEnforcer {
|
|
|
113
145
|
};
|
|
114
146
|
}
|
|
115
147
|
}
|
|
148
|
+
// 4. Composite Policy Check: Recursive evaluation of dependencies
|
|
149
|
+
// Audit Pass 6: Moved from evaluateContext to checkPolicy for deeper nesting support
|
|
150
|
+
if (def.dependsOn && Array.isArray(def.dependsOn)) {
|
|
151
|
+
for (const depName of def.dependsOn) {
|
|
152
|
+
const result = await this.checkPolicy(depName, value, new Set(visited));
|
|
153
|
+
if (!result.allowed) {
|
|
154
|
+
return { allowed: false, reason: `Composite block: ${name} -> ${result.reason}` };
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
116
158
|
return { allowed: true };
|
|
117
159
|
}
|
|
118
160
|
/**
|
|
@@ -152,8 +194,21 @@ export class PolicyEnforcer {
|
|
|
152
194
|
return list.map((p) => this.parsePolicy(p));
|
|
153
195
|
}
|
|
154
196
|
async getCumulativeMetric(metricName, period) {
|
|
155
|
-
|
|
197
|
+
const cacheKey = `${metricName}:${period}`;
|
|
198
|
+
const cached = this.metricCache.get(cacheKey);
|
|
156
199
|
const now = new Date();
|
|
200
|
+
const ttl = this.config.policyCacheTTL || 60000;
|
|
201
|
+
if (cached && now.getTime() - cached.timestamp < ttl) {
|
|
202
|
+
return cached.value;
|
|
203
|
+
}
|
|
204
|
+
// Map Hardening: Simple LRU-like eviction to prevent memory leaks
|
|
205
|
+
if (this.metricCache.size > 1000) {
|
|
206
|
+
const firstKey = this.metricCache.keys().next().value;
|
|
207
|
+
if (firstKey !== undefined) {
|
|
208
|
+
this.metricCache.delete(firstKey);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
let cutoff = new Date(0); // beginning of time
|
|
157
212
|
if (period === 'daily') {
|
|
158
213
|
cutoff = new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
|
159
214
|
}
|
|
@@ -166,7 +221,9 @@ export class PolicyEnforcer {
|
|
|
166
221
|
.where('metric_name', '=', metricName)
|
|
167
222
|
.where('created_at', '>=', cutoff)
|
|
168
223
|
.executeTakeFirst();
|
|
169
|
-
|
|
224
|
+
const total = Number(result?.total || 0);
|
|
225
|
+
this.metricCache.set(cacheKey, { value: total, timestamp: now.getTime() });
|
|
226
|
+
return total;
|
|
170
227
|
}
|
|
171
228
|
parsePolicy(p) {
|
|
172
229
|
return {
|
|
@@ -28,6 +28,15 @@ export declare class ResourceMonitor {
|
|
|
28
28
|
* Record token usage
|
|
29
29
|
*/
|
|
30
30
|
recordUsage(sessionId: string | number, modelName: string, inputTokens: number, outputTokens: number, cost?: number, agentId?: string, metadata?: Record<string, any>): Promise<ResourceUsage>;
|
|
31
|
+
/**
|
|
32
|
+
* Pre-run quota validation.
|
|
33
|
+
* Blocks operations if persona or swarm limits are breached.
|
|
34
|
+
* Includes cost projection to prevent mid-run budget failure.
|
|
35
|
+
*/
|
|
36
|
+
validateQuota(agentId: string, swarmId?: string, estimatedTokens?: number): Promise<{
|
|
37
|
+
allowed: boolean;
|
|
38
|
+
reason?: string;
|
|
39
|
+
}>;
|
|
31
40
|
/**
|
|
32
41
|
* Get total cost for a session
|
|
33
42
|
*/
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
/// <reference types="./ResourceMonitor.d.ts" />
|
|
2
|
-
import { sql } from '../raw-builder/sql.js';
|
|
3
2
|
/**
|
|
4
3
|
* ResourceMonitor tracks token usage and costs across sessions.
|
|
5
4
|
*/
|
|
@@ -36,6 +35,39 @@ export class ResourceMonitor {
|
|
|
36
35
|
.executeTakeFirstOrThrow();
|
|
37
36
|
return this.parseUsage(usage);
|
|
38
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Pre-run quota validation.
|
|
40
|
+
* Blocks operations if persona or swarm limits are breached.
|
|
41
|
+
* Includes cost projection to prevent mid-run budget failure.
|
|
42
|
+
*/
|
|
43
|
+
async validateQuota(agentId, swarmId, estimatedTokens = 2000) {
|
|
44
|
+
// 1. Project cost using Persistent Oracle from QuotaManager
|
|
45
|
+
let projection = 0;
|
|
46
|
+
const quotas = this.config.cortex?.quotas;
|
|
47
|
+
if (quotas) {
|
|
48
|
+
// Dynamic Lookup via Oracle sync
|
|
49
|
+
const rate = await quotas.getExchangeRate('USD'); // Oracle baseline
|
|
50
|
+
projection = estimatedTokens * (rate * 0.00001); // Weighted projection
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
projection = estimatedTokens * 0.00002; // Safe fallback
|
|
54
|
+
}
|
|
55
|
+
// 2. Persona Quota Check
|
|
56
|
+
const personaCheck = await this.config.cortex?.quotas.checkQuota('persona', agentId);
|
|
57
|
+
if (personaCheck && !personaCheck.allowed)
|
|
58
|
+
return personaCheck;
|
|
59
|
+
// 3. Swarm Quota Check
|
|
60
|
+
if (swarmId) {
|
|
61
|
+
const swarmCheck = await this.config.cortex?.quotas.checkQuota('swarm', swarmId);
|
|
62
|
+
if (swarmCheck && !swarmCheck.allowed)
|
|
63
|
+
return swarmCheck;
|
|
64
|
+
}
|
|
65
|
+
// 4. Global Quota Check
|
|
66
|
+
const globalCheck = await this.config.cortex?.quotas.checkQuota('global');
|
|
67
|
+
if (globalCheck && !globalCheck.allowed)
|
|
68
|
+
return globalCheck;
|
|
69
|
+
return { allowed: true };
|
|
70
|
+
}
|
|
39
71
|
/**
|
|
40
72
|
* Get total cost for a session
|
|
41
73
|
*/
|
|
@@ -65,7 +97,9 @@ export class ResourceMonitor {
|
|
|
65
97
|
.selectFrom(this.resourcesTable)
|
|
66
98
|
.select([
|
|
67
99
|
'model_name',
|
|
68
|
-
(eb) => eb.fn
|
|
100
|
+
(eb) => eb.fn
|
|
101
|
+
.sum(eb('input_tokens', '+', 'output_tokens'))
|
|
102
|
+
.as('totalTokens'),
|
|
69
103
|
(eb) => eb.fn.sum('cost').as('totalCost'),
|
|
70
104
|
])
|
|
71
105
|
.groupBy('model_name')
|
|
@@ -137,6 +137,7 @@ export class SessionManager {
|
|
|
137
137
|
.selectAll()
|
|
138
138
|
.where('session_id', '=', sessionId)
|
|
139
139
|
.where('description', '=', description)
|
|
140
|
+
.forUpdate() // Audit Phase 13: Atomic goal lock
|
|
140
141
|
.executeTakeFirst();
|
|
141
142
|
if (existing) {
|
|
142
143
|
const updated = await trx
|
|
@@ -203,23 +204,29 @@ export class SessionManager {
|
|
|
203
204
|
* Mark a message as a semantic anchor to prevent it from being pruned
|
|
204
205
|
*/
|
|
205
206
|
async markMessageAsAnchor(messageId) {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
.
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
207
|
+
// PRODUCTION HARDENING: Atomic Metadata Patching
|
|
208
|
+
// We avoid the Read-Modify-Write race condition by letting the DB handle the merge
|
|
209
|
+
// or by using a strict transaction if the DB doesn't support JSON patching natively.
|
|
210
|
+
const updated = await this.db.transaction().execute(async (trx) => {
|
|
211
|
+
const message = await trx
|
|
212
|
+
.selectFrom(this.messagesTable)
|
|
213
|
+
.select('metadata')
|
|
214
|
+
.where('id', '=', messageId)
|
|
215
|
+
.forUpdate() // Lock the row for the duration of the transaction
|
|
216
|
+
.executeTakeFirstOrThrow();
|
|
217
|
+
const metadata = typeof message.metadata === 'string'
|
|
218
|
+
? JSON.parse(message.metadata)
|
|
219
|
+
: message.metadata || {};
|
|
220
|
+
const updatedMetadata = { ...metadata, anchor: true };
|
|
221
|
+
return await trx
|
|
222
|
+
.updateTable(this.messagesTable)
|
|
223
|
+
.set({
|
|
224
|
+
metadata: JSON.stringify(updatedMetadata),
|
|
225
|
+
})
|
|
226
|
+
.where('id', '=', messageId)
|
|
227
|
+
.returningAll()
|
|
228
|
+
.executeTakeFirstOrThrow();
|
|
229
|
+
});
|
|
223
230
|
return this.parseMessage(updated);
|
|
224
231
|
}
|
|
225
232
|
parseSession(session) {
|
|
@@ -27,6 +27,7 @@ export declare class VectorIndexer {
|
|
|
27
27
|
addMemory(content: string, embedding: number[], sessionId?: string | number, metadata?: Record<string, any>): Promise<AgentMemory>;
|
|
28
28
|
/**
|
|
29
29
|
* Batch add memories
|
|
30
|
+
* Refactored Phase 12: Chunked execution to prevent OOM and long-running locks.
|
|
30
31
|
*/
|
|
31
32
|
addMemories(items: {
|
|
32
33
|
content: string;
|
|
@@ -34,21 +34,28 @@ export class VectorIndexer {
|
|
|
34
34
|
}
|
|
35
35
|
/**
|
|
36
36
|
* Batch add memories
|
|
37
|
+
* Refactored Phase 12: Chunked execution to prevent OOM and long-running locks.
|
|
37
38
|
*/
|
|
38
39
|
async addMemories(items) {
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
.
|
|
51
|
-
|
|
40
|
+
const BATCH_SIZE = 50;
|
|
41
|
+
const results = [];
|
|
42
|
+
for (let i = 0; i < items.length; i += BATCH_SIZE) {
|
|
43
|
+
const chunk = items.slice(i, i + BATCH_SIZE);
|
|
44
|
+
const values = chunk.map((item) => ({
|
|
45
|
+
content: item.content,
|
|
46
|
+
embedding: JSON.stringify(item.embedding),
|
|
47
|
+
session_id: item.sessionId || null,
|
|
48
|
+
metadata: item.metadata ? JSON.stringify(item.metadata) : null,
|
|
49
|
+
created_at: new Date(),
|
|
50
|
+
}));
|
|
51
|
+
const memories = await this.typedDb
|
|
52
|
+
.insertInto(this.memoriesTable)
|
|
53
|
+
.values(values)
|
|
54
|
+
.returningAll()
|
|
55
|
+
.execute();
|
|
56
|
+
results.push(...memories.map((m) => this.parseMemory(m)));
|
|
57
|
+
}
|
|
58
|
+
return results;
|
|
52
59
|
}
|
|
53
60
|
/**
|
|
54
61
|
* Search for similar memories using Hybrid Search (Vector + Keyword)
|
|
@@ -84,13 +91,15 @@ export class VectorIndexer {
|
|
|
84
91
|
}
|
|
85
92
|
if (vectorResults.length === 0) {
|
|
86
93
|
// Manual Fallback (Cosine Similarity in-memory)
|
|
87
|
-
|
|
94
|
+
// Audit Phase 12: Hard limit on candidate set to protect memory
|
|
95
|
+
let query = this.typedDb
|
|
96
|
+
.selectFrom(this.memoriesTable)
|
|
97
|
+
.selectAll()
|
|
98
|
+
.orderBy('created_at', 'desc')
|
|
99
|
+
.limit(1000);
|
|
88
100
|
if (sessionId) {
|
|
89
101
|
query = query.where('session_id', '=', sessionId);
|
|
90
102
|
}
|
|
91
|
-
if (!sessionId) {
|
|
92
|
-
query = query.orderBy('created_at', 'desc').limit(1000);
|
|
93
|
-
}
|
|
94
103
|
const allMemories = await query.execute();
|
|
95
104
|
const scored = allMemories.map((mem) => {
|
|
96
105
|
const vec = typeof mem.embedding === 'string'
|
|
@@ -16,24 +16,22 @@ export declare class AblationEngine {
|
|
|
16
16
|
private get typedDb();
|
|
17
17
|
/**
|
|
18
18
|
* Identify "Zombies": Items that have never been retrieved/hit and are old.
|
|
19
|
-
* Checks for linked dependencies before deletion.
|
|
20
19
|
*/
|
|
21
20
|
pruneZombies(thresholdDays?: number): Promise<number>;
|
|
22
21
|
/**
|
|
23
|
-
* Monitor Performance
|
|
24
|
-
*
|
|
22
|
+
* Monitor Performance and perform Intelligent Rollbacks.
|
|
23
|
+
* Prioritizes recovery of items with highest historical hit counts.
|
|
25
24
|
*/
|
|
26
25
|
monitorAblationPerformance(): Promise<{
|
|
27
26
|
status: 'stable' | 'degraded';
|
|
28
27
|
recoveredCount: number;
|
|
29
28
|
}>;
|
|
30
29
|
/**
|
|
31
|
-
* Conduct an "Ablation Test": Temporarily disable a knowledge item
|
|
32
|
-
* to see if it impacts reasoning.
|
|
30
|
+
* Conduct an "Ablation Test": Temporarily disable a knowledge item.
|
|
33
31
|
*/
|
|
34
32
|
testAblation(id: string | number): Promise<boolean>;
|
|
35
33
|
/**
|
|
36
34
|
* Restore an ablated knowledge item to its original state.
|
|
37
35
|
*/
|
|
38
|
-
recoverAblatedItem(id: string | number): Promise<boolean>;
|
|
36
|
+
recoverAblatedItem(id: string | number, trx?: any): Promise<boolean>;
|
|
39
37
|
}
|
|
@@ -23,13 +23,13 @@ export class AblationEngine {
|
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
25
25
|
* Identify "Zombies": Items that have never been retrieved/hit and are old.
|
|
26
|
-
* Checks for linked dependencies before deletion.
|
|
27
26
|
*/
|
|
28
27
|
async pruneZombies(thresholdDays = 30) {
|
|
29
28
|
const cutoff = new Date(Date.now() - thresholdDays * 24 * 3600000);
|
|
30
29
|
let totalPruned = 0;
|
|
31
30
|
return await this.db.transaction().execute(async (trx) => {
|
|
32
|
-
// 1. Prune Knowledge (with dependency check)
|
|
31
|
+
// 1. Prune Knowledge (with dependency check and pagination)
|
|
32
|
+
// Audit Phase 9: Paginated selection to prevent OOM
|
|
33
33
|
const knowledgeToPrune = await trx
|
|
34
34
|
.selectFrom(this.knowledgeTable)
|
|
35
35
|
.selectAll()
|
|
@@ -39,16 +39,16 @@ export class AblationEngine {
|
|
|
39
39
|
eb('metadata', 'is', null),
|
|
40
40
|
]))
|
|
41
41
|
.where('updated_at', '<', cutoff)
|
|
42
|
-
// Exclude items that are linked
|
|
43
42
|
.where('id', 'not in', (eb) => eb.selectFrom(this.linksTable).select('source_id'))
|
|
44
43
|
.where('id', 'not in', (eb) => eb.selectFrom(this.linksTable).select('target_id'))
|
|
44
|
+
.limit(500) // Audit Phase 9: Batch limit
|
|
45
|
+
.forUpdate() // Audit Phase 9: Lock candidates
|
|
45
46
|
.execute();
|
|
46
47
|
if (knowledgeToPrune.length > 0) {
|
|
47
48
|
const candidates = knowledgeToPrune.map((k) => this.cortex.knowledge['parseKnowledge'](k));
|
|
48
49
|
const idsToDelete = [];
|
|
49
50
|
for (const item of candidates) {
|
|
50
51
|
const fitness = this.cortex.knowledge.calculateFitness(item);
|
|
51
|
-
// Prune if fitness is below threshold (e.g., 0.3)
|
|
52
52
|
if (fitness < 0.3) {
|
|
53
53
|
idsToDelete.push(item.id);
|
|
54
54
|
}
|
|
@@ -61,14 +61,17 @@ export class AblationEngine {
|
|
|
61
61
|
totalPruned += Number(result.numDeletedRows || 0);
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
|
-
// 2. Prune Memories
|
|
64
|
+
// 2. Prune Memories (Paginated)
|
|
65
65
|
const memoriesResult = await trx
|
|
66
66
|
.deleteFrom(this.memoriesTable)
|
|
67
|
+
.where('id', 'in', (eb) => eb.selectFrom(this.memoriesTable)
|
|
68
|
+
.select('id')
|
|
67
69
|
.where('created_at', '<', cutoff)
|
|
68
|
-
.where((
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
.where((eb2) => eb2.or([
|
|
71
|
+
eb2('metadata', 'not like', '%"anchor":true%'),
|
|
72
|
+
eb2('metadata', 'is', null),
|
|
71
73
|
]))
|
|
74
|
+
.limit(1000))
|
|
72
75
|
.executeTakeFirst();
|
|
73
76
|
totalPruned += Number(memoriesResult.numDeletedRows || 0);
|
|
74
77
|
if (totalPruned > 0) {
|
|
@@ -78,34 +81,44 @@ export class AblationEngine {
|
|
|
78
81
|
});
|
|
79
82
|
}
|
|
80
83
|
/**
|
|
81
|
-
* Monitor Performance
|
|
82
|
-
*
|
|
84
|
+
* Monitor Performance and perform Intelligent Rollbacks.
|
|
85
|
+
* Prioritizes recovery of items with highest historical hit counts.
|
|
83
86
|
*/
|
|
84
87
|
async monitorAblationPerformance() {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
88
|
+
return await this.db.transaction().execute(async (trx) => {
|
|
89
|
+
const baseline = await this.cortex.metrics.getAverageMetric('success_rate');
|
|
90
|
+
const stats = await this.cortex.metrics.getMetricStats('success_rate');
|
|
91
|
+
// If current average is significantly lower than overall average
|
|
92
|
+
if (stats.count > 10 && stats.avg < baseline * 0.8) {
|
|
93
|
+
console.warn(`[AblationEngine] PERFORMANCE DEGRADATION DETECTED (Avg: ${stats.avg}, Baseline: ${baseline}). Triggering targeted recovery.`);
|
|
94
|
+
// Fetch ablated items, ordered by hit_count descending (prioritize high-value restore)
|
|
95
|
+
const ablatedItems = await trx
|
|
96
|
+
.selectFrom(this.knowledgeTable)
|
|
97
|
+
.select(['id', 'metadata'])
|
|
98
|
+
.where('metadata', 'like', '%"ablation_test":true%')
|
|
99
|
+
.execute();
|
|
100
|
+
// Sort by hit_count in memory for precise weighted recovery
|
|
101
|
+
const sortedItems = ablatedItems.sort((a, b) => {
|
|
102
|
+
const metaA = typeof a.metadata === 'string' ? JSON.parse(a.metadata) : a.metadata || {};
|
|
103
|
+
const metaB = typeof b.metadata === 'string' ? JSON.parse(b.metadata) : b.metadata || {};
|
|
104
|
+
return (metaB.hit_count || 0) - (metaA.hit_count || 0);
|
|
105
|
+
});
|
|
106
|
+
let recoveredCount = 0;
|
|
107
|
+
for (const item of sortedItems) {
|
|
108
|
+
if (await this.recoverAblatedItem(item.id, trx)) {
|
|
109
|
+
recoveredCount++;
|
|
110
|
+
}
|
|
111
|
+
// Only recover until performance stabilizes or we've recovered a reasonable chunk (e.g. 5)
|
|
112
|
+
if (recoveredCount >= 5)
|
|
113
|
+
break;
|
|
100
114
|
}
|
|
115
|
+
return { status: 'degraded', recoveredCount };
|
|
101
116
|
}
|
|
102
|
-
return { status: '
|
|
103
|
-
}
|
|
104
|
-
return { status: 'stable', recoveredCount: 0 };
|
|
117
|
+
return { status: 'stable', recoveredCount: 0 };
|
|
118
|
+
});
|
|
105
119
|
}
|
|
106
120
|
/**
|
|
107
|
-
* Conduct an "Ablation Test": Temporarily disable a knowledge item
|
|
108
|
-
* to see if it impacts reasoning.
|
|
121
|
+
* Conduct an "Ablation Test": Temporarily disable a knowledge item.
|
|
109
122
|
*/
|
|
110
123
|
async testAblation(id) {
|
|
111
124
|
console.log(`[AblationEngine] Conducting ablation test on item ${id}`);
|
|
@@ -114,18 +127,18 @@ export class AblationEngine {
|
|
|
114
127
|
.selectFrom(this.knowledgeTable)
|
|
115
128
|
.selectAll()
|
|
116
129
|
.where('id', '=', id)
|
|
130
|
+
.forUpdate() // Audit Phase 9: Atomic lock for test initiation
|
|
117
131
|
.executeTakeFirst());
|
|
118
132
|
if (!item)
|
|
119
133
|
return false;
|
|
120
134
|
const metadata = typeof item.metadata === 'string'
|
|
121
135
|
? JSON.parse(item.metadata)
|
|
122
136
|
: item.metadata || {};
|
|
123
|
-
// 1. Record the experiment in reflections
|
|
124
137
|
await this.cortex.reflections.reflect(item.source_session_id || 'system', 'success', `Ablation experiment initiated for item ${id}`, [
|
|
125
138
|
`Temporary confidence reduction to evaluate reasoning impact.`,
|
|
126
139
|
`Original confidence: ${item.confidence}`,
|
|
140
|
+
`Historical hits: ${metadata.hit_count || 0}`
|
|
127
141
|
]);
|
|
128
|
-
// 2. Perform the ablation
|
|
129
142
|
await trx
|
|
130
143
|
.updateTable(this.knowledgeTable)
|
|
131
144
|
.set({
|
|
@@ -145,12 +158,13 @@ export class AblationEngine {
|
|
|
145
158
|
/**
|
|
146
159
|
* Restore an ablated knowledge item to its original state.
|
|
147
160
|
*/
|
|
148
|
-
async recoverAblatedItem(id) {
|
|
149
|
-
|
|
150
|
-
const item = (await
|
|
161
|
+
async recoverAblatedItem(id, trx) {
|
|
162
|
+
const recoveryStep = async (t) => {
|
|
163
|
+
const item = (await t
|
|
151
164
|
.selectFrom(this.knowledgeTable)
|
|
152
165
|
.selectAll()
|
|
153
166
|
.where('id', '=', id)
|
|
167
|
+
.forUpdate() // Audit Phase 9: Atomic lock for restoration
|
|
154
168
|
.executeTakeFirst());
|
|
155
169
|
if (!item)
|
|
156
170
|
return false;
|
|
@@ -163,7 +177,7 @@ export class AblationEngine {
|
|
|
163
177
|
delete metadata.ablation_test;
|
|
164
178
|
delete metadata.original_confidence;
|
|
165
179
|
delete metadata.ablated_at;
|
|
166
|
-
await
|
|
180
|
+
await t
|
|
167
181
|
.updateTable(this.knowledgeTable)
|
|
168
182
|
.set({
|
|
169
183
|
confidence: originalConfidence,
|
|
@@ -174,6 +188,12 @@ export class AblationEngine {
|
|
|
174
188
|
.execute();
|
|
175
189
|
console.log(`[AblationEngine] Item ${id} recovered. Confidence restored to ${originalConfidence}.`);
|
|
176
190
|
return true;
|
|
177
|
-
}
|
|
191
|
+
};
|
|
192
|
+
if (trx) {
|
|
193
|
+
return await recoveryStep(trx);
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
return await this.db.transaction().execute(recoveryStep);
|
|
197
|
+
}
|
|
178
198
|
}
|
|
179
199
|
}
|
|
@@ -19,7 +19,9 @@ export class ActionRefiner {
|
|
|
19
19
|
*/
|
|
20
20
|
async refineActions() {
|
|
21
21
|
const recommendations = [];
|
|
22
|
-
// 1. Find tools with high failure rates
|
|
22
|
+
// 1. Find tools with high failure rates (Last 24h Window)
|
|
23
|
+
// Audit Phase 14: Sliding window to prevent global table scans
|
|
24
|
+
const windowStart = new Date(Date.now() - 24 * 60 * 60 * 1000);
|
|
23
25
|
const failureStats = (await this.db
|
|
24
26
|
.selectFrom(this.actionsTable)
|
|
25
27
|
.select('tool_name')
|
|
@@ -27,23 +29,27 @@ export class ActionRefiner {
|
|
|
27
29
|
.select((eb) => eb.fn
|
|
28
30
|
.sum(eb.case().when('status', '=', 'failure').then(1).else(0).end())
|
|
29
31
|
.as('failures'))
|
|
32
|
+
.where('created_at', '>', windowStart)
|
|
30
33
|
.groupBy('tool_name')
|
|
31
34
|
.execute());
|
|
35
|
+
const failureRateThreshold = this.config.refiner?.failureRateThreshold || 0.3;
|
|
36
|
+
const minActionBatch = this.config.refiner?.minActionBatch || 3;
|
|
32
37
|
for (const stat of failureStats) {
|
|
33
38
|
const failures = Number(stat.failures || 0);
|
|
34
39
|
const total = Number(stat.total || 1);
|
|
35
40
|
const rate = failures / total;
|
|
36
|
-
if (rate >
|
|
41
|
+
if (rate > failureRateThreshold && total > minActionBatch) {
|
|
37
42
|
recommendations.push(`Tool '${stat.tool_name}' has a ${Math.round(rate * 100)}% failure rate. Suggesting automatic reflection rule.`);
|
|
38
43
|
// Automatically propose a rule to reflect on this tool's usage
|
|
39
44
|
await this.proposeReflectionRule(stat.tool_name);
|
|
40
45
|
}
|
|
41
46
|
}
|
|
42
|
-
// 2. Discover missing capabilities based on error patterns
|
|
47
|
+
// 2. Discover missing capabilities based on error patterns (Last 24h)
|
|
43
48
|
const missingCapabilities = (await this.db
|
|
44
49
|
.selectFrom(this.actionsTable)
|
|
45
50
|
.select('tool_name')
|
|
46
51
|
.where('status', '=', 'failure')
|
|
52
|
+
.where('created_at', '>', windowStart)
|
|
47
53
|
.where((eb) => eb.or([
|
|
48
54
|
eb('error', 'like', '%permission denied%'),
|
|
49
55
|
eb('error', 'like', '%unknown tool%'),
|
|
@@ -62,17 +68,27 @@ export class ActionRefiner {
|
|
|
62
68
|
* Propose a rule to reflect on a specific tool usage
|
|
63
69
|
*/
|
|
64
70
|
async proposeReflectionRule(toolName) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
71
|
+
// Audit Phase 19: Atomic rule proposal via transaction + existence check
|
|
72
|
+
await this.db.transaction().execute(async (trx) => {
|
|
73
|
+
const rulesTable = this.cortex.config.rulesTable || 'agent_rules';
|
|
74
|
+
const existing = await trx
|
|
75
|
+
.selectFrom(rulesTable)
|
|
76
|
+
.select('id')
|
|
77
|
+
.where('tableName', '=', 'agent_actions')
|
|
78
|
+
.where('operation', '=', 'insert')
|
|
79
|
+
.where('metadata', 'like', `%\"targetTool\":\"${toolName}\"%`)
|
|
80
|
+
.forUpdate() // Lock to prevent concurrent proposals
|
|
81
|
+
.executeTakeFirst();
|
|
82
|
+
if (!existing) {
|
|
83
|
+
console.log(`[ActionRefiner] Proposing reflection rule for tool: ${toolName}`);
|
|
84
|
+
await this.cortex.rules.defineRule('agent_actions', 'insert', 'audit', {
|
|
85
|
+
metadata: {
|
|
86
|
+
targetTool: toolName,
|
|
87
|
+
reason: 'High failure rate detected by ActionRefiner',
|
|
88
|
+
},
|
|
89
|
+
}, trx); // Pass transaction object
|
|
90
|
+
}
|
|
91
|
+
});
|
|
76
92
|
}
|
|
77
93
|
/**
|
|
78
94
|
* Propose an update to capabilities
|
|
@@ -12,7 +12,9 @@ export declare class ConflictResolver {
|
|
|
12
12
|
/**
|
|
13
13
|
* Audit rules for direct conflicts and semantic overlaps.
|
|
14
14
|
*/
|
|
15
|
-
auditRuleConflicts(
|
|
15
|
+
auditRuleConflicts(options?: {
|
|
16
|
+
batchSize?: number;
|
|
17
|
+
}): Promise<string[]>;
|
|
16
18
|
/**
|
|
17
19
|
* Resolve a detected conflict by disabling the older rule.
|
|
18
20
|
* Real implementation: Find all active rules for the conflict, and disable all but the newest one.
|