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,150 @@
/**
* Skills 2.0 gap K — write-path conflict detection.
*
* When save_memory writes a new frame that contradicts an existing frame
* (detectContradiction), the save still succeeds but:
* - the return string carries a [flag: contradicts_existing …] marker
* - a correction-category improvement signal is recorded
*
* Previously detectContradiction existed but was never called on the write
* path — write-path conflicts silently overwrote reality, degrading the
* evolution-signal loop.
*/
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import {
MindDB,
IdentityLayer,
AwarenessLayer,
FrameStore,
SessionStore,
KnowledgeGraph,
HybridSearch,
ImprovementSignalStore,
} from '@waggle/core';
import { createMindTools } from '../src/tools.js';
import type { ToolDefinition } from '../src/tools.js';
import { MockEmbedder } from '../../hive-mind-core/tests/mind/helpers/mock-embedder.js';
describe('save_memory — gap K (write-path conflict detection)', () => {
let db: MindDB;
let frames: FrameStore;
let sessions: SessionStore;
let tools: ToolDefinition[];
let improvementSignals: ImprovementSignalStore;
function getSaveMemory(): ToolDefinition {
const tool = tools.find(t => t.name === 'save_memory');
if (!tool) throw new Error('save_memory tool not found');
return tool;
}
beforeEach(() => {
db = new MindDB(':memory:');
const embedder = new MockEmbedder();
frames = new FrameStore(db);
sessions = new SessionStore(db);
const knowledge = new KnowledgeGraph(db);
const search = new HybridSearch(db, embedder);
improvementSignals = new ImprovementSignalStore(db);
tools = createMindTools({
db,
identity: new IdentityLayer(db),
awareness: new AwarenessLayer(db),
frames,
sessions,
search,
knowledge,
improvementSignals,
// Intentionally NO cognify → exercises the raw-frame fallback path
// (no LLM-dependent entity extraction in unit tests).
});
});
afterEach(() => {
db.close();
});
it('flags contradictions and records a correction signal', async () => {
const save = getSaveMemory();
// Prime with an affirmative decision frame.
// Using "enable/disable feature flag rollout users" — the existing
// detectContradiction algorithm needs asymmetric sentiment to fire;
// inputs with "will" in both sides add positive noise that can mask
// the polarity swing. Keep inputs tight and unambiguous.
const first = await save.execute({
content: 'Decision: enable feature flag rollout for users; proceed and confirmed.',
importance: 'important',
target: 'personal',
source: 'user_stated',
});
expect(first).toContain('Memory saved');
expect(first).not.toContain('contradicts_existing');
// Contradicting decision — disable/reject/cancel instead of enable/approve
const second = await save.execute({
content: 'Decision: disable feature flag rollout for users; cancel and reject.',
importance: 'important',
target: 'personal',
source: 'user_stated',
});
// Save still succeeded — conflict is a flag, not an abort
expect(second).toContain('Memory saved');
// But the return message is annotated
expect(second).toContain('[flag: contradicts_existing');
// And a correction signal is recorded
const top = improvementSignals.getByCategory('correction');
expect(top.length).toBeGreaterThan(0);
const writeConflict = top.find(s => s.pattern_key.startsWith('write-conflict:'));
expect(writeConflict).toBeDefined();
expect(writeConflict!.detail).toMatch(/contradicts existing frame/i);
expect(writeConflict!.category).toBe('correction');
});
it('non-contradicting saves do not flag or emit a signal', async () => {
const save = getSaveMemory();
await save.execute({
content: 'Decision: we chose PostgreSQL for analytics; approved and confirmed.',
target: 'personal',
source: 'user_stated',
});
const result = await save.execute({
content: 'Meeting notes from standup — discussed roadmap for Q2 and sprint planning.',
target: 'personal',
source: 'user_stated',
});
expect(result).not.toContain('contradicts_existing');
const top = improvementSignals.getByCategory('correction');
expect(top.find(s => s.pattern_key.startsWith('write-conflict:'))).toBeUndefined();
});
it('works without improvementSignals dep (backwards-compatible)', async () => {
// Rebuild tools without signals dep
const db2 = new MindDB(':memory:');
const embedder = new MockEmbedder();
const frames2 = new FrameStore(db2);
const sessions2 = new SessionStore(db2);
const knowledge2 = new KnowledgeGraph(db2);
const search2 = new HybridSearch(db2, embedder);
const tools2 = createMindTools({
db: db2,
identity: new IdentityLayer(db2),
awareness: new AwarenessLayer(db2),
frames: frames2,
sessions: sessions2,
search: search2,
knowledge: knowledge2,
// No improvementSignals — should not throw
});
const save = tools2.find(t => t.name === 'save_memory')!;
await save.execute({ content: 'Decision: enable feature flag rollout for users; proceed.', target: 'personal' });
const result = await save.execute({ content: 'Decision: disable feature flag rollout for users; cancel.', target: 'personal' });
// Flag still appears (detectContradiction doesn't need the signal store)
expect(result).toContain('contradicts_existing');
db2.close();
});
});