Files
msd-core/gsd-memory/dist/tools/index-tool.js
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

107 lines
3.2 KiB
JavaScript

import { getProject, updateProjectIndexTime, getAllProjects } from '../registry.js';
import { qmd } from '../qmd.js';
import { existsSync } from 'fs';
import { join } from 'path';
/**
* Trigger indexing/update for a project
*/
export async function index(options) {
// Find the project
let projectName;
let projectPath;
let qmdCollection;
if (options.project) {
const project = getProject(options.project);
if (!project) {
return {
success: false,
error: `Project not found: ${options.project}`,
qmdUsed: false
};
}
projectName = project.name;
projectPath = project.path;
qmdCollection = project.qmdCollection;
}
else if (options.path) {
// Find project by path
const projects = getAllProjects();
const project = projects.find(p => p.path === options.path);
if (!project) {
return {
success: false,
error: `No project registered for path: ${options.path}`,
qmdUsed: false
};
}
projectName = project.name;
projectPath = project.path;
qmdCollection = project.qmdCollection;
}
else {
return {
success: false,
error: 'Either project or path must be specified',
qmdUsed: false
};
}
// Verify planning directory exists
const planningPath = join(projectPath, '.planning');
if (!existsSync(planningPath)) {
return {
success: false,
project: projectName,
error: `No .planning directory found at: ${planningPath}`,
qmdUsed: false
};
}
// Check if QMD is available
const qmdAvailable = await qmd.isAvailable();
if (qmdAvailable && qmdCollection) {
// Use QMD to update the collection
const result = await qmd.index(qmdCollection);
if (result.success) {
updateProjectIndexTime(projectName);
// Get document count
const status = await qmd.status(qmdCollection);
return {
success: true,
project: projectName,
documentsIndexed: status.documentCount,
qmdUsed: true
};
}
else {
return {
success: false,
project: projectName,
error: `QMD indexing failed: ${result.reason}`,
qmdUsed: true
};
}
}
else {
// No QMD - just update the timestamp
// Grep fallback will search files directly
updateProjectIndexTime(projectName);
return {
success: true,
project: projectName,
qmdUsed: false
};
}
}
/**
* Index all registered projects
*/
export async function indexAll() {
const projects = getAllProjects();
const results = [];
for (const project of projects) {
const result = await index({ project: project.name });
results.push(result);
}
const success = results.every(r => r.success);
return { success, results };
}
//# sourceMappingURL=index-tool.js.map