From cc3c6aca5619e8882ca07d0c22c63ecee9d232a6 Mon Sep 17 00:00:00 2001 From: Lex Christopherson Date: Fri, 6 Feb 2026 09:48:09 -0600 Subject: [PATCH] revert: remove GSD Memory system (not ready for release) Reverts af7a057 "feat: add GSD Memory cross-project knowledge system" The memory system needs more work before shipping: - Workflow integration is incomplete (writes but doesn't query) - UX requires too much manual intervention - Setup friction exceeds value for most users Preserved on branch `memory-wip` for continued development. Co-Authored-By: Claude Opus 4.5 --- agents/gsd-phase-researcher.md | 38 +- agents/gsd-project-researcher.md | 38 +- bin/install.js | 137 +- commands/gsd/new-project.md | 20 - get-shit-done/workflows/complete-milestone.md | 26 - get-shit-done/workflows/execute-phase.md | 16 - gsd-memory/.gitignore | 3 - gsd-memory/README.md | 194 -- gsd-memory/dist/extractors/frontmatter.d.ts | 13 - .../dist/extractors/frontmatter.d.ts.map | 1 - gsd-memory/dist/extractors/frontmatter.js | 34 - gsd-memory/dist/extractors/frontmatter.js.map | 1 - gsd-memory/dist/extractors/index.d.ts | 5 - gsd-memory/dist/extractors/index.d.ts.map | 1 - gsd-memory/dist/extractors/index.js | 5 - gsd-memory/dist/extractors/index.js.map | 1 - gsd-memory/dist/extractors/project.d.ts | 33 - gsd-memory/dist/extractors/project.d.ts.map | 1 - gsd-memory/dist/extractors/project.js | 139 - gsd-memory/dist/extractors/project.js.map | 1 - gsd-memory/dist/extractors/research.d.ts | 40 - gsd-memory/dist/extractors/research.d.ts.map | 1 - gsd-memory/dist/extractors/research.js | 183 - gsd-memory/dist/extractors/research.js.map | 1 - gsd-memory/dist/extractors/summary.d.ts | 38 - gsd-memory/dist/extractors/summary.d.ts.map | 1 - gsd-memory/dist/extractors/summary.js | 88 - gsd-memory/dist/extractors/summary.js.map | 1 - gsd-memory/dist/index.d.ts | 3 - gsd-memory/dist/index.d.ts.map | 1 - gsd-memory/dist/index.js | 298 -- gsd-memory/dist/index.js.map | 1 - gsd-memory/dist/qmd.d.ts | 67 - gsd-memory/dist/qmd.d.ts.map | 1 - gsd-memory/dist/qmd.js | 199 -- gsd-memory/dist/qmd.js.map | 1 - gsd-memory/dist/registry.d.ts | 44 - gsd-memory/dist/registry.d.ts.map | 1 - gsd-memory/dist/registry.js | 106 - gsd-memory/dist/registry.js.map | 1 - gsd-memory/dist/tools/decisions.d.ts | 20 - gsd-memory/dist/tools/decisions.d.ts.map | 1 - gsd-memory/dist/tools/decisions.js | 120 - gsd-memory/dist/tools/decisions.js.map | 1 - gsd-memory/dist/tools/index-tool.d.ts | 23 - gsd-memory/dist/tools/index-tool.d.ts.map | 1 - gsd-memory/dist/tools/index-tool.js | 107 - gsd-memory/dist/tools/index-tool.js.map | 1 - gsd-memory/dist/tools/patterns.d.ts | 19 - gsd-memory/dist/tools/patterns.d.ts.map | 1 - gsd-memory/dist/tools/patterns.js | 81 - gsd-memory/dist/tools/patterns.js.map | 1 - gsd-memory/dist/tools/pitfalls.d.ts | 18 - gsd-memory/dist/tools/pitfalls.d.ts.map | 1 - gsd-memory/dist/tools/pitfalls.js | 85 - gsd-memory/dist/tools/pitfalls.js.map | 1 - gsd-memory/dist/tools/register.d.ts | 37 - gsd-memory/dist/tools/register.d.ts.map | 1 - gsd-memory/dist/tools/register.js | 105 - gsd-memory/dist/tools/register.js.map | 1 - gsd-memory/dist/tools/search.d.ts | 19 - gsd-memory/dist/tools/search.d.ts.map | 1 - gsd-memory/dist/tools/search.js | 92 - gsd-memory/dist/tools/search.js.map | 1 - gsd-memory/dist/tools/stack.d.ts | 19 - gsd-memory/dist/tools/stack.d.ts.map | 1 - gsd-memory/dist/tools/stack.js | 137 - gsd-memory/dist/tools/stack.js.map | 1 - gsd-memory/dist/tools/status.d.ts | 23 - gsd-memory/dist/tools/status.d.ts.map | 1 - gsd-memory/dist/tools/status.js | 67 - gsd-memory/dist/tools/status.js.map | 1 - gsd-memory/package-lock.json | 3005 ----------------- gsd-memory/package.json | 31 - gsd-memory/src/extractors/frontmatter.ts | 36 - gsd-memory/src/extractors/index.ts | 4 - gsd-memory/src/extractors/project.ts | 193 -- gsd-memory/src/extractors/research.ts | 250 -- gsd-memory/src/extractors/summary.ts | 155 - gsd-memory/src/index.ts | 321 -- gsd-memory/src/qmd.ts | 255 -- gsd-memory/src/registry.ts | 137 - gsd-memory/src/tools/decisions.ts | 153 - gsd-memory/src/tools/index-tool.ts | 133 - gsd-memory/src/tools/patterns.ts | 108 - gsd-memory/src/tools/pitfalls.ts | 111 - gsd-memory/src/tools/register.ts | 146 - gsd-memory/src/tools/search.ts | 117 - gsd-memory/src/tools/stack.ts | 171 - gsd-memory/src/tools/status.ts | 94 - .../tests/extractors/frontmatter.test.ts | 141 - gsd-memory/tests/extractors/project.test.ts | 109 - gsd-memory/tests/extractors/research.test.ts | 89 - gsd-memory/tests/extractors/summary.test.ts | 112 - .../tests/fixtures/mock-planning/PROJECT.md | 43 - .../tests/fixtures/mock-planning/STATE.md | 60 - .../tests/fixtures/mock-planning/config.json | 9 - .../phases/01-foundation/01-01-SUMMARY.md | 95 - .../phases/01-foundation/01-RESEARCH.md | 100 - .../mock-planning/research/SUMMARY.md | 21 - .../mock-project/.planning/PROJECT.md | 43 - .../fixtures/mock-project/.planning/STATE.md | 60 - .../mock-project/.planning/config.json | 9 - .../phases/01-foundation/01-01-SUMMARY.md | 95 - .../phases/01-foundation/01-RESEARCH.md | 100 - .../.planning/research/SUMMARY.md | 21 - gsd-memory/tests/fixtures/sample-project.md | 53 - gsd-memory/tests/fixtures/sample-research.md | 285 -- gsd-memory/tests/fixtures/sample-summary.md | 121 - .../tests/integration/end-to-end.test.ts | 476 --- .../tests/integration/mcp-server.test.ts | 359 -- .../tests/integration/qmd-wrapper.test.ts | 265 -- gsd-memory/tests/qmd-wrapper.test.ts | 104 - gsd-memory/tests/setup.ts | 27 - gsd-memory/tests/tools/decisions.test.ts | 87 - gsd-memory/tests/tools/register.test.ts | 142 - gsd-memory/tests/tools/search.test.ts | 75 - gsd-memory/tsconfig.json | 20 - gsd-memory/vitest.config.ts | 16 - gsd-memory/vitest.integration.config.ts | 10 - 120 files changed, 3 insertions(+), 11335 deletions(-) delete mode 100644 gsd-memory/.gitignore delete mode 100644 gsd-memory/README.md delete mode 100644 gsd-memory/dist/extractors/frontmatter.d.ts delete mode 100644 gsd-memory/dist/extractors/frontmatter.d.ts.map delete mode 100644 gsd-memory/dist/extractors/frontmatter.js delete mode 100644 gsd-memory/dist/extractors/frontmatter.js.map delete mode 100644 gsd-memory/dist/extractors/index.d.ts delete mode 100644 gsd-memory/dist/extractors/index.d.ts.map delete mode 100644 gsd-memory/dist/extractors/index.js delete mode 100644 gsd-memory/dist/extractors/index.js.map delete mode 100644 gsd-memory/dist/extractors/project.d.ts delete mode 100644 gsd-memory/dist/extractors/project.d.ts.map delete mode 100644 gsd-memory/dist/extractors/project.js delete mode 100644 gsd-memory/dist/extractors/project.js.map delete mode 100644 gsd-memory/dist/extractors/research.d.ts delete mode 100644 gsd-memory/dist/extractors/research.d.ts.map delete mode 100644 gsd-memory/dist/extractors/research.js delete mode 100644 gsd-memory/dist/extractors/research.js.map delete mode 100644 gsd-memory/dist/extractors/summary.d.ts delete mode 100644 gsd-memory/dist/extractors/summary.d.ts.map delete mode 100644 gsd-memory/dist/extractors/summary.js delete mode 100644 gsd-memory/dist/extractors/summary.js.map delete mode 100644 gsd-memory/dist/index.d.ts delete mode 100644 gsd-memory/dist/index.d.ts.map delete mode 100644 gsd-memory/dist/index.js delete mode 100644 gsd-memory/dist/index.js.map delete mode 100644 gsd-memory/dist/qmd.d.ts delete mode 100644 gsd-memory/dist/qmd.d.ts.map delete mode 100644 gsd-memory/dist/qmd.js delete mode 100644 gsd-memory/dist/qmd.js.map delete mode 100644 gsd-memory/dist/registry.d.ts delete mode 100644 gsd-memory/dist/registry.d.ts.map delete mode 100644 gsd-memory/dist/registry.js delete mode 100644 gsd-memory/dist/registry.js.map delete mode 100644 gsd-memory/dist/tools/decisions.d.ts delete mode 100644 gsd-memory/dist/tools/decisions.d.ts.map delete mode 100644 gsd-memory/dist/tools/decisions.js delete mode 100644 gsd-memory/dist/tools/decisions.js.map delete mode 100644 gsd-memory/dist/tools/index-tool.d.ts delete mode 100644 gsd-memory/dist/tools/index-tool.d.ts.map delete mode 100644 gsd-memory/dist/tools/index-tool.js delete mode 100644 gsd-memory/dist/tools/index-tool.js.map delete mode 100644 gsd-memory/dist/tools/patterns.d.ts delete mode 100644 gsd-memory/dist/tools/patterns.d.ts.map delete mode 100644 gsd-memory/dist/tools/patterns.js delete mode 100644 gsd-memory/dist/tools/patterns.js.map delete mode 100644 gsd-memory/dist/tools/pitfalls.d.ts delete mode 100644 gsd-memory/dist/tools/pitfalls.d.ts.map delete mode 100644 gsd-memory/dist/tools/pitfalls.js delete mode 100644 gsd-memory/dist/tools/pitfalls.js.map delete mode 100644 gsd-memory/dist/tools/register.d.ts delete mode 100644 gsd-memory/dist/tools/register.d.ts.map delete mode 100644 gsd-memory/dist/tools/register.js delete mode 100644 gsd-memory/dist/tools/register.js.map delete mode 100644 gsd-memory/dist/tools/search.d.ts delete mode 100644 gsd-memory/dist/tools/search.d.ts.map delete mode 100644 gsd-memory/dist/tools/search.js delete mode 100644 gsd-memory/dist/tools/search.js.map delete mode 100644 gsd-memory/dist/tools/stack.d.ts delete mode 100644 gsd-memory/dist/tools/stack.d.ts.map delete mode 100644 gsd-memory/dist/tools/stack.js delete mode 100644 gsd-memory/dist/tools/stack.js.map delete mode 100644 gsd-memory/dist/tools/status.d.ts delete mode 100644 gsd-memory/dist/tools/status.d.ts.map delete mode 100644 gsd-memory/dist/tools/status.js delete mode 100644 gsd-memory/dist/tools/status.js.map delete mode 100644 gsd-memory/package-lock.json delete mode 100644 gsd-memory/package.json delete mode 100644 gsd-memory/src/extractors/frontmatter.ts delete mode 100644 gsd-memory/src/extractors/index.ts delete mode 100644 gsd-memory/src/extractors/project.ts delete mode 100644 gsd-memory/src/extractors/research.ts delete mode 100644 gsd-memory/src/extractors/summary.ts delete mode 100644 gsd-memory/src/index.ts delete mode 100644 gsd-memory/src/qmd.ts delete mode 100644 gsd-memory/src/registry.ts delete mode 100644 gsd-memory/src/tools/decisions.ts delete mode 100644 gsd-memory/src/tools/index-tool.ts delete mode 100644 gsd-memory/src/tools/patterns.ts delete mode 100644 gsd-memory/src/tools/pitfalls.ts delete mode 100644 gsd-memory/src/tools/register.ts delete mode 100644 gsd-memory/src/tools/search.ts delete mode 100644 gsd-memory/src/tools/stack.ts delete mode 100644 gsd-memory/src/tools/status.ts delete mode 100644 gsd-memory/tests/extractors/frontmatter.test.ts delete mode 100644 gsd-memory/tests/extractors/project.test.ts delete mode 100644 gsd-memory/tests/extractors/research.test.ts delete mode 100644 gsd-memory/tests/extractors/summary.test.ts delete mode 100644 gsd-memory/tests/fixtures/mock-planning/PROJECT.md delete mode 100644 gsd-memory/tests/fixtures/mock-planning/STATE.md delete mode 100644 gsd-memory/tests/fixtures/mock-planning/config.json delete mode 100644 gsd-memory/tests/fixtures/mock-planning/phases/01-foundation/01-01-SUMMARY.md delete mode 100644 gsd-memory/tests/fixtures/mock-planning/phases/01-foundation/01-RESEARCH.md delete mode 100644 gsd-memory/tests/fixtures/mock-planning/research/SUMMARY.md delete mode 100644 gsd-memory/tests/fixtures/mock-project/.planning/PROJECT.md delete mode 100644 gsd-memory/tests/fixtures/mock-project/.planning/STATE.md delete mode 100644 gsd-memory/tests/fixtures/mock-project/.planning/config.json delete mode 100644 gsd-memory/tests/fixtures/mock-project/.planning/phases/01-foundation/01-01-SUMMARY.md delete mode 100644 gsd-memory/tests/fixtures/mock-project/.planning/phases/01-foundation/01-RESEARCH.md delete mode 100644 gsd-memory/tests/fixtures/mock-project/.planning/research/SUMMARY.md delete mode 100644 gsd-memory/tests/fixtures/sample-project.md delete mode 100644 gsd-memory/tests/fixtures/sample-research.md delete mode 100644 gsd-memory/tests/fixtures/sample-summary.md delete mode 100644 gsd-memory/tests/integration/end-to-end.test.ts delete mode 100644 gsd-memory/tests/integration/mcp-server.test.ts delete mode 100644 gsd-memory/tests/integration/qmd-wrapper.test.ts delete mode 100644 gsd-memory/tests/qmd-wrapper.test.ts delete mode 100644 gsd-memory/tests/setup.ts delete mode 100644 gsd-memory/tests/tools/decisions.test.ts delete mode 100644 gsd-memory/tests/tools/register.test.ts delete mode 100644 gsd-memory/tests/tools/search.test.ts delete mode 100644 gsd-memory/tsconfig.json delete mode 100644 gsd-memory/vitest.config.ts delete mode 100644 gsd-memory/vitest.integration.config.ts diff --git a/agents/gsd-phase-researcher.md b/agents/gsd-phase-researcher.md index efcc1c557..97b5a1327 100644 --- a/agents/gsd-phase-researcher.md +++ b/agents/gsd-phase-researcher.md @@ -1,7 +1,7 @@ --- name: gsd-phase-researcher description: Researches how to implement a phase before planning. Produces RESEARCH.md consumed by gsd-planner. Spawned by /gsd:plan-phase orchestrator. -tools: Read, Write, Bash, Grep, Glob, WebSearch, WebFetch, mcp__context7__*, mcp__gsd-memory__* +tools: Read, Write, Bash, Grep, Glob, WebSearch, WebFetch, mcp__context7__* color: cyan --- @@ -100,42 +100,6 @@ When researching "best library for X": -## GSD Memory: First for Past Work - -**If `gsd_memory_*` MCP tools are available,** query past project knowledge before external research. - -**When to use:** -- Check what decisions were made in similar phases -- Find patterns established in past projects -- Learn from documented pitfalls -- See what tech stack was used for similar domains - -**How to use:** -``` -1. Search for relevant context: - gsd_memory_search({ query: "[phase topic]" }) - -2. Find relevant decisions: - gsd_memory_decisions({ query: "[topic]" }) - -3. Find relevant patterns: - gsd_memory_patterns({ query: "[topic]" }) - -4. Check for pitfalls: - gsd_memory_pitfalls({ domain: "[domain]" }) - -5. See tech stack choices: - gsd_memory_stack({ query: "[library or purpose]" }) -``` - -**Best practices:** -- Query memory BEFORE web research — past decisions may answer questions -- Note which project decisions came from for context -- Past decisions are HIGH confidence for this user's preferences -- Memory augments but doesn't replace current documentation - -**If tools not available:** Skip and proceed to Context7. - ## Context7: First for Libraries Context7 provides authoritative, current documentation for libraries and frameworks. diff --git a/agents/gsd-project-researcher.md b/agents/gsd-project-researcher.md index fddc0810d..f62e76117 100644 --- a/agents/gsd-project-researcher.md +++ b/agents/gsd-project-researcher.md @@ -1,7 +1,7 @@ --- name: gsd-project-researcher description: Researches domain ecosystem before roadmap creation. Produces files in .planning/research/ consumed during roadmap creation. Spawned by /gsd:new-project or /gsd:new-milestone orchestrators. -tools: Read, Write, Bash, Grep, Glob, WebSearch, WebFetch, mcp__context7__*, mcp__gsd-memory__* +tools: Read, Write, Bash, Grep, Glob, WebSearch, WebFetch, mcp__context7__* color: cyan --- @@ -139,42 +139,6 @@ When researching "best library for X": -## GSD Memory: First for Past Work - -**If `gsd_memory_*` MCP tools are available,** query past project knowledge before external research. - -**When to use:** -- Check what tech stack was used in similar projects -- Find patterns established in past work -- Learn from documented pitfalls -- See what decisions were made for similar domains - -**How to use:** -``` -1. Search for relevant context: - gsd_memory_search({ query: "[domain or topic]" }) - -2. Find relevant decisions: - gsd_memory_decisions({ query: "[topic]" }) - -3. Find relevant patterns: - gsd_memory_patterns({ query: "[topic]" }) - -4. Check for pitfalls: - gsd_memory_pitfalls({ domain: "[domain]" }) - -5. See tech stack choices: - gsd_memory_stack({ query: "[library or purpose]" }) -``` - -**Best practices:** -- Query memory BEFORE web research — past decisions inform recommendations -- Past stack choices are HIGH confidence for this user's preferences -- Past pitfalls are HIGH confidence — actually experienced -- Memory augments but doesn't replace current documentation - -**If tools not available:** Skip and proceed to Context7. - ## Context7: First for Libraries Context7 provides authoritative, current documentation for libraries and frameworks. diff --git a/bin/install.js b/bin/install.js index 908cb6765..d741c4653 100755 --- a/bin/install.js +++ b/bin/install.js @@ -907,34 +907,13 @@ function uninstall(isGlobal, runtime = 'claude') { } } - // Remove GSD Memory MCP server config - if (settings.mcpServers && settings.mcpServers['gsd-memory']) { - delete settings.mcpServers['gsd-memory']; - settingsModified = true; - console.log(` ${green}✓${reset} Removed GSD Memory MCP config from settings`); - // Clean up empty mcpServers object - if (Object.keys(settings.mcpServers).length === 0) { - delete settings.mcpServers; - } - } - if (settingsModified) { writeSettings(settingsPath, settings); removedCount++; } } - // 6. Remove MCP server from ~/.gsd/ (Claude Code only) - if (runtime === 'claude') { - const mcpServerDir = path.join(os.homedir(), '.gsd', 'mcp-server'); - if (fs.existsSync(mcpServerDir)) { - fs.rmSync(mcpServerDir, { recursive: true }); - removedCount++; - console.log(` ${green}✓${reset} Removed GSD Memory MCP server`); - } - } - - // 7. For OpenCode, clean up permissions from opencode.json + // 6. For OpenCode, clean up permissions from opencode.json if (isOpencode) { const opencodeConfigDir = getOpencodeGlobalDir(); const configPath = path.join(opencodeConfigDir, 'opencode.json'); @@ -1050,102 +1029,6 @@ function configureOpencodePermissions() { console.log(` ${green}✓${reset} Configured read permission for GSD docs`); } -/** - * Install the GSD Memory MCP server - * - Copies gsd-memory/ to ~/.gsd/mcp-server/ - * - Runs npm install in that directory - * - Returns the path for MCP config - * @returns {{ success: boolean, serverPath?: string, error?: string }} - */ -function installMcpServer() { - const src = path.join(__dirname, '..', 'gsd-memory'); - - // Check if gsd-memory exists in the package - if (!fs.existsSync(src)) { - return { success: false, error: 'gsd-memory not found in package' }; - } - - const gsdDir = path.join(os.homedir(), '.gsd'); - const destDir = path.join(gsdDir, 'mcp-server'); - - // Ensure ~/.gsd exists - fs.mkdirSync(gsdDir, { recursive: true }); - - // Clean install: remove existing mcp-server - if (fs.existsSync(destDir)) { - fs.rmSync(destDir, { recursive: true }); - } - - // Copy gsd-memory to ~/.gsd/mcp-server - copyDirectory(src, destDir); - - // Run npm install in the mcp-server directory - try { - const { execSync } = require('child_process'); - execSync('npm install --production', { - cwd: destDir, - stdio: 'pipe', - timeout: 60000 - }); - } catch (err) { - return { - success: false, - error: `npm install failed: ${err.message}`, - serverPath: destDir - }; - } - - return { - success: true, - serverPath: destDir - }; -} - -/** - * Configure the GSD Memory MCP server in Claude Code settings - * @param {string} settingsPath - Path to settings.json - * @param {object} settings - Settings object - * @param {string} serverPath - Path to the MCP server - */ -function configureMcpServer(settingsPath, settings, serverPath) { - if (!settings.mcpServers) { - settings.mcpServers = {}; - } - - // Add gsd-memory MCP server config - settings.mcpServers['gsd-memory'] = { - command: 'node', - args: [path.join(serverPath, 'dist', 'index.js')] - }; - - return settings; -} - -/** - * Copy a directory recursively - */ -function copyDirectory(src, dest) { - fs.mkdirSync(dest, { recursive: true }); - - const entries = fs.readdirSync(src, { withFileTypes: true }); - - for (const entry of entries) { - const srcPath = path.join(src, entry.name); - const destPath = path.join(dest, entry.name); - - // Skip node_modules, .git, and test directories - if (entry.name === 'node_modules' || entry.name === '.git' || entry.name === 'tests') { - continue; - } - - if (entry.isDirectory()) { - copyDirectory(srcPath, destPath); - } else { - fs.copyFileSync(srcPath, destPath); - } - } -} - /** * Verify a directory exists and contains files */ @@ -1344,18 +1227,6 @@ function install(isGlobal, runtime = 'claude') { process.exit(1); } - // Install GSD Memory MCP server (Claude Code only, global installs only) - let mcpServerPath = null; - if (runtime === 'claude' && isGlobal) { - const mcpResult = installMcpServer(); - if (mcpResult.success) { - mcpServerPath = mcpResult.serverPath; - console.log(` ${green}✓${reset} Installed GSD Memory MCP server`); - } else if (mcpResult.error) { - console.log(` ${yellow}⚠${reset} MCP server install skipped: ${mcpResult.error}`); - } - } - // Configure statusline and hooks in settings.json // Gemini shares same hook system as Claude Code for now const settingsPath = path.join(targetDir, 'settings.json'); @@ -1404,12 +1275,6 @@ function install(isGlobal, runtime = 'claude') { } } - // Configure MCP server if installed (Claude Code only) - if (mcpServerPath && runtime === 'claude') { - configureMcpServer(settingsPath, settings, mcpServerPath); - console.log(` ${green}✓${reset} Configured GSD Memory MCP server`); - } - return { settingsPath, settings, statuslineCommand, runtime }; } diff --git a/commands/gsd/new-project.md b/commands/gsd/new-project.md index a06f089a4..b58b07ef0 100644 --- a/commands/gsd/new-project.md +++ b/commands/gsd/new-project.md @@ -926,26 +926,6 @@ EOF )" ``` -## Phase 9.5: Register with Memory (Optional) - -**If gsd_memory MCP tools are available:** - -Check if `gsd_memory_register` tool exists. If available, register this project with GSD memory for cross-project knowledge: - -``` -gsd_memory_register({ - path: process.cwd(), - name: "[project name from PROJECT.md]" -}) -``` - -Display confirmation: -``` -Memory: Project registered ✓ -``` - -**If tool not available:** Skip silently. GSD memory is optional. - ## Phase 10: Done Present completion with next steps: diff --git a/get-shit-done/workflows/complete-milestone.md b/get-shit-done/workflows/complete-milestone.md index 5d3b27aba..8ae1e551f 100644 --- a/get-shit-done/workflows/complete-milestone.md +++ b/get-shit-done/workflows/complete-milestone.md @@ -814,32 +814,6 @@ Confirm: "Committed: chore: complete v[X.Y] milestone" - - -Index the completed milestone with GSD Memory (if available). - -**Check if gsd_memory MCP tools are available:** - -If `gsd_memory_index` tool exists, trigger indexing: - -``` -gsd_memory_index({ - path: process.cwd() -}) -``` - -This updates the project's searchable knowledge base with: -- Milestone archive documents -- Final phase summaries -- Key decisions from PROJECT.md -- Requirements validation outcomes - -**If tool not available:** Skip silently. - -Report (if indexed): "Indexed milestone in GSD Memory" - - - ``` diff --git a/get-shit-done/workflows/execute-phase.md b/get-shit-done/workflows/execute-phase.md index 506927f86..44527b5ff 100644 --- a/get-shit-done/workflows/execute-phase.md +++ b/get-shit-done/workflows/execute-phase.md @@ -627,22 +627,6 @@ git commit -m "docs(phase-{X}): complete phase execution" ``` - -**If gsd_memory MCP tools are available:** - -Check if `gsd_memory_index` tool exists. If available, trigger indexing: - -``` -gsd_memory_index({ - path: process.cwd() -}) -``` - -This updates the project's searchable knowledge base with new summaries and verification results. - -**If tool not available:** Skip silently. - - Present next steps based on milestone status: diff --git a/gsd-memory/.gitignore b/gsd-memory/.gitignore deleted file mode 100644 index 3c4593898..000000000 --- a/gsd-memory/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -node_modules/ -*.log -.DS_Store diff --git a/gsd-memory/README.md b/gsd-memory/README.md deleted file mode 100644 index e128d4cb0..000000000 --- a/gsd-memory/README.md +++ /dev/null @@ -1,194 +0,0 @@ -# GSD Memory - -Cross-project knowledge system for GSD (Get Shit Done). An MCP server that provides semantic search across all your GSD projects, extracting decisions, patterns, pitfalls, and tech stack from YAML frontmatter. - -## Features - -- **Cross-project search** - Find content across all registered GSD projects -- **Decision extraction** - Query decisions from SUMMARY.md and PROJECT.md -- **Pattern discovery** - Find established patterns from completed phases -- **Pitfall awareness** - Learn from documented pitfalls in RESEARCH.md -- **Tech stack tracking** - Track libraries and tools used across projects -- **QMD integration** - Uses QMD for semantic search when available, falls back to grep - -## Installation - -### Option 1: Add to Claude Code MCP config (recommended) - -Add to `~/.claude/settings.json`: - -```json -{ - "mcpServers": { - "gsd-memory": { - "command": "npx", - "args": ["-y", "gsd-memory"] - } - } -} -``` - -### Option 2: Install globally - -```bash -npm install -g gsd-memory -``` - -Then add to `~/.claude/settings.json`: - -```json -{ - "mcpServers": { - "gsd-memory": { - "command": "gsd-memory" - } - } -} -``` - -### Option 3: With QMD (optional, for semantic search) - -Install QMD for better search results: - -```bash -bun install -g github:tobi/qmd -``` - -GSD Memory automatically detects and uses QMD when available. - -## MCP Tools - -### gsd_memory_register - -Register a project with GSD memory. - -```json -{ - "path": "/path/to/project", - "name": "my-project" -} -``` - -### gsd_memory_search - -Search across all registered projects. - -```json -{ - "query": "authentication JWT", - "project": "optional-filter", - "limit": 20 -} -``` - -### gsd_memory_decisions - -Find decisions made across projects. - -```json -{ - "query": "database choice", - "tags": ["postgres", "prisma"] -} -``` - -### gsd_memory_patterns - -Find established patterns. - -```json -{ - "query": "error handling" -} -``` - -### gsd_memory_pitfalls - -Find documented pitfalls. - -```json -{ - "domain": "authentication" -} -``` - -### gsd_memory_stack - -Find tech stack entries. - -```json -{ - "query": "jose" -} -``` - -### gsd_memory_index - -Trigger re-indexing for a project. - -```json -{ - "project": "my-project" -} -``` - -### gsd_memory_status - -Get status of the memory system. - -```json -{} -``` - -## How It Works - -GSD Memory extracts structured data from GSD's YAML frontmatter: - -| Document | Extracted Fields | -|----------|------------------| -| SUMMARY.md | `subsystem`, `tags`, `requires`, `provides`, `tech-stack`, `key-decisions`, `patterns-established` | -| RESEARCH.md | `domain`, `confidence`, standard stack tables, pitfalls sections | -| PROJECT.md | Requirements, constraints, key decisions table | - -Data is stored in `~/.gsd/projects.json` (registry) and optionally in QMD collections for semantic search. - -## Development - -```bash -cd gsd-memory -npm install -npm test # Run unit tests -npm run build # Build TypeScript -``` - -## Architecture - -``` -gsd-memory/ -├── src/ -│ ├── index.ts # MCP server entry point -│ ├── qmd.ts # QMD wrapper with grep fallback -│ ├── registry.ts # Project registry (~/.gsd/projects.json) -│ ├── extractors/ # Frontmatter and content extractors -│ │ ├── frontmatter.ts -│ │ ├── summary.ts -│ │ ├── research.ts -│ │ └── project.ts -│ └── tools/ # MCP tool implementations -│ ├── search.ts -│ ├── decisions.ts -│ ├── patterns.ts -│ ├── pitfalls.ts -│ ├── stack.ts -│ ├── register.ts -│ ├── index-tool.ts -│ └── status.ts -└── tests/ - ├── fixtures/ # Test fixtures - ├── extractors/ # Extractor tests - └── tools/ # Tool tests -``` - -## License - -MIT diff --git a/gsd-memory/dist/extractors/frontmatter.d.ts b/gsd-memory/dist/extractors/frontmatter.d.ts deleted file mode 100644 index 0e0734fc4..000000000 --- a/gsd-memory/dist/extractors/frontmatter.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Extract YAML frontmatter from markdown content - * Returns empty object if no frontmatter or invalid YAML - */ -export declare function extractFrontmatter(markdown: string): Record; -/** - * Extract frontmatter and content separately - */ -export declare function parseFrontmatter(markdown: string): { - frontmatter: Record; - content: string; -}; -//# sourceMappingURL=frontmatter.d.ts.map \ No newline at end of file diff --git a/gsd-memory/dist/extractors/frontmatter.d.ts.map b/gsd-memory/dist/extractors/frontmatter.d.ts.map deleted file mode 100644 index 3ad5d1c69..000000000 --- a/gsd-memory/dist/extractors/frontmatter.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../../src/extractors/frontmatter.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQ5E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG;IAClD,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC;CACjB,CAaA"} \ No newline at end of file diff --git a/gsd-memory/dist/extractors/frontmatter.js b/gsd-memory/dist/extractors/frontmatter.js deleted file mode 100644 index 858c4a7c2..000000000 --- a/gsd-memory/dist/extractors/frontmatter.js +++ /dev/null @@ -1,34 +0,0 @@ -import matter from 'gray-matter'; -/** - * Extract YAML frontmatter from markdown content - * Returns empty object if no frontmatter or invalid YAML - */ -export function extractFrontmatter(markdown) { - try { - const { data } = matter(markdown); - return data || {}; - } - catch { - // Return empty object on parse errors - return {}; - } -} -/** - * Extract frontmatter and content separately - */ -export function parseFrontmatter(markdown) { - try { - const { data, content } = matter(markdown); - return { - frontmatter: data || {}, - content: content.trim() - }; - } - catch { - return { - frontmatter: {}, - content: markdown.trim() - }; - } -} -//# sourceMappingURL=frontmatter.js.map \ No newline at end of file diff --git a/gsd-memory/dist/extractors/frontmatter.js.map b/gsd-memory/dist/extractors/frontmatter.js.map deleted file mode 100644 index c116bc916..000000000 --- a/gsd-memory/dist/extractors/frontmatter.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../../src/extractors/frontmatter.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AAEjC;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IACjD,IAAI,CAAC;QACH,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;QAClC,OAAO,IAAI,IAAI,EAAE,CAAC;IACpB,CAAC;IAAC,MAAM,CAAC;QACP,sCAAsC;QACtC,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAI/C,IAAI,CAAC;QACH,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC3C,OAAO;YACL,WAAW,EAAE,IAAI,IAAI,EAAE;YACvB,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE;SACxB,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,WAAW,EAAE,EAAE;YACf,OAAO,EAAE,QAAQ,CAAC,IAAI,EAAE;SACzB,CAAC;IACJ,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/gsd-memory/dist/extractors/index.d.ts b/gsd-memory/dist/extractors/index.d.ts deleted file mode 100644 index 029145f05..000000000 --- a/gsd-memory/dist/extractors/index.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -export { extractFrontmatter, parseFrontmatter } from './frontmatter.js'; -export { extractSummary, type SummaryData, type TechStackEntry, type Decision as SummaryDecision } from './summary.js'; -export { extractResearch, type ResearchData, type Pitfall, type DontHandRoll } from './research.js'; -export { extractProject, type ProjectData, type Decision as ProjectDecision, type Constraint } from './project.js'; -//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/gsd-memory/dist/extractors/index.d.ts.map b/gsd-memory/dist/extractors/index.d.ts.map deleted file mode 100644 index b07c2fe50..000000000 --- a/gsd-memory/dist/extractors/index.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/extractors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,KAAK,WAAW,EAAE,KAAK,cAAc,EAAE,KAAK,QAAQ,IAAI,eAAe,EAAE,MAAM,cAAc,CAAC;AACvH,OAAO,EAAE,eAAe,EAAE,KAAK,YAAY,EAAE,KAAK,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AACpG,OAAO,EAAE,cAAc,EAAE,KAAK,WAAW,EAAE,KAAK,QAAQ,IAAI,eAAe,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC"} \ No newline at end of file diff --git a/gsd-memory/dist/extractors/index.js b/gsd-memory/dist/extractors/index.js deleted file mode 100644 index e70ab28fa..000000000 --- a/gsd-memory/dist/extractors/index.js +++ /dev/null @@ -1,5 +0,0 @@ -export { extractFrontmatter, parseFrontmatter } from './frontmatter.js'; -export { extractSummary } from './summary.js'; -export { extractResearch } from './research.js'; -export { extractProject } from './project.js'; -//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/gsd-memory/dist/extractors/index.js.map b/gsd-memory/dist/extractors/index.js.map deleted file mode 100644 index a84f85f24..000000000 --- a/gsd-memory/dist/extractors/index.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/extractors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,cAAc,EAA2E,MAAM,cAAc,CAAC;AACvH,OAAO,EAAE,eAAe,EAAsD,MAAM,eAAe,CAAC;AACpG,OAAO,EAAE,cAAc,EAAuE,MAAM,cAAc,CAAC"} \ No newline at end of file diff --git a/gsd-memory/dist/extractors/project.d.ts b/gsd-memory/dist/extractors/project.d.ts deleted file mode 100644 index b762b7b1a..000000000 --- a/gsd-memory/dist/extractors/project.d.ts +++ /dev/null @@ -1,33 +0,0 @@ -export interface OutOfScopeItem { - item: string; - reason: string; -} -export interface Constraint { - type: string; - value: string; - why?: string; -} -export interface Decision { - decision: string; - rationale: string; - outcome: string; -} -export interface Requirements { - validated: string[]; - active: string[]; - outOfScope: OutOfScopeItem[]; -} -export interface ProjectData { - name: string; - description: string; - coreValue: string; - requirements: Requirements; - context: string; - constraints: Constraint[]; - decisions: Decision[]; -} -/** - * Extract structured data from a PROJECT.md file - */ -export declare function extractProject(markdown: string): ProjectData; -//# sourceMappingURL=project.d.ts.map \ No newline at end of file diff --git a/gsd-memory/dist/extractors/project.d.ts.map b/gsd-memory/dist/extractors/project.d.ts.map deleted file mode 100644 index 74dc4dd8b..000000000 --- a/gsd-memory/dist/extractors/project.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/extractors/project.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,cAAc,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,YAAY,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,SAAS,EAAE,QAAQ,EAAE,CAAC;CACvB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CAU5D"} \ No newline at end of file diff --git a/gsd-memory/dist/extractors/project.js b/gsd-memory/dist/extractors/project.js deleted file mode 100644 index c63ee95cc..000000000 --- a/gsd-memory/dist/extractors/project.js +++ /dev/null @@ -1,139 +0,0 @@ -/** - * Extract structured data from a PROJECT.md file - */ -export function extractProject(markdown) { - return { - name: extractName(markdown), - description: extractSection(markdown, 'What This Is'), - coreValue: extractSection(markdown, 'Core Value'), - requirements: extractRequirements(markdown), - context: extractSection(markdown, 'Context'), - constraints: extractConstraints(markdown), - decisions: extractDecisions(markdown) - }; -} -function extractName(content) { - // First line should be # ProjectName - const match = content.match(/^#\s+(.+)/m); - return match ? match[1].trim() : ''; -} -function extractSection(content, sectionName) { - // Find the section and extract content until next ## heading - const regex = new RegExp(`##\\s+${sectionName}\\n\\n([\\s\\S]*?)(?=\\n##|$)`, 'i'); - const match = content.match(regex); - return match ? match[1].trim() : ''; -} -function extractRequirements(content) { - const requirementsSection = content.match(/##\s+Requirements\n([\s\S]*?)(?=\n##[^#]|$)/i); - if (!requirementsSection) { - return { validated: [], active: [], outOfScope: [] }; - } - const section = requirementsSection[1]; - return { - validated: extractValidatedRequirements(section), - active: extractActiveRequirements(section), - outOfScope: extractOutOfScope(section) - }; -} -function extractValidatedRequirements(section) { - const requirements = []; - // Look for ### Validated subsection - const validatedSection = section.match(/###\s+Validated\n([\s\S]*?)(?=###|$)/i); - if (!validatedSection) - return requirements; - // Extract checkmark items: - ✓ requirement — version - const matches = validatedSection[1].match(/^-\s+✓\s+(.+)/gm); - if (matches) { - for (const match of matches) { - const content = match.replace(/^-\s+✓\s+/, '').trim(); - requirements.push(content); - } - } - return requirements; -} -function extractActiveRequirements(section) { - const requirements = []; - // Look for ### Active subsection - const activeSection = section.match(/###\s+Active\n([\s\S]*?)(?=###|$)/i); - if (!activeSection) - return requirements; - // Extract checkbox items: - [ ] requirement - const matches = activeSection[1].match(/^-\s+\[\s*\]\s+(.+)/gm); - if (matches) { - for (const match of matches) { - const content = match.replace(/^-\s+\[\s*\]\s+/, '').trim(); - requirements.push(content); - } - } - return requirements; -} -function extractOutOfScope(section) { - const items = []; - // Look for ### Out of Scope subsection - const outOfScopeSection = section.match(/###\s+Out of Scope\n([\s\S]*?)(?=###|$)/i); - if (!outOfScopeSection) - return items; - // Extract items: - Item — reason - const matches = outOfScopeSection[1].match(/^-\s+(.+)/gm); - if (matches) { - for (const match of matches) { - const content = match.replace(/^-\s+/, '').trim(); - // Split by em-dash or double hyphen - const parts = content.split(/\s+—\s+|\s+--\s+/); - items.push({ - item: parts[0].trim(), - reason: parts[1]?.trim() || '' - }); - } - } - return items; -} -function extractConstraints(content) { - const constraints = []; - const constraintsSection = content.match(/##\s+Constraints\n([\s\S]*?)(?=\n##|$)/i); - if (!constraintsSection) - return constraints; - // Extract items: - **Type**: Value — Why - const matches = constraintsSection[1].match(/^-\s+\*\*([^*]+)\*\*:\s*(.+)/gm); - if (matches) { - for (const match of matches) { - const typeMatch = match.match(/\*\*([^*]+)\*\*/); - const valueMatch = match.match(/\*\*[^*]+\*\*:\s*(.+)/); - if (typeMatch && valueMatch) { - const valueParts = valueMatch[1].split(/\s+—\s+|\s+--\s+/); - constraints.push({ - type: typeMatch[1].trim(), - value: valueParts[0].trim(), - why: valueParts[1]?.trim() - }); - } - } - } - return constraints; -} -function extractDecisions(content) { - const decisions = []; - const decisionsSection = content.match(/##\s+Key Decisions\n([\s\S]*?)(?=\n##[^#]|\n---|$)/i); - if (!decisionsSection) - return decisions; - // Parse markdown table rows - match rows with 3+ cells - const lines = decisionsSection[1].split('\n'); - for (const line of lines) { - // Must be a table row (starts and ends with |) - if (!line.trim().startsWith('|')) - continue; - // Skip header row (contains 'Decision') and separator row (contains ---) - if (line.includes('Decision') || line.includes('---')) - continue; - const cells = line.split('|').filter(c => c.trim()); - if (cells.length >= 3) { - decisions.push({ - decision: cells[0].trim(), - rationale: cells[1].trim(), - outcome: cells[2].trim() - }); - } - } - return decisions; -} -//# sourceMappingURL=project.js.map \ No newline at end of file diff --git a/gsd-memory/dist/extractors/project.js.map b/gsd-memory/dist/extractors/project.js.map deleted file mode 100644 index 1cd985461..000000000 --- a/gsd-memory/dist/extractors/project.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/extractors/project.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/gsd-memory/dist/extractors/research.d.ts b/gsd-memory/dist/extractors/research.d.ts deleted file mode 100644 index eb1e70e9f..000000000 --- a/gsd-memory/dist/extractors/research.d.ts +++ /dev/null @@ -1,40 +0,0 @@ -export interface StackEntry { - library: string; - version?: string; - purpose: string; - whyStandard?: string; -} -export interface Pitfall { - name: string; - description: string; - cause?: string; - prevention: string; - warningSigns?: string; -} -export interface DontHandRoll { - problem: string; - dontBuild: string; - useInstead: string; - why: string; -} -export interface UserConstraints { - locked: string[]; - discretion: string[]; - deferred: string[]; -} -export interface ResearchData { - domain: string; - confidence: string; - researched: string; - standardStack: StackEntry[]; - pitfalls: Pitfall[]; - dontHandRoll: DontHandRoll[]; - antiPatterns: string[]; - userConstraints: UserConstraints; - primaryRecommendation: string; -} -/** - * Extract structured data from a RESEARCH.md file - */ -export declare function extractResearch(markdown: string): ResearchData; -//# sourceMappingURL=research.d.ts.map \ No newline at end of file diff --git a/gsd-memory/dist/extractors/research.d.ts.map b/gsd-memory/dist/extractors/research.d.ts.map deleted file mode 100644 index 8a46832aa..000000000 --- a/gsd-memory/dist/extractors/research.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"research.d.ts","sourceRoot":"","sources":["../../src/extractors/research.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAE3B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IAGnB,aAAa,EAAE,UAAU,EAAE,CAAC;IAC5B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,YAAY,EAAE,YAAY,EAAE,CAAC;IAC7B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,eAAe,EAAE,eAAe,CAAC;IACjC,qBAAqB,EAAE,MAAM,CAAC;CAC/B;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,CAiB9D"} \ No newline at end of file diff --git a/gsd-memory/dist/extractors/research.js b/gsd-memory/dist/extractors/research.js deleted file mode 100644 index f7e39fc7d..000000000 --- a/gsd-memory/dist/extractors/research.js +++ /dev/null @@ -1,183 +0,0 @@ -import { parseFrontmatter } from './frontmatter.js'; -/** - * Extract structured data from a RESEARCH.md file - */ -export function extractResearch(markdown) { - const { frontmatter, content } = parseFrontmatter(markdown); - return { - // Metadata from frontmatter - domain: frontmatter.domain || '', - confidence: frontmatter.confidence || '', - researched: formatDate(frontmatter.researched), - // Extracted from content - standardStack: extractStandardStack(content), - pitfalls: extractPitfalls(content), - dontHandRoll: extractDontHandRoll(content), - antiPatterns: extractAntiPatterns(content), - userConstraints: extractUserConstraints(content), - primaryRecommendation: extractPrimaryRecommendation(content) - }; -} -function formatDate(date) { - if (!date) - return ''; - if (date instanceof Date) { - return date.toISOString().split('T')[0]; - } - return String(date); -} -function extractStandardStack(content) { - const entries = []; - // Look for standard_stack section and parse markdown tables - const stackSection = extractSection(content, 'standard_stack'); - if (!stackSection) - return entries; - // Parse Core and Supporting tables - const tableRows = stackSection.match(/\|[^|]+\|[^|]+\|[^|]+\|[^|]*\|/g); - if (!tableRows) - return entries; - for (const row of tableRows) { - // Skip header and separator rows - if (row.includes('Library') || row.includes('---')) - continue; - const cells = row.split('|').filter(c => c.trim()); - if (cells.length >= 3) { - entries.push({ - library: cells[0].trim(), - version: cells[1]?.trim(), - purpose: cells[2]?.trim(), - whyStandard: cells[3]?.trim() - }); - } - } - return entries; -} -function extractPitfalls(content) { - const pitfalls = []; - const pitfallSection = extractSection(content, 'common_pitfalls'); - if (!pitfallSection) - return pitfalls; - // Parse individual pitfall blocks (### Pitfall N: Name) - const pitfallBlocks = pitfallSection.split(/###\s+Pitfall\s+\d+:\s+/); - for (const block of pitfallBlocks) { - if (!block.trim()) - continue; - const lines = block.split('\n'); - const name = lines[0]?.trim(); - if (!name) - continue; - const description = extractField(block, 'What goes wrong'); - const cause = extractField(block, 'Why it happens'); - const prevention = extractField(block, 'How to avoid'); - const warningSigns = extractField(block, 'Warning signs'); - if (description || prevention) { - pitfalls.push({ - name, - description: description || '', - cause, - prevention: prevention || '', - warningSigns - }); - } - } - return pitfalls; -} -function extractDontHandRoll(content) { - const items = []; - const section = extractSection(content, 'dont_hand_roll'); - if (!section) - return items; - // Parse table rows - const tableRows = section.match(/\|[^|]+\|[^|]+\|[^|]+\|[^|]+\|/g); - if (!tableRows) - return items; - for (const row of tableRows) { - if (row.includes('Problem') || row.includes('---')) - continue; - const cells = row.split('|').filter(c => c.trim()); - if (cells.length >= 4) { - items.push({ - problem: cells[0].trim(), - dontBuild: cells[1].trim(), - useInstead: cells[2].trim(), - why: cells[3].trim() - }); - } - } - return items; -} -function extractAntiPatterns(content) { - const patterns = []; - const archSection = extractSection(content, 'architecture_patterns'); - if (!archSection) - return patterns; - // Look for "Anti-Patterns to Avoid" subsection - const antiMatch = archSection.match(/###\s+Anti-Patterns to Avoid\n([\s\S]*?)(?=###|$)/); - if (!antiMatch) - return patterns; - // Extract bullet points - const bullets = antiMatch[1].match(/^-\s+\*\*([^*]+)\*\*/gm); - if (bullets) { - for (const bullet of bullets) { - const match = bullet.match(/\*\*([^*]+)\*\*/); - if (match) - patterns.push(match[1].trim()); - } - } - return patterns; -} -function extractUserConstraints(content) { - const constraints = { - locked: [], - discretion: [], - deferred: [] - }; - const section = extractSection(content, 'user_constraints'); - if (!section) - return constraints; - // Extract locked decisions - const lockedMatch = section.match(/###\s+Locked Decisions\n([\s\S]*?)(?=###|$)/); - if (lockedMatch) { - constraints.locked = extractBulletPoints(lockedMatch[1]); - } - // Extract Claude's discretion - const discretionMatch = section.match(/###\s+Claude's Discretion\n([\s\S]*?)(?=###|$)/); - if (discretionMatch) { - constraints.discretion = extractBulletPoints(discretionMatch[1]); - } - // Extract deferred items - const deferredMatch = section.match(/###\s+Deferred Ideas[^#]*\n([\s\S]*?)(?=<\/|$)/); - if (deferredMatch) { - constraints.deferred = extractBulletPoints(deferredMatch[1]); - } - return constraints; -} -function extractPrimaryRecommendation(content) { - // Look for "Primary recommendation:" in summary section - const match = content.match(/\*\*Primary recommendation:\*\*\s*([^\n]+)/); - return match ? match[1].trim() : ''; -} -// Helper functions -function extractSection(content, sectionTag) { - const regex = new RegExp(`<${sectionTag}>([\\s\\S]*?)<\\/${sectionTag}>`, 'i'); - const match = content.match(regex); - return match ? match[1] : null; -} -function extractField(block, fieldName) { - const regex = new RegExp(`\\*\\*${fieldName}:\\*\\*\\s*([^\\n]+)`, 'i'); - const match = block.match(regex); - return match ? match[1].trim() : undefined; -} -function extractBulletPoints(text) { - const points = []; - const matches = text.match(/^-\s+(.+)/gm); - if (matches) { - for (const match of matches) { - const content = match.replace(/^-\s+/, '').trim(); - if (content) - points.push(content); - } - } - return points; -} -//# sourceMappingURL=research.js.map \ No newline at end of file diff --git a/gsd-memory/dist/extractors/research.js.map b/gsd-memory/dist/extractors/research.js.map deleted file mode 100644 index 203e1c97e..000000000 --- a/gsd-memory/dist/extractors/research.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"research.js","sourceRoot":"","sources":["../../src/extractors/research.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/gsd-memory/dist/extractors/summary.d.ts b/gsd-memory/dist/extractors/summary.d.ts deleted file mode 100644 index 7a190fc94..000000000 --- a/gsd-memory/dist/extractors/summary.d.ts +++ /dev/null @@ -1,38 +0,0 @@ -export interface TechStackEntry { - library: string; - version: string; - purpose?: string; -} -export interface Dependency { - phase: string; - provides: string; -} -export interface KeyFiles { - created: string[]; - modified: string[]; -} -export interface Decision { - decision: string; - source?: string; -} -export interface SummaryData { - phase: string; - plan: number | string; - subsystem: string; - tags: string[]; - requires: Dependency[]; - provides: string[]; - affects: string[]; - techStack: TechStackEntry[]; - patterns: string[]; - keyFiles: KeyFiles; - decisions: Decision[]; - duration: string; - completed: string; - oneLiner: string; -} -/** - * Extract structured data from a SUMMARY.md file - */ -export declare function extractSummary(markdown: string): SummaryData; -//# sourceMappingURL=summary.d.ts.map \ No newline at end of file diff --git a/gsd-memory/dist/extractors/summary.d.ts.map b/gsd-memory/dist/extractors/summary.d.ts.map deleted file mode 100644 index f8234ff08..000000000 --- a/gsd-memory/dist/extractors/summary.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"summary.d.ts","sourceRoot":"","sources":["../../src/extractors/summary.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAE1B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,EAAE,CAAC;IAGf,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;IAGlB,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,QAAQ,EAAE,MAAM,EAAE,CAAC;IAGnB,QAAQ,EAAE,QAAQ,CAAC;IAGnB,SAAS,EAAE,QAAQ,EAAE,CAAC;IAGtB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAGlB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CAgC5D"} \ No newline at end of file diff --git a/gsd-memory/dist/extractors/summary.js b/gsd-memory/dist/extractors/summary.js deleted file mode 100644 index 7b4f3ac34..000000000 --- a/gsd-memory/dist/extractors/summary.js +++ /dev/null @@ -1,88 +0,0 @@ -import { parseFrontmatter } from './frontmatter.js'; -/** - * Extract structured data from a SUMMARY.md file - */ -export function extractSummary(markdown) { - const { frontmatter, content } = parseFrontmatter(markdown); - return { - // Identifiers - phase: frontmatter.phase || '', - plan: frontmatter.plan || '', - subsystem: frontmatter.subsystem || '', - tags: frontmatter.tags || [], - // Dependency graph - requires: extractRequires(frontmatter.requires), - provides: frontmatter.provides || [], - affects: frontmatter.affects || [], - // Tech tracking - techStack: extractTechStack(frontmatter['tech-stack']), - patterns: frontmatter['patterns-established'] || [], - // Files - keyFiles: extractKeyFiles(frontmatter['key-files']), - // Decisions - decisions: extractDecisions(frontmatter['key-decisions']), - // Metadata - duration: frontmatter.duration || '', - completed: formatCompleted(frontmatter.completed), - // Content - oneLiner: extractOneLiner(content) - }; -} -function extractRequires(requires) { - if (!Array.isArray(requires)) - return []; - return requires.map((req) => ({ - phase: req.phase || '', - provides: req.provides || '' - })); -} -function extractTechStack(techStack) { - if (!techStack || typeof techStack !== 'object') - return []; - const ts = techStack; - const added = ts.added; - if (!Array.isArray(added)) - return []; - return added.map((entry) => { - // Handle both object format { library: version } and string format - if (typeof entry === 'object' && entry !== null) { - const [library, version] = Object.entries(entry)[0] || ['', '']; - return { library, version: String(version) }; - } - return { library: String(entry), version: '' }; - }); -} -function extractKeyFiles(keyFiles) { - if (!keyFiles || typeof keyFiles !== 'object') { - return { created: [], modified: [] }; - } - const kf = keyFiles; - return { - created: kf.created || [], - modified: kf.modified || [] - }; -} -function extractDecisions(decisions) { - if (!Array.isArray(decisions)) - return []; - return decisions.map((d) => ({ - decision: String(d), - source: 'frontmatter' - })); -} -function formatCompleted(completed) { - if (!completed) - return ''; - // If it's a Date object (YAML parsed it), format as ISO date - if (completed instanceof Date) { - return completed.toISOString().split('T')[0]; - } - return String(completed); -} -function extractOneLiner(content) { - // The one-liner is the bold text after the title - // Pattern: # Title\n\n**one-liner** - const match = content.match(/^#[^\n]+\n\n\*\*([^*]+)\*\*/m); - return match ? match[1].trim() : ''; -} -//# sourceMappingURL=summary.js.map \ No newline at end of file diff --git a/gsd-memory/dist/extractors/summary.js.map b/gsd-memory/dist/extractors/summary.js.map deleted file mode 100644 index 24f8ae8bd..000000000 --- a/gsd-memory/dist/extractors/summary.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"summary.js","sourceRoot":"","sources":["../../src/extractors/summary.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/gsd-memory/dist/index.d.ts b/gsd-memory/dist/index.d.ts deleted file mode 100644 index dc1ec8956..000000000 --- a/gsd-memory/dist/index.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env node -export {}; -//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/gsd-memory/dist/index.d.ts.map b/gsd-memory/dist/index.d.ts.map deleted file mode 100644 index 535b86d29..000000000 --- a/gsd-memory/dist/index.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/gsd-memory/dist/index.js b/gsd-memory/dist/index.js deleted file mode 100644 index 8b36ef6c8..000000000 --- a/gsd-memory/dist/index.js +++ /dev/null @@ -1,298 +0,0 @@ -#!/usr/bin/env node -import { Server } from '@modelcontextprotocol/sdk/server/index.js'; -import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; -import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js'; -import { search } from './tools/search.js'; -import { findDecisions } from './tools/decisions.js'; -import { findPatterns } from './tools/patterns.js'; -import { findPitfalls } from './tools/pitfalls.js'; -import { findStack } from './tools/stack.js'; -import { register } from './tools/register.js'; -import { index, indexAll } from './tools/index-tool.js'; -import { getStatus } from './tools/status.js'; -// Define available tools -const tools = [ - { - name: 'gsd_memory_search', - description: 'Search across all registered GSD projects for content matching a query. Returns enriched results with project, phase, and document type context.', - inputSchema: { - type: 'object', - properties: { - query: { - type: 'string', - description: 'The search query' - }, - project: { - type: 'string', - description: 'Optional: limit search to a specific project' - }, - limit: { - type: 'number', - description: 'Maximum number of results (default: 20)' - } - }, - required: ['query'] - } - }, - { - name: 'gsd_memory_decisions', - description: 'Find decisions made across GSD projects. Searches KEY-DECISIONS from SUMMARY.md frontmatter and Key Decisions tables from PROJECT.md.', - inputSchema: { - type: 'object', - properties: { - query: { - type: 'string', - description: 'Optional: filter decisions by keyword' - }, - project: { - type: 'string', - description: 'Optional: limit to a specific project' - }, - tags: { - type: 'array', - items: { type: 'string' }, - description: 'Optional: filter by tags' - }, - limit: { - type: 'number', - description: 'Maximum number of results (default: 50)' - } - } - } - }, - { - name: 'gsd_memory_patterns', - description: 'Find patterns established across GSD projects. Extracts PATTERNS-ESTABLISHED from SUMMARY.md frontmatter.', - inputSchema: { - type: 'object', - properties: { - query: { - type: 'string', - description: 'Optional: filter patterns by keyword' - }, - project: { - type: 'string', - description: 'Optional: limit to a specific project' - }, - tags: { - type: 'array', - items: { type: 'string' }, - description: 'Optional: filter by tags' - }, - limit: { - type: 'number', - description: 'Maximum number of results (default: 50)' - } - } - } - }, - { - name: 'gsd_memory_pitfalls', - description: 'Find documented pitfalls from RESEARCH.md files. Includes what went wrong, causes, and prevention strategies.', - inputSchema: { - type: 'object', - properties: { - query: { - type: 'string', - description: 'Optional: filter pitfalls by keyword' - }, - project: { - type: 'string', - description: 'Optional: limit to a specific project' - }, - domain: { - type: 'string', - description: 'Optional: filter by technology domain' - }, - limit: { - type: 'number', - description: 'Maximum number of results (default: 50)' - } - } - } - }, - { - name: 'gsd_memory_stack', - description: 'Find tech stack entries across GSD projects. Extracts from SUMMARY.md (tech-stack.added) and RESEARCH.md (standard stack tables).', - inputSchema: { - type: 'object', - properties: { - query: { - type: 'string', - description: 'Optional: filter by library name or purpose' - }, - project: { - type: 'string', - description: 'Optional: limit to a specific project' - }, - limit: { - type: 'number', - description: 'Maximum number of results (default: 100)' - } - } - } - }, - { - name: 'gsd_memory_register', - description: 'Register a project with GSD memory. Creates a QMD collection if QMD is available.', - inputSchema: { - type: 'object', - properties: { - path: { - type: 'string', - description: 'Path to the project root (must contain .planning directory)' - }, - name: { - type: 'string', - description: 'Optional: project name (defaults to directory name)' - } - }, - required: ['path'] - } - }, - { - name: 'gsd_memory_index', - description: 'Trigger indexing/update for a project. Updates QMD collection if available, otherwise marks project as indexed for grep fallback.', - inputSchema: { - type: 'object', - properties: { - project: { - type: 'string', - description: 'Project name to index' - }, - path: { - type: 'string', - description: 'Alternative: project path to index' - } - } - } - }, - { - name: 'gsd_memory_status', - description: 'Show status of GSD memory system: QMD availability, registered projects, document counts.', - inputSchema: { - type: 'object', - properties: {} - } - } -]; -// Create server instance -const server = new Server({ - name: 'gsd-memory', - version: '1.0.0' -}, { - capabilities: { - tools: {} - } -}); -// Handle list tools request -server.setRequestHandler(ListToolsRequestSchema, async () => ({ - tools -})); -// Handle tool calls -server.setRequestHandler(CallToolRequestSchema, async (request) => { - const { name, arguments: args } = request.params; - try { - let result; - switch (name) { - case 'gsd_memory_search': - result = await search({ - query: args?.query, - project: args?.project, - limit: args?.limit - }); - break; - case 'gsd_memory_decisions': - result = await findDecisions({ - query: args?.query, - project: args?.project, - tags: args?.tags, - limit: args?.limit - }); - break; - case 'gsd_memory_patterns': - result = await findPatterns({ - query: args?.query, - project: args?.project, - tags: args?.tags, - limit: args?.limit - }); - break; - case 'gsd_memory_pitfalls': - result = await findPitfalls({ - query: args?.query, - project: args?.project, - domain: args?.domain, - limit: args?.limit - }); - break; - case 'gsd_memory_stack': - result = await findStack({ - query: args?.query, - project: args?.project, - limit: args?.limit - }); - break; - case 'gsd_memory_register': - result = await register({ - path: args?.path, - name: args?.name - }); - break; - case 'gsd_memory_index': - if (args?.project || args?.path) { - result = await index({ - project: args?.project, - path: args?.path - }); - } - else { - result = await indexAll(); - } - break; - case 'gsd_memory_status': - result = await getStatus(); - break; - default: - return { - content: [ - { - type: 'text', - text: `Unknown tool: ${name}` - } - ], - isError: true - }; - } - return { - content: [ - { - type: 'text', - text: JSON.stringify(result, null, 2) - } - ] - }; - } - catch (error) { - return { - content: [ - { - type: 'text', - text: `Error: ${error instanceof Error ? error.message : String(error)}` - } - ], - isError: true - }; - } -}); -// Start the server -async function main() { - const transport = new StdioServerTransport(); - await server.connect(transport); - console.error('GSD Memory MCP server started'); -} -main().catch((error) => { - console.error('Fatal error:', error); - process.exit(1); -}); -//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/gsd-memory/dist/index.js.map b/gsd-memory/dist/index.js.map deleted file mode 100644 index 3ba97f845..000000000 --- a/gsd-memory/dist/index.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/gsd-memory/dist/qmd.d.ts b/gsd-memory/dist/qmd.d.ts deleted file mode 100644 index 9b1cd9e97..000000000 --- a/gsd-memory/dist/qmd.d.ts +++ /dev/null @@ -1,67 +0,0 @@ -export interface QmdSearchResult { - content: string; - source: string; - relevance: number; - context?: string; -} -export interface QmdSearchOptions { - query: string; - paths: string[]; - limit?: number; - collection?: string; -} -export interface QmdCollectionOptions { - name: string; - paths: string[]; - context?: string; -} -export interface QmdResult { - success: boolean; - reason?: string; - data?: unknown; -} -export interface QmdStatus { - available: boolean; - collection?: string; - documentCount?: number; - lastIndexed?: string; -} -/** - * QMD wrapper - provides semantic search when QMD is available, - * falls back to grep-based search otherwise - */ -export declare const qmd: { - /** - * Check if QMD is installed and available - */ - isAvailable(): Promise; - /** - * Search for content using QMD or grep fallback - */ - search(options: QmdSearchOptions): Promise; - /** - * Search using QMD (when available) - */ - qmdSearch(options: QmdSearchOptions): Promise; - /** - * Grep-based fallback search - */ - grepFallback(options: QmdSearchOptions): Promise; - /** - * Find all markdown files in a directory recursively - */ - findMarkdownFiles(dir: string, files?: string[]): string[]; - /** - * Create a QMD collection for a project - */ - createCollection(options: QmdCollectionOptions): Promise; - /** - * Trigger reindexing of a collection - */ - index(collectionName: string): Promise; - /** - * Get status of a collection - */ - status(collectionName: string): Promise; -}; -//# sourceMappingURL=qmd.d.ts.map \ No newline at end of file diff --git a/gsd-memory/dist/qmd.d.ts.map b/gsd-memory/dist/qmd.d.ts.map deleted file mode 100644 index c00edff24..000000000 --- a/gsd-memory/dist/qmd.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"qmd.d.ts","sourceRoot":"","sources":["../src/qmd.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,eAAO,MAAM,GAAG;IACd;;OAEG;mBACkB,OAAO,CAAC,OAAO,CAAC;IASrC;;OAEG;oBACmB,gBAAgB,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAUnE;;OAEG;uBACsB,gBAAgB,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAoBtE;;OAEG;0BACyB,gBAAgB,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IA8CzE;;OAEG;2BACoB,MAAM,UAAS,MAAM,EAAE,GAAQ,MAAM,EAAE;IAyB9D;;OAEG;8BAC6B,oBAAoB,GAAG,OAAO,CAAC,SAAS,CAAC;IA4BzE;;OAEG;0BACyB,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IAsBvD;;OAEG;2BAC0B,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;CAyBzD,CAAC"} \ No newline at end of file diff --git a/gsd-memory/dist/qmd.js b/gsd-memory/dist/qmd.js deleted file mode 100644 index 05a13732f..000000000 --- a/gsd-memory/dist/qmd.js +++ /dev/null @@ -1,199 +0,0 @@ -import { exec } from 'child_process'; -import { promisify } from 'util'; -import { readFileSync, readdirSync, statSync } from 'fs'; -import { join } from 'path'; -const execAsync = promisify(exec); -/** - * QMD wrapper - provides semantic search when QMD is available, - * falls back to grep-based search otherwise - */ -export const qmd = { - /** - * Check if QMD is installed and available - */ - async isAvailable() { - try { - await execAsync('which qmd'); - return true; - } - catch { - return false; - } - }, - /** - * Search for content using QMD or grep fallback - */ - async search(options) { - const available = await this.isAvailable(); - if (available && options.collection) { - return this.qmdSearch(options); - } - return this.grepFallback(options); - }, - /** - * Search using QMD (when available) - */ - async qmdSearch(options) { - try { - const limit = options.limit || 10; - const { stdout } = await execAsync(`qmd query "${options.query}" --collection "${options.collection}" --limit ${limit} --json`); - const parsed = JSON.parse(stdout); - return (parsed.results || []).map((r) => ({ - content: r.content, - source: r.source, - relevance: r.score || 0.5, - context: 'qmd' - })); - } - catch { - // Fall back to grep if QMD search fails - return this.grepFallback(options); - } - }, - /** - * Grep-based fallback search - */ - async grepFallback(options) { - const results = []; - const limit = options.limit || 20; - for (const searchPath of options.paths) { - try { - const files = this.findMarkdownFiles(searchPath); - for (const file of files) { - try { - const content = readFileSync(file, 'utf-8'); - const query = options.query.toLowerCase(); - // Simple relevance: count matches - const matches = (content.toLowerCase().match(new RegExp(query, 'g')) || []).length; - if (matches > 0) { - // Extract context around first match - const lowerContent = content.toLowerCase(); - const matchIndex = lowerContent.indexOf(query); - const start = Math.max(0, matchIndex - 100); - const end = Math.min(content.length, matchIndex + query.length + 100); - const snippet = content.slice(start, end); - results.push({ - content: snippet, - source: file, - relevance: Math.min(1, matches * 0.1), - context: 'grep' - }); - } - } - catch { - // Skip files that can't be read - } - } - } - catch { - // Skip paths that can't be accessed - } - } - // Sort by relevance and limit - return results - .sort((a, b) => b.relevance - a.relevance) - .slice(0, limit); - }, - /** - * Find all markdown files in a directory recursively - */ - findMarkdownFiles(dir, files = []) { - try { - const entries = readdirSync(dir); - for (const entry of entries) { - const fullPath = join(dir, entry); - try { - const stat = statSync(fullPath); - if (stat.isDirectory() && !entry.startsWith('.') && entry !== 'node_modules') { - this.findMarkdownFiles(fullPath, files); - } - else if (stat.isFile() && entry.endsWith('.md')) { - files.push(fullPath); - } - } - catch { - // Skip entries that can't be accessed - } - } - } - catch { - // Return empty if directory can't be read - } - return files; - }, - /** - * Create a QMD collection for a project - */ - async createCollection(options) { - const available = await this.isAvailable(); - if (!available) { - return { - success: false, - reason: 'qmd_not_available' - }; - } - try { - const paths = options.paths.join(' '); - const contextArg = options.context ? `--context "${options.context}"` : ''; - await execAsync(`qmd add "${options.name}" ${paths} ${contextArg}`); - return { success: true }; - } - catch (error) { - return { - success: false, - reason: 'create_failed', - data: error instanceof Error ? error.message : String(error) - }; - } - }, - /** - * Trigger reindexing of a collection - */ - async index(collectionName) { - const available = await this.isAvailable(); - if (!available) { - return { - success: false, - reason: 'qmd_not_available' - }; - } - try { - await execAsync(`qmd update "${collectionName}"`); - return { success: true }; - } - catch (error) { - return { - success: false, - reason: 'index_failed', - data: error instanceof Error ? error.message : String(error) - }; - } - }, - /** - * Get status of a collection - */ - async status(collectionName) { - const available = await this.isAvailable(); - if (!available) { - return { available: false }; - } - try { - const { stdout } = await execAsync(`qmd status "${collectionName}" --json`); - const parsed = JSON.parse(stdout); - return { - available: true, - collection: collectionName, - documentCount: parsed.documentCount || 0, - lastIndexed: parsed.lastIndexed - }; - } - catch { - return { - available: true, - collection: collectionName, - documentCount: 0 - }; - } - } -}; -//# sourceMappingURL=qmd.js.map \ No newline at end of file diff --git a/gsd-memory/dist/qmd.js.map b/gsd-memory/dist/qmd.js.map deleted file mode 100644 index 310892937..000000000 --- a/gsd-memory/dist/qmd.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"qmd.js","sourceRoot":"","sources":["../src/qmd.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/gsd-memory/dist/registry.d.ts b/gsd-memory/dist/registry.d.ts deleted file mode 100644 index 26a6858ff..000000000 --- a/gsd-memory/dist/registry.d.ts +++ /dev/null @@ -1,44 +0,0 @@ -export interface RegisteredProject { - name: string; - path: string; - qmdCollection?: string; - registeredAt: string; - lastIndexed?: string; -} -export interface Registry { - version: string; - projects: RegisteredProject[]; -} -/** - * Read the project registry - */ -export declare function readRegistry(): Registry; -/** - * Write the project registry - */ -export declare function writeRegistry(registry: Registry): void; -/** - * Register a new project - */ -export declare function registerProject(project: Omit): RegisteredProject; -/** - * Update a project's last indexed time - */ -export declare function updateProjectIndexTime(name: string): void; -/** - * Get a project by name - */ -export declare function getProject(name: string): RegisteredProject | undefined; -/** - * Get all registered projects - */ -export declare function getAllProjects(): RegisteredProject[]; -/** - * Remove a project from the registry - */ -export declare function unregisterProject(name: string): boolean; -/** - * Get the registry path (for testing) - */ -export declare function getRegistryPath(): string; -//# sourceMappingURL=registry.d.ts.map \ No newline at end of file diff --git a/gsd-memory/dist/registry.d.ts.map b/gsd-memory/dist/registry.d.ts.map deleted file mode 100644 index 375b37a27..000000000 --- a/gsd-memory/dist/registry.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B;AAcD;;GAEG;AACH,wBAAgB,YAAY,IAAI,QAAQ,CAavC;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAGtD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC,iBAAiB,EAAE,cAAc,CAAC,GAAG,iBAAiB,CA2BnG;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAQzD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAGtE;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,iBAAiB,EAAE,CAEpD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAWvD;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC"} \ No newline at end of file diff --git a/gsd-memory/dist/registry.js b/gsd-memory/dist/registry.js deleted file mode 100644 index 7542bfe2f..000000000 --- a/gsd-memory/dist/registry.js +++ /dev/null @@ -1,106 +0,0 @@ -import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs'; -import { join } from 'path'; -import { homedir } from 'os'; -const REGISTRY_DIR = join(homedir(), '.gsd'); -const REGISTRY_PATH = join(REGISTRY_DIR, 'projects.json'); -/** - * Ensure the registry directory exists - */ -function ensureRegistryDir() { - if (!existsSync(REGISTRY_DIR)) { - mkdirSync(REGISTRY_DIR, { recursive: true }); - } -} -/** - * Read the project registry - */ -export function readRegistry() { - ensureRegistryDir(); - if (!existsSync(REGISTRY_PATH)) { - return { version: '1.0.0', projects: [] }; - } - try { - const content = readFileSync(REGISTRY_PATH, 'utf-8'); - return JSON.parse(content); - } - catch { - return { version: '1.0.0', projects: [] }; - } -} -/** - * Write the project registry - */ -export function writeRegistry(registry) { - ensureRegistryDir(); - writeFileSync(REGISTRY_PATH, JSON.stringify(registry, null, 2)); -} -/** - * Register a new project - */ -export function registerProject(project) { - const registry = readRegistry(); - // Check if project already exists - const existingIndex = registry.projects.findIndex(p => p.path === project.path || p.name === project.name); - const newProject = { - ...project, - registeredAt: new Date().toISOString() - }; - if (existingIndex >= 0) { - // Update existing project - registry.projects[existingIndex] = { - ...registry.projects[existingIndex], - ...newProject, - registeredAt: registry.projects[existingIndex].registeredAt - }; - } - else { - // Add new project - registry.projects.push(newProject); - } - writeRegistry(registry); - return newProject; -} -/** - * Update a project's last indexed time - */ -export function updateProjectIndexTime(name) { - const registry = readRegistry(); - const project = registry.projects.find(p => p.name === name); - if (project) { - project.lastIndexed = new Date().toISOString(); - writeRegistry(registry); - } -} -/** - * Get a project by name - */ -export function getProject(name) { - const registry = readRegistry(); - return registry.projects.find(p => p.name === name); -} -/** - * Get all registered projects - */ -export function getAllProjects() { - return readRegistry().projects; -} -/** - * Remove a project from the registry - */ -export function unregisterProject(name) { - const registry = readRegistry(); - const index = registry.projects.findIndex(p => p.name === name); - if (index >= 0) { - registry.projects.splice(index, 1); - writeRegistry(registry); - return true; - } - return false; -} -/** - * Get the registry path (for testing) - */ -export function getRegistryPath() { - return REGISTRY_PATH; -} -//# sourceMappingURL=registry.js.map \ No newline at end of file diff --git a/gsd-memory/dist/registry.js.map b/gsd-memory/dist/registry.js.map deleted file mode 100644 index eaa9440ca..000000000 --- a/gsd-memory/dist/registry.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACxE,OAAO,EAAE,IAAI,EAAW,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAe7B,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,MAAM,CAAC,CAAC;AAC7C,MAAM,aAAa,GAAG,IAAI,CAAC,YAAY,EAAE,eAAe,CAAC,CAAC;AAE1D;;GAEG;AACH,SAAS,iBAAiB;IACxB,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,SAAS,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY;IAC1B,iBAAiB,EAAE,CAAC;IAEpB,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC5C,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QACrD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC5C,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,QAAkB;IAC9C,iBAAiB,EAAE,CAAC;IACpB,aAAa,CAAC,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,OAAgD;IAC9E,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAC;IAEhC,kCAAkC;IAClC,MAAM,aAAa,GAAG,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAC/C,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,CACxD,CAAC;IAEF,MAAM,UAAU,GAAsB;QACpC,GAAG,OAAO;QACV,YAAY,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACvC,CAAC;IAEF,IAAI,aAAa,IAAI,CAAC,EAAE,CAAC;QACvB,0BAA0B;QAC1B,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC,GAAG;YACjC,GAAG,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC;YACnC,GAAG,UAAU;YACb,YAAY,EAAE,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,YAAY;SAC5D,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,kBAAkB;QAClB,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACrC,CAAC;IAED,aAAa,CAAC,QAAQ,CAAC,CAAC;IACxB,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAY;IACjD,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAC;IAChC,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IAE7D,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC/C,aAAa,CAAC,QAAQ,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAC;IAChC,OAAO,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AACtD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO,YAAY,EAAE,CAAC,QAAQ,CAAC;AACjC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAC;IAChC,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IAEhE,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QACf,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QACnC,aAAa,CAAC,QAAQ,CAAC,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,aAAa,CAAC;AACvB,CAAC"} \ No newline at end of file diff --git a/gsd-memory/dist/tools/decisions.d.ts b/gsd-memory/dist/tools/decisions.d.ts deleted file mode 100644 index a146172cf..000000000 --- a/gsd-memory/dist/tools/decisions.d.ts +++ /dev/null @@ -1,20 +0,0 @@ -export interface DecisionResult { - decision: string; - rationale?: string; - project: string; - phase?: string; - source: string; - date?: string; - tags?: string[]; -} -export interface DecisionOptions { - query?: string; - project?: string; - tags?: string[]; - limit?: number; -} -/** - * Search for decisions across all registered GSD projects - */ -export declare function findDecisions(options: DecisionOptions): Promise; -//# sourceMappingURL=decisions.d.ts.map \ No newline at end of file diff --git a/gsd-memory/dist/tools/decisions.d.ts.map b/gsd-memory/dist/tools/decisions.d.ts.map deleted file mode 100644 index f675dbf22..000000000 --- a/gsd-memory/dist/tools/decisions.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"decisions.d.ts","sourceRoot":"","sources":["../../src/tools/decisions.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAyCvF"} \ No newline at end of file diff --git a/gsd-memory/dist/tools/decisions.js b/gsd-memory/dist/tools/decisions.js deleted file mode 100644 index aa0dcbbe9..000000000 --- a/gsd-memory/dist/tools/decisions.js +++ /dev/null @@ -1,120 +0,0 @@ -import { getAllProjects } from '../registry.js'; -import { extractSummary } from '../extractors/summary.js'; -import { extractProject } from '../extractors/project.js'; -import { readFileSync, existsSync, readdirSync, statSync } from 'fs'; -import { join } from 'path'; -/** - * Search for decisions across all registered GSD projects - */ -export async function findDecisions(options) { - const projects = options.project - ? getAllProjects().filter(p => p.name === options.project) - : getAllProjects(); - const allDecisions = []; - for (const project of projects) { - const planningPath = join(project.path, '.planning'); - if (!existsSync(planningPath)) - continue; - // Extract decisions from PROJECT.md - const projectDecisions = extractProjectDecisions(planningPath, project.name); - allDecisions.push(...projectDecisions); - // Extract decisions from all SUMMARY.md files - const summaryDecisions = extractSummaryDecisions(planningPath, project.name); - allDecisions.push(...summaryDecisions); - } - // Filter by query if provided - let filtered = allDecisions; - if (options.query) { - const query = options.query.toLowerCase(); - filtered = allDecisions.filter(d => d.decision.toLowerCase().includes(query) || - d.rationale?.toLowerCase().includes(query)); - } - // Filter by tags if provided - if (options.tags && options.tags.length > 0) { - const tags = options.tags.map(t => t.toLowerCase()); - filtered = filtered.filter(d => d.tags?.some(t => tags.includes(t.toLowerCase()))); - } - // Apply limit - const limit = options.limit || 50; - return filtered.slice(0, limit); -} -/** - * Extract decisions from PROJECT.md - */ -function extractProjectDecisions(planningPath, projectName) { - const projectPath = join(planningPath, 'PROJECT.md'); - if (!existsSync(projectPath)) - return []; - try { - const content = readFileSync(projectPath, 'utf-8'); - const projectData = extractProject(content); - return projectData.decisions.map(d => ({ - decision: d.decision, - rationale: d.rationale, - project: projectName, - source: projectPath - })); - } - catch { - return []; - } -} -/** - * Extract decisions from all SUMMARY.md files in a project - */ -function extractSummaryDecisions(planningPath, projectName) { - const decisions = []; - const phasesPath = join(planningPath, 'phases'); - if (!existsSync(phasesPath)) - return decisions; - // Find all SUMMARY.md files - const summaryFiles = findSummaryFiles(phasesPath); - for (const file of summaryFiles) { - try { - const content = readFileSync(file, 'utf-8'); - const summaryData = extractSummary(content); - for (const decision of summaryData.decisions) { - decisions.push({ - decision: decision.decision, - project: projectName, - phase: summaryData.phase, - source: file, - date: summaryData.completed, - tags: summaryData.tags - }); - } - } - catch { - // Skip files that can't be parsed - } - } - return decisions; -} -/** - * Recursively find all SUMMARY.md files - */ -function findSummaryFiles(dir, files = []) { - try { - const entries = readdirSync(dir); - for (const entry of entries) { - const fullPath = join(dir, entry); - try { - const stat = statSync(fullPath); - if (stat.isDirectory()) { - findSummaryFiles(fullPath, files); - } - else if (entry.toUpperCase().includes('SUMMARY') && entry.endsWith('.md')) { - files.push(fullPath); - } - } - catch { - // Skip entries that can't be accessed - } - } - } - catch { - // Return empty if directory can't be read - } - return files; -} -//# sourceMappingURL=decisions.js.map \ No newline at end of file diff --git a/gsd-memory/dist/tools/decisions.js.map b/gsd-memory/dist/tools/decisions.js.map deleted file mode 100644 index 565644b48..000000000 --- a/gsd-memory/dist/tools/decisions.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"decisions.js","sourceRoot":"","sources":["../../src/tools/decisions.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/gsd-memory/dist/tools/index-tool.d.ts b/gsd-memory/dist/tools/index-tool.d.ts deleted file mode 100644 index 5cbaef1ed..000000000 --- a/gsd-memory/dist/tools/index-tool.d.ts +++ /dev/null @@ -1,23 +0,0 @@ -export interface IndexOptions { - path?: string; - project?: string; -} -export interface IndexResult { - success: boolean; - project?: string; - documentsIndexed?: number; - error?: string; - qmdUsed: boolean; -} -/** - * Trigger indexing/update for a project - */ -export declare function index(options: IndexOptions): Promise; -/** - * Index all registered projects - */ -export declare function indexAll(): Promise<{ - success: boolean; - results: IndexResult[]; -}>; -//# sourceMappingURL=index-tool.d.ts.map \ No newline at end of file diff --git a/gsd-memory/dist/tools/index-tool.d.ts.map b/gsd-memory/dist/tools/index-tool.d.ts.map deleted file mode 100644 index f25951a94..000000000 --- a/gsd-memory/dist/tools/index-tool.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index-tool.d.ts","sourceRoot":"","sources":["../../src/tools/index-tool.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,wBAAsB,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CA2FvE;AAED;;GAEG;AACH,wBAAsB,QAAQ,IAAI,OAAO,CAAC;IACxC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB,CAAC,CAYD"} \ No newline at end of file diff --git a/gsd-memory/dist/tools/index-tool.js b/gsd-memory/dist/tools/index-tool.js deleted file mode 100644 index be703ffeb..000000000 --- a/gsd-memory/dist/tools/index-tool.js +++ /dev/null @@ -1,107 +0,0 @@ -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 \ No newline at end of file diff --git a/gsd-memory/dist/tools/index-tool.js.map b/gsd-memory/dist/tools/index-tool.js.map deleted file mode 100644 index 38b046fb2..000000000 --- a/gsd-memory/dist/tools/index-tool.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index-tool.js","sourceRoot":"","sources":["../../src/tools/index-tool.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/gsd-memory/dist/tools/patterns.d.ts b/gsd-memory/dist/tools/patterns.d.ts deleted file mode 100644 index 06c825db2..000000000 --- a/gsd-memory/dist/tools/patterns.d.ts +++ /dev/null @@ -1,19 +0,0 @@ -export interface PatternResult { - pattern: string; - project: string; - phase: string; - source: string; - date?: string; - tags?: string[]; -} -export interface PatternOptions { - query?: string; - project?: string; - tags?: string[]; - limit?: number; -} -/** - * Search for patterns established across all registered GSD projects - */ -export declare function findPatterns(options: PatternOptions): Promise; -//# sourceMappingURL=patterns.d.ts.map \ No newline at end of file diff --git a/gsd-memory/dist/tools/patterns.d.ts.map b/gsd-memory/dist/tools/patterns.d.ts.map deleted file mode 100644 index 559e55b47..000000000 --- a/gsd-memory/dist/tools/patterns.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../../src/tools/patterns.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAuDpF"} \ No newline at end of file diff --git a/gsd-memory/dist/tools/patterns.js b/gsd-memory/dist/tools/patterns.js deleted file mode 100644 index 03dfa69e9..000000000 --- a/gsd-memory/dist/tools/patterns.js +++ /dev/null @@ -1,81 +0,0 @@ -import { getAllProjects } from '../registry.js'; -import { extractSummary } from '../extractors/summary.js'; -import { readFileSync, existsSync, readdirSync, statSync } from 'fs'; -import { join } from 'path'; -/** - * Search for patterns established across all registered GSD projects - */ -export async function findPatterns(options) { - const projects = options.project - ? getAllProjects().filter(p => p.name === options.project) - : getAllProjects(); - const allPatterns = []; - for (const project of projects) { - const phasesPath = join(project.path, '.planning', 'phases'); - if (!existsSync(phasesPath)) - continue; - // Find all SUMMARY.md files and extract patterns - const summaryFiles = findSummaryFiles(phasesPath); - for (const file of summaryFiles) { - try { - const content = readFileSync(file, 'utf-8'); - const summaryData = extractSummary(content); - for (const pattern of summaryData.patterns) { - allPatterns.push({ - pattern, - project: project.name, - phase: summaryData.phase, - source: file, - date: summaryData.completed, - tags: summaryData.tags - }); - } - } - catch { - // Skip files that can't be parsed - } - } - } - // Filter by query if provided - let filtered = allPatterns; - if (options.query) { - const query = options.query.toLowerCase(); - filtered = allPatterns.filter(p => p.pattern.toLowerCase().includes(query)); - } - // Filter by tags if provided - if (options.tags && options.tags.length > 0) { - const tags = options.tags.map(t => t.toLowerCase()); - filtered = filtered.filter(p => p.tags?.some(t => tags.includes(t.toLowerCase()))); - } - // Apply limit - const limit = options.limit || 50; - return filtered.slice(0, limit); -} -/** - * Recursively find all SUMMARY.md files - */ -function findSummaryFiles(dir, files = []) { - try { - const entries = readdirSync(dir); - for (const entry of entries) { - const fullPath = join(dir, entry); - try { - const stat = statSync(fullPath); - if (stat.isDirectory()) { - findSummaryFiles(fullPath, files); - } - else if (entry.toUpperCase().includes('SUMMARY') && entry.endsWith('.md')) { - files.push(fullPath); - } - } - catch { - // Skip entries that can't be accessed - } - } - } - catch { - // Return empty if directory can't be read - } - return files; -} -//# sourceMappingURL=patterns.js.map \ No newline at end of file diff --git a/gsd-memory/dist/tools/patterns.js.map b/gsd-memory/dist/tools/patterns.js.map deleted file mode 100644 index a69874e6d..000000000 --- a/gsd-memory/dist/tools/patterns.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"patterns.js","sourceRoot":"","sources":["../../src/tools/patterns.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/gsd-memory/dist/tools/pitfalls.d.ts b/gsd-memory/dist/tools/pitfalls.d.ts deleted file mode 100644 index 13c1cbdd3..000000000 --- a/gsd-memory/dist/tools/pitfalls.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { type Pitfall } from '../extractors/research.js'; -export interface PitfallResult extends Pitfall { - project: string; - phase?: string; - domain: string; - source: string; -} -export interface PitfallOptions { - query?: string; - project?: string; - domain?: string; - limit?: number; -} -/** - * Search for pitfalls documented across all registered GSD projects - */ -export declare function findPitfalls(options: PitfallOptions): Promise; -//# sourceMappingURL=pitfalls.d.ts.map \ No newline at end of file diff --git a/gsd-memory/dist/tools/pitfalls.d.ts.map b/gsd-memory/dist/tools/pitfalls.d.ts.map deleted file mode 100644 index 3feba832e..000000000 --- a/gsd-memory/dist/tools/pitfalls.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"pitfalls.d.ts","sourceRoot":"","sources":["../../src/tools/pitfalls.ts"],"names":[],"mappings":"AACA,OAAO,EAAmB,KAAK,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAI1E,MAAM,WAAW,aAAc,SAAQ,OAAO;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CA4DpF"} \ No newline at end of file diff --git a/gsd-memory/dist/tools/pitfalls.js b/gsd-memory/dist/tools/pitfalls.js deleted file mode 100644 index b89fc63e2..000000000 --- a/gsd-memory/dist/tools/pitfalls.js +++ /dev/null @@ -1,85 +0,0 @@ -import { getAllProjects } from '../registry.js'; -import { extractResearch } from '../extractors/research.js'; -import { readFileSync, existsSync, readdirSync, statSync } from 'fs'; -import { join } from 'path'; -/** - * Search for pitfalls documented across all registered GSD projects - */ -export async function findPitfalls(options) { - const projects = options.project - ? getAllProjects().filter(p => p.name === options.project) - : getAllProjects(); - const allPitfalls = []; - for (const project of projects) { - const planningPath = join(project.path, '.planning'); - if (!existsSync(planningPath)) - continue; - // Find all RESEARCH.md files - const researchFiles = findResearchFiles(planningPath); - for (const file of researchFiles) { - try { - const content = readFileSync(file, 'utf-8'); - const researchData = extractResearch(content); - // Extract phase from path if present - const phaseMatch = file.match(/phases\/(\d+-[^/]+)/); - const phase = phaseMatch ? phaseMatch[1] : undefined; - for (const pitfall of researchData.pitfalls) { - allPitfalls.push({ - ...pitfall, - project: project.name, - phase, - domain: researchData.domain, - source: file - }); - } - } - catch { - // Skip files that can't be parsed - } - } - } - // Filter by query if provided - let filtered = allPitfalls; - if (options.query) { - const query = options.query.toLowerCase(); - filtered = allPitfalls.filter(p => p.name.toLowerCase().includes(query) || - p.description.toLowerCase().includes(query) || - p.prevention.toLowerCase().includes(query)); - } - // Filter by domain if provided - if (options.domain) { - const domain = options.domain.toLowerCase(); - filtered = filtered.filter(p => p.domain.toLowerCase().includes(domain)); - } - // Apply limit - const limit = options.limit || 50; - return filtered.slice(0, limit); -} -/** - * Recursively find all RESEARCH.md files - */ -function findResearchFiles(dir, files = []) { - try { - const entries = readdirSync(dir); - for (const entry of entries) { - const fullPath = join(dir, entry); - try { - const stat = statSync(fullPath); - if (stat.isDirectory() && !entry.startsWith('.')) { - findResearchFiles(fullPath, files); - } - else if (entry.toUpperCase().includes('RESEARCH') && entry.endsWith('.md')) { - files.push(fullPath); - } - } - catch { - // Skip entries that can't be accessed - } - } - } - catch { - // Return empty if directory can't be read - } - return files; -} -//# sourceMappingURL=pitfalls.js.map \ No newline at end of file diff --git a/gsd-memory/dist/tools/pitfalls.js.map b/gsd-memory/dist/tools/pitfalls.js.map deleted file mode 100644 index 3b815eeb8..000000000 --- a/gsd-memory/dist/tools/pitfalls.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"pitfalls.js","sourceRoot":"","sources":["../../src/tools/pitfalls.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/gsd-memory/dist/tools/register.d.ts b/gsd-memory/dist/tools/register.d.ts deleted file mode 100644 index 6f672d025..000000000 --- a/gsd-memory/dist/tools/register.d.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { type RegisteredProject } from '../registry.js'; -export interface RegisterOptions { - path: string; - name?: string; -} -export interface RegisterResult { - success: boolean; - project?: RegisteredProject; - qmdCollection?: string; - error?: string; -} -/** - * Register a project with GSD memory - */ -export declare function register(options: RegisterOptions): Promise; -/** - * Get status of all registered projects - */ -export declare function status(): Promise<{ - qmdAvailable: boolean; - projects: Array<{ - name: string; - path: string; - qmdCollection?: string; - registeredAt: string; - lastIndexed?: string; - documentCount?: number; - }>; -}>; -/** - * Unregister a project - */ -export declare function unregister(name: string): Promise<{ - success: boolean; - error?: string; -}>; -//# sourceMappingURL=register.d.ts.map \ No newline at end of file diff --git a/gsd-memory/dist/tools/register.d.ts.map b/gsd-memory/dist/tools/register.d.ts.map deleted file mode 100644 index 673b353a9..000000000 --- a/gsd-memory/dist/tools/register.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/tools/register.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkE,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAKxH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAqDhF;AAED;;GAEG;AACH,wBAAsB,MAAM,IAAI,OAAO,CAAC;IACtC,YAAY,EAAE,OAAO,CAAC;IACtB,QAAQ,EAAE,KAAK,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,YAAY,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC,CAAC;CACJ,CAAC,CA4BD;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAwB5F"} \ No newline at end of file diff --git a/gsd-memory/dist/tools/register.js b/gsd-memory/dist/tools/register.js deleted file mode 100644 index dbcb9c314..000000000 --- a/gsd-memory/dist/tools/register.js +++ /dev/null @@ -1,105 +0,0 @@ -import { registerProject, getProject, getAllProjects, unregisterProject } from '../registry.js'; -import { qmd } from '../qmd.js'; -import { existsSync } from 'fs'; -import { join, basename } from 'path'; -/** - * Register a project with GSD memory - */ -export async function register(options) { - // Validate path exists - if (!existsSync(options.path)) { - return { - success: false, - error: `Path does not exist: ${options.path}` - }; - } - // Validate .planning directory exists - const planningPath = join(options.path, '.planning'); - if (!existsSync(planningPath)) { - return { - success: false, - error: `No .planning directory found at: ${planningPath}` - }; - } - // Determine project name - const name = options.name || basename(options.path); - // Check if QMD is available for semantic search - const qmdAvailable = await qmd.isAvailable(); - let qmdCollection; - if (qmdAvailable) { - // Create QMD collection - qmdCollection = `gsd-${name.toLowerCase().replace(/[^a-z0-9]/g, '-')}`; - const qmdResult = await qmd.createCollection({ - name: qmdCollection, - paths: [planningPath], - context: `GSD project: ${name}` - }); - if (!qmdResult.success) { - // QMD collection creation failed, but we can still register - qmdCollection = undefined; - } - } - // Register in local registry - const project = registerProject({ - name, - path: options.path, - qmdCollection - }); - return { - success: true, - project, - qmdCollection - }; -} -/** - * Get status of all registered projects - */ -export async function status() { - const qmdAvailable = await qmd.isAvailable(); - const projects = getAllProjects(); - const enrichedProjects = await Promise.all(projects.map(async (project) => { - let documentCount; - if (qmdAvailable && project.qmdCollection) { - const qmdStatus = await qmd.status(project.qmdCollection); - documentCount = qmdStatus.documentCount; - } - return { - name: project.name, - path: project.path, - qmdCollection: project.qmdCollection, - registeredAt: project.registeredAt, - lastIndexed: project.lastIndexed, - documentCount - }; - })); - return { - qmdAvailable, - projects: enrichedProjects - }; -} -/** - * Unregister a project - */ -export async function unregister(name) { - const project = getProject(name); - if (!project) { - return { - success: false, - error: `Project not found: ${name}` - }; - } - // Remove from QMD if it has a collection - if (project.qmdCollection && await qmd.isAvailable()) { - try { - // QMD doesn't have a direct remove command, so we just skip - // The collection will be orphaned but harmless - } - catch { - // Ignore QMD errors - } - } - // Remove from registry - unregisterProject(name); - return { success: true }; -} -//# sourceMappingURL=register.js.map \ No newline at end of file diff --git a/gsd-memory/dist/tools/register.js.map b/gsd-memory/dist/tools/register.js.map deleted file mode 100644 index c4a2c5642..000000000 --- a/gsd-memory/dist/tools/register.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"register.js","sourceRoot":"","sources":["../../src/tools/register.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/gsd-memory/dist/tools/search.d.ts b/gsd-memory/dist/tools/search.d.ts deleted file mode 100644 index 1f5116881..000000000 --- a/gsd-memory/dist/tools/search.d.ts +++ /dev/null @@ -1,19 +0,0 @@ -export interface SearchResult { - content: string; - source: string; - project: string; - phase?: string; - relevance: number; - documentType?: 'summary' | 'research' | 'project' | 'plan' | 'other'; -} -export interface SearchOptions { - query: string; - project?: string; - tags?: string[]; - limit?: number; -} -/** - * Search across all registered GSD projects - */ -export declare function search(options: SearchOptions): Promise; -//# sourceMappingURL=search.d.ts.map \ No newline at end of file diff --git a/gsd-memory/dist/tools/search.d.ts.map b/gsd-memory/dist/tools/search.d.ts.map deleted file mode 100644 index f6bb515e1..000000000 --- a/gsd-memory/dist/tools/search.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/tools/search.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;CACtE;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAsB,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAqC5E"} \ No newline at end of file diff --git a/gsd-memory/dist/tools/search.js b/gsd-memory/dist/tools/search.js deleted file mode 100644 index eb1597d4f..000000000 --- a/gsd-memory/dist/tools/search.js +++ /dev/null @@ -1,92 +0,0 @@ -import { qmd } from '../qmd.js'; -import { getAllProjects } from '../registry.js'; -import { extractFrontmatter } from '../extractors/frontmatter.js'; -import { readFileSync, existsSync } from 'fs'; -import { join, basename } from 'path'; -/** - * Search across all registered GSD projects - */ -export async function search(options) { - const projects = options.project - ? getAllProjects().filter(p => p.name === options.project) - : getAllProjects(); - if (projects.length === 0) { - return []; - } - const allResults = []; - for (const project of projects) { - const planningPath = join(project.path, '.planning'); - if (!existsSync(planningPath)) - continue; - // Search using QMD or grep fallback - const searchResults = await qmd.search({ - query: options.query, - paths: [planningPath], - collection: project.qmdCollection, - limit: options.limit || 20 - }); - // Enrich results with GSD context - for (const result of searchResults) { - const enriched = enrichResult(result, project.name); - allResults.push(enriched); - } - } - // Sort by relevance - allResults.sort((a, b) => b.relevance - a.relevance); - // Apply limit - const limit = options.limit || 20; - return allResults.slice(0, limit); -} -/** - * Enrich a search result with GSD-specific context - */ -function enrichResult(result, projectName) { - const enriched = { - content: result.content, - source: result.source, - project: projectName, - relevance: result.relevance, - documentType: getDocumentType(result.source) - }; - // Try to extract phase from frontmatter or path - enriched.phase = extractPhase(result.source); - return enriched; -} -/** - * Determine document type from file path/name - */ -function getDocumentType(source) { - const filename = basename(source).toUpperCase(); - if (filename.includes('SUMMARY')) - return 'summary'; - if (filename.includes('RESEARCH')) - return 'research'; - if (filename.includes('PROJECT')) - return 'project'; - if (filename.includes('PLAN')) - return 'plan'; - return 'other'; -} -/** - * Extract phase identifier from file path or content - */ -function extractPhase(source) { - // Try to get from path: .planning/phases/01-foundation/... - const pathMatch = source.match(/phases\/(\d+-[^/]+)/); - if (pathMatch) - return pathMatch[1]; - // Try to get from frontmatter - try { - if (existsSync(source)) { - const content = readFileSync(source, 'utf-8'); - const frontmatter = extractFrontmatter(content); - if (frontmatter.phase) - return String(frontmatter.phase); - } - } - catch { - // Ignore errors reading file - } - return undefined; -} -//# sourceMappingURL=search.js.map \ No newline at end of file diff --git a/gsd-memory/dist/tools/search.js.map b/gsd-memory/dist/tools/search.js.map deleted file mode 100644 index 16a051d53..000000000 --- a/gsd-memory/dist/tools/search.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/tools/search.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/gsd-memory/dist/tools/stack.d.ts b/gsd-memory/dist/tools/stack.d.ts deleted file mode 100644 index 61d1cf152..000000000 --- a/gsd-memory/dist/tools/stack.d.ts +++ /dev/null @@ -1,19 +0,0 @@ -export interface StackResult { - library: string; - version?: string; - purpose?: string; - project: string; - phase?: string; - source: string; - sourceType: 'summary' | 'research'; -} -export interface StackOptions { - query?: string; - project?: string; - limit?: number; -} -/** - * Search for tech stack entries across all registered GSD projects - */ -export declare function findStack(options: StackOptions): Promise; -//# sourceMappingURL=stack.d.ts.map \ No newline at end of file diff --git a/gsd-memory/dist/tools/stack.d.ts.map b/gsd-memory/dist/tools/stack.d.ts.map deleted file mode 100644 index ae7dde47e..000000000 --- a/gsd-memory/dist/tools/stack.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"stack.d.ts","sourceRoot":"","sources":["../../src/tools/stack.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,SAAS,GAAG,UAAU,CAAC;CACpC;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CA0C7E"} \ No newline at end of file diff --git a/gsd-memory/dist/tools/stack.js b/gsd-memory/dist/tools/stack.js deleted file mode 100644 index cd6bb3a60..000000000 --- a/gsd-memory/dist/tools/stack.js +++ /dev/null @@ -1,137 +0,0 @@ -import { getAllProjects } from '../registry.js'; -import { extractSummary } from '../extractors/summary.js'; -import { extractResearch } from '../extractors/research.js'; -import { readFileSync, existsSync, readdirSync, statSync } from 'fs'; -import { join } from 'path'; -/** - * Search for tech stack entries across all registered GSD projects - */ -export async function findStack(options) { - const projects = options.project - ? getAllProjects().filter(p => p.name === options.project) - : getAllProjects(); - const allStack = []; - for (const project of projects) { - const planningPath = join(project.path, '.planning'); - if (!existsSync(planningPath)) - continue; - // Extract from SUMMARY.md files - const summaryStack = extractFromSummaries(planningPath, project.name); - allStack.push(...summaryStack); - // Extract from RESEARCH.md files - const researchStack = extractFromResearch(planningPath, project.name); - allStack.push(...researchStack); - } - // Filter by query if provided - let filtered = allStack; - if (options.query) { - const query = options.query.toLowerCase(); - filtered = allStack.filter(s => s.library.toLowerCase().includes(query) || - s.purpose?.toLowerCase().includes(query)); - } - // Deduplicate by library name within each project - const seen = new Set(); - const deduplicated = filtered.filter(s => { - const key = `${s.project}:${s.library}`; - if (seen.has(key)) - return false; - seen.add(key); - return true; - }); - // Apply limit - const limit = options.limit || 100; - return deduplicated.slice(0, limit); -} -/** - * Extract tech stack from all SUMMARY.md files - */ -function extractFromSummaries(planningPath, projectName) { - const stack = []; - const phasesPath = join(planningPath, 'phases'); - if (!existsSync(phasesPath)) - return stack; - const summaryFiles = findFiles(phasesPath, 'SUMMARY'); - for (const file of summaryFiles) { - try { - const content = readFileSync(file, 'utf-8'); - const summaryData = extractSummary(content); - // Extract phase from path - const phaseMatch = file.match(/phases\/(\d+-[^/]+)/); - const phase = phaseMatch ? phaseMatch[1] : undefined; - for (const entry of summaryData.techStack) { - stack.push({ - library: entry.library, - version: entry.version, - purpose: entry.purpose, - project: projectName, - phase, - source: file, - sourceType: 'summary' - }); - } - } - catch { - // Skip files that can't be parsed - } - } - return stack; -} -/** - * Extract tech stack from all RESEARCH.md files - */ -function extractFromResearch(planningPath, projectName) { - const stack = []; - const researchFiles = findFiles(planningPath, 'RESEARCH'); - for (const file of researchFiles) { - try { - const content = readFileSync(file, 'utf-8'); - const researchData = extractResearch(content); - // Extract phase from path - const phaseMatch = file.match(/phases\/(\d+-[^/]+)/); - const phase = phaseMatch ? phaseMatch[1] : undefined; - for (const entry of researchData.standardStack) { - stack.push({ - library: entry.library, - version: entry.version, - purpose: entry.purpose, - project: projectName, - phase, - source: file, - sourceType: 'research' - }); - } - } - catch { - // Skip files that can't be parsed - } - } - return stack; -} -/** - * Recursively find files matching a pattern - */ -function findFiles(dir, pattern, files = []) { - try { - const entries = readdirSync(dir); - for (const entry of entries) { - const fullPath = join(dir, entry); - try { - const stat = statSync(fullPath); - if (stat.isDirectory() && !entry.startsWith('.')) { - findFiles(fullPath, pattern, files); - } - else if (entry.toUpperCase().includes(pattern) && entry.endsWith('.md')) { - files.push(fullPath); - } - } - catch { - // Skip entries that can't be accessed - } - } - } - catch { - // Return empty if directory can't be read - } - return files; -} -//# sourceMappingURL=stack.js.map \ No newline at end of file diff --git a/gsd-memory/dist/tools/stack.js.map b/gsd-memory/dist/tools/stack.js.map deleted file mode 100644 index 3bc9b527c..000000000 --- a/gsd-memory/dist/tools/stack.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"stack.js","sourceRoot":"","sources":["../../src/tools/stack.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAuB,MAAM,0BAA0B,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AACrE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAkB5B;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAqB;IACnD,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO;QAC9B,CAAC,CAAC,cAAc,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,OAAO,CAAC;QAC1D,CAAC,CAAC,cAAc,EAAE,CAAC;IAErB,MAAM,QAAQ,GAAkB,EAAE,CAAC;IAEnC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QACrD,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;YAAE,SAAS;QAExC,gCAAgC;QAChC,MAAM,YAAY,GAAG,oBAAoB,CAAC,YAAY,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QACtE,QAAQ,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,CAAC;QAE/B,iCAAiC;QACjC,MAAM,aAAa,GAAG,mBAAmB,CAAC,YAAY,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QACtE,QAAQ,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,CAAC;IAClC,CAAC;IAED,8BAA8B;IAC9B,IAAI,QAAQ,GAAG,QAAQ,CAAC;IACxB,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;QAC1C,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAC7B,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC;YACvC,CAAC,CAAC,OAAO,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CACzC,CAAC;IACJ,CAAC;IAED,kDAAkD;IAClD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;QACvC,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;QACxC,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;QAChC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;IAEH,cAAc;IACd,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,GAAG,CAAC;IACnC,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;AACtC,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB,CAAC,YAAoB,EAAE,WAAmB;IACrE,MAAM,KAAK,GAAkB,EAAE,CAAC;IAChC,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;IAEhD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,KAAK,CAAC;IAE1C,MAAM,YAAY,GAAG,SAAS,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IAEtD,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;QAChC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC5C,MAAM,WAAW,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;YAE5C,0BAA0B;YAC1B,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;YACrD,MAAM,KAAK,GAAG,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAErD,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,SAAS,EAAE,CAAC;gBAC1C,KAAK,CAAC,IAAI,CAAC;oBACT,OAAO,EAAE,KAAK,CAAC,OAAO;oBACtB,OAAO,EAAE,KAAK,CAAC,OAAO;oBACtB,OAAO,EAAE,KAAK,CAAC,OAAO;oBACtB,OAAO,EAAE,WAAW;oBACpB,KAAK;oBACL,MAAM,EAAE,IAAI;oBACZ,UAAU,EAAE,SAAS;iBACtB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,kCAAkC;QACpC,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB,CAAC,YAAoB,EAAE,WAAmB;IACpE,MAAM,KAAK,GAAkB,EAAE,CAAC;IAEhC,MAAM,aAAa,GAAG,SAAS,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IAE1D,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;QACjC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC5C,MAAM,YAAY,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;YAE9C,0BAA0B;YAC1B,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;YACrD,MAAM,KAAK,GAAG,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAErD,KAAK,MAAM,KAAK,IAAI,YAAY,CAAC,aAAa,EAAE,CAAC;gBAC/C,KAAK,CAAC,IAAI,CAAC;oBACT,OAAO,EAAE,KAAK,CAAC,OAAO;oBACtB,OAAO,EAAE,KAAK,CAAC,OAAO;oBACtB,OAAO,EAAE,KAAK,CAAC,OAAO;oBACtB,OAAO,EAAE,WAAW;oBACpB,KAAK;oBACL,MAAM,EAAE,IAAI;oBACZ,UAAU,EAAE,UAAU;iBACvB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,kCAAkC;QACpC,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,SAAS,SAAS,CAAC,GAAW,EAAE,OAAe,EAAE,QAAkB,EAAE;IACnE,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;QAEjC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YAClC,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;gBAEhC,IAAI,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBACjD,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;gBACtC,CAAC;qBAAM,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC1E,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACvB,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,sCAAsC;YACxC,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,0CAA0C;IAC5C,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"} \ No newline at end of file diff --git a/gsd-memory/dist/tools/status.d.ts b/gsd-memory/dist/tools/status.d.ts deleted file mode 100644 index 0290c902c..000000000 --- a/gsd-memory/dist/tools/status.d.ts +++ /dev/null @@ -1,23 +0,0 @@ -export interface ProjectStatus { - name: string; - path: string; - exists: boolean; - hasPlanningDir: boolean; - qmdCollection?: string; - qmdAvailable: boolean; - documentCount: number; - registeredAt: string; - lastIndexed?: string; -} -export interface MemoryStatus { - qmdAvailable: boolean; - qmdVersion?: string; - totalProjects: number; - totalDocuments: number; - projects: ProjectStatus[]; -} -/** - * Get comprehensive status of GSD memory system - */ -export declare function getStatus(): Promise; -//# sourceMappingURL=status.d.ts.map \ No newline at end of file diff --git a/gsd-memory/dist/tools/status.d.ts.map b/gsd-memory/dist/tools/status.d.ts.map deleted file mode 100644 index adfb8a450..000000000 --- a/gsd-memory/dist/tools/status.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/tools/status.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,cAAc,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B;AAED;;GAEG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,YAAY,CAAC,CAmCvD"} \ No newline at end of file diff --git a/gsd-memory/dist/tools/status.js b/gsd-memory/dist/tools/status.js deleted file mode 100644 index afdf903fa..000000000 --- a/gsd-memory/dist/tools/status.js +++ /dev/null @@ -1,67 +0,0 @@ -import { getAllProjects } from '../registry.js'; -import { qmd } from '../qmd.js'; -import { existsSync, readdirSync, statSync } from 'fs'; -import { join } from 'path'; -/** - * Get comprehensive status of GSD memory system - */ -export async function getStatus() { - const qmdAvailable = await qmd.isAvailable(); - const projects = getAllProjects(); - let totalDocuments = 0; - const projectStatuses = []; - for (const project of projects) { - const planningPath = join(project.path, '.planning'); - const exists = existsSync(project.path); - const hasPlanningDir = existsSync(planningPath); - // Count documents in .planning directory - const documentCount = hasPlanningDir ? countMarkdownFiles(planningPath) : 0; - totalDocuments += documentCount; - projectStatuses.push({ - name: project.name, - path: project.path, - exists, - hasPlanningDir, - qmdCollection: project.qmdCollection, - qmdAvailable: qmdAvailable && !!project.qmdCollection, - documentCount, - registeredAt: project.registeredAt, - lastIndexed: project.lastIndexed - }); - } - return { - qmdAvailable, - totalProjects: projects.length, - totalDocuments, - projects: projectStatuses - }; -} -/** - * Count markdown files in a directory recursively - */ -function countMarkdownFiles(dir) { - let count = 0; - try { - const entries = readdirSync(dir); - for (const entry of entries) { - const fullPath = join(dir, entry); - try { - const stat = statSync(fullPath); - if (stat.isDirectory() && !entry.startsWith('.')) { - count += countMarkdownFiles(fullPath); - } - else if (stat.isFile() && entry.endsWith('.md')) { - count++; - } - } - catch { - // Skip entries that can't be accessed - } - } - } - catch { - // Return 0 if directory can't be read - } - return count; -} -//# sourceMappingURL=status.js.map \ No newline at end of file diff --git a/gsd-memory/dist/tools/status.js.map b/gsd-memory/dist/tools/status.js.map deleted file mode 100644 index 7f89fcb50..000000000 --- a/gsd-memory/dist/tools/status.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/tools/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAsB5B;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,MAAM,YAAY,GAAG,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC;IAC7C,MAAM,QAAQ,GAAG,cAAc,EAAE,CAAC;IAElC,IAAI,cAAc,GAAG,CAAC,CAAC;IACvB,MAAM,eAAe,GAAoB,EAAE,CAAC;IAE5C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QACrD,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACxC,MAAM,cAAc,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;QAEhD,yCAAyC;QACzC,MAAM,aAAa,GAAG,cAAc,CAAC,CAAC,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5E,cAAc,IAAI,aAAa,CAAC;QAEhC,eAAe,CAAC,IAAI,CAAC;YACnB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,MAAM;YACN,cAAc;YACd,aAAa,EAAE,OAAO,CAAC,aAAa;YACpC,YAAY,EAAE,YAAY,IAAI,CAAC,CAAC,OAAO,CAAC,aAAa;YACrD,aAAa;YACb,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,WAAW,EAAE,OAAO,CAAC,WAAW;SACjC,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,YAAY;QACZ,aAAa,EAAE,QAAQ,CAAC,MAAM;QAC9B,cAAc;QACd,QAAQ,EAAE,eAAe;KAC1B,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CAAC,GAAW;IACrC,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;QAEjC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YAClC,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;gBAEhC,IAAI,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBACjD,KAAK,IAAI,kBAAkB,CAAC,QAAQ,CAAC,CAAC;gBACxC,CAAC;qBAAM,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;oBAClD,KAAK,EAAE,CAAC;gBACV,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,sCAAsC;YACxC,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,sCAAsC;IACxC,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"} \ No newline at end of file diff --git a/gsd-memory/package-lock.json b/gsd-memory/package-lock.json deleted file mode 100644 index b9e56ded4..000000000 --- a/gsd-memory/package-lock.json +++ /dev/null @@ -1,3005 +0,0 @@ -{ - "name": "gsd-memory", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "gsd-memory", - "version": "1.0.0", - "dependencies": { - "@modelcontextprotocol/sdk": "^1.0.0", - "gray-matter": "^4.0.3", - "yaml": "^2.3.0" - }, - "bin": { - "gsd-memory": "dist/index.js" - }, - "devDependencies": { - "@types/node": "^20.0.0", - "typescript": "^5.3.0", - "vitest": "^1.0.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@hono/node-server": { - "version": "1.19.9", - "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.9.tgz", - "integrity": "sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==", - "license": "MIT", - "engines": { - "node": ">=18.14.1" - }, - "peerDependencies": { - "hono": "^4" - } - }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@modelcontextprotocol/sdk": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.26.0.tgz", - "integrity": "sha512-Y5RmPncpiDtTXDbLKswIJzTqu2hyBKxTNsgKqKclDbhIgg1wgtf1fRuvxgTnRfcnxtvvgbIEcqUOzZrJ6iSReg==", - "license": "MIT", - "dependencies": { - "@hono/node-server": "^1.19.9", - "ajv": "^8.17.1", - "ajv-formats": "^3.0.1", - "content-type": "^1.0.5", - "cors": "^2.8.5", - "cross-spawn": "^7.0.5", - "eventsource": "^3.0.2", - "eventsource-parser": "^3.0.0", - "express": "^5.2.1", - "express-rate-limit": "^8.2.1", - "hono": "^4.11.4", - "jose": "^6.1.3", - "json-schema-typed": "^8.0.2", - "pkce-challenge": "^5.0.0", - "raw-body": "^3.0.0", - "zod": "^3.25 || ^4.0", - "zod-to-json-schema": "^3.25.1" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@cfworker/json-schema": "^4.1.1", - "zod": "^3.25 || ^4.0" - }, - "peerDependenciesMeta": { - "@cfworker/json-schema": { - "optional": true - }, - "zod": { - "optional": false - } - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.1.tgz", - "integrity": "sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.57.1.tgz", - "integrity": "sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.57.1.tgz", - "integrity": "sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.57.1.tgz", - "integrity": "sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.57.1.tgz", - "integrity": "sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.57.1.tgz", - "integrity": "sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.57.1.tgz", - "integrity": "sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.57.1.tgz", - "integrity": "sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.57.1.tgz", - "integrity": "sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.57.1.tgz", - "integrity": "sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.57.1.tgz", - "integrity": "sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.57.1.tgz", - "integrity": "sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.57.1.tgz", - "integrity": "sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.57.1.tgz", - "integrity": "sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.57.1.tgz", - "integrity": "sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.57.1.tgz", - "integrity": "sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.57.1.tgz", - "integrity": "sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.57.1.tgz", - "integrity": "sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.57.1.tgz", - "integrity": "sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.57.1.tgz", - "integrity": "sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.57.1.tgz", - "integrity": "sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.57.1.tgz", - "integrity": "sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.57.1.tgz", - "integrity": "sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.57.1.tgz", - "integrity": "sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.57.1.tgz", - "integrity": "sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@sinclair/typebox": { - "version": "0.27.10", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz", - "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "20.19.32", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.32.tgz", - "integrity": "sha512-Ez8QE4DMfhjjTsES9K2dwfV258qBui7qxUsoaixZDiTzbde4U12e1pXGNu/ECsUIOi5/zoCxAQxIhQnaUQ2VvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/@vitest/expect": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.1.tgz", - "integrity": "sha512-jXL+9+ZNIJKruofqXuuTClf44eSpcHlgj3CiuNihUF3Ioujtmc0zIa3UJOW5RjDK1YLBJZnWBlPuqhYycLioog==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/spy": "1.6.1", - "@vitest/utils": "1.6.1", - "chai": "^4.3.10" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.6.1.tgz", - "integrity": "sha512-3nSnYXkVkf3mXFfE7vVyPmi3Sazhb/2cfZGGs0JRzFsPFvAMBEcrweV1V1GsrstdXeKCTXlJbvnQwGWgEIHmOA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/utils": "1.6.1", - "p-limit": "^5.0.0", - "pathe": "^1.1.1" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/snapshot": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.6.1.tgz", - "integrity": "sha512-WvidQuWAzU2p95u8GAKlRMqMyN1yOJkGHnx3M1PL9Raf7AQ1kwLKg04ADlCa3+OXUZE7BceOhVZiuWAbzCKcUQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "magic-string": "^0.30.5", - "pathe": "^1.1.1", - "pretty-format": "^29.7.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/spy": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.6.1.tgz", - "integrity": "sha512-MGcMmpGkZebsMZhbQKkAf9CX5zGvjkBTqf8Zx3ApYWXr3wG+QvEu2eXWfnIIWYSJExIp4V9FCKDEeygzkYrXMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "tinyspy": "^2.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.6.1.tgz", - "integrity": "sha512-jOrrUvXM4Av9ZWiG1EajNto0u96kWAhJ1LmPmJhXXQx/32MecEKd10pOLYgS2BQx1TgkGhloPU1ArDW2vvaY6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "diff-sequences": "^29.6.3", - "estree-walker": "^3.0.3", - "loupe": "^2.3.7", - "pretty-format": "^29.7.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/accepts": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", - "license": "MIT", - "dependencies": { - "mime-types": "^3.0.0", - "negotiator": "^1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", - "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", - "license": "MIT", - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/body-parser": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", - "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", - "license": "MIT", - "dependencies": { - "bytes": "^3.1.2", - "content-type": "^1.0.5", - "debug": "^4.4.3", - "http-errors": "^2.0.0", - "iconv-lite": "^0.7.0", - "on-finished": "^2.4.1", - "qs": "^6.14.1", - "raw-body": "^3.0.1", - "type-is": "^2.0.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/cac": { - "version": "6.7.14", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/chai": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", - "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", - "dev": true, - "license": "MIT", - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.3", - "deep-eql": "^4.1.3", - "get-func-name": "^2.0.2", - "loupe": "^2.3.6", - "pathval": "^1.1.1", - "type-detect": "^4.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/check-error": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", - "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-func-name": "^2.0.2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/confbox": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", - "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", - "dev": true, - "license": "MIT" - }, - "node_modules/content-disposition": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", - "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", - "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", - "license": "MIT", - "engines": { - "node": ">=6.6.0" - } - }, - "node_modules/cors": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", - "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", - "license": "MIT", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deep-eql": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", - "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "license": "MIT" - }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "license": "MIT" - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eventsource": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz", - "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==", - "license": "MIT", - "dependencies": { - "eventsource-parser": "^3.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/eventsource-parser": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz", - "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==", - "license": "MIT", - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/express": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", - "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", - "license": "MIT", - "dependencies": { - "accepts": "^2.0.0", - "body-parser": "^2.2.1", - "content-disposition": "^1.0.0", - "content-type": "^1.0.5", - "cookie": "^0.7.1", - "cookie-signature": "^1.2.1", - "debug": "^4.4.0", - "depd": "^2.0.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "finalhandler": "^2.1.0", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "merge-descriptors": "^2.0.0", - "mime-types": "^3.0.0", - "on-finished": "^2.4.1", - "once": "^1.4.0", - "parseurl": "^1.3.3", - "proxy-addr": "^2.0.7", - "qs": "^6.14.0", - "range-parser": "^1.2.1", - "router": "^2.2.0", - "send": "^1.1.0", - "serve-static": "^2.2.0", - "statuses": "^2.0.1", - "type-is": "^2.0.1", - "vary": "^1.1.2" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/express-rate-limit": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.2.1.tgz", - "integrity": "sha512-PCZEIEIxqwhzw4KF0n7QF4QqruVTcF73O5kFKUnGOyjbCCgizBBiFaYpd/fnBLUMPw/BWw9OsiN7GgrNYr7j6g==", - "license": "MIT", - "dependencies": { - "ip-address": "10.0.1" - }, - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://github.com/sponsors/express-rate-limit" - }, - "peerDependencies": { - "express": ">= 4.11" - } - }, - "node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "license": "MIT", - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "license": "MIT" - }, - "node_modules/fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/finalhandler": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", - "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "on-finished": "^2.4.1", - "parseurl": "^1.3.3", - "statuses": "^2.0.1" - }, - "engines": { - "node": ">= 18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", - "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gray-matter": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", - "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", - "license": "MIT", - "dependencies": { - "js-yaml": "^3.13.1", - "kind-of": "^6.0.2", - "section-matter": "^1.0.0", - "strip-bom-string": "^1.0.0" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/hono": { - "version": "4.11.7", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.7.tgz", - "integrity": "sha512-l7qMiNee7t82bH3SeyUCt9UF15EVmaBvsppY2zQtrbIhl/yzBTny+YUxsVjSjQ6gaqaeVtZmGocom8TzBlA4Yw==", - "license": "MIT", - "engines": { - "node": ">=16.9.0" - } - }, - "node_modules/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", - "license": "MIT", - "dependencies": { - "depd": "~2.0.0", - "inherits": "~2.0.4", - "setprototypeof": "~1.2.0", - "statuses": "~2.0.2", - "toidentifier": "~1.0.1" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=16.17.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", - "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/ip-address": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz", - "integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==", - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-promise": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", - "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", - "license": "MIT" - }, - "node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "license": "ISC" - }, - "node_modules/jose": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/jose/-/jose-6.1.3.tgz", - "integrity": "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/panva" - } - }, - "node_modules/js-tokens": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", - "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/js-yaml": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "license": "MIT" - }, - "node_modules/json-schema-typed": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-8.0.2.tgz", - "integrity": "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==", - "license": "BSD-2-Clause" - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/local-pkg": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.1.tgz", - "integrity": "sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "mlly": "^1.7.3", - "pkg-types": "^1.2.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/loupe": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", - "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-func-name": "^2.0.1" - } - }, - "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/media-typer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", - "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/merge-descriptors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", - "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true, - "license": "MIT" - }, - "node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", - "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", - "license": "MIT", - "dependencies": { - "mime-db": "^1.54.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mlly": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz", - "integrity": "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^8.15.0", - "pathe": "^2.0.3", - "pkg-types": "^1.3.1", - "ufo": "^1.6.1" - } - }, - "node_modules/mlly/node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true, - "license": "MIT" - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/negotiator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-limit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", - "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^1.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-to-regexp": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", - "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/pathe": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", - "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/pkce-challenge": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.1.tgz", - "integrity": "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==", - "license": "MIT", - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/pkg-types": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", - "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "confbox": "^0.1.8", - "mlly": "^1.7.4", - "pathe": "^2.0.1" - } - }, - "node_modules/pkg-types/node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true, - "license": "MIT" - }, - "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "license": "MIT", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/qs": { - "version": "6.14.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", - "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", - "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.7.0", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true, - "license": "MIT" - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/rollup": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz", - "integrity": "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.57.1", - "@rollup/rollup-android-arm64": "4.57.1", - "@rollup/rollup-darwin-arm64": "4.57.1", - "@rollup/rollup-darwin-x64": "4.57.1", - "@rollup/rollup-freebsd-arm64": "4.57.1", - "@rollup/rollup-freebsd-x64": "4.57.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.57.1", - "@rollup/rollup-linux-arm-musleabihf": "4.57.1", - "@rollup/rollup-linux-arm64-gnu": "4.57.1", - "@rollup/rollup-linux-arm64-musl": "4.57.1", - "@rollup/rollup-linux-loong64-gnu": "4.57.1", - "@rollup/rollup-linux-loong64-musl": "4.57.1", - "@rollup/rollup-linux-ppc64-gnu": "4.57.1", - "@rollup/rollup-linux-ppc64-musl": "4.57.1", - "@rollup/rollup-linux-riscv64-gnu": "4.57.1", - "@rollup/rollup-linux-riscv64-musl": "4.57.1", - "@rollup/rollup-linux-s390x-gnu": "4.57.1", - "@rollup/rollup-linux-x64-gnu": "4.57.1", - "@rollup/rollup-linux-x64-musl": "4.57.1", - "@rollup/rollup-openbsd-x64": "4.57.1", - "@rollup/rollup-openharmony-arm64": "4.57.1", - "@rollup/rollup-win32-arm64-msvc": "4.57.1", - "@rollup/rollup-win32-ia32-msvc": "4.57.1", - "@rollup/rollup-win32-x64-gnu": "4.57.1", - "@rollup/rollup-win32-x64-msvc": "4.57.1", - "fsevents": "~2.3.2" - } - }, - "node_modules/router": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", - "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "depd": "^2.0.0", - "is-promise": "^4.0.0", - "parseurl": "^1.3.3", - "path-to-regexp": "^8.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "license": "MIT" - }, - "node_modules/section-matter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", - "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", - "license": "MIT", - "dependencies": { - "extend-shallow": "^2.0.1", - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/send": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", - "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", - "license": "MIT", - "dependencies": { - "debug": "^4.4.3", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "fresh": "^2.0.0", - "http-errors": "^2.0.1", - "mime-types": "^3.0.2", - "ms": "^2.1.3", - "on-finished": "^2.4.1", - "range-parser": "^1.2.1", - "statuses": "^2.0.2" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/serve-static": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", - "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", - "license": "MIT", - "dependencies": { - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "parseurl": "^1.3.3", - "send": "^1.2.0" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "license": "ISC" - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/siginfo": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", - "dev": true, - "license": "ISC" - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "license": "BSD-3-Clause" - }, - "node_modules/stackback": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", - "dev": true, - "license": "MIT" - }, - "node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/std-env": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", - "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", - "dev": true, - "license": "MIT" - }, - "node_modules/strip-bom-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", - "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-literal": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.1.tgz", - "integrity": "sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "js-tokens": "^9.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/tinybench": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinypool": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.4.tgz", - "integrity": "sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tinyspy": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", - "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/type-detect": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", - "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/type-is": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", - "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", - "license": "MIT", - "dependencies": { - "content-type": "^1.0.5", - "media-typer": "^1.1.0", - "mime-types": "^3.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/ufo": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.3.tgz", - "integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/vite": { - "version": "5.4.21", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", - "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "node_modules/vite-node": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.6.1.tgz", - "integrity": "sha512-YAXkfvGtuTzwWbDSACdJSg4A4DZiAqckWe90Zapc/sEX3XvHcw1NdurM/6od8J207tSDqNbSsgdCacBgvJKFuA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cac": "^6.7.14", - "debug": "^4.3.4", - "pathe": "^1.1.1", - "picocolors": "^1.0.0", - "vite": "^5.0.0" - }, - "bin": { - "vite-node": "vite-node.mjs" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/vitest": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.6.1.tgz", - "integrity": "sha512-Ljb1cnSJSivGN0LqXd/zmDbWEM0RNNg2t1QW/XUhYl/qPqyu7CsqeWtqQXHVaJsecLPuDoak2oJcZN2QoRIOag==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/expect": "1.6.1", - "@vitest/runner": "1.6.1", - "@vitest/snapshot": "1.6.1", - "@vitest/spy": "1.6.1", - "@vitest/utils": "1.6.1", - "acorn-walk": "^8.3.2", - "chai": "^4.3.10", - "debug": "^4.3.4", - "execa": "^8.0.1", - "local-pkg": "^0.5.0", - "magic-string": "^0.30.5", - "pathe": "^1.1.1", - "picocolors": "^1.0.0", - "std-env": "^3.5.0", - "strip-literal": "^2.0.0", - "tinybench": "^2.5.1", - "tinypool": "^0.8.3", - "vite": "^5.0.0", - "vite-node": "1.6.1", - "why-is-node-running": "^2.2.2" - }, - "bin": { - "vitest": "vitest.mjs" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@edge-runtime/vm": "*", - "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "1.6.1", - "@vitest/ui": "1.6.1", - "happy-dom": "*", - "jsdom": "*" - }, - "peerDependenciesMeta": { - "@edge-runtime/vm": { - "optional": true - }, - "@types/node": { - "optional": true - }, - "@vitest/browser": { - "optional": true - }, - "@vitest/ui": { - "optional": true - }, - "happy-dom": { - "optional": true - }, - "jsdom": { - "optional": true - } - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/why-is-node-running": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", - "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", - "dev": true, - "license": "MIT", - "dependencies": { - "siginfo": "^2.0.0", - "stackback": "0.0.2" - }, - "bin": { - "why-is-node-running": "cli.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "license": "ISC" - }, - "node_modules/yaml": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", - "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - }, - "funding": { - "url": "https://github.com/sponsors/eemeli" - } - }, - "node_modules/yocto-queue": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", - "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zod": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", - "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/zod-to-json-schema": { - "version": "3.25.1", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz", - "integrity": "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==", - "license": "ISC", - "peerDependencies": { - "zod": "^3.25 || ^4" - } - } - } -} diff --git a/gsd-memory/package.json b/gsd-memory/package.json deleted file mode 100644 index 4a956ed79..000000000 --- a/gsd-memory/package.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "gsd-memory", - "version": "1.0.0", - "description": "GSD Memory - Cross-project knowledge system MCP server", - "type": "module", - "main": "dist/index.js", - "bin": { - "gsd-memory": "./dist/index.js" - }, - "scripts": { - "build": "tsc", - "dev": "tsc --watch", - "test": "vitest run", - "test:watch": "vitest", - "test:integration": "vitest run --config vitest.integration.config.ts", - "start": "node dist/index.js" - }, - "dependencies": { - "@modelcontextprotocol/sdk": "^1.0.0", - "gray-matter": "^4.0.3", - "yaml": "^2.3.0" - }, - "devDependencies": { - "@types/node": "^20.0.0", - "typescript": "^5.3.0", - "vitest": "^1.0.0" - }, - "engines": { - "node": ">=18.0.0" - } -} diff --git a/gsd-memory/src/extractors/frontmatter.ts b/gsd-memory/src/extractors/frontmatter.ts deleted file mode 100644 index 48b05c5f3..000000000 --- a/gsd-memory/src/extractors/frontmatter.ts +++ /dev/null @@ -1,36 +0,0 @@ -import matter from 'gray-matter'; - -/** - * Extract YAML frontmatter from markdown content - * Returns empty object if no frontmatter or invalid YAML - */ -export function extractFrontmatter(markdown: string): Record { - try { - const { data } = matter(markdown); - return data || {}; - } catch { - // Return empty object on parse errors - return {}; - } -} - -/** - * Extract frontmatter and content separately - */ -export function parseFrontmatter(markdown: string): { - frontmatter: Record; - content: string; -} { - try { - const { data, content } = matter(markdown); - return { - frontmatter: data || {}, - content: content.trim() - }; - } catch { - return { - frontmatter: {}, - content: markdown.trim() - }; - } -} diff --git a/gsd-memory/src/extractors/index.ts b/gsd-memory/src/extractors/index.ts deleted file mode 100644 index fbd1a8788..000000000 --- a/gsd-memory/src/extractors/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { extractFrontmatter, parseFrontmatter } from './frontmatter.js'; -export { extractSummary, type SummaryData, type TechStackEntry, type Decision as SummaryDecision } from './summary.js'; -export { extractResearch, type ResearchData, type Pitfall, type DontHandRoll } from './research.js'; -export { extractProject, type ProjectData, type Decision as ProjectDecision, type Constraint } from './project.js'; diff --git a/gsd-memory/src/extractors/project.ts b/gsd-memory/src/extractors/project.ts deleted file mode 100644 index a61c8577f..000000000 --- a/gsd-memory/src/extractors/project.ts +++ /dev/null @@ -1,193 +0,0 @@ -export interface OutOfScopeItem { - item: string; - reason: string; -} - -export interface Constraint { - type: string; - value: string; - why?: string; -} - -export interface Decision { - decision: string; - rationale: string; - outcome: string; -} - -export interface Requirements { - validated: string[]; - active: string[]; - outOfScope: OutOfScopeItem[]; -} - -export interface ProjectData { - name: string; - description: string; - coreValue: string; - requirements: Requirements; - context: string; - constraints: Constraint[]; - decisions: Decision[]; -} - -/** - * Extract structured data from a PROJECT.md file - */ -export function extractProject(markdown: string): ProjectData { - return { - name: extractName(markdown), - description: extractSection(markdown, 'What This Is'), - coreValue: extractSection(markdown, 'Core Value'), - requirements: extractRequirements(markdown), - context: extractSection(markdown, 'Context'), - constraints: extractConstraints(markdown), - decisions: extractDecisions(markdown) - }; -} - -function extractName(content: string): string { - // First line should be # ProjectName - const match = content.match(/^#\s+(.+)/m); - return match ? match[1].trim() : ''; -} - -function extractSection(content: string, sectionName: string): string { - // Find the section and extract content until next ## heading - const regex = new RegExp(`##\\s+${sectionName}\\n\\n([\\s\\S]*?)(?=\\n##|$)`, 'i'); - const match = content.match(regex); - return match ? match[1].trim() : ''; -} - -function extractRequirements(content: string): Requirements { - const requirementsSection = content.match(/##\s+Requirements\n([\s\S]*?)(?=\n##[^#]|$)/i); - if (!requirementsSection) { - return { validated: [], active: [], outOfScope: [] }; - } - - const section = requirementsSection[1]; - - return { - validated: extractValidatedRequirements(section), - active: extractActiveRequirements(section), - outOfScope: extractOutOfScope(section) - }; -} - -function extractValidatedRequirements(section: string): string[] { - const requirements: string[] = []; - - // Look for ### Validated subsection - const validatedSection = section.match(/###\s+Validated\n([\s\S]*?)(?=###|$)/i); - if (!validatedSection) return requirements; - - // Extract checkmark items: - ✓ requirement — version - const matches = validatedSection[1].match(/^-\s+✓\s+(.+)/gm); - if (matches) { - for (const match of matches) { - const content = match.replace(/^-\s+✓\s+/, '').trim(); - requirements.push(content); - } - } - - return requirements; -} - -function extractActiveRequirements(section: string): string[] { - const requirements: string[] = []; - - // Look for ### Active subsection - const activeSection = section.match(/###\s+Active\n([\s\S]*?)(?=###|$)/i); - if (!activeSection) return requirements; - - // Extract checkbox items: - [ ] requirement - const matches = activeSection[1].match(/^-\s+\[\s*\]\s+(.+)/gm); - if (matches) { - for (const match of matches) { - const content = match.replace(/^-\s+\[\s*\]\s+/, '').trim(); - requirements.push(content); - } - } - - return requirements; -} - -function extractOutOfScope(section: string): OutOfScopeItem[] { - const items: OutOfScopeItem[] = []; - - // Look for ### Out of Scope subsection - const outOfScopeSection = section.match(/###\s+Out of Scope\n([\s\S]*?)(?=###|$)/i); - if (!outOfScopeSection) return items; - - // Extract items: - Item — reason - const matches = outOfScopeSection[1].match(/^-\s+(.+)/gm); - if (matches) { - for (const match of matches) { - const content = match.replace(/^-\s+/, '').trim(); - // Split by em-dash or double hyphen - const parts = content.split(/\s+—\s+|\s+--\s+/); - items.push({ - item: parts[0].trim(), - reason: parts[1]?.trim() || '' - }); - } - } - - return items; -} - -function extractConstraints(content: string): Constraint[] { - const constraints: Constraint[] = []; - - const constraintsSection = content.match(/##\s+Constraints\n([\s\S]*?)(?=\n##|$)/i); - if (!constraintsSection) return constraints; - - // Extract items: - **Type**: Value — Why - const matches = constraintsSection[1].match(/^-\s+\*\*([^*]+)\*\*:\s*(.+)/gm); - if (matches) { - for (const match of matches) { - const typeMatch = match.match(/\*\*([^*]+)\*\*/); - const valueMatch = match.match(/\*\*[^*]+\*\*:\s*(.+)/); - - if (typeMatch && valueMatch) { - const valueParts = valueMatch[1].split(/\s+—\s+|\s+--\s+/); - constraints.push({ - type: typeMatch[1].trim(), - value: valueParts[0].trim(), - why: valueParts[1]?.trim() - }); - } - } - } - - return constraints; -} - -function extractDecisions(content: string): Decision[] { - const decisions: Decision[] = []; - - const decisionsSection = content.match(/##\s+Key Decisions\n([\s\S]*?)(?=\n##[^#]|\n---|$)/i); - if (!decisionsSection) return decisions; - - // Parse markdown table rows - match rows with 3+ cells - const lines = decisionsSection[1].split('\n'); - - for (const line of lines) { - // Must be a table row (starts and ends with |) - if (!line.trim().startsWith('|')) continue; - - // Skip header row (contains 'Decision') and separator row (contains ---) - if (line.includes('Decision') || line.includes('---')) continue; - - const cells = line.split('|').filter(c => c.trim()); - if (cells.length >= 3) { - decisions.push({ - decision: cells[0].trim(), - rationale: cells[1].trim(), - outcome: cells[2].trim() - }); - } - } - - return decisions; -} diff --git a/gsd-memory/src/extractors/research.ts b/gsd-memory/src/extractors/research.ts deleted file mode 100644 index 7419d7074..000000000 --- a/gsd-memory/src/extractors/research.ts +++ /dev/null @@ -1,250 +0,0 @@ -import { parseFrontmatter } from './frontmatter.js'; - -export interface StackEntry { - library: string; - version?: string; - purpose: string; - whyStandard?: string; -} - -export interface Pitfall { - name: string; - description: string; - cause?: string; - prevention: string; - warningSigns?: string; -} - -export interface DontHandRoll { - problem: string; - dontBuild: string; - useInstead: string; - why: string; -} - -export interface UserConstraints { - locked: string[]; - discretion: string[]; - deferred: string[]; -} - -export interface ResearchData { - // Metadata - domain: string; - confidence: string; - researched: string; - - // Extracted sections - standardStack: StackEntry[]; - pitfalls: Pitfall[]; - dontHandRoll: DontHandRoll[]; - antiPatterns: string[]; - userConstraints: UserConstraints; - primaryRecommendation: string; -} - -/** - * Extract structured data from a RESEARCH.md file - */ -export function extractResearch(markdown: string): ResearchData { - const { frontmatter, content } = parseFrontmatter(markdown); - - return { - // Metadata from frontmatter - domain: (frontmatter.domain as string) || '', - confidence: (frontmatter.confidence as string) || '', - researched: formatDate(frontmatter.researched), - - // Extracted from content - standardStack: extractStandardStack(content), - pitfalls: extractPitfalls(content), - dontHandRoll: extractDontHandRoll(content), - antiPatterns: extractAntiPatterns(content), - userConstraints: extractUserConstraints(content), - primaryRecommendation: extractPrimaryRecommendation(content) - }; -} - -function formatDate(date: unknown): string { - if (!date) return ''; - if (date instanceof Date) { - return date.toISOString().split('T')[0]; - } - return String(date); -} - -function extractStandardStack(content: string): StackEntry[] { - const entries: StackEntry[] = []; - - // Look for standard_stack section and parse markdown tables - const stackSection = extractSection(content, 'standard_stack'); - if (!stackSection) return entries; - - // Parse Core and Supporting tables - const tableRows = stackSection.match(/\|[^|]+\|[^|]+\|[^|]+\|[^|]*\|/g); - if (!tableRows) return entries; - - for (const row of tableRows) { - // Skip header and separator rows - if (row.includes('Library') || row.includes('---')) continue; - - const cells = row.split('|').filter(c => c.trim()); - if (cells.length >= 3) { - entries.push({ - library: cells[0].trim(), - version: cells[1]?.trim(), - purpose: cells[2]?.trim(), - whyStandard: cells[3]?.trim() - }); - } - } - - return entries; -} - -function extractPitfalls(content: string): Pitfall[] { - const pitfalls: Pitfall[] = []; - - const pitfallSection = extractSection(content, 'common_pitfalls'); - if (!pitfallSection) return pitfalls; - - // Parse individual pitfall blocks (### Pitfall N: Name) - const pitfallBlocks = pitfallSection.split(/###\s+Pitfall\s+\d+:\s+/); - - for (const block of pitfallBlocks) { - if (!block.trim()) continue; - - const lines = block.split('\n'); - const name = lines[0]?.trim(); - if (!name) continue; - - const description = extractField(block, 'What goes wrong'); - const cause = extractField(block, 'Why it happens'); - const prevention = extractField(block, 'How to avoid'); - const warningSigns = extractField(block, 'Warning signs'); - - if (description || prevention) { - pitfalls.push({ - name, - description: description || '', - cause, - prevention: prevention || '', - warningSigns - }); - } - } - - return pitfalls; -} - -function extractDontHandRoll(content: string): DontHandRoll[] { - const items: DontHandRoll[] = []; - - const section = extractSection(content, 'dont_hand_roll'); - if (!section) return items; - - // Parse table rows - const tableRows = section.match(/\|[^|]+\|[^|]+\|[^|]+\|[^|]+\|/g); - if (!tableRows) return items; - - for (const row of tableRows) { - if (row.includes('Problem') || row.includes('---')) continue; - - const cells = row.split('|').filter(c => c.trim()); - if (cells.length >= 4) { - items.push({ - problem: cells[0].trim(), - dontBuild: cells[1].trim(), - useInstead: cells[2].trim(), - why: cells[3].trim() - }); - } - } - - return items; -} - -function extractAntiPatterns(content: string): string[] { - const patterns: string[] = []; - - const archSection = extractSection(content, 'architecture_patterns'); - if (!archSection) return patterns; - - // Look for "Anti-Patterns to Avoid" subsection - const antiMatch = archSection.match(/###\s+Anti-Patterns to Avoid\n([\s\S]*?)(?=###|$)/); - if (!antiMatch) return patterns; - - // Extract bullet points - const bullets = antiMatch[1].match(/^-\s+\*\*([^*]+)\*\*/gm); - if (bullets) { - for (const bullet of bullets) { - const match = bullet.match(/\*\*([^*]+)\*\*/); - if (match) patterns.push(match[1].trim()); - } - } - - return patterns; -} - -function extractUserConstraints(content: string): UserConstraints { - const constraints: UserConstraints = { - locked: [], - discretion: [], - deferred: [] - }; - - const section = extractSection(content, 'user_constraints'); - if (!section) return constraints; - - // Extract locked decisions - const lockedMatch = section.match(/###\s+Locked Decisions\n([\s\S]*?)(?=###|$)/); - if (lockedMatch) { - constraints.locked = extractBulletPoints(lockedMatch[1]); - } - - // Extract Claude's discretion - const discretionMatch = section.match(/###\s+Claude's Discretion\n([\s\S]*?)(?=###|$)/); - if (discretionMatch) { - constraints.discretion = extractBulletPoints(discretionMatch[1]); - } - - // Extract deferred items - const deferredMatch = section.match(/###\s+Deferred Ideas[^#]*\n([\s\S]*?)(?=<\/|$)/); - if (deferredMatch) { - constraints.deferred = extractBulletPoints(deferredMatch[1]); - } - - return constraints; -} - -function extractPrimaryRecommendation(content: string): string { - // Look for "Primary recommendation:" in summary section - const match = content.match(/\*\*Primary recommendation:\*\*\s*([^\n]+)/); - return match ? match[1].trim() : ''; -} - -// Helper functions - -function extractSection(content: string, sectionTag: string): string | null { - const regex = new RegExp(`<${sectionTag}>([\\s\\S]*?)<\\/${sectionTag}>`, 'i'); - const match = content.match(regex); - return match ? match[1] : null; -} - -function extractField(block: string, fieldName: string): string | undefined { - const regex = new RegExp(`\\*\\*${fieldName}:\\*\\*\\s*([^\\n]+)`, 'i'); - const match = block.match(regex); - return match ? match[1].trim() : undefined; -} - -function extractBulletPoints(text: string): string[] { - const points: string[] = []; - const matches = text.match(/^-\s+(.+)/gm); - if (matches) { - for (const match of matches) { - const content = match.replace(/^-\s+/, '').trim(); - if (content) points.push(content); - } - } - return points; -} diff --git a/gsd-memory/src/extractors/summary.ts b/gsd-memory/src/extractors/summary.ts deleted file mode 100644 index 00aa0a575..000000000 --- a/gsd-memory/src/extractors/summary.ts +++ /dev/null @@ -1,155 +0,0 @@ -import { parseFrontmatter } from './frontmatter.js'; - -export interface TechStackEntry { - library: string; - version: string; - purpose?: string; -} - -export interface Dependency { - phase: string; - provides: string; -} - -export interface KeyFiles { - created: string[]; - modified: string[]; -} - -export interface Decision { - decision: string; - source?: string; -} - -export interface SummaryData { - // Identifiers - phase: string; - plan: number | string; - subsystem: string; - tags: string[]; - - // Dependency graph - requires: Dependency[]; - provides: string[]; - affects: string[]; - - // Tech tracking - techStack: TechStackEntry[]; - patterns: string[]; - - // Files - keyFiles: KeyFiles; - - // Decisions - decisions: Decision[]; - - // Metadata - duration: string; - completed: string; - - // Content - oneLiner: string; -} - -/** - * Extract structured data from a SUMMARY.md file - */ -export function extractSummary(markdown: string): SummaryData { - const { frontmatter, content } = parseFrontmatter(markdown); - - return { - // Identifiers - phase: (frontmatter.phase as string) || '', - plan: (frontmatter.plan as number | string) || '', - subsystem: (frontmatter.subsystem as string) || '', - tags: (frontmatter.tags as string[]) || [], - - // Dependency graph - requires: extractRequires(frontmatter.requires), - provides: (frontmatter.provides as string[]) || [], - affects: (frontmatter.affects as string[]) || [], - - // Tech tracking - techStack: extractTechStack(frontmatter['tech-stack']), - patterns: (frontmatter['patterns-established'] as string[]) || [], - - // Files - keyFiles: extractKeyFiles(frontmatter['key-files']), - - // Decisions - decisions: extractDecisions(frontmatter['key-decisions']), - - // Metadata - duration: (frontmatter.duration as string) || '', - completed: formatCompleted(frontmatter.completed), - - // Content - oneLiner: extractOneLiner(content) - }; -} - -function extractRequires(requires: unknown): Dependency[] { - if (!Array.isArray(requires)) return []; - - return requires.map((req) => ({ - phase: (req as Record).phase as string || '', - provides: (req as Record).provides as string || '' - })); -} - -function extractTechStack(techStack: unknown): TechStackEntry[] { - if (!techStack || typeof techStack !== 'object') return []; - - const ts = techStack as Record; - const added = ts.added; - - if (!Array.isArray(added)) return []; - - return added.map((entry) => { - // Handle both object format { library: version } and string format - if (typeof entry === 'object' && entry !== null) { - const [library, version] = Object.entries(entry)[0] || ['', '']; - return { library, version: String(version) }; - } - return { library: String(entry), version: '' }; - }); -} - -function extractKeyFiles(keyFiles: unknown): KeyFiles { - if (!keyFiles || typeof keyFiles !== 'object') { - return { created: [], modified: [] }; - } - - const kf = keyFiles as Record; - return { - created: (kf.created as string[]) || [], - modified: (kf.modified as string[]) || [] - }; -} - -function extractDecisions(decisions: unknown): Decision[] { - if (!Array.isArray(decisions)) return []; - - return decisions.map((d) => ({ - decision: String(d), - source: 'frontmatter' - })); -} - -function formatCompleted(completed: unknown): string { - if (!completed) return ''; - - // If it's a Date object (YAML parsed it), format as ISO date - if (completed instanceof Date) { - return completed.toISOString().split('T')[0]; - } - - return String(completed); -} - -function extractOneLiner(content: string): string { - // The one-liner is the bold text after the title - // Pattern: # Title\n\n**one-liner** - const match = content.match(/^#[^\n]+\n\n\*\*([^*]+)\*\*/m); - return match ? match[1].trim() : ''; -} diff --git a/gsd-memory/src/index.ts b/gsd-memory/src/index.ts deleted file mode 100644 index 7c58e607a..000000000 --- a/gsd-memory/src/index.ts +++ /dev/null @@ -1,321 +0,0 @@ -#!/usr/bin/env node - -import { Server } from '@modelcontextprotocol/sdk/server/index.js'; -import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; -import { - CallToolRequestSchema, - ListToolsRequestSchema, - type Tool -} from '@modelcontextprotocol/sdk/types.js'; - -import { search } from './tools/search.js'; -import { findDecisions } from './tools/decisions.js'; -import { findPatterns } from './tools/patterns.js'; -import { findPitfalls } from './tools/pitfalls.js'; -import { findStack } from './tools/stack.js'; -import { register, status as registerStatus, unregister } from './tools/register.js'; -import { index, indexAll } from './tools/index-tool.js'; -import { getStatus } from './tools/status.js'; - -// Define available tools -const tools: Tool[] = [ - { - name: 'gsd_memory_search', - description: 'Search across all registered GSD projects for content matching a query. Returns enriched results with project, phase, and document type context.', - inputSchema: { - type: 'object', - properties: { - query: { - type: 'string', - description: 'The search query' - }, - project: { - type: 'string', - description: 'Optional: limit search to a specific project' - }, - limit: { - type: 'number', - description: 'Maximum number of results (default: 20)' - } - }, - required: ['query'] - } - }, - { - name: 'gsd_memory_decisions', - description: 'Find decisions made across GSD projects. Searches KEY-DECISIONS from SUMMARY.md frontmatter and Key Decisions tables from PROJECT.md.', - inputSchema: { - type: 'object', - properties: { - query: { - type: 'string', - description: 'Optional: filter decisions by keyword' - }, - project: { - type: 'string', - description: 'Optional: limit to a specific project' - }, - tags: { - type: 'array', - items: { type: 'string' }, - description: 'Optional: filter by tags' - }, - limit: { - type: 'number', - description: 'Maximum number of results (default: 50)' - } - } - } - }, - { - name: 'gsd_memory_patterns', - description: 'Find patterns established across GSD projects. Extracts PATTERNS-ESTABLISHED from SUMMARY.md frontmatter.', - inputSchema: { - type: 'object', - properties: { - query: { - type: 'string', - description: 'Optional: filter patterns by keyword' - }, - project: { - type: 'string', - description: 'Optional: limit to a specific project' - }, - tags: { - type: 'array', - items: { type: 'string' }, - description: 'Optional: filter by tags' - }, - limit: { - type: 'number', - description: 'Maximum number of results (default: 50)' - } - } - } - }, - { - name: 'gsd_memory_pitfalls', - description: 'Find documented pitfalls from RESEARCH.md files. Includes what went wrong, causes, and prevention strategies.', - inputSchema: { - type: 'object', - properties: { - query: { - type: 'string', - description: 'Optional: filter pitfalls by keyword' - }, - project: { - type: 'string', - description: 'Optional: limit to a specific project' - }, - domain: { - type: 'string', - description: 'Optional: filter by technology domain' - }, - limit: { - type: 'number', - description: 'Maximum number of results (default: 50)' - } - } - } - }, - { - name: 'gsd_memory_stack', - description: 'Find tech stack entries across GSD projects. Extracts from SUMMARY.md (tech-stack.added) and RESEARCH.md (standard stack tables).', - inputSchema: { - type: 'object', - properties: { - query: { - type: 'string', - description: 'Optional: filter by library name or purpose' - }, - project: { - type: 'string', - description: 'Optional: limit to a specific project' - }, - limit: { - type: 'number', - description: 'Maximum number of results (default: 100)' - } - } - } - }, - { - name: 'gsd_memory_register', - description: 'Register a project with GSD memory. Creates a QMD collection if QMD is available.', - inputSchema: { - type: 'object', - properties: { - path: { - type: 'string', - description: 'Path to the project root (must contain .planning directory)' - }, - name: { - type: 'string', - description: 'Optional: project name (defaults to directory name)' - } - }, - required: ['path'] - } - }, - { - name: 'gsd_memory_index', - description: 'Trigger indexing/update for a project. Updates QMD collection if available, otherwise marks project as indexed for grep fallback.', - inputSchema: { - type: 'object', - properties: { - project: { - type: 'string', - description: 'Project name to index' - }, - path: { - type: 'string', - description: 'Alternative: project path to index' - } - } - } - }, - { - name: 'gsd_memory_status', - description: 'Show status of GSD memory system: QMD availability, registered projects, document counts.', - inputSchema: { - type: 'object', - properties: {} - } - } -]; - -// Create server instance -const server = new Server( - { - name: 'gsd-memory', - version: '1.0.0' - }, - { - capabilities: { - tools: {} - } - } -); - -// Handle list tools request -server.setRequestHandler(ListToolsRequestSchema, async () => ({ - tools -})); - -// Handle tool calls -server.setRequestHandler(CallToolRequestSchema, async (request) => { - const { name, arguments: args } = request.params; - - try { - let result: unknown; - - switch (name) { - case 'gsd_memory_search': - result = await search({ - query: args?.query as string, - project: args?.project as string | undefined, - limit: args?.limit as number | undefined - }); - break; - - case 'gsd_memory_decisions': - result = await findDecisions({ - query: args?.query as string | undefined, - project: args?.project as string | undefined, - tags: args?.tags as string[] | undefined, - limit: args?.limit as number | undefined - }); - break; - - case 'gsd_memory_patterns': - result = await findPatterns({ - query: args?.query as string | undefined, - project: args?.project as string | undefined, - tags: args?.tags as string[] | undefined, - limit: args?.limit as number | undefined - }); - break; - - case 'gsd_memory_pitfalls': - result = await findPitfalls({ - query: args?.query as string | undefined, - project: args?.project as string | undefined, - domain: args?.domain as string | undefined, - limit: args?.limit as number | undefined - }); - break; - - case 'gsd_memory_stack': - result = await findStack({ - query: args?.query as string | undefined, - project: args?.project as string | undefined, - limit: args?.limit as number | undefined - }); - break; - - case 'gsd_memory_register': - result = await register({ - path: args?.path as string, - name: args?.name as string | undefined - }); - break; - - case 'gsd_memory_index': - if (args?.project || args?.path) { - result = await index({ - project: args?.project as string | undefined, - path: args?.path as string | undefined - }); - } else { - result = await indexAll(); - } - break; - - case 'gsd_memory_status': - result = await getStatus(); - break; - - default: - return { - content: [ - { - type: 'text', - text: `Unknown tool: ${name}` - } - ], - isError: true - }; - } - - return { - content: [ - { - type: 'text', - text: JSON.stringify(result, null, 2) - } - ] - }; - } catch (error) { - return { - content: [ - { - type: 'text', - text: `Error: ${error instanceof Error ? error.message : String(error)}` - } - ], - isError: true - }; - } -}); - -// Start the server -async function main() { - const transport = new StdioServerTransport(); - await server.connect(transport); - console.error('GSD Memory MCP server started'); -} - -main().catch((error) => { - console.error('Fatal error:', error); - process.exit(1); -}); diff --git a/gsd-memory/src/qmd.ts b/gsd-memory/src/qmd.ts deleted file mode 100644 index cbd6e141f..000000000 --- a/gsd-memory/src/qmd.ts +++ /dev/null @@ -1,255 +0,0 @@ -import { exec } from 'child_process'; -import { promisify } from 'util'; -import { readFileSync, readdirSync, statSync } from 'fs'; -import { join, relative } from 'path'; - -const execAsync = promisify(exec); - -export interface QmdSearchResult { - content: string; - source: string; - relevance: number; - context?: string; -} - -export interface QmdSearchOptions { - query: string; - paths: string[]; - limit?: number; - collection?: string; -} - -export interface QmdCollectionOptions { - name: string; - paths: string[]; - context?: string; -} - -export interface QmdResult { - success: boolean; - reason?: string; - data?: unknown; -} - -export interface QmdStatus { - available: boolean; - collection?: string; - documentCount?: number; - lastIndexed?: string; -} - -/** - * QMD wrapper - provides semantic search when QMD is available, - * falls back to grep-based search otherwise - */ -export const qmd = { - /** - * Check if QMD is installed and available - */ - async isAvailable(): Promise { - try { - await execAsync('which qmd'); - return true; - } catch { - return false; - } - }, - - /** - * Search for content using QMD or grep fallback - */ - async search(options: QmdSearchOptions): Promise { - const available = await this.isAvailable(); - - if (available && options.collection) { - return this.qmdSearch(options); - } - - return this.grepFallback(options); - }, - - /** - * Search using QMD (when available) - */ - async qmdSearch(options: QmdSearchOptions): Promise { - try { - const limit = options.limit || 10; - const { stdout } = await execAsync( - `qmd query "${options.query}" --collection "${options.collection}" --limit ${limit} --json` - ); - - const parsed = JSON.parse(stdout); - return (parsed.results || []).map((r: { content: string; source: string; score: number }) => ({ - content: r.content, - source: r.source, - relevance: r.score || 0.5, - context: 'qmd' - })); - } catch { - // Fall back to grep if QMD search fails - return this.grepFallback(options); - } - }, - - /** - * Grep-based fallback search - */ - async grepFallback(options: QmdSearchOptions): Promise { - const results: QmdSearchResult[] = []; - const limit = options.limit || 20; - - for (const searchPath of options.paths) { - try { - const files = this.findMarkdownFiles(searchPath); - - for (const file of files) { - try { - const content = readFileSync(file, 'utf-8'); - const query = options.query.toLowerCase(); - - // Simple relevance: count matches - const matches = (content.toLowerCase().match(new RegExp(query, 'g')) || []).length; - - if (matches > 0) { - // Extract context around first match - const lowerContent = content.toLowerCase(); - const matchIndex = lowerContent.indexOf(query); - const start = Math.max(0, matchIndex - 100); - const end = Math.min(content.length, matchIndex + query.length + 100); - const snippet = content.slice(start, end); - - results.push({ - content: snippet, - source: file, - relevance: Math.min(1, matches * 0.1), - context: 'grep' - }); - } - } catch { - // Skip files that can't be read - } - } - } catch { - // Skip paths that can't be accessed - } - } - - // Sort by relevance and limit - return results - .sort((a, b) => b.relevance - a.relevance) - .slice(0, limit); - }, - - /** - * Find all markdown files in a directory recursively - */ - findMarkdownFiles(dir: string, files: string[] = []): string[] { - try { - const entries = readdirSync(dir); - - for (const entry of entries) { - const fullPath = join(dir, entry); - try { - const stat = statSync(fullPath); - - if (stat.isDirectory() && !entry.startsWith('.') && entry !== 'node_modules') { - this.findMarkdownFiles(fullPath, files); - } else if (stat.isFile() && entry.endsWith('.md')) { - files.push(fullPath); - } - } catch { - // Skip entries that can't be accessed - } - } - } catch { - // Return empty if directory can't be read - } - - return files; - }, - - /** - * Create a QMD collection for a project - */ - async createCollection(options: QmdCollectionOptions): Promise { - const available = await this.isAvailable(); - - if (!available) { - return { - success: false, - reason: 'qmd_not_available' - }; - } - - try { - const paths = options.paths.join(' '); - const contextArg = options.context ? `--context "${options.context}"` : ''; - - await execAsync( - `qmd add "${options.name}" ${paths} ${contextArg}` - ); - - return { success: true }; - } catch (error) { - return { - success: false, - reason: 'create_failed', - data: error instanceof Error ? error.message : String(error) - }; - } - }, - - /** - * Trigger reindexing of a collection - */ - async index(collectionName: string): Promise { - const available = await this.isAvailable(); - - if (!available) { - return { - success: false, - reason: 'qmd_not_available' - }; - } - - try { - await execAsync(`qmd update "${collectionName}"`); - return { success: true }; - } catch (error) { - return { - success: false, - reason: 'index_failed', - data: error instanceof Error ? error.message : String(error) - }; - } - }, - - /** - * Get status of a collection - */ - async status(collectionName: string): Promise { - const available = await this.isAvailable(); - - if (!available) { - return { available: false }; - } - - try { - const { stdout } = await execAsync(`qmd status "${collectionName}" --json`); - const parsed = JSON.parse(stdout); - - return { - available: true, - collection: collectionName, - documentCount: parsed.documentCount || 0, - lastIndexed: parsed.lastIndexed - }; - } catch { - return { - available: true, - collection: collectionName, - documentCount: 0 - }; - } - } -}; diff --git a/gsd-memory/src/registry.ts b/gsd-memory/src/registry.ts deleted file mode 100644 index f27e292d6..000000000 --- a/gsd-memory/src/registry.ts +++ /dev/null @@ -1,137 +0,0 @@ -import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs'; -import { join, dirname } from 'path'; -import { homedir } from 'os'; - -export interface RegisteredProject { - name: string; - path: string; - qmdCollection?: string; - registeredAt: string; - lastIndexed?: string; -} - -export interface Registry { - version: string; - projects: RegisteredProject[]; -} - -const REGISTRY_DIR = join(homedir(), '.gsd'); -const REGISTRY_PATH = join(REGISTRY_DIR, 'projects.json'); - -/** - * Ensure the registry directory exists - */ -function ensureRegistryDir(): void { - if (!existsSync(REGISTRY_DIR)) { - mkdirSync(REGISTRY_DIR, { recursive: true }); - } -} - -/** - * Read the project registry - */ -export function readRegistry(): Registry { - ensureRegistryDir(); - - if (!existsSync(REGISTRY_PATH)) { - return { version: '1.0.0', projects: [] }; - } - - try { - const content = readFileSync(REGISTRY_PATH, 'utf-8'); - return JSON.parse(content); - } catch { - return { version: '1.0.0', projects: [] }; - } -} - -/** - * Write the project registry - */ -export function writeRegistry(registry: Registry): void { - ensureRegistryDir(); - writeFileSync(REGISTRY_PATH, JSON.stringify(registry, null, 2)); -} - -/** - * Register a new project - */ -export function registerProject(project: Omit): RegisteredProject { - const registry = readRegistry(); - - // Check if project already exists - const existingIndex = registry.projects.findIndex( - p => p.path === project.path || p.name === project.name - ); - - const newProject: RegisteredProject = { - ...project, - registeredAt: new Date().toISOString() - }; - - if (existingIndex >= 0) { - // Update existing project - registry.projects[existingIndex] = { - ...registry.projects[existingIndex], - ...newProject, - registeredAt: registry.projects[existingIndex].registeredAt - }; - } else { - // Add new project - registry.projects.push(newProject); - } - - writeRegistry(registry); - return newProject; -} - -/** - * Update a project's last indexed time - */ -export function updateProjectIndexTime(name: string): void { - const registry = readRegistry(); - const project = registry.projects.find(p => p.name === name); - - if (project) { - project.lastIndexed = new Date().toISOString(); - writeRegistry(registry); - } -} - -/** - * Get a project by name - */ -export function getProject(name: string): RegisteredProject | undefined { - const registry = readRegistry(); - return registry.projects.find(p => p.name === name); -} - -/** - * Get all registered projects - */ -export function getAllProjects(): RegisteredProject[] { - return readRegistry().projects; -} - -/** - * Remove a project from the registry - */ -export function unregisterProject(name: string): boolean { - const registry = readRegistry(); - const index = registry.projects.findIndex(p => p.name === name); - - if (index >= 0) { - registry.projects.splice(index, 1); - writeRegistry(registry); - return true; - } - - return false; -} - -/** - * Get the registry path (for testing) - */ -export function getRegistryPath(): string { - return REGISTRY_PATH; -} diff --git a/gsd-memory/src/tools/decisions.ts b/gsd-memory/src/tools/decisions.ts deleted file mode 100644 index 57602ca0e..000000000 --- a/gsd-memory/src/tools/decisions.ts +++ /dev/null @@ -1,153 +0,0 @@ -import { getAllProjects } from '../registry.js'; -import { extractSummary, type SummaryData } from '../extractors/summary.js'; -import { extractProject, type ProjectData } from '../extractors/project.js'; -import { readFileSync, existsSync, readdirSync, statSync } from 'fs'; -import { join, basename } from 'path'; - -export interface DecisionResult { - decision: string; - rationale?: string; - project: string; - phase?: string; - source: string; - date?: string; - tags?: string[]; -} - -export interface DecisionOptions { - query?: string; - project?: string; - tags?: string[]; - limit?: number; -} - -/** - * Search for decisions across all registered GSD projects - */ -export async function findDecisions(options: DecisionOptions): Promise { - const projects = options.project - ? getAllProjects().filter(p => p.name === options.project) - : getAllProjects(); - - const allDecisions: DecisionResult[] = []; - - for (const project of projects) { - const planningPath = join(project.path, '.planning'); - if (!existsSync(planningPath)) continue; - - // Extract decisions from PROJECT.md - const projectDecisions = extractProjectDecisions(planningPath, project.name); - allDecisions.push(...projectDecisions); - - // Extract decisions from all SUMMARY.md files - const summaryDecisions = extractSummaryDecisions(planningPath, project.name); - allDecisions.push(...summaryDecisions); - } - - // Filter by query if provided - let filtered = allDecisions; - if (options.query) { - const query = options.query.toLowerCase(); - filtered = allDecisions.filter(d => - d.decision.toLowerCase().includes(query) || - d.rationale?.toLowerCase().includes(query) - ); - } - - // Filter by tags if provided - if (options.tags && options.tags.length > 0) { - const tags = options.tags.map(t => t.toLowerCase()); - filtered = filtered.filter(d => - d.tags?.some(t => tags.includes(t.toLowerCase())) - ); - } - - // Apply limit - const limit = options.limit || 50; - return filtered.slice(0, limit); -} - -/** - * Extract decisions from PROJECT.md - */ -function extractProjectDecisions(planningPath: string, projectName: string): DecisionResult[] { - const projectPath = join(planningPath, 'PROJECT.md'); - if (!existsSync(projectPath)) return []; - - try { - const content = readFileSync(projectPath, 'utf-8'); - const projectData = extractProject(content); - - return projectData.decisions.map(d => ({ - decision: d.decision, - rationale: d.rationale, - project: projectName, - source: projectPath - })); - } catch { - return []; - } -} - -/** - * Extract decisions from all SUMMARY.md files in a project - */ -function extractSummaryDecisions(planningPath: string, projectName: string): DecisionResult[] { - const decisions: DecisionResult[] = []; - const phasesPath = join(planningPath, 'phases'); - - if (!existsSync(phasesPath)) return decisions; - - // Find all SUMMARY.md files - const summaryFiles = findSummaryFiles(phasesPath); - - for (const file of summaryFiles) { - try { - const content = readFileSync(file, 'utf-8'); - const summaryData = extractSummary(content); - - for (const decision of summaryData.decisions) { - decisions.push({ - decision: decision.decision, - project: projectName, - phase: summaryData.phase, - source: file, - date: summaryData.completed, - tags: summaryData.tags - }); - } - } catch { - // Skip files that can't be parsed - } - } - - return decisions; -} - -/** - * Recursively find all SUMMARY.md files - */ -function findSummaryFiles(dir: string, files: string[] = []): string[] { - try { - const entries = readdirSync(dir); - - for (const entry of entries) { - const fullPath = join(dir, entry); - try { - const stat = statSync(fullPath); - - if (stat.isDirectory()) { - findSummaryFiles(fullPath, files); - } else if (entry.toUpperCase().includes('SUMMARY') && entry.endsWith('.md')) { - files.push(fullPath); - } - } catch { - // Skip entries that can't be accessed - } - } - } catch { - // Return empty if directory can't be read - } - - return files; -} diff --git a/gsd-memory/src/tools/index-tool.ts b/gsd-memory/src/tools/index-tool.ts deleted file mode 100644 index 5fc5d9bfb..000000000 --- a/gsd-memory/src/tools/index-tool.ts +++ /dev/null @@ -1,133 +0,0 @@ -import { getProject, updateProjectIndexTime, getAllProjects } from '../registry.js'; -import { qmd } from '../qmd.js'; -import { existsSync } from 'fs'; -import { join } from 'path'; - -export interface IndexOptions { - path?: string; - project?: string; -} - -export interface IndexResult { - success: boolean; - project?: string; - documentsIndexed?: number; - error?: string; - qmdUsed: boolean; -} - -/** - * Trigger indexing/update for a project - */ -export async function index(options: IndexOptions): Promise { - // Find the project - let projectName: string | undefined; - let projectPath: string | undefined; - let qmdCollection: string | undefined; - - 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(): Promise<{ - success: boolean; - results: IndexResult[]; -}> { - const projects = getAllProjects(); - const results: IndexResult[] = []; - - 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 }; -} diff --git a/gsd-memory/src/tools/patterns.ts b/gsd-memory/src/tools/patterns.ts deleted file mode 100644 index 74d7a09e8..000000000 --- a/gsd-memory/src/tools/patterns.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { getAllProjects } from '../registry.js'; -import { extractSummary } from '../extractors/summary.js'; -import { readFileSync, existsSync, readdirSync, statSync } from 'fs'; -import { join } from 'path'; - -export interface PatternResult { - pattern: string; - project: string; - phase: string; - source: string; - date?: string; - tags?: string[]; -} - -export interface PatternOptions { - query?: string; - project?: string; - tags?: string[]; - limit?: number; -} - -/** - * Search for patterns established across all registered GSD projects - */ -export async function findPatterns(options: PatternOptions): Promise { - const projects = options.project - ? getAllProjects().filter(p => p.name === options.project) - : getAllProjects(); - - const allPatterns: PatternResult[] = []; - - for (const project of projects) { - const phasesPath = join(project.path, '.planning', 'phases'); - if (!existsSync(phasesPath)) continue; - - // Find all SUMMARY.md files and extract patterns - const summaryFiles = findSummaryFiles(phasesPath); - - for (const file of summaryFiles) { - try { - const content = readFileSync(file, 'utf-8'); - const summaryData = extractSummary(content); - - for (const pattern of summaryData.patterns) { - allPatterns.push({ - pattern, - project: project.name, - phase: summaryData.phase, - source: file, - date: summaryData.completed, - tags: summaryData.tags - }); - } - } catch { - // Skip files that can't be parsed - } - } - } - - // Filter by query if provided - let filtered = allPatterns; - if (options.query) { - const query = options.query.toLowerCase(); - filtered = allPatterns.filter(p => - p.pattern.toLowerCase().includes(query) - ); - } - - // Filter by tags if provided - if (options.tags && options.tags.length > 0) { - const tags = options.tags.map(t => t.toLowerCase()); - filtered = filtered.filter(p => - p.tags?.some(t => tags.includes(t.toLowerCase())) - ); - } - - // Apply limit - const limit = options.limit || 50; - return filtered.slice(0, limit); -} - -/** - * Recursively find all SUMMARY.md files - */ -function findSummaryFiles(dir: string, files: string[] = []): string[] { - try { - const entries = readdirSync(dir); - - for (const entry of entries) { - const fullPath = join(dir, entry); - try { - const stat = statSync(fullPath); - - if (stat.isDirectory()) { - findSummaryFiles(fullPath, files); - } else if (entry.toUpperCase().includes('SUMMARY') && entry.endsWith('.md')) { - files.push(fullPath); - } - } catch { - // Skip entries that can't be accessed - } - } - } catch { - // Return empty if directory can't be read - } - - return files; -} diff --git a/gsd-memory/src/tools/pitfalls.ts b/gsd-memory/src/tools/pitfalls.ts deleted file mode 100644 index 4d029b84c..000000000 --- a/gsd-memory/src/tools/pitfalls.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { getAllProjects } from '../registry.js'; -import { extractResearch, type Pitfall } from '../extractors/research.js'; -import { readFileSync, existsSync, readdirSync, statSync } from 'fs'; -import { join } from 'path'; - -export interface PitfallResult extends Pitfall { - project: string; - phase?: string; - domain: string; - source: string; -} - -export interface PitfallOptions { - query?: string; - project?: string; - domain?: string; - limit?: number; -} - -/** - * Search for pitfalls documented across all registered GSD projects - */ -export async function findPitfalls(options: PitfallOptions): Promise { - const projects = options.project - ? getAllProjects().filter(p => p.name === options.project) - : getAllProjects(); - - const allPitfalls: PitfallResult[] = []; - - for (const project of projects) { - const planningPath = join(project.path, '.planning'); - if (!existsSync(planningPath)) continue; - - // Find all RESEARCH.md files - const researchFiles = findResearchFiles(planningPath); - - for (const file of researchFiles) { - try { - const content = readFileSync(file, 'utf-8'); - const researchData = extractResearch(content); - - // Extract phase from path if present - const phaseMatch = file.match(/phases\/(\d+-[^/]+)/); - const phase = phaseMatch ? phaseMatch[1] : undefined; - - for (const pitfall of researchData.pitfalls) { - allPitfalls.push({ - ...pitfall, - project: project.name, - phase, - domain: researchData.domain, - source: file - }); - } - } catch { - // Skip files that can't be parsed - } - } - } - - // Filter by query if provided - let filtered = allPitfalls; - if (options.query) { - const query = options.query.toLowerCase(); - filtered = allPitfalls.filter(p => - p.name.toLowerCase().includes(query) || - p.description.toLowerCase().includes(query) || - p.prevention.toLowerCase().includes(query) - ); - } - - // Filter by domain if provided - if (options.domain) { - const domain = options.domain.toLowerCase(); - filtered = filtered.filter(p => - p.domain.toLowerCase().includes(domain) - ); - } - - // Apply limit - const limit = options.limit || 50; - return filtered.slice(0, limit); -} - -/** - * Recursively find all RESEARCH.md files - */ -function findResearchFiles(dir: string, files: string[] = []): string[] { - try { - const entries = readdirSync(dir); - - for (const entry of entries) { - const fullPath = join(dir, entry); - try { - const stat = statSync(fullPath); - - if (stat.isDirectory() && !entry.startsWith('.')) { - findResearchFiles(fullPath, files); - } else if (entry.toUpperCase().includes('RESEARCH') && entry.endsWith('.md')) { - files.push(fullPath); - } - } catch { - // Skip entries that can't be accessed - } - } - } catch { - // Return empty if directory can't be read - } - - return files; -} diff --git a/gsd-memory/src/tools/register.ts b/gsd-memory/src/tools/register.ts deleted file mode 100644 index 2b554876a..000000000 --- a/gsd-memory/src/tools/register.ts +++ /dev/null @@ -1,146 +0,0 @@ -import { registerProject, getProject, getAllProjects, unregisterProject, type RegisteredProject } from '../registry.js'; -import { qmd } from '../qmd.js'; -import { existsSync } from 'fs'; -import { join, basename } from 'path'; - -export interface RegisterOptions { - path: string; - name?: string; -} - -export interface RegisterResult { - success: boolean; - project?: RegisteredProject; - qmdCollection?: string; - error?: string; -} - -/** - * Register a project with GSD memory - */ -export async function register(options: RegisterOptions): Promise { - // Validate path exists - if (!existsSync(options.path)) { - return { - success: false, - error: `Path does not exist: ${options.path}` - }; - } - - // Validate .planning directory exists - const planningPath = join(options.path, '.planning'); - if (!existsSync(planningPath)) { - return { - success: false, - error: `No .planning directory found at: ${planningPath}` - }; - } - - // Determine project name - const name = options.name || basename(options.path); - - // Check if QMD is available for semantic search - const qmdAvailable = await qmd.isAvailable(); - let qmdCollection: string | undefined; - - if (qmdAvailable) { - // Create QMD collection - qmdCollection = `gsd-${name.toLowerCase().replace(/[^a-z0-9]/g, '-')}`; - - const qmdResult = await qmd.createCollection({ - name: qmdCollection, - paths: [planningPath], - context: `GSD project: ${name}` - }); - - if (!qmdResult.success) { - // QMD collection creation failed, but we can still register - qmdCollection = undefined; - } - } - - // Register in local registry - const project = registerProject({ - name, - path: options.path, - qmdCollection - }); - - return { - success: true, - project, - qmdCollection - }; -} - -/** - * Get status of all registered projects - */ -export async function status(): Promise<{ - qmdAvailable: boolean; - projects: Array<{ - name: string; - path: string; - qmdCollection?: string; - registeredAt: string; - lastIndexed?: string; - documentCount?: number; - }>; -}> { - const qmdAvailable = await qmd.isAvailable(); - const projects = getAllProjects(); - - const enrichedProjects = await Promise.all( - projects.map(async (project) => { - let documentCount: number | undefined; - - if (qmdAvailable && project.qmdCollection) { - const qmdStatus = await qmd.status(project.qmdCollection); - documentCount = qmdStatus.documentCount; - } - - return { - name: project.name, - path: project.path, - qmdCollection: project.qmdCollection, - registeredAt: project.registeredAt, - lastIndexed: project.lastIndexed, - documentCount - }; - }) - ); - - return { - qmdAvailable, - projects: enrichedProjects - }; -} - -/** - * Unregister a project - */ -export async function unregister(name: string): Promise<{ success: boolean; error?: string }> { - const project = getProject(name); - - if (!project) { - return { - success: false, - error: `Project not found: ${name}` - }; - } - - // Remove from QMD if it has a collection - if (project.qmdCollection && await qmd.isAvailable()) { - try { - // QMD doesn't have a direct remove command, so we just skip - // The collection will be orphaned but harmless - } catch { - // Ignore QMD errors - } - } - - // Remove from registry - unregisterProject(name); - - return { success: true }; -} diff --git a/gsd-memory/src/tools/search.ts b/gsd-memory/src/tools/search.ts deleted file mode 100644 index a90238de3..000000000 --- a/gsd-memory/src/tools/search.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { qmd, QmdSearchResult } from '../qmd.js'; -import { getAllProjects } from '../registry.js'; -import { extractFrontmatter } from '../extractors/frontmatter.js'; -import { readFileSync, existsSync } from 'fs'; -import { join, basename, dirname } from 'path'; - -export interface SearchResult { - content: string; - source: string; - project: string; - phase?: string; - relevance: number; - documentType?: 'summary' | 'research' | 'project' | 'plan' | 'other'; -} - -export interface SearchOptions { - query: string; - project?: string; - tags?: string[]; - limit?: number; -} - -/** - * Search across all registered GSD projects - */ -export async function search(options: SearchOptions): Promise { - const projects = options.project - ? getAllProjects().filter(p => p.name === options.project) - : getAllProjects(); - - if (projects.length === 0) { - return []; - } - - const allResults: SearchResult[] = []; - - for (const project of projects) { - const planningPath = join(project.path, '.planning'); - - if (!existsSync(planningPath)) continue; - - // Search using QMD or grep fallback - const searchResults = await qmd.search({ - query: options.query, - paths: [planningPath], - collection: project.qmdCollection, - limit: options.limit || 20 - }); - - // Enrich results with GSD context - for (const result of searchResults) { - const enriched = enrichResult(result, project.name); - allResults.push(enriched); - } - } - - // Sort by relevance - allResults.sort((a, b) => b.relevance - a.relevance); - - // Apply limit - const limit = options.limit || 20; - return allResults.slice(0, limit); -} - -/** - * Enrich a search result with GSD-specific context - */ -function enrichResult(result: QmdSearchResult, projectName: string): SearchResult { - const enriched: SearchResult = { - content: result.content, - source: result.source, - project: projectName, - relevance: result.relevance, - documentType: getDocumentType(result.source) - }; - - // Try to extract phase from frontmatter or path - enriched.phase = extractPhase(result.source); - - return enriched; -} - -/** - * Determine document type from file path/name - */ -function getDocumentType(source: string): SearchResult['documentType'] { - const filename = basename(source).toUpperCase(); - - if (filename.includes('SUMMARY')) return 'summary'; - if (filename.includes('RESEARCH')) return 'research'; - if (filename.includes('PROJECT')) return 'project'; - if (filename.includes('PLAN')) return 'plan'; - - return 'other'; -} - -/** - * Extract phase identifier from file path or content - */ -function extractPhase(source: string): string | undefined { - // Try to get from path: .planning/phases/01-foundation/... - const pathMatch = source.match(/phases\/(\d+-[^/]+)/); - if (pathMatch) return pathMatch[1]; - - // Try to get from frontmatter - try { - if (existsSync(source)) { - const content = readFileSync(source, 'utf-8'); - const frontmatter = extractFrontmatter(content); - if (frontmatter.phase) return String(frontmatter.phase); - } - } catch { - // Ignore errors reading file - } - - return undefined; -} diff --git a/gsd-memory/src/tools/stack.ts b/gsd-memory/src/tools/stack.ts deleted file mode 100644 index 1939e662a..000000000 --- a/gsd-memory/src/tools/stack.ts +++ /dev/null @@ -1,171 +0,0 @@ -import { getAllProjects } from '../registry.js'; -import { extractSummary, type TechStackEntry } from '../extractors/summary.js'; -import { extractResearch } from '../extractors/research.js'; -import { readFileSync, existsSync, readdirSync, statSync } from 'fs'; -import { join } from 'path'; - -export interface StackResult { - library: string; - version?: string; - purpose?: string; - project: string; - phase?: string; - source: string; - sourceType: 'summary' | 'research'; -} - -export interface StackOptions { - query?: string; - project?: string; - limit?: number; -} - -/** - * Search for tech stack entries across all registered GSD projects - */ -export async function findStack(options: StackOptions): Promise { - const projects = options.project - ? getAllProjects().filter(p => p.name === options.project) - : getAllProjects(); - - const allStack: StackResult[] = []; - - for (const project of projects) { - const planningPath = join(project.path, '.planning'); - if (!existsSync(planningPath)) continue; - - // Extract from SUMMARY.md files - const summaryStack = extractFromSummaries(planningPath, project.name); - allStack.push(...summaryStack); - - // Extract from RESEARCH.md files - const researchStack = extractFromResearch(planningPath, project.name); - allStack.push(...researchStack); - } - - // Filter by query if provided - let filtered = allStack; - if (options.query) { - const query = options.query.toLowerCase(); - filtered = allStack.filter(s => - s.library.toLowerCase().includes(query) || - s.purpose?.toLowerCase().includes(query) - ); - } - - // Deduplicate by library name within each project - const seen = new Set(); - const deduplicated = filtered.filter(s => { - const key = `${s.project}:${s.library}`; - if (seen.has(key)) return false; - seen.add(key); - return true; - }); - - // Apply limit - const limit = options.limit || 100; - return deduplicated.slice(0, limit); -} - -/** - * Extract tech stack from all SUMMARY.md files - */ -function extractFromSummaries(planningPath: string, projectName: string): StackResult[] { - const stack: StackResult[] = []; - const phasesPath = join(planningPath, 'phases'); - - if (!existsSync(phasesPath)) return stack; - - const summaryFiles = findFiles(phasesPath, 'SUMMARY'); - - for (const file of summaryFiles) { - try { - const content = readFileSync(file, 'utf-8'); - const summaryData = extractSummary(content); - - // Extract phase from path - const phaseMatch = file.match(/phases\/(\d+-[^/]+)/); - const phase = phaseMatch ? phaseMatch[1] : undefined; - - for (const entry of summaryData.techStack) { - stack.push({ - library: entry.library, - version: entry.version, - purpose: entry.purpose, - project: projectName, - phase, - source: file, - sourceType: 'summary' - }); - } - } catch { - // Skip files that can't be parsed - } - } - - return stack; -} - -/** - * Extract tech stack from all RESEARCH.md files - */ -function extractFromResearch(planningPath: string, projectName: string): StackResult[] { - const stack: StackResult[] = []; - - const researchFiles = findFiles(planningPath, 'RESEARCH'); - - for (const file of researchFiles) { - try { - const content = readFileSync(file, 'utf-8'); - const researchData = extractResearch(content); - - // Extract phase from path - const phaseMatch = file.match(/phases\/(\d+-[^/]+)/); - const phase = phaseMatch ? phaseMatch[1] : undefined; - - for (const entry of researchData.standardStack) { - stack.push({ - library: entry.library, - version: entry.version, - purpose: entry.purpose, - project: projectName, - phase, - source: file, - sourceType: 'research' - }); - } - } catch { - // Skip files that can't be parsed - } - } - - return stack; -} - -/** - * Recursively find files matching a pattern - */ -function findFiles(dir: string, pattern: string, files: string[] = []): string[] { - try { - const entries = readdirSync(dir); - - for (const entry of entries) { - const fullPath = join(dir, entry); - try { - const stat = statSync(fullPath); - - if (stat.isDirectory() && !entry.startsWith('.')) { - findFiles(fullPath, pattern, files); - } else if (entry.toUpperCase().includes(pattern) && entry.endsWith('.md')) { - files.push(fullPath); - } - } catch { - // Skip entries that can't be accessed - } - } - } catch { - // Return empty if directory can't be read - } - - return files; -} diff --git a/gsd-memory/src/tools/status.ts b/gsd-memory/src/tools/status.ts deleted file mode 100644 index 313dcdf08..000000000 --- a/gsd-memory/src/tools/status.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { getAllProjects } from '../registry.js'; -import { qmd } from '../qmd.js'; -import { existsSync, readdirSync, statSync } from 'fs'; -import { join } from 'path'; - -export interface ProjectStatus { - name: string; - path: string; - exists: boolean; - hasPlanningDir: boolean; - qmdCollection?: string; - qmdAvailable: boolean; - documentCount: number; - registeredAt: string; - lastIndexed?: string; -} - -export interface MemoryStatus { - qmdAvailable: boolean; - qmdVersion?: string; - totalProjects: number; - totalDocuments: number; - projects: ProjectStatus[]; -} - -/** - * Get comprehensive status of GSD memory system - */ -export async function getStatus(): Promise { - const qmdAvailable = await qmd.isAvailable(); - const projects = getAllProjects(); - - let totalDocuments = 0; - const projectStatuses: ProjectStatus[] = []; - - for (const project of projects) { - const planningPath = join(project.path, '.planning'); - const exists = existsSync(project.path); - const hasPlanningDir = existsSync(planningPath); - - // Count documents in .planning directory - const documentCount = hasPlanningDir ? countMarkdownFiles(planningPath) : 0; - totalDocuments += documentCount; - - projectStatuses.push({ - name: project.name, - path: project.path, - exists, - hasPlanningDir, - qmdCollection: project.qmdCollection, - qmdAvailable: qmdAvailable && !!project.qmdCollection, - documentCount, - registeredAt: project.registeredAt, - lastIndexed: project.lastIndexed - }); - } - - return { - qmdAvailable, - totalProjects: projects.length, - totalDocuments, - projects: projectStatuses - }; -} - -/** - * Count markdown files in a directory recursively - */ -function countMarkdownFiles(dir: string): number { - let count = 0; - - try { - const entries = readdirSync(dir); - - for (const entry of entries) { - const fullPath = join(dir, entry); - try { - const stat = statSync(fullPath); - - if (stat.isDirectory() && !entry.startsWith('.')) { - count += countMarkdownFiles(fullPath); - } else if (stat.isFile() && entry.endsWith('.md')) { - count++; - } - } catch { - // Skip entries that can't be accessed - } - } - } catch { - // Return 0 if directory can't be read - } - - return count; -} diff --git a/gsd-memory/tests/extractors/frontmatter.test.ts b/gsd-memory/tests/extractors/frontmatter.test.ts deleted file mode 100644 index fa5646072..000000000 --- a/gsd-memory/tests/extractors/frontmatter.test.ts +++ /dev/null @@ -1,141 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import { extractFrontmatter } from '../../src/extractors/frontmatter.js'; -import { readFixture } from '../setup.js'; - -describe('frontmatter extractor', () => { - it('extracts YAML frontmatter from markdown', () => { - const md = `--- -phase: 01-foundation -plan: "01" -tags: [auth, jwt] ---- -# Content`; - const result = extractFrontmatter(md); - expect(result.phase).toBe('01-foundation'); - expect(result.plan).toBe('01'); - expect(result.tags).toEqual(['auth', 'jwt']); - }); - - it('parses numeric plan values as numbers', () => { - const md = `--- -phase: 01-foundation -plan: 01 ---- -# Content`; - const result = extractFrontmatter(md); - expect(result.plan).toBe(1); // YAML parses 01 as number - }); - - it('returns empty object for no frontmatter', () => { - const result = extractFrontmatter('# Just content'); - expect(result).toEqual({}); - }); - - it('returns empty object for markdown starting with heading', () => { - const md = `# Title - -Some content here.`; - const result = extractFrontmatter(md); - expect(result).toEqual({}); - }); - - it('handles malformed YAML gracefully', () => { - const md = `--- -invalid: [unclosed -broken: yaml: here ---- -# Content`; - expect(() => extractFrontmatter(md)).not.toThrow(); - const result = extractFrontmatter(md); - expect(result).toEqual({}); - }); - - it('handles empty frontmatter', () => { - const md = `--- ---- -# Content`; - const result = extractFrontmatter(md); - expect(result).toEqual({}); - }); - - it('extracts nested objects', () => { - const md = `--- -tech-stack: - added: - - jose: 5.2.0 - - bcrypt: 5.1.1 - patterns: - - httpOnly cookies ---- -# Content`; - const result = extractFrontmatter(md); - expect(result['tech-stack']).toBeDefined(); - // YAML parses these as objects with key-value pairs - expect(result['tech-stack'].added).toHaveLength(2); - expect(result['tech-stack'].added[0]).toHaveProperty('jose', '5.2.0'); - expect(result['tech-stack'].patterns).toContain('httpOnly cookies'); - }); - - it('extracts requires/provides structure', () => { - const md = `--- -requires: - - phase: 01-auth - provides: User model -provides: - - Dashboard component - - Real-time updates ---- -# Content`; - const result = extractFrontmatter(md); - expect(result.requires).toHaveLength(1); - expect(result.requires[0].phase).toBe('01-auth'); - expect(result.provides).toContain('Dashboard component'); - }); - - it('extracts from real SUMMARY.md fixture', () => { - const summary = readFixture('sample-summary.md'); - const result = extractFrontmatter(summary); - - expect(result.phase).toBe('01-foundation'); - expect(result.plan).toBe(1); // YAML parses 01 as number - expect(result.subsystem).toBe('auth'); - expect(result.tags).toContain('jwt'); - expect(result['key-decisions']).toBeDefined(); - expect(result['key-decisions'].length).toBeGreaterThan(0); - }); - - it('extracts from real RESEARCH.md fixture', () => { - const research = readFixture('sample-research.md'); - const result = extractFrontmatter(research); - - // Research frontmatter structure (lowercase keys) - expect(result).toHaveProperty('researched'); - expect(result).toHaveProperty('domain'); - expect(result).toHaveProperty('confidence'); - expect(result.confidence).toBe('HIGH'); - }); - - it('handles multiline strings in frontmatter', () => { - const md = `--- -description: | - This is a multiline - description that spans - multiple lines ---- -# Content`; - const result = extractFrontmatter(md); - expect(result.description).toContain('multiline'); - expect(result.description).toContain('multiple lines'); - }); - - it('handles special characters in values', () => { - const md = `--- -decision: "Used jose instead of jsonwebtoken - ESM native" -path: src/lib/auth.ts ---- -# Content`; - const result = extractFrontmatter(md); - expect(result.decision).toBe('Used jose instead of jsonwebtoken - ESM native'); - expect(result.path).toBe('src/lib/auth.ts'); - }); -}); diff --git a/gsd-memory/tests/extractors/project.test.ts b/gsd-memory/tests/extractors/project.test.ts deleted file mode 100644 index b1faaf740..000000000 --- a/gsd-memory/tests/extractors/project.test.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import { extractProject, type ProjectData } from '../../src/extractors/project.js'; -import { readFixture } from '../setup.js'; - -describe('project extractor', () => { - it('extracts project name from title', () => { - const project = readFixture('sample-project.md'); - const result = extractProject(project); - - expect(result.name).toBe('TaskFlow'); - }); - - it('extracts what this is description', () => { - const project = readFixture('sample-project.md'); - const result = extractProject(project); - - expect(result.description).toContain('task management'); - expect(result.description).toContain('terminal'); - }); - - it('extracts core value', () => { - const project = readFixture('sample-project.md'); - const result = extractProject(project); - - expect(result.coreValue).toContain('Fast task capture'); - }); - - it('extracts validated requirements', () => { - const project = readFixture('sample-project.md'); - const result = extractProject(project); - - expect(result.requirements.validated.length).toBeGreaterThan(0); - expect(result.requirements.validated[0]).toContain('CLI task creation'); - }); - - it('extracts active requirements', () => { - const project = readFixture('sample-project.md'); - const result = extractProject(project); - - expect(result.requirements.active.length).toBeGreaterThan(0); - expect(result.requirements.active).toContainEqual( - expect.stringContaining('dashboard') - ); - }); - - it('extracts out of scope items', () => { - const project = readFixture('sample-project.md'); - const result = extractProject(project); - - expect(result.requirements.outOfScope.length).toBeGreaterThan(0); - expect(result.requirements.outOfScope[0]).toHaveProperty('item'); - expect(result.requirements.outOfScope[0]).toHaveProperty('reason'); - }); - - it('extracts constraints', () => { - const project = readFixture('sample-project.md'); - const result = extractProject(project); - - expect(result.constraints.length).toBeGreaterThan(0); - expect(result.constraints[0]).toHaveProperty('type'); - expect(result.constraints[0]).toHaveProperty('value'); - }); - - it('extracts key decisions table', () => { - const project = readFixture('sample-project.md'); - const result = extractProject(project); - - expect(result.decisions.length).toBeGreaterThan(0); - expect(result.decisions[0]).toHaveProperty('decision'); - expect(result.decisions[0]).toHaveProperty('rationale'); - expect(result.decisions[0]).toHaveProperty('outcome'); - }); - - it('extracts context section', () => { - const project = readFixture('sample-project.md'); - const result = extractProject(project); - - expect(result.context).toBeDefined(); - expect(result.context).toContain('developers'); - }); - - it('handles project without optional sections', () => { - const minimalProject = `# MinimalProject - -## What This Is - -A minimal test project. - -## Core Value - -Test core value. - -## Requirements - -### Active - -- [ ] One feature -`; - - const result = extractProject(minimalProject); - - expect(result.name).toBe('MinimalProject'); - expect(result.description).toContain('minimal'); - expect(result.coreValue).toContain('Test core value'); - expect(result.requirements.active).toHaveLength(1); - expect(result.requirements.validated).toEqual([]); - expect(result.decisions).toEqual([]); - }); -}); diff --git a/gsd-memory/tests/extractors/research.test.ts b/gsd-memory/tests/extractors/research.test.ts deleted file mode 100644 index 335786490..000000000 --- a/gsd-memory/tests/extractors/research.test.ts +++ /dev/null @@ -1,89 +0,0 @@ -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([]); - }); -}); diff --git a/gsd-memory/tests/extractors/summary.test.ts b/gsd-memory/tests/extractors/summary.test.ts deleted file mode 100644 index e3a3b2273..000000000 --- a/gsd-memory/tests/extractors/summary.test.ts +++ /dev/null @@ -1,112 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import { extractSummary, type SummaryData } from '../../src/extractors/summary.js'; -import { readFixture } from '../setup.js'; - -describe('summary extractor', () => { - it('extracts decisions from frontmatter', () => { - const summary = readFixture('sample-summary.md'); - const result = extractSummary(summary); - - expect(result.decisions.length).toBeGreaterThan(0); - expect(result.decisions[0]).toHaveProperty('decision'); - expect(result.decisions[0].decision).toContain('jose'); - }); - - it('extracts tech stack additions', () => { - const summary = readFixture('sample-summary.md'); - const result = extractSummary(summary); - - expect(result.techStack.length).toBeGreaterThan(0); - expect(result.techStack).toContainEqual( - expect.objectContaining({ - library: 'jose', - version: '5.2.0' - }) - ); - }); - - it('extracts patterns established', () => { - const summary = readFixture('sample-summary.md'); - const result = extractSummary(summary); - - expect(result.patterns.length).toBeGreaterThan(0); - expect(result.patterns[0]).toContain('Token rotation'); - }); - - it('extracts requires/provides for dependency graph', () => { - const summary = readFixture('sample-summary.md'); - const result = extractSummary(summary); - - expect(result.requires).toBeDefined(); - expect(result.provides).toBeDefined(); - expect(result.provides.length).toBeGreaterThan(0); - }); - - it('extracts phase and plan identifiers', () => { - const summary = readFixture('sample-summary.md'); - const result = extractSummary(summary); - - expect(result.phase).toBe('01-foundation'); - expect(result.plan).toBe(1); - }); - - it('extracts subsystem and tags', () => { - const summary = readFixture('sample-summary.md'); - const result = extractSummary(summary); - - expect(result.subsystem).toBe('auth'); - expect(result.tags).toContain('jwt'); - expect(result.tags).toContain('prisma'); - }); - - it('extracts affects list', () => { - const summary = readFixture('sample-summary.md'); - const result = extractSummary(summary); - - expect(result.affects).toBeDefined(); - expect(result.affects).toContain('02-features'); - }); - - it('extracts key files', () => { - const summary = readFixture('sample-summary.md'); - const result = extractSummary(summary); - - expect(result.keyFiles).toBeDefined(); - expect(result.keyFiles.created).toContain('src/lib/auth.ts'); - }); - - it('extracts duration and completion date', () => { - const summary = readFixture('sample-summary.md'); - const result = extractSummary(summary); - - expect(result.duration).toBe('28min'); - expect(result.completed).toBe('2025-01-15'); - }); - - it('handles summary without optional fields', () => { - const minimalSummary = `--- -phase: 01-test -plan: 01 -subsystem: testing -tags: [test] ---- -# Phase 1 Summary - -**Test phase**`; - - const result = extractSummary(minimalSummary); - - expect(result.phase).toBe('01-test'); - expect(result.decisions).toEqual([]); - expect(result.techStack).toEqual([]); - expect(result.patterns).toEqual([]); - }); - - it('extracts one-liner from content', () => { - const summary = readFixture('sample-summary.md'); - const result = extractSummary(summary); - - expect(result.oneLiner).toBeDefined(); - expect(result.oneLiner).toContain('JWT auth'); - }); -}); diff --git a/gsd-memory/tests/fixtures/mock-planning/PROJECT.md b/gsd-memory/tests/fixtures/mock-planning/PROJECT.md deleted file mode 100644 index 511063c4e..000000000 --- a/gsd-memory/tests/fixtures/mock-planning/PROJECT.md +++ /dev/null @@ -1,43 +0,0 @@ -# MockProject - -## What This Is - -A test project for validating GSD memory extraction. Contains all expected document types and frontmatter structures. - -## Core Value - -Test coverage for GSD memory extractors. - -## Requirements - -### Validated - -- ✓ Extractor parses SUMMARY.md frontmatter — Phase 1 - -### Active - -- [ ] Cross-project search works -- [ ] Decision extraction includes rationale - -### Out of Scope - -- Production deployment — test fixture only - -## Context - -Mock project used in GSD memory test suite. - -## Constraints - -- **Tech stack**: TypeScript, Vitest -- **Scope**: Test fixtures only - -## Key Decisions - -| Decision | Rationale | Outcome | -|----------|-----------|---------| -| YAML frontmatter | Machine-readable metadata | ✓ Good | -| Gray-matter parser | Battle-tested, handles edge cases | — Pending | - ---- -*Last updated: 2025-01-20 after creation* diff --git a/gsd-memory/tests/fixtures/mock-planning/STATE.md b/gsd-memory/tests/fixtures/mock-planning/STATE.md deleted file mode 100644 index 471e6c744..000000000 --- a/gsd-memory/tests/fixtures/mock-planning/STATE.md +++ /dev/null @@ -1,60 +0,0 @@ -# Project State - -## Project Reference - -See: .planning/PROJECT.md (updated 2025-01-20) - -**Core value:** Test coverage for GSD memory extractors -**Current focus:** Phase 1 Foundation - -## Current Position - -Phase: 1 of 2 (Foundation) -Plan: 1 of 1 in current phase -Status: Phase complete -Last activity: 2025-01-20 — Completed foundation phase - -Progress: [█████░░░░░] 50% - -## Performance Metrics - -**Velocity:** -- Total plans completed: 1 -- Average duration: 15 min -- Total execution time: 0.25 hours - -**By Phase:** - -| Phase | Plans | Total | Avg/Plan | -|-------|-------|-------|----------| -| 01-foundation | 1 | 15min | 15min | - -**Recent Trend:** -- Last 5 plans: [15min] -- Trend: Stable - -*Updated after each plan completion* - -## Accumulated Context - -### Decisions - -Decisions are logged in PROJECT.md Key Decisions table. -Recent decisions affecting current work: - -- [Phase 1]: Used YAML frontmatter for metadata -- [Phase 1]: Selected gray-matter parser - -### Pending Todos - -None yet. - -### Blockers/Concerns - -None yet. - -## Session Continuity - -Last session: 2025-01-20 14:30 -Stopped at: Phase 1 complete, ready for Phase 2 -Resume file: None diff --git a/gsd-memory/tests/fixtures/mock-planning/config.json b/gsd-memory/tests/fixtures/mock-planning/config.json deleted file mode 100644 index e5afc2d1b..000000000 --- a/gsd-memory/tests/fixtures/mock-planning/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "project": "MockProject", - "version": "1.0.0", - "created": "2025-01-20", - "settings": { - "parallelization": true, - "atomicCommits": true - } -} diff --git a/gsd-memory/tests/fixtures/mock-planning/phases/01-foundation/01-01-SUMMARY.md b/gsd-memory/tests/fixtures/mock-planning/phases/01-foundation/01-01-SUMMARY.md deleted file mode 100644 index 0ea367b35..000000000 --- a/gsd-memory/tests/fixtures/mock-planning/phases/01-foundation/01-01-SUMMARY.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -phase: 01-foundation -plan: 01 -subsystem: testing -tags: [vitest, typescript, testing] - -requires: - - phase: none - provides: greenfield project - -provides: - - Test fixture structure - - Extractor test coverage - - Mock planning directory - -affects: [02-integration] - -tech-stack: - added: - - vitest: 1.0.0 - - gray-matter: 4.0.3 - patterns: - - TDD for extractors - - Fixture-based testing - -key-files: - created: - - tests/fixtures/sample-summary.md - - tests/fixtures/sample-research.md - - tests/fixtures/sample-project.md - modified: [] - -key-decisions: - - "Used Vitest for test runner - fast, ESM native" - - "Created realistic fixtures from actual GSD templates" - -patterns-established: - - "Fixture files mirror real GSD output" - - "Tests verify extraction accuracy" - -duration: 15min -completed: 2025-01-20 ---- - -# Phase 1: Foundation Summary - -**Test fixtures and extractor test coverage for GSD memory server** - -## Performance - -- **Duration:** 15 min -- **Started:** 2025-01-20T14:00:00Z -- **Completed:** 2025-01-20T14:15:00Z -- **Tasks:** 3 -- **Files modified:** 5 - -## Accomplishments -- Created realistic test fixtures -- Set up Vitest configuration -- Established TDD pattern for extractors - -## Task Commits - -1. **Task 1: Create fixtures** - `fix001` (feat) -2. **Task 2: Configure Vitest** - `fix002` (chore) -3. **Task 3: Write extractor tests** - `fix003` (test) - -## Files Created/Modified -- `tests/fixtures/sample-summary.md` - SUMMARY.md fixture -- `tests/fixtures/sample-research.md` - RESEARCH.md fixture -- `tests/fixtures/sample-project.md` - PROJECT.md fixture -- `vitest.config.ts` - Test configuration - -## Decisions Made -- Used Vitest over Jest for ESM support -- Created comprehensive fixtures from real templates - -## Deviations from Plan - -None - plan executed exactly as written. - -## Issues Encountered -None. - -## User Setup Required - -None - no external service configuration required. - -## Next Phase Readiness -- Fixtures complete, ready for extractor implementation -- Test patterns established - ---- -*Phase: 01-foundation* -*Completed: 2025-01-20* diff --git a/gsd-memory/tests/fixtures/mock-planning/phases/01-foundation/01-RESEARCH.md b/gsd-memory/tests/fixtures/mock-planning/phases/01-foundation/01-RESEARCH.md deleted file mode 100644 index 05cb6a11c..000000000 --- a/gsd-memory/tests/fixtures/mock-planning/phases/01-foundation/01-RESEARCH.md +++ /dev/null @@ -1,100 +0,0 @@ -# Phase 1: Foundation - Research - -**Researched:** 2025-01-18 -**Domain:** TypeScript testing and YAML parsing -**Confidence:** HIGH - - -## Summary - -Researched testing frameworks and YAML parsing for TypeScript MCP server development. Vitest is the clear standard for ESM TypeScript projects. Gray-matter is battle-tested for markdown frontmatter parsing. - -**Primary recommendation:** Use Vitest + gray-matter. Follow TDD for all extractors. - - - -## Standard Stack - -### Core -| Library | Version | Purpose | Why Standard | -|---------|---------|---------|--------------| -| vitest | 1.0.0 | Test runner | Fast, ESM native, TS support | -| gray-matter | 4.0.3 | Frontmatter parsing | Handles edge cases, widely used | - -### Supporting -| Library | Version | Purpose | When to Use | -|---------|---------|---------|-------------| -| yaml | 2.3.0 | YAML parsing | Complex YAML beyond frontmatter | - -### Alternatives Considered -| Instead of | Could Use | Tradeoff | -|------------|-----------|----------| -| Vitest | Jest | Jest slower for ESM, more config | -| gray-matter | manual regex | Gray-matter handles edge cases | - - - -## Don't Hand-Roll - -| Problem | Don't Build | Use Instead | Why | -|---------|-------------|-------------|-----| -| YAML frontmatter | Regex parsing | gray-matter | Multiline, escaping, edge cases | -| Test runner | Custom harness | Vitest | Watch mode, coverage, parallel | - -**Key insight:** YAML parsing has many edge cases. Gray-matter handles them all. - - - -## Common Pitfalls - -### Pitfall 1: Malformed YAML -**What goes wrong:** Parser throws on invalid YAML -**Why it happens:** User-edited files may have syntax errors -**How to avoid:** Wrap parsing in try-catch, return empty object on failure -**Warning signs:** Tests fail with YAML parse errors - -### Pitfall 2: Missing Frontmatter -**What goes wrong:** Code assumes frontmatter exists -**Why it happens:** Not all markdown files have frontmatter -**How to avoid:** Always check for empty result -**Warning signs:** Undefined errors on .data access - - - -## Sources - -### Primary (HIGH confidence) -- Vitest documentation - test configuration -- gray-matter npm - API reference - -### Secondary (MEDIUM confidence) -- None - -### Tertiary (LOW confidence - needs validation) -- None - - - -## Metadata - -**Research scope:** -- Core technology: TypeScript testing -- Ecosystem: Vitest, gray-matter -- Patterns: TDD, fixture-based testing -- Pitfalls: YAML parsing edge cases - -**Confidence breakdown:** -- Standard stack: HIGH - widely used -- Architecture: HIGH - standard patterns -- Pitfalls: HIGH - documented extensively -- Code examples: HIGH - from official docs - -**Research date:** 2025-01-18 -**Valid until:** 2025-02-18 (30 days - stable tech) - - ---- - -*Phase: 01-foundation* -*Research completed: 2025-01-18* -*Ready for planning: yes* diff --git a/gsd-memory/tests/fixtures/mock-planning/research/SUMMARY.md b/gsd-memory/tests/fixtures/mock-planning/research/SUMMARY.md deleted file mode 100644 index 1d3e7d776..000000000 --- a/gsd-memory/tests/fixtures/mock-planning/research/SUMMARY.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -domain: typescript-testing -confidence: HIGH -researched: 2025-01-18 ---- - -# Research Summary - -Research completed on TypeScript testing ecosystem for GSD memory server. - -## Key Findings - -- Vitest is the standard for TypeScript projects -- Gray-matter handles YAML frontmatter parsing -- MCP SDK provides standard server implementation - -## Recommendations - -1. Use Vitest for all tests -2. Use gray-matter for frontmatter extraction -3. Follow MCP SDK patterns for tool implementation diff --git a/gsd-memory/tests/fixtures/mock-project/.planning/PROJECT.md b/gsd-memory/tests/fixtures/mock-project/.planning/PROJECT.md deleted file mode 100644 index 511063c4e..000000000 --- a/gsd-memory/tests/fixtures/mock-project/.planning/PROJECT.md +++ /dev/null @@ -1,43 +0,0 @@ -# MockProject - -## What This Is - -A test project for validating GSD memory extraction. Contains all expected document types and frontmatter structures. - -## Core Value - -Test coverage for GSD memory extractors. - -## Requirements - -### Validated - -- ✓ Extractor parses SUMMARY.md frontmatter — Phase 1 - -### Active - -- [ ] Cross-project search works -- [ ] Decision extraction includes rationale - -### Out of Scope - -- Production deployment — test fixture only - -## Context - -Mock project used in GSD memory test suite. - -## Constraints - -- **Tech stack**: TypeScript, Vitest -- **Scope**: Test fixtures only - -## Key Decisions - -| Decision | Rationale | Outcome | -|----------|-----------|---------| -| YAML frontmatter | Machine-readable metadata | ✓ Good | -| Gray-matter parser | Battle-tested, handles edge cases | — Pending | - ---- -*Last updated: 2025-01-20 after creation* diff --git a/gsd-memory/tests/fixtures/mock-project/.planning/STATE.md b/gsd-memory/tests/fixtures/mock-project/.planning/STATE.md deleted file mode 100644 index 471e6c744..000000000 --- a/gsd-memory/tests/fixtures/mock-project/.planning/STATE.md +++ /dev/null @@ -1,60 +0,0 @@ -# Project State - -## Project Reference - -See: .planning/PROJECT.md (updated 2025-01-20) - -**Core value:** Test coverage for GSD memory extractors -**Current focus:** Phase 1 Foundation - -## Current Position - -Phase: 1 of 2 (Foundation) -Plan: 1 of 1 in current phase -Status: Phase complete -Last activity: 2025-01-20 — Completed foundation phase - -Progress: [█████░░░░░] 50% - -## Performance Metrics - -**Velocity:** -- Total plans completed: 1 -- Average duration: 15 min -- Total execution time: 0.25 hours - -**By Phase:** - -| Phase | Plans | Total | Avg/Plan | -|-------|-------|-------|----------| -| 01-foundation | 1 | 15min | 15min | - -**Recent Trend:** -- Last 5 plans: [15min] -- Trend: Stable - -*Updated after each plan completion* - -## Accumulated Context - -### Decisions - -Decisions are logged in PROJECT.md Key Decisions table. -Recent decisions affecting current work: - -- [Phase 1]: Used YAML frontmatter for metadata -- [Phase 1]: Selected gray-matter parser - -### Pending Todos - -None yet. - -### Blockers/Concerns - -None yet. - -## Session Continuity - -Last session: 2025-01-20 14:30 -Stopped at: Phase 1 complete, ready for Phase 2 -Resume file: None diff --git a/gsd-memory/tests/fixtures/mock-project/.planning/config.json b/gsd-memory/tests/fixtures/mock-project/.planning/config.json deleted file mode 100644 index e5afc2d1b..000000000 --- a/gsd-memory/tests/fixtures/mock-project/.planning/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "project": "MockProject", - "version": "1.0.0", - "created": "2025-01-20", - "settings": { - "parallelization": true, - "atomicCommits": true - } -} diff --git a/gsd-memory/tests/fixtures/mock-project/.planning/phases/01-foundation/01-01-SUMMARY.md b/gsd-memory/tests/fixtures/mock-project/.planning/phases/01-foundation/01-01-SUMMARY.md deleted file mode 100644 index 0ea367b35..000000000 --- a/gsd-memory/tests/fixtures/mock-project/.planning/phases/01-foundation/01-01-SUMMARY.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -phase: 01-foundation -plan: 01 -subsystem: testing -tags: [vitest, typescript, testing] - -requires: - - phase: none - provides: greenfield project - -provides: - - Test fixture structure - - Extractor test coverage - - Mock planning directory - -affects: [02-integration] - -tech-stack: - added: - - vitest: 1.0.0 - - gray-matter: 4.0.3 - patterns: - - TDD for extractors - - Fixture-based testing - -key-files: - created: - - tests/fixtures/sample-summary.md - - tests/fixtures/sample-research.md - - tests/fixtures/sample-project.md - modified: [] - -key-decisions: - - "Used Vitest for test runner - fast, ESM native" - - "Created realistic fixtures from actual GSD templates" - -patterns-established: - - "Fixture files mirror real GSD output" - - "Tests verify extraction accuracy" - -duration: 15min -completed: 2025-01-20 ---- - -# Phase 1: Foundation Summary - -**Test fixtures and extractor test coverage for GSD memory server** - -## Performance - -- **Duration:** 15 min -- **Started:** 2025-01-20T14:00:00Z -- **Completed:** 2025-01-20T14:15:00Z -- **Tasks:** 3 -- **Files modified:** 5 - -## Accomplishments -- Created realistic test fixtures -- Set up Vitest configuration -- Established TDD pattern for extractors - -## Task Commits - -1. **Task 1: Create fixtures** - `fix001` (feat) -2. **Task 2: Configure Vitest** - `fix002` (chore) -3. **Task 3: Write extractor tests** - `fix003` (test) - -## Files Created/Modified -- `tests/fixtures/sample-summary.md` - SUMMARY.md fixture -- `tests/fixtures/sample-research.md` - RESEARCH.md fixture -- `tests/fixtures/sample-project.md` - PROJECT.md fixture -- `vitest.config.ts` - Test configuration - -## Decisions Made -- Used Vitest over Jest for ESM support -- Created comprehensive fixtures from real templates - -## Deviations from Plan - -None - plan executed exactly as written. - -## Issues Encountered -None. - -## User Setup Required - -None - no external service configuration required. - -## Next Phase Readiness -- Fixtures complete, ready for extractor implementation -- Test patterns established - ---- -*Phase: 01-foundation* -*Completed: 2025-01-20* diff --git a/gsd-memory/tests/fixtures/mock-project/.planning/phases/01-foundation/01-RESEARCH.md b/gsd-memory/tests/fixtures/mock-project/.planning/phases/01-foundation/01-RESEARCH.md deleted file mode 100644 index 05cb6a11c..000000000 --- a/gsd-memory/tests/fixtures/mock-project/.planning/phases/01-foundation/01-RESEARCH.md +++ /dev/null @@ -1,100 +0,0 @@ -# Phase 1: Foundation - Research - -**Researched:** 2025-01-18 -**Domain:** TypeScript testing and YAML parsing -**Confidence:** HIGH - - -## Summary - -Researched testing frameworks and YAML parsing for TypeScript MCP server development. Vitest is the clear standard for ESM TypeScript projects. Gray-matter is battle-tested for markdown frontmatter parsing. - -**Primary recommendation:** Use Vitest + gray-matter. Follow TDD for all extractors. - - - -## Standard Stack - -### Core -| Library | Version | Purpose | Why Standard | -|---------|---------|---------|--------------| -| vitest | 1.0.0 | Test runner | Fast, ESM native, TS support | -| gray-matter | 4.0.3 | Frontmatter parsing | Handles edge cases, widely used | - -### Supporting -| Library | Version | Purpose | When to Use | -|---------|---------|---------|-------------| -| yaml | 2.3.0 | YAML parsing | Complex YAML beyond frontmatter | - -### Alternatives Considered -| Instead of | Could Use | Tradeoff | -|------------|-----------|----------| -| Vitest | Jest | Jest slower for ESM, more config | -| gray-matter | manual regex | Gray-matter handles edge cases | - - - -## Don't Hand-Roll - -| Problem | Don't Build | Use Instead | Why | -|---------|-------------|-------------|-----| -| YAML frontmatter | Regex parsing | gray-matter | Multiline, escaping, edge cases | -| Test runner | Custom harness | Vitest | Watch mode, coverage, parallel | - -**Key insight:** YAML parsing has many edge cases. Gray-matter handles them all. - - - -## Common Pitfalls - -### Pitfall 1: Malformed YAML -**What goes wrong:** Parser throws on invalid YAML -**Why it happens:** User-edited files may have syntax errors -**How to avoid:** Wrap parsing in try-catch, return empty object on failure -**Warning signs:** Tests fail with YAML parse errors - -### Pitfall 2: Missing Frontmatter -**What goes wrong:** Code assumes frontmatter exists -**Why it happens:** Not all markdown files have frontmatter -**How to avoid:** Always check for empty result -**Warning signs:** Undefined errors on .data access - - - -## Sources - -### Primary (HIGH confidence) -- Vitest documentation - test configuration -- gray-matter npm - API reference - -### Secondary (MEDIUM confidence) -- None - -### Tertiary (LOW confidence - needs validation) -- None - - - -## Metadata - -**Research scope:** -- Core technology: TypeScript testing -- Ecosystem: Vitest, gray-matter -- Patterns: TDD, fixture-based testing -- Pitfalls: YAML parsing edge cases - -**Confidence breakdown:** -- Standard stack: HIGH - widely used -- Architecture: HIGH - standard patterns -- Pitfalls: HIGH - documented extensively -- Code examples: HIGH - from official docs - -**Research date:** 2025-01-18 -**Valid until:** 2025-02-18 (30 days - stable tech) - - ---- - -*Phase: 01-foundation* -*Research completed: 2025-01-18* -*Ready for planning: yes* diff --git a/gsd-memory/tests/fixtures/mock-project/.planning/research/SUMMARY.md b/gsd-memory/tests/fixtures/mock-project/.planning/research/SUMMARY.md deleted file mode 100644 index 1d3e7d776..000000000 --- a/gsd-memory/tests/fixtures/mock-project/.planning/research/SUMMARY.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -domain: typescript-testing -confidence: HIGH -researched: 2025-01-18 ---- - -# Research Summary - -Research completed on TypeScript testing ecosystem for GSD memory server. - -## Key Findings - -- Vitest is the standard for TypeScript projects -- Gray-matter handles YAML frontmatter parsing -- MCP SDK provides standard server implementation - -## Recommendations - -1. Use Vitest for all tests -2. Use gray-matter for frontmatter extraction -3. Follow MCP SDK patterns for tool implementation diff --git a/gsd-memory/tests/fixtures/sample-project.md b/gsd-memory/tests/fixtures/sample-project.md deleted file mode 100644 index 9238d9ec3..000000000 --- a/gsd-memory/tests/fixtures/sample-project.md +++ /dev/null @@ -1,53 +0,0 @@ -# TaskFlow - -## What This Is - -A task management app for developers who want to track their work without leaving the terminal. CLI-first with optional web dashboard for visualization. - -## Core Value - -Fast task capture from anywhere — if adding a task takes more than 3 seconds, developers won't use it. - -## Requirements - -### Validated - -- ✓ CLI task creation with `task add "description"` — v0.1 -- ✓ List tasks with filtering `task list --tag=bug` — v0.1 - -### Active - -- [ ] Web dashboard showing task burndown -- [ ] Real-time sync between CLI and dashboard -- [ ] GitHub issue integration for bidirectional sync - -### Out of Scope - -- Mobile app — complexity for limited value, CLI works via SSH -- Team features — solo developer focus, teams use Jira/Linear -- Time tracking — feature creep, use dedicated tool - -## Context - -Built as a personal tool that grew. Users are developers who live in terminals. Primary use case is quick capture during coding sessions. Existing solutions (Todoist, Things) require context switching to GUI. - -Current user base: ~50 developers using CLI, requesting dashboard for weekly reviews. - -## Constraints - -- **Tech stack**: TypeScript, Next.js, SQLite — matches existing CLI codebase -- **Deployment**: Self-hosted or Vercel — users want data ownership -- **Performance**: Task add must complete in <100ms — core value -- **Compatibility**: Works offline, syncs when connected — developers travel - -## Key Decisions - -| Decision | Rationale | Outcome | -|----------|-----------|---------| -| SQLite over Postgres | Simpler self-hosting, no DB server | ✓ Good | -| SSE over WebSockets | Unidirectional updates, simpler | — Pending | -| jose for JWT | ESM-native, Edge-compatible | ✓ Good | -| Prisma ORM | Type safety, migrations | ✓ Good | - ---- -*Last updated: 2025-01-15 after Phase 1* diff --git a/gsd-memory/tests/fixtures/sample-research.md b/gsd-memory/tests/fixtures/sample-research.md deleted file mode 100644 index cbecac8df..000000000 --- a/gsd-memory/tests/fixtures/sample-research.md +++ /dev/null @@ -1,285 +0,0 @@ ---- -researched: 2025-01-20 -domain: WebSocket and Server-Sent Events for real-time updates -confidence: HIGH ---- - -# Phase 2: Real-time Features - Research - - -## User Constraints (from CONTEXT.md) - -### Locked Decisions -- Use Server-Sent Events (not WebSockets) for dashboard updates -- Must work behind Cloudflare proxy - -### Claude's Discretion -- Choice of SSE library -- Event structure and naming - -### Deferred Ideas (OUT OF SCOPE) -- Bi-directional chat feature (future milestone) -- Push notifications - - - -## Summary - -Researched Server-Sent Events for real-time dashboard updates in Next.js. SSE is simpler than WebSockets for unidirectional server-to-client streaming and works reliably behind Cloudflare. - -Key finding: Next.js App Router supports SSE via ReadableStream in route handlers. No additional libraries needed - native EventSource on client, ReadableStream on server. - -**Primary recommendation:** Use native SSE with Next.js route handlers. Implement heartbeat to detect disconnections. Use EventSource with reconnection logic on client. - - - -## Standard Stack - -### Core -| Library | Version | Purpose | Why Standard | -|---------|---------|---------|--------------| -| Native EventSource | - | Client-side SSE | Built into browsers, no deps | -| ReadableStream | - | Server-side SSE | Built into Next.js/Node | - -### Supporting -| Library | Version | Purpose | When to Use | -|---------|---------|---------|-------------| -| eventsource | 2.0.2 | Node SSE client | If testing SSE endpoints | -| reconnecting-eventsource | 1.6.2 | Auto-reconnect | Production client resilience | - -### Alternatives Considered -| Instead of | Could Use | Tradeoff | -|------------|-----------|----------| -| Native SSE | socket.io | Socket.io if bidirectional needed, heavier | -| Native SSE | Pusher | Pusher for scale, but adds dependency | - -**Installation:** -```bash -npm install reconnecting-eventsource -``` - - - -## Architecture Patterns - -### Recommended Project Structure -``` -src/ -├── app/api/events/ -│ └── route.ts # SSE endpoint -├── hooks/ -│ └── useSSE.ts # Client hook -└── lib/ - └── events.ts # Event types and helpers -``` - -### Pattern 1: SSE Route Handler -**What:** Next.js route handler returning SSE stream -**When to use:** Any server-to-client streaming -**Example:** -```typescript -// Source: Next.js App Router docs -export async function GET() { - const stream = new ReadableStream({ - start(controller) { - const encoder = new TextEncoder(); - - const send = (data: object) => { - controller.enqueue(encoder.encode(`data: ${JSON.stringify(data)}\n\n`)); - }; - - // Heartbeat every 30s - const heartbeat = setInterval(() => send({ type: 'heartbeat' }), 30000); - - // Cleanup on close - return () => clearInterval(heartbeat); - } - }); - - return new Response(stream, { - headers: { - 'Content-Type': 'text/event-stream', - 'Cache-Control': 'no-cache', - 'Connection': 'keep-alive' - } - }); -} -``` - -### Pattern 2: Client Hook with Reconnection -**What:** React hook that manages SSE connection lifecycle -**When to use:** Any component consuming SSE -**Example:** -```typescript -// Source: Community pattern, verified -function useSSE(url: string) { - const [data, setData] = useState(null); - const [error, setError] = useState(null); - - useEffect(() => { - const es = new EventSource(url); - - es.onmessage = (e) => setData(JSON.parse(e.data)); - es.onerror = () => setError(new Error('SSE connection failed')); - - return () => es.close(); - }, [url]); - - return { data, error }; -} -``` - -### Anti-Patterns to Avoid -- **Polling instead of SSE:** SSE is more efficient for real-time -- **No heartbeat:** Connections die silently without heartbeat -- **Missing reconnection:** EventSource auto-reconnects but custom logic may be needed - - - -## Don't Hand-Roll - -| Problem | Don't Build | Use Instead | Why | -|---------|-------------|-------------|-----| -| SSE parsing | Custom parser | Native EventSource | Browser handles format | -| Reconnection | setTimeout loops | reconnecting-eventsource | Handles edge cases | -| Event typing | Inline types | Shared types file | Type safety across client/server | - -**Key insight:** SSE is standardized. The browser's EventSource handles parsing, reconnection, and error recovery. Custom implementations miss edge cases. - - - -## Common Pitfalls - -### Pitfall 1: Cloudflare Buffering -**What goes wrong:** Events don't arrive in real-time, come in batches -**Why it happens:** Cloudflare buffers responses by default -**How to avoid:** Set `Cache-Control: no-cache` and `X-Accel-Buffering: no` -**Warning signs:** Events arrive in bursts, not individually - -### Pitfall 2: Connection Limits -**What goes wrong:** Browser limits SSE connections to same origin -**Why it happens:** Browsers limit ~6 concurrent connections per domain -**How to avoid:** Single SSE connection multiplexing multiple event types -**Warning signs:** Later connections fail or queue - -### Pitfall 3: Memory Leaks -**What goes wrong:** Server memory grows over time -**Why it happens:** Event handlers not cleaned up on disconnect -**How to avoid:** Track connections, clean up on close/error -**Warning signs:** Server memory increases with usage - - - -## Code Examples - -### Complete SSE Endpoint -```typescript -// Source: Next.js docs + community best practices -import { NextRequest } from 'next/server'; - -export const runtime = 'edge'; // Better for SSE - -export async function GET(req: NextRequest) { - const stream = new ReadableStream({ - start(controller) { - const encoder = new TextEncoder(); - - const send = (event: string, data: unknown) => { - controller.enqueue( - encoder.encode(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`) - ); - }; - - // Initial data - send('init', { connected: true }); - - // Heartbeat - const interval = setInterval(() => send('heartbeat', {}), 30000); - - // Simulate updates - const updates = setInterval(() => { - send('update', { timestamp: Date.now() }); - }, 5000); - - req.signal.addEventListener('abort', () => { - clearInterval(interval); - clearInterval(updates); - }); - } - }); - - return new Response(stream, { - headers: { - 'Content-Type': 'text/event-stream', - 'Cache-Control': 'no-cache, no-transform', - 'Connection': 'keep-alive', - 'X-Accel-Buffering': 'no' - } - }); -} -``` - - - -## State of the Art (2024-2025) - -| Old Approach | Current Approach | When Changed | Impact | -|--------------|------------------|--------------|--------| -| Pages API SSE | App Router + ReadableStream | 2023 | Cleaner API, Edge support | -| socket.io default | SSE for unidirectional | 2022 | Simpler, less overhead | - -**New tools/patterns to consider:** -- **Edge Runtime:** Better for long-lived connections -- **React Server Components:** Can coexist with SSE for initial data - -**Deprecated/outdated:** -- **res.write() in Pages API:** Use ReadableStream in App Router - - - -## Open Questions - -1. **Connection cleanup on Vercel** - - What we know: Vercel has function timeout limits - - What's unclear: Exact behavior of long-lived SSE on serverless - - Recommendation: Test with 10-minute connections, implement client reconnection - - - -## Sources - -### Primary (HIGH confidence) -- /vercel/next.js - App Router streaming, route handlers -- MDN EventSource - Browser API reference - -### Secondary (MEDIUM confidence) -- Next.js GitHub discussions on SSE - verified against docs - -### Tertiary (LOW confidence - needs validation) -- None - - - -## Metadata - -**Research scope:** -- Core technology: Server-Sent Events -- Ecosystem: Next.js App Router, Edge Runtime -- Patterns: SSE routes, client hooks, reconnection -- Pitfalls: Buffering, connection limits, memory - -**Confidence breakdown:** -- Standard stack: HIGH - native browser/server APIs -- Architecture: HIGH - verified with Next.js docs -- Pitfalls: HIGH - documented in production apps -- Code examples: HIGH - from official sources - -**Research date:** 2025-01-20 -**Valid until:** 2025-02-20 (30 days - stable tech) - - ---- - -*Phase: 02-realtime* -*Research completed: 2025-01-20* -*Ready for planning: yes* diff --git a/gsd-memory/tests/fixtures/sample-summary.md b/gsd-memory/tests/fixtures/sample-summary.md deleted file mode 100644 index 54c26b2e8..000000000 --- a/gsd-memory/tests/fixtures/sample-summary.md +++ /dev/null @@ -1,121 +0,0 @@ ---- -phase: 01-foundation -plan: 01 -subsystem: auth -tags: [jwt, jose, prisma, bcrypt] - -requires: - - phase: none - provides: greenfield project - -provides: - - User model with email/password authentication - - JWT access/refresh token system - - Protected API middleware - -affects: [02-features, 03-dashboard] - -tech-stack: - added: - - jose: 5.2.0 - - bcrypt: 5.1.1 - - prisma: 5.10.0 - patterns: - - httpOnly cookies for tokens - - refresh token rotation - -key-files: - created: - - src/lib/auth.ts - - src/middleware.ts - - prisma/schema.prisma - modified: - - package.json - -key-decisions: - - "Used jose instead of jsonwebtoken for ESM and Edge compatibility" - - "15-min access tokens, 7-day refresh tokens for security/UX balance" - - "Database-stored refresh tokens enable revocation" - -patterns-established: - - "Token rotation: every refresh request issues new refresh token" - - "Protected routes: middleware checks JWT before handler" - - "Password hashing: bcrypt with 10 salt rounds" - -duration: 28min -completed: 2025-01-15 ---- - -# Phase 1: Foundation Summary - -**JWT auth with refresh rotation using jose library, Prisma User model, and protected API middleware** - -## Performance - -- **Duration:** 28 min -- **Started:** 2025-01-15T14:22:10Z -- **Completed:** 2025-01-15T14:50:33Z -- **Tasks:** 5 -- **Files modified:** 8 - -## Accomplishments -- User model with email/password auth -- Login/logout endpoints with httpOnly JWT cookies -- Protected route middleware checking token validity -- Refresh token rotation on each request - -## Task Commits - -Each task was committed atomically: - -1. **Task 1: Create User model** - `abc123f` (feat) -2. **Task 2: Login endpoint** - `def456g` (feat) -3. **Task 3: Logout endpoint** - `hij789k` (feat) -4. **Task 4: JWT helpers** - `lmn012o` (feat) -5. **Task 5: Protected middleware** - `pqr345s` (feat) - -**Plan metadata:** `tuv678w` (docs: complete plan) - -## Files Created/Modified -- `prisma/schema.prisma` - User and Session models -- `src/app/api/auth/login/route.ts` - Login endpoint -- `src/app/api/auth/logout/route.ts` - Logout endpoint -- `src/middleware.ts` - Protected route checks -- `src/lib/auth.ts` - JWT helpers using jose - -## Decisions Made -- Used jose instead of jsonwebtoken (ESM-native, Edge-compatible) -- 15-min access tokens with 7-day refresh tokens -- Storing refresh tokens in database for revocation capability - -## Deviations from Plan - -### Auto-fixed Issues - -**1. [Rule 2 - Missing Critical] Added password hashing with bcrypt** -- **Found during:** Task 2 (Login endpoint implementation) -- **Issue:** Plan didn't specify password hashing - storing plaintext would be critical security flaw -- **Fix:** Added bcrypt hashing on registration, comparison on login with salt rounds 10 -- **Files modified:** src/app/api/auth/login/route.ts, src/lib/auth.ts -- **Verification:** Password hash test passes, plaintext never stored -- **Committed in:** abc123f (Task 2 commit) - ---- - -**Total deviations:** 1 auto-fixed (1 missing critical) -**Impact on plan:** Auto-fix essential for security. No scope creep. - -## Issues Encountered -- jsonwebtoken CommonJS import failed in Edge runtime - switched to jose (planned library change, worked as expected) - -## User Setup Required - -None - no external service configuration required. - -## Next Phase Readiness -- Auth foundation complete, ready for feature development -- User registration endpoint needed before public launch - ---- -*Phase: 01-foundation* -*Completed: 2025-01-15* diff --git a/gsd-memory/tests/integration/end-to-end.test.ts b/gsd-memory/tests/integration/end-to-end.test.ts deleted file mode 100644 index 54e46ddd9..000000000 --- a/gsd-memory/tests/integration/end-to-end.test.ts +++ /dev/null @@ -1,476 +0,0 @@ -import { describe, it, expect, beforeAll, afterAll, beforeEach } from 'vitest'; -import * as fs from 'fs'; -import * as path from 'path'; -import * as os from 'os'; - -// Import tools directly for e2e testing -import { register, unregister } from '../../src/tools/register.js'; -import { index, indexAll } from '../../src/tools/index-tool.js'; -import { search } from '../../src/tools/search.js'; -import { findDecisions } from '../../src/tools/decisions.js'; -import { findPatterns } from '../../src/tools/patterns.js'; -import { findPitfalls } from '../../src/tools/pitfalls.js'; -import { findStack } from '../../src/tools/stack.js'; -import { getStatus } from '../../src/tools/status.js'; -import { getRegistry, saveRegistry, type ProjectRegistry } from '../../src/registry.js'; - -/** - * End-to-end integration tests - * - * These tests exercise the full workflow: - * 1. Register a project - * 2. Index its contents - * 3. Search and query across projects - * 4. Cross-project search - */ - -describe('End-to-end workflow', () => { - let project1Dir: string; - let project2Dir: string; - let originalRegistry: ProjectRegistry | null = null; - - beforeAll(async () => { - // Backup existing registry - try { - originalRegistry = await getRegistry(); - } catch { - originalRegistry = null; - } - - // Create project 1 - an auth service - project1Dir = path.join(os.tmpdir(), `gsd-e2e-project1-${Date.now()}`); - createTestProject(project1Dir, 'auth-service', { - phase: '01', - planSummary: { - phase: '01-auth', - plan: '01', - subsystem: 'authentication', - tags: ['auth', 'jwt', 'security'], - keyDecisions: ['Use JWT for stateless auth', 'Token expiry: 1 hour'], - patternsEstablished: ['Bearer token middleware', 'Refresh token rotation'], - techStack: [ - { name: 'jose', version: '5.2.0' }, - { name: 'bcrypt', version: '5.1.0' } - ] - }, - research: { - domain: 'authentication', - pitfalls: [ - { description: 'JWT secret in code', prevention: 'Use env vars' }, - { description: 'No token rotation', prevention: 'Implement refresh tokens' } - ], - standardStack: [ - { library: 'jose', version: '5.x', purpose: 'JWT signing' } - ] - }, - project: { - decisions: [ - { decision: 'Stateless auth with JWT', rationale: 'Horizontal scaling', outcome: 'Good' } - ] - } - }); - - // Create project 2 - an API gateway - project2Dir = path.join(os.tmpdir(), `gsd-e2e-project2-${Date.now()}`); - createTestProject(project2Dir, 'api-gateway', { - phase: '01', - planSummary: { - phase: '01-gateway', - plan: '01', - subsystem: 'gateway', - tags: ['api', 'routing', 'ratelimit'], - keyDecisions: ['Use express for routing', 'Redis for rate limiting'], - patternsEstablished: ['Route middleware chain', 'Error boundary pattern'], - techStack: [ - { name: 'express', version: '4.18.0' }, - { name: 'ioredis', version: '5.3.0' } - ] - }, - research: { - domain: 'api-design', - pitfalls: [ - { description: 'No rate limiting', prevention: 'Add Redis-based limiter' } - ], - standardStack: [ - { library: 'express', version: '4.x', purpose: 'HTTP server' } - ] - }, - project: { - decisions: [ - { decision: 'Express over Fastify', rationale: 'Team familiarity', outcome: 'Pending' } - ] - } - }); - }); - - afterAll(async () => { - // Cleanup projects - if (fs.existsSync(project1Dir)) { - fs.rmSync(project1Dir, { recursive: true }); - } - if (fs.existsSync(project2Dir)) { - fs.rmSync(project2Dir, { recursive: true }); - } - - // Restore original registry - if (originalRegistry) { - await saveRegistry(originalRegistry); - } - }); - - describe('Project registration', () => { - it('registers project 1', async () => { - const result = await register({ - path: project1Dir, - name: 'e2e-auth-service' - }); - - expect(result.success).toBe(true); - expect(result.project?.name).toBe('e2e-auth-service'); - }); - - it('registers project 2', async () => { - const result = await register({ - path: project2Dir, - name: 'e2e-api-gateway' - }); - - expect(result.success).toBe(true); - expect(result.project?.name).toBe('e2e-api-gateway'); - }); - - it('shows both projects in status', async () => { - const status = await getStatus(); - - expect(status.totalProjects).toBeGreaterThanOrEqual(2); - expect(status.projects.some((p) => p.name === 'e2e-auth-service')).toBe(true); - expect(status.projects.some((p) => p.name === 'e2e-api-gateway')).toBe(true); - }); - }); - - describe('Project indexing', () => { - it('indexes project 1', async () => { - const result = await index({ - project: 'e2e-auth-service' - }); - - expect(result.success).toBe(true); - }); - - it('indexes project 2', async () => { - const result = await index({ - project: 'e2e-api-gateway' - }); - - expect(result.success).toBe(true); - }); - - it('indexes all projects', async () => { - const result = await indexAll(); - - // indexAll returns success: true only if ALL projects succeed - // Since we may have stale projects from previous test runs, check results array - expect(result.results.length).toBeGreaterThanOrEqual(2); - // At least our 2 test projects should succeed - const successCount = result.results.filter(r => r.success).length; - expect(successCount).toBeGreaterThanOrEqual(2); - }); - }); - - describe('Search functionality', () => { - it('searches across all projects', async () => { - const results = await search({ - query: 'authentication' - }); - - expect(results.length).toBeGreaterThan(0); - // Should find matches in auth-service - expect(results.some(r => r.project === 'e2e-auth-service')).toBe(true); - }); - - it('filters search by project', async () => { - const results = await search({ - query: 'token', - project: 'e2e-auth-service' - }); - - expect(results.length).toBeGreaterThan(0); - // All results should be from auth-service - for (const r of results) { - expect(r.project).toBe('e2e-auth-service'); - } - }); - - it('respects limit parameter', async () => { - const results = await search({ - query: 'the', - limit: 3 - }); - - expect(results.length).toBeLessThanOrEqual(3); - }); - }); - - describe('Decision queries', () => { - it('finds decisions across projects', async () => { - const decisions = await findDecisions({}); - - expect(decisions.length).toBeGreaterThan(0); - - // Should find JWT decision from project 1 - const jwtDecision = decisions.find( - d => d.decision.toLowerCase().includes('jwt') - ); - expect(jwtDecision).toBeDefined(); - }); - - it('filters decisions by keyword', async () => { - const decisions = await findDecisions({ - query: 'express' - }); - - expect(decisions.length).toBeGreaterThan(0); - // All matching decisions should mention express - for (const d of decisions) { - expect( - d.decision.toLowerCase().includes('express') || - d.rationale?.toLowerCase().includes('express') - ).toBe(true); - } - }); - - it('filters decisions by project', async () => { - const decisions = await findDecisions({ - project: 'e2e-api-gateway' - }); - - // All decisions should be from api-gateway - for (const d of decisions) { - expect(d.project).toBe('e2e-api-gateway'); - } - }); - }); - - describe('Pattern queries', () => { - it('finds patterns across projects', async () => { - const patterns = await findPatterns({}); - - expect(patterns.length).toBeGreaterThan(0); - - // Should find bearer token pattern from project 1 - const bearerPattern = patterns.find( - p => p.pattern.toLowerCase().includes('bearer') || - p.pattern.toLowerCase().includes('token') - ); - expect(bearerPattern).toBeDefined(); - }); - - it('filters patterns by keyword', async () => { - const patterns = await findPatterns({ - query: 'middleware' - }); - - expect(patterns.length).toBeGreaterThan(0); - }); - }); - - describe('Pitfall queries', () => { - it('finds pitfalls across projects', async () => { - const pitfalls = await findPitfalls({}); - - // Pitfalls require XML-tagged sections in RESEARCH.md - // Our simple test fixtures don't have these, so we just verify the query works - expect(Array.isArray(pitfalls)).toBe(true); - }); - - it('filters pitfalls by domain', async () => { - const pitfalls = await findPitfalls({ - domain: 'authentication' - }); - - // All pitfalls should be from auth domain (if any found) - for (const p of pitfalls) { - expect(p.domain.toLowerCase()).toContain('auth'); - } - }); - }); - - describe('Tech stack queries', () => { - it('finds tech stack across projects', async () => { - const stack = await findStack({}); - - // Tech stack is extracted from SUMMARY.md tech-stack.added frontmatter - // and RESEARCH.md sections - expect(Array.isArray(stack)).toBe(true); - - // If we have stack entries, verify structure - if (stack.length > 0) { - expect(stack[0]).toHaveProperty('library'); - expect(stack[0]).toHaveProperty('project'); - } - }); - - it('filters stack by library name', async () => { - const stack = await findStack({ - query: 'jose' - }); - - // All results should match the query - for (const s of stack) { - expect( - s.library.toLowerCase().includes('jose') || - s.purpose?.toLowerCase().includes('jose') - ).toBe(true); - } - }); - }); - - describe('Cross-project search', () => { - it('returns results from multiple projects', async () => { - // Search for something that exists in both projects - const results = await search({ - query: 'version' - }); - - const projectsFound = new Set(results.map(r => r.project)); - expect(projectsFound.size).toBeGreaterThanOrEqual(2); - }); - - it('includes project context in results', async () => { - const results = await search({ - query: 'token' - }); - - for (const r of results) { - expect(r.project).toBeDefined(); - expect(r.source).toBeDefined(); - } - }); - }); - - describe('Project unregistration', () => { - it('unregisters a project', async () => { - // Register a temp project to unregister - const tempDir = path.join(os.tmpdir(), `gsd-e2e-temp-${Date.now()}`); - createTestProject(tempDir, 'temp-project', { - phase: '01', - planSummary: { - phase: '01-temp', - plan: '01', - subsystem: 'temp', - tags: ['temp'], - keyDecisions: [], - patternsEstablished: [], - techStack: [] - }, - research: { - domain: 'temp', - pitfalls: [], - standardStack: [] - }, - project: { decisions: [] } - }); - - await register({ path: tempDir, name: 'e2e-temp' }); - - const result = await unregister('e2e-temp'); - expect(result.success).toBe(true); - - // Verify removed from status - const status = await getStatus(); - expect(status.projects.some((p) => p.name === 'e2e-temp')).toBe(false); - - // Cleanup - fs.rmSync(tempDir, { recursive: true }); - }); - }); -}); - -// Helper function to create test project structure -interface TestProjectOptions { - phase: string; - planSummary: { - phase: string; - plan: string; - subsystem: string; - tags: string[]; - keyDecisions: string[]; - patternsEstablished: string[]; - techStack: Array<{ name: string; version: string }>; - }; - research: { - domain: string; - pitfalls: Array<{ description: string; prevention: string }>; - standardStack: Array<{ library: string; version: string; purpose: string }>; - }; - project: { - decisions: Array<{ decision: string; rationale: string; outcome: string }>; - }; -} - -function createTestProject(dir: string, name: string, opts: TestProjectOptions): void { - const planningDir = path.join(dir, '.planning'); - const phasesDir = path.join(planningDir, 'phases', `${opts.phase}-${name}`); - fs.mkdirSync(phasesDir, { recursive: true }); - - // Create PROJECT.md - let projectMd = `# ${name}\n\n## Key Decisions\n\n| Decision | Rationale | Outcome |\n|----------|-----------|---------|`; - for (const d of opts.project.decisions) { - projectMd += `\n| ${d.decision} | ${d.rationale} | ${d.outcome} |`; - } - fs.writeFileSync(path.join(planningDir, 'PROJECT.md'), projectMd); - - // Create SUMMARY.md - const techStackYaml = opts.planSummary.techStack.map(t => ` ${t.name}: "${t.version}"`).join('\n'); - const summaryMd = `--- -phase: ${opts.planSummary.phase} -plan: ${opts.planSummary.plan} -subsystem: ${opts.planSummary.subsystem} -tags: -${opts.planSummary.tags.map(t => ` - ${t}`).join('\n')} -key-decisions: -${opts.planSummary.keyDecisions.map(d => ` - ${d}`).join('\n')} -patterns-established: -${opts.planSummary.patternsEstablished.map(p => ` - ${p}`).join('\n')} -tech-stack: - added: -${techStackYaml} ---- -# Phase Summary - -Implementation summary for ${name}. -`; - fs.writeFileSync(path.join(phasesDir, `${opts.phase}-01-SUMMARY.md`), summaryMd); - - // Create RESEARCH.md - let pitfallsSection = ''; - if (opts.research.pitfalls.length > 0) { - pitfallsSection = '\n## Pitfalls\n\n'; - for (const p of opts.research.pitfalls) { - pitfallsSection += `### ${p.description}\n\n**Prevention:** ${p.prevention}\n\n`; - } - } - - let stackTable = ''; - if (opts.research.standardStack.length > 0) { - stackTable = '\n## Standard Stack\n\n| Library | Version | Purpose |\n|---------|---------|---------|'; - for (const s of opts.research.standardStack) { - stackTable += `\n| ${s.library} | ${s.version} | ${s.purpose} |`; - } - } - - const researchMd = `--- -domain: ${opts.research.domain} -confidence: high ---- -# Research for ${name} -${pitfallsSection}${stackTable} -`; - fs.writeFileSync(path.join(phasesDir, `${opts.phase}-RESEARCH.md`), researchMd); - - // Create config.json - fs.writeFileSync( - path.join(planningDir, 'config.json'), - JSON.stringify({ project: name }, null, 2) - ); -} diff --git a/gsd-memory/tests/integration/mcp-server.test.ts b/gsd-memory/tests/integration/mcp-server.test.ts deleted file mode 100644 index 69f7e1e9c..000000000 --- a/gsd-memory/tests/integration/mcp-server.test.ts +++ /dev/null @@ -1,359 +0,0 @@ -import { describe, it, expect, beforeAll, afterAll } from 'vitest'; -import { spawn, ChildProcess } from 'child_process'; -import * as path from 'path'; -import * as fs from 'fs'; -import * as os from 'os'; - -/** - * Integration tests for the MCP server - * - * These tests spawn the actual MCP server and communicate with it - * via the MCP protocol over stdio. - */ - -interface McpMessage { - jsonrpc: '2.0'; - id?: number; - method?: string; - params?: Record; - result?: unknown; - error?: { code: number; message: string }; -} - -class McpClient { - private serverProcess: ChildProcess | null = null; - private buffer = ''; - private pendingRequests: Map void; reject: (err: Error) => void }> = new Map(); - private nextId = 1; - - async start(): Promise { - const serverPath = path.join(__dirname, '../../dist/index.js'); - - // Check if built - if (!fs.existsSync(serverPath)) { - throw new Error('Server not built. Run npm run build first.'); - } - - this.serverProcess = spawn('node', [serverPath], { - stdio: ['pipe', 'pipe', 'pipe'] - }); - - this.serverProcess.stdout?.on('data', (data: Buffer) => { - this.buffer += data.toString(); - this.processBuffer(); - }); - - this.serverProcess.stderr?.on('data', (data: Buffer) => { - // Server logs to stderr, ignore for tests - }); - - // Wait for server to start - await new Promise(resolve => setTimeout(resolve, 500)); - } - - private processBuffer(): void { - const lines = this.buffer.split('\n'); - this.buffer = lines.pop() || ''; - - for (const line of lines) { - if (line.trim()) { - try { - const message: McpMessage = JSON.parse(line); - if (message.id !== undefined) { - const pending = this.pendingRequests.get(message.id); - if (pending) { - this.pendingRequests.delete(message.id); - if (message.error) { - pending.reject(new Error(message.error.message)); - } else { - pending.resolve(message.result); - } - } - } - } catch { - // Ignore non-JSON lines - } - } - } - } - - async sendRequest(method: string, params?: Record): Promise { - if (!this.serverProcess) { - throw new Error('Server not started'); - } - - const id = this.nextId++; - const message: McpMessage = { - jsonrpc: '2.0', - id, - method, - params - }; - - return new Promise((resolve, reject) => { - this.pendingRequests.set(id, { resolve, reject }); - this.serverProcess!.stdin?.write(JSON.stringify(message) + '\n'); - - // Timeout after 5 seconds - setTimeout(() => { - if (this.pendingRequests.has(id)) { - this.pendingRequests.delete(id); - reject(new Error('Request timeout')); - } - }, 5000); - }); - } - - async listTools(): Promise<{ tools: Array<{ name: string; description: string }> }> { - const result = await this.sendRequest('tools/list'); - return result as { tools: Array<{ name: string; description: string }> }; - } - - async callTool(name: string, args: Record): Promise<{ content: Array<{ type: string; text: string }> }> { - const result = await this.sendRequest('tools/call', { - name, - arguments: args - }); - return result as { content: Array<{ type: string; text: string }> }; - } - - stop(): void { - if (this.serverProcess) { - this.serverProcess.kill(); - this.serverProcess = null; - } - } -} - -describe('MCP server integration', () => { - let client: McpClient; - let testProjectDir: string; - - beforeAll(async () => { - // Create test project directory - testProjectDir = path.join(os.tmpdir(), `gsd-mcp-test-${Date.now()}`); - fs.mkdirSync(path.join(testProjectDir, '.planning', 'phases', '01-test'), { recursive: true }); - fs.writeFileSync( - path.join(testProjectDir, '.planning', 'PROJECT.md'), - `# Test Project - -## Key Decisions - -| Decision | Rationale | Outcome | -|----------|-----------|---------| -| Use TypeScript | Type safety | Good | -` - ); - fs.writeFileSync( - path.join(testProjectDir, '.planning', 'phases', '01-test', '01-01-SUMMARY.md'), - `--- -phase: 01-test -plan: 01 -subsystem: core -tags: - - testing - - integration -key-decisions: - - Use vitest for testing -patterns-established: - - TDD workflow -tech-stack: - added: - - vitest: 1.0.0 ---- -# Plan Summary - -Implemented testing infrastructure. -` - ); - - // Try to start client - may fail if not built - try { - client = new McpClient(); - await client.start(); - } catch (err) { - // Will handle in individual tests - } - }); - - afterAll(() => { - if (client) { - client.stop(); - } - if (fs.existsSync(testProjectDir)) { - fs.rmSync(testProjectDir, { recursive: true }); - } - }); - - describe('tool listing', () => { - it('lists all GSD memory tools', async () => { - if (!client) { - // Server not built, skip test - console.log('Skipping: server not built'); - return; - } - - const { tools } = await client.listTools(); - const toolNames = tools.map(t => t.name); - - expect(toolNames).toContain('gsd_memory_search'); - expect(toolNames).toContain('gsd_memory_decisions'); - expect(toolNames).toContain('gsd_memory_patterns'); - expect(toolNames).toContain('gsd_memory_pitfalls'); - expect(toolNames).toContain('gsd_memory_stack'); - expect(toolNames).toContain('gsd_memory_register'); - expect(toolNames).toContain('gsd_memory_index'); - expect(toolNames).toContain('gsd_memory_status'); - }); - - it('returns tool descriptions', async () => { - if (!client) return; - - const { tools } = await client.listTools(); - - for (const tool of tools) { - expect(tool.description).toBeTruthy(); - expect(typeof tool.description).toBe('string'); - } - }); - }); - - describe('status tool', () => { - it('returns status information', async () => { - if (!client) return; - - const result = await client.callTool('gsd_memory_status', {}); - expect(result.content).toBeDefined(); - expect(result.content[0].type).toBe('text'); - - const status = JSON.parse(result.content[0].text); - expect(status).toHaveProperty('qmdAvailable'); - expect(status).toHaveProperty('totalProjects'); - expect(status).toHaveProperty('projects'); - }); - }); - - describe('register tool', () => { - it('registers a project successfully', async () => { - if (!client) return; - - const result = await client.callTool('gsd_memory_register', { - path: testProjectDir, - name: 'mcp-test-project' - }); - - expect(result.content).toBeDefined(); - const response = JSON.parse(result.content[0].text); - expect(response.success).toBe(true); - }); - - it('fails gracefully for non-existent path', async () => { - if (!client) return; - - const result = await client.callTool('gsd_memory_register', { - path: '/nonexistent/path', - name: 'bad-project' - }); - - const response = JSON.parse(result.content[0].text); - expect(response.success).toBe(false); - }); - }); - - describe('search tool', () => { - it('searches across registered projects', async () => { - if (!client) return; - - // Register first - await client.callTool('gsd_memory_register', { - path: testProjectDir, - name: 'search-test-project' - }); - - const result = await client.callTool('gsd_memory_search', { - query: 'testing' - }); - - expect(result.content).toBeDefined(); - const response = JSON.parse(result.content[0].text); - // search returns an array directly - expect(Array.isArray(response)).toBe(true); - }); - - it('filters by project', async () => { - if (!client) return; - - const result = await client.callTool('gsd_memory_search', { - query: 'test', - project: 'search-test-project' - }); - - expect(result.content).toBeDefined(); - const response = JSON.parse(result.content[0].text); - expect(Array.isArray(response)).toBe(true); - }); - }); - - describe('decisions tool', () => { - it('finds decisions from registered projects', async () => { - if (!client) return; - - const result = await client.callTool('gsd_memory_decisions', {}); - - expect(result.content).toBeDefined(); - const response = JSON.parse(result.content[0].text); - // findDecisions returns an array directly - expect(Array.isArray(response)).toBe(true); - }); - }); - - describe('patterns tool', () => { - it('finds patterns from registered projects', async () => { - if (!client) return; - - const result = await client.callTool('gsd_memory_patterns', {}); - - expect(result.content).toBeDefined(); - const response = JSON.parse(result.content[0].text); - // findPatterns returns an array directly - expect(Array.isArray(response)).toBe(true); - }); - }); - - describe('stack tool', () => { - it('finds tech stack entries', async () => { - if (!client) return; - - const result = await client.callTool('gsd_memory_stack', {}); - - expect(result.content).toBeDefined(); - const response = JSON.parse(result.content[0].text); - // findStack returns an array directly - expect(Array.isArray(response)).toBe(true); - }); - }); - - describe('error handling', () => { - it('handles unknown tool gracefully', async () => { - if (!client) return; - - try { - await client.callTool('nonexistent_tool', {}); - expect.fail('Should have thrown'); - } catch (err) { - expect(err).toBeDefined(); - } - }); - - it('handles missing required parameters', async () => { - if (!client) return; - - const result = await client.callTool('gsd_memory_register', { - // Missing required 'path' parameter - }); - - const response = JSON.parse(result.content[0].text); - expect(response.success).toBe(false); - }); - }); -}); diff --git a/gsd-memory/tests/integration/qmd-wrapper.test.ts b/gsd-memory/tests/integration/qmd-wrapper.test.ts deleted file mode 100644 index d58d7ce4b..000000000 --- a/gsd-memory/tests/integration/qmd-wrapper.test.ts +++ /dev/null @@ -1,265 +0,0 @@ -import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; -import { qmd } from '../../src/qmd.js'; -import { execSync } from 'child_process'; -import * as fs from 'fs'; -import * as path from 'path'; -import * as os from 'os'; - -describe('QMD wrapper integration', () => { - let testDir: string; - let originalIsAvailable: typeof qmd.isAvailable; - - beforeEach(() => { - // Create temp test directory with some markdown files - testDir = path.join(os.tmpdir(), `gsd-qmd-test-${Date.now()}`); - fs.mkdirSync(testDir, { recursive: true }); - - // Create test markdown files - fs.writeFileSync( - path.join(testDir, 'test1.md'), - `--- -phase: 01 -tags: [auth, jwt] ---- -# Authentication Module - -This module handles JWT authentication and session management. -We use jose for token signing and verification. -` - ); - - fs.writeFileSync( - path.join(testDir, 'test2.md'), - `--- -phase: 02 -tags: [api, rest] ---- -# API Layer - -RESTful API endpoints for user management. -Authentication is required for all protected routes. -` - ); - - fs.writeFileSync( - path.join(testDir, 'test3.md'), - `# Unrelated Content - -This file contains unrelated content about database migrations. -` - ); - - originalIsAvailable = qmd.isAvailable.bind(qmd); - }); - - afterEach(() => { - // Cleanup - if (fs.existsSync(testDir)) { - fs.rmSync(testDir, { recursive: true }); - } - qmd.isAvailable = originalIsAvailable; - }); - - describe('isAvailable', () => { - it('returns boolean indicating QMD availability', async () => { - const available = await qmd.isAvailable(); - expect(typeof available).toBe('boolean'); - }); - }); - - describe('findMarkdownFiles', () => { - it('finds all markdown files recursively', () => { - const files = qmd.findMarkdownFiles(testDir); - expect(files.length).toBe(3); - expect(files.some(f => f.endsWith('test1.md'))).toBe(true); - expect(files.some(f => f.endsWith('test2.md'))).toBe(true); - expect(files.some(f => f.endsWith('test3.md'))).toBe(true); - }); - - it('excludes node_modules and hidden directories', () => { - // Create node_modules with markdown - const nmDir = path.join(testDir, 'node_modules'); - fs.mkdirSync(nmDir, { recursive: true }); - fs.writeFileSync(path.join(nmDir, 'package.md'), '# Package'); - - // Create hidden directory with markdown - const hiddenDir = path.join(testDir, '.hidden'); - fs.mkdirSync(hiddenDir, { recursive: true }); - fs.writeFileSync(path.join(hiddenDir, 'secret.md'), '# Secret'); - - const files = qmd.findMarkdownFiles(testDir); - expect(files.some(f => f.includes('node_modules'))).toBe(false); - expect(files.some(f => f.includes('.hidden'))).toBe(false); - }); - - it('handles nested directories', () => { - const nestedDir = path.join(testDir, 'docs', 'api'); - fs.mkdirSync(nestedDir, { recursive: true }); - fs.writeFileSync(path.join(nestedDir, 'nested.md'), '# Nested'); - - const files = qmd.findMarkdownFiles(testDir); - expect(files.some(f => f.endsWith('nested.md'))).toBe(true); - }); - - it('returns empty array for non-existent directory', () => { - const files = qmd.findMarkdownFiles('/nonexistent/path'); - expect(files).toEqual([]); - }); - }); - - describe('grepFallback', () => { - it('finds content matching query', async () => { - const results = await qmd.grepFallback({ - query: 'authentication', - paths: [testDir], - limit: 10 - }); - - expect(results.length).toBeGreaterThan(0); - expect(results.some(r => r.source.includes('test1.md'))).toBe(true); - expect(results.some(r => r.source.includes('test2.md'))).toBe(true); - }); - - it('returns results with relevance scores', async () => { - const results = await qmd.grepFallback({ - query: 'jwt', - paths: [testDir] - }); - - expect(results.length).toBeGreaterThan(0); - for (const result of results) { - expect(result).toHaveProperty('relevance'); - expect(typeof result.relevance).toBe('number'); - expect(result.relevance).toBeGreaterThanOrEqual(0); - expect(result.relevance).toBeLessThanOrEqual(1); - } - }); - - it('returns content snippets around matches', async () => { - const results = await qmd.grepFallback({ - query: 'jwt', - paths: [testDir] - }); - - expect(results.length).toBeGreaterThan(0); - for (const result of results) { - expect(result).toHaveProperty('content'); - expect(result.content.toLowerCase()).toContain('jwt'); - } - }); - - it('respects limit parameter', async () => { - const results = await qmd.grepFallback({ - query: 'the', // Common word - paths: [testDir], - limit: 2 - }); - - expect(results.length).toBeLessThanOrEqual(2); - }); - - it('sorts results by relevance', async () => { - const results = await qmd.grepFallback({ - query: 'authentication', - paths: [testDir] - }); - - if (results.length > 1) { - for (let i = 1; i < results.length; i++) { - expect(results[i - 1].relevance).toBeGreaterThanOrEqual(results[i].relevance); - } - } - }); - - it('case insensitive search', async () => { - const results = await qmd.grepFallback({ - query: 'JWT', // Uppercase - paths: [testDir] - }); - - expect(results.length).toBeGreaterThan(0); - expect(results.some(r => r.source.includes('test1.md'))).toBe(true); - }); - - it('returns empty array for no matches', async () => { - const results = await qmd.grepFallback({ - query: 'xyznonexistent123', - paths: [testDir] - }); - - expect(results).toEqual([]); - }); - - it('marks context as grep', async () => { - const results = await qmd.grepFallback({ - query: 'authentication', - paths: [testDir] - }); - - for (const result of results) { - expect(result.context).toBe('grep'); - } - }); - }); - - describe('search (integration)', () => { - it('uses grep fallback when QMD unavailable', async () => { - // Force QMD unavailable - vi.spyOn(qmd, 'isAvailable').mockResolvedValue(false); - - const results = await qmd.search({ - query: 'authentication', - paths: [testDir] - }); - - expect(results.length).toBeGreaterThan(0); - expect(results[0].context).toBe('grep'); - }); - - it('uses grep fallback when no collection specified', async () => { - const results = await qmd.search({ - query: 'authentication', - paths: [testDir] - // No collection specified - }); - - expect(results.length).toBeGreaterThan(0); - expect(results[0].context).toBe('grep'); - }); - }); - - describe('createCollection', () => { - it('returns graceful error when QMD unavailable', async () => { - vi.spyOn(qmd, 'isAvailable').mockResolvedValue(false); - - const result = await qmd.createCollection({ - name: 'test-collection', - paths: [testDir] - }); - - expect(result.success).toBe(false); - expect(result.reason).toBe('qmd_not_available'); - }); - }); - - describe('index', () => { - it('returns graceful error when QMD unavailable', async () => { - vi.spyOn(qmd, 'isAvailable').mockResolvedValue(false); - - const result = await qmd.index('test-collection'); - - expect(result.success).toBe(false); - expect(result.reason).toBe('qmd_not_available'); - }); - }); - - describe('status', () => { - it('returns available: false when QMD unavailable', async () => { - vi.spyOn(qmd, 'isAvailable').mockResolvedValue(false); - - const result = await qmd.status('test-collection'); - - expect(result.available).toBe(false); - }); - }); -}); diff --git a/gsd-memory/tests/qmd-wrapper.test.ts b/gsd-memory/tests/qmd-wrapper.test.ts deleted file mode 100644 index 3389ce64f..000000000 --- a/gsd-memory/tests/qmd-wrapper.test.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; -import { qmd, QmdSearchResult } from '../src/qmd.js'; - -describe('QMD wrapper', () => { - describe('isAvailable', () => { - it('returns boolean indicating QMD availability', async () => { - const available = await qmd.isAvailable(); - expect(typeof available).toBe('boolean'); - }); - }); - - describe('when QMD is available', () => { - // These tests only run if QMD is actually installed - it.skipIf(async () => !(await qmd.isAvailable()))('can check status', async () => { - const available = await qmd.isAvailable(); - if (!available) return; - - // Just verify the method doesn't throw - expect(qmd.isAvailable).toBeDefined(); - }); - }); - - describe('when QMD is not available', () => { - let originalIsAvailable: typeof qmd.isAvailable; - - beforeEach(() => { - originalIsAvailable = qmd.isAvailable; - qmd.isAvailable = vi.fn().mockResolvedValue(false); - }); - - afterEach(() => { - qmd.isAvailable = originalIsAvailable; - }); - - it('search falls back to grep-based results', async () => { - const results = await qmd.search({ - query: 'authentication', - paths: ['/nonexistent/path'] - }); - - // Should return empty array without QMD, not throw - expect(Array.isArray(results)).toBe(true); - }); - - it('createCollection returns graceful error', async () => { - const result = await qmd.createCollection({ - name: 'test-project', - paths: ['/tmp/test-project/.planning'], - context: 'GSD project' - }); - - expect(result.success).toBe(false); - expect(result.reason).toBe('qmd_not_available'); - }); - - it('index returns graceful error', async () => { - const result = await qmd.index('test-project'); - - expect(result.success).toBe(false); - expect(result.reason).toBe('qmd_not_available'); - }); - - it('status returns unavailable state', async () => { - const status = await qmd.status('test-project'); - - expect(status.available).toBe(false); - }); - }); - - describe('grep fallback', () => { - it('searches files with grep when QMD unavailable', async () => { - // Force fallback mode - const originalIsAvailable = qmd.isAvailable; - qmd.isAvailable = vi.fn().mockResolvedValue(false); - - try { - const results = await qmd.grepFallback({ - query: 'phase', - paths: [process.cwd() + '/tests/fixtures'] - }); - - // Should find matches in our fixture files - expect(Array.isArray(results)).toBe(true); - // Fixtures contain 'phase' - expect(results.length).toBeGreaterThan(0); - } finally { - qmd.isAvailable = originalIsAvailable; - } - }); - - it('grep fallback returns structured results', async () => { - const results = await qmd.grepFallback({ - query: 'JWT', - paths: [process.cwd() + '/tests/fixtures'] - }); - - if (results.length > 0) { - expect(results[0]).toHaveProperty('content'); - expect(results[0]).toHaveProperty('source'); - expect(results[0]).toHaveProperty('relevance'); - } - }); - }); -}); diff --git a/gsd-memory/tests/setup.ts b/gsd-memory/tests/setup.ts deleted file mode 100644 index 3561a8360..000000000 --- a/gsd-memory/tests/setup.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { readFileSync } from 'fs'; -import { join, dirname } from 'path'; -import { fileURLToPath } from 'url'; - -const __dirname = dirname(fileURLToPath(import.meta.url)); - -/** - * Read a test fixture file - */ -export function readFixture(filename: string): string { - const fixturePath = join(__dirname, 'fixtures', filename); - return readFileSync(fixturePath, 'utf-8'); -} - -/** - * Get the path to the mock planning directory - */ -export function getMockPlanningPath(): string { - return join(__dirname, 'fixtures', 'mock-planning'); -} - -/** - * Get path to a specific fixture file - */ -export function getFixturePath(filename: string): string { - return join(__dirname, 'fixtures', filename); -} diff --git a/gsd-memory/tests/tools/decisions.test.ts b/gsd-memory/tests/tools/decisions.test.ts deleted file mode 100644 index ccb90442e..000000000 --- a/gsd-memory/tests/tools/decisions.test.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; -import { findDecisions } from '../../src/tools/decisions.js'; -import * as registry from '../../src/registry.js'; -import { getFixturePath } from '../setup.js'; -import { join, dirname } from 'path'; - -describe('decisions tool', () => { - const fixturesDir = dirname(getFixturePath('sample-project.md')); - - beforeEach(() => { - // Mock getAllProjects to return our test fixture location - vi.spyOn(registry, 'getAllProjects').mockReturnValue([ - { - name: 'fixture-project', - path: fixturesDir, - registeredAt: new Date().toISOString() - } - ]); - }); - - afterEach(() => { - vi.restoreAllMocks(); - }); - - it('returns decisions with full context', async () => { - const results = await findDecisions({}); - - // Should find decisions from sample-project.md fixture - expect(Array.isArray(results)).toBe(true); - }); - - it('extracts decisions from PROJECT.md', async () => { - // Create a mock project with PROJECT.md in .planning - vi.spyOn(registry, 'getAllProjects').mockReturnValue([ - { - name: 'mock-project', - path: join(fixturesDir, 'mock-planning'), - registeredAt: new Date().toISOString() - } - ]); - - const results = await findDecisions({}); - - // Should find decisions from mock-planning/PROJECT.md - if (results.length > 0) { - expect(results[0]).toHaveProperty('decision'); - expect(results[0]).toHaveProperty('project'); - } - }); - - it('filters by query', async () => { - vi.spyOn(registry, 'getAllProjects').mockReturnValue([ - { - name: 'mock-project', - path: join(fixturesDir, 'mock-planning'), - registeredAt: new Date().toISOString() - } - ]); - - const results = await findDecisions({ - query: 'YAML' - }); - - // All results should contain the query term - results.forEach(r => { - const hasQuery = r.decision.toLowerCase().includes('yaml') || - r.rationale?.toLowerCase().includes('yaml'); - expect(hasQuery).toBe(true); - }); - }); - - it('respects limit parameter', async () => { - const results = await findDecisions({ - limit: 1 - }); - - expect(results.length).toBeLessThanOrEqual(1); - }); - - it('returns empty array for non-existent project', async () => { - const results = await findDecisions({ - project: 'non-existent-project' - }); - - expect(results).toEqual([]); - }); -}); diff --git a/gsd-memory/tests/tools/register.test.ts b/gsd-memory/tests/tools/register.test.ts deleted file mode 100644 index 0a264d8ca..000000000 --- a/gsd-memory/tests/tools/register.test.ts +++ /dev/null @@ -1,142 +0,0 @@ -import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; -import { register, status, unregister } from '../../src/tools/register.js'; -import * as registryModule from '../../src/registry.js'; -import { qmd } from '../../src/qmd.js'; -import { getMockPlanningPath, getFixturePath } from '../setup.js'; -import { join, dirname } from 'path'; - -describe('register tool', () => { - const fixturesDir = dirname(getFixturePath('sample-project.md')); - const mockProjectDir = join(fixturesDir, 'mock-project'); // Has .planning subdirectory - - beforeEach(() => { - // Mock QMD as unavailable for consistent tests - vi.spyOn(qmd, 'isAvailable').mockResolvedValue(false); - }); - - afterEach(() => { - vi.restoreAllMocks(); - }); - - it('registers project in registry', async () => { - const mockRegister = vi.spyOn(registryModule, 'registerProject').mockReturnValue({ - name: 'test-project', - path: mockProjectDir, - registeredAt: new Date().toISOString() - }); - - const result = await register({ - path: mockProjectDir, - name: 'test-project' - }); - - expect(result.success).toBe(true); - expect(result.project?.name).toBe('test-project'); - expect(mockRegister).toHaveBeenCalled(); - }); - - it('fails for non-existent path', async () => { - const result = await register({ - path: '/nonexistent/path', - name: 'test-project' - }); - - expect(result.success).toBe(false); - expect(result.error).toContain('does not exist'); - }); - - it('fails for path without .planning directory', async () => { - // Use fixtures directory which has no .planning at root level - const result = await register({ - path: fixturesDir, - name: 'test-project' - }); - - expect(result.success).toBe(false); - expect(result.error).toContain('.planning'); - }); - - it('creates QMD collection if QMD available', async () => { - vi.spyOn(qmd, 'isAvailable').mockResolvedValue(true); - const mockCreateCollection = vi.spyOn(qmd, 'createCollection').mockResolvedValue({ - success: true - }); - - vi.spyOn(registryModule, 'registerProject').mockReturnValue({ - name: 'test-project', - path: mockProjectDir, - qmdCollection: 'gsd-test-project', - registeredAt: new Date().toISOString() - }); - - const result = await register({ - path: mockProjectDir, - name: 'test-project' - }); - - expect(result.success).toBe(true); - expect(mockCreateCollection).toHaveBeenCalled(); - }); -}); - -describe('status tool', () => { - beforeEach(() => { - vi.spyOn(qmd, 'isAvailable').mockResolvedValue(false); - vi.spyOn(registryModule, 'getAllProjects').mockReturnValue([ - { - name: 'project-1', - path: '/path/to/project1', - registeredAt: '2025-01-15T00:00:00Z' - } - ]); - }); - - afterEach(() => { - vi.restoreAllMocks(); - }); - - it('returns QMD availability and project list', async () => { - const result = await status(); - - expect(result).toHaveProperty('qmdAvailable'); - expect(result).toHaveProperty('projects'); - expect(Array.isArray(result.projects)).toBe(true); - }); - - it('includes project details', async () => { - const result = await status(); - - expect(result.projects.length).toBe(1); - expect(result.projects[0].name).toBe('project-1'); - expect(result.projects[0].path).toBe('/path/to/project1'); - }); -}); - -describe('unregister tool', () => { - afterEach(() => { - vi.restoreAllMocks(); - }); - - it('removes project from registry', async () => { - vi.spyOn(registryModule, 'getProject').mockReturnValue({ - name: 'test-project', - path: '/path/to/project', - registeredAt: '2025-01-15T00:00:00Z' - }); - const mockUnregister = vi.spyOn(registryModule, 'unregisterProject').mockReturnValue(true); - - const result = await unregister('test-project'); - - expect(result.success).toBe(true); - expect(mockUnregister).toHaveBeenCalledWith('test-project'); - }); - - it('returns error for non-existent project', async () => { - vi.spyOn(registryModule, 'getProject').mockReturnValue(undefined); - - const result = await unregister('non-existent'); - - expect(result.success).toBe(false); - expect(result.error).toContain('not found'); - }); -}); diff --git a/gsd-memory/tests/tools/search.test.ts b/gsd-memory/tests/tools/search.test.ts deleted file mode 100644 index 45988121a..000000000 --- a/gsd-memory/tests/tools/search.test.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; -import { search } from '../../src/tools/search.js'; -import * as registry from '../../src/registry.js'; -import { getMockPlanningPath } from '../setup.js'; - -describe('search tool', () => { - beforeEach(() => { - // Mock getAllProjects to return our test fixture - vi.spyOn(registry, 'getAllProjects').mockReturnValue([ - { - name: 'test-project', - path: getMockPlanningPath().replace('/.planning', '').replace('/mock-planning', '/mock-planning'), - registeredAt: new Date().toISOString() - } - ]); - }); - - afterEach(() => { - vi.restoreAllMocks(); - }); - - it('returns enriched results with GSD context', async () => { - // Note: This test may return empty if mock-planning structure doesn't match expectations - // The path needs to point to a directory containing .planning - const results = await search({ - query: 'test' - }); - - // With mocked registry pointing to fixtures, should return results - expect(Array.isArray(results)).toBe(true); - }); - - it('returns results with required fields', async () => { - const results = await search({ - query: 'phase' - }); - - if (results.length > 0) { - expect(results[0]).toHaveProperty('content'); - expect(results[0]).toHaveProperty('source'); - expect(results[0]).toHaveProperty('project'); - expect(results[0]).toHaveProperty('relevance'); - } - }); - - it('filters by project when specified', async () => { - const results = await search({ - query: 'test', - project: 'test-project' - }); - - // All results should be from specified project - results.forEach(r => { - expect(r.project).toBe('test-project'); - }); - }); - - it('respects limit parameter', async () => { - const results = await search({ - query: 'the', - limit: 2 - }); - - expect(results.length).toBeLessThanOrEqual(2); - }); - - it('returns empty array for non-existent project', async () => { - const results = await search({ - query: 'test', - project: 'non-existent-project' - }); - - expect(results).toEqual([]); - }); -}); diff --git a/gsd-memory/tsconfig.json b/gsd-memory/tsconfig.json deleted file mode 100644 index 837faa33c..000000000 --- a/gsd-memory/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "module": "NodeNext", - "moduleResolution": "NodeNext", - "lib": ["ES2022"], - "outDir": "./dist", - "rootDir": "./src", - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "declaration": true, - "declarationMap": true, - "sourceMap": true, - "resolveJsonModule": true - }, - "include": ["src/**/*"], - "exclude": ["node_modules", "dist", "tests"] -} diff --git a/gsd-memory/vitest.config.ts b/gsd-memory/vitest.config.ts deleted file mode 100644 index 810da8f8d..000000000 --- a/gsd-memory/vitest.config.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { defineConfig } from 'vitest/config'; - -export default defineConfig({ - test: { - globals: true, - environment: 'node', - include: ['tests/**/*.test.ts'], - exclude: ['tests/integration/**'], - coverage: { - provider: 'v8', - reporter: ['text', 'json', 'html'], - include: ['src/**/*.ts'], - exclude: ['src/index.ts'] - } - } -}); diff --git a/gsd-memory/vitest.integration.config.ts b/gsd-memory/vitest.integration.config.ts deleted file mode 100644 index 3e24f3aa7..000000000 --- a/gsd-memory/vitest.integration.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { defineConfig } from 'vitest/config'; - -export default defineConfig({ - test: { - globals: true, - environment: 'node', - include: ['tests/integration/**/*.test.ts'], - testTimeout: 30000 - } -});