Files
proffesor-for-testing__agen…/docs/loki-mode-integration-plan.md
Profa 4b0ec635f5 feat(loki-mode): integrate 7 adversarial quality gates (ADR-074)
Add anti-sycophancy scoring, test quality gates, blind review,
EMA calibration, edge-case injection, complexity-driven composition,
and auto-escalation. All features enabled by default (opt-out).
178 tests, 14 new files, 6 config flags.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:36:19 +00:00

445 lines
20 KiB
Markdown

# Loki-Mode Integration Plan for AQE (Revised)
## Overview
This **revised** plan integrates 7 concepts from loki-mode into AQE by **extending existing infrastructure** rather than building parallel systems. A thorough codebase audit revealed that AQE already has 50-70% of the needed functionality. This plan focuses only on the **genuinely missing pieces**.
**Date**: 2026-03-04
**Base branch**: `working-branch-march`
**Estimated total effort**: ~20-30 hours (down from ~50 in v1)
---
## Codebase Audit Summary
| # | Concept | What Already Exists | What's Actually Missing |
|---|---------|-------------------|----------------------|
| 1 | Anti-Sycophancy | Devil's Advocate agent, Consensus Engine, Competing Hypotheses | Quantitative Jaccard cross-agent agreement scorer |
| 2 | Mock/Mutation Detectors | Devil's Advocate edge-case strategies (partial) | Tautological assertion, empty test, missing-import detectors |
| 3 | Blind Review | Competing Hypotheses parallel investigation | Test-gen-specific blind review with deduplication |
| 4 | EMA Calibration | Pattern Promotion (successRate), Routing Feedback (outcome tracking) | EMA-derived dynamic voting weights for agent consensus |
| 5 | Compound Learning | Experience Capture, Consolidation, Pattern Lifecycle, Learning Coordinator | Pre-task pattern injection into test generation prompts |
| 6 | Complexity Composition | AST Complexity Analyzer, Fleet Tier Selector, Routing Config | Unified 8-dim → agent team composition bridge |
| 7 | Auto-Escalation | Fleet Tier Selector (escalate/deescalate), FallbackConfig, HybridRouter failover | Consecutive-failure-triggered automatic escalation |
---
## Architecture Principles (Revised)
- **Extend, don't duplicate**: Wire into existing services via new methods or optional dependencies
- **Minimal new files**: Only create new files for genuinely new logic; add features to existing modules where natural
- **No parallel infrastructure**: Don't create new feedback/learning systems; enhance the existing ones
- **All additions are optional**: Behind config flags, existing behavior unchanged when disabled
---
## Stream A: Quality Gates (Items 1, 2)
### Item 1: Sycophancy Scorer — Extend Consensus Engine
**What exists**: `ConsensusEngineImpl` in `src/coordination/consensus/consensus-engine.ts` already orchestrates multi-model votes with weighted/unanimous strategies and tracks per-model stats (agreements, confidence).
**What to add**: A `SycophancyScorer` that runs as a **post-consensus gate** — after votes are collected but before final verdict.
**New Files** (2 files, not 4):
- `src/coordination/consensus/sycophancy-scorer.ts` (~180 lines)
- `tests/coordination/consensus/sycophancy-scorer.test.ts` (~250 lines)
**Modified Files**:
- `src/coordination/consensus/interfaces.ts` — add `SycophancyResult` type and optional `sycophancyCheck` to `ConsensusResult` (~15 lines)
- `src/coordination/consensus/consensus-engine.ts` — call scorer after vote collection, before verdict (~10 lines)
**Implementation**:
```typescript
// src/coordination/consensus/sycophancy-scorer.ts
export interface SycophancySignal {
name: string;
weight: number;
score: number; // 0-1
}
export type SycophancyLevel = 'independent' | 'mild' | 'moderate' | 'severe';
export interface SycophancyResult {
level: SycophancyLevel;
compositeScore: number;
signals: SycophancySignal[];
recommendation: string;
}
export class SycophancyScorer {
evaluate(votes: ModelVote[]): SycophancyResult {
// 4 signals computed from existing ModelVote data:
// 1. Verdict unanimity (30%): all votes same verdict?
// 2. Reasoning similarity (30%): Jaccard on tokenized justifications
// 3. Confidence uniformity (20%): std dev of confidence scores
// 4. Issue count consistency (20%): variation in reported issue counts
}
}
```
**Why this is better than v1 plan**: Reuses existing `ModelVote` type (already has `vote`, `confidence`, `justification`, `issuesFound`). No need for a new `AgentFinding` type. Integrates directly into the consensus flow that already exists.
**Integration**: `ConsensusEngineImpl.verify()` → collect votes → `sycophancyScorer.evaluate(votes)` → attach to `ConsensusResult` → if `severe`, escalate to human review (existing `humanReview` threshold path).
**Also integrates with**: `DevilsAdvocate` — when sycophancy is `severe`, automatically trigger a Devil's Advocate review (existing agent, just needs a trigger).
**Success Criteria**:
- [ ] 3 identical votes → `severe`; 3 divergent votes → `independent`
- [ ] Integrated into `ConsensusEngineImpl` without breaking existing tests
- [ ] Triggers Devil's Advocate on `severe` sycophancy
---
### Item 2: Test Quality Gates (Mock/Mutation Detectors)
**What exists**: Devil's Advocate `MissingEdgeCaseStrategy` checks for null/boundary/concurrency coverage in test output. But it operates on output metadata, not on **test code itself**.
**What's genuinely new**: Regex-based detection of tautological assertions, empty test bodies, and missing source imports in **generated test code strings**. This is a distinct concern from DA strategies.
**New Files** (3 files):
- `src/domains/test-generation/gates/test-quality-gate.ts` (~250 lines, combines mock + mutation detection)
- `src/domains/test-generation/gates/index.ts` (~10 lines)
- `tests/domains/test-generation/gates/test-quality-gate.test.ts` (~300 lines)
**Modified Files**:
- `src/domains/test-generation/services/test-generator.ts` — add optional gate call after generation (~15 lines)
- `src/domains/test-generation/interfaces.ts` — add `TestQualityIssue` to `GeneratedTest` metadata (~5 lines)
**Implementation** (single file, not split):
```typescript
// src/domains/test-generation/gates/test-quality-gate.ts
export interface TestQualityIssue {
type: 'no-source-import' | 'tautological-assertion' | 'empty-test-body' | 'mirrored-assertion';
severity: 'error' | 'warning';
line?: number;
description: string;
}
export interface TestQualityGateResult {
passed: boolean;
issues: TestQualityIssue[];
score: number; // 0-100
}
export class TestQualityGate {
validate(testCode: string, sourceFilePath: string): TestQualityGateResult {
const issues: TestQualityIssue[] = [];
// 1. Check imports reference source file
// 2. Detect tautological: expect(true).toBe(true), expect(x).toBe(x)
// 3. Detect empty bodies: it('...', () => {}) or test('...', () => {})
// 4. Detect mirrored assertions (values copied from source literals)
}
}
```
**Why combined**: Mock detector and mutation detector share the same test-code-analysis context. A single class with 4 check methods is cleaner than 2 separate files.
**Config**: `TestGeneratorConfig.enableTestQualityGate?: boolean` (default: false)
**Success Criteria**:
- [ ] Detects `expect(true).toBe(true)` as tautological
- [ ] Detects test file with zero source imports
- [ ] Detects empty test bodies
- [ ] Score of 100 for well-formed tests
- [ ] Integrated behind config flag, no regression
---
## Stream B: Agent Composition (Items 3, 6)
### Item 3: Blind Review for Test Generation — Extend Competing Hypotheses
**What exists**: `HypothesisManager` (`src/coordination/competing-hypotheses/hypothesis-manager.ts`) runs N parallel agents on different hypotheses and converges via evidence-weighted scoring.
**What's actually needed**: A thin wrapper that uses the existing parallel execution pattern but specialized for test generation with deduplication.
**New Files** (2 files):
- `src/domains/test-generation/blind-review/blind-review-orchestrator.ts` (~200 lines)
- `tests/domains/test-generation/blind-review/blind-review-orchestrator.test.ts` (~250 lines)
**No modified files** — this is a new optional MCP tool path.
**Implementation**:
```typescript
// Reuses TestGeneratorService (existing) with varied temperatures
// Reuses cosineSimilarity from shared/utils/vector-math.ts (existing)
// Does NOT create a new investigation framework — just Promise.all + dedup
export class BlindReviewOrchestrator {
constructor(
private testGenerator: ITestGenerationService,
private config: BlindReviewConfig = DEFAULT_CONFIG
) {}
async generateWithBlindReview(request: GenerateTestsRequest): Promise<Result<BlindReviewResult, Error>> {
// 1. Run testGenerator N times in parallel with different temperatures
// 2. Collect all generated tests
// 3. Deduplicate using Jaccard on tokenized assertions (reuse cosineSimilarity)
// 4. Return merged set with uniqueness stats
}
}
```
**Why simpler than v1**: No need for a separate `TestDeduplicator` class — deduplication is ~30 lines of Jaccard comparison, not worth a separate module. No need for a new MCP tool in v1 — expose via existing `test_generate_enhanced` with a `blindReview: true` option.
---
### Item 6: Complexity-Driven Composition — Bridge Existing Systems
**What exists separately**:
- `RuVectorASTComplexityAnalyzer` → cyclomatic, cognitive, LOC, maintainability
- `TierSelector` → smoke/standard/deep/crisis based on trigger context
- `QETaskRouter` → domain keyword matching + capability scoring
- `ComplexityTierMapping` in routing config → maps complexity scores to agent tiers
**What's missing**: A bridge that takes AST complexity output + security/concurrency signals and produces a specific agent team composition.
**New Files** (2 files):
- `src/coordination/complexity-composition/team-composer.ts` (~200 lines)
- `tests/coordination/complexity-composition/team-composer.test.ts` (~250 lines)
**Modified Files**:
- `src/coordination/fleet-tiers/tier-selector.ts` — add optional `ITeamComposer` that enriches tier selection with agent recommendations (~15 lines)
**Implementation**:
```typescript
// Consumes existing ComplexityMetrics from ruvector/interfaces.ts
// Consumes existing FleetTier from fleet-tiers/types.ts
// Adds security/concurrency dimension detection (regex-based, ~50 lines)
export class TeamComposer {
compose(
complexity: ComplexityMetrics, // Existing type from ruvector
tier: FleetTier, // Existing type from fleet-tiers
sourceCode: string // For security/concurrency scanning
): AgentComposition {
// Base agents from tier (existing mapping)
// + security agent if auth/crypto/token keywords found
// + chaos agent if async/Promise/shared-state patterns found
// + integration agent if high API surface
}
}
```
**Why better**: Reuses `ComplexityMetrics` (4 dimensions already computed) instead of building a new 8-dimension classifier from scratch. Adds only the 4 missing dimensions (security, concurrency, data-flow, API-surface) as lightweight regex checks, not full AST analysis.
---
## Stream C: Routing Enhancements (Items 4, 7)
### Item 4: EMA Calibration — Extend Routing Feedback
**What exists**: `RoutingFeedbackCollector.recordOutcome()` already records per-agent success/failure with quality scores and persists to SQLite. `PatternPromotionManager` already tracks `successRate` and `recentSuccessRate`.
**What's missing**: Computing an EMA from these outcomes and deriving a dynamic voting weight.
**New Files** (1 file + 1 test):
- `src/routing/calibration/ema-calibrator.ts` (~150 lines — simpler since persistence infra exists)
- `tests/routing/calibration/ema-calibrator.test.ts` (~200 lines)
**Modified Files**:
- `src/routing/routing-feedback.ts` — call `calibrator.recordOutcome()` in existing `recordOutcome()` method (~8 lines)
- `src/routing/types.ts` — add optional `calibratedWeight: number` to `AgentPerformanceMetrics` (~3 lines)
**Implementation note**: The existing `updatePatternFeedback` in `LearningCoordinatorService` already uses an EMA pattern (alpha=0.1) for pattern success rates. The new calibrator follows the same pattern for agent-level calibration, so it's architecturally consistent.
**Success Criteria**:
- [ ] EMA converges correctly over 100 outcomes
- [ ] Weight floor (0.2) and ceiling (2.0) enforced
- [ ] Integrates with existing `RoutingFeedbackCollector` SQLite persistence
- [ ] `QETaskRouter` can optionally use calibrated weights
---
### Item 7: Auto-Escalation — Extend Fleet Tier Selector
**What exists**: `TierSelector` already has `escalate(currentTier, reason)` and `deescalate(currentTier)` methods. `FallbackConfig` has a `chain: Record<AgentTier, AgentTier | null>`. But escalation is only triggered manually or by context (PR size, domain count).
**What's missing**: Automatic triggering based on consecutive failure/success counts.
**New Files** (1 file + 1 test):
- `src/routing/escalation/auto-escalation-tracker.ts` (~120 lines)
- `tests/routing/escalation/auto-escalation-tracker.test.ts` (~200 lines)
**Modified Files**:
- `src/routing/routing-feedback.ts` — call tracker after outcome recording (~8 lines)
**Implementation**:
```typescript
// Lightweight — just tracks consecutive outcomes and triggers existing escalation
export class AutoEscalationTracker {
private state = new Map<string, { failures: number; successes: number; currentTier: AgentTier }>();
recordOutcome(agentId: string, success: boolean, baseTier: AgentTier): {
action: 'escalate' | 'de-escalate' | 'none';
newTier: AgentTier;
} {
// Track consecutive failures/successes
// Return escalation recommendation
// Caller (RoutingFeedbackCollector) applies via existing FallbackConfig.chain
}
}
```
**Why simpler**: Doesn't duplicate `TierSelector.escalate()`/`deescalate()`. Just provides the trigger logic; the existing tier system does the actual tier change.
---
## Stream D: Learning Enhancement (Item 5)
### Item 5: Pre-Task Pattern Injection — Extend Experience Capture
**What exists**:
- `ExperienceCaptureService` captures task experiences with pattern extraction (post-task ✓)
- `PatternStore` stores/retrieves patterns with HNSW search
- `LearningCoordinatorService.mineInsights()` extracts patterns from experience clusters
- `TestGeneratorService` already has LLM enhancement with prompt construction
**What's genuinely missing**: The "pre-task injection" step — querying historical edge-case patterns and prepending them to the LLM prompt before test generation.
**New Files** (1 file + 1 test):
- `src/domains/test-generation/pattern-injection/edge-case-injector.ts` (~150 lines)
- `tests/domains/test-generation/pattern-injection/edge-case-injector.test.ts` (~200 lines)
**Modified Files**:
- `src/domains/test-generation/services/test-generator.ts` — call injector before LLM enhancement, prepend context to prompt (~15 lines)
**Implementation**:
```typescript
// Uses existing PatternStore.search() for retrieval
// Uses existing MemoryBackend for storage
// Formats top-3 patterns into prompt context string
export class EdgeCaseInjector {
constructor(private patternStore: PatternStore) {}
async getInjectionContext(
sourceCode: string,
domain: QEDomain,
topN: number = 3
): Promise<{ promptContext: string; patternsUsed: number }> {
// 1. Search patternStore for edge-case patterns matching domain + code characteristics
// 2. Rank by (successRate * applicationCount) descending
// 3. Format top-N as prompt context:
// "## Edge cases that caught real bugs in similar code:\n1. ..."
// 4. Return formatted string for prepending to LLM prompt
}
}
```
**Why simpler**: Doesn't create a new extraction step (ExperienceCaptureService already does this). Only adds the injection side. Reuses existing `PatternStore.search()` instead of creating parallel retrieval logic.
**Config**: `TestGeneratorConfig.enableEdgeCaseInjection?: boolean` (default: false)
---
## Revised Implementation Milestones
### Milestone 1: Core Logic (3-4 days)
All new modules — can run fully in parallel since no file conflicts:
| Work Item | New Files | Lines | Stream |
|-----------|-----------|-------|--------|
| Sycophancy Scorer | 2 | ~430 | A |
| Test Quality Gate | 2 | ~550 | A |
| Blind Review Orchestrator | 2 | ~450 | B |
| Team Composer | 2 | ~450 | B |
| EMA Calibrator | 2 | ~350 | C |
| Auto-Escalation Tracker | 2 | ~320 | C |
| Edge Case Injector | 2 | ~350 | D |
| **Total** | **14** | **~2,900** | |
### Milestone 2: Integration Wiring (1-2 days)
Sequenced where files overlap:
| Integration | Modifies | Depends On |
|-------------|----------|------------|
| Wire sycophancy into ConsensusEngine | `consensus-engine.ts`, `interfaces.ts` | Item 1 |
| Wire quality gate into TestGenerator | `test-generator.ts` | Item 2 |
| Wire EMA into RoutingFeedback | `routing-feedback.ts`, `types.ts` | Item 4 |
| Wire auto-escalation into RoutingFeedback | `routing-feedback.ts` | Item 7 (after Item 4) |
| Wire edge-case injection into TestGenerator | `test-generator.ts` | Item 5 (after Item 2) |
| Wire team composer into TierSelector | `tier-selector.ts` | Item 6 |
### Milestone 3: Validation (1 day)
- Run full test suite (`npm test -- --run`)
- Build verification (`npm run build`)
- Spot-check each feature with synthetic data
---
## File Conflict Matrix (Revised)
| Existing File | Item 1 | Item 2 | Item 3 | Item 4 | Item 5 | Item 6 | Item 7 |
|---------------|--------|--------|--------|--------|--------|--------|--------|
| `consensus/consensus-engine.ts` | M | | | | | | |
| `consensus/interfaces.ts` | M | | | | | | |
| `test-generation/services/test-generator.ts` | | M | | | M | | |
| `routing/routing-feedback.ts` | | | | M | | | M |
| `routing/types.ts` | | | | M | | | |
| `fleet-tiers/tier-selector.ts` | | | | | | M | |
**Parallel Groups**:
```
Group 1 (fully parallel — zero file overlap):
- Item 1 (sycophancy scorer) → consensus files
- Item 3 (blind review) → new files only
- Item 4 (EMA calibrator) → routing files
- Item 6 (team composer) → fleet-tiers files
Group 2 (after Group 1 — sequenced for shared files):
- Item 2 (test quality gate) → test-generator.ts
- Item 5 (edge case injector) → test-generator.ts (after Item 2)
- Item 7 (auto-escalation) → routing-feedback.ts (after Item 4)
```
---
## Comparison: v1 Plan vs Revised Plan
| Metric | v1 Plan | Revised Plan | Improvement |
|--------|---------|-------------|-------------|
| New files | 36 | 14 | -61% |
| Estimated lines | ~4,650 | ~2,900 | -38% |
| Modified existing files | 7 | 7 | Same |
| New types/interfaces | ~15 | ~7 | -53% |
| Duplicate infrastructure | High (new feedback, new learning) | None | Eliminated |
| Risk of regression | Medium | Low | Reduced |
---
## Agent Assignment (Revised)
| QE Agent | Items | Role |
|----------|-------|------|
| `qe-code-intelligence` | 1, 6 | Sycophancy scoring, team composition |
| `qe-test-generator` | 2, 3, 5 | Quality gate, blind review, injection |
| `qe-defect-predictor` | 4 | EMA calibration |
| `qe-test-executor` | 7 | Auto-escalation tracking |
---
## Configuration Summary
```typescript
// TestGeneratorConfig (existing)
enableTestQualityGate?: boolean; // Item 2 (default: false)
enableEdgeCaseInjection?: boolean; // Item 5 (default: false)
// ConsensusEngineConfig (existing)
enableSycophancyCheck?: boolean; // Item 1 (default: false)
// RoutingConfig (existing)
enableEMACalibration?: boolean; // Item 4 (default: false)
enableAutoEscalation?: boolean; // Item 7 (default: false)
// TierConfig (existing)
enableComplexityComposition?: boolean; // Item 6 (default: false)
```
All features enabled by default (opt-out) — disable individually via config flags if needed.