Files
msd-core/gsd-memory/tests/extractors/research.test.ts
Lex Christopherson af7a057294 feat: add GSD Memory cross-project knowledge system
Implements MCP server for semantic search across GSD projects:

MCP Tools:
- gsd_memory_search: Search across all registered projects
- gsd_memory_decisions: Find decisions from SUMMARY/PROJECT.md
- gsd_memory_patterns: Find patterns from SUMMARY.md
- gsd_memory_pitfalls: Find pitfalls from RESEARCH.md
- gsd_memory_stack: Find tech stack entries
- gsd_memory_register: Register project with memory
- gsd_memory_index: Trigger indexing/update
- gsd_memory_status: Show system status

Architecture:
- QMD wrapper with grep fallback when QMD unavailable
- YAML frontmatter extractors for GSD document types
- Project registry at ~/.gsd/projects.json
- Auto-install via bin/install.js for Claude Code

Workflow integrations:
- new-project: Registers project with memory
- plan-phase: Indexes after planning
- execute-phase: Indexes after execution
- complete-milestone: Indexes milestone completion
- Researcher agents query memory before Context7

Tests: 117 passing (66 unit + 51 integration)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 13:13:22 -06:00

90 lines
2.8 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import { extractResearch, type ResearchData } from '../../src/extractors/research.js';
import { readFixture } from '../setup.js';
describe('research extractor', () => {
it('extracts metadata from frontmatter', () => {
const research = readFixture('sample-research.md');
const result = extractResearch(research);
expect(result.domain).toBe('WebSocket and Server-Sent Events for real-time updates');
expect(result.confidence).toBe('HIGH');
expect(result.researched).toBe('2025-01-20');
});
it('extracts pitfalls section', () => {
const research = readFixture('sample-research.md');
const result = extractResearch(research);
expect(result.pitfalls.length).toBeGreaterThan(0);
expect(result.pitfalls[0]).toHaveProperty('name');
expect(result.pitfalls[0]).toHaveProperty('description');
expect(result.pitfalls[0]).toHaveProperty('prevention');
});
it('extracts standard stack table', () => {
const research = readFixture('sample-research.md');
const result = extractResearch(research);
expect(result.standardStack.length).toBeGreaterThan(0);
expect(result.standardStack[0]).toHaveProperty('library');
expect(result.standardStack[0]).toHaveProperty('purpose');
});
it('extracts dont-hand-roll items', () => {
const research = readFixture('sample-research.md');
const result = extractResearch(research);
expect(result.dontHandRoll.length).toBeGreaterThan(0);
expect(result.dontHandRoll[0]).toHaveProperty('problem');
expect(result.dontHandRoll[0]).toHaveProperty('useInstead');
});
it('extracts anti-patterns', () => {
const research = readFixture('sample-research.md');
const result = extractResearch(research);
expect(result.antiPatterns.length).toBeGreaterThan(0);
});
it('extracts user constraints if present', () => {
const research = readFixture('sample-research.md');
const result = extractResearch(research);
expect(result.userConstraints).toBeDefined();
expect(result.userConstraints.locked.length).toBeGreaterThan(0);
});
it('extracts primary recommendation', () => {
const research = readFixture('sample-research.md');
const result = extractResearch(research);
expect(result.primaryRecommendation).toBeDefined();
expect(result.primaryRecommendation).toContain('SSE');
});
it('handles research without optional sections', () => {
const minimalResearch = `---
domain: testing
confidence: LOW
researched: 2025-01-20
---
# Research
## Summary
Basic research document.
**Primary recommendation:** Use standard tools.
`;
const result = extractResearch(minimalResearch);
expect(result.domain).toBe('testing');
expect(result.pitfalls).toEqual([]);
expect(result.standardStack).toEqual([]);
expect(result.dontHandRoll).toEqual([]);
});
});