* SwarmMemoryManager Refactoring Plan * fix: add missing directories to npm package (v1.9.3) Added templates/, .claude/helpers/, and docs/reference/ to package.json files array. These were missing from the npm distribution, causing `aqe init` to fail with "Template file not found" errors. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * checkpoint improvements * fix: critical memory/learning system fixes for v1.9.4 ## Critical Fixes - Vector embeddings now stored correctly (was storing NULL) - SQL parameter style fixed for agentdb's SqlJsDatabase wrapper - HNSW index schema mismatch resolved with pattern_id column - Hooks now save to correct database (.agentic-qe/agentdb.db) ## New Features - Added 5 SwarmMemoryManager methods for learning data retrieval: - getBestAction() - Q-learning best action selection - getRecentLearningExperiences() - Recent experience retrieval - getLearningExperiencesByTaskType() - Task-filtered experiences - getHighRewardExperiences() - Successful experience extraction - getLearningStats() - Aggregate learning statistics - Added comprehensive integration test for memory/learning loop - Added RuVector pattern store integration (experimental) ## Technical Details - Vector embeddings: 384 dimensions × 4 bytes = 1,536 bytes per pattern - All 12 integration tests pass - HNSW index: 150x faster vector search enabled 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: move ARM64-only ruvector packages to optionalDependencies Fixes CI failures caused by platform-specific dependencies: - @ruvector/node-linux-arm64-gnu (ARM64 only) - ruvector-core-linux-arm64-gnu (ARM64 only) These packages caused npm ci to fail on x64 CI runners with: "EBADPLATFORM - wanted linux/arm64, current linux/x64" Solution: Move ARM64 packages to optionalDependencies and add x64 variants for cross-platform compatibility. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * chore: regenerate package-lock.json with x64 ruvector packages Updates lockfile to include optional x64 platform packages for CI compatibility: - @ruvector/node-linux-x64-gnu@0.1.17 - ruvector-core-linux-x64-gnu@0.1.15 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
42 KiB
Autonomous Feedback Loop Architecture
Issue: #69 - Section 4.1 Alerting & Feedback Version: 1.0.0 Status: Design Complete Date: 2025-11-29
Executive Summary
This document describes the autonomous feedback loop architecture that enables the Agentic QE Fleet to:
- Detect quality degradation automatically through metric monitoring
- Trigger adaptive responses without human intervention
- Learn from outcomes to improve future responses
- Self-heal common quality issues
The feedback loop integrates seamlessly with existing infrastructure:
- OpenTelemetry metrics
- Event store persistence
- LearningEngine Q-learning
- AgentDB memory system
Table of Contents
- Architecture Overview
- Component Interactions
- Feedback Flow
- Integration with QE Agents
- Auto-Remediation Strategies
- Learning & Adaptation
- Example Scenarios
- Implementation Details
Architecture Overview
High-Level Architecture
┌─────────────────────────────────────────────────────────────────────────┐
│ AGENTIC QE FLEET - FEEDBACK LOOP │
└─────────────────────────────────────────────────────────────────────────┘
│
┌───────────────┴────────────────┐
│ │
┌─────────▼─────────┐ ┌──────────▼──────────┐
│ MONITORING │ │ AGENT EXECUTION │
│ LAYER │ │ LAYER │
└─────────┬─────────┘ └──────────┬──────────┘
│ │
│ ┌─────────────────────┐ │
└───▶│ QUALITY METRICS │◀───┘
│ (OpenTelemetry) │
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ ALERT MANAGER │
│ (Rule Evaluation) │
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ FEEDBACK ROUTER │
│ (Orchestration) │
└──────────┬──────────┘
│
┌───────────────┼───────────────┐
│ │ │
┌─────────▼────────┐ ┌───▼────┐ ┌────────▼─────────┐
│ STRATEGY │ │ MEMORY │ │ LEARNING ENGINE │
│ APPLICATOR │ │ STORE │ │ (Q-Learning) │
└─────────┬────────┘ └───┬────┘ └────────┬─────────┘
│ │ │
└───────────────┼───────────────┘
│
┌──────────▼──────────┐
│ QE AGENTS │
│ (Auto-Adaptation) │
└─────────────────────┘
Component Responsibilities
| Component | Responsibility | Output |
|---|---|---|
| Quality Metrics | Collect and expose metrics | Metric values |
| Alert Manager | Evaluate rules, trigger alerts | Alert events |
| Feedback Router | Orchestrate feedback actions | Feedback events |
| Strategy Applicator | Apply strategies to agents | Memory updates |
| Learning Engine | Learn from outcomes | Updated Q-values |
| QE Agents | Execute tasks with adaptation | Improved results |
Component Interactions
Sequence Diagram: Quality Degradation Detected
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ Agent │ │ Metrics │ │ Alert │ │ Feedback │ │ Learning │
│ │ │ │ │ Manager │ │ Router │ │ Engine │
└────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │ │ │
│ Execute Task │ │ │ │
│─────────────▶│ │ │ │
│ │ │ │ │
│ │ Record Metric│ │ │
│ │──────────────▶ │ │
│ │ │ │ │
│ │ │ Evaluate │ │
│ │ │ Threshold │ │
│ │ │──────┐ │ │
│ │ │ │ │ │
│ │ │◀─────┘ │ │
│ │ │ │ │
│ │ │ Threshold │ │
│ │ │ Exceeded! │ │
│ │ │──────────────▶ │
│ │ │ │ │
│ │ │ │ Generate │
│ │ │ │ Feedback │
│ │ │ │──────┐ │
│ │ │ │ │ │
│ │ │ │◀─────┘ │
│ │ │ │ │
│ │ │ │ Route │
│ │ │ │ Feedback │
│ │ │ │──────────────▶
│ │ │ │ │
│ │ │ │ │ Record
│ │ │ │ │ Experience
│ │ │ │ │──────┐
│ │ │ │ │ │
│ │ │ │ │◀─────┘
│ │ │ │ │
│ │ │ │ Apply │
│ │ │ │ Strategy │
│ │ │◀────────────── │
│ │ │ │ │
│ Read Strategy│ │ │ │
│ from Memory │ │ │ │
│◀─────────────┘ │ │ │
│ │ │ │ │
│ Adapt │ │ │ │
│ Behavior │ │ │ │
│──────┐ │ │ │ │
│ │ │ │ │ │
│◀─────┘ │ │ │ │
│ │ │ │ │
│ Execute with │ │ │ │
│ New Strategy │ │ │ │
│─────────────▶│ │ │ │
│ │ │ │ │
│ │ Record │ │ │
│ │ Improved │ │ │
│ │ Metric │ │ │
│ │──────────────▶ │ │
│ │ │ │ │
│ │ │ │ Record │
│ │ │ │ Success │
│ │ │ │──────────────▶
│ │ │ │ │
Data Flow Diagram
┌─────────────────────────────────────────────────────────────────────┐
│ CONTINUOUS IMPROVEMENT LOOP │
└─────────────────────────────────────────────────────────────────────┘
│
▼
┌──────────────────┐
│ Execute Tasks │
└──────────────────┘
│
▼
┌──────────────────┐
│ Collect Metrics │
│ - Coverage │
│ - Performance │
│ - Quality │
└──────────────────┘
│
▼
┌──────────────────┐
│ Evaluate Rules │
│ - Thresholds │
│ - Windows │
│ - Occurrences │
└──────────────────┘
│
┌─────────┴──────────┐
│ │
┌────────▼────────┐ ┌───────▼────────┐
│ Threshold OK │ │ Threshold FAIL │
└────────┬────────┘ └───────┬────────┘
│ │
│ ┌──────────▼──────────┐
│ │ Trigger Alert │
│ └──────────┬──────────┘
│ │
│ ┌──────────▼──────────┐
│ │ Generate Feedback │
│ │ - Type │
│ │ - Severity │
│ │ - Suggestions │
│ └──────────┬──────────┘
│ │
│ ┌──────────▼──────────┐
│ │ Analyze Patterns │
│ │ - Historical │
│ │ - Context │
│ └──────────┬──────────┘
│ │
│ ┌──────────▼──────────┐
│ │ Adjust Strategy │
│ │ - Learning rate │
│ │ - Exploration │
│ │ - Parameters │
│ └──────────┬──────────┘
│ │
│ ┌──────────▼──────────┐
│ │ Update Learning │
│ │ - Q-values │
│ │ - Patterns │
│ │ - Experience │
│ └──────────┬──────────┘
│ │
└────────────────────┘
│
▼
(Loop continues)
Feedback Flow
1. Metric Collection
Quality metrics are continuously collected by OpenTelemetry:
// In src/telemetry/metrics/quality-metrics.ts
export function recordCoverage(data: CoverageData): void {
const metrics = getQualityMetrics();
// Record coverage metrics
metrics.coverageLine.record(data.line, {
target: data.target,
framework: data.framework
});
// TRIGGER ALERT EVALUATION
alertManager.evaluateMetric(
'aqe.quality.coverage.line',
data.line,
{
target: data.target,
framework: data.framework,
timestamp: Date.now()
}
);
}
2. Alert Evaluation
AlertManager evaluates metrics against configured rules:
// In src/alerting/AlertManager.ts
export class AlertManager {
async evaluateMetric(
metricName: string,
value: number,
context: Record<string, unknown>
): Promise<Alert | null> {
const rules = this.rulesForMetric.get(metricName) || [];
for (const rule of rules) {
// Check if in cooldown
if (this.isInCooldown(rule.id)) {
continue;
}
// Evaluate threshold
const triggered = this.evaluateThreshold(
rule.operator,
value,
rule.threshold
);
if (triggered) {
// Track occurrence
this.trackOccurrence(rule.id);
// Check if minOccurrences met
if (this.meetsMinOccurrences(rule.id, rule.minOccurrences)) {
// Fire alert
const alert = await this.fireAlert(rule, value, context);
// Trigger feedback if configured
if (rule.triggerFeedback && rule.feedbackAction) {
await this.triggerFeedback(alert, rule.feedbackAction);
}
return alert;
}
}
}
return null;
}
}
3. Feedback Generation
FeedbackRouter generates feedback events from alerts:
// In src/feedback/FeedbackRouter.ts
export class FeedbackRouter {
async triggerFeedback(
alert: Alert,
action: FeedbackAction
): Promise<void> {
// Generate feedback event
const feedback: FeedbackEvent = {
id: uuidv4(),
timestamp: new Date(),
alertRuleId: alert.ruleId,
agentIds: this.determineAffectedAgents(alert),
metricName: alert.metricName,
currentValue: alert.currentValue,
expectedValue: alert.threshold,
type: this.determineFeedbackType(alert),
severity: this.mapSeverity(alert.severity),
suggestions: await this.generateSuggestions(alert, action),
context: alert.context
};
// Route feedback
await this.routeFeedback(feedback);
}
}
4. Strategy Application
StrategyApplicator applies recommended strategies:
// In src/feedback/StrategyApplicator.ts
export class StrategyApplicator {
async applyStrategy(
suggestion: StrategyRecommendation,
agentIds: string[]
): Promise<void> {
for (const agentId of agentIds) {
// Store strategy in agent memory
await this.memoryStore.store(
`aqe/feedback/strategy/${agentId}`,
{
strategy: suggestion.strategy,
parameters: suggestion.parameters,
confidence: suggestion.confidence,
appliedAt: new Date(),
expectedImpact: suggestion.expectedImpact
},
{ partition: 'feedback' }
);
// Emit event for agent to consume
this.eventBus.emit(`feedback:${agentId}`, {
type: 'strategy_applied',
strategy: suggestion.strategy
});
}
}
}
5. Learning Update
LearningEngine records feedback as experience:
// In src/learning/LearningEngine.ts
export class LearningEngine {
async processFeedback(feedback: FeedbackEvent): Promise<void> {
// Calculate reward based on feedback
const reward = this.calculateReward(feedback);
// Record as experience
const experience: TaskExperience = {
taskId: feedback.id,
state: this.extractState(feedback.context),
action: feedback.context.lastAction as any,
reward: reward,
nextState: this.extractState(feedback.context),
timestamp: feedback.timestamp
};
await this.recordExperience(experience);
// Store successful patterns
if (feedback.type === 'success_pattern') {
await this.storeSuccessPattern(feedback);
}
// Adjust exploration based on feedback
await this.adjustExploration(feedback);
}
private calculateReward(feedback: FeedbackEvent): number {
const delta = feedback.currentValue - feedback.expectedValue;
// Normalize based on severity
const severityMultiplier = {
low: 0.1,
medium: 0.5,
high: 1.0,
critical: 2.0
};
return delta * severityMultiplier[feedback.severity];
}
private async adjustExploration(
feedback: FeedbackEvent
): Promise<void> {
const config = await this.getConfig();
if (feedback.type === 'performance_degradation') {
// Increase exploration to find better strategies
await this.updateConfig({
explorationRate: Math.min(config.explorationRate * 1.5, 0.5)
});
} else if (feedback.type === 'quality_improvement') {
// Decrease exploration to exploit success
await this.updateConfig({
explorationRate: Math.max(config.explorationRate * 0.9, 0.01)
});
}
}
}
Integration with QE Agents
Agent Feedback Handling
Each QE agent subscribes to feedback events and adapts behavior:
// In src/agents/BaseAgent.ts
export abstract class BaseAgent extends EventEmitter {
protected feedbackHandler?: FeedbackHandler;
async initialize(): Promise<void> {
// ... existing initialization ...
// Initialize feedback handler
this.feedbackHandler = new FeedbackHandler(
this.agentId,
this.learningEngine,
this.memoryStore
);
// Subscribe to agent-specific feedback
this.eventBus.on(
`feedback:${this.agentId.id}`,
async (event) => {
await this.feedbackHandler.handleFeedback(event);
}
);
// Subscribe to broadcast feedback (all agents)
this.eventBus.on(
'feedback:broadcast',
async (event) => {
await this.feedbackHandler.handleFeedback(event);
}
);
}
protected async adaptToFeedback(
feedback: FeedbackEvent
): Promise<void> {
// Read strategy from memory
const strategy = await this.memoryStore.retrieve(
`aqe/feedback/strategy/${this.agentId.id}`
);
if (!strategy) return;
// Apply strategy based on type
switch (strategy.strategy) {
case 'increase_test_isolation':
await this.increaseTestIsolation(strategy.parameters);
break;
case 'optimize_test_suite':
await this.optimizeTestSuite(strategy.parameters);
break;
case 'generate_additional_tests':
await this.generateAdditionalTests(strategy.parameters);
break;
// ... other strategies ...
}
// Update learning engine
if (this.learningEngine) {
await this.learningEngine.processFeedback(feedback);
}
}
}
Agent-Specific Adaptations
Different agent types respond to feedback differently:
Coverage Analyzer Agent
// In src/agents/qe/QECoverageAnalyzerAgent.ts
export class QECoverageAnalyzerAgent extends BaseQEAgent {
protected async generateAdditionalTests(
params: Record<string, unknown>
): Promise<void> {
const targetCoverage = params.target_coverage as number;
// Analyze uncovered paths
const gaps = await this.analyzeUncoveredPaths();
// Generate tests for gaps
for (const gap of gaps) {
await this.generateTestForPath(gap);
// Check if target reached
const currentCoverage = await this.measureCoverage();
if (currentCoverage >= targetCoverage) {
break;
}
}
// Record success in learning engine
await this.learningEngine.recordSuccess({
strategy: 'generate_additional_tests',
improvement: currentCoverage - params.initial_coverage
});
}
}
Test Executor Agent
// In src/agents/qe/QETestExecutorAgent.ts
export class QETestExecutorAgent extends BaseQEAgent {
protected async optimizeTestSuite(
params: Record<string, unknown>
): Promise<void> {
const action = params.action as string;
if (action === 'parallel_execution') {
// Enable parallel test execution
this.config.parallelism = Math.min(
this.config.parallelism * 2,
os.cpus().length
);
// Update test selection strategy
this.testSelector.strategy = 'changed_files_first';
}
// Store optimization in memory
await this.memoryStore.store(
`aqe/optimization/${this.agentId.id}`,
{
parallelism: this.config.parallelism,
strategy: this.testSelector.strategy,
appliedAt: new Date()
}
);
}
}
Security Scanner Agent
// In src/agents/qe/QESecurityScannerAgent.ts
export class QESecurityScannerAgent extends BaseQEAgent {
protected async handleSecurityEscalation(
params: Record<string, unknown>
): Promise<void> {
// Create security incident
const incident = await this.createSecurityIncident({
severity: 'critical',
vulnerabilities: params.vulnerabilities,
blocksDeployment: params.block_deployment === true
});
// Notify security team
if (params.notify === 'security_team') {
await this.notifySecurityTeam(incident);
}
// Set deployment gate
if (params.block_deployment === true) {
await this.setDeploymentGate('security', 'blocked');
}
}
}
Auto-Remediation Strategies
Strategy Catalog
The system supports multiple remediation strategies:
1. Test Generation Strategies
export const testGenerationStrategies = {
generate_additional_tests: {
description: 'Generate tests for uncovered code paths',
parameters: {
target_coverage: { type: 'number', default: 85 },
focus_areas: { type: 'array', default: ['uncovered_branches'] }
},
applicableAgents: ['qe-coverage-analyzer', 'qe-test-generator'],
expectedImpact: {
metric: 'coverage',
improvement: 5-10
}
},
increase_test_isolation: {
description: 'Improve test isolation to reduce flakiness',
parameters: {
focus: { type: 'string', default: 'failing_tests' }
},
applicableAgents: ['qe-test-executor', 'qe-flaky-detector'],
expectedImpact: {
metric: 'flakiness',
improvement: -30
}
}
};
2. Performance Optimization Strategies
export const performanceStrategies = {
parallel_execution: {
description: 'Enable parallel test execution',
parameters: {
max_parallelism: { type: 'number', default: 'cpu_count' }
},
applicableAgents: ['qe-test-executor'],
expectedImpact: {
metric: 'execution_time',
improvement: -40
}
},
optimize_test_suite: {
description: 'Optimize test suite for faster execution',
parameters: {
strategy: {
type: 'enum',
values: ['changed_files_first', 'failure_prone_first', 'fastest_first']
}
},
applicableAgents: ['qe-test-executor', 'qe-performance-analyzer'],
expectedImpact: {
metric: 'execution_time',
improvement: -25
}
}
};
3. Quality Improvement Strategies
export const qualityStrategies = {
increase_review_depth: {
description: 'Increase code review depth and static analysis',
parameters: {
static_analysis: { type: 'boolean', default: true },
complexity_threshold: { type: 'number', default: 8 }
},
applicableAgents: ['qe-quality-analyzer'],
expectedImpact: {
metric: 'defect_density',
improvement: -15
}
},
stabilize_flaky_tests: {
description: 'Analyze and stabilize flaky tests',
parameters: {
analysis_depth: { type: 'enum', values: ['shallow', 'deep'] },
auto_quarantine: { type: 'boolean', default: false }
},
applicableAgents: ['qe-flaky-detector'],
expectedImpact: {
metric: 'flaky_count',
improvement: -40
}
}
};
Strategy Selection Algorithm
export class StrategySelector {
async selectStrategy(
feedback: FeedbackEvent
): Promise<StrategyRecommendation[]> {
const strategies: StrategyRecommendation[] = [];
// Get historical effectiveness
const history = await this.getStrategyHistory(
feedback.metricName,
feedback.type
);
// Get applicable strategies for this feedback type
const applicable = this.getApplicableStrategies(feedback);
// Score strategies based on:
// 1. Historical success rate
// 2. Expected impact
// 3. Agent availability
// 4. Resource requirements
for (const strategy of applicable) {
const score = await this.scoreStrategy(strategy, feedback, history);
if (score > 0.5) { // Confidence threshold
strategies.push({
strategy: strategy.name,
confidence: score,
expectedImpact: strategy.expectedImpact,
steps: strategy.implementationSteps,
parameters: strategy.defaultParameters
});
}
}
// Sort by confidence
return strategies.sort((a, b) => b.confidence - a.confidence);
}
}
Learning & Adaptation
Q-Learning Integration
The feedback loop enhances Q-learning by providing labeled experiences:
// State representation
interface State {
metricName: string;
metricValue: number;
trend: 'improving' | 'degrading' | 'stable';
agentLoad: number;
recentFailures: number;
}
// Action space
type Action =
| 'increase_exploration'
| 'decrease_exploration'
| 'adjust_learning_rate'
| 'apply_strategy'
| 'no_action';
// Q-learning update
async function updateQValues(
feedback: FeedbackEvent
): Promise<void> {
const state = extractState(feedback.context);
const action = feedback.context.lastAction as Action;
const reward = calculateReward(feedback);
const nextState = extractState(feedback.context);
// Q-learning update rule
const qValue = await qTable.get(state, action);
const maxNextQ = await qTable.getMaxQ(nextState);
const newQValue =
qValue +
learningRate * (reward + discountFactor * maxNextQ - qValue);
await qTable.set(state, action, newQValue);
}
Exploration vs Exploitation
Feedback events adjust exploration/exploitation balance:
export class ExplorationController {
async adjustExploration(
feedback: FeedbackEvent
): Promise<void> {
const config = await this.learningEngine.getConfig();
switch (feedback.type) {
case 'performance_degradation':
case 'error_pattern':
// Increase exploration to escape local optimum
await this.learningEngine.updateConfig({
explorationRate: Math.min(
config.explorationRate * 1.5,
0.5 // Max exploration
)
});
break;
case 'quality_improvement':
case 'success_pattern':
// Decrease exploration to exploit success
await this.learningEngine.updateConfig({
explorationRate: Math.max(
config.explorationRate * 0.9,
0.01 // Min exploration
)
});
break;
}
}
}
Pattern Storage
Successful strategies are stored for future reference:
export class PatternStore {
async storeSuccessPattern(
feedback: FeedbackEvent
): Promise<void> {
const pattern: Pattern = {
id: uuidv4(),
agentId: feedback.agentIds[0],
taskType: feedback.context.taskType as string,
pattern: feedback.suggestions[0].strategy,
confidence: feedback.suggestions[0].confidence,
occurrences: 1,
lastSeen: feedback.timestamp,
metadata: {
metricName: feedback.metricName,
improvement: feedback.currentValue - feedback.expectedValue,
context: feedback.context
}
};
await this.memoryStore.storePattern(pattern);
}
async retrieveSimilarPatterns(
context: Record<string, unknown>
): Promise<Pattern[]> {
return await this.memoryStore.searchPatterns({
taskType: context.taskType,
minConfidence: 0.7,
limit: 5
});
}
}
Example Scenarios
Scenario 1: Coverage Drop → Auto-Remediation
Initial State:
- Coverage: 78% (threshold: 80%)
- Alert: coverage-drop-critical
- Severity: critical
Feedback Loop:
1. AlertManager detects threshold breach
2. Triggers feedback: type=quality_improvement
3. StrategySelector recommends: generate_additional_tests (confidence: 0.92)
4. StrategyApplicator stores strategy in memory
5. qe-coverage-analyzer reads strategy
6. Agent analyzes uncovered paths:
- src/utils/validator.ts: lines 45-67 (branch coverage gap)
- src/core/processor.ts: lines 120-135 (uncovered error path)
7. Agent generates tests:
- validator.spec.ts: +23 lines (coverage +4%)
- processor.spec.ts: +31 lines (coverage +5%)
8. Coverage re-measured: 87%
9. LearningEngine records:
- Experience: {state, action, reward: +2.0, nextState}
- Pattern: {strategy: generate_additional_tests, confidence: 0.95}
10. Exploration rate decreased: 0.15 → 0.135
Outcome:
✅ Coverage improved: 78% → 87%
✅ Strategy effectiveness recorded
✅ Learning model updated
✅ Future similar issues handled faster
Scenario 2: Performance Degradation → Strategy Adaptation
Initial State:
- Test execution time: P95 = 45s (threshold: 30s)
- Alert: test-execution-slow
- Severity: warning
Feedback Loop:
1. MetricMonitor detects 5 occurrences over 5 minutes
2. Alert fired after minOccurrences threshold met
3. Feedback generated: type=performance_degradation
4. Multiple strategies recommended:
a. parallel_execution (confidence: 0.88)
b. optimize_test_suite (confidence: 0.75)
c. test_selection (confidence: 0.65)
5. Top strategy applied: parallel_execution
6. qe-test-executor adapts:
- Parallelism: 2 → 4 workers
- Test selection: changed_files_first
7. LearningEngine:
- Exploration increased: 0.10 → 0.15
- Searches for better execution strategies
8. Next execution: P95 = 22s
9. Success detected:
- Reward: +1.8
- Pattern stored
- Exploration decreased: 0.15 → 0.135
Outcome:
✅ Execution time improved: 45s → 22s (51% faster)
✅ Parallel execution effectiveness confirmed
✅ Strategy applied to similar future cases
Scenario 3: Security Vulnerability → Escalation
Initial State:
- Security scan detects: 2 critical vulnerabilities
- Alert: security-vulnerabilities-detected
- Severity: critical
Feedback Loop:
1. Alert fired immediately (cooldown: 0)
2. Feedback action: escalate
3. StrategyApplicator:
- Creates security incident #SEC-2025-029
- Notifies security team via webhook
- Sets deployment gate: BLOCKED
4. qe-security-scanner:
- Generates detailed vulnerability report
- Creates GitHub issues for each CVE
- Adds remediation steps
5. Human intervention required:
- Security team reviews findings
- Prioritizes remediation
- Updates dependencies
6. Post-remediation:
- Security scan re-run
- Vulnerabilities cleared
- Deployment gate: OPEN
- LearningEngine records successful pattern
Outcome:
✅ Security vulnerabilities blocked from production
✅ Security team notified within 30 seconds
✅ Deployment prevented until remediation
✅ Pattern stored for similar future vulnerabilities
Implementation Details
Alert Rule Loading
// src/alerting/AlertRule.ts
export class AlertRuleLoader {
async loadFromYaml(filePath: string): Promise<AlertRule[]> {
const yaml = require('js-yaml');
const fs = require('fs');
const content = fs.readFileSync(filePath, 'utf8');
const data = yaml.load(content);
const rules: AlertRule[] = [];
for (const ruleData of data.rules) {
// Validate rule schema
this.validateRule(ruleData);
// Create rule instance
const rule: AlertRule = {
id: ruleData.id,
name: ruleData.name,
description: ruleData.description,
metricName: ruleData.metricName,
operator: ruleData.operator,
threshold: ruleData.threshold,
severity: ruleData.severity,
windowMs: ruleData.windowMs,
minOccurrences: ruleData.minOccurrences,
agentScope: ruleData.agentScope,
triggerFeedback: ruleData.triggerFeedback,
feedbackAction: ruleData.feedbackAction,
cooldownMs: ruleData.cooldownMs,
metadata: ruleData.metadata
};
rules.push(rule);
}
return rules;
}
}
Feedback Event Storage
// src/feedback/FeedbackEvent.ts
export class FeedbackEventStore {
constructor(private db: Database) {}
async store(event: FeedbackEvent): Promise<void> {
await this.db.run(
`INSERT INTO feedback_events (
id, timestamp, alert_rule_id, agent_ids,
metric_name, current_value, expected_value,
type, severity, suggestions, context
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
[
event.id,
event.timestamp.toISOString(),
event.alertRuleId,
JSON.stringify(event.agentIds),
event.metricName,
event.currentValue,
event.expectedValue,
event.type,
event.severity,
JSON.stringify(event.suggestions),
JSON.stringify(event.context)
]
);
}
async getHistory(
options: {
agentId?: string;
type?: string;
from?: Date;
to?: Date;
limit?: number;
}
): Promise<FeedbackEvent[]> {
// Query implementation
}
}
Memory Integration
// src/feedback/StrategyApplicator.ts
export class StrategyApplicator {
constructor(
private memoryStore: SwarmMemoryManager,
private eventBus: EventEmitter
) {}
async applyStrategy(
suggestion: StrategyRecommendation,
agentIds: string[]
): Promise<void> {
const strategyId = uuidv4();
for (const agentId of agentIds) {
// Store in agent-specific memory partition
await this.memoryStore.store(
`aqe/feedback/strategy/${agentId}`,
{
id: strategyId,
strategy: suggestion.strategy,
parameters: suggestion.parameters,
confidence: suggestion.confidence,
appliedAt: new Date(),
expectedImpact: suggestion.expectedImpact,
status: 'active'
},
{
partition: 'feedback',
ttl: 3600000 // 1 hour TTL
}
);
// Emit event for immediate notification
this.eventBus.emit(`feedback:${agentId}`, {
type: 'strategy_applied',
strategyId,
strategy: suggestion.strategy
});
}
// Store in feedback history
await this.memoryStore.store(
`aqe/feedback/history/${strategyId}`,
{
id: strategyId,
agentIds,
suggestion,
appliedAt: new Date()
},
{ partition: 'history' }
);
}
}
Monitoring & Metrics
Feedback Loop Metrics
// Track feedback loop performance
export const feedbackMetrics = {
// Alert metrics
alertsFired: counter('aqe.alerting.alerts.fired'),
alertsSuppressed: counter('aqe.alerting.alerts.suppressed'),
alertPrecision: gauge('aqe.alerting.precision'),
alertRecall: gauge('aqe.alerting.recall'),
// Feedback metrics
feedbackGenerated: counter('aqe.feedback.generated'),
feedbackProcessingDuration: histogram('aqe.feedback.processing_duration'),
strategiesApplied: counter('aqe.feedback.strategies_applied'),
// Effectiveness metrics
improvementRate: gauge('aqe.feedback.improvement_rate'),
timeToImprovement: histogram('aqe.feedback.time_to_improvement'),
strategySuccessRate: gauge('aqe.feedback.strategy_success_rate')
};
Effectiveness Tracking
export interface FeedbackEffectiveness {
feedbackId: string;
metricName: string;
metricBefore: number;
metricAfter: number;
improvementPercent: number;
strategyApplied: string;
timeToImprovement: number; // milliseconds
success: boolean;
}
// Track effectiveness
async function trackEffectiveness(
feedbackId: string,
before: number,
after: number
): Promise<void> {
const improvement = ((after - before) / before) * 100;
const effectiveness: FeedbackEffectiveness = {
feedbackId,
metricName: 'coverage',
metricBefore: before,
metricAfter: after,
improvementPercent: improvement,
strategyApplied: 'generate_additional_tests',
timeToImprovement: Date.now() - feedbackStartTime,
success: improvement > 0
};
await eventStore.recordEvent({
agent_id: 'feedback-router',
event_type: 'feedback_effectiveness',
payload: effectiveness
});
// Update metrics
feedbackMetrics.improvementRate.set(improvement);
feedbackMetrics.timeToImprovement.record(effectiveness.timeToImprovement);
}
Success Criteria
Immediate (Week 1)
- ✅ Alerts fire when thresholds exceeded
- ✅ Feedback events generated automatically
- ✅ Strategies applied to agent memory
- ✅ Learning engine updated with feedback
- ✅ Alert precision >70%
Short-term (Month 1)
- ✅ Alert precision >90%
- ✅ Feedback improvement rate >70%
- ✅ Demonstrable learning convergence
- ✅ Zero system instability from feedback
Long-term (Quarter 1)
- ✅ Adaptive thresholds based on history
- ✅ Predictive alerting (ML-based)
- ✅ Multi-agent coordination feedback
- ✅ Strategy evolution via genetic algorithms
Conclusion
This feedback loop architecture enables true autonomous quality engineering by:
- Continuously monitoring quality metrics without human intervention
- Automatically detecting degradation through threshold-based rules
- Intelligently adapting agent strategies based on feedback
- Learning from outcomes to improve future responses
- Self-healing common quality issues
The system integrates seamlessly with existing infrastructure and requires minimal implementation overhead (11 hours estimated).
Version: 1.0.0 Status: ✅ Ready for Implementation Date: 2025-11-29