#
tokens: 47042/50000 10/274 files (page 7/29)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 7 of 29. Use http://codebase.md/tosin2013/documcp?lines=true&page={x} to view the full context.

# Directory Structure

```
├── .dockerignore
├── .eslintignore
├── .eslintrc.json
├── .github
│   ├── agents
│   │   ├── documcp-ast.md
│   │   ├── documcp-deploy.md
│   │   ├── documcp-memory.md
│   │   ├── documcp-test.md
│   │   └── documcp-tool.md
│   ├── copilot-instructions.md
│   ├── dependabot.yml
│   ├── ISSUE_TEMPLATE
│   │   ├── automated-changelog.md
│   │   ├── bug_report.md
│   │   ├── bug_report.yml
│   │   ├── documentation_issue.md
│   │   ├── feature_request.md
│   │   ├── feature_request.yml
│   │   ├── npm-publishing-fix.md
│   │   └── release_improvements.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── release-drafter.yml
│   └── workflows
│       ├── auto-merge.yml
│       ├── ci.yml
│       ├── codeql.yml
│       ├── dependency-review.yml
│       ├── deploy-docs.yml
│       ├── README.md
│       ├── release-drafter.yml
│       └── release.yml
├── .gitignore
├── .husky
│   ├── commit-msg
│   └── pre-commit
├── .linkcheck.config.json
├── .markdown-link-check.json
├── .nvmrc
├── .pre-commit-config.yaml
├── .versionrc.json
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── commitlint.config.js
├── CONTRIBUTING.md
├── docker-compose.docs.yml
├── Dockerfile.docs
├── docs
│   ├── .docusaurus
│   │   ├── docusaurus-plugin-content-docs
│   │   │   └── default
│   │   │       └── __mdx-loader-dependency.json
│   │   └── docusaurus-plugin-content-pages
│   │       └── default
│   │           └── __plugin.json
│   ├── adrs
│   │   ├── 001-mcp-server-architecture.md
│   │   ├── 002-repository-analysis-engine.md
│   │   ├── 003-static-site-generator-recommendation-engine.md
│   │   ├── 004-diataxis-framework-integration.md
│   │   ├── 005-github-pages-deployment-automation.md
│   │   ├── 006-mcp-tools-api-design.md
│   │   ├── 007-mcp-prompts-and-resources-integration.md
│   │   ├── 008-intelligent-content-population-engine.md
│   │   ├── 009-content-accuracy-validation-framework.md
│   │   ├── 010-mcp-resource-pattern-redesign.md
│   │   └── README.md
│   ├── api
│   │   ├── .nojekyll
│   │   ├── assets
│   │   │   ├── hierarchy.js
│   │   │   ├── highlight.css
│   │   │   ├── icons.js
│   │   │   ├── icons.svg
│   │   │   ├── main.js
│   │   │   ├── navigation.js
│   │   │   ├── search.js
│   │   │   └── style.css
│   │   ├── hierarchy.html
│   │   ├── index.html
│   │   ├── modules.html
│   │   └── variables
│   │       └── TOOLS.html
│   ├── assets
│   │   └── logo.svg
│   ├── development
│   │   └── MCP_INSPECTOR_TESTING.md
│   ├── docusaurus.config.js
│   ├── explanation
│   │   ├── architecture.md
│   │   └── index.md
│   ├── guides
│   │   ├── link-validation.md
│   │   ├── playwright-integration.md
│   │   └── playwright-testing-workflow.md
│   ├── how-to
│   │   ├── analytics-setup.md
│   │   ├── custom-domains.md
│   │   ├── documentation-freshness-tracking.md
│   │   ├── github-pages-deployment.md
│   │   ├── index.md
│   │   ├── local-testing.md
│   │   ├── performance-optimization.md
│   │   ├── prompting-guide.md
│   │   ├── repository-analysis.md
│   │   ├── seo-optimization.md
│   │   ├── site-monitoring.md
│   │   ├── troubleshooting.md
│   │   └── usage-examples.md
│   ├── index.md
│   ├── knowledge-graph.md
│   ├── package-lock.json
│   ├── package.json
│   ├── phase-2-intelligence.md
│   ├── reference
│   │   ├── api-overview.md
│   │   ├── cli.md
│   │   ├── configuration.md
│   │   ├── deploy-pages.md
│   │   ├── index.md
│   │   ├── mcp-tools.md
│   │   └── prompt-templates.md
│   ├── research
│   │   ├── cross-domain-integration
│   │   │   └── README.md
│   │   ├── domain-1-mcp-architecture
│   │   │   ├── index.md
│   │   │   └── mcp-performance-research.md
│   │   ├── domain-2-repository-analysis
│   │   │   └── README.md
│   │   ├── domain-3-ssg-recommendation
│   │   │   ├── index.md
│   │   │   └── ssg-performance-analysis.md
│   │   ├── domain-4-diataxis-integration
│   │   │   └── README.md
│   │   ├── domain-5-github-deployment
│   │   │   ├── github-pages-security-analysis.md
│   │   │   └── index.md
│   │   ├── domain-6-api-design
│   │   │   └── README.md
│   │   ├── README.md
│   │   ├── research-integration-summary-2025-01-14.md
│   │   ├── research-progress-template.md
│   │   └── research-questions-2025-01-14.md
│   ├── robots.txt
│   ├── sidebars.js
│   ├── sitemap.xml
│   ├── src
│   │   └── css
│   │       └── custom.css
│   └── tutorials
│       ├── development-setup.md
│       ├── environment-setup.md
│       ├── first-deployment.md
│       ├── getting-started.md
│       ├── index.md
│       ├── memory-workflows.md
│       └── user-onboarding.md
├── jest.config.js
├── LICENSE
├── Makefile
├── MCP_PHASE2_IMPLEMENTATION.md
├── mcp-config-example.json
├── mcp.json
├── package-lock.json
├── package.json
├── README.md
├── release.sh
├── scripts
│   └── check-package-structure.cjs
├── SECURITY.md
├── setup-precommit.sh
├── src
│   ├── benchmarks
│   │   └── performance.ts
│   ├── index.ts
│   ├── memory
│   │   ├── contextual-retrieval.ts
│   │   ├── deployment-analytics.ts
│   │   ├── enhanced-manager.ts
│   │   ├── export-import.ts
│   │   ├── freshness-kg-integration.ts
│   │   ├── index.ts
│   │   ├── integration.ts
│   │   ├── kg-code-integration.ts
│   │   ├── kg-health.ts
│   │   ├── kg-integration.ts
│   │   ├── kg-link-validator.ts
│   │   ├── kg-storage.ts
│   │   ├── knowledge-graph.ts
│   │   ├── learning.ts
│   │   ├── manager.ts
│   │   ├── multi-agent-sharing.ts
│   │   ├── pruning.ts
│   │   ├── schemas.ts
│   │   ├── storage.ts
│   │   ├── temporal-analysis.ts
│   │   ├── user-preferences.ts
│   │   └── visualization.ts
│   ├── prompts
│   │   └── technical-writer-prompts.ts
│   ├── scripts
│   │   └── benchmark.ts
│   ├── templates
│   │   └── playwright
│   │       ├── accessibility.spec.template.ts
│   │       ├── Dockerfile.template
│   │       ├── docs-e2e.workflow.template.yml
│   │       ├── link-validation.spec.template.ts
│   │       └── playwright.config.template.ts
│   ├── tools
│   │   ├── analyze-deployments.ts
│   │   ├── analyze-readme.ts
│   │   ├── analyze-repository.ts
│   │   ├── check-documentation-links.ts
│   │   ├── deploy-pages.ts
│   │   ├── detect-gaps.ts
│   │   ├── evaluate-readme-health.ts
│   │   ├── generate-config.ts
│   │   ├── generate-contextual-content.ts
│   │   ├── generate-llm-context.ts
│   │   ├── generate-readme-template.ts
│   │   ├── generate-technical-writer-prompts.ts
│   │   ├── kg-health-check.ts
│   │   ├── manage-preferences.ts
│   │   ├── manage-sitemap.ts
│   │   ├── optimize-readme.ts
│   │   ├── populate-content.ts
│   │   ├── readme-best-practices.ts
│   │   ├── recommend-ssg.ts
│   │   ├── setup-playwright-tests.ts
│   │   ├── setup-structure.ts
│   │   ├── sync-code-to-docs.ts
│   │   ├── test-local-deployment.ts
│   │   ├── track-documentation-freshness.ts
│   │   ├── update-existing-documentation.ts
│   │   ├── validate-content.ts
│   │   ├── validate-documentation-freshness.ts
│   │   ├── validate-readme-checklist.ts
│   │   └── verify-deployment.ts
│   ├── types
│   │   └── api.ts
│   ├── utils
│   │   ├── ast-analyzer.ts
│   │   ├── code-scanner.ts
│   │   ├── content-extractor.ts
│   │   ├── drift-detector.ts
│   │   ├── freshness-tracker.ts
│   │   ├── language-parsers-simple.ts
│   │   ├── permission-checker.ts
│   │   └── sitemap-generator.ts
│   └── workflows
│       └── documentation-workflow.ts
├── test-docs-local.sh
├── tests
│   ├── api
│   │   └── mcp-responses.test.ts
│   ├── benchmarks
│   │   └── performance.test.ts
│   ├── edge-cases
│   │   └── error-handling.test.ts
│   ├── functional
│   │   └── tools.test.ts
│   ├── integration
│   │   ├── kg-documentation-workflow.test.ts
│   │   ├── knowledge-graph-workflow.test.ts
│   │   ├── mcp-readme-tools.test.ts
│   │   ├── memory-mcp-tools.test.ts
│   │   ├── readme-technical-writer.test.ts
│   │   └── workflow.test.ts
│   ├── memory
│   │   ├── contextual-retrieval.test.ts
│   │   ├── enhanced-manager.test.ts
│   │   ├── export-import.test.ts
│   │   ├── freshness-kg-integration.test.ts
│   │   ├── kg-code-integration.test.ts
│   │   ├── kg-health.test.ts
│   │   ├── kg-link-validator.test.ts
│   │   ├── kg-storage-validation.test.ts
│   │   ├── kg-storage.test.ts
│   │   ├── knowledge-graph-enhanced.test.ts
│   │   ├── knowledge-graph.test.ts
│   │   ├── learning.test.ts
│   │   ├── manager-advanced.test.ts
│   │   ├── manager.test.ts
│   │   ├── mcp-resource-integration.test.ts
│   │   ├── mcp-tool-persistence.test.ts
│   │   ├── schemas.test.ts
│   │   ├── storage.test.ts
│   │   ├── temporal-analysis.test.ts
│   │   └── user-preferences.test.ts
│   ├── performance
│   │   ├── memory-load-testing.test.ts
│   │   └── memory-stress-testing.test.ts
│   ├── prompts
│   │   ├── guided-workflow-prompts.test.ts
│   │   └── technical-writer-prompts.test.ts
│   ├── server.test.ts
│   ├── setup.ts
│   ├── tools
│   │   ├── all-tools.test.ts
│   │   ├── analyze-coverage.test.ts
│   │   ├── analyze-deployments.test.ts
│   │   ├── analyze-readme.test.ts
│   │   ├── analyze-repository.test.ts
│   │   ├── check-documentation-links.test.ts
│   │   ├── deploy-pages-kg-retrieval.test.ts
│   │   ├── deploy-pages-tracking.test.ts
│   │   ├── deploy-pages.test.ts
│   │   ├── detect-gaps.test.ts
│   │   ├── evaluate-readme-health.test.ts
│   │   ├── generate-contextual-content.test.ts
│   │   ├── generate-llm-context.test.ts
│   │   ├── generate-readme-template.test.ts
│   │   ├── generate-technical-writer-prompts.test.ts
│   │   ├── kg-health-check.test.ts
│   │   ├── manage-sitemap.test.ts
│   │   ├── optimize-readme.test.ts
│   │   ├── readme-best-practices.test.ts
│   │   ├── recommend-ssg-historical.test.ts
│   │   ├── recommend-ssg-preferences.test.ts
│   │   ├── recommend-ssg.test.ts
│   │   ├── simple-coverage.test.ts
│   │   ├── sync-code-to-docs.test.ts
│   │   ├── test-local-deployment.test.ts
│   │   ├── tool-error-handling.test.ts
│   │   ├── track-documentation-freshness.test.ts
│   │   ├── validate-content.test.ts
│   │   ├── validate-documentation-freshness.test.ts
│   │   └── validate-readme-checklist.test.ts
│   ├── types
│   │   └── type-safety.test.ts
│   └── utils
│       ├── ast-analyzer.test.ts
│       ├── content-extractor.test.ts
│       ├── drift-detector.test.ts
│       ├── freshness-tracker.test.ts
│       └── sitemap-generator.test.ts
├── tsconfig.json
└── typedoc.json
```

# Files

--------------------------------------------------------------------------------
/tests/integration/knowledge-graph-workflow.test.ts:
--------------------------------------------------------------------------------

```typescript
  1 | /**
  2 |  * Integration Tests for Knowledge Graph Workflow
  3 |  * Phase 1: End-to-End KG-Analysis Integration
  4 |  */
  5 | 
  6 | import { describe, it, expect, beforeEach, afterEach } from "@jest/globals";
  7 | import { promises as fs } from "fs";
  8 | import { join } from "path";
  9 | import { tmpdir } from "os";
 10 | import {
 11 |   initializeKnowledgeGraph,
 12 |   getKnowledgeGraph,
 13 |   saveKnowledgeGraph,
 14 |   createOrUpdateProject,
 15 |   getProjectContext,
 16 |   trackDeployment,
 17 |   getKGStatistics,
 18 | } from "../../src/memory/kg-integration.js";
 19 | 
 20 | describe("Knowledge Graph Workflow Integration", () => {
 21 |   let testDir: string;
 22 |   let originalEnv: string | undefined;
 23 | 
 24 |   beforeEach(async () => {
 25 |     // Create temporary test directory
 26 |     testDir = join(tmpdir(), `kg-workflow-test-${Date.now()}`);
 27 |     await fs.mkdir(testDir, { recursive: true });
 28 | 
 29 |     // Set environment variable for storage
 30 |     originalEnv = process.env.DOCUMCP_STORAGE_DIR;
 31 |     process.env.DOCUMCP_STORAGE_DIR = testDir;
 32 | 
 33 |     // Initialize KG
 34 |     await initializeKnowledgeGraph(testDir);
 35 |   });
 36 | 
 37 |   afterEach(async () => {
 38 |     // Restore environment
 39 |     if (originalEnv) {
 40 |       process.env.DOCUMCP_STORAGE_DIR = originalEnv;
 41 |     } else {
 42 |       delete process.env.DOCUMCP_STORAGE_DIR;
 43 |     }
 44 | 
 45 |     // Clean up test directory
 46 |     try {
 47 |       await fs.rm(testDir, { recursive: true, force: true });
 48 |     } catch (error) {
 49 |       console.warn("Failed to clean up test directory:", error);
 50 |     }
 51 |   });
 52 | 
 53 |   describe("Complete Analysis Workflow", () => {
 54 |     it("should handle first-time project analysis", async () => {
 55 |       const analysis = {
 56 |         id: "analysis_001",
 57 |         timestamp: new Date().toISOString(),
 58 |         path: "/test/project",
 59 |         projectName: "Test Project",
 60 |         structure: {
 61 |           totalFiles: 100,
 62 |           totalDirectories: 10,
 63 |           languages: {
 64 |             typescript: 60,
 65 |             javascript: 30,
 66 |             json: 10,
 67 |           },
 68 |           hasTests: true,
 69 |           hasCI: true,
 70 |           hasDocs: false,
 71 |         },
 72 |       };
 73 | 
 74 |       // Create project in KG
 75 |       const projectNode = await createOrUpdateProject(analysis);
 76 | 
 77 |       expect(projectNode).toBeDefined();
 78 |       expect(projectNode.type).toBe("project");
 79 |       expect(projectNode.properties.name).toBe("Test Project");
 80 |       expect(projectNode.properties.analysisCount).toBe(1);
 81 | 
 82 |       // Get context (should be empty for first analysis)
 83 |       const context = await getProjectContext("/test/project");
 84 |       expect(context.previousAnalyses).toBe(1);
 85 |       expect(context.knownTechnologies).toContain("typescript");
 86 |     });
 87 | 
 88 |     it("should track returning project with historical context", async () => {
 89 |       const analysis1 = {
 90 |         id: "analysis_001",
 91 |         timestamp: new Date().toISOString(),
 92 |         path: "/test/project",
 93 |         projectName: "Test Project",
 94 |         structure: {
 95 |           totalFiles: 100,
 96 |           languages: { typescript: 60, javascript: 40 },
 97 |           hasTests: true,
 98 |           hasCI: false,
 99 |           hasDocs: false,
100 |         },
101 |       };
102 | 
103 |       const analysis2 = {
104 |         id: "analysis_002",
105 |         timestamp: new Date().toISOString(),
106 |         path: "/test/project",
107 |         projectName: "Test Project",
108 |         structure: {
109 |           totalFiles: 120,
110 |           languages: { typescript: 80, javascript: 40 },
111 |           hasTests: true,
112 |           hasCI: true,
113 |           hasDocs: true,
114 |         },
115 |       };
116 | 
117 |       // First analysis
118 |       await createOrUpdateProject(analysis1);
119 | 
120 |       // Second analysis
121 |       const projectNode = await createOrUpdateProject(analysis2);
122 | 
123 |       expect(projectNode.properties.analysisCount).toBe(2);
124 | 
125 |       // Get context
126 |       const context = await getProjectContext("/test/project");
127 |       expect(context.previousAnalyses).toBe(2);
128 |       expect(context.lastAnalyzed).toBeDefined();
129 |     });
130 | 
131 |     it("should find similar projects based on technologies", async () => {
132 |       // Create multiple projects with shared technologies
133 |       const project1 = {
134 |         id: "analysis_001",
135 |         timestamp: new Date().toISOString(),
136 |         path: "/test/project1",
137 |         projectName: "React App",
138 |         structure: {
139 |           totalFiles: 50,
140 |           languages: { typescript: 30, javascript: 20 },
141 |           hasTests: true,
142 |           hasCI: false,
143 |           hasDocs: false,
144 |         },
145 |       };
146 | 
147 |       const project2 = {
148 |         id: "analysis_002",
149 |         timestamp: new Date().toISOString(),
150 |         path: "/test/project2",
151 |         projectName: "Another React App",
152 |         structure: {
153 |           totalFiles: 75,
154 |           languages: { typescript: 50, javascript: 25 },
155 |           hasTests: true,
156 |           hasCI: true,
157 |           hasDocs: false,
158 |         },
159 |       };
160 | 
161 |       const project3 = {
162 |         id: "analysis_003",
163 |         timestamp: new Date().toISOString(),
164 |         path: "/test/project3",
165 |         projectName: "Python Project",
166 |         structure: {
167 |           totalFiles: 40,
168 |           languages: { python: 40 },
169 |           hasTests: true,
170 |           hasCI: false,
171 |           hasDocs: false,
172 |         },
173 |       };
174 | 
175 |       // Create all projects
176 |       await createOrUpdateProject(project1);
177 |       await createOrUpdateProject(project2);
178 |       await createOrUpdateProject(project3);
179 | 
180 |       // Get context for project1
181 |       const context = await getProjectContext("/test/project1");
182 | 
183 |       // Should find project2 as similar (shares typescript/javascript)
184 |       // Should not find project3 (uses different stack)
185 |       expect(context.similarProjects.length).toBeGreaterThan(0);
186 | 
187 |       const similarProject = context.similarProjects.find(
188 |         (p) => p.properties.name === "Another React App",
189 |       );
190 |       expect(similarProject).toBeDefined();
191 |     });
192 |   });
193 | 
194 |   describe("Deployment Tracking Workflow", () => {
195 |     it("should track successful deployment", async () => {
196 |       // Create project
197 |       const analysis = {
198 |         id: "project_001",
199 |         timestamp: new Date().toISOString(),
200 |         path: "/test/project",
201 |         projectName: "Test Project",
202 |         structure: {
203 |           totalFiles: 50,
204 |           languages: { typescript: 50 },
205 |           hasTests: true,
206 |           hasCI: false,
207 |           hasDocs: false,
208 |         },
209 |       };
210 | 
211 |       const projectNode = await createOrUpdateProject(analysis);
212 | 
213 |       // Track successful deployment
214 |       await trackDeployment(projectNode.id, "docusaurus", true, {
215 |         buildTime: 45,
216 |         deploymentUrl: "https://test.github.io",
217 |       });
218 | 
219 |       // Verify deployment was tracked
220 |       const kg = await getKnowledgeGraph();
221 |       const edges = await kg.findEdges({
222 |         source: projectNode.id,
223 |         properties: { baseType: "project_deployed_with" },
224 |       });
225 | 
226 |       expect(edges.length).toBeGreaterThan(0);
227 |       expect(edges[0].properties.success).toBe(true);
228 |       expect(edges[0].properties.buildTime).toBe(45);
229 |     });
230 | 
231 |     it("should track failed deployment", async () => {
232 |       const analysis = {
233 |         id: "project_002",
234 |         timestamp: new Date().toISOString(),
235 |         path: "/test/project2",
236 |         projectName: "Test Project 2",
237 |         structure: {
238 |           totalFiles: 50,
239 |           languages: { javascript: 50 },
240 |           hasTests: false,
241 |           hasCI: false,
242 |           hasDocs: false,
243 |         },
244 |       };
245 | 
246 |       const projectNode = await createOrUpdateProject(analysis);
247 | 
248 |       // Track failed deployment
249 |       await trackDeployment(projectNode.id, "jekyll", false, {
250 |         errorMessage: "Ruby version mismatch",
251 |       });
252 | 
253 |       const kg = await getKnowledgeGraph();
254 |       const edges = await kg.findEdges({
255 |         source: projectNode.id,
256 |         properties: { baseType: "project_deployed_with" },
257 |       });
258 | 
259 |       expect(edges.length).toBeGreaterThan(0);
260 |       expect(edges[0].properties.success).toBe(false);
261 |       expect(edges[0].properties.errorMessage).toContain("Ruby version");
262 |     });
263 | 
264 |     it("should update configuration success rate over time", async () => {
265 |       const analysis = {
266 |         id: "project_003",
267 |         timestamp: new Date().toISOString(),
268 |         path: "/test/project3",
269 |         projectName: "Test Project 3",
270 |         structure: {
271 |           totalFiles: 50,
272 |           languages: { typescript: 50 },
273 |           hasTests: false,
274 |           hasCI: false,
275 |           hasDocs: false,
276 |         },
277 |       };
278 | 
279 |       const projectNode = await createOrUpdateProject(analysis);
280 | 
281 |       // Track multiple deployments
282 |       await trackDeployment(projectNode.id, "hugo", true);
283 |       await trackDeployment(projectNode.id, "hugo", true);
284 |       await trackDeployment(projectNode.id, "hugo", false);
285 | 
286 |       const kg = await getKnowledgeGraph();
287 |       const configNode = await kg.findNode({
288 |         type: "configuration",
289 |         properties: { ssg: "hugo" },
290 |       });
291 | 
292 |       expect(configNode).toBeDefined();
293 |       expect(configNode!.properties.usageCount).toBe(3);
294 |       // Success rate: 2/3 = 0.666...
295 |       expect(configNode!.properties.deploymentSuccessRate).toBeCloseTo(
296 |         0.666,
297 |         2,
298 |       );
299 |     });
300 |   });
301 | 
302 |   describe("Knowledge Graph Statistics", () => {
303 |     it("should return accurate statistics", async () => {
304 |       // Create multiple projects
305 |       for (let i = 0; i < 5; i++) {
306 |         const analysis = {
307 |           id: `project_00${i}`,
308 |           timestamp: new Date().toISOString(),
309 |           path: `/test/project${i}`,
310 |           projectName: `Project ${i}`,
311 |           structure: {
312 |             totalFiles: 50,
313 |             languages: { typescript: 30, javascript: 20 },
314 |             hasTests: true,
315 |             hasCI: false,
316 |             hasDocs: false,
317 |           },
318 |         };
319 |         await createOrUpdateProject(analysis);
320 |       }
321 | 
322 |       const stats = await getKGStatistics();
323 | 
324 |       expect(stats.projectCount).toBe(5);
325 |       expect(stats.technologyCount).toBeGreaterThan(0);
326 |       expect(stats.nodeCount).toBeGreaterThan(5); // Projects + technologies
327 |       expect(stats.edgeCount).toBeGreaterThan(0); // project_uses_technology edges
328 |     });
329 |   });
330 | 
331 |   describe("Persistence Workflow", () => {
332 |     it("should persist data across sessions", async () => {
333 |       const analysis = {
334 |         id: "persistent_project",
335 |         timestamp: new Date().toISOString(),
336 |         path: "/test/persistent",
337 |         projectName: "Persistent Project",
338 |         structure: {
339 |           totalFiles: 50,
340 |           languages: { typescript: 50 },
341 |           hasTests: true,
342 |           hasCI: false,
343 |           hasDocs: false,
344 |         },
345 |       };
346 | 
347 |       // Create project and save
348 |       await createOrUpdateProject(analysis);
349 |       await saveKnowledgeGraph();
350 | 
351 |       // Reinitialize (simulating new session)
352 |       await initializeKnowledgeGraph(testDir);
353 | 
354 |       // Verify data was loaded
355 |       const context = await getProjectContext("/test/persistent");
356 |       expect(context.previousAnalyses).toBe(1);
357 |       expect(context.knownTechnologies).toContain("typescript");
358 |     });
359 |   });
360 | 
361 |   describe("Complex Multi-Step Workflow", () => {
362 |     it("should handle complete project lifecycle", async () => {
363 |       // Step 1: Initial analysis
364 |       const initialAnalysis = {
365 |         id: "lifecycle_project",
366 |         timestamp: new Date().toISOString(),
367 |         path: "/test/lifecycle",
368 |         projectName: "Lifecycle Project",
369 |         structure: {
370 |           totalFiles: 30,
371 |           languages: { javascript: 30 },
372 |           hasTests: false,
373 |           hasCI: false,
374 |           hasDocs: false,
375 |         },
376 |       };
377 | 
378 |       const project1 = await createOrUpdateProject(initialAnalysis);
379 |       expect(project1.properties.analysisCount).toBe(1);
380 | 
381 |       // Step 2: Track deployment attempt (failed)
382 |       await trackDeployment(project1.id, "jekyll", false, {
383 |         errorMessage: "Missing dependencies",
384 |       });
385 | 
386 |       // Step 3: Re-analysis after fixes
387 |       const updatedAnalysis = {
388 |         ...initialAnalysis,
389 |         id: "lifecycle_project_2",
390 |         timestamp: new Date().toISOString(),
391 |         structure: {
392 |           totalFiles: 35,
393 |           languages: { javascript: 30, json: 5 },
394 |           hasTests: true,
395 |           hasCI: true,
396 |           hasDocs: true,
397 |         },
398 |       };
399 | 
400 |       const project2 = await createOrUpdateProject(updatedAnalysis);
401 |       expect(project2.properties.analysisCount).toBe(2);
402 |       expect(project2.properties.hasCI).toBe(true);
403 | 
404 |       // Step 4: Successful deployment
405 |       await trackDeployment(project2.id, "eleventy", true, {
406 |         buildTime: 30,
407 |         deploymentUrl: "https://lifecycle.github.io",
408 |       });
409 | 
410 |       // Verify complete lifecycle
411 |       const kg = await getKnowledgeGraph();
412 | 
413 |       // Check project node
414 |       const projectNode = await kg.findNode({
415 |         type: "project",
416 |         properties: { path: "/test/lifecycle" },
417 |       });
418 |       expect(projectNode).toBeDefined();
419 |       expect(projectNode!.properties.analysisCount).toBe(2);
420 | 
421 |       // Check deployments
422 |       const deployments = await kg.findEdges({
423 |         source: projectNode!.id,
424 |         properties: { baseType: "project_deployed_with" },
425 |       });
426 |       expect(deployments).toHaveLength(2);
427 | 
428 |       // Check technologies
429 |       const techEdges = await kg.findEdges({
430 |         source: projectNode!.id,
431 |         type: "project_uses_technology",
432 |       });
433 |       expect(techEdges.length).toBeGreaterThan(0);
434 | 
435 |       // Get final context
436 |       const context = await getProjectContext("/test/lifecycle");
437 |       expect(context.previousAnalyses).toBe(2);
438 |       expect(context.knownTechnologies).toContain("javascript");
439 |     });
440 |   });
441 | });
442 | 
```

--------------------------------------------------------------------------------
/docs/adrs/003-static-site-generator-recommendation-engine.md:
--------------------------------------------------------------------------------

```markdown
  1 | ---
  2 | id: 003-static-site-generator-recommendation-engine
  3 | title: "ADR-003: SSG Recommendation Engine Design"
  4 | sidebar_label: "ADR-3: SSG Recommendation Engine Design"
  5 | sidebar_position: 3
  6 | documcp:
  7 |   last_updated: "2025-11-20T00:46:21.937Z"
  8 |   last_validated: "2025-11-20T00:46:21.937Z"
  9 |   auto_updated: false
 10 |   update_frequency: monthly
 11 | ---
 12 | 
 13 | # ADR-003: Static Site Generator Recommendation Engine Design
 14 | 
 15 | ## Status
 16 | 
 17 | Accepted
 18 | 
 19 | ## Context
 20 | 
 21 | DocuMCP must intelligently recommend the most appropriate static site generator (SSG) for each project based on comprehensive analysis of project characteristics, team capabilities, and technical requirements. The recommendation engine needs to move beyond simple feature comparison to provide data-driven, contextual recommendations with clear justifications.
 22 | 
 23 | Current SSG landscape includes:
 24 | 
 25 | - **Jekyll**: GitHub Pages native, Ruby-based, mature ecosystem
 26 | - **Hugo**: Go-based, fast builds, extensive theming
 27 | - **Docusaurus**: React-based, modern features, Meta-backed
 28 | - **MkDocs**: Python-based, simple, Material theme
 29 | - **Eleventy**: JavaScript-based, flexible, minimal configuration
 30 | 
 31 | Key challenges:
 32 | 
 33 | - Choice paralysis for users unfamiliar with SSG ecosystem
 34 | - Technical requirements vary significantly by project type
 35 | - Performance needs differ based on content volume and update frequency
 36 | - Team capabilities and preferences affect long-term success
 37 | - Maintenance overhead varies dramatically between options
 38 | 
 39 | ## Decision
 40 | 
 41 | We will implement a multi-criteria decision analysis (MCDA) framework that evaluates project characteristics against SSG capabilities to provide ranked recommendations with confidence scores and detailed justifications.
 42 | 
 43 | ### Recommendation Engine Architecture:
 44 | 
 45 | #### 1. SSG Knowledge Base
 46 | 
 47 | - **Comprehensive SSG profiles** with quantitative and qualitative metrics
 48 | - **Performance characteristics**: build times, memory usage, scalability limits
 49 | - **Learning curve assessments**: setup complexity, maintenance requirements
 50 | - **Feature compatibility matrices**: advanced features, plugin ecosystems
 51 | - **Community metrics**: activity, support quality, ecosystem maturity
 52 | 
 53 | #### 2. Decision Matrix Framework
 54 | 
 55 | - **Multi-criteria evaluation** across weighted factors
 56 | - **Project-specific factor weighting** based on analysis results
 57 | - **Algorithmic scoring** with transparent calculation methods
 58 | - **Confidence assessment** based on factor alignment quality
 59 | 
 60 | #### 3. Performance Modeling
 61 | 
 62 | - **Build time prediction** based on content volume and complexity
 63 | - **Scalability assessment** for projected growth patterns
 64 | - **Resource requirement estimation** for different deployment scenarios
 65 | 
 66 | #### 4. Compatibility Assessment
 67 | 
 68 | - **Technical stack alignment** with existing project technologies
 69 | - **Workflow integration** with current development processes
 70 | - **CI/CD compatibility** with existing automation infrastructure
 71 | 
 72 | ## Alternatives Considered
 73 | 
 74 | ### Simple Rule-Based Recommendations
 75 | 
 76 | - **Pros**: Easy to implement, fast execution, predictable results
 77 | - **Cons**: Inflexible, doesn't handle edge cases, poor justification quality
 78 | - **Decision**: Rejected due to insufficient sophistication for quality recommendations
 79 | 
 80 | ### Machine Learning-Based Recommendation
 81 | 
 82 | - **Pros**: Could learn from successful project outcomes, adaptive over time
 83 | - **Cons**: Requires training data, model maintenance, unpredictable results
 84 | - **Decision**: Deferred to future versions; insufficient training data initially
 85 | 
 86 | ### User Survey-Based Selection
 87 | 
 88 | - **Pros**: Direct user input, captures preferences and constraints
 89 | - **Cons**: Requires user expertise, time-consuming, potential analysis paralysis
 90 | - **Decision**: Integrated as preference input to algorithmic recommendation
 91 | 
 92 | ### External Service Integration (StackShare, etc.)
 93 | 
 94 | - **Pros**: Real-world usage data, community insights
 95 | - **Cons**: External dependency, potential bias, limited project-specific context
 96 | - **Decision**: Rejected for core logic; may integrate for validation
 97 | 
 98 | ## Consequences
 99 | 
100 | ### Positive
101 | 
102 | - **Objective Recommendations**: Data-driven approach reduces bias and subjectivity
103 | - **Clear Justifications**: Users understand why specific SSGs are recommended
104 | - **Confidence Indicators**: Users know when recommendations are highly certain vs. uncertain
105 | - **Contextual Intelligence**: Recommendations adapt to specific project characteristics
106 | - **Educational Value**: Users learn about SSG capabilities and trade-offs
107 | 
108 | ### Negative
109 | 
110 | - **Algorithm Complexity**: Multi-criteria analysis requires careful tuning and validation
111 | - **Knowledge Base Maintenance**: SSG profiles need regular updates as tools evolve
112 | - **Subjectivity in Weights**: Factor importance assignments may not match all user preferences
113 | 
114 | ### Risks and Mitigations
115 | 
116 | - **Recommendation Accuracy**: Validate against known successful project combinations
117 | - **Algorithm Bias**: Test across diverse project types and regularly audit results
118 | - **Knowledge Staleness**: Implement automated SSG capability monitoring and updates
119 | 
120 | ## Implementation Details
121 | 
122 | ### Decision Criteria Framework
123 | 
124 | ```typescript
125 | interface RecommendationCriteria {
126 |   projectSize: ProjectSizeMetrics;
127 |   technicalComplexity: ComplexityAssessment;
128 |   teamCapabilities: TeamProfile;
129 |   performanceRequirements: PerformanceNeeds;
130 |   maintenancePreferences: MaintenanceProfile;
131 |   customizationNeeds: CustomizationRequirements;
132 | }
133 | 
134 | interface SSGProfile {
135 |   name: string;
136 |   capabilities: SSGCapabilities;
137 |   performance: PerformanceProfile;
138 |   learningCurve: LearningCurveMetrics;
139 |   ecosystem: EcosystemMetrics;
140 |   maintenanceOverhead: MaintenanceMetrics;
141 | }
142 | ```
143 | 
144 | ### Scoring Algorithm
145 | 
146 | ```typescript
147 | interface ScoringWeights {
148 |   buildPerformance: number; // 0.20
149 |   setupComplexity: number; // 0.15
150 |   technicalAlignment: number; // 0.25
151 |   customizationFlexibility: number; // 0.15
152 |   maintenanceOverhead: number; // 0.15
153 |   ecosystemMaturity: number; // 0.10
154 | }
155 | 
156 | function calculateSSGScore(
157 |   project: ProjectAnalysis,
158 |   ssg: SSGProfile,
159 |   weights: ScoringWeights,
160 | ): RecommendationScore {
161 |   // Weighted scoring across multiple criteria
162 |   // Returns score (0-100) with component breakdown
163 | }
164 | ```
165 | 
166 | ### Performance Modeling (Updated with Research 2025-01-14)
167 | 
168 | **Research Integration**: Comprehensive SSG performance analysis validates and refines our approach:
169 | 
170 | ```typescript
171 | interface PerformanceModel {
172 |   predictBuildTime(
173 |     contentVolume: number,
174 |     complexity: number,
175 |   ): BuildTimeEstimate;
176 |   assessScalability(projectedGrowth: GrowthPattern): ScalabilityRating;
177 |   estimateResourceNeeds(deployment: DeploymentTarget): ResourceRequirements;
178 | 
179 |   // Research-validated performance tiers
180 |   calculatePerformanceTier(
181 |     ssg: SSGType,
182 |     projectScale: ProjectScale,
183 |   ): PerformanceTier;
184 | }
185 | 
186 | // Research-validated performance characteristics
187 | const SSG_PERFORMANCE_MATRIX = {
188 |   hugo: {
189 |     smallSites: { buildTime: "instant", scaleFactor: 1.0, overhead: "minimal" },
190 |     mediumSites: {
191 |       buildTime: "seconds",
192 |       scaleFactor: 1.1,
193 |       overhead: "minimal",
194 |     },
195 |     largeSites: { buildTime: "seconds", scaleFactor: 1.2, overhead: "minimal" },
196 |   },
197 |   gatsby: {
198 |     smallSites: { buildTime: "slow", scaleFactor: 250, overhead: "webpack" },
199 |     mediumSites: {
200 |       buildTime: "moderate",
201 |       scaleFactor: 100,
202 |       overhead: "webpack",
203 |     },
204 |     largeSites: {
205 |       buildTime: "improving",
206 |       scaleFactor: 40,
207 |       overhead: "optimized",
208 |     },
209 |   },
210 |   eleventy: {
211 |     smallSites: { buildTime: "fast", scaleFactor: 3, overhead: "node" },
212 |     mediumSites: { buildTime: "good", scaleFactor: 8, overhead: "node" },
213 |     largeSites: { buildTime: "moderate", scaleFactor: 15, overhead: "node" },
214 |   },
215 |   jekyll: {
216 |     smallSites: { buildTime: "good", scaleFactor: 2, overhead: "ruby" },
217 |     mediumSites: { buildTime: "slowing", scaleFactor: 12, overhead: "ruby" },
218 |     largeSites: {
219 |       buildTime: "poor",
220 |       scaleFactor: 25,
221 |       overhead: "ruby-bottleneck",
222 |     },
223 |   },
224 | } as const;
225 | 
226 | // Research-validated recommendation algorithm
227 | const calculatePerformanceScore = (
228 |   ssg: SSGType,
229 |   projectMetrics: ProjectMetrics,
230 | ): number => {
231 |   const { pageCount, updateFrequency, teamTechnicalLevel } = projectMetrics;
232 | 
233 |   // Scale-based performance weighting (research-validated)
234 |   const performanceWeight =
235 |     pageCount > 1000 ? 0.8 : pageCount > 100 ? 0.6 : 0.4;
236 | 
237 |   // Research-based performance scores
238 |   const baseScores = {
239 |     hugo: 100, // Fastest across all scales
240 |     eleventy: 85, // Good balance
241 |     jekyll: pageCount > 500 ? 60 : 80, // Ruby bottleneck at scale
242 |     nextjs: 70, // Framework overhead, good at scale
243 |     gatsby: pageCount > 1000 ? 65 : 45, // Severe small-site penalty
244 |     docusaurus: 75, // Optimized for documentation
245 |   };
246 | 
247 |   return (
248 |     baseScores[ssg] * performanceWeight +
249 |     baseScores[ssg] * (1 - performanceWeight) * featureScore[ssg]
250 |   );
251 | };
252 | ```
253 | 
254 | ### Recommendation Output
255 | 
256 | ```typescript
257 | interface Recommendation {
258 |   ssg: SSGProfile;
259 |   score: number;
260 |   confidence: number;
261 |   justification: RecommendationJustification;
262 |   tradeoffs: Tradeoff[];
263 |   alternativeOptions: AlternativeRecommendation[];
264 | }
265 | 
266 | interface RecommendationJustification {
267 |   primaryStrengths: string[];
268 |   concerningWeaknesses: string[];
269 |   bestFitReasons: string[];
270 |   performancePredictions: PerformancePrediction[];
271 | }
272 | ```
273 | 
274 | ### SSG Knowledge Base Structure
275 | 
276 | ```typescript
277 | const SSG_PROFILES: Record<string, SSGProfile> = {
278 |   jekyll: {
279 |     name: "Jekyll",
280 |     capabilities: {
281 |       buildSpeed: "moderate",
282 |       themingFlexibility: "high",
283 |       pluginEcosystem: "mature",
284 |       githubPagesNative: true,
285 |       contentTypes: ["markdown", "liquid"],
286 |       i18nSupport: "plugin-based",
287 |     },
288 |     performance: {
289 |       averageBuildTime: "2-5 minutes per 100 pages",
290 |       memoryUsage: "moderate",
291 |       scalabilityLimit: "1000+ pages",
292 |     },
293 |     learningCurve: {
294 |       setupComplexity: "low-moderate",
295 |       configurationComplexity: "moderate",
296 |       customizationComplexity: "moderate-high",
297 |     },
298 |     // ... additional profile data
299 |   },
300 |   // ... other SSG profiles
301 | };
302 | ```
303 | 
304 | ### Confidence Calculation
305 | 
306 | ```typescript
307 | function calculateConfidence(
308 |   scores: SSGScore[],
309 |   projectAnalysis: ProjectAnalysis,
310 | ): number {
311 |   const scoreSpread = Math.max(...scores) - Math.min(...scores);
312 |   const analysisCompleteness = assessAnalysisCompleteness(projectAnalysis);
313 |   const criteriaAlignment = assessCriteriaAlignment(scores);
314 | 
315 |   // Higher confidence when:
316 |   // - Clear winner emerges (high score spread)
317 |   // - Analysis is comprehensive
318 |   // - Criteria strongly align with one option
319 |   return calculateWeightedConfidence(
320 |     scoreSpread,
321 |     analysisCompleteness,
322 |     criteriaAlignment,
323 |   );
324 | }
325 | ```
326 | 
327 | ## Quality Assurance
328 | 
329 | ### Validation Strategy
330 | 
331 | - **Benchmark Projects**: Test against known successful project-SSG combinations
332 | - **Expert Review**: Documentation experts validate recommendation logic
333 | - **User Feedback**: Collect real-world outcomes to refine algorithms
334 | - **A/B Testing**: Compare algorithm versions for recommendation quality
335 | 
336 | ### Testing Framework
337 | 
338 | ```typescript
339 | describe("RecommendationEngine", () => {
340 |   it("should recommend Jekyll for simple documentation sites");
341 |   it("should recommend Hugo for performance-critical large sites");
342 |   it("should recommend Docusaurus for React-based projects");
343 |   it("should provide low confidence for ambiguous project profiles");
344 |   it("should justify all recommendations with specific reasons");
345 | });
346 | ```
347 | 
348 | ### Monitoring and Metrics
349 | 
350 | - Recommendation accuracy rates by project type
351 | - User satisfaction with recommendations
352 | - Confidence score calibration accuracy
353 | - Algorithm performance and execution time
354 | 
355 | ## Knowledge Base Maintenance
356 | 
357 | ### SSG Capability Tracking
358 | 
359 | - Regular monitoring of SSG releases and capability changes
360 | - Community feedback integration for real-world performance data
361 | - Automated testing of SSG performance benchmarks
362 | - Expert review cycles for knowledge base accuracy
363 | 
364 | ### Update Processes
365 | 
366 | - Quarterly comprehensive review of all SSG profiles
367 | - Monthly monitoring of major releases and capability changes
368 | - Community contribution process for knowledge base improvements
369 | - Automated validation of knowledge base consistency
370 | 
371 | ## Future Enhancements
372 | 
373 | ### Advanced Analytics
374 | 
375 | - Historical success rate tracking by recommendation
376 | - Machine learning integration for pattern recognition
377 | - User preference learning and personalization
378 | - Comparative analysis across similar projects
379 | 
380 | ### Extended SSG Support
381 | 
382 | - Evaluation framework for new SSG additions
383 | - Community-contributed SSG profiles
384 | - Specialized SSG recommendations (e.g., Sphinx for API docs)
385 | - Custom SSG configuration for specific use cases
386 | 
387 | ### Integration Features
388 | 
389 | - Direct integration with SSG documentation and examples
390 | - Automated setup validation and testing
391 | - Performance monitoring and optimization recommendations
392 | - Migration assistance between SSGs
393 | 
394 | ## Security and Privacy
395 | 
396 | - No collection of sensitive project information
397 | - Anonymized analytics for algorithm improvement
398 | - Transparent recommendation criteria and methodology
399 | - User control over data sharing preferences
400 | 
401 | ## References
402 | 
403 | - [Static Site Generator Comparison Studies](https://jamstack.org/generators/)
404 | - [Multi-Criteria Decision Analysis](https://en.wikipedia.org/wiki/Multiple-criteria_decision_analysis)
405 | - [Static Site Generator Performance Comparison](https://jamstack.org/generators/)
406 | 
```

--------------------------------------------------------------------------------
/src/memory/user-preferences.ts:
--------------------------------------------------------------------------------

```typescript
  1 | /**
  2 |  * User Preference Management Module
  3 |  * Phase 2.2: User Preference Learning and Application
  4 |  *
  5 |  * Tracks and applies user preferences across DocuMCP operations
  6 |  */
  7 | 
  8 | import { getKnowledgeGraph, saveKnowledgeGraph } from "./kg-integration.js";
  9 | import { GraphNode } from "./knowledge-graph.js";
 10 | 
 11 | export interface UserPreferences {
 12 |   userId: string;
 13 |   preferredSSGs: string[];
 14 |   documentationStyle: "minimal" | "comprehensive" | "tutorial-heavy";
 15 |   expertiseLevel: "beginner" | "intermediate" | "advanced";
 16 |   preferredTechnologies: string[];
 17 |   preferredDiataxisCategories: Array<
 18 |     "tutorials" | "how-to" | "reference" | "explanation"
 19 |   >;
 20 |   autoApplyPreferences: boolean;
 21 |   lastUpdated: string;
 22 | }
 23 | 
 24 | export interface SSGUsageEvent {
 25 |   ssg: string;
 26 |   success: boolean;
 27 |   timestamp: string;
 28 |   projectType?: string;
 29 | }
 30 | 
 31 | /**
 32 |  * User Preference Manager
 33 |  * Handles storage, retrieval, and inference of user preferences
 34 |  */
 35 | export class UserPreferenceManager {
 36 |   private userId: string;
 37 |   private preferences: UserPreferences | null = null;
 38 | 
 39 |   constructor(userId: string = "default") {
 40 |     this.userId = userId;
 41 |   }
 42 | 
 43 |   /**
 44 |    * Initialize and load user preferences from knowledge graph
 45 |    */
 46 |   async initialize(): Promise<void> {
 47 |     const kg = await getKnowledgeGraph();
 48 | 
 49 |     // Find existing user node
 50 |     const userNode = await kg.findNode({
 51 |       type: "user",
 52 |       properties: { userId: this.userId },
 53 |     });
 54 | 
 55 |     if (userNode) {
 56 |       this.preferences = {
 57 |         userId: this.userId,
 58 |         preferredSSGs: userNode.properties.preferredSSGs || [],
 59 |         documentationStyle:
 60 |           userNode.properties.documentationStyle || "comprehensive",
 61 |         expertiseLevel: userNode.properties.expertiseLevel || "intermediate",
 62 |         preferredTechnologies: userNode.properties.preferredTechnologies || [],
 63 |         preferredDiataxisCategories:
 64 |           userNode.properties.preferredDiataxisCategories || [],
 65 |         autoApplyPreferences:
 66 |           userNode.properties.autoApplyPreferences !== false,
 67 |         lastUpdated: userNode.properties.lastActive || new Date().toISOString(),
 68 |       };
 69 |     } else {
 70 |       // Create default preferences
 71 |       this.preferences = {
 72 |         userId: this.userId,
 73 |         preferredSSGs: [],
 74 |         documentationStyle: "comprehensive",
 75 |         expertiseLevel: "intermediate",
 76 |         preferredTechnologies: [],
 77 |         preferredDiataxisCategories: [],
 78 |         autoApplyPreferences: true,
 79 |         lastUpdated: new Date().toISOString(),
 80 |       };
 81 | 
 82 |       // Store in knowledge graph
 83 |       await this.save();
 84 |     }
 85 |   }
 86 | 
 87 |   /**
 88 |    * Get current user preferences
 89 |    */
 90 |   async getPreferences(): Promise<UserPreferences> {
 91 |     if (!this.preferences) {
 92 |       await this.initialize();
 93 |     }
 94 |     return this.preferences!;
 95 |   }
 96 | 
 97 |   /**
 98 |    * Update user preferences
 99 |    */
100 |   async updatePreferences(
101 |     updates: Partial<Omit<UserPreferences, "userId" | "lastUpdated">>,
102 |   ): Promise<UserPreferences> {
103 |     if (!this.preferences) {
104 |       await this.initialize();
105 |     }
106 | 
107 |     this.preferences = {
108 |       ...this.preferences!,
109 |       ...updates,
110 |       lastUpdated: new Date().toISOString(),
111 |     };
112 | 
113 |     await this.save();
114 |     return this.preferences;
115 |   }
116 | 
117 |   /**
118 |    * Track SSG usage and infer preferences
119 |    */
120 |   async trackSSGUsage(event: SSGUsageEvent): Promise<void> {
121 |     if (!this.preferences) {
122 |       await this.initialize();
123 |     }
124 | 
125 |     const kg = await getKnowledgeGraph();
126 | 
127 |     // Find user node
128 |     const userNodeId = `user:${this.userId}`;
129 |     let userNode = await kg.findNode({
130 |       type: "user",
131 |       properties: { userId: this.userId },
132 |     });
133 | 
134 |     if (!userNode) {
135 |       userNode = kg.addNode({
136 |         id: userNodeId,
137 |         type: "user",
138 |         label: this.userId,
139 |         properties: {
140 |           userId: this.userId,
141 |           expertiseLevel: this.preferences!.expertiseLevel,
142 |           preferredSSGs: [],
143 |           preferredTechnologies: [],
144 |           documentationStyle: this.preferences!.documentationStyle,
145 |           projectCount: 0,
146 |           lastActive: new Date().toISOString(),
147 |           createdAt: new Date().toISOString(),
148 |         },
149 |         weight: 1.0,
150 |       });
151 |     }
152 | 
153 |     // Find or create configuration node
154 |     const configNodeId = `configuration:${event.ssg}`;
155 |     let configNode = await kg.findNode({
156 |       type: "configuration",
157 |       properties: { ssg: event.ssg },
158 |     });
159 | 
160 |     if (!configNode) {
161 |       configNode = kg.addNode({
162 |         id: configNodeId,
163 |         type: "configuration",
164 |         label: `${event.ssg} configuration`,
165 |         properties: {
166 |           ssg: event.ssg,
167 |           settings: {},
168 |           deploymentSuccessRate: event.success ? 1.0 : 0.0,
169 |           usageCount: 1,
170 |           lastUsed: event.timestamp,
171 |         },
172 |         weight: 1.0,
173 |       });
174 |     }
175 | 
176 |     // Create or update preference relationship
177 |     const existingEdges = await kg.findEdges({
178 |       source: userNode.id,
179 |       target: configNode.id,
180 |       type: "user_prefers_ssg",
181 |     });
182 | 
183 |     if (existingEdges.length > 0) {
184 |       // Update existing preference
185 |       const edge = existingEdges[0];
186 |       const currentCount = edge.properties.usageCount || 1;
187 |       const currentRate = edge.properties.successRate || 0.5;
188 | 
189 |       edge.properties.usageCount = currentCount + 1;
190 |       edge.properties.successRate =
191 |         (currentRate * currentCount + (event.success ? 1.0 : 0.0)) /
192 |         (currentCount + 1);
193 |       edge.properties.lastUsed = event.timestamp;
194 |       edge.weight = edge.properties.successRate;
195 |     } else {
196 |       // Create new preference relationship
197 |       kg.addEdge({
198 |         source: userNode.id,
199 |         target: configNode.id,
200 |         type: "user_prefers_ssg",
201 |         weight: event.success ? 1.0 : 0.5,
202 |         confidence: 1.0,
203 |         properties: {
204 |           usageCount: 1,
205 |           lastUsed: event.timestamp,
206 |           successRate: event.success ? 1.0 : 0.0,
207 |         },
208 |       });
209 |     }
210 | 
211 |     // Update user's preferred SSGs list based on success rate
212 |     await this.inferPreferredSSGs();
213 | 
214 |     await saveKnowledgeGraph();
215 |   }
216 | 
217 |   /**
218 |    * Infer preferred SSGs from usage history
219 |    */
220 |   private async inferPreferredSSGs(): Promise<void> {
221 |     if (!this.preferences) {
222 |       await this.initialize();
223 |     }
224 | 
225 |     const kg = await getKnowledgeGraph();
226 | 
227 |     // Find user node
228 |     const userNode = await kg.findNode({
229 |       type: "user",
230 |       properties: { userId: this.userId },
231 |     });
232 | 
233 |     if (!userNode) return;
234 | 
235 |     // Get all SSG preference edges
236 |     const preferenceEdges = await kg.findEdges({
237 |       source: userNode.id,
238 |       type: "user_prefers_ssg",
239 |     });
240 | 
241 |     // Calculate preference scores (usage count * success rate)
242 |     const ssgScores = new Map<string, number>();
243 | 
244 |     for (const edge of preferenceEdges) {
245 |       const configNode = (await kg.getAllNodes()).find(
246 |         (n) => n.id === edge.target,
247 |       );
248 |       if (configNode && configNode.type === "configuration") {
249 |         const ssg = configNode.properties.ssg;
250 |         const usageCount = edge.properties.usageCount || 1;
251 |         const successRate = edge.properties.successRate || 0.5;
252 | 
253 |         // Score = usage frequency * success rate
254 |         const score = usageCount * successRate;
255 |         ssgScores.set(ssg, score);
256 |       }
257 |     }
258 | 
259 |     // Sort by score and take top 3
260 |     const topSSGs = Array.from(ssgScores.entries())
261 |       .sort((a, b) => b[1] - a[1])
262 |       .slice(0, 3)
263 |       .map(([ssg]) => ssg);
264 | 
265 |     // Update preferences
266 |     this.preferences!.preferredSSGs = topSSGs;
267 |     this.preferences!.lastUpdated = new Date().toISOString();
268 | 
269 |     // Update user node
270 |     userNode.properties.preferredSSGs = topSSGs;
271 |   }
272 | 
273 |   /**
274 |    * Get SSG recommendations based on user preferences
275 |    */
276 |   async getSSGRecommendations(): Promise<
277 |     Array<{ ssg: string; score: number; reason: string }>
278 |   > {
279 |     if (!this.preferences) {
280 |       await this.initialize();
281 |     }
282 | 
283 |     const kg = await getKnowledgeGraph();
284 | 
285 |     // Find user node
286 |     const userNode = await kg.findNode({
287 |       type: "user",
288 |       properties: { userId: this.userId },
289 |     });
290 | 
291 |     if (!userNode) {
292 |       return [];
293 |     }
294 | 
295 |     // Get all SSG preference edges
296 |     const preferenceEdges = await kg.findEdges({
297 |       source: userNode.id,
298 |       type: "user_prefers_ssg",
299 |     });
300 | 
301 |     const recommendations: Array<{
302 |       ssg: string;
303 |       score: number;
304 |       reason: string;
305 |     }> = [];
306 | 
307 |     for (const edge of preferenceEdges) {
308 |       const configNode = (await kg.getAllNodes()).find(
309 |         (n) => n.id === edge.target,
310 |       );
311 | 
312 |       if (configNode && configNode.type === "configuration") {
313 |         const ssg = configNode.properties.ssg;
314 |         const usageCount = edge.properties.usageCount || 1;
315 |         const successRate = edge.properties.successRate || 0.5;
316 | 
317 |         // Calculate recommendation score
318 |         const score = usageCount * successRate;
319 | 
320 |         let reason = `Used ${usageCount} time(s)`;
321 |         if (successRate >= 0.8) {
322 |           reason += `, ${(successRate * 100).toFixed(0)}% success rate`;
323 |         } else if (successRate < 0.5) {
324 |           reason += `, only ${(successRate * 100).toFixed(0)}% success rate`;
325 |         }
326 | 
327 |         recommendations.push({ ssg, score, reason });
328 |       }
329 |     }
330 | 
331 |     return recommendations.sort((a, b) => b.score - a.score);
332 |   }
333 | 
334 |   /**
335 |    * Apply user preferences to a recommendation
336 |    */
337 |   applyPreferencesToRecommendation(
338 |     recommendation: string,
339 |     alternatives: string[],
340 |   ): { recommended: string; adjustmentReason?: string } {
341 |     if (!this.preferences || !this.preferences.autoApplyPreferences) {
342 |       return { recommended: recommendation };
343 |     }
344 | 
345 |     // Check if user has a strong preference
346 |     const preferredSSGs = this.preferences.preferredSSGs;
347 | 
348 |     if (preferredSSGs.length > 0) {
349 |       // If recommended SSG is already in preferences, keep it
350 |       if (preferredSSGs.includes(recommendation)) {
351 |         return {
352 |           recommended: recommendation,
353 |           adjustmentReason: "Matches your preferred SSG",
354 |         };
355 |       }
356 | 
357 |       // Check if any preferred SSG is in alternatives
358 |       for (const preferred of preferredSSGs) {
359 |         if (alternatives.includes(preferred)) {
360 |           return {
361 |             recommended: preferred,
362 |             adjustmentReason: `Switched to ${preferred} based on your usage history`,
363 |           };
364 |         }
365 |       }
366 |     }
367 | 
368 |     return { recommended: recommendation };
369 |   }
370 | 
371 |   /**
372 |    * Save preferences to knowledge graph
373 |    */
374 |   private async save(): Promise<void> {
375 |     if (!this.preferences) return;
376 | 
377 |     const kg = await getKnowledgeGraph();
378 | 
379 |     const userNodeId = `user:${this.userId}`;
380 |     const existingNode = await kg.findNode({
381 |       type: "user",
382 |       properties: { userId: this.userId },
383 |     });
384 | 
385 |     const userNode: GraphNode = {
386 |       id: existingNode?.id || userNodeId,
387 |       type: "user",
388 |       label: this.userId,
389 |       properties: {
390 |         userId: this.preferences.userId,
391 |         expertiseLevel: this.preferences.expertiseLevel,
392 |         preferredSSGs: this.preferences.preferredSSGs,
393 |         preferredTechnologies: this.preferences.preferredTechnologies,
394 |         documentationStyle: this.preferences.documentationStyle,
395 |         preferredDiataxisCategories:
396 |           this.preferences.preferredDiataxisCategories,
397 |         autoApplyPreferences: this.preferences.autoApplyPreferences,
398 |         projectCount: existingNode?.properties.projectCount || 0,
399 |         lastActive: this.preferences.lastUpdated,
400 |         createdAt:
401 |           existingNode?.properties.createdAt || this.preferences.lastUpdated,
402 |       },
403 |       weight: 1.0,
404 |       lastUpdated: this.preferences.lastUpdated,
405 |     };
406 | 
407 |     kg.addNode(userNode);
408 |     await saveKnowledgeGraph();
409 |   }
410 | 
411 |   /**
412 |    * Reset preferences to defaults
413 |    */
414 |   async resetPreferences(): Promise<UserPreferences> {
415 |     this.preferences = {
416 |       userId: this.userId,
417 |       preferredSSGs: [],
418 |       documentationStyle: "comprehensive",
419 |       expertiseLevel: "intermediate",
420 |       preferredTechnologies: [],
421 |       preferredDiataxisCategories: [],
422 |       autoApplyPreferences: true,
423 |       lastUpdated: new Date().toISOString(),
424 |     };
425 | 
426 |     await this.save();
427 |     return this.preferences;
428 |   }
429 | 
430 |   /**
431 |    * Export preferences as JSON
432 |    */
433 |   async exportPreferences(): Promise<string> {
434 |     if (!this.preferences) {
435 |       await this.initialize();
436 |     }
437 |     return JSON.stringify(this.preferences, null, 2);
438 |   }
439 | 
440 |   /**
441 |    * Import preferences from JSON
442 |    */
443 |   async importPreferences(json: string): Promise<UserPreferences> {
444 |     const imported = JSON.parse(json) as UserPreferences;
445 | 
446 |     // Validate userId matches
447 |     if (imported.userId !== this.userId) {
448 |       throw new Error(
449 |         `User ID mismatch: expected ${this.userId}, got ${imported.userId}`,
450 |       );
451 |     }
452 | 
453 |     this.preferences = {
454 |       ...imported,
455 |       lastUpdated: new Date().toISOString(),
456 |     };
457 | 
458 |     await this.save();
459 |     return this.preferences;
460 |   }
461 | }
462 | 
463 | /**
464 |  * Get or create a user preference manager instance
465 |  */
466 | const userPreferenceManagers = new Map<string, UserPreferenceManager>();
467 | 
468 | export async function getUserPreferenceManager(
469 |   userId: string = "default",
470 | ): Promise<UserPreferenceManager> {
471 |   if (!userPreferenceManagers.has(userId)) {
472 |     const manager = new UserPreferenceManager(userId);
473 |     await manager.initialize();
474 |     userPreferenceManagers.set(userId, manager);
475 |   }
476 |   return userPreferenceManagers.get(userId)!;
477 | }
478 | 
479 | /**
480 |  * Clear all cached preference managers (for testing)
481 |  */
482 | export function clearPreferenceManagerCache(): void {
483 |   userPreferenceManagers.clear();
484 | }
485 | 
```

--------------------------------------------------------------------------------
/src/workflows/documentation-workflow.ts:
--------------------------------------------------------------------------------

```typescript
  1 | // Documentation Workflow Guide for LLMs using DocuMCP MCP Server
  2 | 
  3 | export interface WorkflowStep {
  4 |   tool: string;
  5 |   description: string;
  6 |   requiredInputs: string[];
  7 |   outputs: string[];
  8 |   optional: boolean;
  9 |   alternatives?: string[];
 10 | }
 11 | 
 12 | export interface DocumentationWorkflow {
 13 |   name: string;
 14 |   description: string;
 15 |   useCase: string;
 16 |   steps: WorkflowStep[];
 17 |   estimatedTime: string;
 18 |   complexity: "simple" | "moderate" | "complex";
 19 | }
 20 | 
 21 | // Primary Documentation Creation Workflows
 22 | export const DOCUMENTATION_WORKFLOWS: Record<string, DocumentationWorkflow> = {
 23 |   // Complete end-to-end documentation setup
 24 |   "full-documentation-setup": {
 25 |     name: "Complete Documentation Setup",
 26 |     description:
 27 |       "Analyze repository, recommend SSG, create structure, populate content, and deploy",
 28 |     useCase:
 29 |       "Starting from scratch with a new project that needs comprehensive documentation",
 30 |     complexity: "complex",
 31 |     estimatedTime: "5-10 minutes",
 32 |     steps: [
 33 |       {
 34 |         tool: "analyze_repository",
 35 |         description:
 36 |           "Analyze the repository structure, dependencies, and documentation needs",
 37 |         requiredInputs: ["path"],
 38 |         outputs: ["analysisId", "projectMetadata", "technologyStack"],
 39 |         optional: false,
 40 |       },
 41 |       {
 42 |         tool: "recommend_ssg",
 43 |         description:
 44 |           "Get intelligent SSG recommendation based on project analysis",
 45 |         requiredInputs: ["analysisId"],
 46 |         outputs: ["recommendedSSG", "justification", "alternatives"],
 47 |         optional: false,
 48 |       },
 49 |       {
 50 |         tool: "generate_config",
 51 |         description: "Generate configuration files for the recommended SSG",
 52 |         requiredInputs: ["ssg", "projectName", "outputPath"],
 53 |         outputs: ["configFiles", "setupInstructions"],
 54 |         optional: false,
 55 |       },
 56 |       {
 57 |         tool: "setup_structure",
 58 |         description: "Create Diataxis-compliant documentation structure",
 59 |         requiredInputs: ["path", "ssg"],
 60 |         outputs: ["directoryStructure", "templateFiles"],
 61 |         optional: false,
 62 |       },
 63 |       {
 64 |         tool: "populate_diataxis_content",
 65 |         description: "Intelligently populate content based on project analysis",
 66 |         requiredInputs: ["analysisId", "docsPath"],
 67 |         outputs: ["generatedContent", "populationMetrics"],
 68 |         optional: false,
 69 |       },
 70 |       {
 71 |         tool: "validate_diataxis_content",
 72 |         description: "Validate generated content for accuracy and compliance",
 73 |         requiredInputs: ["contentPath"],
 74 |         outputs: ["validationResults", "recommendations"],
 75 |         optional: true,
 76 |       },
 77 |       {
 78 |         tool: "deploy_pages",
 79 |         description: "Set up GitHub Pages deployment workflow",
 80 |         requiredInputs: ["repository", "ssg"],
 81 |         outputs: ["deploymentWorkflow", "deploymentInstructions"],
 82 |         optional: true,
 83 |       },
 84 |     ],
 85 |   },
 86 | 
 87 |   // Quick documentation setup for existing projects
 88 |   "quick-documentation-setup": {
 89 |     name: "Quick Documentation Setup",
 90 |     description: "Rapid documentation creation using intelligent defaults",
 91 |     useCase:
 92 |       "Existing project needs documentation quickly with minimal customization",
 93 |     complexity: "simple",
 94 |     estimatedTime: "2-3 minutes",
 95 |     steps: [
 96 |       {
 97 |         tool: "analyze_repository",
 98 |         description: "Quick analysis of repository",
 99 |         requiredInputs: ["path"],
100 |         outputs: ["analysisId"],
101 |         optional: false,
102 |       },
103 |       {
104 |         tool: "setup_structure",
105 |         description:
106 |           "Create documentation structure with intelligent SSG selection",
107 |         requiredInputs: ["path"],
108 |         outputs: ["directoryStructure"],
109 |         optional: false,
110 |         alternatives: ["Use analyze_repository output to auto-select SSG"],
111 |       },
112 |       {
113 |         tool: "populate_diataxis_content",
114 |         description: "Auto-populate with project-specific content",
115 |         requiredInputs: ["analysisId", "docsPath"],
116 |         outputs: ["generatedContent"],
117 |         optional: false,
118 |       },
119 |     ],
120 |   },
121 | 
122 |   // Content-focused workflow for existing documentation
123 |   "enhance-existing-documentation": {
124 |     name: "Enhance Existing Documentation",
125 |     description: "Improve and populate existing documentation structure",
126 |     useCase:
127 |       "Project already has basic documentation that needs content and validation",
128 |     complexity: "moderate",
129 |     estimatedTime: "3-5 minutes",
130 |     steps: [
131 |       {
132 |         tool: "analyze_repository",
133 |         description: "Analyze repository and existing documentation",
134 |         requiredInputs: ["path"],
135 |         outputs: ["analysisId", "existingDocsAnalysis"],
136 |         optional: false,
137 |       },
138 |       {
139 |         tool: "validate_diataxis_content",
140 |         description: "Validate existing content and identify gaps",
141 |         requiredInputs: ["contentPath", "analysisId"],
142 |         outputs: ["validationResults", "contentGaps"],
143 |         optional: false,
144 |       },
145 |       {
146 |         tool: "populate_diataxis_content",
147 |         description: "Fill content gaps with intelligent population",
148 |         requiredInputs: ["analysisId", "docsPath", "preserveExisting: true"],
149 |         outputs: ["enhancedContent"],
150 |         optional: false,
151 |       },
152 |       {
153 |         tool: "validate_diataxis_content",
154 |         description: "Final validation of enhanced content",
155 |         requiredInputs: ["contentPath"],
156 |         outputs: ["finalValidation"],
157 |         optional: true,
158 |       },
159 |     ],
160 |   },
161 | 
162 |   // Deployment-focused workflow
163 |   "deployment-only": {
164 |     name: "Documentation Deployment Setup",
165 |     description: "Set up deployment for existing documentation",
166 |     useCase: "Documentation exists but needs automated deployment setup",
167 |     complexity: "simple",
168 |     estimatedTime: "1-2 minutes",
169 |     steps: [
170 |       {
171 |         tool: "analyze_repository",
172 |         description:
173 |           "Analyze repository structure for deployment configuration",
174 |         requiredInputs: ["path"],
175 |         outputs: ["deploymentContext"],
176 |         optional: true,
177 |       },
178 |       {
179 |         tool: "deploy_pages",
180 |         description: "Set up GitHub Pages deployment workflow",
181 |         requiredInputs: ["repository", "ssg"],
182 |         outputs: ["deploymentWorkflow"],
183 |         optional: false,
184 |       },
185 |       {
186 |         tool: "verify_deployment",
187 |         description: "Verify deployment configuration and test",
188 |         requiredInputs: ["repository"],
189 |         outputs: ["deploymentStatus", "troubleshootingInfo"],
190 |         optional: true,
191 |       },
192 |     ],
193 |   },
194 | 
195 |   // Validation and quality assurance workflow
196 |   "documentation-audit": {
197 |     name: "Documentation Quality Audit",
198 |     description: "Comprehensive validation and quality assessment",
199 |     useCase:
200 |       "Existing documentation needs quality assessment and improvement recommendations",
201 |     complexity: "moderate",
202 |     estimatedTime: "2-3 minutes",
203 |     steps: [
204 |       {
205 |         tool: "analyze_repository",
206 |         description: "Analyze repository for context-aware validation",
207 |         requiredInputs: ["path"],
208 |         outputs: ["analysisId", "projectContext"],
209 |         optional: false,
210 |       },
211 |       {
212 |         tool: "validate_diataxis_content",
213 |         description: "Comprehensive content validation with all checks",
214 |         requiredInputs: [
215 |           "contentPath",
216 |           "analysisId",
217 |           "validationType: all",
218 |           "confidence: strict",
219 |         ],
220 |         outputs: ["detailedValidation", "improvementPlan"],
221 |         optional: false,
222 |       },
223 |       {
224 |         tool: "verify_deployment",
225 |         description: "Validate deployment if applicable",
226 |         requiredInputs: ["repository"],
227 |         outputs: ["deploymentHealth"],
228 |         optional: true,
229 |       },
230 |     ],
231 |   },
232 | };
233 | 
234 | // Workflow Decision Helper
235 | export interface WorkflowRecommendation {
236 |   recommendedWorkflow: string;
237 |   reason: string;
238 |   alternativeWorkflows: string[];
239 |   customizationSuggestions: string[];
240 | }
241 | 
242 | export function recommendWorkflow(
243 |   projectStatus:
244 |     | "new"
245 |     | "existing-no-docs"
246 |     | "existing-basic-docs"
247 |     | "existing-full-docs",
248 |   requirements: {
249 |     needsDeployment?: boolean;
250 |     timeConstraint?: "minimal" | "moderate" | "comprehensive";
251 |     qualityFocus?: boolean;
252 |     customization?: "minimal" | "moderate" | "high";
253 |   },
254 | ): WorkflowRecommendation {
255 |   // New project or no documentation
256 |   if (projectStatus === "new" || projectStatus === "existing-no-docs") {
257 |     if (requirements.timeConstraint === "minimal") {
258 |       return {
259 |         recommendedWorkflow: "quick-documentation-setup",
260 |         reason:
261 |           "Fast setup with intelligent defaults for time-constrained scenario",
262 |         alternativeWorkflows: ["full-documentation-setup"],
263 |         customizationSuggestions: [
264 |           "Consider full-documentation-setup if time allows for better customization",
265 |           "Add deployment-only workflow later if needed",
266 |         ],
267 |       };
268 |     } else {
269 |       return {
270 |         recommendedWorkflow: "full-documentation-setup",
271 |         reason:
272 |           "Comprehensive setup provides best foundation for new documentation",
273 |         alternativeWorkflows: ["quick-documentation-setup"],
274 |         customizationSuggestions: [
275 |           "Skip deploy_pages step if deployment not needed immediately",
276 |           "Use validate_diataxis_content for quality assurance",
277 |         ],
278 |       };
279 |     }
280 |   }
281 | 
282 |   // Existing documentation that needs enhancement
283 |   if (projectStatus === "existing-basic-docs") {
284 |     if (requirements.qualityFocus) {
285 |       return {
286 |         recommendedWorkflow: "documentation-audit",
287 |         reason: "Quality-focused validation and improvement recommendations",
288 |         alternativeWorkflows: ["enhance-existing-documentation"],
289 |         customizationSuggestions: [
290 |           "Follow up with enhance-existing-documentation based on audit results",
291 |           "Consider deployment-only if deployment setup is needed",
292 |         ],
293 |       };
294 |     } else {
295 |       return {
296 |         recommendedWorkflow: "enhance-existing-documentation",
297 |         reason: "Improve and expand existing documentation content",
298 |         alternativeWorkflows: ["documentation-audit"],
299 |         customizationSuggestions: [
300 |           "Run documentation-audit first if quality is uncertain",
301 |           "Set preserveExisting: true in populate_diataxis_content",
302 |         ],
303 |       };
304 |     }
305 |   }
306 | 
307 |   // Full documentation that needs deployment or validation
308 |   if (projectStatus === "existing-full-docs") {
309 |     if (requirements.needsDeployment) {
310 |       return {
311 |         recommendedWorkflow: "deployment-only",
312 |         reason: "Focus on deployment setup for complete documentation",
313 |         alternativeWorkflows: ["documentation-audit"],
314 |         customizationSuggestions: [
315 |           "Run documentation-audit if quality validation is also needed",
316 |           "Consider verify_deployment for troubleshooting",
317 |         ],
318 |       };
319 |     } else {
320 |       return {
321 |         recommendedWorkflow: "documentation-audit",
322 |         reason:
323 |           "Quality assurance and validation for existing complete documentation",
324 |         alternativeWorkflows: ["deployment-only"],
325 |         customizationSuggestions: [
326 |           "Focus on validation aspects most relevant to your concerns",
327 |           "Use strict confidence level for thorough quality checking",
328 |         ],
329 |       };
330 |     }
331 |   }
332 | 
333 |   // Fallback
334 |   return {
335 |     recommendedWorkflow: "full-documentation-setup",
336 |     reason: "Default comprehensive workflow for unclear requirements",
337 |     alternativeWorkflows: ["quick-documentation-setup", "documentation-audit"],
338 |     customizationSuggestions: [
339 |       "Analyze your specific needs to choose a more targeted workflow",
340 |       "Consider running analyze_repository first to understand your project better",
341 |     ],
342 |   };
343 | }
344 | 
345 | // Workflow execution guidance for LLMs
346 | export const WORKFLOW_EXECUTION_GUIDANCE = {
347 |   description: "How LLMs should execute DocuMCP workflows",
348 |   principles: [
349 |     "Each tool can be called independently - workflows are guidance, not rigid requirements",
350 |     "Always check tool outputs before proceeding to next step",
351 |     "Adapt workflows based on user feedback and tool results",
352 |     "Skip optional steps if user has time constraints or different priorities",
353 |     "Use tool outputs (like analysisId) as inputs for subsequent tools",
354 |     "Validate critical assumptions before proceeding with deployment steps",
355 |   ],
356 |   errorHandling: [
357 |     "If a tool fails, provide clear error information to user",
358 |     "Suggest alternative approaches or simplified workflows",
359 |     "Don't abandon the entire workflow - adapt and continue with available information",
360 |     "Use verify_deployment and validate_diataxis_content for troubleshooting",
361 |   ],
362 |   customization: [
363 |     "Ask users about their priorities (speed vs quality, deployment needs, etc.)",
364 |     "Adapt tool parameters based on project analysis results",
365 |     "Suggest workflow modifications based on repository characteristics",
366 |     "Allow users to skip or modify steps based on their specific needs",
367 |   ],
368 | };
369 | 
370 | // Export workflow metadata for MCP resource exposure
371 | export const WORKFLOW_METADATA = {
372 |   totalWorkflows: Object.keys(DOCUMENTATION_WORKFLOWS).length,
373 |   workflowNames: Object.keys(DOCUMENTATION_WORKFLOWS),
374 |   complexityLevels: ["simple", "moderate", "complex"],
375 |   estimatedTimeRange: "1-10 minutes depending on workflow and project size",
376 |   toolsUsed: [
377 |     "analyze_repository",
378 |     "recommend_ssg",
379 |     "generate_config",
380 |     "setup_structure",
381 |     "populate_diataxis_content",
382 |     "validate_diataxis_content",
383 |     "deploy_pages",
384 |     "verify_deployment",
385 |   ],
386 | };
387 | 
```

--------------------------------------------------------------------------------
/docs/tutorials/environment-setup.md:
--------------------------------------------------------------------------------

```markdown
  1 | ---
  2 | documcp:
  3 |   last_updated: "2025-11-20T00:46:21.971Z"
  4 |   last_validated: "2025-11-20T00:46:21.971Z"
  5 |   auto_updated: false
  6 |   update_frequency: monthly
  7 | ---
  8 | 
  9 | # DocuMCP Environment Setup Guide
 10 | 
 11 | This guide will help you set up DocuMCP in your own environment, from basic installation to advanced configuration for team collaboration.
 12 | 
 13 | ## 🚀 Quick Setup
 14 | 
 15 | ### Prerequisites Check
 16 | 
 17 | Before installing DocuMCP, ensure you have the required software:
 18 | 
 19 | ```bash
 20 | # Check Node.js version (requires 20.0.0+)
 21 | node --version
 22 | 
 23 | # Check npm version (requires 8.0.0+)
 24 | npm --version
 25 | 
 26 | # Check Git version
 27 | git --version
 28 | 
 29 | # Check GitHub CLI (optional but recommended)
 30 | gh --version
 31 | ```
 32 | 
 33 | ### Installation Methods
 34 | 
 35 | #### Method 1: Global Installation (Recommended)
 36 | 
 37 | ```bash
 38 | # Install DocuMCP globally
 39 | npm install -g documcp
 40 | 
 41 | # Verify installation
 42 | documcp --version
 43 | # Should output: DocuMCP v0.5.0
 44 | ```
 45 | 
 46 | #### Method 2: Local Project Installation
 47 | 
 48 | ```bash
 49 | # Navigate to your project directory
 50 | cd /path/to/your/project
 51 | 
 52 | # Install DocuMCP as a dev dependency
 53 | npm install documcp --save-dev
 54 | 
 55 | # Add to package.json scripts
 56 | npm pkg set scripts.docs="documcp"
 57 | npm pkg set scripts.docs:analyze="documcp analyze-repository --path ."
 58 | npm pkg set scripts.docs:deploy="documcp deploy-pages --repository $(git remote get-url origin | sed 's/.*github.com[:/]\([^.]*\).*/\1/')"
 59 | ```
 60 | 
 61 | #### Method 3: Docker Installation
 62 | 
 63 | ```bash
 64 | # Pull the official DocuMCP Docker image
 65 | docker pull documcp/documcp:latest
 66 | 
 67 | # Run DocuMCP in a container
 68 | docker run -it --rm -v $(pwd):/workspace documcp/documcp:latest
 69 | ```
 70 | 
 71 | ## 🔧 Basic Configuration
 72 | 
 73 | ### Environment Variables
 74 | 
 75 | Create a `.env` file in your project root:
 76 | 
 77 | ```bash
 78 | # DocuMCP Configuration
 79 | export DOCUMCP_STORAGE_DIR="./.documcp"
 80 | export DOCUMCP_LOG_LEVEL="info"
 81 | export DOCUMCP_CACHE_ENABLED="true"
 82 | 
 83 | # GitHub Integration
 84 | export GITHUB_TOKEN="your_github_token_here"
 85 | export GITHUB_USERNAME="your_username"
 86 | 
 87 | # Optional: Custom configuration
 88 | export DOCUMCP_DEFAULT_SSG="docusaurus"
 89 | export DOCUMCP_DEFAULT_DEPTH="standard"
 90 | ```
 91 | 
 92 | ### Configuration File
 93 | 
 94 | Create a `documcp.config.json` file:
 95 | 
 96 | ```json
 97 | {
 98 |   "storage": {
 99 |     "directory": "./.documcp",
100 |     "enableCache": true,
101 |     "maxCacheSize": "100MB"
102 |   },
103 |   "github": {
104 |     "token": "${GITHUB_TOKEN}",
105 |     "username": "${GITHUB_USERNAME}",
106 |     "defaultBranch": "main"
107 |   },
108 |   "defaults": {
109 |     "ssg": "docusaurus",
110 |     "analysisDepth": "standard",
111 |     "includeExamples": true,
112 |     "targetAudience": "community_contributors"
113 |   },
114 |   "memory": {
115 |     "enableLearning": true,
116 |     "retentionDays": 90,
117 |     "enableAnalytics": true
118 |   }
119 | }
120 | ```
121 | 
122 | ## 🏗️ Project Structure Setup
123 | 
124 | ### Recommended Project Structure
125 | 
126 | ```
127 | your-project/
128 | ├── .documcp/                 # DocuMCP storage and cache
129 | │   ├── memory/              # Memory system data
130 | │   ├── cache/               # Analysis cache
131 | │   └── config/              # Local configuration
132 | ├── docs/                    # Generated documentation
133 | │   ├── api/                 # API documentation
134 | │   ├── tutorials/           # Tutorial content
135 | │   ├── how-to/              # How-to guides
136 | │   ├── reference/           # Reference documentation
137 | │   └── explanation/         # Explanatory content
138 | ├── src/                     # Source code
139 | ├── README.md                # Project README
140 | ├── documcp.config.json      # DocuMCP configuration
141 | ├── .env                     # Environment variables
142 | └── package.json             # Node.js dependencies
143 | ```
144 | 
145 | ### Initialize DocuMCP in Your Project
146 | 
147 | ```bash
148 | # Initialize DocuMCP in your project
149 | documcp init
150 | 
151 | # This creates:
152 | # - .documcp/ directory
153 | # - documcp.config.json
154 | # - .env template
155 | # - .gitignore entries
156 | ```
157 | 
158 | ## 🔐 GitHub Integration Setup
159 | 
160 | ### GitHub Token Setup
161 | 
162 | 1. **Create a GitHub Personal Access Token:**
163 | 
164 |    Go to GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic)
165 | 
166 |    Required permissions:
167 | 
168 |    - `repo` (Full control of private repositories)
169 |    - `pages` (Write access to GitHub Pages)
170 |    - `workflow` (Update GitHub Action workflows)
171 |    - `read:org` (Read organization membership)
172 | 
173 | 2. **Set the token in your environment:**
174 | 
175 |    ```bash
176 |    # Add to your shell profile (.bashrc, .zshrc, etc.)
177 |    export GITHUB_TOKEN="ghp_your_token_here"
178 | 
179 |    # Or add to .env file
180 |    echo "GITHUB_TOKEN=ghp_your_token_here" >> .env
181 |    ```
182 | 
183 | 3. **Verify GitHub integration:**
184 | 
185 |    ```bash
186 |    # Test GitHub connection
187 |    documcp github test
188 | 
189 |    # Should output: ✅ GitHub connection successful
190 |    ```
191 | 
192 | ### GitHub Pages Setup
193 | 
194 | 1. **Enable GitHub Pages in your repository:**
195 | 
196 |    Go to your repository → Settings → Pages
197 | 
198 |    - Source: GitHub Actions
199 |    - Branch: main (or your preferred branch)
200 | 
201 | 2. **Configure deployment:**
202 | 
203 |    ```bash
204 |    # Configure GitHub Pages deployment
205 |    documcp github configure-pages --repository "username/repository"
206 |    ```
207 | 
208 | ## 🧠 Memory System Setup
209 | 
210 | ### Initialize Memory System
211 | 
212 | ```bash
213 | # Initialize memory system with custom storage
214 | documcp memory init --storage-dir ./.documcp/memory
215 | 
216 | # Initialize with specific configuration
217 | documcp memory init --storage-dir ./.documcp/memory --enable-learning --retention-days 90
218 | ```
219 | 
220 | ### Memory System Configuration
221 | 
222 | Create a memory configuration file:
223 | 
224 | ```json
225 | {
226 |   "storage": {
227 |     "directory": "./.documcp/memory",
228 |     "enableCompression": true,
229 |     "maxSize": "500MB"
230 |   },
231 |   "learning": {
232 |     "enabled": true,
233 |     "retentionDays": 90,
234 |     "enableAnalytics": true,
235 |     "enablePatternRecognition": true
236 |   },
237 |   "userPreferences": {
238 |     "enablePersonalization": true,
239 |     "defaultUserId": "developer123"
240 |   }
241 | }
242 | ```
243 | 
244 | ### Memory System Testing
245 | 
246 | ```bash
247 | # Test memory system
248 | documcp memory test
249 | 
250 | # Check memory statistics
251 | documcp memory stats
252 | 
253 | # Export memories for backup
254 | documcp memory export --format json --output ./documcp-memories-backup.json
255 | ```
256 | 
257 | ## 🔧 Advanced Configuration
258 | 
259 | ### Custom SSG Configuration
260 | 
261 | ```bash
262 | # Configure custom SSG settings
263 | documcp config set --key "ssg.docusaurus.theme" --value "classic"
264 | documcp config set --key "ssg.hugo.baseURL" --value "https://docs.example.com"
265 | documcp config set --key "ssg.mkdocs.theme" --value "material"
266 | ```
267 | 
268 | ### User Preferences Setup
269 | 
270 | ```bash
271 | # Set user preferences
272 | documcp preferences set --user-id "developer123" --priority performance --ecosystem javascript
273 | 
274 | # Set team preferences
275 | documcp preferences set --user-id "team" --priority simplicity --ecosystem any
276 | 
277 | # Export preferences
278 | documcp preferences export --user-id "developer123" --output ./preferences.json
279 | ```
280 | 
281 | ### Cache Configuration
282 | 
283 | ```bash
284 | # Configure caching
285 | documcp cache config --enable --max-size "200MB" --ttl "24h"
286 | 
287 | # Clear cache
288 | documcp cache clear
289 | 
290 | # Cache statistics
291 | documcp cache stats
292 | ```
293 | 
294 | ## 🐳 Docker Setup
295 | 
296 | ### Docker Compose Configuration
297 | 
298 | Create a `docker-compose.yml` file:
299 | 
300 | ```yaml
301 | version: "3.8"
302 | 
303 | services:
304 |   documcp:
305 |     image: documcp/documcp:latest
306 |     container_name: documcp
307 |     volumes:
308 |       - ./:/workspace
309 |       - ./documcp-data:/app/.documcp
310 |     environment:
311 |       - GITHUB_TOKEN=${GITHUB_TOKEN}
312 |       - DOCUMCP_STORAGE_DIR=/app/.documcp
313 |     working_dir: /workspace
314 |     command: ["documcp", "serve", "--port", "3000", "--host", "0.0.0.0"]
315 |     ports:
316 |       - "3000:3000"
317 | ```
318 | 
319 | ### Docker Usage
320 | 
321 | ```bash
322 | # Start DocuMCP with Docker Compose
323 | docker-compose up -d
324 | 
325 | # Run specific commands
326 | docker-compose exec documcp documcp analyze-repository --path .
327 | 
328 | # Stop services
329 | docker-compose down
330 | ```
331 | 
332 | ## 🔄 CI/CD Integration
333 | 
334 | ### GitHub Actions Setup
335 | 
336 | Create `.github/workflows/docs.yml`:
337 | 
338 | ```yaml
339 | name: Documentation Deployment
340 | 
341 | on:
342 |   push:
343 |     branches: [main]
344 |     paths: ["docs/**", "src/**", "README.md"]
345 |   pull_request:
346 |     branches: [main]
347 | 
348 | jobs:
349 |   analyze:
350 |     runs-on: ubuntu-latest
351 |     steps:
352 |       - uses: actions/checkout@v4
353 | 
354 |       - name: Setup Node.js
355 |         uses: actions/setup-node@v4
356 |         with:
357 |           node-version: "20"
358 | 
359 |       - name: Install DocuMCP
360 |         run: npm install -g documcp
361 | 
362 |       - name: Analyze Repository
363 |         run: |
364 |           ANALYSIS_ID=$(documcp analyze-repository --path . --depth standard | jq -r '.data.id')
365 |           echo "analysis_id=$ANALYSIS_ID" >> $GITHUB_OUTPUT
366 |         id: analyze
367 | 
368 |       - name: Validate Documentation
369 |         run: |
370 |           documcp validate-content --docs-path ./docs
371 | 
372 |   deploy:
373 |     needs: analyze
374 |     runs-on: ubuntu-latest
375 |     if: github.ref == 'refs/heads/main'
376 |     steps:
377 |       - uses: actions/checkout@v4
378 | 
379 |       - name: Setup Node.js
380 |         uses: actions/setup-node@v4
381 |         with:
382 |           node-version: "20"
383 | 
384 |       - name: Install DocuMCP
385 |         run: npm install -g documcp
386 | 
387 |       - name: Deploy Documentation
388 |         run: |
389 |           documcp deploy-pages --repository ${{ github.repository }} --ssg docusaurus
390 |         env:
391 |           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
392 | ```
393 | 
394 | ### GitLab CI Setup
395 | 
396 | Create `.gitlab-ci.yml`:
397 | 
398 | ```yaml
399 | stages:
400 |   - analyze
401 |   - deploy
402 | 
403 | variables:
404 |   NODE_VERSION: "20"
405 | 
406 | analyze:
407 |   stage: analyze
408 |   image: node:${NODE_VERSION}-alpine
409 |   before_script:
410 |     - npm install -g documcp
411 |   script:
412 |     - documcp analyze-repository --path . --depth standard
413 |     - documcp validate-content --docs-path ./docs
414 |   artifacts:
415 |     reports:
416 |       junit: documcp-results.xml
417 |     paths:
418 |       - .documcp/
419 |     expire_in: 1 hour
420 | 
421 | deploy:
422 |   stage: deploy
423 |   image: node:${NODE_VERSION}-alpine
424 |   before_script:
425 |     - npm install -g documcp
426 |   script:
427 |     - documcp deploy-pages --repository $CI_PROJECT_PATH --ssg docusaurus
428 |   only:
429 |     - main
430 |   environment:
431 |     name: production
432 |     url: https://$CI_PROJECT_NAMESPACE.gitlab.io/$CI_PROJECT_NAME
433 | ```
434 | 
435 | ## 🔍 Development Setup
436 | 
437 | ### Local Development
438 | 
439 | ```bash
440 | # Clone DocuMCP repository
441 | git clone https://github.com/tosin2013/documcp.git
442 | cd documcp
443 | 
444 | # Install dependencies
445 | npm install
446 | 
447 | # Build the project
448 | npm run build
449 | 
450 | # Run in development mode
451 | npm run dev
452 | 
453 | # Run tests
454 | npm test
455 | 
456 | # Run linting
457 | npm run lint
458 | ```
459 | 
460 | ### IDE Configuration
461 | 
462 | #### VS Code Configuration
463 | 
464 | Create `.vscode/settings.json`:
465 | 
466 | ```json
467 | {
468 |   "typescript.preferences.importModuleSpecifier": "relative",
469 |   "typescript.suggest.autoImports": true,
470 |   "editor.formatOnSave": true,
471 |   "editor.codeActionsOnSave": {
472 |     "source.fixAll.eslint": true
473 |   },
474 |   "files.associations": {
475 |     "*.mcp": "json"
476 |   }
477 | }
478 | ```
479 | 
480 | #### VS Code Extensions
481 | 
482 | Recommended extensions:
483 | 
484 | - TypeScript and JavaScript Language Features
485 | - ESLint
486 | - Prettier
487 | - GitLens
488 | - REST Client (for testing API endpoints)
489 | 
490 | ## 🧪 Testing Setup
491 | 
492 | ### Unit Testing
493 | 
494 | ```bash
495 | # Install testing dependencies
496 | npm install --save-dev jest @types/jest ts-jest
497 | 
498 | # Create jest.config.js
499 | cat > jest.config.js << EOF
500 | module.exports = {
501 |   preset: 'ts-jest',
502 |   testEnvironment: 'node',
503 |   testMatch: ['**/__tests__/**/*.test.ts'],
504 |   collectCoverage: true,
505 |   coverageDirectory: 'coverage',
506 |   coverageReporters: ['text', 'lcov', 'html']
507 | };
508 | EOF
509 | 
510 | # Run tests
511 | npm test
512 | ```
513 | 
514 | ### Integration Testing
515 | 
516 | ```bash
517 | # Create test repository
518 | mkdir test-repo
519 | cd test-repo
520 | git init
521 | echo "# Test Repository" > README.md
522 | git add README.md
523 | git commit -m "Initial commit"
524 | 
525 | # Test DocuMCP with test repository
526 | cd ..
527 | documcp analyze-repository --path ./test-repo --depth quick
528 | ```
529 | 
530 | ### Performance Testing
531 | 
532 | ```bash
533 | # Run performance benchmarks
534 | documcp benchmark run --repository ./test-repo --iterations 10
535 | 
536 | # Check performance metrics
537 | documcp benchmark current
538 | ```
539 | 
540 | ## 🔧 Troubleshooting
541 | 
542 | ### Common Issues
543 | 
544 | #### Issue 1: Permission Denied
545 | 
546 | **Problem:** `Permission denied: Cannot read directory`
547 | 
548 | **Solution:**
549 | 
550 | ```bash
551 | # Check permissions
552 | ls -la /path/to/repository
553 | 
554 | # Fix permissions
555 | chmod -R 755 /path/to/repository
556 | 
557 | # Or run with sudo (not recommended for production)
558 | sudo documcp analyze-repository --path /path/to/repository
559 | ```
560 | 
561 | #### Issue 2: GitHub Token Invalid
562 | 
563 | **Problem:** `GitHub authentication failed`
564 | 
565 | **Solution:**
566 | 
567 | ```bash
568 | # Check token validity
569 | curl -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/user
570 | 
571 | # Regenerate token with correct permissions
572 | # Go to GitHub → Settings → Developer settings → Personal access tokens
573 | 
574 | # Update environment variable
575 | export GITHUB_TOKEN="new_token_here"
576 | ```
577 | 
578 | #### Issue 3: Memory System Errors
579 | 
580 | **Problem:** `Memory system initialization failed`
581 | 
582 | **Solution:**
583 | 
584 | ```bash
585 | # Clear memory storage
586 | rm -rf ./.documcp/memory
587 | 
588 | # Reinitialize memory system
589 | documcp memory init --storage-dir ./.documcp/memory
590 | 
591 | # Check memory system status
592 | documcp memory status
593 | ```
594 | 
595 | #### Issue 4: Build Failures
596 | 
597 | **Problem:** `Documentation build failed`
598 | 
599 | **Solution:**
600 | 
601 | ```bash
602 | # Check for syntax errors
603 | documcp validate-content --docs-path ./docs
604 | 
605 | # Test local build
606 | documcp test-local --docs-path ./docs --ssg docusaurus
607 | 
608 | # Check SSG configuration
609 | cat ./docs/docusaurus.config.js
610 | ```
611 | 
612 | ### Debug Mode
613 | 
614 | ```bash
615 | # Enable debug logging
616 | export DOCUMCP_LOG_LEVEL="debug"
617 | 
618 | # Run with verbose output
619 | documcp analyze-repository --path . --depth standard --verbose
620 | 
621 | # Check logs
622 | tail -f ./.documcp/logs/documcp.log
623 | ```
624 | 
625 | ### Health Check
626 | 
627 | ```bash
628 | # Run comprehensive health check
629 | documcp health-check
630 | 
631 | # Should output:
632 | # ✅ Node.js version: v20.0.0
633 | # ✅ npm version: 8.0.0
634 | # ✅ Git version: 2.30.0
635 | # ✅ GitHub token: valid
636 | # ✅ Memory system: healthy
637 | # ✅ Cache system: healthy
638 | ```
639 | 
640 | ## 📚 Next Steps
641 | 
642 | After completing the environment setup:
643 | 
644 | 1. **Read the [User Onboarding Guide](./user-onboarding.md)** for usage patterns
645 | 2. **Explore [Usage Examples](../how-to/usage-examples.md)** for practical examples
646 | 3. **Check the [API Reference](/api/)** for complete function documentation
647 | 4. **Join the [GitHub Issues](https://github.com/tosin2013/documcp/issues)** for community support and feature requests
648 | 
649 | ## 🆘 Getting Help
650 | 
651 | - **Documentation**: Check the comprehensive documentation
652 | - **GitHub Issues**: Report bugs and request features
653 | - **GitHub Discussions**: Ask questions and share ideas
654 | - **Community**: Join the DocuMCP community for support
655 | 
656 | Your DocuMCP environment is now ready! 🎉
657 | 
```

--------------------------------------------------------------------------------
/src/memory/freshness-kg-integration.ts:
--------------------------------------------------------------------------------

```typescript
  1 | /**
  2 |  * Documentation Freshness Knowledge Graph Integration
  3 |  *
  4 |  * Provides functions for storing and retrieving documentation freshness
  5 |  * tracking events in the Knowledge Graph for historical analysis and insights.
  6 |  */
  7 | 
  8 | import { getKnowledgeGraph, getKGStorage } from "./kg-integration.js";
  9 | import type {
 10 |   DocumentationFreshnessEventEntity,
 11 |   ProjectHasFreshnessEventRelationship,
 12 | } from "./schemas.js";
 13 | import type { FreshnessScanReport } from "../utils/freshness-tracker.js";
 14 | import crypto from "crypto";
 15 | 
 16 | /**
 17 |  * Generate a unique ID for a freshness event
 18 |  */
 19 | function generateFreshnessEventId(
 20 |   projectPath: string,
 21 |   timestamp: string,
 22 | ): string {
 23 |   const hash = crypto
 24 |     .createHash("sha256")
 25 |     .update(`${projectPath}:${timestamp}`)
 26 |     .digest("hex")
 27 |     .substring(0, 16);
 28 |   return `freshness_event:${hash}`;
 29 | }
 30 | 
 31 | /**
 32 |  * Generate a project ID from project path
 33 |  */
 34 | function generateProjectId(projectPath: string): string {
 35 |   const hash = crypto
 36 |     .createHash("sha256")
 37 |     .update(projectPath)
 38 |     .digest("hex")
 39 |     .substring(0, 16);
 40 |   return `project:${hash}`;
 41 | }
 42 | 
 43 | /**
 44 |  * Store a documentation freshness scan event in the Knowledge Graph
 45 |  */
 46 | export async function storeFreshnessEvent(
 47 |   projectPath: string,
 48 |   docsPath: string,
 49 |   report: FreshnessScanReport,
 50 |   eventType: "scan" | "validation" | "initialization" | "update" = "scan",
 51 | ): Promise<string> {
 52 |   const kg = await getKnowledgeGraph();
 53 |   const storage = await getKGStorage();
 54 | 
 55 |   const timestamp = new Date().toISOString();
 56 |   const eventId = generateFreshnessEventId(projectPath, timestamp);
 57 |   const projectId = generateProjectId(projectPath);
 58 | 
 59 |   // Calculate average age in days
 60 |   const filesWithAge = report.files.filter((f) => f.ageInMs !== undefined);
 61 |   const averageAge =
 62 |     filesWithAge.length > 0
 63 |       ? filesWithAge.reduce((sum, f) => sum + (f.ageInMs || 0), 0) /
 64 |         filesWithAge.length /
 65 |         (1000 * 60 * 60 * 24)
 66 |       : undefined;
 67 | 
 68 |   // Find oldest file
 69 |   const oldestFile =
 70 |     filesWithAge.length > 0
 71 |       ? filesWithAge.reduce((oldest, current) =>
 72 |           (current.ageInMs || 0) > (oldest.ageInMs || 0) ? current : oldest,
 73 |         )
 74 |       : undefined;
 75 | 
 76 |   // Get most stale files (critical and stale)
 77 |   const mostStaleFiles = report.files
 78 |     .filter(
 79 |       (f) => f.stalenessLevel === "critical" || f.stalenessLevel === "stale",
 80 |     )
 81 |     .sort((a, b) => (b.ageInMs || 0) - (a.ageInMs || 0))
 82 |     .slice(0, 10)
 83 |     .map((f) => f.relativePath);
 84 | 
 85 |   // Create freshness event entity
 86 |   const freshnessEntity: DocumentationFreshnessEventEntity = {
 87 |     docsPath,
 88 |     projectPath,
 89 |     scannedAt: report.scannedAt,
 90 |     totalFiles: report.totalFiles,
 91 |     freshFiles: report.freshFiles,
 92 |     warningFiles: report.warningFiles,
 93 |     staleFiles: report.staleFiles,
 94 |     criticalFiles: report.criticalFiles,
 95 |     filesWithoutMetadata: report.filesWithoutMetadata,
 96 |     thresholds: report.thresholds,
 97 |     averageAge,
 98 |     oldestFile: oldestFile
 99 |       ? {
100 |           path: oldestFile.relativePath,
101 |           ageInDays: (oldestFile.ageInMs || 0) / (1000 * 60 * 60 * 24),
102 |         }
103 |       : undefined,
104 |     mostStaleFiles,
105 |     eventType,
106 |   };
107 | 
108 |   // Add entity to knowledge graph
109 |   kg.addNode({
110 |     id: eventId,
111 |     type: "documentation_freshness_event",
112 |     label: `Freshness Event ${timestamp}`,
113 |     properties: freshnessEntity,
114 |     weight: 1.0,
115 |   });
116 | 
117 |   // Check if project node exists via async findNode, if not, create a minimal one
118 |   const projectNode = await kg.findNode({
119 |     type: "project",
120 |     properties: { path: projectPath },
121 |   });
122 |   if (!projectNode) {
123 |     kg.addNode({
124 |       id: projectId,
125 |       type: "project",
126 |       label: projectPath.split("/").pop() || "Unknown Project",
127 |       properties: {
128 |         name: projectPath.split("/").pop() || "Unknown",
129 |         path: projectPath,
130 |         createdAt: timestamp,
131 |       },
132 |       weight: 1.0,
133 |     });
134 |   }
135 | 
136 |   // Calculate improvement score (0-1, higher is better)
137 |   const improvementScore =
138 |     report.totalFiles > 0
139 |       ? (report.freshFiles +
140 |           report.warningFiles * 0.7 +
141 |           report.staleFiles * 0.3) /
142 |         report.totalFiles
143 |       : 1.0;
144 | 
145 |   // Create relationship between project and freshness event
146 |   const relationship: ProjectHasFreshnessEventRelationship = {
147 |     type: "project_has_freshness_event",
148 |     eventType,
149 |     filesScanned: report.totalFiles,
150 |     freshFiles: report.freshFiles,
151 |     staleFiles: report.staleFiles,
152 |     criticalFiles: report.criticalFiles,
153 |     filesInitialized: 0, // This will be updated by validation events
154 |     filesUpdated: 0, // This will be updated by update events
155 |     averageStaleness: averageAge,
156 |     improvementScore,
157 |     weight: 1.0,
158 |     confidence: 1.0,
159 |     createdAt: timestamp,
160 |     lastUpdated: timestamp,
161 |     metadata: {
162 |       docsPath,
163 |       thresholds: report.thresholds,
164 |     },
165 |   };
166 | 
167 |   kg.addEdge({
168 |     source: projectId,
169 |     target: eventId,
170 |     type: "project_has_freshness_event",
171 |     weight: 1.0,
172 |     confidence: 1.0,
173 |     properties: relationship,
174 |   });
175 | 
176 |   // Persist to storage
177 |   const nodes = await kg.getAllNodes();
178 |   const edges = await kg.getAllEdges();
179 |   await storage.saveGraph(nodes, edges);
180 | 
181 |   return eventId;
182 | }
183 | 
184 | /**
185 |  * Update a freshness event with validation/update results
186 |  */
187 | export async function updateFreshnessEvent(
188 |   eventId: string,
189 |   updates: {
190 |     filesInitialized?: number;
191 |     filesUpdated?: number;
192 |     eventType?: "scan" | "validation" | "initialization" | "update";
193 |   },
194 | ): Promise<void> {
195 |   const kg = await getKnowledgeGraph();
196 |   const storage = await getKGStorage();
197 | 
198 |   // Find event node by ID
199 |   const eventNode = await kg.getNodeById(eventId);
200 |   if (!eventNode) {
201 |     throw new Error(`Freshness event not found: ${eventId}`);
202 |   }
203 | 
204 |   // Update entity properties
205 |   if (updates.eventType) {
206 |     eventNode.properties.eventType = updates.eventType;
207 |   }
208 |   eventNode.lastUpdated = new Date().toISOString();
209 | 
210 |   // Find and update the relationship
211 |   const relEdges = await kg.findEdges({
212 |     target: eventId,
213 |     type: "project_has_freshness_event",
214 |   });
215 | 
216 |   for (const edge of relEdges) {
217 |     const props = edge.properties as ProjectHasFreshnessEventRelationship;
218 |     if (updates.filesInitialized !== undefined) {
219 |       props.filesInitialized = updates.filesInitialized;
220 |     }
221 |     if (updates.filesUpdated !== undefined) {
222 |       props.filesUpdated = updates.filesUpdated;
223 |     }
224 |     if (updates.eventType) {
225 |       props.eventType = updates.eventType;
226 |     }
227 |     edge.lastUpdated = new Date().toISOString();
228 |   }
229 | 
230 |   // Persist to storage
231 |   const allNodes = await kg.getAllNodes();
232 |   const allEdges = await kg.getAllEdges();
233 |   await storage.saveGraph(allNodes, allEdges);
234 | }
235 | 
236 | /**
237 |  * Get freshness event history for a project
238 |  */
239 | export async function getFreshnessHistory(
240 |   projectPath: string,
241 |   limit: number = 10,
242 | ): Promise<
243 |   Array<{
244 |     eventId: string;
245 |     event: DocumentationFreshnessEventEntity;
246 |     relationship: ProjectHasFreshnessEventRelationship;
247 |   }>
248 | > {
249 |   const kg = await getKnowledgeGraph();
250 |   const projectId = generateProjectId(projectPath);
251 | 
252 |   const edges = await kg.findEdges({
253 |     source: projectId,
254 |     type: "project_has_freshness_event",
255 |   });
256 | 
257 |   // Sort by timestamp (most recent first)
258 |   const sorted = await Promise.all(
259 |     edges.map(async (edge) => {
260 |       const eventNode = await kg.getNodeById(edge.target);
261 |       if (!eventNode || eventNode.type !== "documentation_freshness_event") {
262 |         return null;
263 |       }
264 | 
265 |       return {
266 |         eventId: edge.target,
267 |         event: eventNode.properties as DocumentationFreshnessEventEntity,
268 |         relationship: edge.properties as ProjectHasFreshnessEventRelationship,
269 |         timestamp: (eventNode.properties as DocumentationFreshnessEventEntity)
270 |           .scannedAt,
271 |       };
272 |     }),
273 |   );
274 | 
275 |   const filtered = sorted
276 |     .filter((item): item is NonNullable<typeof item> => item !== null)
277 |     .sort(
278 |       (a, b) =>
279 |         new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime(),
280 |     )
281 |     .slice(0, limit);
282 | 
283 |   return filtered.map(({ eventId, event, relationship }) => ({
284 |     eventId,
285 |     event,
286 |     relationship,
287 |   }));
288 | }
289 | 
290 | /**
291 |  * Get staleness insights for a project
292 |  */
293 | export async function getStalenessInsights(projectPath: string): Promise<{
294 |   totalEvents: number;
295 |   averageImprovementScore: number;
296 |   trend: "improving" | "declining" | "stable";
297 |   currentStatus: {
298 |     freshFiles: number;
299 |     staleFiles: number;
300 |     criticalFiles: number;
301 |     totalFiles: number;
302 |   } | null;
303 |   recommendations: string[];
304 | }> {
305 |   const history = await getFreshnessHistory(projectPath, 100);
306 | 
307 |   if (history.length === 0) {
308 |     return {
309 |       totalEvents: 0,
310 |       averageImprovementScore: 0,
311 |       trend: "stable",
312 |       currentStatus: null,
313 |       recommendations: [
314 |         "No freshness tracking history found. Run track_documentation_freshness to begin monitoring.",
315 |       ],
316 |     };
317 |   }
318 | 
319 |   // Calculate average improvement score
320 |   const avgScore =
321 |     history.reduce(
322 |       (sum, h) => sum + (h.relationship.improvementScore || 0),
323 |       0,
324 |     ) / history.length;
325 | 
326 |   // Determine trend (compare first half to second half)
327 |   const midpoint = Math.floor(history.length / 2);
328 |   const recentScore =
329 |     history
330 |       .slice(0, midpoint)
331 |       .reduce((sum, h) => sum + (h.relationship.improvementScore || 0), 0) /
332 |     Math.max(midpoint, 1);
333 |   const olderScore =
334 |     history
335 |       .slice(midpoint)
336 |       .reduce((sum, h) => sum + (h.relationship.improvementScore || 0), 0) /
337 |     Math.max(history.length - midpoint, 1);
338 | 
339 |   let trend: "improving" | "declining" | "stable";
340 |   if (recentScore > olderScore + 0.1) {
341 |     trend = "improving";
342 |   } else if (recentScore < olderScore - 0.1) {
343 |     trend = "declining";
344 |   } else {
345 |     trend = "stable";
346 |   }
347 | 
348 |   // Get current status from most recent event
349 |   const latest = history[0];
350 |   const currentStatus = {
351 |     freshFiles: latest.event.freshFiles,
352 |     staleFiles: latest.event.staleFiles,
353 |     criticalFiles: latest.event.criticalFiles,
354 |     totalFiles: latest.event.totalFiles,
355 |   };
356 | 
357 |   // Generate recommendations
358 |   const recommendations: string[] = [];
359 | 
360 |   if (currentStatus.criticalFiles > 0) {
361 |     recommendations.push(
362 |       `🔴 ${currentStatus.criticalFiles} files are critically stale and need immediate attention`,
363 |     );
364 |   }
365 | 
366 |   if (currentStatus.staleFiles > currentStatus.totalFiles * 0.3) {
367 |     recommendations.push(
368 |       `🟠 Over 30% of documentation is stale. Consider running validate_documentation_freshness`,
369 |     );
370 |   }
371 | 
372 |   if (trend === "declining") {
373 |     recommendations.push(
374 |       "📉 Documentation freshness is declining. Review update processes and automation",
375 |     );
376 |   } else if (trend === "improving") {
377 |     recommendations.push(
378 |       "📈 Documentation freshness is improving. Keep up the good work!",
379 |     );
380 |   }
381 | 
382 |   if (latest.event.filesWithoutMetadata > 0) {
383 |     recommendations.push(
384 |       `⚠️ ${latest.event.filesWithoutMetadata} files lack freshness metadata. Run validate_documentation_freshness with initializeMissing=true`,
385 |     );
386 |   }
387 | 
388 |   // Analyze most commonly stale files
389 |   const allStaleFiles = history.flatMap((h) => h.event.mostStaleFiles);
390 |   const staleFileCounts = new Map<string, number>();
391 |   for (const file of allStaleFiles) {
392 |     staleFileCounts.set(file, (staleFileCounts.get(file) || 0) + 1);
393 |   }
394 | 
395 |   const chronicallyStale = Array.from(staleFileCounts.entries())
396 |     .filter(([_, count]) => count >= Math.min(3, history.length * 0.5))
397 |     .map(([file]) => file);
398 | 
399 |   if (chronicallyStale.length > 0) {
400 |     recommendations.push(
401 |       `🔄 ${
402 |         chronicallyStale.length
403 |       } files are chronically stale: ${chronicallyStale
404 |         .slice(0, 3)
405 |         .join(", ")}${chronicallyStale.length > 3 ? "..." : ""}`,
406 |     );
407 |   }
408 | 
409 |   return {
410 |     totalEvents: history.length,
411 |     averageImprovementScore: avgScore,
412 |     trend,
413 |     currentStatus,
414 |     recommendations,
415 |   };
416 | }
417 | 
418 | /**
419 |  * Compare freshness across similar projects
420 |  */
421 | export async function compareFreshnessAcrossProjects(
422 |   projectPath: string,
423 | ): Promise<{
424 |   currentProject: {
425 |     path: string;
426 |     improvementScore: number;
427 |   };
428 |   similarProjects: Array<{
429 |     path: string;
430 |     improvementScore: number;
431 |     similarity: number;
432 |   }>;
433 |   ranking: number; // 1-based ranking (1 = best)
434 | }> {
435 |   const kg = await getKnowledgeGraph();
436 |   const projectId = generateProjectId(projectPath);
437 | 
438 |   // Get current project's latest score
439 |   const history = await getFreshnessHistory(projectPath, 1);
440 |   const currentScore =
441 |     history.length > 0 ? history[0].relationship.improvementScore || 0 : 0;
442 | 
443 |   // Find similar projects
444 |   const similarEdges = await kg.findEdges({
445 |     source: projectId,
446 |     type: "similar_to",
447 |   });
448 | 
449 |   const similarProjectsPromises = similarEdges.map(async (edge) => {
450 |     const similarProjectNode = await kg.getNodeById(edge.target);
451 |     if (!similarProjectNode || similarProjectNode.type !== "project") {
452 |       return null;
453 |     }
454 | 
455 |     const similarPath = (similarProjectNode.properties as any).path || "";
456 |     const similarHistory = await getFreshnessHistory(similarPath, 1);
457 |     const similarScore =
458 |       similarHistory.length > 0
459 |         ? similarHistory[0].relationship.improvementScore || 0
460 |         : 0;
461 | 
462 |     return {
463 |       path: similarPath,
464 |       improvementScore: similarScore,
465 |       similarity: (edge.properties as any).similarityScore || 0,
466 |     };
467 |   });
468 | 
469 |   const similarProjects = await Promise.all(similarProjectsPromises);
470 |   const validSimilarProjects = similarProjects.filter(
471 |     (p): p is NonNullable<typeof p> => p !== null,
472 |   );
473 | 
474 |   // Calculate ranking
475 |   const allScores = [
476 |     currentScore,
477 |     ...validSimilarProjects.map((p) => p.improvementScore),
478 |   ];
479 |   const sortedScores = [...allScores].sort((a, b) => b - a);
480 |   const ranking = sortedScores.indexOf(currentScore) + 1;
481 | 
482 |   return {
483 |     currentProject: {
484 |       path: projectPath,
485 |       improvementScore: currentScore,
486 |     },
487 |     similarProjects: validSimilarProjects,
488 |     ranking,
489 |   };
490 | }
491 | 
```

--------------------------------------------------------------------------------
/docs/adrs/004-diataxis-framework-integration.md:
--------------------------------------------------------------------------------

```markdown
  1 | ---
  2 | id: 004-diataxis-framework-integration
  3 | title: "ADR-004: Diataxis Framework Integration"
  4 | sidebar_label: "ADR-4: Diataxis Framework Integration"
  5 | sidebar_position: 4
  6 | documcp:
  7 |   last_updated: "2025-11-20T00:46:21.938Z"
  8 |   last_validated: "2025-11-20T00:46:21.938Z"
  9 |   auto_updated: false
 10 |   update_frequency: monthly
 11 | ---
 12 | 
 13 | # ADR-004: Diataxis Framework Integration for Documentation Structure
 14 | 
 15 | ## Status
 16 | 
 17 | Accepted
 18 | 
 19 | ## Context
 20 | 
 21 | DocuMCP aims to improve the quality and effectiveness of technical documentation by implementing proven information architecture principles. The Diataxis framework provides a systematic approach to organizing technical documentation into four distinct categories that serve different user needs and learning contexts.
 22 | 
 23 | Diataxis Framework Components:
 24 | 
 25 | - **Tutorials**: Learning-oriented content for skill acquisition (study context)
 26 | - **How-to Guides**: Problem-solving oriented content for specific tasks (work context)
 27 | - **Reference**: Information-oriented content for lookup and verification (information context)
 28 | - **Explanation**: Understanding-oriented content for context and background (understanding context)
 29 | 
 30 | Current documentation challenges:
 31 | 
 32 | - Most projects mix different content types without clear organization
 33 | - Users struggle to find appropriate content for their current needs
 34 | - Documentation often fails to serve different user contexts effectively
 35 | - Information architecture is typically ad-hoc and inconsistent
 36 | 
 37 | The framework addresses fundamental differences in user intent:
 38 | 
 39 | - **Study vs. Work**: Different contexts require different content approaches
 40 | - **Acquisition vs. Application**: Learning new skills vs. applying existing knowledge
 41 | - **Practical vs. Theoretical**: Task completion vs. understanding concepts
 42 | 
 43 | ## Decision
 44 | 
 45 | We will integrate the Diataxis framework as the foundational information architecture for all DocuMCP-generated documentation structures, with intelligent content planning and navigation generation adapted to each static site generator's capabilities.
 46 | 
 47 | ### Integration Approach:
 48 | 
 49 | #### 1. Automated Structure Generation
 50 | 
 51 | - **Directory organization** that clearly separates Diataxis content types
 52 | - **Navigation systems** that help users understand content categorization
 53 | - **Template generation** for each content type with appropriate guidance
 54 | - **Cross-reference systems** that maintain logical relationships between content types
 55 | 
 56 | #### 2. Content Type Templates
 57 | 
 58 | - **Tutorial templates** with learning objectives, prerequisites, step-by-step instructions
 59 | - **How-to guide templates** focused on problem-solution patterns
 60 | - **Reference templates** for systematic information organization
 61 | - **Explanation templates** for conceptual and architectural content
 62 | 
 63 | #### 3. Content Planning Intelligence
 64 | 
 65 | - **Automated content suggestions** based on project analysis
 66 | - **Gap identification** for missing content types
 67 | - **User journey mapping** to appropriate content categories
 68 | - **Content relationship mapping** to ensure comprehensive coverage
 69 | 
 70 | #### 4. SSG-Specific Implementation
 71 | 
 72 | - **Adaptation to SSG capabilities** while maintaining Diataxis principles
 73 | - **Theme and plugin recommendations** that support Diataxis organization
 74 | - **Navigation configuration** optimized for each SSG's features
 75 | 
 76 | ## Alternatives Considered
 77 | 
 78 | ### Generic Documentation Templates
 79 | 
 80 | - **Pros**: Simpler implementation, fewer constraints on content organization
 81 | - **Cons**: Perpetuates existing documentation quality problems, no systematic improvement
 82 | - **Decision**: Rejected due to missed opportunity for significant quality improvement
 83 | 
 84 | ### Custom Documentation Framework
 85 | 
 86 | - **Pros**: Full control over documentation approach and features
 87 | - **Cons**: Reinventing proven methodology, reduced credibility, maintenance burden
 88 | - **Decision**: Rejected in favor of proven, established framework
 89 | 
 90 | ### Multiple Framework Options
 91 | 
 92 | - **Pros**: Could accommodate different project preferences and approaches
 93 | - **Cons**: Choice paralysis, inconsistent quality, complex implementation
 94 | - **Decision**: Rejected to maintain focus and ensure consistent quality outcomes
 95 | 
 96 | ### Optional Diataxis Integration
 97 | 
 98 | - **Pros**: Gives users choice, accommodates existing documentation structures
 99 | - **Cons**: Reduces value proposition, complicates implementation, inconsistent results
100 | - **Decision**: Rejected to ensure consistent quality and educational value
101 | 
102 | ## Consequences
103 | 
104 | ### Positive
105 | 
106 | - **Improved Documentation Quality**: Systematic application of proven principles
107 | - **Better User Experience**: Users can find appropriate content for their context
108 | - **Educational Value**: Projects learn proper documentation organization
109 | - **Consistency**: All DocuMCP projects benefit from same high-quality structure
110 | - **Maintenance Benefits**: Clear content types simplify ongoing documentation work
111 | 
112 | ### Negative
113 | 
114 | - **Learning Curve**: Teams need to understand Diataxis principles for optimal results
115 | - **Initial Overhead**: More structure requires more initial planning and content creation
116 | - **Rigidity**: Some projects might prefer different organizational approaches
117 | 
118 | ### Risks and Mitigations
119 | 
120 | - **User Resistance**: Provide clear education about benefits and implementation guidance
121 | - **Implementation Complexity**: Start with basic structure, enhance over time
122 | - **Content Quality**: Provide high-quality templates and examples
123 | 
124 | ## Implementation Details
125 | 
126 | ### Directory Structure Generation
127 | 
128 | ```typescript
129 | interface DiataxisStructure {
130 |   tutorials: DirectoryConfig;
131 |   howToGuides: DirectoryConfig;
132 |   reference: DirectoryConfig;
133 |   explanation: DirectoryConfig;
134 |   navigation: NavigationConfig;
135 | }
136 | 
137 | const DIATAXIS_TEMPLATES: Record<SSGType, DiataxisStructure> = {
138 |   hugo: {
139 |     tutorials: { path: "content/tutorials", layout: "tutorial" },
140 |     howToGuides: { path: "content/how-to", layout: "guide" },
141 |     reference: { path: "content/reference", layout: "reference" },
142 |     explanation: { path: "content/explanation", layout: "explanation" },
143 |     navigation: { menu: "diataxis", weight: "category-based" },
144 |   },
145 |   // ... other SSG configurations
146 | };
147 | ```
148 | 
149 | ### Content Template System
150 | 
151 | ```typescript
152 | interface ContentTemplate {
153 |   frontmatter: Record<string, any>;
154 |   structure: ContentSection[];
155 |   guidance: string[];
156 |   examples: string[];
157 | }
158 | 
159 | const TUTORIAL_TEMPLATE: ContentTemplate = {
160 |   frontmatter: {
161 |     title: "{{ tutorial_title }}",
162 |     description: "{{ tutorial_description }}",
163 |     difficulty: "{{ difficulty_level }}",
164 |     prerequisites: "{{ prerequisites }}",
165 |     estimated_time: "{{ time_estimate }}",
166 |   },
167 |   structure: [
168 |     { section: "learning_objectives", required: true },
169 |     { section: "prerequisites", required: true },
170 |     { section: "step_by_step_instructions", required: true },
171 |     { section: "verification", required: true },
172 |     { section: "next_steps", required: false },
173 |   ],
174 |   guidance: [
175 |     "Focus on learning and skill acquisition",
176 |     "Provide complete, working examples",
177 |     "Include verification steps for each major milestone",
178 |     "Assume minimal prior knowledge",
179 |   ],
180 | };
181 | ```
182 | 
183 | ### Content Planning Algorithm
184 | 
185 | ```typescript
186 | interface ContentPlan {
187 |   tutorials: TutorialSuggestion[];
188 |   howToGuides: HowToSuggestion[];
189 |   reference: ReferenceSuggestion[];
190 |   explanation: ExplanationSuggestion[];
191 | }
192 | 
193 | function generateContentPlan(projectAnalysis: ProjectAnalysis): ContentPlan {
194 |   return {
195 |     tutorials: suggestTutorials(projectAnalysis),
196 |     howToGuides: suggestHowToGuides(projectAnalysis),
197 |     reference: suggestReference(projectAnalysis),
198 |     explanation: suggestExplanation(projectAnalysis),
199 |   };
200 | }
201 | 
202 | function suggestTutorials(analysis: ProjectAnalysis): TutorialSuggestion[] {
203 |   const suggestions: TutorialSuggestion[] = [];
204 | 
205 |   // Getting started tutorial (always recommended)
206 |   suggestions.push({
207 |     title: "Getting Started",
208 |     description: "First steps with {{ project_name }}",
209 |     priority: "high",
210 |     estimated_effort: "medium",
211 |   });
212 | 
213 |   // Feature-specific tutorials based on project complexity
214 |   if (analysis.complexity.apiSurface > 5) {
215 |     suggestions.push({
216 |       title: "API Integration Tutorial",
217 |       description: "Complete guide to integrating with the API",
218 |       priority: "high",
219 |       estimated_effort: "large",
220 |     });
221 |   }
222 | 
223 |   return suggestions;
224 | }
225 | ```
226 | 
227 | ### Navigation Generation
228 | 
229 | ```typescript
230 | interface DiataxisNavigation {
231 |   structure: NavigationItem[];
232 |   labels: NavigationLabels;
233 |   descriptions: CategoryDescriptions;
234 | }
235 | 
236 | const NAVIGATION_STRUCTURE: DiataxisNavigation = {
237 |   structure: [
238 |     {
239 |       category: "tutorials",
240 |       label: "Tutorials",
241 |       description: "Learning-oriented guides",
242 |       icon: "graduation-cap",
243 |       order: 1,
244 |     },
245 |     {
246 |       category: "how-to",
247 |       label: "How-to Guides",
248 |       description: "Problem-solving recipes",
249 |       icon: "tools",
250 |       order: 2,
251 |     },
252 |     {
253 |       category: "reference",
254 |       label: "Reference",
255 |       description: "Technical information",
256 |       icon: "book",
257 |       order: 3,
258 |     },
259 |     {
260 |       category: "explanation",
261 |       label: "Explanation",
262 |       description: "Understanding and context",
263 |       icon: "lightbulb",
264 |       order: 4,
265 |     },
266 |   ],
267 |   labels: {
268 |     tutorials: "Learn",
269 |     howToGuides: "Solve",
270 |     reference: "Lookup",
271 |     explanation: "Understand",
272 |   },
273 |   descriptions: {
274 |     tutorials: "Step-by-step learning paths",
275 |     howToGuides: "Solutions to specific problems",
276 |     reference: "Complete technical details",
277 |     explanation: "Background and concepts",
278 |   },
279 | };
280 | ```
281 | 
282 | ### SSG-Specific Adaptations
283 | 
284 | ```typescript
285 | interface SSGDiataxisAdapter {
286 |   generateStructure(
287 |     ssg: SSGType,
288 |     project: ProjectAnalysis,
289 |   ): DiataxisImplementation;
290 |   createNavigation(
291 |     ssg: SSGType,
292 |     structure: DiataxisStructure,
293 |   ): NavigationConfig;
294 |   generateTemplates(ssg: SSGType, contentTypes: ContentType[]): TemplateSet;
295 | }
296 | 
297 | class HugoDiataxisAdapter implements SSGDiataxisAdapter {
298 |   generateStructure(
299 |     ssg: SSGType,
300 |     project: ProjectAnalysis,
301 |   ): DiataxisImplementation {
302 |     return {
303 |       contentDirectories: this.createHugoContentStructure(),
304 |       frontmatterSchemas: this.createHugoFrontmatter(),
305 |       taxonomies: this.createDiataxisTaxonomies(),
306 |       menuConfiguration: this.createHugoMenus(),
307 |     };
308 |   }
309 | 
310 |   createHugoContentStructure(): ContentStructure {
311 |     return {
312 |       "content/tutorials/": { weight: 10, section: "tutorials" },
313 |       "content/how-to/": { weight: 20, section: "guides" },
314 |       "content/reference/": { weight: 30, section: "reference" },
315 |       "content/explanation/": { weight: 40, section: "explanation" },
316 |     };
317 |   }
318 | }
319 | ```
320 | 
321 | ## Quality Assurance
322 | 
323 | ### Diataxis Compliance Validation
324 | 
325 | ```typescript
326 | interface DiataxisValidator {
327 |   validateStructure(documentation: DocumentationStructure): ValidationResult;
328 |   checkContentTypeAlignment(
329 |     content: Content,
330 |     declaredType: ContentType,
331 |   ): AlignmentResult;
332 |   identifyMissingCategories(structure: DocumentationStructure): Gap[];
333 | }
334 | 
335 | function validateDiataxisCompliance(
336 |   docs: DocumentationStructure,
337 | ): ComplianceReport {
338 |   return {
339 |     structureCompliance: checkDirectoryOrganization(docs),
340 |     contentTypeAccuracy: validateContentCategorization(docs),
341 |     navigationClarity: assessNavigationEffectiveness(docs),
342 |     crossReferenceCompleteness: checkContentRelationships(docs),
343 |   };
344 | }
345 | ```
346 | 
347 | ### Content Quality Guidelines
348 | 
349 | - **Tutorial Content**: Must include learning objectives, prerequisites, and verification steps
350 | - **How-to Content**: Must focus on specific problems with clear solution steps
351 | - **Reference Content**: Must be comprehensive, accurate, and systematically organized
352 | - **Explanation Content**: Must provide context, background, and conceptual understanding
353 | 
354 | ### Testing Strategy
355 | 
356 | - **Structure Tests**: Validate directory organization and navigation generation
357 | - **Template Tests**: Ensure all content type templates are properly formatted
358 | - **Integration Tests**: Test complete Diataxis implementation across different SSGs
359 | - **User Experience Tests**: Validate that users can effectively navigate and find content
360 | 
361 | ## Educational Integration
362 | 
363 | ### User Guidance
364 | 
365 | - **Diataxis Explanation**: Clear documentation of framework benefits and principles
366 | - **Content Type Guidelines**: Detailed guidance for creating each type of content
367 | - **Migration Assistance**: Help converting existing documentation to Diataxis structure
368 | - **Best Practice Examples**: Templates and examples demonstrating effective implementation
369 | 
370 | ### Community Building
371 | 
372 | - **Diataxis Advocacy**: Promote framework adoption across open-source community
373 | - **Success Story Sharing**: Highlight projects benefiting from Diataxis implementation
374 | - **Training Resources**: Develop educational materials for technical writers and maintainers
375 | - **Feedback Collection**: Gather community input for framework implementation improvements
376 | 
377 | ## Future Enhancements
378 | 
379 | ### Advanced Features
380 | 
381 | - **Content Gap Analysis**: AI-powered identification of missing content areas
382 | - **User Journey Optimization**: Intelligent linking between content types based on user flows
383 | - **Content Quality Scoring**: Automated assessment of content quality within each category
384 | - **Personalized Navigation**: Adaptive navigation based on user role and experience level
385 | 
386 | ### Tool Integration
387 | 
388 | - **Analytics Integration**: Track how users navigate between different content types
389 | - **Content Management**: Tools for maintaining Diataxis compliance over time
390 | - **Translation Support**: Multi-language implementations of Diataxis structure
391 | - **Accessibility Features**: Ensure Diataxis implementation supports accessibility standards
392 | 
393 | ## References
394 | 
395 | - [Diataxis Framework Official Documentation](https://diataxis.fr/)
396 | - [Information Architecture Principles](https://www.usability.gov/what-and-why/information-architecture.html)
397 | - [Technical Writing Best Practices](https://developers.google.com/tech-writing)
398 | 
```

--------------------------------------------------------------------------------
/docs/how-to/troubleshooting.md:
--------------------------------------------------------------------------------

```markdown
  1 | ---
  2 | documcp:
  3 |   last_updated: "2025-11-20T00:46:21.956Z"
  4 |   last_validated: "2025-11-20T00:46:21.956Z"
  5 |   auto_updated: false
  6 |   update_frequency: monthly
  7 | ---
  8 | 
  9 | # Troubleshooting Common Issues
 10 | 
 11 | This guide helps you diagnose and fix common problems when using DocuMCP for documentation deployment.
 12 | 
 13 | ## Quick Diagnostic Commands
 14 | 
 15 | Use these DocuMCP prompts for immediate diagnosis:
 16 | 
 17 | ```bash
 18 | # General troubleshooting
 19 | "diagnose issues with my documentation deployment"
 20 | 
 21 | # Specific verification
 22 | "verify my GitHub Pages deployment and identify any problems"
 23 | 
 24 | # Link validation
 25 | "check all my documentation links for broken references"
 26 | 
 27 | # Content validation
 28 | "validate my documentation content for errors and inconsistencies"
 29 | ```
 30 | 
 31 | ## Repository Analysis Issues
 32 | 
 33 | ### Problem: Analysis Returns Empty or Incomplete Results
 34 | 
 35 | **Symptoms:**
 36 | 
 37 | - Analysis shows 0 files or minimal structure
 38 | - Missing language detection
 39 | - No dependency information
 40 | 
 41 | **Solutions:**
 42 | 
 43 | 1. **Check directory permissions:**
 44 | 
 45 | ```bash
 46 | ls -la /path/to/your/repository
 47 | # Ensure read permissions exist
 48 | ```
 49 | 
 50 | 2. **Verify Git repository:**
 51 | 
 52 | ```bash
 53 | git status
 54 | # Must be in a valid Git repository
 55 | ```
 56 | 
 57 | 3. **Use deeper analysis:**
 58 | 
 59 | ```bash
 60 | "analyze my repository with deep analysis to get comprehensive results"
 61 | ```
 62 | 
 63 | 4. **Check for hidden files:**
 64 | 
 65 | ```bash
 66 | # Include hidden files in analysis
 67 | ls -la
 68 | # Look for .gitignore excluding important files
 69 | ```
 70 | 
 71 | ### Problem: Wrong Project Type Detection
 72 | 
 73 | **Symptoms:**
 74 | 
 75 | - Library detected as application
 76 | - Wrong primary language
 77 | - Incorrect team size estimation
 78 | 
 79 | **Solutions:**
 80 | 
 81 | 1. **Provide more context:**
 82 | 
 83 | ```bash
 84 | "analyze my TypeScript library project with focus on API documentation"
 85 | ```
 86 | 
 87 | 2. **Check file extensions:**
 88 | 
 89 | ```bash
 90 | # Ensure your main files have correct extensions
 91 | find . -name "*.ts" -o -name "*.js" -o -name "*.py" | head -20
 92 | ```
 93 | 
 94 | 3. **Update package.json:**
 95 | 
 96 | ```json
 97 | {
 98 |   "type": "module",
 99 |   "main": "dist/index.js",
100 |   "types": "dist/index.d.ts",
101 |   "keywords": ["library", "typescript", "api"]
102 | }
103 | ```
104 | 
105 | ## Static Site Generator Recommendation Issues
106 | 
107 | ### Problem: No Recommendations or Low Confidence Scores
108 | 
109 | **Symptoms:**
110 | 
111 | - Empty recommendation list
112 | - All SSGs have similar low scores
113 | - Recommendation doesn't match project needs
114 | 
115 | **Solutions:**
116 | 
117 | 1. **Provide preferences:**
118 | 
119 | ```bash
120 | "recommend SSG for my project with preferences for JavaScript ecosystem and feature-rich capabilities"
121 | ```
122 | 
123 | 2. **Re-analyze with specific focus:**
124 | 
125 | ```bash
126 | "analyze my repository focusing on documentation needs and complexity"
127 | ```
128 | 
129 | 3. **Check project characteristics:**
130 | 
131 | - Ensure sufficient code files exist
132 | - Verify dependencies are in package.json/requirements.txt
133 | - Add README with project description
134 | 
135 | ### Problem: Recommended SSG Doesn't Match Expectations
136 | 
137 | **Symptoms:**
138 | 
139 | - Hugo recommended for React project
140 | - MkDocs suggested for JavaScript library
141 | - Jekyll proposed for Python project
142 | 
143 | **Solutions:**
144 | 
145 | 1. **Specify ecosystem preference:**
146 | 
147 | ```bash
148 | "recommend SSG for my project with JavaScript ecosystem preference"
149 | ```
150 | 
151 | 2. **Review analysis results:**
152 | 
153 | ```bash
154 | "explain why you recommended Hugo instead of Docusaurus for my React project"
155 | ```
156 | 
157 | 3. **Override with specific request:**
158 | 
159 | ```bash
160 | "generate Docusaurus configuration for my project despite the Hugo recommendation"
161 | ```
162 | 
163 | ## Configuration Generation Issues
164 | 
165 | ### Problem: Configuration Files Not Created
166 | 
167 | **Symptoms:**
168 | 
169 | - No config files generated
170 | - Empty configuration
171 | - Missing dependencies
172 | 
173 | **Solutions:**
174 | 
175 | 1. **Check output path:**
176 | 
177 | ```bash
178 | # Ensure output path exists and is writable
179 | mkdir -p ./docs
180 | chmod 755 ./docs
181 | ```
182 | 
183 | 2. **Specify absolute path:**
184 | 
185 | ```bash
186 | "generate Hugo configuration files at /full/path/to/project"
187 | ```
188 | 
189 | 3. **Check project name format:**
190 | 
191 | ```bash
192 | # Avoid special characters in project names
193 | "generate config for project 'My-Simple-Docs' not 'My Project (v2.0)'"
194 | ```
195 | 
196 | ### Problem: Invalid Configuration Generated
197 | 
198 | **Symptoms:**
199 | 
200 | - Build fails with config errors
201 | - Missing required fields
202 | - Wrong file format
203 | 
204 | **Solutions:**
205 | 
206 | 1. **Validate generated config:**
207 | 
208 | ```bash
209 | # For Docusaurus
210 | npm run docusaurus --version
211 | 
212 | # For Hugo
213 | hugo version && hugo config
214 | 
215 | # For MkDocs
216 | mkdocs --version && mkdocs build --strict
217 | ```
218 | 
219 | 2. **Regenerate with project details:**
220 | 
221 | ```bash
222 | "generate detailed Hugo configuration with custom theme and GitHub integration"
223 | ```
224 | 
225 | 3. **Fix common issues:**
226 | 
227 | **Docusaurus baseUrl fix:**
228 | 
229 | ```javascript
230 | // Fix in docusaurus.config.js
231 | const config = {
232 |   baseUrl: "/your-repo-name/", // Must match repository name
233 |   url: "https://yourusername.github.io",
234 | };
235 | ```
236 | 
237 | **Hugo baseURL fix:**
238 | 
239 | ```yaml
240 | # Fix in config.yml
241 | baseURL: "https://yourusername.github.io/your-repo-name/"
242 | ```
243 | 
244 | ## Documentation Structure Issues
245 | 
246 | ### Problem: Diataxis Structure Not Created
247 | 
248 | **Symptoms:**
249 | 
250 | - Missing directories
251 | - Empty folders
252 | - No example content
253 | 
254 | **Solutions:**
255 | 
256 | 1. **Check path permissions:**
257 | 
258 | ```bash
259 | ls -ld /path/to/docs
260 | # Ensure write permissions
261 | ```
262 | 
263 | 2. **Use absolute path:**
264 | 
265 | ```bash
266 | "set up Diataxis structure at /absolute/path/to/docs"
267 | ```
268 | 
269 | 3. **Force recreation:**
270 | 
271 | ```bash
272 | "recreate documentation structure with examples for my SSG"
273 | ```
274 | 
275 | ### Problem: Content Population Fails
276 | 
277 | **Symptoms:**
278 | 
279 | - Empty documentation files
280 | - Generic content only
281 | - Missing project-specific information
282 | 
283 | **Solutions:**
284 | 
285 | 1. **Provide analysis context:**
286 | 
287 | ```bash
288 | "populate documentation using analysis ID analysis_abc123 with comprehensive content"
289 | ```
290 | 
291 | 2. **Specify technology focus:**
292 | 
293 | ```bash
294 | "populate docs focusing on TypeScript, React, and API documentation"
295 | ```
296 | 
297 | 3. **Check source code structure:**
298 | 
299 | ```bash
300 | # Ensure code has discoverable patterns
301 | find . -name "*.ts" -exec grep -l "export" {} \;
302 | ```
303 | 
304 | ## GitHub Pages Deployment Issues
305 | 
306 | ### Problem: Deployment Workflow Fails
307 | 
308 | **Symptoms:**
309 | 
310 | - GitHub Actions shows red X
311 | - Build fails with errors
312 | - Deployment never completes
313 | 
314 | **Solutions:**
315 | 
316 | 1. **Check workflow logs:**
317 | 
318 | - Go to Actions tab in GitHub
319 | - Click on failed workflow
320 | - Review step-by-step logs
321 | 
322 | 2. **Common fixes:**
323 | 
324 | **Node.js version mismatch:**
325 | 
326 | ```yaml
327 | # Fix in .github/workflows/deploy.yml
328 | - name: Setup Node.js
329 |   uses: actions/setup-node@v4
330 |   with:
331 |     node-version: "20" # Match your local version
332 | ```
333 | 
334 | **Missing dependencies:**
335 | 
336 | ```json
337 | # Ensure all dependencies in package.json
338 | {
339 |   "dependencies": {
340 |     "@docusaurus/core": "^3.0.0",
341 |     "@docusaurus/preset-classic": "^3.0.0"
342 |   }
343 | }
344 | ```
345 | 
346 | **Build command issues:**
347 | 
348 | ```yaml
349 | # Fix build command
350 | - name: Build
351 |   run: npm run build # Ensure this command exists in package.json
352 | ```
353 | 
354 | ### Problem: Site Shows 404 Error
355 | 
356 | **Symptoms:**
357 | 
358 | - GitHub Pages URL returns 404
359 | - Site deployed but not accessible
360 | - Some pages work, others don't
361 | 
362 | **Solutions:**
363 | 
364 | 1. **Check GitHub Pages settings:**
365 | 
366 | - Repository Settings > Pages
367 | - Source should be "GitHub Actions"
368 | - Custom domain configured correctly (if used)
369 | 
370 | 2. **Fix baseURL configuration:**
371 | 
372 | **Docusaurus:**
373 | 
374 | ```javascript
375 | const config = {
376 |   baseUrl: "/repository-name/", // Must match your repo name exactly
377 |   url: "https://username.github.io",
378 | };
379 | ```
380 | 
381 | **Hugo:**
382 | 
383 | ```yaml
384 | baseURL: "https://username.github.io/repository-name/"
385 | ```
386 | 
387 | **MkDocs:**
388 | 
389 | ```yaml
390 | site_url: "https://username.github.io/repository-name/"
391 | ```
392 | 
393 | 3. **Check file naming:**
394 | 
395 | ```bash
396 | # Ensure index.html or index.md exists
397 | ls docs/index.*
398 | ```
399 | 
400 | ### Problem: Assets Not Loading (CSS/JS/Images)
401 | 
402 | **Symptoms:**
403 | 
404 | - Site loads but no styling
405 | - Images show as broken
406 | - JavaScript functionality missing
407 | 
408 | **Solutions:**
409 | 
410 | 1. **Check asset paths:**
411 | 
412 | ```javascript
413 | // Use relative paths
414 | <img src="./images/logo.png" />  // Good
415 | <img src="/images/logo.png" />   // May fail
416 | ```
417 | 
418 | 2. **Configure public path:**
419 | 
420 | **Docusaurus:**
421 | 
422 | ```javascript
423 | const config = {
424 |   baseUrl: "/repo-name/",
425 |   staticDirectories: ["static"],
426 | };
427 | ```
428 | 
429 | **Hugo:**
430 | 
431 | ```yaml
432 | # In config.yml
433 | baseURL: "https://username.github.io/repo-name/"
434 | canonifyURLs: true
435 | ```
436 | 
437 | 3. **Verify asset directories:**
438 | 
439 | ```bash
440 | # Check assets exist in build output
441 | ls -la build/assets/  # Docusaurus
442 | ls -la public/css/    # Hugo
443 | ls -la site/css/      # MkDocs
444 | ```
445 | 
446 | ## Content Validation Issues
447 | 
448 | ### Problem: Link Validation Shows False Positives
449 | 
450 | **Symptoms:**
451 | 
452 | - Valid links reported as broken
453 | - External links fail intermittently
454 | - Anchor links not found
455 | 
456 | **Solutions:**
457 | 
458 | 1. **Configure link checking:**
459 | 
460 | ```bash
461 | "check documentation links with timeout of 10 seconds and ignore external domains github.com"
462 | ```
463 | 
464 | 2. **Check anchor links:**
465 | 
466 | ```markdown
467 | <!-- Ensure anchors exist -->
468 | 
469 | ## My Section
470 | 
471 | Link to [My Section](#my-section) <!-- Correct -->
472 | Link to [My Section](#my_section) <!-- May fail -->
473 | ```
474 | 
475 | 3. **Handle external link timeouts:**
476 | 
477 | ```bash
478 | "validate content with longer timeout for external links and retry failed checks"
479 | ```
480 | 
481 | ### Problem: Code Block Validation Fails
482 | 
483 | **Symptoms:**
484 | 
485 | - Valid code marked as invalid
486 | - Syntax highlighting not working
487 | - Code examples cause build failures
488 | 
489 | **Solutions:**
490 | 
491 | 1. **Check language tags:**
492 | 
493 | ````markdown
494 | <!-- Correct -->
495 | 
496 | ```javascript
497 | const example = "Hello World";
498 | ```
499 | ````
500 | 
501 | <!-- Incorrect - missing language -->
502 | 
503 | ```
504 | const example = "Hello World";
505 | ```
506 | 
507 | ````
508 | 
509 | 2. **Validate code syntax:**
510 | ```bash
511 | # Test code blocks separately
512 | node -e "const example = 'Hello World'; console.log(example);"
513 | ````
514 | 
515 | 3. **Configure code validation:**
516 | 
517 | ```bash
518 | "validate content with permissive code validation and syntax checking disabled"
519 | ```
520 | 
521 | ## Memory System Issues
522 | 
523 | ### Problem: Memory System Not Initializing
524 | 
525 | **Symptoms:**
526 | 
527 | - Memory tools return errors
528 | - No historical data available
529 | - Analysis doesn't include insights
530 | 
531 | **Solutions:**
532 | 
533 | 1. **Check storage directory:**
534 | 
535 | ```bash
536 | ls -la .documcp/memory/
537 | # Should contain analysis files
538 | ```
539 | 
540 | 2. **Initialize manually:**
541 | 
542 | ```bash
543 | "recall all memories to initialize the memory system"
544 | ```
545 | 
546 | 3. **Check permissions:**
547 | 
548 | ```bash
549 | chmod -R 755 .documcp/
550 | ```
551 | 
552 | ### Problem: Similar Projects Not Found
553 | 
554 | **Symptoms:**
555 | 
556 | - No similar projects in results
557 | - Low-quality recommendations
558 | - Missing historical patterns
559 | 
560 | **Solutions:**
561 | 
562 | 1. **Build memory with more analyses:**
563 | 
564 | ```bash
565 | "analyze multiple repositories to build memory patterns"
566 | ```
567 | 
568 | 2. **Export and import memory:**
569 | 
570 | ```bash
571 | "export memories in JSON format for backup"
572 | ```
573 | 
574 | 3. **Clean and rebuild:**
575 | 
576 | ```bash
577 | "cleanup old memories and rebuild with recent analyses"
578 | ```
579 | 
580 | ## Performance Issues
581 | 
582 | ### Problem: Slow Build Times
583 | 
584 | **Symptoms:**
585 | 
586 | - Builds take too long
587 | - GitHub Actions timeout
588 | - Local development is slow
589 | 
590 | **Solutions:**
591 | 
592 | 1. **Optimize build configuration:**
593 | 
594 | **Docusaurus:**
595 | 
596 | ```javascript
597 | const config = {
598 |   future: {
599 |     experimental_faster: true,
600 |   },
601 |   webpack: {
602 |     jsLoader: (isServer) => ({
603 |       loader: "esbuild-loader",
604 |       options: {
605 |         loader: "tsx",
606 |         target: isServer ? "node12" : "es2017",
607 |       },
608 |     }),
609 |   },
610 | };
611 | ```
612 | 
613 | **Hugo:**
614 | 
615 | ```yaml
616 | # config.yml
617 | build:
618 |   writeStats: false
619 |   noJSConfigInAssets: true
620 | ```
621 | 
622 | 2. **Enable caching:**
623 | 
624 | ```yaml
625 | # In GitHub Actions
626 | - name: Cache dependencies
627 |   uses: actions/cache@v4
628 |   with:
629 |     path: ~/.npm
630 |     key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
631 | ```
632 | 
633 | 3. **Reduce build scope:**
634 | 
635 | ```bash
636 | # Build only changed files
637 | npm run build -- --locale en
638 | ```
639 | 
640 | ### Problem: Large Bundle Sizes
641 | 
642 | **Symptoms:**
643 | 
644 | - Slow page loads
645 | - High bandwidth usage
646 | - Poor mobile performance
647 | 
648 | **Solutions:**
649 | 
650 | 1. **Analyze bundle:**
651 | 
652 | ```bash
653 | # Docusaurus
654 | npm run build -- --bundle-analyzer
655 | 
656 | # Check generated files
657 | ls -lh build/assets/
658 | ```
659 | 
660 | 2. **Optimize images:**
661 | 
662 | ```bash
663 | # Convert images to WebP
664 | find docs -name "*.png" -exec cwebp {} -o {}.webp \;
665 | ```
666 | 
667 | 3. **Enable code splitting:**
668 | 
669 | ```javascript
670 | // Docusaurus config
671 | const config = {
672 |   webpack: {
673 |     splitChunks: {
674 |       chunks: "all",
675 |       cacheGroups: {
676 |         default: {
677 |           minChunks: 2,
678 |           reuseExistingChunk: true,
679 |         },
680 |       },
681 |     },
682 |   },
683 | };
684 | ```
685 | 
686 | ## Getting Help
687 | 
688 | ### Diagnostic Information
689 | 
690 | When reporting issues, include:
691 | 
692 | 1. **DocuMCP version:**
693 | 
694 | ```bash
695 | npm list documcp
696 | ```
697 | 
698 | 2. **System information:**
699 | 
700 | ```bash
701 | node --version
702 | npm --version
703 | git --version
704 | ```
705 | 
706 | 3. **Error logs:**
707 | 
708 | ```bash
709 | # GitHub Actions logs
710 | # Local build output
711 | # Browser console errors
712 | ```
713 | 
714 | ### Support Channels
715 | 
716 | - **GitHub Issues**: [Report bugs and feature requests](https://github.com/tosin2013/documcp/issues)
717 | - **Documentation**: Check other guides in this documentation
718 | - **Community**: Search existing issues for solutions
719 | 
720 | ### Self-Diagnostic Commands
721 | 
722 | ```bash
723 | # Complete health check
724 | "verify my entire documentation setup and identify all issues"
725 | 
726 | # Performance analysis
727 | "analyze my documentation build performance and suggest optimizations"
728 | 
729 | # Security check
730 | "validate my GitHub Pages deployment for security best practices"
731 | ```
732 | 
733 | ## Prevention Tips
734 | 
735 | ### Regular Maintenance
736 | 
737 | 1. **Weekly validation:**
738 | 
739 | ```bash
740 | "check all documentation links and validate content quality"
741 | ```
742 | 
743 | 2. **Monthly updates:**
744 | 
745 | ```bash
746 | # Update dependencies
747 | npm update
748 | # Regenerate configurations if needed
749 | ```
750 | 
751 | 3. **Monitor deployment:**
752 | 
753 | - Set up GitHub Actions notifications
754 | - Check site accessibility regularly
755 | - Monitor build times and performance
756 | 
757 | ### Best Practices
758 | 
759 | 1. **Always test locally before deploying**
760 | 2. **Use DocuMCP validation before committing**
761 | 3. **Keep dependencies updated**
762 | 4. **Monitor GitHub Actions for failures**
763 | 5. **Backup memory and configurations**
764 | 
765 | ## Summary
766 | 
767 | Common issue categories and solutions:
768 | ✅ Repository analysis problems - permissions and context
769 | ✅ SSG recommendation issues - preferences and project type
770 | ✅ Configuration generation - paths and project details
771 | ✅ Deployment failures - workflows and settings
772 | ✅ Content validation - links and code blocks
773 | ✅ Performance optimization - builds and bundles
774 | ✅ Memory system troubleshooting - initialization and data
775 | 
776 | Most issues can be resolved by providing more context to DocuMCP or fixing configuration details!
777 | 
```

--------------------------------------------------------------------------------
/src/tools/generate-readme-template.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { z } from "zod";
  2 | 
  3 | // Template types
  4 | export const TemplateType = z.enum([
  5 |   "library",
  6 |   "application",
  7 |   "cli-tool",
  8 |   "api",
  9 |   "documentation",
 10 | ]);
 11 | export type TemplateType = z.infer<typeof TemplateType>;
 12 | 
 13 | // Input schema
 14 | export const GenerateReadmeTemplateSchema = z.object({
 15 |   projectName: z.string().min(1, "Project name is required"),
 16 |   description: z.string().min(1, "Project description is required"),
 17 |   templateType: TemplateType,
 18 |   author: z.string().optional(),
 19 |   license: z.string().default("MIT"),
 20 |   includeScreenshots: z.boolean().default(false),
 21 |   includeBadges: z.boolean().default(true),
 22 |   includeContributing: z.boolean().default(true),
 23 |   outputPath: z.string().optional(),
 24 | });
 25 | 
 26 | export type GenerateReadmeTemplateInput = z.infer<
 27 |   typeof GenerateReadmeTemplateSchema
 28 | >;
 29 | 
 30 | interface TemplateSection {
 31 |   title: string;
 32 |   content: string;
 33 |   required: boolean;
 34 | }
 35 | 
 36 | interface ReadmeTemplate {
 37 |   sections: TemplateSection[];
 38 |   badges: string[];
 39 |   metadata: {
 40 |     type: TemplateType;
 41 |     estimatedLength: number;
 42 |   };
 43 | }
 44 | 
 45 | export class ReadmeTemplateGenerator {
 46 |   private templates: Map<TemplateType, ReadmeTemplate> = new Map();
 47 | 
 48 |   constructor() {
 49 |     this.initializeTemplates();
 50 |   }
 51 | 
 52 |   private initializeTemplates(): void {
 53 |     // Library/Package Template
 54 |     this.templates.set("library", {
 55 |       sections: [
 56 |         {
 57 |           title: "Header",
 58 |           content: "# {{projectName}}\n\n> {{description}}",
 59 |           required: true,
 60 |         },
 61 |         {
 62 |           title: "Badges",
 63 |           content: "{{badges}}",
 64 |           required: false,
 65 |         },
 66 |         {
 67 |           title: "TL;DR",
 68 |           content:
 69 |             "## TL;DR\n\nWhat it does in 2-3 sentences. Who should use it.\n\n- ✅ Perfect for X use cases\n- ✅ Solves Y problems\n- ❌ Not suitable for Z (consider [alternative] instead)",
 70 |           required: true,
 71 |         },
 72 |         {
 73 |           title: "Quick Start",
 74 |           content:
 75 |             "## Quick Start\n\n### Install\n\n```bash\nnpm install {{projectName}}\n```\n\n### Use\n\n```javascript\nconst {{camelCaseName}} = require('{{projectName}}');\n\n// Basic usage example\nconst result = {{camelCaseName}}.doSomething();\nconsole.log(result);\n```",
 76 |           required: true,
 77 |         },
 78 |         {
 79 |           title: "API Documentation",
 80 |           content:
 81 |             "## API Documentation\n\n[Link to full API documentation]\n\n### Core Methods\n\n#### `methodName(param)`\n\n- **param** `{Type}` - Description\n- **Returns** `{Type}` - Description\n\nExample:\n```javascript\n// Example usage\n```",
 82 |           required: true,
 83 |         },
 84 |         {
 85 |           title: "Contributing",
 86 |           content:
 87 |             "## Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.\n\n### Development Setup\n\n```bash\ngit clone https://github.com/{{author}}/{{projectName}}.git\ncd {{projectName}}\nnpm install\nnpm test\n```",
 88 |           required: false,
 89 |         },
 90 |         {
 91 |           title: "License",
 92 |           content: "## License\n\n{{license}} © {{author}}",
 93 |           required: true,
 94 |         },
 95 |       ],
 96 |       badges: [
 97 |         "[![npm version](https://badge.fury.io/js/{{projectName}}.svg)](https://badge.fury.io/js/{{projectName}})",
 98 |         "[![Build Status](https://travis-ci.org/{{author}}/{{projectName}}.svg?branch=main)](https://travis-ci.org/{{author}}/{{projectName}})",
 99 |         "[![License: {{license}}](https://img.shields.io/badge/License-{{license}}-yellow.svg)](https://opensource.org/licenses/{{license}})",
100 |       ],
101 |       metadata: {
102 |         type: "library",
103 |         estimatedLength: 150,
104 |       },
105 |     });
106 | 
107 |     // Application Template
108 |     this.templates.set("application", {
109 |       sections: [
110 |         {
111 |           title: "Header",
112 |           content: "# {{projectName}}\n\n> {{description}}",
113 |           required: true,
114 |         },
115 |         {
116 |           title: "Screenshot",
117 |           content: "{{screenshot}}",
118 |           required: false,
119 |         },
120 |         {
121 |           title: "What This Does",
122 |           content:
123 |             "## What This Does\n\n{{projectName}} helps you:\n\n- 🎯 **Feature 1** - Brief explanation\n- ⚡ **Feature 2** - Brief explanation\n- 🔧 **Feature 3** - Brief explanation",
124 |           required: true,
125 |         },
126 |         {
127 |           title: "Quick Start",
128 |           content:
129 |             "## Quick Start\n\n### Prerequisites\n\n- Node.js 18+ \n- npm or yarn\n- [Additional requirements]\n\n### Install & Run\n\n```bash\ngit clone https://github.com/{{author}}/{{projectName}}.git\ncd {{projectName}}\nnpm install\nnpm start\n```\n\nOpen http://localhost:3000 in your browser.",
130 |           required: true,
131 |         },
132 |         {
133 |           title: "Configuration",
134 |           content:
135 |             "## Configuration\n\nCreate a `.env` file in the root directory:\n\n```env\n# Required settings\nPORT=3000\nNODE_ENV=development\n\n# Optional settings\nDATABASE_URL=your_database_url\nAPI_KEY=your_api_key\n```\n\nSee [Configuration Guide](docs/configuration.md) for all options.",
136 |           required: true,
137 |         },
138 |         {
139 |           title: "Usage",
140 |           content:
141 |             "## Usage\n\n### Basic Operations\n\n1. **Step 1** - Description\n2. **Step 2** - Description\n3. **Step 3** - Description\n\n### Advanced Features\n\n[Link to advanced documentation]",
142 |           required: true,
143 |         },
144 |         {
145 |           title: "Contributing",
146 |           content:
147 |             "## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and contribution guidelines.",
148 |           required: false,
149 |         },
150 |         {
151 |           title: "License",
152 |           content: "## License\n\n{{license}} © {{author}}",
153 |           required: true,
154 |         },
155 |       ],
156 |       badges: [
157 |         "[![Build Status](https://github.com/{{author}}/{{projectName}}/workflows/CI/badge.svg)](https://github.com/{{author}}/{{projectName}}/actions)",
158 |         "[![License: {{license}}](https://img.shields.io/badge/License-{{license}}-blue.svg)](LICENSE)",
159 |       ],
160 |       metadata: {
161 |         type: "application",
162 |         estimatedLength: 200,
163 |       },
164 |     });
165 | 
166 |     // CLI Tool Template
167 |     this.templates.set("cli-tool", {
168 |       sections: [
169 |         {
170 |           title: "Header",
171 |           content: "# {{projectName}}\n\n> {{description}}",
172 |           required: true,
173 |         },
174 |         {
175 |           title: "Installation",
176 |           content:
177 |             "## Installation\n\n```bash\n# Global installation\nnpm install -g {{projectName}}\n\n# Or use with npx\nnpx {{projectName}} --help\n```",
178 |           required: true,
179 |         },
180 |         {
181 |           title: "Usage",
182 |           content:
183 |             "## Usage\n\n### Basic Commands\n\n```bash\n# Basic usage\n{{projectName}} [options] [arguments]\n\n# Show help\n{{projectName}} --help\n\n# Show version\n{{projectName}} --version\n```\n\n### Examples\n\n```bash\n# Example 1\n{{projectName}} command --option value\n\n# Example 2\n{{projectName}} another-command file.txt\n```",
184 |           required: true,
185 |         },
186 |         {
187 |           title: "Options",
188 |           content:
189 |             "## Options\n\n| Option | Description | Default |\n|--------|-------------|----------|\n| `-h, --help` | Show help | |\n| `-v, --version` | Show version | |\n| `--config <path>` | Config file path | `./config.json` |\n| `--verbose` | Verbose output | `false` |",
190 |           required: true,
191 |         },
192 |         {
193 |           title: "Configuration",
194 |           content:
195 |             '## Configuration\n\nCreate a config file:\n\n```json\n{\n  "setting1": "value1",\n  "setting2": "value2"\n}\n```',
196 |           required: false,
197 |         },
198 |         {
199 |           title: "Contributing",
200 |           content:
201 |             "## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for development guidelines.",
202 |           required: false,
203 |         },
204 |         {
205 |           title: "License",
206 |           content: "## License\n\n{{license}} © {{author}}",
207 |           required: true,
208 |         },
209 |       ],
210 |       badges: [
211 |         "[![npm version](https://badge.fury.io/js/{{projectName}}.svg)](https://www.npmjs.com/package/{{projectName}})",
212 |         "[![License: {{license}}](https://img.shields.io/badge/License-{{license}}-green.svg)](LICENSE)",
213 |       ],
214 |       metadata: {
215 |         type: "cli-tool",
216 |         estimatedLength: 180,
217 |       },
218 |     });
219 |   }
220 | 
221 |   generateTemplate(input: GenerateReadmeTemplateInput): string {
222 |     const template = this.templates.get(input.templateType);
223 |     if (!template) {
224 |       throw new Error(`Template type "${input.templateType}" not supported`);
225 |     }
226 | 
227 |     let readme = "";
228 |     const camelCaseName = this.toCamelCase(input.projectName);
229 | 
230 |     // Process each section
231 |     for (const section of template.sections) {
232 |       if (section.title === "Badges" && input.includeBadges) {
233 |         readme += this.processBadges(template.badges, input) + "\n\n";
234 |       } else if (section.title === "Screenshot" && input.includeScreenshots) {
235 |         readme += this.processScreenshot(input) + "\n\n";
236 |       } else if (
237 |         section.title === "Contributing" &&
238 |         !input.includeContributing
239 |       ) {
240 |         continue;
241 |       } else {
242 |         readme +=
243 |           this.processSection(section.content, input, camelCaseName) + "\n\n";
244 |       }
245 |     }
246 | 
247 |     return readme.trim();
248 |   }
249 | 
250 |   private processBadges(
251 |     badges: string[],
252 |     input: GenerateReadmeTemplateInput,
253 |   ): string {
254 |     return badges
255 |       .map((badge) => this.replaceVariables(badge, input))
256 |       .join("\n");
257 |   }
258 | 
259 |   private processScreenshot(input: GenerateReadmeTemplateInput): string {
260 |     return `![${input.projectName} Screenshot](docs/screenshot.png)\n\n*Add a screenshot or demo GIF here*`;
261 |   }
262 | 
263 |   private processSection(
264 |     content: string,
265 |     input: GenerateReadmeTemplateInput,
266 |     camelCaseName: string,
267 |   ): string {
268 |     let processed = this.replaceVariables(content, input);
269 |     processed = processed.replace(/\{\{camelCaseName\}\}/g, camelCaseName);
270 |     return processed;
271 |   }
272 | 
273 |   private replaceVariables(
274 |     content: string,
275 |     input: GenerateReadmeTemplateInput,
276 |   ): string {
277 |     return content
278 |       .replace(/\{\{projectName\}\}/g, input.projectName)
279 |       .replace(/\{\{description\}\}/g, input.description)
280 |       .replace(/\{\{author\}\}/g, input.author || "your-username")
281 |       .replace(/\{\{license\}\}/g, input.license);
282 |   }
283 | 
284 |   private toCamelCase(str: string): string {
285 |     return str
286 |       .replace(/[-_\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ""))
287 |       .replace(/^./, (c) => c.toLowerCase());
288 |   }
289 | 
290 |   getAvailableTemplates(): TemplateType[] {
291 |     return Array.from(this.templates.keys());
292 |   }
293 | 
294 |   getTemplateInfo(type: TemplateType): ReadmeTemplate["metadata"] | null {
295 |     const template = this.templates.get(type);
296 |     return template ? template.metadata : null;
297 |   }
298 | }
299 | 
300 | /**
301 |  * Generates standardized README templates for different project types with best practices.
302 |  *
303 |  * Creates comprehensive README templates tailored to specific project types (library,
304 |  * application, CLI tool, API, documentation) following community best practices. Includes
305 |  * customizable sections, badges, contributing guidelines, and project-specific content
306 |  * to ensure professional documentation standards.
307 |  *
308 |  * @param input - The input parameters for README template generation
309 |  * @param input.projectName - Name of the project (required)
310 |  * @param input.description - Brief description of what the project does (required)
311 |  * @param input.templateType - Type of project template to generate
312 |  * @param input.author - Optional project author/organization name
313 |  * @param input.license - Project license (default: "MIT")
314 |  * @param input.includeScreenshots - Whether to include screenshot placeholders (default: false)
315 |  * @param input.includeBadges - Whether to include status badges (default: true)
316 |  * @param input.includeContributing - Whether to include contributing section (default: true)
317 |  * @param input.outputPath - Optional path to write the generated README.md file
318 |  *
319 |  * @returns Promise resolving to README template generation results
320 |  * @returns template - The generated README template content
321 |  * @returns metadata - Template metadata including type and estimated length
322 |  * @returns filePath - Path where the README was written (if outputPath provided)
323 |  *
324 |  * @throws {Error} When required parameters are missing
325 |  * @throws {Error} When output path is inaccessible
326 |  * @throws {Error} When template generation fails
327 |  *
328 |  * @example
329 |  * ```typescript
330 |  * // Generate library README template
331 |  * const result = await generateReadmeTemplate({
332 |  *   projectName: "MyAwesomeLibrary",
333 |  *   description: "A powerful utility library for data processing",
334 |  *   templateType: "library",
335 |  *   author: "Your Name",
336 |  *   license: "MIT",
337 |  *   includeBadges: true
338 |  * });
339 |  *
340 |  * console.log(`Generated ${result.metadata.estimatedLength} line README`);
341 |  *
342 |  * // Generate CLI tool template with output file
343 |  * const cliTemplate = await generateReadmeTemplate({
344 |  *   projectName: "my-cli-tool",
345 |  *   description: "Command-line interface for project management",
346 |  *   templateType: "cli-tool",
347 |  *   outputPath: "./README.md"
348 |  * });
349 |  * ```
350 |  *
351 |  * @since 1.0.0
352 |  */
353 | export async function generateReadmeTemplate(
354 |   input: GenerateReadmeTemplateInput,
355 | ): Promise<{
356 |   content: string;
357 |   metadata: {
358 |     templateType: TemplateType;
359 |     estimatedLength: number;
360 |     sectionsIncluded: number;
361 |   };
362 | }> {
363 |   const validatedInput = GenerateReadmeTemplateSchema.parse(input);
364 |   const generator = new ReadmeTemplateGenerator();
365 | 
366 |   const content = generator.generateTemplate(validatedInput);
367 |   const templateInfo = generator.getTemplateInfo(validatedInput.templateType);
368 | 
369 |   if (!templateInfo) {
370 |     throw new Error(`Template type "${validatedInput.templateType}" not found`);
371 |   }
372 | 
373 |   // Write to file if output path specified
374 |   if (validatedInput.outputPath) {
375 |     const fs = await import("fs/promises");
376 |     await fs.writeFile(validatedInput.outputPath, content, "utf-8");
377 |   }
378 | 
379 |   return {
380 |     content,
381 |     metadata: {
382 |       templateType: validatedInput.templateType,
383 |       estimatedLength: templateInfo.estimatedLength,
384 |       sectionsIncluded: content.split("##").length - 1,
385 |     },
386 |   };
387 | }
388 | 
```

--------------------------------------------------------------------------------
/src/tools/manage-sitemap.ts:
--------------------------------------------------------------------------------

```typescript
  1 | /**
  2 |  * Manage Sitemap Tool
  3 |  *
  4 |  * MCP tool for generating, validating, and managing sitemap.xml files.
  5 |  * Sitemap.xml serves as the source of truth for all documentation links.
  6 |  */
  7 | 
  8 | import { z } from "zod";
  9 | import path from "path";
 10 | import { promises as fs } from "fs";
 11 | import {
 12 |   generateSitemap,
 13 |   validateSitemap,
 14 |   updateSitemap,
 15 |   listSitemapUrls,
 16 |   type SitemapUrl,
 17 |   type SitemapStats,
 18 | } from "../utils/sitemap-generator.js";
 19 | import { formatMCPResponse } from "../types/api.js";
 20 | 
 21 | /**
 22 |  * Input schema for manage_sitemap tool
 23 |  */
 24 | export const ManageSitemapInputSchema = z.object({
 25 |   action: z
 26 |     .enum(["generate", "validate", "update", "list"])
 27 |     .describe(
 28 |       "Action to perform: generate (create new), validate (check structure), update (sync with docs), list (show all URLs)",
 29 |     ),
 30 |   docsPath: z.string().describe("Path to documentation root directory"),
 31 |   baseUrl: z
 32 |     .string()
 33 |     .optional()
 34 |     .describe(
 35 |       "Base URL for the site (e.g., https://user.github.io/repo). Required for generate/update actions.",
 36 |     ),
 37 |   includePatterns: z
 38 |     .array(z.string())
 39 |     .optional()
 40 |     .describe(
 41 |       "File patterns to include (default: **/*.md, **/*.html, **/*.mdx)",
 42 |     ),
 43 |   excludePatterns: z
 44 |     .array(z.string())
 45 |     .optional()
 46 |     .describe(
 47 |       "File patterns to exclude (default: node_modules, .git, dist, build, .documcp)",
 48 |     ),
 49 |   updateFrequency: z
 50 |     .enum(["always", "hourly", "daily", "weekly", "monthly", "yearly", "never"])
 51 |     .optional()
 52 |     .describe("Default change frequency for pages"),
 53 |   useGitHistory: z
 54 |     .boolean()
 55 |     .optional()
 56 |     .default(true)
 57 |     .describe("Use git history for last modified dates (default: true)"),
 58 |   sitemapPath: z
 59 |     .string()
 60 |     .optional()
 61 |     .describe("Custom path for sitemap.xml (default: docsPath/sitemap.xml)"),
 62 | });
 63 | 
 64 | export type ManageSitemapInput = z.input<typeof ManageSitemapInputSchema>;
 65 | 
 66 | /**
 67 |  * Manage sitemap.xml for documentation
 68 |  */
 69 | export async function manageSitemap(
 70 |   input: ManageSitemapInput,
 71 | ): Promise<{ content: any[] }> {
 72 |   const { action, docsPath, sitemapPath } = input;
 73 | 
 74 |   // Resolve sitemap path
 75 |   const resolvedSitemapPath = sitemapPath || path.join(docsPath, "sitemap.xml");
 76 | 
 77 |   try {
 78 |     // Verify docs directory exists
 79 |     try {
 80 |       await fs.access(docsPath);
 81 |     } catch {
 82 |       return formatMCPResponse({
 83 |         success: false,
 84 |         error: {
 85 |           code: "DOCS_DIR_NOT_FOUND",
 86 |           message: `Documentation directory not found: ${docsPath}`,
 87 |         },
 88 |         metadata: {
 89 |           toolVersion: "1.0.0",
 90 |           executionTime: Date.now(),
 91 |           timestamp: new Date().toISOString(),
 92 |         },
 93 |       });
 94 |     }
 95 | 
 96 |     switch (action) {
 97 |       case "generate":
 98 |         return await generateSitemapAction(input, resolvedSitemapPath);
 99 | 
100 |       case "validate":
101 |         return await validateSitemapAction(resolvedSitemapPath);
102 | 
103 |       case "update":
104 |         return await updateSitemapAction(input, resolvedSitemapPath);
105 | 
106 |       case "list":
107 |         return await listSitemapAction(resolvedSitemapPath);
108 | 
109 |       default:
110 |         return formatMCPResponse({
111 |           success: false,
112 |           error: {
113 |             code: "UNKNOWN_ACTION",
114 |             message: `Unknown action: ${action}`,
115 |           },
116 |           metadata: {
117 |             toolVersion: "1.0.0",
118 |             executionTime: Date.now(),
119 |             timestamp: new Date().toISOString(),
120 |           },
121 |         });
122 |     }
123 |   } catch (error) {
124 |     return formatMCPResponse({
125 |       success: false,
126 |       error: {
127 |         code: "SITEMAP_ERROR",
128 |         message: `Error managing sitemap: ${
129 |           error instanceof Error ? error.message : String(error)
130 |         }`,
131 |       },
132 |       metadata: {
133 |         toolVersion: "1.0.0",
134 |         executionTime: Date.now(),
135 |         timestamp: new Date().toISOString(),
136 |       },
137 |     });
138 |   }
139 | }
140 | 
141 | /**
142 |  * Generate new sitemap.xml
143 |  */
144 | async function generateSitemapAction(
145 |   input: ManageSitemapInput,
146 |   sitemapPath: string,
147 | ): Promise<{ content: any[] }> {
148 |   const {
149 |     docsPath,
150 |     baseUrl,
151 |     includePatterns,
152 |     excludePatterns,
153 |     updateFrequency,
154 |   } = input;
155 | 
156 |   if (!baseUrl) {
157 |     return formatMCPResponse({
158 |       success: false,
159 |       error: {
160 |         code: "BASE_URL_REQUIRED",
161 |         message: "baseUrl is required for generate action",
162 |       },
163 |       metadata: {
164 |         toolVersion: "1.0.0",
165 |         executionTime: 0,
166 |         timestamp: new Date().toISOString(),
167 |       },
168 |     });
169 |   }
170 | 
171 |   // Generate sitemap
172 |   const { xml, urls, stats } = await generateSitemap({
173 |     baseUrl,
174 |     docsPath,
175 |     includePatterns,
176 |     excludePatterns,
177 |     useGitHistory: input.useGitHistory,
178 |     defaultChangeFreq: updateFrequency || "monthly",
179 |   });
180 | 
181 |   // Write sitemap.xml
182 |   await fs.writeFile(sitemapPath, xml, "utf-8");
183 | 
184 |   // Format output
185 |   const output = formatGenerateOutput(sitemapPath, urls, stats);
186 | 
187 |   return formatMCPResponse({
188 |     success: true,
189 |     data: {
190 |       action: "generate",
191 |       sitemapPath,
192 |       totalUrls: stats.totalUrls,
193 |       categories: stats.byCategory,
194 |       output,
195 |     },
196 |     metadata: {
197 |       toolVersion: "1.0.0",
198 |       executionTime: Date.now(),
199 |       timestamp: new Date().toISOString(),
200 |     },
201 |   });
202 | }
203 | 
204 | /**
205 |  * Validate existing sitemap.xml
206 |  */
207 | async function validateSitemapAction(
208 |   sitemapPath: string,
209 | ): Promise<{ content: any[] }> {
210 |   // Check if sitemap exists
211 |   try {
212 |     await fs.access(sitemapPath);
213 |   } catch {
214 |     return formatMCPResponse({
215 |       success: false,
216 |       error: {
217 |         code: "SITEMAP_NOT_FOUND",
218 |         message: `Sitemap not found: ${sitemapPath}. Use action: "generate" to create a new sitemap.`,
219 |       },
220 |       metadata: {
221 |         toolVersion: "1.0.0",
222 |         executionTime: 0,
223 |         timestamp: new Date().toISOString(),
224 |       },
225 |     });
226 |   }
227 | 
228 |   // Validate sitemap
229 |   const validation = await validateSitemap(sitemapPath);
230 | 
231 |   // Format output
232 |   const output = formatValidationOutput(sitemapPath, validation);
233 | 
234 |   return formatMCPResponse({
235 |     success: validation.valid,
236 |     data: {
237 |       action: "validate",
238 |       valid: validation.valid,
239 |       errorCount: validation.errors.length,
240 |       warningCount: validation.warnings.length,
241 |       urlCount: validation.urlCount,
242 |       output,
243 |     },
244 |     error: validation.valid
245 |       ? undefined
246 |       : {
247 |           code: "VALIDATION_FAILED",
248 |           message: `Sitemap validation failed with ${validation.errors.length} error(s)`,
249 |         },
250 |     metadata: {
251 |       toolVersion: "1.0.0",
252 |       executionTime: Date.now(),
253 |       timestamp: new Date().toISOString(),
254 |     },
255 |   });
256 | }
257 | 
258 | /**
259 |  * Update existing sitemap.xml
260 |  */
261 | async function updateSitemapAction(
262 |   input: ManageSitemapInput,
263 |   sitemapPath: string,
264 | ): Promise<{ content: any[] }> {
265 |   const {
266 |     docsPath,
267 |     baseUrl,
268 |     includePatterns,
269 |     excludePatterns,
270 |     updateFrequency,
271 |   } = input;
272 | 
273 |   if (!baseUrl) {
274 |     return formatMCPResponse({
275 |       success: false,
276 |       error: {
277 |         code: "BASE_URL_REQUIRED",
278 |         message: "baseUrl is required for update action",
279 |       },
280 |       metadata: {
281 |         toolVersion: "1.0.0",
282 |         executionTime: 0,
283 |         timestamp: new Date().toISOString(),
284 |       },
285 |     });
286 |   }
287 | 
288 |   // Check if sitemap exists
289 |   const sitemapExists = await fs
290 |     .access(sitemapPath)
291 |     .then(() => true)
292 |     .catch(() => false);
293 | 
294 |   if (!sitemapExists) {
295 |     return formatMCPResponse({
296 |       success: false,
297 |       error: {
298 |         code: "SITEMAP_NOT_FOUND",
299 |         message: `Sitemap not found: ${sitemapPath}. Run generate action first.`,
300 |       },
301 |       metadata: {
302 |         toolVersion: "1.0.0",
303 |         executionTime: 0,
304 |         timestamp: new Date().toISOString(),
305 |       },
306 |     });
307 |   }
308 | 
309 |   // Update sitemap
310 |   const changes = await updateSitemap(sitemapPath, {
311 |     baseUrl,
312 |     docsPath,
313 |     includePatterns,
314 |     excludePatterns,
315 |     useGitHistory: input.useGitHistory,
316 |     defaultChangeFreq: updateFrequency || "monthly",
317 |   });
318 | 
319 |   // Format output
320 |   const output = formatUpdateOutput(sitemapPath, changes);
321 | 
322 |   return formatMCPResponse({
323 |     success: true,
324 |     data: {
325 |       action: "update",
326 |       added: changes.added,
327 |       removed: changes.removed,
328 |       updated: changes.updated,
329 |       total: changes.total,
330 |       output,
331 |     },
332 |     metadata: {
333 |       toolVersion: "1.0.0",
334 |       executionTime: Date.now(),
335 |       timestamp: new Date().toISOString(),
336 |     },
337 |   });
338 | }
339 | 
340 | /**
341 |  * List all URLs from sitemap.xml
342 |  */
343 | async function listSitemapAction(
344 |   sitemapPath: string,
345 | ): Promise<{ content: any[] }> {
346 |   // Check if sitemap exists
347 |   try {
348 |     await fs.access(sitemapPath);
349 |   } catch {
350 |     return formatMCPResponse({
351 |       success: false,
352 |       error: {
353 |         code: "SITEMAP_NOT_FOUND",
354 |         message: `Sitemap not found: ${sitemapPath}. Use action: "generate" to create a new sitemap.`,
355 |       },
356 |       metadata: {
357 |         toolVersion: "1.0.0",
358 |         executionTime: 0,
359 |         timestamp: new Date().toISOString(),
360 |       },
361 |     });
362 |   }
363 | 
364 |   // List URLs
365 |   const urls = await listSitemapUrls(sitemapPath);
366 | 
367 |   // Format output
368 |   const output = formatListOutput(sitemapPath, urls);
369 | 
370 |   return formatMCPResponse({
371 |     success: true,
372 |     data: {
373 |       action: "list",
374 |       totalUrls: urls.length,
375 |       urls: urls.map((u) => ({
376 |         loc: u.loc,
377 |         priority: u.priority,
378 |         category: u.category,
379 |         lastmod: u.lastmod,
380 |       })),
381 |       output,
382 |     },
383 |     metadata: {
384 |       toolVersion: "1.0.0",
385 |       executionTime: Date.now(),
386 |       timestamp: new Date().toISOString(),
387 |     },
388 |   });
389 | }
390 | 
391 | /**
392 |  * Format generate action output
393 |  */
394 | function formatGenerateOutput(
395 |   sitemapPath: string,
396 |   urls: SitemapUrl[],
397 |   stats: SitemapStats,
398 | ): string {
399 |   const lines: string[] = [
400 |     "✅ Sitemap generated successfully!",
401 |     "",
402 |     `📄 Location: ${sitemapPath}`,
403 |     `📊 Total URLs: ${stats.totalUrls}`,
404 |     "",
405 |     "📋 URLs by Category:",
406 |   ];
407 | 
408 |   // Sort categories by count (descending)
409 |   const sortedCategories = Object.entries(stats.byCategory).sort(
410 |     ([, a], [, b]) => b - a,
411 |   );
412 | 
413 |   for (const [category, count] of sortedCategories) {
414 |     const percentage = ((count / stats.totalUrls) * 100).toFixed(1);
415 |     lines.push(`  • ${category}: ${count} (${percentage}%)`);
416 |   }
417 | 
418 |   lines.push("");
419 |   lines.push("🔄 Change Frequencies:");
420 | 
421 |   // Sort change frequencies
422 |   const sortedFreqs = Object.entries(stats.byChangeFreq).sort(
423 |     ([, a], [, b]) => b - a,
424 |   );
425 | 
426 |   for (const [freq, count] of sortedFreqs) {
427 |     lines.push(`  • ${freq}: ${count}`);
428 |   }
429 | 
430 |   // Show top priority URLs
431 |   const topUrls = urls.filter((u) => (u.priority || 0) >= 0.9).slice(0, 5);
432 | 
433 |   if (topUrls.length > 0) {
434 |     lines.push("");
435 |     lines.push("⭐ High Priority Pages:");
436 |     for (const url of topUrls) {
437 |       lines.push(`  • [${url.priority?.toFixed(1)}] ${url.title || url.loc}`);
438 |     }
439 |   }
440 | 
441 |   lines.push("");
442 |   lines.push("💡 Next Steps:");
443 |   lines.push("  → Submit sitemap to search engines (Google, Bing)");
444 |   lines.push("  → Add sitemap to robots.txt");
445 |   lines.push("  → Deploy to GitHub Pages");
446 | 
447 |   return lines.join("\n");
448 | }
449 | 
450 | /**
451 |  * Format validation output
452 |  */
453 | function formatValidationOutput(
454 |   sitemapPath: string,
455 |   validation: {
456 |     valid: boolean;
457 |     errors: string[];
458 |     warnings: string[];
459 |     urlCount: number;
460 |   },
461 | ): string {
462 |   const lines: string[] = [];
463 | 
464 |   if (validation.valid) {
465 |     lines.push("✅ Sitemap is valid!");
466 |   } else {
467 |     lines.push("❌ Sitemap validation failed!");
468 |   }
469 | 
470 |   lines.push("");
471 |   lines.push(`📄 Location: ${sitemapPath}`);
472 |   lines.push(`📊 Total URLs: ${validation.urlCount}`);
473 | 
474 |   if (validation.errors.length > 0) {
475 |     lines.push("");
476 |     lines.push("🔴 Errors:");
477 |     for (const error of validation.errors) {
478 |       lines.push(`  • ${error}`);
479 |     }
480 |   }
481 | 
482 |   if (validation.warnings.length > 0) {
483 |     lines.push("");
484 |     lines.push("⚠️ Warnings:");
485 |     for (const warning of validation.warnings) {
486 |       lines.push(`  • ${warning}`);
487 |     }
488 |   }
489 | 
490 |   if (validation.valid) {
491 |     lines.push("");
492 |     lines.push("💡 Recommendations:");
493 |     lines.push("  ℹ️ Sitemap follows the Sitemaps 0.9 protocol");
494 |     lines.push("  ℹ️ Ready for search engine submission");
495 |   }
496 | 
497 |   return lines.join("\n");
498 | }
499 | 
500 | /**
501 |  * Format update output
502 |  */
503 | function formatUpdateOutput(
504 |   sitemapPath: string,
505 |   changes: { added: number; removed: number; updated: number; total: number },
506 | ): string {
507 |   const lines: string[] = [
508 |     "✅ Sitemap updated successfully!",
509 |     "",
510 |     `📄 Location: ${sitemapPath}`,
511 |     `📊 Total URLs: ${changes.total}`,
512 |     "",
513 |     "📝 Changes:",
514 |   ];
515 | 
516 |   if (changes.added > 0) {
517 |     lines.push(`  ✨ Added: ${changes.added} new page(s)`);
518 |   }
519 | 
520 |   if (changes.removed > 0) {
521 |     lines.push(`  🗑️ Removed: ${changes.removed} deleted page(s)`);
522 |   }
523 | 
524 |   if (changes.updated > 0) {
525 |     lines.push(`  🔄 Updated: ${changes.updated} modified page(s)`);
526 |   }
527 | 
528 |   if (changes.added === 0 && changes.removed === 0 && changes.updated === 0) {
529 |     lines.push("  ℹ️ No changes detected");
530 |   }
531 | 
532 |   lines.push("");
533 |   lines.push("💡 Next Steps:");
534 |   lines.push("  → Review changes if needed");
535 |   lines.push("  → Redeploy to GitHub Pages");
536 |   lines.push("  → Notify search engines of updates");
537 | 
538 |   return lines.join("\n");
539 | }
540 | 
541 | /**
542 |  * Format list output
543 |  */
544 | function formatListOutput(sitemapPath: string, urls: SitemapUrl[]): string {
545 |   const lines: string[] = [
546 |     `📄 Sitemap URLs from: ${sitemapPath}`,
547 |     `📊 Total: ${urls.length}`,
548 |     "",
549 |   ];
550 | 
551 |   // Group by category
552 |   const byCategory: Record<string, SitemapUrl[]> = {};
553 |   for (const url of urls) {
554 |     const category = url.category || "default";
555 |     if (!byCategory[category]) {
556 |       byCategory[category] = [];
557 |     }
558 |     byCategory[category].push(url);
559 |   }
560 | 
561 |   // Display by category
562 |   for (const [category, categoryUrls] of Object.entries(byCategory)) {
563 |     lines.push(`📂 ${category} (${categoryUrls.length}):`);
564 | 
565 |     // Sort by priority
566 |     const sorted = categoryUrls.sort(
567 |       (a, b) => (b.priority || 0) - (a.priority || 0),
568 |     );
569 | 
570 |     for (const url of sorted.slice(0, 10)) {
571 |       // Show first 10 per category
572 |       const priority = url.priority?.toFixed(1) || "0.5";
573 |       const title = url.title || path.basename(url.loc);
574 |       lines.push(`  [${priority}] ${title}`);
575 |       lines.push(`      ${url.loc}`);
576 |     }
577 | 
578 |     if (categoryUrls.length > 10) {
579 |       lines.push(`  ... and ${categoryUrls.length - 10} more`);
580 |     }
581 | 
582 |     lines.push("");
583 |   }
584 | 
585 |   return lines.join("\n");
586 | }
587 | 
```
Page 7/29FirstPrevNextLast