import { describe, it, expect } from 'vitest'; import { decide } from './enforce-memory-coverage.mjs'; function entries(userPrompt, assistantText) { const out = []; if (userPrompt) out.push({ message: { role: 'user', content: userPrompt } }); if (assistantText) out.push({ message: { role: 'assistant', content: [{ type: 'text', text: assistantText }] } }); return out; } describe('enforce-memory-coverage / decide', () => { it('allows non-memory paths regardless of coverage', () => { const r = decide({ toolName: 'Write', filePath: 'tools/foo.mjs', transcriptEntries: entries('do it', 'coverage: skill:tdd'), }); expect(r.block).toBe(false); }); it('blocks memory path with TDD coverage (stale)', () => { const r = decide({ toolName: 'Edit', filePath: 'C:\\Users\\x\\.claude\\projects\\proj\\memory\\foo.md', transcriptEntries: entries('do', 'coverage: skill:superpowers:test-driven-development'), }); expect(r.block).toBe(true); expect(r.message).toMatch(/memory-sync/); // 1A (2026-05-31): не рекламировать мёртвую override-фразу (findOverride — заглушка v4). expect(r.message).not.toMatch(/Override:/); expect(r.message).not.toMatch(/memory dump/); }); it('blocks memory path with no coverage at all', () => { const r = decide({ toolName: 'Write', filePath: '/Users/x/.claude/projects/p/memory/x.md', transcriptEntries: entries('do', 'no coverage line here'), }); expect(r.block).toBe(true); expect(r.message).toMatch(/NONE/); }); it('allows memory path with direct:memory-sync coverage', () => { const r = decide({ toolName: 'Edit', filePath: 'C:\\Users\\x\\.claude\\projects\\proj\\memory\\foo.md', transcriptEntries: entries('do', 'coverage: direct:memory-sync\nок'), }); expect(r.block).toBe(false); }); it('allows memory path with skill:memory-something coverage', () => { const r = decide({ toolName: 'Edit', filePath: '/x/.claude/projects/p/memory/foo.md', transcriptEntries: entries('do', 'coverage: skill:memory-coordinator'), }); expect(r.block).toBe(false); }); it('allows memory path when override phrase present', () => { const r = decide({ toolName: 'Write', filePath: '/x/.claude/projects/p/memory/foo.md', transcriptEntries: entries('memory dump please', 'no coverage'), override: { phrase: 'memory dump', suppresses: ['memory-sync-coverage'] }, }); expect(r.block).toBe(false); }); it('skips non-Edit/Write/MultiEdit tools', () => { const r = decide({ toolName: 'Bash', filePath: 'memory/x.md', transcriptEntries: entries('do', 'no coverage'), }); expect(r.block).toBe(false); }); it('matches MEMORY.md anywhere', () => { const r = decide({ toolName: 'Edit', filePath: '/whatever/MEMORY.md', transcriptEntries: entries('do', 'coverage: skill:tdd'), }); expect(r.block).toBe(true); }); });