moving
Some checks failed
Installer Smoke / installer-smoke (push) Has been cancelled

This commit is contained in:
Oleg Maslov
2026-09-02 10:10:29 +02:00
commit 0c3e2ead3b
3841 changed files with 970576 additions and 0 deletions

View File

@@ -0,0 +1,226 @@
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { MindDB, ImprovementSignalStore } from '@waggle/core';
import {
recordCapabilityGap,
analyzeAndRecordCorrection,
recordWorkflowPattern,
buildAwarenessSummary,
formatAwarenessPrompt,
markSummarySurfaced,
} from '../src/improvement-detector.js';
describe('improvement-detector', () => {
let db: MindDB;
let store: ImprovementSignalStore;
beforeEach(() => {
db = new MindDB(':memory:');
store = new ImprovementSignalStore(db);
});
afterEach(() => {
db.close();
});
// ── recordCapabilityGap ────────────────────────────────────
describe('recordCapabilityGap', () => {
it('records a capability gap signal', () => {
recordCapabilityGap(store, 'pdf_reader', 'user asked to read a PDF');
const gaps = store.getByCategory('capability_gap');
expect(gaps).toHaveLength(1);
expect(gaps[0].pattern_key).toBe('missing:pdf_reader');
expect(gaps[0].count).toBe(1);
});
it('increments count on repeated gap', () => {
recordCapabilityGap(store, 'web_search');
recordCapabilityGap(store, 'web_search');
const gaps = store.getByCategory('capability_gap');
expect(gaps).toHaveLength(1);
expect(gaps[0].count).toBe(2);
});
});
// ── analyzeAndRecordCorrection ─────────────────────────────
describe('analyzeAndRecordCorrection', () => {
it('returns null for non-correction messages', () => {
const result = analyzeAndRecordCorrection(store, 'Please write a sorting function');
expect(result).toBeNull();
expect(store.getByCategory('correction')).toHaveLength(0);
});
it('detects and records a correction', () => {
const result = analyzeAndRecordCorrection(
store,
"No, that's wrong. I told you to use markdown headers.",
);
expect(result).not.toBeNull();
expect(result!.patternKey).toBeDefined();
const corrections = store.getByCategory('correction');
expect(corrections).toHaveLength(1);
});
it('records both durable and task-local corrections', () => {
analyzeAndRecordCorrection(store, "No, always use shorter responses. I said keep it brief.");
analyzeAndRecordCorrection(store, "No, not that. Just use a list this time.");
const corrections = store.getByCategory('correction');
expect(corrections.length).toBeGreaterThanOrEqual(1);
});
});
// ── recordWorkflowPattern ──────────────────────────────────
describe('recordWorkflowPattern', () => {
it('records a workflow pattern', () => {
recordWorkflowPattern(store, 'research', 'analyze competitor pricing');
const patterns = store.getByCategory('workflow_pattern');
expect(patterns).toHaveLength(1);
expect(patterns[0].pattern_key).toBe('shape:research');
});
it('increments on repeated task shapes', () => {
recordWorkflowPattern(store, 'research', 'analyze competitor pricing');
recordWorkflowPattern(store, 'research', 'investigate market trends');
recordWorkflowPattern(store, 'research', 'review latest papers');
const patterns = store.getByCategory('workflow_pattern');
expect(patterns).toHaveLength(1);
expect(patterns[0].count).toBe(3);
});
});
// ── buildAwarenessSummary ──────────────────────────────────
describe('buildAwarenessSummary', () => {
it('returns empty summary when no actionable signals', () => {
const summary = buildAwarenessSummary(store);
expect(summary.totalActionable).toBe(0);
expect(summary.capabilityGaps).toEqual([]);
expect(summary.corrections).toEqual([]);
expect(summary.workflowPatterns).toEqual([]);
});
it('includes capability gaps above threshold', () => {
// Default threshold for capability_gap is 2
recordCapabilityGap(store, 'pdf_reader');
recordCapabilityGap(store, 'pdf_reader');
const summary = buildAwarenessSummary(store);
expect(summary.capabilityGaps).toHaveLength(1);
expect(summary.capabilityGaps[0].toolName).toBe('pdf_reader');
expect(summary.capabilityGaps[0].occurrences).toBe(2);
expect(summary.capabilityGaps[0].suggestion).toContain('pdf_reader');
});
it('includes corrections above threshold', () => {
// Default threshold for correction is 3
for (let i = 0; i < 3; i++) {
store.record('correction', 'tone:too_formal', 'Keep responses casual');
}
const summary = buildAwarenessSummary(store);
expect(summary.corrections).toHaveLength(1);
expect(summary.corrections[0].patternKey).toBe('tone:too_formal');
expect(summary.corrections[0].occurrences).toBe(3);
});
it('includes recent workflow patterns above threshold', () => {
// Default threshold for workflow_pattern is 3
for (let i = 0; i < 3; i++) {
recordWorkflowPattern(store, 'research', 'investigate topic');
}
const summary = buildAwarenessSummary(store);
expect(summary.workflowPatterns).toHaveLength(1);
expect(summary.workflowPatterns[0].patternKey).toBe('shape:research');
});
it('excludes stale workflow patterns', () => {
// Manually insert a workflow_pattern with old last_seen
const raw = db.getDatabase();
raw.prepare(`
INSERT INTO improvement_signals (category, pattern_key, count, last_seen)
VALUES ('workflow_pattern', 'shape:old_task', 5, datetime('now', '-30 days'))
`).run();
const summary = buildAwarenessSummary(store);
expect(summary.workflowPatterns).toHaveLength(0);
});
it('respects total cap of 3 actionable signals', () => {
// Create many signals above threshold
for (let i = 0; i < 5; i++) {
const key = `missing:tool_${i}`;
store.record('capability_gap', key);
store.record('capability_gap', key);
}
const summary = buildAwarenessSummary(store);
expect(summary.totalActionable).toBeLessThanOrEqual(3);
});
});
// ── formatAwarenessPrompt ──────────────────────────────────
describe('formatAwarenessPrompt', () => {
it('returns null for empty summary', () => {
const summary = buildAwarenessSummary(store);
expect(formatAwarenessPrompt(summary)).toBeNull();
});
it('formats capability gaps into prompt text', () => {
recordCapabilityGap(store, 'pdf_reader');
recordCapabilityGap(store, 'pdf_reader');
const summary = buildAwarenessSummary(store);
const prompt = formatAwarenessPrompt(summary);
expect(prompt).not.toBeNull();
expect(prompt).toContain('## Improvement Signals');
expect(prompt).toContain('pdf_reader');
expect(prompt).toContain('Missing capabilities');
});
it('formats corrections into prompt text', () => {
for (let i = 0; i < 3; i++) {
store.record('correction', 'tone:too_formal', 'Keep it casual');
}
const summary = buildAwarenessSummary(store);
const prompt = formatAwarenessPrompt(summary);
expect(prompt).toContain('Behavioral adjustments');
expect(prompt).toContain('casual');
});
it('formats workflow patterns into prompt text', () => {
for (let i = 0; i < 3; i++) {
recordWorkflowPattern(store, 'compare', 'compare options');
}
const summary = buildAwarenessSummary(store);
const prompt = formatAwarenessPrompt(summary);
expect(prompt).toContain('Recurring workflows');
expect(prompt).toContain('compare');
});
});
// ── markSummarySurfaced ────────────────────────────────────
describe('markSummarySurfaced', () => {
it('marks all signals in summary as surfaced', () => {
recordCapabilityGap(store, 'pdf_reader');
recordCapabilityGap(store, 'pdf_reader');
const summary = buildAwarenessSummary(store);
expect(summary.capabilityGaps).toHaveLength(1);
markSummarySurfaced(store, summary);
// Should not appear in next summary
const summary2 = buildAwarenessSummary(store);
expect(summary2.capabilityGaps).toHaveLength(0);
expect(summary2.totalActionable).toBe(0);
});
});
});