Files
proffesor-for-testing__agen…/docs/implementation/specs/SPEC-050-A-ml-observability-persistence.md
Profa 2253d05618 feat: flatten project structure — archive v2, promote v3 to root
Remove the nested v3/ subdirectory by moving all active source code,
tests, configs, and assets directly to the project root. Archive v2/
(dead code, 847MB) to v2-archive.tar.gz.

Key changes:
- Move v3/src/ → src/, v3/tests/ → tests/, v3/packages/ → packages/
- Move v3/tsconfig.json, v3/vitest.config.ts to root
- Merge v3/package.json into root package.json (ESM, scripts, deps, exports)
- Merge v3/scripts/ into scripts/, v3/implementation/ into docs/implementation/
- Update all CI workflows to remove "cd v3 &&" and v3/ path prefixes
- Fix all init installer path resolution (3-level-up → 2-level-up)
- Fix hooks to use "node ./dist/cli/bundle.js" instead of bare "aqe"
- Update settings.json ADR/DDD directories to docs/implementation/
- Fix helper scripts (statusline, adr-compliance, ddd-tracker, guidance-hooks)
- Update 58 agent definitions: aqe/v3/ → aqe/ memory namespaces
- Update 15 guidance shards: v3/src/ → src/ path references
- Fix sync interfaces: remove v3/ and v2/ path references
- Fix test path calculations (process.cwd() + '..' no longer needed)
- Fix flaky perf test threshold (500ms → 1000ms for CI environments)
- Fix complexity-analyzer test to match ADR-051 keyword-based eligibility

Build passes, 17,901 tests pass, CLI and MCP bundles verified.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 11:35:41 +00:00

247 lines
6.8 KiB
Markdown

# SPEC-050-A: ML Observability and Persistence
| Field | Value |
|-------|-------|
| **Specification ID** | SPEC-050-A |
| **Parent ADR** | [ADR-050](../adrs/ADR-050-ruvector-neural-backbone.md) |
| **Version** | 1.0 |
| **Status** | In Progress |
| **Last Updated** | 2026-01-20 |
| **Author** | GOAP Specialist |
---
## Overview
This specification covers Actions 1-4 from the GOAP plan: ML Observability Layer, Q-Learning Persistence, SONA Pattern Persistence, and Silent Fallback Removal.
---
## Action 1: ML Observability Layer
**Priority:** P0 (Critical)
**Estimated Time:** 4 hours
### Interface Definition
```typescript
// File: v3/src/integrations/ruvector/observability.ts
export interface MLObservabilityMetrics {
mlUsed: number;
fallbackUsed: number;
mlLatencyMs: number[];
fallbackReasons: Map<string, number>;
}
export interface MLObservabilityReport {
mlUsageRate: number; // mlUsed / (mlUsed + fallbackUsed)
avgMlLatencyMs: number;
topFallbackReasons: Array<{ reason: string; count: number }>;
alertTriggered: boolean;
}
export class RuVectorObservability {
private metrics: MLObservabilityMetrics;
private alertThreshold = 0.2; // Alert if ML usage drops below 20%
recordMLUsage(component: string, used: boolean, latencyMs?: number): void;
recordFallback(component: string, reason: string): void;
checkAndAlert(): void; // Emit alert if fallback rate too high
getReport(): MLObservabilityReport;
}
```
### Requirements
- [x] RuVector wrappers exist (`v3/src/integrations/ruvector/`)
- [x] Fallback implementations exist (`fallback.ts`)
- [ ] All ruvector calls emit metrics
- [ ] `usedML` flag on every routing result
- [ ] Alert system for fallback usage
---
## Action 2: Q-Learning Persistence
**Priority:** P0 (Critical)
**Estimated Time:** 8 hours
### Implementation
```typescript
// File: v3/src/integrations/ruvector/persistent-q-router.ts
export class PersistentQLearningRouter implements QLearningRouter {
private store: QValueStore;
private ewcConfig: EWCConfig;
constructor(config: PersistentQLearningConfig) {
this.store = createQValueStore();
this.ewcConfig = {
lambda: 1000.0, // EWC regularization strength
consolidationInterval: 3600000, // 1 hour
fisherSampleSize: 100,
};
}
async initialize(): Promise<void> {
await this.store.initialize();
await this.loadQValues(); // Restore from DB
}
async routeTask(task: TestTask): Promise<AgentRoutingResult> {
const result = await this.mlRoute(task);
await this.store.setQValue(agentId, stateKey, actionKey, qValue);
return result;
}
private async consolidateWithEWC(): Promise<void> {
// Apply EWC++ to prevent forgetting old patterns
}
}
```
### Requirements
- [x] QValueStore exists with SQLite backend
- [x] UnifiedPersistenceManager available
- [x] Q-Learning router exists
- [ ] Q-values persist to `memory.db`
- [ ] Q-values restored on router initialization
- [ ] EWC++ prevents catastrophic forgetting
---
## Action 3: SONA Pattern Persistence
**Priority:** P0 (Critical)
**Estimated Time:** 6 hours
### Implementation
```typescript
// File: v3/src/integrations/ruvector/sona-persistence.ts
export class PersistentSONAEngine extends QESONA {
private persistence: UnifiedPersistenceManager;
async initialize(): Promise<void> {
await super.initialize();
await this.restorePatterns();
}
async storePattern(pattern: QESONAPattern): Promise<void> {
super.storePattern(pattern);
await this.persistPattern(pattern);
}
private async persistPattern(pattern: QESONAPattern): Promise<void> {
const db = this.persistence.getDatabase();
db.prepare(`
INSERT INTO sona_patterns (id, type, domain, embedding, confidence, created_at)
VALUES (?, ?, ?, ?, ?, datetime('now'))
`).run(pattern.id, pattern.type, pattern.domain,
JSON.stringify(pattern.stateEmbedding), pattern.confidence);
}
private async restorePatterns(): Promise<void> {
const patterns = this.persistence.getDatabase().prepare(`
SELECT * FROM sona_patterns ORDER BY confidence DESC LIMIT 10000
`).all();
for (const p of patterns) {
super.importPatterns([this.deserializePattern(p)]);
}
}
}
```
### Requirements
- [x] QESONA wrapper exists
- [x] UnifiedPersistenceManager available
- [ ] SONA patterns persist to `memory.db`
- [ ] Patterns restored on SONA initialization
- [ ] Cross-agent pattern sharing via DB
---
## Action 4: Remove Silent Fallbacks
**Priority:** P1 (High)
**Estimated Time:** 12 hours
### Modified Provider
```typescript
// File: v3/src/integrations/ruvector/provider.ts (modified)
export function createQLearningRouter(config?: QLearningConfig): QLearningRouter {
const observability = getRuVectorObservability();
// TRY ML FIRST - no preemptive fallback
try {
const router = new RuVectorQLearningRouter(config);
await router.initialize(); // Will throw if ruvector unavailable
observability.recordMLUsage('q-learning', true);
return router;
} catch (error) {
// ONLY fall back on actual error
observability.recordFallback('q-learning', error.message);
observability.alert({
component: 'q-learning',
reason: error.message,
recommendation: 'Install/fix ruvector to enable ML routing',
});
return new FallbackQLearningRouter(); // Still works, but user knows
}
}
```
### Files to Modify
- `v3/src/integrations/ruvector/provider.ts`
- All domain coordinators that create ruvector components
### Requirements
- [ ] Fallbacks only used on explicit error
- [ ] All fallback usage logged and alerted
- [ ] No more silent degradation
---
## Database Schema Additions
```sql
-- Migration: 20260120_add_sona_patterns.sql
CREATE TABLE IF NOT EXISTS sona_patterns (
id TEXT PRIMARY KEY,
type TEXT NOT NULL,
domain TEXT NOT NULL,
embedding TEXT NOT NULL, -- JSON array
confidence REAL DEFAULT 0.0,
created_at TEXT DEFAULT (datetime('now')),
updated_at TEXT DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_sona_patterns_domain ON sona_patterns(domain);
CREATE INDEX IF NOT EXISTS idx_sona_patterns_confidence ON sona_patterns(confidence DESC);
```
---
## Agent Assignments
| Action | Agent | Phase |
|--------|-------|-------|
| Action 1 | qe-learning-coordinator | Phase 1 |
| Action 2 | qe-pattern-learner | Phase 1 |
| Action 3 | qe-pattern-learner | Phase 2 |
| Action 4 | qe-test-architect, qe-coverage-specialist | Phase 2 |
---
## Changelog
| Version | Date | Author | Changes |
|---------|------|--------|---------|
| 1.0 | 2026-01-20 | GOAP Specialist | Initial specification |