Skip to main content
Glama
bias-monitoring-system.test.ts8.12 kB
/** * Tests for BiasMonitoringSystem - Continuous Reasoning Analysis * * Tests the continuous monitoring of reasoning chains for bias detection, * real-time alert generation, and performance overhead measurement. */ import { afterEach, beforeEach, describe, expect, it } from "vitest"; import { BiasMonitoringSystem } from "../../../bias/bias-monitoring-system"; import { BiasPatternRecognizer } from "../../../bias/bias-pattern-recognizer"; import type { ReasoningChain } from "../../../bias/types"; import { deterministicId, resetDeterministicId } from "../../utils/test-helpers"; /** * Helper: Create test reasoning chain */ function createTestReasoningChain(overrides: Partial<ReasoningChain> = {}): ReasoningChain { return { id: overrides.id ?? deterministicId("chain"), steps: overrides.steps ?? [ { id: "step-1", content: "Initial hypothesis", type: "hypothesis", confidence: 0.8, }, ], branches: overrides.branches ?? [], assumptions: overrides.assumptions ?? [], inferences: overrides.inferences ?? [], evidence: overrides.evidence ?? [], conclusion: overrides.conclusion ?? "Test conclusion", confidence: overrides.confidence ?? 0.8, }; } /** * Helper: Create reasoning chain with confirmation bias */ function createBiasedReasoningChain(): ReasoningChain { return createTestReasoningChain({ steps: [ { id: "step-1", content: "I believe this approach will work", type: "hypothesis", confidence: 0.9, }, ], evidence: [ { id: "ev-1", content: "Supporting evidence", source: "test", relevance: 0.9, }, { id: "ev-2", content: "More supporting evidence", source: "test", relevance: 0.85, }, ], }); } describe("BiasMonitoringSystem", () => { let recognizer: BiasPatternRecognizer; let monitoringSystem: BiasMonitoringSystem; beforeEach(() => { recognizer = new BiasPatternRecognizer(); monitoringSystem = new BiasMonitoringSystem(recognizer); resetDeterministicId(); }); afterEach(() => { if (monitoringSystem) { monitoringSystem.stop(); } }); describe("Continuous Monitoring", () => { it("should start monitoring and process reasoning chains", async () => { const chain = createTestReasoningChain(); await monitoringSystem.monitorContinuously(chain); const metrics = monitoringSystem.getMetrics(); expect(metrics.totalChains).toBe(1); }); it("should process multiple chains sequentially", async () => { const chain1 = createTestReasoningChain({ id: "chain-1" }); const chain2 = createTestReasoningChain({ id: "chain-2" }); const chain3 = createTestReasoningChain({ id: "chain-3" }); await monitoringSystem.monitorContinuously(chain1); await monitoringSystem.monitorContinuously(chain2); await monitoringSystem.monitorContinuously(chain3); const metrics = monitoringSystem.getMetrics(); expect(metrics.totalChains).toBe(3); }); it("should handle invalid reasoning chains gracefully", async () => { const invalidChain = { id: "invalid", steps: [], branches: [], assumptions: [], inferences: [], evidence: [], conclusion: "", } as ReasoningChain; await expect(monitoringSystem.monitorContinuously(invalidChain)).resolves.not.toThrow(); const metrics = monitoringSystem.getMetrics(); expect(metrics.totalChains).toBe(1); }); it("should handle null and undefined reasoning chains gracefully", async () => { await expect(monitoringSystem.monitorContinuously(null as any)).resolves.not.toThrow(); await expect(monitoringSystem.monitorContinuously(undefined as any)).resolves.not.toThrow(); const metrics = monitoringSystem.getMetrics(); expect(metrics.totalChains).toBe(2); }); it("should allow monitoring to be stopped", async () => { const chain = createTestReasoningChain(); await monitoringSystem.monitorContinuously(chain); monitoringSystem.stop(); // Metrics should still be available after stop const metrics = monitoringSystem.getMetrics(); expect(metrics.totalChains).toBe(1); }); }); describe("Integration with BiasPatternRecognizer", () => { it("should use BiasPatternRecognizer for bias detection", async () => { const chain = createBiasedReasoningChain(); await monitoringSystem.monitorContinuously(chain); const metrics = monitoringSystem.getMetrics(); expect(metrics.totalChains).toBe(1); }); it("should handle chains with no biases", async () => { const chain = createTestReasoningChain({ steps: [ { id: "step-1", content: "Neutral analysis", type: "inference", confidence: 0.7, }, ], }); await monitoringSystem.monitorContinuously(chain); const metrics = monitoringSystem.getMetrics(); expect(metrics.totalChains).toBe(1); }); }); describe("Configuration", () => { it("should accept custom configuration", () => { const customConfig = { maxProcessingTime: 5000, alertThreshold: 0.8, debounceMs: 200, }; const customSystem = new BiasMonitoringSystem(recognizer, customConfig); expect(customSystem).toBeDefined(); customSystem.stop(); }); it("should use default configuration when not provided", () => { const defaultSystem = new BiasMonitoringSystem(recognizer); expect(defaultSystem).toBeDefined(); defaultSystem.stop(); }); }); describe("Metrics Tracking", () => { it("should track metrics after monitoring", async () => { const chain = createBiasedReasoningChain(); await monitoringSystem.monitorContinuously(chain); const metrics = monitoringSystem.getMetrics(); expect(metrics.totalChains).toBeGreaterThan(0); expect(metrics.averageProcessingTime).toBeGreaterThanOrEqual(0); }); it("should handle chains with no biases gracefully", async () => { const chain = createTestReasoningChain(); await monitoringSystem.monitorContinuously(chain); // Should not throw const metrics = monitoringSystem.getMetrics(); expect(metrics.totalChains).toBe(1); }); }); describe("Performance Metrics", () => { it("should track processing time metrics", async () => { const chain = createTestReasoningChain(); await monitoringSystem.monitorContinuously(chain); const metrics = monitoringSystem.getMetrics(); expect(metrics.averageProcessingTime).toBeGreaterThanOrEqual(0); }); it("should calculate overhead percentage", async () => { const chain = createTestReasoningChain(); await monitoringSystem.monitorContinuously(chain); const metrics = monitoringSystem.getMetrics(); expect(metrics.overheadPercentage).toBeGreaterThanOrEqual(0); }); }); describe("Real-Time Alerts", () => { it("should generate alerts for detected biases", async () => { const chain = createBiasedReasoningChain(); await monitoringSystem.monitorContinuously(chain); const alerts = monitoringSystem.generateRealTimeAlerts(chain); // Alerts may or may not be generated depending on bias detection expect(Array.isArray(alerts)).toBe(true); }); it("should return empty alerts for chain with no biases", async () => { const chain = createTestReasoningChain(); await monitoringSystem.monitorContinuously(chain); const alerts = monitoringSystem.generateRealTimeAlerts(chain); expect(Array.isArray(alerts)).toBe(true); }); it("should return empty alerts for unknown chain", () => { const unknownChain = createTestReasoningChain({ id: "unknown-chain" }); const alerts = monitoringSystem.generateRealTimeAlerts(unknownChain); expect(alerts).toEqual([]); }); }); });

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