Skip to main content
Glama
adaptive-strategy-system.test.ts27.9 kB
/** * Tests for Adaptive Strategy System * * Tests pattern identification, strategy effectiveness measurement, * adaptive rule adjustment, and improvement tracking. */ import { beforeEach, describe, expect, it } from "vitest"; import { AdaptiveStrategySystem } from "../../../metacognitive/adaptive-strategy-system"; import type { Context, Feedback, Outcome, Performance, Strategy, StrategyExecution, } from "../../../metacognitive/types"; // Helper function to create proper Outcome objects function createOutcome(success: boolean, quality: number): Outcome { return { id: `outcome-${Date.now()}-${Math.random()}`, success, quality, description: success ? "Success" : "Failure", timestamp: new Date(), }; } describe("AdaptiveStrategySystem", () => { let system: AdaptiveStrategySystem; beforeEach(() => { system = new AdaptiveStrategySystem(); }); describe("Pattern Identification", () => { describe("Success Patterns", () => { it("should identify success patterns from execution history", () => { const history: StrategyExecution[] = [ { id: "exec1", strategyId: "analytical", context: { complexity: "high", uncertainty: "low" }, outcome: createOutcome(true, 0.9), timestamp: new Date(), }, { id: "exec2", strategyId: "analytical", context: { complexity: "high", uncertainty: "low" }, outcome: createOutcome(true, 0.85), timestamp: new Date(), }, { id: "exec3", strategyId: "analytical", context: { complexity: "high", uncertainty: "low" }, outcome: createOutcome(true, 0.88), timestamp: new Date(), }, ]; const patterns = system.identifySuccessPatterns(history); expect(patterns).toBeDefined(); expect(patterns.length).toBeGreaterThan(0); expect(patterns[0]).toHaveProperty("strategyId"); expect(patterns[0]).toHaveProperty("contextFactors"); expect(patterns[0]).toHaveProperty("confidence"); }); it("should extract contextual factors from success patterns", () => { const history: StrategyExecution[] = [ { id: "exec1", strategyId: "creative", context: { complexity: "moderate", uncertainty: "high", timePressure: "low" }, outcome: createOutcome(true, 0.92), timestamp: new Date(), }, { id: "exec2", strategyId: "creative", context: { complexity: "moderate", uncertainty: "high", timePressure: "low" }, outcome: createOutcome(true, 0.89), timestamp: new Date(), }, ]; const patterns = system.identifySuccessPatterns(history); expect(patterns[0].contextFactors).toContain("complexity:moderate"); expect(patterns[0].contextFactors).toContain("uncertainty:high"); }); it("should calculate pattern confidence scores", () => { const history: StrategyExecution[] = [ { id: "exec1", strategyId: "systematic", context: { complexity: "simple" }, outcome: createOutcome(true, 0.8), timestamp: new Date(), }, { id: "exec2", strategyId: "systematic", context: { complexity: "simple" }, outcome: createOutcome(true, 0.85), timestamp: new Date(), }, { id: "exec3", strategyId: "systematic", context: { complexity: "simple" }, outcome: createOutcome(true, 0.9), timestamp: new Date(), }, ]; const patterns = system.identifySuccessPatterns(history); expect(patterns[0].confidence).toBeGreaterThan(0); expect(patterns[0].confidence).toBeLessThanOrEqual(1); }); it("should handle empty execution history", () => { const patterns = system.identifySuccessPatterns([]); expect(patterns).toBeDefined(); expect(patterns.length).toBe(0); }); it("should handle history with no successes", () => { const history: StrategyExecution[] = [ { id: "exec1", strategyId: "analytical", context: { complexity: "high" }, outcome: createOutcome(false, 0.3), timestamp: new Date(), }, ]; const patterns = system.identifySuccessPatterns(history); expect(patterns).toBeDefined(); expect(patterns.length).toBe(0); }); }); describe("Failure Patterns", () => { it("should identify failure patterns from execution history", () => { const history: StrategyExecution[] = [ { id: "exec1", strategyId: "creative", context: { complexity: "simple", timePressure: "high" }, outcome: createOutcome(false, 0.3), timestamp: new Date(), }, { id: "exec2", strategyId: "creative", context: { complexity: "simple", timePressure: "high" }, outcome: createOutcome(false, 0.25), timestamp: new Date(), }, ]; const patterns = system.identifyFailurePatterns(history); expect(patterns).toBeDefined(); expect(patterns.length).toBeGreaterThan(0); expect(patterns[0]).toHaveProperty("strategyId"); expect(patterns[0]).toHaveProperty("contextFactors"); expect(patterns[0]).toHaveProperty("confidence"); }); it("should identify anti-patterns in failures", () => { const history: StrategyExecution[] = [ { id: "exec1", strategyId: "analytical", context: { complexity: "low", uncertainty: "high" }, outcome: createOutcome(false, 0.4), timestamp: new Date(), }, { id: "exec2", strategyId: "analytical", context: { complexity: "low", uncertainty: "high" }, outcome: createOutcome(false, 0.35), timestamp: new Date(), }, ]; const patterns = system.identifyFailurePatterns(history); expect(patterns[0].contextFactors).toContain("uncertainty:high"); }); it("should handle history with no failures", () => { const history: StrategyExecution[] = [ { id: "exec1", strategyId: "analytical", context: { complexity: "high" }, outcome: createOutcome(true, 0.9), timestamp: new Date(), }, ]; const patterns = system.identifyFailurePatterns(history); expect(patterns).toBeDefined(); expect(patterns.length).toBe(0); }); }); }); describe("Strategy Effectiveness Measurement", () => { it("should measure strategy effectiveness with multiple outcomes", () => { const strategy: Strategy = { id: "analytical", name: "Analytical Strategy", rules: [], }; const outcomes: Outcome[] = [ { id: "o1", success: true, quality: 0.9, description: "Good", timestamp: new Date() }, { id: "o2", success: true, quality: 0.85, description: "Good", timestamp: new Date() }, { id: "o3", success: false, quality: 0.4, description: "Poor", timestamp: new Date() }, ]; const effectiveness = system.measureStrategyEffectiveness(strategy, outcomes); expect(effectiveness).toBeGreaterThan(0); expect(effectiveness).toBeLessThanOrEqual(1); }); it("should weight effectiveness by outcome quality", () => { const strategy: Strategy = { id: "creative", name: "Creative Strategy", rules: [], }; const highQualityOutcomes: Outcome[] = [ { id: "o1", success: true, quality: 0.95, description: "Excellent", timestamp: new Date() }, { id: "o2", success: true, quality: 0.92, description: "Excellent", timestamp: new Date() }, ]; const lowQualityOutcomes: Outcome[] = [ { id: "o3", success: true, quality: 0.6, description: "Mediocre", timestamp: new Date() }, { id: "o4", success: true, quality: 0.55, description: "Mediocre", timestamp: new Date() }, ]; const highEffectiveness = system.measureStrategyEffectiveness(strategy, highQualityOutcomes); const lowEffectiveness = system.measureStrategyEffectiveness(strategy, lowQualityOutcomes); expect(highEffectiveness).toBeGreaterThan(lowEffectiveness); }); it("should handle strategy with no outcomes", () => { const strategy: Strategy = { id: "systematic", name: "Systematic Strategy", rules: [], }; const effectiveness = system.measureStrategyEffectiveness(strategy, []); expect(effectiveness).toBe(0); }); it("should normalize effectiveness scores to 0-1 range", () => { const strategy: Strategy = { id: "hybrid", name: "Hybrid Strategy", rules: [], }; const outcomes: Outcome[] = [ { id: "o1", success: true, quality: 1.0, description: "Perfect", timestamp: new Date() }, { id: "o2", success: true, quality: 0.9, description: "Great", timestamp: new Date() }, ]; const effectiveness = system.measureStrategyEffectiveness(strategy, outcomes); expect(effectiveness).toBeGreaterThanOrEqual(0); expect(effectiveness).toBeLessThanOrEqual(1); }); it("should compare strategies in same context", () => { const strategy1: Strategy = { id: "analytical", name: "Analytical", rules: [], }; const strategy2: Strategy = { id: "creative", name: "Creative", rules: [], }; const context: Context = { complexity: "high", uncertainty: "low", }; const comparison = system.compareStrategies([strategy1, strategy2], context); expect(comparison).toBeDefined(); expect(comparison).toHaveProperty("rankings"); expect(comparison.rankings.length).toBe(2); expect(comparison.rankings[0]).toHaveProperty("strategyId"); expect(comparison.rankings[0]).toHaveProperty("score"); }); it("should rank strategies by effectiveness", () => { const strategy1: Strategy = { id: "high-performer", name: "High Performer", rules: [], }; const strategy2: Strategy = { id: "low-performer", name: "Low Performer", rules: [], }; const context: Context = { complexity: "moderate", }; const comparison = system.compareStrategies([strategy1, strategy2], context); expect(comparison.rankings[0].score).toBeGreaterThanOrEqual(comparison.rankings[1].score); }); }); describe("Adaptive Rule Adjustment", () => { it("should adjust strategy rules based on patterns", () => { const patterns = [ { strategyId: "analytical", contextFactors: ["complexity:high", "uncertainty:low"], confidence: 0.85, sampleSize: 10, }, ]; expect(() => system.adjustStrategyRules(patterns)).not.toThrow(); }); it("should update rule weights dynamically", () => { const patterns = [ { strategyId: "creative", contextFactors: ["uncertainty:high"], confidence: 0.8, sampleSize: 8, }, ]; system.adjustStrategyRules(patterns); // Verify rules were adjusted (implementation-specific) expect(true).toBe(true); }); it("should add new rules for discovered patterns", () => { const patterns = [ { strategyId: "systematic", contextFactors: ["complexity:simple", "timePressure:low"], confidence: 0.9, sampleSize: 12, }, ]; system.adjustStrategyRules(patterns); // Verify new rules were added (implementation-specific) expect(true).toBe(true); }); it("should validate rule adjustments", () => { const invalidPatterns = [ { strategyId: "", contextFactors: [], confidence: -0.5, // Invalid confidence sampleSize: 0, }, ]; expect(() => system.adjustStrategyRules(invalidPatterns)).not.toThrow(); }); it("should update strategy selection based on feedback", () => { const feedback: Feedback[] = [ { id: "f1", strategyId: "analytical", rating: 0.9, context: { complexity: "high" }, timestamp: new Date(), }, { id: "f2", strategyId: "creative", rating: 0.6, context: { complexity: "high" }, timestamp: new Date(), }, ]; expect(() => system.updateStrategySelection(feedback)).not.toThrow(); }); }); describe("Improvement Tracking", () => { it("should calculate improvement metrics", () => { const baseline: Performance = { successRate: 0.7, averageQuality: 0.75, averageTime: 5000, timestamp: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000), // 30 days ago }; const current: Performance = { successRate: 0.8, averageQuality: 0.85, averageTime: 4500, timestamp: new Date(), }; const improvement = system.demonstrateImprovement(baseline, current); expect(improvement).toBeDefined(); expect(improvement).toHaveProperty("successRateImprovement"); expect(improvement).toHaveProperty("qualityImprovement"); expect(improvement).toHaveProperty("timeImprovement"); }); it("should calculate improvement percentages", () => { const baseline: Performance = { successRate: 0.7, averageQuality: 0.7, averageTime: 5000, timestamp: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000), }; const current: Performance = { successRate: 0.77, // 10% improvement averageQuality: 0.77, // 10% improvement averageTime: 4500, // 10% improvement timestamp: new Date(), }; const improvement = system.demonstrateImprovement(baseline, current); expect(improvement.successRateImprovement).toBeCloseTo(0.1, 1); expect(improvement.qualityImprovement).toBeCloseTo(0.1, 1); expect(improvement.timeImprovement).toBeCloseTo(0.1, 1); }); it("should identify improvement trends", () => { const baseline: Performance = { successRate: 0.7, averageQuality: 0.7, averageTime: 5000, timestamp: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000), }; const current: Performance = { successRate: 0.8, averageQuality: 0.85, averageTime: 4000, timestamp: new Date(), }; const improvement = system.demonstrateImprovement(baseline, current); expect(improvement).toHaveProperty("trend"); expect(improvement.trend).toBe("improving"); }); it("should handle no improvement scenario", () => { const baseline: Performance = { successRate: 0.8, averageQuality: 0.8, averageTime: 4000, timestamp: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000), }; const current: Performance = { successRate: 0.8, averageQuality: 0.8, averageTime: 4000, timestamp: new Date(), }; const improvement = system.demonstrateImprovement(baseline, current); expect(improvement.successRateImprovement).toBe(0); expect(improvement.qualityImprovement).toBe(0); expect(improvement.trend).toBe("stable"); }); it("should handle declining performance", () => { const baseline: Performance = { successRate: 0.8, averageQuality: 0.85, averageTime: 4000, timestamp: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000), }; const current: Performance = { successRate: 0.7, averageQuality: 0.75, averageTime: 5000, timestamp: new Date(), }; const improvement = system.demonstrateImprovement(baseline, current); expect(improvement.successRateImprovement).toBeLessThan(0); expect(improvement.qualityImprovement).toBeLessThan(0); expect(improvement.trend).toBe("declining"); }); }); describe("Adaptation Speed and Performance", () => { it("should complete pattern identification quickly", () => { const history: StrategyExecution[] = Array.from({ length: 1000 }, (_, i) => ({ id: `exec${i}`, strategyId: i % 2 === 0 ? "analytical" : "creative", context: { complexity: i % 3 === 0 ? "high" : "moderate" }, outcome: createOutcome(i % 4 !== 0, 0.7 + Math.random() * 0.3), timestamp: new Date(), })); const start = Date.now(); system.identifySuccessPatterns(history); const duration = Date.now() - start; expect(duration).toBeLessThan(1000); // Should complete in < 1 second }); it("should handle concurrent adaptation requests", async () => { const history: StrategyExecution[] = Array.from({ length: 100 }, (_, i) => ({ id: `exec${i}`, strategyId: "analytical", context: { complexity: "high" }, outcome: createOutcome(true, 0.8), timestamp: new Date(), })); const promises = [ Promise.resolve(system.identifySuccessPatterns(history)), Promise.resolve(system.identifyFailurePatterns(history)), Promise.resolve(system.identifySuccessPatterns(history)), ]; await expect(Promise.all(promises)).resolves.toBeDefined(); }); it("should maintain low overhead", () => { const history: StrategyExecution[] = Array.from({ length: 500 }, (_, i) => ({ id: `exec${i}`, strategyId: "systematic", context: { complexity: "moderate" }, outcome: createOutcome(true, 0.8), timestamp: new Date(), })); const start = Date.now(); system.identifySuccessPatterns(history); system.identifyFailurePatterns(history); const duration = Date.now() - start; // Overhead should be minimal (< 500ms for 500 executions) expect(duration).toBeLessThan(500); }); }); describe("Edge Cases", () => { it("should handle mixed success/failure patterns", () => { const history: StrategyExecution[] = [ { id: "exec1", strategyId: "analytical", context: { complexity: "high" }, outcome: createOutcome(true, 0.9), timestamp: new Date(), }, { id: "exec2", strategyId: "analytical", context: { complexity: "high" }, outcome: createOutcome(false, 0.3), timestamp: new Date(), }, { id: "exec3", strategyId: "analytical", context: { complexity: "high" }, outcome: createOutcome(true, 0.85), timestamp: new Date(), }, { id: "exec4", strategyId: "analytical", context: { complexity: "high" }, outcome: createOutcome(false, 0.25), timestamp: new Date(), }, ]; const successPatterns = system.identifySuccessPatterns(history); const failurePatterns = system.identifyFailurePatterns(history); expect(successPatterns.length).toBeGreaterThan(0); expect(failurePatterns.length).toBeGreaterThan(0); }); it("should handle strategies with insufficient data", () => { const strategy: Strategy = { id: "new-strategy", name: "New Strategy", rules: [], }; const outcomes: Outcome[] = [ { id: "o1", success: true, quality: 0.8, description: "Single outcome", timestamp: new Date(), }, ]; const effectiveness = system.measureStrategyEffectiveness(strategy, outcomes); expect(effectiveness).toBeGreaterThanOrEqual(0); expect(effectiveness).toBeLessThanOrEqual(1); }); it("should handle context with missing factors", () => { const strategy1: Strategy = { id: "s1", name: "Strategy 1", rules: [], }; const context: Context = {}; // Empty context const comparison = system.compareStrategies([strategy1], context); expect(comparison).toBeDefined(); expect(comparison.rankings.length).toBe(1); }); it("should handle baseline with zero success rate", () => { const baseline: Performance = { successRate: 0, averageQuality: 0.7, averageTime: 5000, timestamp: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000), }; const current: Performance = { successRate: 0.5, averageQuality: 0.8, averageTime: 4500, timestamp: new Date(), }; const improvement = system.demonstrateImprovement(baseline, current); expect(improvement.successRateImprovement).toBe(0); expect(improvement.qualityImprovement).toBeGreaterThan(0); expect(improvement.timeImprovement).toBeGreaterThan(0); }); it("should handle baseline with zero quality", () => { const baseline: Performance = { successRate: 0.7, averageQuality: 0, averageTime: 5000, timestamp: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000), }; const current: Performance = { successRate: 0.8, averageQuality: 0.8, averageTime: 4500, timestamp: new Date(), }; const improvement = system.demonstrateImprovement(baseline, current); expect(improvement.successRateImprovement).toBeGreaterThan(0); expect(improvement.qualityImprovement).toBe(0); expect(improvement.timeImprovement).toBeGreaterThan(0); }); it("should handle baseline with zero time", () => { const baseline: Performance = { successRate: 0.7, averageQuality: 0.7, averageTime: 0, timestamp: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000), }; const current: Performance = { successRate: 0.8, averageQuality: 0.8, averageTime: 4500, timestamp: new Date(), }; const improvement = system.demonstrateImprovement(baseline, current); expect(improvement.successRateImprovement).toBeGreaterThan(0); expect(improvement.qualityImprovement).toBeGreaterThan(0); expect(improvement.timeImprovement).toBe(0); }); }); describe("Execution History Management", () => { it("should record strategy execution", () => { const execution: StrategyExecution = { id: "exec1", strategyId: "analytical", context: { complexity: "high" }, outcome: createOutcome(true, 0.9), timestamp: new Date(), }; system.recordExecution(execution); const history = system.getExecutionHistory(); expect(history).toHaveLength(1); expect(history[0]).toEqual(execution); }); it("should record multiple executions", () => { const execution1: StrategyExecution = { id: "exec1", strategyId: "analytical", context: { complexity: "high" }, outcome: createOutcome(true, 0.9), timestamp: new Date(), }; const execution2: StrategyExecution = { id: "exec2", strategyId: "creative", context: { complexity: "moderate" }, outcome: createOutcome(true, 0.85), timestamp: new Date(), }; system.recordExecution(execution1); system.recordExecution(execution2); const history = system.getExecutionHistory(); expect(history).toHaveLength(2); expect(history[0]).toEqual(execution1); expect(history[1]).toEqual(execution2); }); it("should return copy of execution history", () => { const execution: StrategyExecution = { id: "exec1", strategyId: "analytical", context: { complexity: "high" }, outcome: createOutcome(true, 0.9), timestamp: new Date(), }; system.recordExecution(execution); const history1 = system.getExecutionHistory(); const history2 = system.getExecutionHistory(); expect(history1).not.toBe(history2); // Different array instances expect(history1).toEqual(history2); // Same content }); it("should clear execution history", () => { const execution1: StrategyExecution = { id: "exec1", strategyId: "analytical", context: { complexity: "high" }, outcome: createOutcome(true, 0.9), timestamp: new Date(), }; const execution2: StrategyExecution = { id: "exec2", strategyId: "creative", context: { complexity: "moderate" }, outcome: createOutcome(true, 0.85), timestamp: new Date(), }; system.recordExecution(execution1); system.recordExecution(execution2); expect(system.getExecutionHistory()).toHaveLength(2); system.clearHistory(); expect(system.getExecutionHistory()).toHaveLength(0); }); it("should use recorded history in strategy comparison", () => { const strategy1: Strategy = { id: "analytical", name: "Analytical", rules: [], }; const strategy2: Strategy = { id: "creative", name: "Creative", rules: [], }; const context: Context = { complexity: "high", uncertainty: "low", }; // Record executions for analytical strategy with similar context for (let i = 0; i < 5; i++) { system.recordExecution({ id: `exec-analytical-${i}`, strategyId: "analytical", context: { complexity: "high", uncertainty: "low" }, outcome: createOutcome(true, 0.9), timestamp: new Date(), }); } // Record executions for creative strategy with similar context for (let i = 0; i < 5; i++) { system.recordExecution({ id: `exec-creative-${i}`, strategyId: "creative", context: { complexity: "high", uncertainty: "low" }, outcome: createOutcome(true, 0.7), timestamp: new Date(), }); } const comparison = system.compareStrategies([strategy1, strategy2], context); expect(comparison.rankings).toHaveLength(2); // Analytical should rank higher due to better outcomes expect(comparison.rankings[0].strategyId).toBe("analytical"); expect(comparison.rankings[0].score).toBeGreaterThan(comparison.rankings[1].score); expect(comparison.rankings[0].confidence).toBeGreaterThan(0); }); it("should handle strategy comparison with no relevant history", () => { const strategy1: Strategy = { id: "new-strategy", name: "New Strategy", rules: [], }; const context: Context = { complexity: "high", }; // Record executions for different strategy system.recordExecution({ id: "exec1", strategyId: "other-strategy", context: { complexity: "low" }, outcome: createOutcome(true, 0.9), timestamp: new Date(), }); const comparison = system.compareStrategies([strategy1], context); expect(comparison.rankings).toHaveLength(1); expect(comparison.rankings[0].score).toBe(0); // No relevant history expect(comparison.rankings[0].confidence).toBe(0); // No samples }); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/keyurgolani/ThoughtMcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server