noormme 1.2.2 → 1.2.4
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/dist/cjs/agentic/ActionJournal.d.ts +6 -6
- package/dist/cjs/agentic/ActionJournal.js +10 -10
- package/dist/cjs/agentic/CapabilityManager.d.ts +5 -5
- package/dist/cjs/agentic/CapabilityManager.js +34 -19
- package/dist/cjs/agentic/Cortex.js +12 -13
- package/dist/cjs/agentic/PersonaManager.d.ts +4 -4
- package/dist/cjs/agentic/PersonaManager.js +18 -10
- package/dist/cjs/agentic/PolicyEnforcer.d.ts +4 -8
- package/dist/cjs/agentic/PolicyEnforcer.js +25 -22
- package/dist/cjs/agentic/improvement/AblationEngine.d.ts +7 -3
- package/dist/cjs/agentic/improvement/AblationEngine.js +51 -24
- package/dist/cjs/agentic/improvement/ActionRefiner.d.ts +1 -1
- package/dist/cjs/agentic/improvement/ActionRefiner.js +25 -15
- package/dist/cjs/agentic/improvement/EvolutionRitual.js +2 -1
- package/dist/cjs/agentic/improvement/EvolutionaryPilot.d.ts +1 -1
- package/dist/cjs/agentic/improvement/EvolutionaryPilot.js +17 -19
- package/dist/cjs/agentic/improvement/GovernanceManager.d.ts +5 -5
- package/dist/cjs/agentic/improvement/GovernanceManager.js +12 -22
- package/dist/cjs/agentic/improvement/HiveLink.d.ts +3 -3
- package/dist/cjs/agentic/improvement/HiveLink.js +15 -157
- package/dist/cjs/agentic/improvement/KnowledgeDistiller.d.ts +15 -29
- package/dist/cjs/agentic/improvement/KnowledgeDistiller.js +66 -349
- package/dist/cjs/agentic/improvement/QuotaManager.d.ts +1 -1
- package/dist/cjs/agentic/improvement/QuotaManager.js +11 -11
- package/dist/cjs/agentic/improvement/RecursiveReasoner.d.ts +4 -4
- package/dist/cjs/agentic/improvement/RecursiveReasoner.js +10 -10
- package/dist/cjs/agentic/improvement/ReflectionEngine.d.ts +2 -2
- package/dist/cjs/agentic/improvement/ReflectionEngine.js +2 -2
- package/dist/cjs/agentic/improvement/RitualOrchestrator.d.ts +3 -3
- package/dist/cjs/agentic/improvement/RitualOrchestrator.js +12 -9
- package/dist/cjs/agentic/improvement/SelfEvolution.d.ts +1 -1
- package/dist/cjs/agentic/improvement/SelfEvolution.js +21 -18
- package/dist/cjs/agentic/improvement/SelfTestRegistry.d.ts +1 -1
- package/dist/cjs/agentic/improvement/SelfTestRegistry.js +31 -19
- package/dist/cjs/agentic/improvement/SovereignMetrics.d.ts +6 -6
- package/dist/cjs/agentic/improvement/SovereignMetrics.js +12 -12
- package/dist/cjs/agentic/improvement/StrategicPlanner.d.ts +10 -54
- package/dist/cjs/agentic/improvement/StrategicPlanner.js +43 -396
- package/dist/cjs/agentic/improvement/distillation/ConflictChallenger.d.ts +3 -0
- package/dist/cjs/agentic/improvement/distillation/ConflictChallenger.js +54 -0
- package/dist/cjs/agentic/improvement/distillation/FactDistiller.d.ts +10 -0
- package/dist/cjs/agentic/improvement/distillation/FactDistiller.js +115 -0
- package/dist/cjs/agentic/improvement/distillation/KnowledgeConsolidator.d.ts +6 -0
- package/dist/cjs/agentic/improvement/distillation/KnowledgeConsolidator.js +63 -0
- package/dist/cjs/agentic/improvement/distillation/RelationshipArchitect.d.ts +6 -0
- package/dist/cjs/agentic/improvement/distillation/RelationshipArchitect.js +73 -0
- package/dist/cjs/agentic/improvement/governance/MaintenanceOracle.js +5 -5
- package/dist/cjs/agentic/improvement/governance/PersonaAuditor.js +41 -29
- package/dist/cjs/agentic/improvement/governance/RemediationEngine.js +8 -3
- package/dist/cjs/agentic/improvement/governance/SkillAuditor.js +17 -9
- package/dist/cjs/agentic/improvement/hive/DomainMaster.d.ts +4 -0
- package/dist/cjs/agentic/improvement/hive/DomainMaster.js +19 -0
- package/dist/cjs/agentic/improvement/hive/KnowledgePromoter.d.ts +6 -0
- package/dist/cjs/agentic/improvement/hive/KnowledgePromoter.js +56 -0
- package/dist/cjs/agentic/improvement/hive/SkillPropagator.d.ts +6 -0
- package/dist/cjs/agentic/improvement/hive/SkillPropagator.js +91 -0
- package/dist/cjs/agentic/improvement/strategy/EvolutionVerificator.d.ts +6 -0
- package/dist/cjs/agentic/improvement/strategy/EvolutionVerificator.js +48 -0
- package/dist/cjs/agentic/improvement/strategy/MutationEngine.d.ts +10 -0
- package/dist/cjs/agentic/improvement/strategy/MutationEngine.js +119 -0
- package/dist/cjs/agentic/improvement/strategy/PerformanceAnalyst.d.ts +6 -0
- package/dist/cjs/agentic/improvement/strategy/PerformanceAnalyst.js +84 -0
- package/dist/cjs/cli/index.js +0 -0
- package/dist/cjs/types/index.d.ts +8 -0
- package/dist/esm/agentic/ActionJournal.d.ts +6 -6
- package/dist/esm/agentic/ActionJournal.js +10 -10
- package/dist/esm/agentic/CapabilityManager.d.ts +5 -5
- package/dist/esm/agentic/CapabilityManager.js +34 -19
- package/dist/esm/agentic/Cortex.js +12 -13
- package/dist/esm/agentic/PersonaManager.d.ts +4 -4
- package/dist/esm/agentic/PersonaManager.js +18 -10
- package/dist/esm/agentic/PolicyEnforcer.d.ts +4 -8
- package/dist/esm/agentic/PolicyEnforcer.js +25 -22
- package/dist/esm/agentic/improvement/AblationEngine.d.ts +7 -3
- package/dist/esm/agentic/improvement/AblationEngine.js +51 -24
- package/dist/esm/agentic/improvement/ActionRefiner.d.ts +1 -1
- package/dist/esm/agentic/improvement/ActionRefiner.js +25 -15
- package/dist/esm/agentic/improvement/EvolutionRitual.js +2 -1
- package/dist/esm/agentic/improvement/EvolutionaryPilot.d.ts +1 -1
- package/dist/esm/agentic/improvement/EvolutionaryPilot.js +17 -19
- package/dist/esm/agentic/improvement/GovernanceManager.d.ts +5 -5
- package/dist/esm/agentic/improvement/GovernanceManager.js +12 -22
- package/dist/esm/agentic/improvement/HiveLink.d.ts +3 -3
- package/dist/esm/agentic/improvement/HiveLink.js +15 -157
- package/dist/esm/agentic/improvement/KnowledgeDistiller.d.ts +15 -29
- package/dist/esm/agentic/improvement/KnowledgeDistiller.js +66 -349
- package/dist/esm/agentic/improvement/QuotaManager.d.ts +1 -1
- package/dist/esm/agentic/improvement/QuotaManager.js +11 -11
- package/dist/esm/agentic/improvement/RecursiveReasoner.d.ts +4 -4
- package/dist/esm/agentic/improvement/RecursiveReasoner.js +10 -10
- package/dist/esm/agentic/improvement/ReflectionEngine.d.ts +2 -2
- package/dist/esm/agentic/improvement/ReflectionEngine.js +2 -2
- package/dist/esm/agentic/improvement/RitualOrchestrator.d.ts +3 -3
- package/dist/esm/agentic/improvement/RitualOrchestrator.js +12 -9
- package/dist/esm/agentic/improvement/SelfEvolution.d.ts +1 -1
- package/dist/esm/agentic/improvement/SelfEvolution.js +21 -18
- package/dist/esm/agentic/improvement/SelfTestRegistry.d.ts +1 -1
- package/dist/esm/agentic/improvement/SelfTestRegistry.js +31 -19
- package/dist/esm/agentic/improvement/SovereignMetrics.d.ts +6 -6
- package/dist/esm/agentic/improvement/SovereignMetrics.js +12 -12
- package/dist/esm/agentic/improvement/StrategicPlanner.d.ts +10 -54
- package/dist/esm/agentic/improvement/StrategicPlanner.js +43 -396
- package/dist/esm/agentic/improvement/distillation/ConflictChallenger.d.ts +3 -0
- package/dist/esm/agentic/improvement/distillation/ConflictChallenger.js +51 -0
- package/dist/esm/agentic/improvement/distillation/FactDistiller.d.ts +10 -0
- package/dist/esm/agentic/improvement/distillation/FactDistiller.js +112 -0
- package/dist/esm/agentic/improvement/distillation/KnowledgeConsolidator.d.ts +6 -0
- package/dist/esm/agentic/improvement/distillation/KnowledgeConsolidator.js +60 -0
- package/dist/esm/agentic/improvement/distillation/RelationshipArchitect.d.ts +6 -0
- package/dist/esm/agentic/improvement/distillation/RelationshipArchitect.js +70 -0
- package/dist/esm/agentic/improvement/governance/MaintenanceOracle.js +5 -5
- package/dist/esm/agentic/improvement/governance/PersonaAuditor.js +41 -29
- package/dist/esm/agentic/improvement/governance/RemediationEngine.js +8 -3
- package/dist/esm/agentic/improvement/governance/SkillAuditor.js +17 -9
- package/dist/esm/agentic/improvement/hive/DomainMaster.d.ts +4 -0
- package/dist/esm/agentic/improvement/hive/DomainMaster.js +16 -0
- package/dist/esm/agentic/improvement/hive/KnowledgePromoter.d.ts +6 -0
- package/dist/esm/agentic/improvement/hive/KnowledgePromoter.js +53 -0
- package/dist/esm/agentic/improvement/hive/SkillPropagator.d.ts +6 -0
- package/dist/esm/agentic/improvement/hive/SkillPropagator.js +88 -0
- package/dist/esm/agentic/improvement/strategy/EvolutionVerificator.d.ts +6 -0
- package/dist/esm/agentic/improvement/strategy/EvolutionVerificator.js +45 -0
- package/dist/esm/agentic/improvement/strategy/MutationEngine.d.ts +10 -0
- package/dist/esm/agentic/improvement/strategy/MutationEngine.js +116 -0
- package/dist/esm/agentic/improvement/strategy/PerformanceAnalyst.d.ts +6 -0
- package/dist/esm/agentic/improvement/strategy/PerformanceAnalyst.js +81 -0
- package/dist/esm/types/index.d.ts +8 -0
- package/package.json +40 -44
|
@@ -17,14 +17,16 @@ export class PersonaManager {
|
|
|
17
17
|
/**
|
|
18
18
|
* Create or update a persona
|
|
19
19
|
*/
|
|
20
|
-
async upsertPersona(name, options = {}) {
|
|
21
|
-
|
|
20
|
+
async upsertPersona(name, options = {}, trxOrDb = this.db) {
|
|
21
|
+
const runner = async (trx) => {
|
|
22
22
|
let query = trx
|
|
23
23
|
.selectFrom(this.personasTable)
|
|
24
24
|
.selectAll()
|
|
25
25
|
.where('name', '=', name);
|
|
26
26
|
// Audit Phase 13: Atomic identity lock (Skip for SQLite)
|
|
27
|
-
|
|
27
|
+
const executor = trx.getExecutor();
|
|
28
|
+
const adapterName = executor?.adapter?.constructor?.name || executor?.dialect?.constructor?.name || '';
|
|
29
|
+
if (!adapterName.toLowerCase().includes('sqlite')) {
|
|
28
30
|
query = query.forUpdate();
|
|
29
31
|
}
|
|
30
32
|
const existing = await query.executeTakeFirst();
|
|
@@ -56,13 +58,19 @@ export class PersonaManager {
|
|
|
56
58
|
.returningAll()
|
|
57
59
|
.executeTakeFirstOrThrow();
|
|
58
60
|
return this.parsePersona(created);
|
|
59
|
-
}
|
|
61
|
+
};
|
|
62
|
+
if (trxOrDb && trxOrDb !== this.db) {
|
|
63
|
+
return await runner(trxOrDb);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
return await this.db.transaction().execute(runner);
|
|
67
|
+
}
|
|
60
68
|
}
|
|
61
69
|
/**
|
|
62
70
|
* Get a persona by name
|
|
63
71
|
*/
|
|
64
|
-
async getPersona(name) {
|
|
65
|
-
const persona = await
|
|
72
|
+
async getPersona(name, trxOrDb = this.db) {
|
|
73
|
+
const persona = await trxOrDb
|
|
66
74
|
.selectFrom(this.personasTable)
|
|
67
75
|
.selectAll()
|
|
68
76
|
.where('name', '=', name)
|
|
@@ -72,8 +80,8 @@ export class PersonaManager {
|
|
|
72
80
|
/**
|
|
73
81
|
* Delete a persona by name
|
|
74
82
|
*/
|
|
75
|
-
async deletePersona(name) {
|
|
76
|
-
const result = await
|
|
83
|
+
async deletePersona(name, trxOrDb = this.db) {
|
|
84
|
+
const result = await trxOrDb
|
|
77
85
|
.deleteFrom(this.personasTable)
|
|
78
86
|
.where('name', '=', name)
|
|
79
87
|
.executeTakeFirst();
|
|
@@ -82,8 +90,8 @@ export class PersonaManager {
|
|
|
82
90
|
/**
|
|
83
91
|
* List all personas
|
|
84
92
|
*/
|
|
85
|
-
async listPersonas() {
|
|
86
|
-
const list = await
|
|
93
|
+
async listPersonas(trxOrDb = this.db) {
|
|
94
|
+
const list = await trxOrDb
|
|
87
95
|
.selectFrom(this.personasTable)
|
|
88
96
|
.selectAll()
|
|
89
97
|
.orderBy('name', 'asc')
|
|
@@ -33,30 +33,26 @@ export declare class PolicyEnforcer {
|
|
|
33
33
|
/**
|
|
34
34
|
* Define or update a policy with robust validation.
|
|
35
35
|
*/
|
|
36
|
-
definePolicy(name: string, type: AgentPolicy['type'], definition: Record<string, any>, isEnabled?: boolean): Promise<AgentPolicy>;
|
|
36
|
+
definePolicy(name: string, type: AgentPolicy['type'], definition: Record<string, any>, isEnabled?: boolean, trxOrDb?: any): Promise<AgentPolicy>;
|
|
37
37
|
/**
|
|
38
38
|
* Comprehensive policy evaluation against a context value.
|
|
39
39
|
* Supports thresholds, regex patterns, and cumulative budgets.
|
|
40
40
|
*/
|
|
41
|
-
|
|
42
|
-
* Comprehensive policy evaluation against a context value.
|
|
43
|
-
* Supports thresholds, regex patterns, and cumulative budgets.
|
|
44
|
-
*/
|
|
45
|
-
checkPolicy(name: string, value: any, visited?: Set<string>): Promise<{
|
|
41
|
+
checkPolicy(name: string, value: any, visited?: Set<string>, trxOrDb?: any): Promise<{
|
|
46
42
|
allowed: boolean;
|
|
47
43
|
reason?: string;
|
|
48
44
|
}>;
|
|
49
45
|
/**
|
|
50
46
|
* Evaluate a full context (object) against all applicable policies.
|
|
51
47
|
*/
|
|
52
|
-
evaluateContext(context: Record<string, any
|
|
48
|
+
evaluateContext(context: Record<string, any>, trxOrDb?: any): Promise<{
|
|
53
49
|
allowed: boolean;
|
|
54
50
|
violations: string[];
|
|
55
51
|
}>;
|
|
56
52
|
/**
|
|
57
53
|
* Get all active policies.
|
|
58
54
|
*/
|
|
59
|
-
getActivePolicies(): Promise<AgentPolicy[]>;
|
|
55
|
+
getActivePolicies(trxOrDb?: any): Promise<AgentPolicy[]>;
|
|
60
56
|
private getCumulativeMetric;
|
|
61
57
|
private parsePolicy;
|
|
62
58
|
}
|
|
@@ -21,14 +21,15 @@ export class PolicyEnforcer {
|
|
|
21
21
|
/**
|
|
22
22
|
* Define or update a policy with robust validation.
|
|
23
23
|
*/
|
|
24
|
-
async definePolicy(name, type, definition, isEnabled = true) {
|
|
25
|
-
|
|
24
|
+
async definePolicy(name, type, definition, isEnabled = true, trxOrDb = this.db) {
|
|
25
|
+
const runner = async (trx) => {
|
|
26
26
|
let query = trx
|
|
27
27
|
.selectFrom(this.policiesTable)
|
|
28
28
|
.select('id')
|
|
29
29
|
.where('name', '=', name);
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
const executor = trx.getExecutor();
|
|
31
|
+
const adapterName = executor?.adapter?.constructor?.name || executor?.dialect?.constructor?.name || '';
|
|
32
|
+
if (!adapterName.toLowerCase().includes('sqlite')) {
|
|
32
33
|
query = query.forUpdate();
|
|
33
34
|
}
|
|
34
35
|
const existing = await query.executeTakeFirst();
|
|
@@ -59,17 +60,19 @@ export class PolicyEnforcer {
|
|
|
59
60
|
.returningAll()
|
|
60
61
|
.executeTakeFirstOrThrow();
|
|
61
62
|
return this.parsePolicy(created);
|
|
62
|
-
}
|
|
63
|
+
};
|
|
64
|
+
if (trxOrDb && trxOrDb !== this.db) {
|
|
65
|
+
return await runner(trxOrDb);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
return await this.db.transaction().execute(runner);
|
|
69
|
+
}
|
|
63
70
|
}
|
|
64
71
|
/**
|
|
65
72
|
* Comprehensive policy evaluation against a context value.
|
|
66
73
|
* Supports thresholds, regex patterns, and cumulative budgets.
|
|
67
74
|
*/
|
|
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()) {
|
|
75
|
+
async checkPolicy(name, value, visited = new Set(), trxOrDb = this.db) {
|
|
73
76
|
// Audit Pass 6: Re-entrancy / Circular Dependency Detection
|
|
74
77
|
if (visited.has(name)) {
|
|
75
78
|
return {
|
|
@@ -78,7 +81,7 @@ export class PolicyEnforcer {
|
|
|
78
81
|
};
|
|
79
82
|
}
|
|
80
83
|
visited.add(name);
|
|
81
|
-
const policy = await
|
|
84
|
+
const policy = await trxOrDb
|
|
82
85
|
.selectFrom(this.policiesTable)
|
|
83
86
|
.selectAll()
|
|
84
87
|
.where('name', '=', name)
|
|
@@ -109,7 +112,7 @@ export class PolicyEnforcer {
|
|
|
109
112
|
if (def.pattern.length > 500) {
|
|
110
113
|
return { allowed: false, reason: `Policy '${name}' regex pattern too long (potential ReDoS risk)` };
|
|
111
114
|
}
|
|
112
|
-
const dangerousPatterns = /(\*|\+)\1|\(\.\*\)
|
|
115
|
+
const dangerousPatterns = /(\*|\+)\1|\(\.\*\)\*|\(\[.*\](\*|\+)\)(\*|\+)|\(.*\+\)\+/;
|
|
113
116
|
if (dangerousPatterns.test(def.pattern)) {
|
|
114
117
|
return { allowed: false, reason: `Policy '${name}' contains potentially dangerous ReDoS pattern` };
|
|
115
118
|
}
|
|
@@ -137,7 +140,7 @@ export class PolicyEnforcer {
|
|
|
137
140
|
if (policy.type === 'budget' && def.metricName) {
|
|
138
141
|
const period = def.period || 'daily';
|
|
139
142
|
const limit = def.limit || 0;
|
|
140
|
-
const total = await this.getCumulativeMetric(def.metricName, period);
|
|
143
|
+
const total = await this.getCumulativeMetric(def.metricName, period, trxOrDb);
|
|
141
144
|
if (total + (typeof value === 'number' ? value : 0) > limit) {
|
|
142
145
|
return {
|
|
143
146
|
allowed: false,
|
|
@@ -149,7 +152,7 @@ export class PolicyEnforcer {
|
|
|
149
152
|
// Audit Pass 6: Moved from evaluateContext to checkPolicy for deeper nesting support
|
|
150
153
|
if (def.dependsOn && Array.isArray(def.dependsOn)) {
|
|
151
154
|
for (const depName of def.dependsOn) {
|
|
152
|
-
const result = await this.checkPolicy(depName, value, new Set(visited));
|
|
155
|
+
const result = await this.checkPolicy(depName, value, new Set(visited), trxOrDb);
|
|
153
156
|
if (!result.allowed) {
|
|
154
157
|
return { allowed: false, reason: `Composite block: ${name} -> ${result.reason}` };
|
|
155
158
|
}
|
|
@@ -160,19 +163,19 @@ export class PolicyEnforcer {
|
|
|
160
163
|
/**
|
|
161
164
|
* Evaluate a full context (object) against all applicable policies.
|
|
162
165
|
*/
|
|
163
|
-
async evaluateContext(context) {
|
|
164
|
-
const policies = await this.getActivePolicies();
|
|
166
|
+
async evaluateContext(context, trxOrDb = this.db) {
|
|
167
|
+
const policies = await this.getActivePolicies(trxOrDb);
|
|
165
168
|
const violations = [];
|
|
166
169
|
for (const policy of policies) {
|
|
167
170
|
// If the context has a key matching the policy name, check it
|
|
168
171
|
if (context[policy.name] !== undefined) {
|
|
169
|
-
const result = await this.checkPolicy(policy.name, context[policy.name]);
|
|
172
|
+
const result = await this.checkPolicy(policy.name, context[policy.name], new Set(), trxOrDb);
|
|
170
173
|
if (!result.allowed)
|
|
171
174
|
violations.push(result.reason);
|
|
172
175
|
}
|
|
173
176
|
// Check for type-specific global policies (e.g. all privacy policies)
|
|
174
177
|
if (policy.type === 'privacy' && context.content) {
|
|
175
|
-
const result = await this.checkPolicy(policy.name, context.content);
|
|
178
|
+
const result = await this.checkPolicy(policy.name, context.content, new Set(), trxOrDb);
|
|
176
179
|
if (!result.allowed)
|
|
177
180
|
violations.push(result.reason);
|
|
178
181
|
}
|
|
@@ -185,15 +188,15 @@ export class PolicyEnforcer {
|
|
|
185
188
|
/**
|
|
186
189
|
* Get all active policies.
|
|
187
190
|
*/
|
|
188
|
-
async getActivePolicies() {
|
|
189
|
-
const list = await
|
|
191
|
+
async getActivePolicies(trxOrDb = this.db) {
|
|
192
|
+
const list = await trxOrDb
|
|
190
193
|
.selectFrom(this.policiesTable)
|
|
191
194
|
.selectAll()
|
|
192
195
|
.where('is_enabled', '=', true)
|
|
193
196
|
.execute();
|
|
194
197
|
return list.map((p) => this.parsePolicy(p));
|
|
195
198
|
}
|
|
196
|
-
async getCumulativeMetric(metricName, period) {
|
|
199
|
+
async getCumulativeMetric(metricName, period, trxOrDb = this.db) {
|
|
197
200
|
const cacheKey = `${metricName}:${period}`;
|
|
198
201
|
const cached = this.metricCache.get(cacheKey);
|
|
199
202
|
const now = new Date();
|
|
@@ -215,7 +218,7 @@ export class PolicyEnforcer {
|
|
|
215
218
|
else if (period === 'hourly') {
|
|
216
219
|
cutoff = new Date(now.getTime() - 3600000);
|
|
217
220
|
}
|
|
218
|
-
const result = await
|
|
221
|
+
const result = await trxOrDb
|
|
219
222
|
.selectFrom(this.metricsTable)
|
|
220
223
|
.select((eb) => eb.fn.sum('metric_value').as('total'))
|
|
221
224
|
.where('metric_name', '=', metricName)
|
|
@@ -14,22 +14,26 @@ export declare class AblationEngine {
|
|
|
14
14
|
private linksTable;
|
|
15
15
|
constructor(db: Kysely<any>, cortex: Cortex, config?: AgenticConfig);
|
|
16
16
|
private get typedDb();
|
|
17
|
+
/**
|
|
18
|
+
* Helper to apply forUpdate only where supported (Skip for SQLite)
|
|
19
|
+
*/
|
|
20
|
+
private withLock;
|
|
17
21
|
/**
|
|
18
22
|
* Identify "Zombies": Items that have never been retrieved/hit and are old.
|
|
19
23
|
*/
|
|
20
|
-
pruneZombies(thresholdDays?: number): Promise<number>;
|
|
24
|
+
pruneZombies(thresholdDays?: number, trxOrDb?: any): Promise<number>;
|
|
21
25
|
/**
|
|
22
26
|
* Monitor Performance and perform Intelligent Rollbacks.
|
|
23
27
|
* Prioritizes recovery of items with highest historical hit counts.
|
|
24
28
|
*/
|
|
25
|
-
monitorAblationPerformance(): Promise<{
|
|
29
|
+
monitorAblationPerformance(trxOrDb?: any): Promise<{
|
|
26
30
|
status: 'stable' | 'degraded';
|
|
27
31
|
recoveredCount: number;
|
|
28
32
|
}>;
|
|
29
33
|
/**
|
|
30
34
|
* Conduct an "Ablation Test": Temporarily disable a knowledge item.
|
|
31
35
|
*/
|
|
32
|
-
testAblation(id: string | number): Promise<boolean>;
|
|
36
|
+
testAblation(id: string | number, trxOrDb?: any): Promise<boolean>;
|
|
33
37
|
/**
|
|
34
38
|
* Restore an ablated knowledge item to its original state.
|
|
35
39
|
*/
|
|
@@ -21,16 +21,27 @@ export class AblationEngine {
|
|
|
21
21
|
get typedDb() {
|
|
22
22
|
return this.db;
|
|
23
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Helper to apply forUpdate only where supported (Skip for SQLite)
|
|
26
|
+
*/
|
|
27
|
+
withLock(query, trx) {
|
|
28
|
+
const executor = trx.getExecutor();
|
|
29
|
+
const adapterName = executor?.adapter?.constructor?.name || executor?.dialect?.constructor?.name || '';
|
|
30
|
+
if (adapterName.toLowerCase().includes('sqlite')) {
|
|
31
|
+
return query;
|
|
32
|
+
}
|
|
33
|
+
return query.forUpdate();
|
|
34
|
+
}
|
|
24
35
|
/**
|
|
25
36
|
* Identify "Zombies": Items that have never been retrieved/hit and are old.
|
|
26
37
|
*/
|
|
27
|
-
async pruneZombies(thresholdDays = 30) {
|
|
38
|
+
async pruneZombies(thresholdDays = 30, trxOrDb = this.db) {
|
|
28
39
|
const cutoff = new Date(Date.now() - thresholdDays * 24 * 3600000);
|
|
29
40
|
let totalPruned = 0;
|
|
30
|
-
|
|
41
|
+
const runner = async (trx) => {
|
|
31
42
|
// 1. Prune Knowledge (with dependency check and pagination)
|
|
32
43
|
// Audit Phase 9: Paginated selection to prevent OOM
|
|
33
|
-
const
|
|
44
|
+
const query = trx
|
|
34
45
|
.selectFrom(this.knowledgeTable)
|
|
35
46
|
.selectAll()
|
|
36
47
|
.where((eb) => eb.or([
|
|
@@ -41,9 +52,8 @@ export class AblationEngine {
|
|
|
41
52
|
.where('updated_at', '<', cutoff)
|
|
42
53
|
.where('id', 'not in', (eb) => eb.selectFrom(this.linksTable).select('source_id'))
|
|
43
54
|
.where('id', 'not in', (eb) => eb.selectFrom(this.linksTable).select('target_id'))
|
|
44
|
-
.limit(500) // Audit Phase 9: Batch limit
|
|
45
|
-
|
|
46
|
-
.execute();
|
|
55
|
+
.limit(500); // Audit Phase 9: Batch limit
|
|
56
|
+
const knowledgeToPrune = await this.withLock(query, trx).execute();
|
|
47
57
|
if (knowledgeToPrune.length > 0) {
|
|
48
58
|
const candidates = knowledgeToPrune.map((k) => this.cortex.knowledge['parseKnowledge'](k));
|
|
49
59
|
const idsToDelete = [];
|
|
@@ -78,16 +88,22 @@ export class AblationEngine {
|
|
|
78
88
|
console.log(`[AblationEngine] Pruned ${totalPruned} zombie items older than ${thresholdDays} days.`);
|
|
79
89
|
}
|
|
80
90
|
return totalPruned;
|
|
81
|
-
}
|
|
91
|
+
};
|
|
92
|
+
if (trxOrDb && trxOrDb !== this.db) {
|
|
93
|
+
return await runner(trxOrDb);
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
return await this.db.transaction().execute(runner);
|
|
97
|
+
}
|
|
82
98
|
}
|
|
83
99
|
/**
|
|
84
100
|
* Monitor Performance and perform Intelligent Rollbacks.
|
|
85
101
|
* Prioritizes recovery of items with highest historical hit counts.
|
|
86
102
|
*/
|
|
87
|
-
async monitorAblationPerformance() {
|
|
88
|
-
|
|
89
|
-
const baseline = await this.cortex.metrics.getAverageMetric('success_rate');
|
|
90
|
-
const stats = await this.cortex.metrics.getMetricStats('success_rate');
|
|
103
|
+
async monitorAblationPerformance(trxOrDb = this.db) {
|
|
104
|
+
const runner = async (trx) => {
|
|
105
|
+
const baseline = await this.cortex.metrics.getAverageMetric('success_rate', trx);
|
|
106
|
+
const stats = await this.cortex.metrics.getMetricStats('success_rate', {}, trx);
|
|
91
107
|
// If current average is significantly lower than overall average
|
|
92
108
|
if (stats.count > 10 && stats.avg < baseline * 0.8) {
|
|
93
109
|
console.warn(`[AblationEngine] PERFORMANCE DEGRADATION DETECTED (Avg: ${stats.avg}, Baseline: ${baseline}). Triggering targeted recovery.`);
|
|
@@ -115,20 +131,25 @@ export class AblationEngine {
|
|
|
115
131
|
return { status: 'degraded', recoveredCount };
|
|
116
132
|
}
|
|
117
133
|
return { status: 'stable', recoveredCount: 0 };
|
|
118
|
-
}
|
|
134
|
+
};
|
|
135
|
+
if (trxOrDb && trxOrDb !== this.db) {
|
|
136
|
+
return await runner(trxOrDb);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
return await this.db.transaction().execute(runner);
|
|
140
|
+
}
|
|
119
141
|
}
|
|
120
142
|
/**
|
|
121
143
|
* Conduct an "Ablation Test": Temporarily disable a knowledge item.
|
|
122
144
|
*/
|
|
123
|
-
async testAblation(id) {
|
|
145
|
+
async testAblation(id, trxOrDb = this.db) {
|
|
124
146
|
console.log(`[AblationEngine] Conducting ablation test on item ${id}`);
|
|
125
|
-
|
|
126
|
-
const
|
|
147
|
+
const runner = async (trx) => {
|
|
148
|
+
const query = trx
|
|
127
149
|
.selectFrom(this.knowledgeTable)
|
|
128
150
|
.selectAll()
|
|
129
|
-
.where('id', '=', id)
|
|
130
|
-
|
|
131
|
-
.executeTakeFirst());
|
|
151
|
+
.where('id', '=', id);
|
|
152
|
+
const item = (await this.withLock(query, trx).executeTakeFirst());
|
|
132
153
|
if (!item)
|
|
133
154
|
return false;
|
|
134
155
|
const metadata = typeof item.metadata === 'string'
|
|
@@ -138,7 +159,7 @@ export class AblationEngine {
|
|
|
138
159
|
`Temporary confidence reduction to evaluate reasoning impact.`,
|
|
139
160
|
`Original confidence: ${item.confidence}`,
|
|
140
161
|
`Historical hits: ${metadata.hit_count || 0}`
|
|
141
|
-
]);
|
|
162
|
+
], undefined, trx);
|
|
142
163
|
await trx
|
|
143
164
|
.updateTable(this.knowledgeTable)
|
|
144
165
|
.set({
|
|
@@ -153,19 +174,25 @@ export class AblationEngine {
|
|
|
153
174
|
.where('id', '=', id)
|
|
154
175
|
.execute();
|
|
155
176
|
return true;
|
|
156
|
-
}
|
|
177
|
+
};
|
|
178
|
+
if (trxOrDb && trxOrDb !== this.db) {
|
|
179
|
+
await runner(trxOrDb);
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
await this.db.transaction().execute(runner);
|
|
183
|
+
}
|
|
184
|
+
return true;
|
|
157
185
|
}
|
|
158
186
|
/**
|
|
159
187
|
* Restore an ablated knowledge item to its original state.
|
|
160
188
|
*/
|
|
161
189
|
async recoverAblatedItem(id, trx) {
|
|
162
190
|
const recoveryStep = async (t) => {
|
|
163
|
-
const
|
|
191
|
+
const query = t
|
|
164
192
|
.selectFrom(this.knowledgeTable)
|
|
165
193
|
.selectAll()
|
|
166
|
-
.where('id', '=', id)
|
|
167
|
-
|
|
168
|
-
.executeTakeFirst());
|
|
194
|
+
.where('id', '=', id);
|
|
195
|
+
const item = (await this.withLock(query, t).executeTakeFirst());
|
|
169
196
|
if (!item)
|
|
170
197
|
return false;
|
|
171
198
|
const metadata = typeof item.metadata === 'string'
|
|
@@ -14,7 +14,7 @@ export declare class ActionRefiner {
|
|
|
14
14
|
/**
|
|
15
15
|
* Analyze recent actions and propose improvements
|
|
16
16
|
*/
|
|
17
|
-
refineActions(): Promise<string[]>;
|
|
17
|
+
refineActions(trxOrDb?: any): Promise<string[]>;
|
|
18
18
|
/**
|
|
19
19
|
* Propose a rule to reflect on a specific tool usage
|
|
20
20
|
*/
|
|
@@ -17,12 +17,12 @@ export class ActionRefiner {
|
|
|
17
17
|
/**
|
|
18
18
|
* Analyze recent actions and propose improvements
|
|
19
19
|
*/
|
|
20
|
-
async refineActions() {
|
|
20
|
+
async refineActions(trxOrDb = this.db) {
|
|
21
21
|
const recommendations = [];
|
|
22
22
|
// 1. Find tools with high failure rates (Last 24h Window)
|
|
23
23
|
// Audit Phase 14: Sliding window to prevent global table scans
|
|
24
24
|
const windowStart = new Date(Date.now() - 24 * 60 * 60 * 1000);
|
|
25
|
-
const failureStats = (await
|
|
25
|
+
const failureStats = (await trxOrDb
|
|
26
26
|
.selectFrom(this.actionsTable)
|
|
27
27
|
.select('tool_name')
|
|
28
28
|
.select((eb) => eb.fn.count('id').as('total'))
|
|
@@ -41,11 +41,11 @@ export class ActionRefiner {
|
|
|
41
41
|
if (rate > failureRateThreshold && total > minActionBatch) {
|
|
42
42
|
recommendations.push(`Tool '${stat.tool_name}' has a ${Math.round(rate * 100)}% failure rate. Suggesting automatic reflection rule.`);
|
|
43
43
|
// Automatically propose a rule to reflect on this tool's usage
|
|
44
|
-
await this.proposeReflectionRule(stat.tool_name);
|
|
44
|
+
await this.proposeReflectionRule(stat.tool_name, trxOrDb);
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
// 2. Discover missing capabilities based on error patterns (Last 24h)
|
|
48
|
-
const missingCapabilities = (await
|
|
48
|
+
const missingCapabilities = (await trxOrDb
|
|
49
49
|
.selectFrom(this.actionsTable)
|
|
50
50
|
.select('tool_name')
|
|
51
51
|
.where('status', '=', 'failure')
|
|
@@ -60,25 +60,29 @@ export class ActionRefiner {
|
|
|
60
60
|
.execute());
|
|
61
61
|
for (const row of missingCapabilities) {
|
|
62
62
|
recommendations.push(`Detected repeated access/existence failures for tool '${row.tool_name}'. Proposing capability expansion.`);
|
|
63
|
-
await this.proposeCapabilityUpdate(row.tool_name);
|
|
63
|
+
await this.proposeCapabilityUpdate(row.tool_name, trxOrDb);
|
|
64
64
|
}
|
|
65
65
|
return recommendations;
|
|
66
66
|
}
|
|
67
67
|
/**
|
|
68
68
|
* Propose a rule to reflect on a specific tool usage
|
|
69
69
|
*/
|
|
70
|
-
async proposeReflectionRule(toolName) {
|
|
70
|
+
async proposeReflectionRule(toolName, trxOrDb = this.db) {
|
|
71
71
|
// Audit Phase 19: Atomic rule proposal via transaction + existence check
|
|
72
|
-
|
|
72
|
+
const runner = async (trx) => {
|
|
73
73
|
const rulesTable = this.cortex.config.rulesTable || 'agent_rules';
|
|
74
|
-
|
|
74
|
+
let query = trx
|
|
75
75
|
.selectFrom(rulesTable)
|
|
76
76
|
.select('id')
|
|
77
|
-
.where('
|
|
77
|
+
.where('table_name', '=', 'agent_actions')
|
|
78
78
|
.where('operation', '=', 'insert')
|
|
79
|
-
.where('metadata', 'like', `%\"targetTool\":\"${toolName}\"%`)
|
|
80
|
-
|
|
81
|
-
|
|
79
|
+
.where('metadata', 'like', `%\"targetTool\":\"${toolName}\"%`);
|
|
80
|
+
const executor = trx.getExecutor();
|
|
81
|
+
const adapterName = executor?.adapter?.constructor?.name || executor?.dialect?.constructor?.name || '';
|
|
82
|
+
if (!adapterName.toLowerCase().includes('sqlite')) {
|
|
83
|
+
query = query.forUpdate();
|
|
84
|
+
}
|
|
85
|
+
const existing = await query.executeTakeFirst();
|
|
82
86
|
if (!existing) {
|
|
83
87
|
console.log(`[ActionRefiner] Proposing reflection rule for tool: ${toolName}`);
|
|
84
88
|
await this.cortex.rules.defineRule('agent_actions', 'insert', 'audit', {
|
|
@@ -88,16 +92,22 @@ export class ActionRefiner {
|
|
|
88
92
|
},
|
|
89
93
|
}, trx); // Pass transaction object
|
|
90
94
|
}
|
|
91
|
-
}
|
|
95
|
+
};
|
|
96
|
+
if (trxOrDb && trxOrDb !== this.db) {
|
|
97
|
+
await runner(trxOrDb);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
await this.db.transaction().execute((trx) => runner(trx));
|
|
101
|
+
}
|
|
92
102
|
}
|
|
93
103
|
/**
|
|
94
104
|
* Propose an update to capabilities
|
|
95
105
|
*/
|
|
96
|
-
async proposeCapabilityUpdate(toolName) {
|
|
106
|
+
async proposeCapabilityUpdate(toolName, trxOrDb = this.db) {
|
|
97
107
|
console.log(`[ActionRefiner] Proposing capability expansion for tool: ${toolName}`);
|
|
98
108
|
await this.cortex.reflections.reflect('system', 'failure', `Architectural Gap: Missing Capability for '${toolName}'`, [
|
|
99
109
|
`Identified repeated failures using tool '${toolName}'.`,
|
|
100
110
|
`Resolution: Inspect permission sets and ensure the tool is correctly registered in the CapabilityManager.`,
|
|
101
|
-
]);
|
|
111
|
+
], undefined, trxOrDb);
|
|
102
112
|
}
|
|
103
113
|
}
|
|
@@ -62,7 +62,8 @@ export class EvolutionRitual {
|
|
|
62
62
|
// Find domains that are currently "hot" (high density of recent knowledge)
|
|
63
63
|
// Refactored Phase 13: Paginated scanning to handle large knowledge bursts
|
|
64
64
|
const domainScores = new Map();
|
|
65
|
-
const
|
|
65
|
+
const lookbackHours = this.config.evolutionLookbackHours || 24;
|
|
66
|
+
const cutoff = new Date(Date.now() - lookbackHours * 60 * 60 * 1000);
|
|
66
67
|
let offset = 0;
|
|
67
68
|
const limit = 1000;
|
|
68
69
|
while (true) {
|
|
@@ -16,7 +16,7 @@ export class EvolutionaryPilot {
|
|
|
16
16
|
/**
|
|
17
17
|
* Run a self-improvement cycle based on dynamic baselining
|
|
18
18
|
*/
|
|
19
|
-
async runSelfImprovementCycle() {
|
|
19
|
+
async runSelfImprovementCycle(trxOrDb = this.db) {
|
|
20
20
|
console.log('[EvolutionaryPilot] Initiating self-improvement cycle with full-spectrum baselining...');
|
|
21
21
|
const changes = [];
|
|
22
22
|
let evolved = false;
|
|
@@ -28,7 +28,7 @@ export class EvolutionaryPilot {
|
|
|
28
28
|
'trust_signal',
|
|
29
29
|
];
|
|
30
30
|
const samplingCount = this.config.evolution?.samplingCount || 100;
|
|
31
|
-
const recentMetrics = await this.cortex.metrics.getRecentMetrics(samplingCount);
|
|
31
|
+
const recentMetrics = await this.cortex.metrics.getRecentMetrics(samplingCount, trxOrDb);
|
|
32
32
|
for (const metricName of metrics) {
|
|
33
33
|
// Audit Phase 17: Bounded metric slice for scale-safe baselining
|
|
34
34
|
const values = recentMetrics
|
|
@@ -41,14 +41,14 @@ export class EvolutionaryPilot {
|
|
|
41
41
|
const minSamples = this.config.evolution?.minSamples || 5;
|
|
42
42
|
if (values.length < minSamples)
|
|
43
43
|
continue;
|
|
44
|
-
const policies = await this.cortex.policies.getActivePolicies();
|
|
44
|
+
const policies = await this.cortex.policies.getActivePolicies(trxOrDb);
|
|
45
45
|
const latencyZ = policies.find(p => p.name === 'latency_drift_z')?.definition?.threshold || 2.0;
|
|
46
46
|
const latencyMean = policies.find(p => p.name === 'latency_mean_ceiling')?.definition?.threshold || 1000;
|
|
47
47
|
console.log(`[EvolutionaryPilot] Baselining ${metricName}: Mean=${stats.mean.toFixed(2)}, StdDev=${stats.stdDev.toFixed(2)}, Current=${stats.current.toFixed(2)}, Z-Score=${stats.zScore.toFixed(2)}`);
|
|
48
48
|
// 2. Trigger Evolution based on metric-specific thresholds
|
|
49
49
|
if (metricName === 'query_latency' &&
|
|
50
50
|
(stats.zScore > latencyZ || stats.mean > latencyMean)) {
|
|
51
|
-
const result = await this.optimizeLatency();
|
|
51
|
+
const result = await this.optimizeLatency(trxOrDb);
|
|
52
52
|
if (result) {
|
|
53
53
|
changes.push(...result);
|
|
54
54
|
evolved = true;
|
|
@@ -59,7 +59,7 @@ export class EvolutionaryPilot {
|
|
|
59
59
|
if (metricName === 'success_rate' &&
|
|
60
60
|
(stats.zScore < successZ || stats.mean < successMean)) {
|
|
61
61
|
console.warn(`[EvolutionaryPilot] Success rate collapse detected (${stats.mean.toFixed(2)}). Triggering strategic mutation.`);
|
|
62
|
-
const strategies = await this.cortex.strategy.mutateStrategy();
|
|
62
|
+
const strategies = await this.cortex.strategy.mutateStrategy(trxOrDb);
|
|
63
63
|
changes.push(...strategies);
|
|
64
64
|
evolved = true;
|
|
65
65
|
}
|
|
@@ -72,13 +72,13 @@ export class EvolutionaryPilot {
|
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
// 3. Meta-Meta Evolution Tuning
|
|
75
|
-
const tuned = await this.tuneEmergentSkillHyperparameters(recentMetrics);
|
|
75
|
+
const tuned = await this.tuneEmergentSkillHyperparameters(recentMetrics, trxOrDb);
|
|
76
76
|
if (tuned) {
|
|
77
77
|
changes.push('Self-tuned emergent skill hyperparameters (Meta-Meta Evolution)');
|
|
78
78
|
evolved = true;
|
|
79
79
|
}
|
|
80
80
|
// 4. Verify: Perform an audit
|
|
81
|
-
const audit = await this.cortex.governor.performAudit();
|
|
81
|
+
const audit = await this.cortex.governor.performAudit(trxOrDb);
|
|
82
82
|
if (!audit.healthy) {
|
|
83
83
|
console.warn('[EvolutionaryPilot] Evolution resulted in unhealthy state. Reverting may be required.');
|
|
84
84
|
changes.push('WARNING: Unhealthy state detected after evolution');
|
|
@@ -89,11 +89,11 @@ export class EvolutionaryPilot {
|
|
|
89
89
|
* Meta-Meta Evolution: Adjusts the hyperparameters of the SkillSynthesizer
|
|
90
90
|
* based on the systemic success or failure of recently verified skills.
|
|
91
91
|
*/
|
|
92
|
-
async tuneEmergentSkillHyperparameters(recentMetrics) {
|
|
92
|
+
async tuneEmergentSkillHyperparameters(recentMetrics, trxOrDb = this.db) {
|
|
93
93
|
console.log(`[EvolutionaryPilot] Running Meta-Meta Evolution tuning...`);
|
|
94
94
|
// Count how many skills are currently blacklisted vs verified
|
|
95
|
-
const blacklisted = await this.cortex.capabilities.getCapabilities('blacklisted');
|
|
96
|
-
const verified = await this.cortex.capabilities.getCapabilities('verified');
|
|
95
|
+
const blacklisted = await this.cortex.capabilities.getCapabilities('blacklisted', trxOrDb);
|
|
96
|
+
const verified = await this.cortex.capabilities.getCapabilities('verified', trxOrDb);
|
|
97
97
|
let tuned = false;
|
|
98
98
|
const config = this.config.evolution;
|
|
99
99
|
if (!config)
|
|
@@ -150,21 +150,19 @@ export class EvolutionaryPilot {
|
|
|
150
150
|
const zScore = stdDev === 0 ? 0 : (current - mean) / stdDev;
|
|
151
151
|
return { mean, stdDev, current, zScore };
|
|
152
152
|
}
|
|
153
|
-
async optimizeLatency() {
|
|
153
|
+
async optimizeLatency(trxOrDb = this.db) {
|
|
154
154
|
const changes = [];
|
|
155
155
|
console.log(`[EvolutionaryPilot] Triggering latency optimization...`);
|
|
156
|
-
const
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
.adapter.constructor.name.toLowerCase()
|
|
160
|
-
.includes('sqlite') ||
|
|
161
|
-
(dialect && dialect.constructor.name.toLowerCase().includes('sqlite'));
|
|
156
|
+
const executor = trxOrDb.getExecutor();
|
|
157
|
+
const adapterName = executor?.adapter?.constructor?.name || executor?.dialect?.constructor?.name || '';
|
|
158
|
+
const isSqlite = adapterName.toLowerCase().includes('sqlite');
|
|
162
159
|
if (isSqlite) {
|
|
163
|
-
await sql `PRAGMA optimize`.execute(
|
|
160
|
+
await sql `PRAGMA optimize`.execute(trxOrDb);
|
|
164
161
|
changes.push('Applied PRAGMA optimize');
|
|
165
162
|
}
|
|
166
163
|
const messagesTable = this.config.messagesTable || 'agent_messages';
|
|
167
|
-
|
|
164
|
+
// NOTE: cortex.evolution.evolve should be transaction-aware
|
|
165
|
+
await this.cortex.evolution.evolve(`CREATE INDEX IF NOT EXISTS idx_agent_msg_session_time ON ${messagesTable}(session_id, created_at)`, {}, trxOrDb);
|
|
168
166
|
changes.push(`Applied composite index to ${messagesTable}`);
|
|
169
167
|
return changes;
|
|
170
168
|
}
|