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>
107 lines
3.2 KiB
JavaScript
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
|