#
tokens: 45581/50000 8/274 files (page 12/20)
lines: off (toggle) GitHub
raw markdown copy
This is page 12 of 20. Use http://codebase.md/tosin2013/documcp?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/workflow.test.ts:
--------------------------------------------------------------------------------

```typescript
// Integration tests for complete documentation workflows
import { promises as fs } from "fs";
import path from "path";
import os from "os";
import { analyzeRepository } from "../../src/tools/analyze-repository";
import { recommendSSG } from "../../src/tools/recommend-ssg";
import { generateConfig } from "../../src/tools/generate-config";
import { setupStructure } from "../../src/tools/setup-structure";
import { deployPages } from "../../src/tools/deploy-pages";
import { verifyDeployment } from "../../src/tools/verify-deployment";

describe("Integration Testing - Complete Workflows", () => {
  let tempDir: string;
  let testProject: string;

  beforeAll(async () => {
    tempDir = path.join(os.tmpdir(), "documcp-integration-tests");
    await fs.mkdir(tempDir, { recursive: true });

    testProject = await createRealisticProject();
  });

  afterAll(async () => {
    try {
      await fs.rm(tempDir, { recursive: true, force: true });
    } catch (error) {
      console.warn("Failed to cleanup integration test directory:", error);
    }
  });

  describe("End-to-End Documentation Workflow", () => {
    it("should complete full documentation setup workflow", async () => {
      const workflowDir = path.join(tempDir, "e2e-workflow");
      await fs.mkdir(workflowDir, { recursive: true });

      // Step 1: Analyze Repository
      console.log("Step 1: Analyzing repository...");
      const analysisResult = await analyzeRepository({
        path: testProject,
        depth: "standard",
      });

      expect(analysisResult.content).toBeDefined();
      expect((analysisResult as any).isError).toBeFalsy();

      // Extract analysis ID for next step
      const analysisText = analysisResult.content.find((c) =>
        c.text.includes('"id"'),
      );
      const analysis = JSON.parse(analysisText!.text);
      const analysisId = analysis.id;

      expect(analysisId).toBeDefined();
      expect(analysis.dependencies.ecosystem).toBe("javascript");

      // Step 2: Get SSG Recommendation
      console.log("Step 2: Getting SSG recommendation...");
      const recommendationResult = await recommendSSG({
        analysisId: analysisId,
        preferences: {
          priority: "features",
          ecosystem: "javascript",
        },
      });

      expect(recommendationResult.content).toBeDefined();
      const recommendationText = recommendationResult.content.find((c) =>
        c.text.includes('"recommended"'),
      );
      const recommendation = JSON.parse(recommendationText!.text);

      expect(recommendation.recommended).toBeDefined();
      expect(["jekyll", "hugo", "docusaurus", "mkdocs", "eleventy"]).toContain(
        recommendation.recommended,
      );

      // Step 3: Generate Configuration
      console.log("Step 3: Generating configuration...");
      const configResult = await generateConfig({
        ssg: recommendation.recommended,
        projectName: "Integration Test Project",
        projectDescription: "End-to-end integration test",
        outputPath: workflowDir,
      });

      expect(configResult.content).toBeDefined();
      expect((configResult as any).isError).toBeFalsy();

      // Verify config files were created
      const files = await fs.readdir(workflowDir);
      expect(files.length).toBeGreaterThan(0);

      // Step 4: Setup Documentation Structure
      console.log("Step 4: Setting up documentation structure...");
      const docsDir = path.join(workflowDir, "docs");
      const structureResult = await setupStructure({
        path: docsDir,
        ssg: recommendation.recommended,
        includeExamples: true,
      });

      expect(structureResult.content).toBeDefined();
      expect((structureResult as any).isError).toBeFalsy();

      // Verify Diataxis structure was created
      const diataxisCategories = [
        "tutorials",
        "how-to",
        "reference",
        "explanation",
      ];
      for (const category of diataxisCategories) {
        const categoryPath = path.join(docsDir, category);
        expect(
          await fs
            .access(categoryPath)
            .then(() => true)
            .catch(() => false),
        ).toBe(true);
      }

      // Step 5: Setup Deployment
      console.log("Step 5: Setting up deployment...");
      const deploymentResult = await deployPages({
        repository: workflowDir,
        ssg: recommendation.recommended,
        branch: "gh-pages",
        customDomain: "docs.example.com",
      });

      expect(deploymentResult.content).toBeDefined();
      expect((deploymentResult as any).isError).toBeFalsy();

      // Verify workflow and CNAME were created
      const workflowPath = path.join(
        workflowDir,
        ".github",
        "workflows",
        "deploy-docs.yml",
      );
      const cnamePath = path.join(workflowDir, "CNAME");

      expect(
        await fs
          .access(workflowPath)
          .then(() => true)
          .catch(() => false),
      ).toBe(true);
      expect(
        await fs
          .access(cnamePath)
          .then(() => true)
          .catch(() => false),
      ).toBe(true);

      // Step 6: Verify Deployment Setup
      console.log("Step 6: Verifying deployment setup...");
      const verificationResult = await verifyDeployment({
        repository: workflowDir,
        url: "https://docs.example.com",
      });

      expect(verificationResult.content).toBeDefined();

      // Parse the JSON response to check actual verification data
      const verificationData = JSON.parse(verificationResult.content[0].text);
      const passCount = verificationData.summary.passed;
      const failCount = verificationData.summary.failed;

      console.log("Pass count:", passCount, "Fail count:", failCount);

      // Should have at least some passing checks
      expect(passCount).toBeGreaterThan(0);
      expect(passCount).toBeGreaterThanOrEqual(failCount);

      console.log("✅ End-to-end workflow completed successfully!");
    }, 30000); // 30 second timeout for full workflow
  });

  describe("Workflow Variations", () => {
    it("should handle Python project workflow", async () => {
      const pythonProject = await createPythonProject();

      // Analyze Python project
      const analysis = await analyzeRepository({
        path: pythonProject,
        depth: "standard",
      });
      const analysisData = JSON.parse(
        analysis.content.find((c) => c.text.includes('"ecosystem"'))!.text,
      );

      expect(analysisData.dependencies.ecosystem).toBe("python");

      // Get recommendation (likely MkDocs for Python)
      const recommendation = await recommendSSG({
        analysisId: analysisData.id,
      });
      // const recData = JSON.parse(recommendation.content.find(c => c.text.includes('"recommended"'))!.text);

      // Generate MkDocs config
      const configDir = path.join(tempDir, "python-workflow");
      await fs.mkdir(configDir, { recursive: true });

      const config = await generateConfig({
        ssg: "mkdocs",
        projectName: "Python Test Project",
        outputPath: configDir,
      });

      // Verify MkDocs-specific files
      expect(
        await fs
          .access(path.join(configDir, "mkdocs.yml"))
          .then(() => true)
          .catch(() => false),
      ).toBe(true);
      expect(
        await fs
          .access(path.join(configDir, "requirements.txt"))
          .then(() => true)
          .catch(() => false),
      ).toBe(true);
    });

    it("should handle different SSG preferences", async () => {
      const analysisId = "test-preferences-123";

      // Test simplicity preference
      const simplicityRec = await recommendSSG({
        analysisId,
        preferences: { priority: "simplicity" },
      });

      // Test performance preference
      const performanceRec = await recommendSSG({
        analysisId,
        preferences: { priority: "performance" },
      });

      // Test features preference
      const featuresRec = await recommendSSG({
        analysisId,
        preferences: { priority: "features" },
      });

      // All should provide valid recommendations
      [simplicityRec, performanceRec, featuresRec].forEach((result) => {
        expect(result.content).toBeDefined();
        const rec = JSON.parse(
          result.content.find((c) => c.text.includes('"recommended"'))!.text,
        );
        expect([
          "jekyll",
          "hugo",
          "docusaurus",
          "mkdocs",
          "eleventy",
        ]).toContain(rec.recommended);
      });
    });

    it("should handle deployment workflow variations", async () => {
      const deploymentDir = path.join(tempDir, "deployment-variations");
      await fs.mkdir(deploymentDir, { recursive: true });

      // Test different SSGs
      const ssgs = [
        "docusaurus",
        "mkdocs",
        "hugo",
        "jekyll",
        "eleventy",
      ] as const;

      for (const ssg of ssgs) {
        const ssgDir = path.join(deploymentDir, ssg);
        await fs.mkdir(ssgDir, { recursive: true });

        const result = await deployPages({
          repository: ssgDir,
          ssg: ssg,
          branch: "main",
        });

        expect(result.content).toBeDefined();

        const workflowPath = path.join(
          ssgDir,
          ".github",
          "workflows",
          "deploy-docs.yml",
        );
        expect(
          await fs
            .access(workflowPath)
            .then(() => true)
            .catch(() => false),
        ).toBe(true);

        const workflowContent = await fs.readFile(workflowPath, "utf-8");
        // Handle different SSG name formats
        const expectedName =
          ssg === "mkdocs"
            ? "Deploy MkDocs"
            : `Deploy ${ssg.charAt(0).toUpperCase() + ssg.slice(1)}`;
        expect(workflowContent).toContain(expectedName);

        // Verify SSG-specific workflow content
        switch (ssg) {
          case "docusaurus":
            expect(workflowContent).toContain("npm run build");
            expect(workflowContent).toContain("id-token: write"); // OIDC compliance
            break;
          case "mkdocs":
            expect(workflowContent).toContain("mkdocs gh-deploy");
            expect(workflowContent).toContain("python");
            break;
          case "hugo":
            expect(workflowContent).toContain("peaceiris/actions-hugo");
            expect(workflowContent).toContain("hugo --minify");
            break;
          case "jekyll":
            expect(workflowContent).toContain("bundle exec jekyll build");
            expect(workflowContent).toContain("ruby");
            break;
          case "eleventy":
            expect(workflowContent).toContain("npm run build");
            break;
        }
      }
    });
  });

  describe("Error Handling and Recovery", () => {
    it("should handle missing repository gracefully", async () => {
      const result = await analyzeRepository({
        path: "/non/existent/path",
        depth: "standard",
      });

      expect((result as any).isError).toBe(true);
      expect(result.content[0].text).toContain("Error:");
    });

    it("should handle invalid configuration gracefully", async () => {
      const invalidDir = "/invalid/write/path/that/should/fail";

      const result = await generateConfig({
        ssg: "docusaurus",
        projectName: "Test",
        outputPath: invalidDir,
      });

      expect((result as any).isError).toBe(true);
      expect(result.content[0].text).toContain("Error:");
    });

    it("should handle structure setup in non-existent directory", async () => {
      // This should actually work because setupStructure creates directories
      const result = await setupStructure({
        path: path.join(tempDir, "new-structure-dir"),
        ssg: "docusaurus",
        includeExamples: false,
      });

      expect((result as any).isError).toBeFalsy();
      expect(result.content).toBeDefined();
    });

    it("should provide helpful error messages and resolutions", async () => {
      const errorResult = await analyzeRepository({
        path: "/definitely/does/not/exist",
        depth: "standard",
      });

      expect((errorResult as any).isError).toBe(true);
      const errorText = errorResult.content.map((c) => c.text).join(" ");
      // Check for resolution in JSON format (lowercase) or formatted text (capitalized)
      expect(errorText.toLowerCase()).toContain("resolution");
      expect(errorText.toLowerCase()).toContain("ensure");
    });
  });

  describe("Performance and Resource Management", () => {
    it("should handle large repository analysis within performance bounds", async () => {
      const largeRepo = await createLargeRepository();

      const startTime = Date.now();
      const result = await analyzeRepository({
        path: largeRepo,
        depth: "standard",
      });
      const executionTime = Date.now() - startTime;

      // Should complete within reasonable time (large repo target is 60s)
      expect(executionTime).toBeLessThan(60000);
      expect(result.content).toBeDefined();

      const analysisData = JSON.parse(
        result.content.find((c) => c.text.includes('"totalFiles"'))!.text,
      );
      expect(analysisData.structure.totalFiles).toBeGreaterThan(1000);
    }, 65000); // 65s timeout for large repo test

    it("should clean up resources properly", async () => {
      const tempWorkflowDir = path.join(tempDir, "resource-cleanup");

      // Run multiple operations
      await generateConfig({
        ssg: "docusaurus",
        projectName: "Cleanup Test",
        outputPath: tempWorkflowDir,
      });

      await setupStructure({
        path: path.join(tempWorkflowDir, "docs"),
        ssg: "docusaurus",
        includeExamples: true,
      });

      // Verify files were created
      const files = await fs.readdir(tempWorkflowDir);
      expect(files.length).toBeGreaterThan(0);

      // Cleanup should work
      await fs.rm(tempWorkflowDir, { recursive: true, force: true });
      expect(
        await fs
          .access(tempWorkflowDir)
          .then(() => false)
          .catch(() => true),
      ).toBe(true);
    });
  });

  // Helper functions
  async function createRealisticProject(): Promise<string> {
    const projectPath = path.join(tempDir, "realistic-project");
    await fs.mkdir(projectPath, { recursive: true });

    // package.json with realistic dependencies
    const packageJson = {
      name: "realistic-test-project",
      version: "2.1.0",
      description: "A realistic Node.js project for testing DocuMCP",
      main: "src/index.js",
      scripts: {
        start: "node src/index.js",
        dev: "nodemon src/index.js",
        test: "jest",
        build: "webpack --mode production",
        lint: "eslint src/",
        docs: "jsdoc src/ -d docs/",
      },
      dependencies: {
        express: "^4.18.2",
        lodash: "^4.17.21",
        axios: "^1.4.0",
        moment: "^2.29.4",
        "body-parser": "^1.20.2",
      },
      devDependencies: {
        jest: "^29.5.0",
        nodemon: "^2.0.22",
        eslint: "^8.42.0",
        webpack: "^5.86.0",
        jsdoc: "^4.0.2",
      },
      keywords: ["node", "express", "api", "web"],
      author: "Test Author",
      license: "MIT",
    };

    await fs.writeFile(
      path.join(projectPath, "package.json"),
      JSON.stringify(packageJson, null, 2),
    );

    // Source directory structure
    await fs.mkdir(path.join(projectPath, "src"), { recursive: true });
    await fs.mkdir(path.join(projectPath, "src", "controllers"), {
      recursive: true,
    });
    await fs.mkdir(path.join(projectPath, "src", "models"), {
      recursive: true,
    });
    await fs.mkdir(path.join(projectPath, "src", "routes"), {
      recursive: true,
    });
    await fs.mkdir(path.join(projectPath, "src", "utils"), { recursive: true });

    // Main application files
    await fs.writeFile(
      path.join(projectPath, "src", "index.js"),
      `const express = require('express');
const bodyParser = require('body-parser');
const routes = require('./routes');

const app = express();
app.use(bodyParser.json());
app.use('/api', routes);

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(\`Server running on port \${PORT}\`);
});`,
    );

    await fs.writeFile(
      path.join(projectPath, "src", "routes", "index.js"),
      `const express = require('express');
const router = express.Router();

router.get('/health', (req, res) => {
  res.json({ status: 'OK', timestamp: new Date().toISOString() });
});

module.exports = router;`,
    );

    await fs.writeFile(
      path.join(projectPath, "src", "controllers", "userController.js"),
      `const { getUserById, createUser } = require('../models/user');

async function getUser(req, res) {
  const user = await getUserById(req.params.id);
  res.json(user);
}

module.exports = { getUser };`,
    );

    await fs.writeFile(
      path.join(projectPath, "src", "models", "user.js"),
      `const users = [];

function getUserById(id) {
  return users.find(user => user.id === id);
}

function createUser(userData) {
  const user = { id: Date.now(), ...userData };
  users.push(user);
  return user;
}

module.exports = { getUserById, createUser };`,
    );

    await fs.writeFile(
      path.join(projectPath, "src", "utils", "helpers.js"),
      `const _ = require('lodash');
const moment = require('moment');

function formatDate(date) {
  return moment(date).format('YYYY-MM-DD HH:mm:ss');
}

function validateEmail(email) {
  return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email);
}

module.exports = { formatDate, validateEmail };`,
    );

    // Test directory
    await fs.mkdir(path.join(projectPath, "tests"), { recursive: true });
    await fs.writeFile(
      path.join(projectPath, "tests", "app.test.js"),
      `const { formatDate, validateEmail } = require('../src/utils/helpers');

describe('Helper Functions', () => {
  test('formatDate should format date correctly', () => {
    const date = new Date('2023-01-01');
    expect(formatDate(date)).toMatch(/\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}/);
  });

  test('validateEmail should validate email correctly', () => {
    expect(validateEmail('[email protected]')).toBe(true);
    expect(validateEmail('invalid-email')).toBe(false);
  });
});`,
    );

    // Configuration files
    await fs.writeFile(
      path.join(projectPath, ".eslintrc.js"),
      `module.exports = {
  env: { node: true, es2021: true },
  extends: ['eslint:recommended'],
  parserOptions: { ecmaVersion: 12, sourceType: 'module' },
  rules: { 'no-unused-vars': 'warn' }
};`,
    );

    await fs.writeFile(
      path.join(projectPath, "jest.config.js"),
      `module.exports = {
  testEnvironment: 'node',
  collectCoverageFrom: ['src/**/*.js'],
  testMatch: ['**/tests/**/*.test.js']
};`,
    );

    // Documentation
    await fs.writeFile(
      path.join(projectPath, "README.md"),
      `# Realistic Test Project

A comprehensive Node.js application for testing DocuMCP functionality.

## Features

- Express.js web server
- RESTful API endpoints
- User management system
- Comprehensive test suite
- ESLint code quality
- JSDoc documentation

## Getting Started

1. Install dependencies: \`npm install\`
2. Start development server: \`npm run dev\`
3. Run tests: \`npm test\`

## API Endpoints

- \`GET /api/health\` - Health check endpoint
- \`GET /api/users/:id\` - Get user by ID

## Contributing

Please read CONTRIBUTING.md for contribution guidelines.`,
    );

    await fs.writeFile(
      path.join(projectPath, "CONTRIBUTING.md"),
      `# Contributing to Realistic Test Project

## Development Setup

1. Fork the repository
2. Clone your fork
3. Install dependencies
4. Create a feature branch
5. Make changes and test
6. Submit a pull request

## Code Style

- Follow ESLint configuration
- Write tests for new features
- Update documentation as needed`,
    );

    await fs.writeFile(
      path.join(projectPath, "LICENSE"),
      "MIT License\n\nCopyright (c) 2023 Test Author",
    );

    // CI/CD workflow
    await fs.mkdir(path.join(projectPath, ".github", "workflows"), {
      recursive: true,
    });
    await fs.writeFile(
      path.join(projectPath, ".github", "workflows", "ci.yml"),
      `name: CI

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '20'
      - run: npm ci
      - run: npm run lint
      - run: npm test
      - run: npm run build`,
    );

    return projectPath;
  }

  async function createPythonProject(): Promise<string> {
    const projectPath = path.join(tempDir, "python-project");
    await fs.mkdir(projectPath, { recursive: true });

    // Python project structure
    await fs.writeFile(
      path.join(projectPath, "requirements.txt"),
      `flask==2.3.2
requests==2.31.0
pytest==7.4.0
black==23.3.0
flake8==6.0.0`,
    );

    await fs.mkdir(path.join(projectPath, "src"), { recursive: true });
    await fs.writeFile(
      path.join(projectPath, "src", "app.py"),
      `from flask import Flask, jsonify
import requests

app = Flask(__name__)

@app.route('/health')
def health():
    return jsonify({'status': 'OK'})

if __name__ == '__main__':
    app.run(debug=True)`,
    );

    await fs.mkdir(path.join(projectPath, "tests"), { recursive: true });
    await fs.writeFile(
      path.join(projectPath, "tests", "test_app.py"),
      `import pytest
from src.app import app

def test_health():
    client = app.test_client()
    response = client.get('/health')
    assert response.status_code == 200`,
    );

    await fs.writeFile(
      path.join(projectPath, "README.md"),
      "# Python Test Project\n\nA Flask application for testing Python project analysis.",
    );

    return projectPath;
  }

  async function createLargeRepository(): Promise<string> {
    const repoPath = path.join(tempDir, "large-repository");
    await fs.mkdir(repoPath, { recursive: true });

    // Create a repository with 1200+ files to trigger large repo categorization
    await fs.writeFile(
      path.join(repoPath, "package.json"),
      '{"name": "large-repo"}',
    );

    for (let i = 0; i < 30; i++) {
      const dirPath = path.join(repoPath, `module-${i}`);
      await fs.mkdir(dirPath, { recursive: true });

      for (let j = 0; j < 40; j++) {
        const fileName = `component-${j}.js`;
        const content = `// Component ${i}-${j}
export default function Component${i}${j}() {
  return <div>Component ${i}-${j}</div>;
}`;
        await fs.writeFile(path.join(dirPath, fileName), content);
      }
    }

    await fs.writeFile(
      path.join(repoPath, "README.md"),
      "# Large Repository\n\nThis repository has 1200+ files for performance testing.",
    );

    return repoPath;
  }
});

```

--------------------------------------------------------------------------------
/tests/memory/freshness-kg-integration.test.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Tests for Documentation Freshness Knowledge Graph Integration
 */

import { promises as fs } from "fs";
import path from "path";
import { tmpdir } from "os";
import {
  storeFreshnessEvent,
  updateFreshnessEvent,
  getFreshnessHistory,
  getStalenessInsights,
  compareFreshnessAcrossProjects,
} from "../../src/memory/freshness-kg-integration.js";
import type { FreshnessScanReport } from "../../src/utils/freshness-tracker.js";

describe("Freshness Knowledge Graph Integration", () => {
  let testDir: string;

  beforeEach(async () => {
    // Create temporary test directory
    testDir = path.join(tmpdir(), `freshness-kg-test-${Date.now()}`);
    await fs.mkdir(testDir, { recursive: true });

    // Set storage directory to test directory
    process.env.DOCUMCP_STORAGE_DIR = path.join(testDir, ".documcp/memory");
  });

  afterEach(async () => {
    // Clean up test directory
    try {
      await fs.rm(testDir, { recursive: true, force: true });
    } catch (error) {
      // Ignore cleanup errors
    }
    delete process.env.DOCUMCP_STORAGE_DIR;
  });

  describe("storeFreshnessEvent", () => {
    it("should store a freshness scan event in KG", async () => {
      const projectPath = path.join(testDir, "test-project");
      const docsPath = path.join(projectPath, "docs");

      const report: FreshnessScanReport = {
        docsPath,
        scannedAt: new Date().toISOString(),
        totalFiles: 10,
        filesWithMetadata: 8,
        filesWithoutMetadata: 2,
        freshFiles: 6,
        warningFiles: 2,
        staleFiles: 1,
        criticalFiles: 1,
        files: [
          {
            filePath: path.join(docsPath, "page1.md"),
            relativePath: "page1.md",
            hasMetadata: true,
            isStale: false,
            stalenessLevel: "fresh",
            ageInMs: 1000 * 60 * 60 * 24, // 1 day
            ageFormatted: "1 day",
          },
          {
            filePath: path.join(docsPath, "page2.md"),
            relativePath: "page2.md",
            hasMetadata: true,
            isStale: true,
            stalenessLevel: "critical",
            ageInMs: 1000 * 60 * 60 * 24 * 100, // 100 days
            ageFormatted: "100 days",
          },
        ],
        thresholds: {
          warning: { value: 7, unit: "days" },
          stale: { value: 30, unit: "days" },
          critical: { value: 90, unit: "days" },
        },
      };

      const eventId = await storeFreshnessEvent(
        projectPath,
        docsPath,
        report,
        "scan",
      );

      expect(eventId).toBeDefined();
      expect(eventId).toContain("freshness_event:");
    });

    it("should store event with different event types", async () => {
      const projectPath = path.join(testDir, "test-project");
      const docsPath = path.join(projectPath, "docs");

      const report: FreshnessScanReport = {
        docsPath,
        scannedAt: new Date().toISOString(),
        totalFiles: 5,
        filesWithMetadata: 5,
        filesWithoutMetadata: 0,
        freshFiles: 5,
        warningFiles: 0,
        staleFiles: 0,
        criticalFiles: 0,
        files: [],
        thresholds: {
          warning: { value: 7, unit: "days" },
          stale: { value: 30, unit: "days" },
          critical: { value: 90, unit: "days" },
        },
      };

      const initEventId = await storeFreshnessEvent(
        projectPath,
        docsPath,
        report,
        "initialization",
      );
      expect(initEventId).toBeDefined();

      const updateEventId = await storeFreshnessEvent(
        projectPath,
        docsPath,
        report,
        "update",
      );
      expect(updateEventId).toBeDefined();

      const validationEventId = await storeFreshnessEvent(
        projectPath,
        docsPath,
        report,
        "validation",
      );
      expect(validationEventId).toBeDefined();
    });
  });

  describe("getFreshnessHistory", () => {
    it("should retrieve freshness event history", async () => {
      const projectPath = path.join(testDir, "test-project");
      const docsPath = path.join(projectPath, "docs");

      const report: FreshnessScanReport = {
        docsPath,
        scannedAt: new Date().toISOString(),
        totalFiles: 5,
        filesWithMetadata: 5,
        filesWithoutMetadata: 0,
        freshFiles: 5,
        warningFiles: 0,
        staleFiles: 0,
        criticalFiles: 0,
        files: [],
        thresholds: {
          warning: { value: 7, unit: "days" },
          stale: { value: 30, unit: "days" },
          critical: { value: 90, unit: "days" },
        },
      };

      // Store multiple events
      await storeFreshnessEvent(projectPath, docsPath, report, "scan");
      await new Promise((resolve) => setTimeout(resolve, 10)); // Small delay
      await storeFreshnessEvent(projectPath, docsPath, report, "update");

      const history = await getFreshnessHistory(projectPath, 10);

      expect(history).toBeDefined();
      expect(history.length).toBeGreaterThanOrEqual(0);
    });

    it("should return empty array for project with no history", async () => {
      const projectPath = path.join(testDir, "new-project");

      const history = await getFreshnessHistory(projectPath, 10);

      expect(history).toEqual([]);
    });
  });

  describe("getStalenessInsights", () => {
    it("should return insights for project with no history", async () => {
      const projectPath = path.join(testDir, "new-project");

      const insights = await getStalenessInsights(projectPath);

      expect(insights).toBeDefined();
      expect(insights.totalEvents).toBe(0);
      expect(insights.averageImprovementScore).toBe(0);
      expect(insights.trend).toBe("stable");
      expect(insights.currentStatus).toBeNull();
      expect(insights.recommendations.length).toBeGreaterThan(0);
      expect(insights.recommendations[0]).toContain(
        "No freshness tracking history found",
      );
    });

    it("should calculate insights from event history", async () => {
      const projectPath = path.join(testDir, "test-project");
      const docsPath = path.join(projectPath, "docs");

      const report: FreshnessScanReport = {
        docsPath,
        scannedAt: new Date().toISOString(),
        totalFiles: 10,
        filesWithMetadata: 10,
        filesWithoutMetadata: 0,
        freshFiles: 8,
        warningFiles: 1,
        staleFiles: 1,
        criticalFiles: 0,
        files: [],
        thresholds: {
          warning: { value: 7, unit: "days" },
          stale: { value: 30, unit: "days" },
          critical: { value: 90, unit: "days" },
        },
      };

      await storeFreshnessEvent(projectPath, docsPath, report, "scan");

      const insights = await getStalenessInsights(projectPath);

      expect(insights).toBeDefined();
      expect(insights.trend).toMatch(/improving|declining|stable/);
      expect(insights.recommendations).toBeDefined();
      expect(Array.isArray(insights.recommendations)).toBe(true);
    });

    it("should detect improving trend", async () => {
      const projectPath = path.join(testDir, "test-project");
      const docsPath = path.join(projectPath, "docs");

      // Store older event with worse metrics
      const olderReport: FreshnessScanReport = {
        docsPath,
        scannedAt: new Date(Date.now() - 1000 * 60 * 60 * 24).toISOString(),
        totalFiles: 10,
        filesWithMetadata: 10,
        filesWithoutMetadata: 0,
        freshFiles: 5,
        warningFiles: 2,
        staleFiles: 2,
        criticalFiles: 1,
        files: [],
        thresholds: {
          warning: { value: 7, unit: "days" },
          stale: { value: 30, unit: "days" },
          critical: { value: 90, unit: "days" },
        },
      };

      await storeFreshnessEvent(projectPath, docsPath, olderReport, "scan");
      await new Promise((resolve) => setTimeout(resolve, 10));

      // Store newer event with better metrics
      const newerReport: FreshnessScanReport = {
        ...olderReport,
        scannedAt: new Date().toISOString(),
        freshFiles: 9,
        warningFiles: 1,
        staleFiles: 0,
        criticalFiles: 0,
      };

      await storeFreshnessEvent(projectPath, docsPath, newerReport, "scan");

      const insights = await getStalenessInsights(projectPath);

      expect(insights.trend).toMatch(/improving|stable/);
    });

    it("should generate recommendations for critical files", async () => {
      const projectPath = path.join(testDir, "test-project");
      const docsPath = path.join(projectPath, "docs");

      const report: FreshnessScanReport = {
        docsPath,
        scannedAt: new Date().toISOString(),
        totalFiles: 10,
        filesWithMetadata: 10,
        filesWithoutMetadata: 0,
        freshFiles: 5,
        warningFiles: 2,
        staleFiles: 1,
        criticalFiles: 2,
        files: [],
        thresholds: {
          warning: { value: 7, unit: "days" },
          stale: { value: 30, unit: "days" },
          critical: { value: 90, unit: "days" },
        },
      };

      await storeFreshnessEvent(projectPath, docsPath, report, "scan");

      const insights = await getStalenessInsights(projectPath);

      expect(insights).toBeDefined();
      expect(insights.recommendations).toBeDefined();
      expect(Array.isArray(insights.recommendations)).toBe(true);
    });

    it("should recommend validation for files without metadata", async () => {
      const projectPath = path.join(testDir, "test-project");
      const docsPath = path.join(projectPath, "docs");

      const report: FreshnessScanReport = {
        docsPath,
        scannedAt: new Date().toISOString(),
        totalFiles: 10,
        filesWithMetadata: 7,
        filesWithoutMetadata: 3,
        freshFiles: 7,
        warningFiles: 0,
        staleFiles: 0,
        criticalFiles: 0,
        files: [],
        thresholds: {
          warning: { value: 7, unit: "days" },
          stale: { value: 30, unit: "days" },
          critical: { value: 90, unit: "days" },
        },
      };

      await storeFreshnessEvent(projectPath, docsPath, report, "scan");

      const insights = await getStalenessInsights(projectPath);

      expect(insights).toBeDefined();
      expect(insights.recommendations).toBeDefined();
      expect(Array.isArray(insights.recommendations)).toBe(true);
    });
  });

  describe("compareFreshnessAcrossProjects", () => {
    it("should handle project with no history", async () => {
      const projectPath = path.join(testDir, "new-project");

      const comparison = await compareFreshnessAcrossProjects(projectPath);

      expect(comparison).toBeDefined();
      expect(comparison.currentProject.path).toBe(projectPath);
      expect(comparison.currentProject.improvementScore).toBe(0);
      expect(comparison.similarProjects).toEqual([]);
    });

    it("should calculate ranking for project", async () => {
      const projectPath = path.join(testDir, "test-project");
      const docsPath = path.join(projectPath, "docs");

      const report: FreshnessScanReport = {
        docsPath,
        scannedAt: new Date().toISOString(),
        totalFiles: 10,
        filesWithMetadata: 10,
        filesWithoutMetadata: 0,
        freshFiles: 8,
        warningFiles: 1,
        staleFiles: 1,
        criticalFiles: 0,
        files: [],
        thresholds: {
          warning: { value: 7, unit: "days" },
          stale: { value: 30, unit: "days" },
          critical: { value: 90, unit: "days" },
        },
      };

      await storeFreshnessEvent(projectPath, docsPath, report, "scan");

      const comparison = await compareFreshnessAcrossProjects(projectPath);

      expect(comparison.ranking).toBeGreaterThan(0);
    });

    it("should compare with similar projects", async () => {
      const projectPath1 = path.join(testDir, "project1");
      const docsPath1 = path.join(projectPath1, "docs");
      const projectPath2 = path.join(testDir, "project2");
      const docsPath2 = path.join(projectPath2, "docs");

      // Store events for both projects
      const report1: FreshnessScanReport = {
        docsPath: docsPath1,
        scannedAt: new Date().toISOString(),
        totalFiles: 10,
        filesWithMetadata: 10,
        filesWithoutMetadata: 0,
        freshFiles: 9,
        warningFiles: 1,
        staleFiles: 0,
        criticalFiles: 0,
        files: [],
        thresholds: {
          warning: { value: 7, unit: "days" },
          stale: { value: 30, unit: "days" },
          critical: { value: 90, unit: "days" },
        },
      };

      const report2: FreshnessScanReport = {
        ...report1,
        docsPath: docsPath2,
        freshFiles: 7,
        warningFiles: 2,
        staleFiles: 1,
      };

      await storeFreshnessEvent(projectPath1, docsPath1, report1, "scan");
      await storeFreshnessEvent(projectPath2, docsPath2, report2, "scan");

      // The function should work even if there are no similar_to edges
      // (it will just return empty similarProjects array)
      const comparison = await compareFreshnessAcrossProjects(projectPath1);

      expect(comparison.currentProject.path).toBe(projectPath1);
      expect(comparison.similarProjects).toBeDefined();
      expect(Array.isArray(comparison.similarProjects)).toBe(true);
    });
  });

  describe("updateFreshnessEvent", () => {
    it("should update a freshness event with new data", async () => {
      const projectPath = path.join(testDir, "test-project");
      const docsPath = path.join(projectPath, "docs");

      const report: FreshnessScanReport = {
        docsPath,
        scannedAt: new Date().toISOString(),
        totalFiles: 10,
        filesWithMetadata: 8,
        filesWithoutMetadata: 2,
        freshFiles: 8,
        warningFiles: 0,
        staleFiles: 0,
        criticalFiles: 0,
        files: [],
        thresholds: {
          warning: { value: 7, unit: "days" },
          stale: { value: 30, unit: "days" },
          critical: { value: 90, unit: "days" },
        },
      };

      const eventId = await storeFreshnessEvent(
        projectPath,
        docsPath,
        report,
        "scan",
      );

      await updateFreshnessEvent(eventId, {
        filesInitialized: 2,
        filesUpdated: 5,
        eventType: "update",
      });

      // Verify the update by checking history
      const history = await getFreshnessHistory(projectPath, 10);
      expect(history.length).toBeGreaterThan(0);
    });

    it("should throw error for non-existent event", async () => {
      await expect(
        updateFreshnessEvent("freshness_event:nonexistent", {
          filesInitialized: 1,
        }),
      ).rejects.toThrow();
    });
  });

  describe("Edge cases and additional coverage", () => {
    it("should handle more than 10 stale files", async () => {
      const projectPath = path.join(testDir, "test-project");
      const docsPath = path.join(projectPath, "docs");

      // Create 15 stale files
      const staleFiles = Array.from({ length: 15 }, (_, i) => ({
        filePath: path.join(docsPath, `stale${i}.md`),
        relativePath: `stale${i}.md`,
        hasMetadata: true,
        isStale: true,
        stalenessLevel: "stale" as const,
        ageInMs: 1000 * 60 * 60 * 24 * (40 + i), // 40+ days
        ageFormatted: `${40 + i} days`,
      }));

      const report: FreshnessScanReport = {
        docsPath,
        scannedAt: new Date().toISOString(),
        totalFiles: 15,
        filesWithMetadata: 15,
        filesWithoutMetadata: 0,
        freshFiles: 0,
        warningFiles: 0,
        staleFiles: 15,
        criticalFiles: 0,
        files: staleFiles,
        thresholds: {
          warning: { value: 7, unit: "days" },
          stale: { value: 30, unit: "days" },
          critical: { value: 90, unit: "days" },
        },
      };

      const eventId = await storeFreshnessEvent(
        projectPath,
        docsPath,
        report,
        "scan",
      );
      expect(eventId).toBeDefined();

      const history = await getFreshnessHistory(projectPath, 1);
      expect(history[0].event.mostStaleFiles.length).toBeLessThanOrEqual(10);
    });

    it("should recommend action for 30%+ stale files", async () => {
      const projectPath = path.join(testDir, "test-project");
      const docsPath = path.join(projectPath, "docs");

      const report: FreshnessScanReport = {
        docsPath,
        scannedAt: new Date().toISOString(),
        totalFiles: 10,
        filesWithMetadata: 10,
        filesWithoutMetadata: 0,
        freshFiles: 6,
        warningFiles: 0,
        staleFiles: 4, // 40% stale
        criticalFiles: 0,
        files: [],
        thresholds: {
          warning: { value: 7, unit: "days" },
          stale: { value: 30, unit: "days" },
          critical: { value: 90, unit: "days" },
        },
      };

      await storeFreshnessEvent(projectPath, docsPath, report, "scan");

      const insights = await getStalenessInsights(projectPath);
      expect(insights.recommendations).toBeDefined();
      expect(insights.recommendations.length).toBeGreaterThan(0);
      // Check that we get recommendations about stale files
      const hasStaleRecommendation = insights.recommendations.some(
        (r) => r.includes("30%") || r.includes("stale"),
      );
      expect(hasStaleRecommendation).toBe(true);
    });

    it("should detect declining trend", async () => {
      const projectPath = path.join(testDir, "test-project");
      const docsPath = path.join(projectPath, "docs");

      // Store older event with good metrics
      const olderReport: FreshnessScanReport = {
        docsPath,
        scannedAt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 7).toISOString(),
        totalFiles: 10,
        filesWithMetadata: 10,
        filesWithoutMetadata: 0,
        freshFiles: 9,
        warningFiles: 1,
        staleFiles: 0,
        criticalFiles: 0,
        files: [],
        thresholds: {
          warning: { value: 7, unit: "days" },
          stale: { value: 30, unit: "days" },
          critical: { value: 90, unit: "days" },
        },
      };

      await storeFreshnessEvent(projectPath, docsPath, olderReport, "scan");
      await new Promise((resolve) => setTimeout(resolve, 10));

      // Store newer event with worse metrics
      const newerReport: FreshnessScanReport = {
        ...olderReport,
        scannedAt: new Date().toISOString(),
        freshFiles: 5,
        warningFiles: 2,
        staleFiles: 2,
        criticalFiles: 1,
      };

      await storeFreshnessEvent(projectPath, docsPath, newerReport, "scan");

      const insights = await getStalenessInsights(projectPath);
      expect(insights.trend).toMatch(/declining|stable/);
    });

    it("should identify chronically stale files", async () => {
      const projectPath = path.join(testDir, "test-project");
      const docsPath = path.join(projectPath, "docs");

      // Create multiple events with same critical/stale files
      // Need to create enough events so files appear repeatedly
      for (let i = 0; i < 6; i++) {
        const report: FreshnessScanReport = {
          docsPath,
          scannedAt: new Date(
            Date.now() - 1000 * 60 * 60 * 24 * (6 - i),
          ).toISOString(),
          totalFiles: 10,
          filesWithMetadata: 10,
          filesWithoutMetadata: 0,
          freshFiles: 6,
          warningFiles: 0,
          staleFiles: 2,
          criticalFiles: 2,
          files: [
            {
              filePath: path.join(docsPath, "always-stale.md"),
              relativePath: "always-stale.md",
              hasMetadata: true,
              isStale: true,
              stalenessLevel: "critical",
              ageInMs: 1000 * 60 * 60 * 24 * 100,
              ageFormatted: "100 days",
            },
            {
              filePath: path.join(docsPath, "also-stale.md"),
              relativePath: "also-stale.md",
              hasMetadata: true,
              isStale: true,
              stalenessLevel: "critical",
              ageInMs: 1000 * 60 * 60 * 24 * 95,
              ageFormatted: "95 days",
            },
            {
              filePath: path.join(docsPath, "stale-doc.md"),
              relativePath: "stale-doc.md",
              hasMetadata: true,
              isStale: true,
              stalenessLevel: "stale",
              ageInMs: 1000 * 60 * 60 * 24 * 40,
              ageFormatted: "40 days",
            },
            {
              filePath: path.join(docsPath, "another-stale.md"),
              relativePath: "another-stale.md",
              hasMetadata: true,
              isStale: true,
              stalenessLevel: "stale",
              ageInMs: 1000 * 60 * 60 * 24 * 35,
              ageFormatted: "35 days",
            },
          ],
          thresholds: {
            warning: { value: 7, unit: "days" },
            stale: { value: 30, unit: "days" },
            critical: { value: 90, unit: "days" },
          },
        };

        await storeFreshnessEvent(projectPath, docsPath, report, "scan");
        await new Promise((resolve) => setTimeout(resolve, 10));
      }

      const insights = await getStalenessInsights(projectPath);
      // With 6 events and files appearing in all of them,
      // should trigger chronically stale recommendation
      const hasChronicallyStale = insights.recommendations.some(
        (r) => r.includes("chronically") || r.includes("critical"),
      );
      expect(hasChronicallyStale).toBe(true);
    });

    it("should handle files without age information", async () => {
      const projectPath = path.join(testDir, "test-project");
      const docsPath = path.join(projectPath, "docs");

      const report: FreshnessScanReport = {
        docsPath,
        scannedAt: new Date().toISOString(),
        totalFiles: 5,
        filesWithMetadata: 3,
        filesWithoutMetadata: 2,
        freshFiles: 3,
        warningFiles: 0,
        staleFiles: 0,
        criticalFiles: 0,
        files: [
          {
            filePath: path.join(docsPath, "no-metadata.md"),
            relativePath: "no-metadata.md",
            hasMetadata: false,
            isStale: false,
            stalenessLevel: "unknown",
          },
        ],
        thresholds: {
          warning: { value: 7, unit: "days" },
          stale: { value: 30, unit: "days" },
          critical: { value: 90, unit: "days" },
        },
      };

      const eventId = await storeFreshnessEvent(
        projectPath,
        docsPath,
        report,
        "scan",
      );
      expect(eventId).toBeDefined();

      const history = await getFreshnessHistory(projectPath, 1);
      expect(history.length).toBeGreaterThan(0);
      if (history.length > 0) {
        expect(history[0].event.averageAge).toBeUndefined();
        expect(history[0].event.oldestFile).toBeUndefined();
      }
    });
  });
});

```

--------------------------------------------------------------------------------
/src/memory/multi-agent-sharing.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Multi-Agent Memory Sharing System for DocuMCP
 * Implements Issue #50: Multi-Agent Memory Sharing
 *
 * Enables multiple DocuMCP instances to share and synchronize memory,
 * creating a collaborative knowledge network for enhanced learning and recommendations.
 */

import { MemoryManager } from "./manager.js";
import { MemoryEntry } from "./storage.js";
import { EventEmitter } from "events";
import * as crypto from "crypto";

export interface AgentIdentity {
  id: string;
  name: string;
  version: string;
  capabilities: string[];
  lastSeen: string;
  trustLevel: "untrusted" | "low" | "medium" | "high" | "trusted";
  specializations: string[];
}

export interface SharedMemory {
  originalEntry: MemoryEntry;
  sharingMetadata: {
    sourceAgent: string;
    sharedAt: string;
    accessCount: number;
    trustScore: number;
    validatedBy: string[];
    conflicts: string[];
  };
  transformations: Array<{
    agentId: string;
    transformationType:
      | "anonymization"
      | "aggregation"
      | "enrichment"
      | "validation";
    appliedAt: string;
    details: Record<string, any>;
  }>;
}

export interface SyncRequest {
  id: string;
  fromAgent: string;
  toAgent: string;
  requestType: "full_sync" | "incremental" | "selective" | "validation";
  criteria?: {
    types?: string[];
    tags?: string[];
    timeRange?: { start: string; end: string };
    minTrustLevel?: number;
  };
  requestedAt: string;
  status: "pending" | "in_progress" | "completed" | "failed";
}

export interface ConflictResolution {
  conflictId: string;
  conflictType:
    | "duplicate"
    | "contradiction"
    | "version_mismatch"
    | "trust_dispute";
  involvedEntries: string[];
  involvedAgents: string[];
  resolutionStrategy:
    | "merge"
    | "prioritize_trusted"
    | "manual_review"
    | "temporal_precedence";
  resolvedAt?: string;
  resolution?: {
    action: string;
    resultingEntry?: MemoryEntry;
    metadata: Record<string, any>;
  };
}

export interface CollaborativeInsight {
  id: string;
  type: "trend" | "pattern" | "anomaly" | "consensus" | "disagreement";
  description: string;
  evidence: string[];
  contributingAgents: string[];
  confidence: number;
  generatedAt: string;
  actionable: boolean;
  recommendations?: string[];
}

export class MultiAgentMemorySharing extends EventEmitter {
  private memoryManager: MemoryManager;
  private agentId: string;
  private knownAgents: Map<string, AgentIdentity>;
  private sharedMemories: Map<string, SharedMemory>;
  private syncRequests: Map<string, SyncRequest>;
  private conflicts: Map<string, ConflictResolution>;
  private collaborativeInsights: Map<string, CollaborativeInsight>;
  private syncInterval: NodeJS.Timeout | null = null;

  constructor(
    memoryManager: MemoryManager,
    agentIdentity: Partial<AgentIdentity>,
  ) {
    super();
    this.memoryManager = memoryManager;
    this.agentId = agentIdentity.id || this.generateAgentId();
    this.knownAgents = new Map();
    this.sharedMemories = new Map();
    this.syncRequests = new Map();
    this.conflicts = new Map();
    this.collaborativeInsights = new Map();

    // Register self
    this.registerAgent({
      id: this.agentId,
      name: agentIdentity.name || "DocuMCP Agent",
      version: agentIdentity.version || "1.0.0",
      capabilities: agentIdentity.capabilities || [
        "analysis",
        "recommendation",
        "deployment",
      ],
      lastSeen: new Date().toISOString(),
      trustLevel: "trusted",
      specializations: agentIdentity.specializations || [],
    });
  }

  /**
   * Initialize multi-agent sharing
   */
  async initialize(): Promise<void> {
    await this.loadSharedMemories();
    await this.loadKnownAgents();
    await this.loadPendingSyncRequests();

    // Start periodic sync
    this.startPeriodicSync();

    this.emit("initialized", { agentId: this.agentId });
  }

  /**
   * Register a new agent in the network
   */
  async registerAgent(agent: AgentIdentity): Promise<void> {
    this.knownAgents.set(agent.id, {
      ...agent,
      lastSeen: new Date().toISOString(),
    });

    await this.persistAgentRegistry();
    this.emit("agent-registered", agent);
  }

  /**
   * Share a memory entry with other agents
   */
  async shareMemory(
    memoryId: string,
    targetAgents?: string[],
    options?: {
      anonymize?: boolean;
      requireValidation?: boolean;
      trustLevel?: number;
    },
  ): Promise<SharedMemory> {
    const memory = await this.memoryManager.recall(memoryId);
    if (!memory) {
      throw new Error(`Memory ${memoryId} not found`);
    }

    // Create shared memory wrapper
    const sharedMemory: SharedMemory = {
      originalEntry: this.anonymizeIfRequired(memory, options?.anonymize),
      sharingMetadata: {
        sourceAgent: this.agentId,
        sharedAt: new Date().toISOString(),
        accessCount: 0,
        trustScore: this.calculateInitialTrustScore(memory),
        validatedBy: [],
        conflicts: [],
      },
      transformations: [],
    };

    // Apply anonymization transformation if required
    if (options?.anonymize) {
      sharedMemory.transformations.push({
        agentId: this.agentId,
        transformationType: "anonymization",
        appliedAt: new Date().toISOString(),
        details: { level: "standard", preserveStructure: true },
      });
    }

    this.sharedMemories.set(memoryId, sharedMemory);

    // Create sync requests for target agents
    if (targetAgents) {
      for (const targetAgent of targetAgents) {
        await this.createSyncRequest(targetAgent, "selective", {
          memoryIds: [memoryId],
        });
      }
    } else {
      // Broadcast to all trusted agents
      await this.broadcastToTrustedAgents(sharedMemory);
    }

    await this.persistSharedMemories();
    this.emit("memory-shared", { memoryId, sharedMemory });

    return sharedMemory;
  }

  /**
   * Receive shared memory from another agent
   */
  async receiveSharedMemory(
    sharedMemory: SharedMemory,
    sourceAgent: string,
  ): Promise<{
    accepted: boolean;
    conflicts?: ConflictResolution[];
    integrationResult?: string;
  }> {
    // Validate source agent trust level
    const sourceAgentInfo = this.knownAgents.get(sourceAgent);
    if (!sourceAgentInfo || sourceAgentInfo.trustLevel === "untrusted") {
      return { accepted: false };
    }

    // Check for conflicts with existing memories
    const conflicts = await this.detectConflicts(sharedMemory);

    if (conflicts.length > 0) {
      // Store conflicts for resolution
      for (const conflict of conflicts) {
        this.conflicts.set(conflict.conflictId, conflict);
        await this.resolveConflict(conflict);
      }

      this.emit("conflict-detected", { conflicts, sharedMemory });
    }

    // Integrate the shared memory
    const integrationResult = await this.integrateSharedMemory(
      sharedMemory,
      sourceAgent,
    );

    // Update sharing metadata
    sharedMemory.sharingMetadata.accessCount++;

    this.emit("memory-received", {
      sharedMemory,
      sourceAgent,
      integrationResult,
    });

    return {
      accepted: true,
      conflicts: conflicts.length > 0 ? conflicts : undefined,
      integrationResult,
    };
  }

  /**
   * Request synchronization with another agent
   */
  async requestSync(
    targetAgent: string,
    syncType: SyncRequest["requestType"] = "incremental",
    criteria?: SyncRequest["criteria"],
  ): Promise<SyncRequest> {
    const syncRequest: SyncRequest = {
      id: this.generateSyncId(),
      fromAgent: this.agentId,
      toAgent: targetAgent,
      requestType: syncType,
      criteria,
      requestedAt: new Date().toISOString(),
      status: "pending",
    };

    this.syncRequests.set(syncRequest.id, syncRequest);
    await this.persistSyncRequests();

    this.emit("sync-requested", syncRequest);
    return syncRequest;
  }

  /**
   * Process incoming sync request
   */
  async processSyncRequest(syncRequest: SyncRequest): Promise<{
    approved: boolean;
    memories?: SharedMemory[];
    reason?: string;
  }> {
    // Validate requesting agent
    const requestingAgent = this.knownAgents.get(syncRequest.fromAgent);
    if (!requestingAgent || requestingAgent.trustLevel === "untrusted") {
      return { approved: false, reason: "Untrusted agent" };
    }

    // Update request status
    syncRequest.status = "in_progress";
    this.syncRequests.set(syncRequest.id, syncRequest);

    try {
      // Get memories based on sync type and criteria
      const memories = await this.getMemoriesForSync(syncRequest);

      syncRequest.status = "completed";
      this.emit("sync-completed", {
        syncRequest,
        memoriesCount: memories.length,
      });

      return { approved: true, memories };
    } catch (error) {
      syncRequest.status = "failed";
      this.emit("sync-failed", { syncRequest, error });

      return {
        approved: false,
        reason: error instanceof Error ? error.message : "Unknown error",
      };
    }
  }

  /**
   * Generate collaborative insights from shared memories
   */
  async generateCollaborativeInsights(): Promise<CollaborativeInsight[]> {
    const insights: CollaborativeInsight[] = [];

    // Analyze trends across agents
    const trends = await this.analyzeTrends();
    insights.push(...trends);

    // Find consensus patterns
    const consensus = await this.findConsensusPatterns();
    insights.push(...consensus);

    // Identify disagreements that need attention
    const disagreements = await this.identifyDisagreements();
    insights.push(...disagreements);

    // Detect anomalies
    const anomalies = await this.detectAnomalies();
    insights.push(...anomalies);

    // Store insights
    for (const insight of insights) {
      this.collaborativeInsights.set(insight.id, insight);
    }

    await this.persistCollaborativeInsights();
    this.emit("insights-generated", { count: insights.length });

    return insights;
  }

  /**
   * Validate shared memory against local knowledge
   */
  async validateSharedMemory(sharedMemory: SharedMemory): Promise<{
    isValid: boolean;
    confidence: number;
    issues: string[];
    recommendations: string[];
  }> {
    const issues: string[] = [];
    const recommendations: string[] = [];
    let confidence = 1.0;

    // Check data consistency
    if (!this.validateDataStructure(sharedMemory.originalEntry)) {
      issues.push("Invalid data structure");
      confidence *= 0.7;
    }

    // Cross-validate with local memories
    const similarMemories = await this.findSimilarLocalMemories(
      sharedMemory.originalEntry,
    );
    if (similarMemories.length > 0) {
      const consistencyScore = this.calculateConsistency(
        sharedMemory.originalEntry,
        similarMemories,
      );
      if (consistencyScore < 0.8) {
        issues.push("Inconsistent with local knowledge");
        confidence *= consistencyScore;
      }
    }

    // Check source agent reliability
    const sourceAgent = this.knownAgents.get(
      sharedMemory.sharingMetadata.sourceAgent,
    );
    if (sourceAgent) {
      if (sourceAgent.trustLevel === "low") {
        confidence *= 0.8;
        recommendations.push("Verify with additional sources");
      } else if (
        sourceAgent.trustLevel === "high" ||
        sourceAgent.trustLevel === "trusted"
      ) {
        confidence *= 1.1;
      }
    }

    // Validate transformations
    for (const transformation of sharedMemory.transformations) {
      if (transformation.transformationType === "anonymization") {
        // Check if anonymization preserved essential information
        if (!this.validateAnonymization(transformation)) {
          issues.push("Anonymization may have removed critical information");
          confidence *= 0.9;
        }
      }
    }

    return {
      isValid: issues.length === 0 || confidence > 0.6,
      confidence: Math.min(confidence, 1.0),
      issues,
      recommendations,
    };
  }

  /**
   * Get network statistics
   */
  getNetworkStatistics(): {
    connectedAgents: number;
    sharedMemories: number;
    activeSyncs: number;
    resolvedConflicts: number;
    trustDistribution: Record<string, number>;
    collaborativeInsights: number;
    networkHealth: number;
  } {
    const trustDistribution: Record<string, number> = {};
    for (const agent of this.knownAgents.values()) {
      trustDistribution[agent.trustLevel] =
        (trustDistribution[agent.trustLevel] || 0) + 1;
    }

    const activeSyncs = Array.from(this.syncRequests.values()).filter(
      (req) => req.status === "pending" || req.status === "in_progress",
    ).length;

    const resolvedConflicts = Array.from(this.conflicts.values()).filter(
      (conflict) => conflict.resolvedAt,
    ).length;

    // Calculate network health (0-1)
    const trustedAgents = Array.from(this.knownAgents.values()).filter(
      (agent) => agent.trustLevel === "high" || agent.trustLevel === "trusted",
    ).length;
    const totalAgents = this.knownAgents.size;
    const networkHealth = totalAgents > 0 ? trustedAgents / totalAgents : 0;

    return {
      connectedAgents: this.knownAgents.size,
      sharedMemories: this.sharedMemories.size,
      activeSyncs,
      resolvedConflicts,
      trustDistribution,
      collaborativeInsights: this.collaborativeInsights.size,
      networkHealth,
    };
  }

  // Private helper methods

  private generateAgentId(): string {
    return `agent_${crypto.randomBytes(8).toString("hex")}`;
  }

  private generateSyncId(): string {
    return `sync_${Date.now()}_${crypto.randomBytes(4).toString("hex")}`;
  }

  private anonymizeIfRequired(
    memory: MemoryEntry,
    anonymize?: boolean,
  ): MemoryEntry {
    if (!anonymize) return memory;

    // Create anonymized copy
    const anonymized = JSON.parse(JSON.stringify(memory));

    // Remove/hash sensitive information
    if (anonymized.metadata.repository) {
      anonymized.metadata.repository = this.hashSensitiveData(
        anonymized.metadata.repository,
      );
    }

    if (anonymized.metadata.projectId) {
      anonymized.metadata.projectId = this.hashSensitiveData(
        anonymized.metadata.projectId,
      );
    }

    // Remove file paths and specific identifiers
    if (anonymized.data.files) {
      delete anonymized.data.files;
    }

    return anonymized;
  }

  private hashSensitiveData(data: string): string {
    return crypto
      .createHash("sha256")
      .update(data)
      .digest("hex")
      .substring(0, 16);
  }

  private calculateInitialTrustScore(memory: MemoryEntry): number {
    let score = 0.5; // Base score

    // Boost for successful outcomes
    if (memory.data.status === "success") score += 0.2;

    // Boost for rich metadata
    if (memory.metadata.tags && memory.metadata.tags.length > 2) score += 0.1;

    // Boost for recent data
    const daysSince =
      (Date.now() - new Date(memory.timestamp).getTime()) /
      (1000 * 60 * 60 * 24);
    if (daysSince <= 30) score += 0.1;

    // Boost for complete data
    if (memory.checksum) score += 0.1;

    return Math.min(score, 1.0);
  }

  private async detectConflicts(
    sharedMemory: SharedMemory,
  ): Promise<ConflictResolution[]> {
    const conflicts: ConflictResolution[] = [];

    // Check for duplicates
    const similarLocal = await this.findSimilarLocalMemories(
      sharedMemory.originalEntry,
    );
    for (const similar of similarLocal) {
      if (this.isLikelyDuplicate(sharedMemory.originalEntry, similar)) {
        conflicts.push({
          conflictId: `conflict_${Date.now()}_${crypto
            .randomBytes(4)
            .toString("hex")}`,
          conflictType: "duplicate",
          involvedEntries: [sharedMemory.originalEntry.id, similar.id],
          involvedAgents: [
            sharedMemory.sharingMetadata.sourceAgent,
            this.agentId,
          ],
          resolutionStrategy: "merge",
        });
      }
    }

    return conflicts;
  }

  private async resolveConflict(conflict: ConflictResolution): Promise<void> {
    // Implement conflict resolution based on strategy
    switch (conflict.resolutionStrategy) {
      case "merge":
        await this.mergeConflictingEntries(conflict);
        break;
      case "prioritize_trusted":
        await this.prioritizeTrustedSource(conflict);
        break;
      case "temporal_precedence":
        await this.useTemporalPrecedence(conflict);
        break;
      default:
        // Mark for manual review
        conflict.resolutionStrategy = "manual_review";
    }

    conflict.resolvedAt = new Date().toISOString();
    this.conflicts.set(conflict.conflictId, conflict);
  }

  private async integrateSharedMemory(
    sharedMemory: SharedMemory,
    sourceAgent: string,
  ): Promise<string> {
    // Add transformation for integration
    sharedMemory.transformations.push({
      agentId: this.agentId,
      transformationType: "enrichment",
      appliedAt: new Date().toISOString(),
      details: { integratedFrom: sourceAgent },
    });

    // Store in local memory with special metadata
    const enrichedEntry = {
      ...sharedMemory.originalEntry,
      metadata: {
        ...sharedMemory.originalEntry.metadata,
        sharedFrom: sourceAgent,
        integratedAt: new Date().toISOString(),
        tags: [
          ...(sharedMemory.originalEntry.metadata.tags || []),
          "shared",
          "collaborative",
        ],
      },
    };

    await this.memoryManager.remember(
      enrichedEntry.type,
      enrichedEntry.data,
      enrichedEntry.metadata,
    );

    return "integrated_successfully";
  }

  private async getMemoriesForSync(
    syncRequest: SyncRequest,
  ): Promise<SharedMemory[]> {
    const allMemories = await this.memoryManager.search("", {
      sortBy: "timestamp",
    });
    let filteredMemories = allMemories;

    // Apply criteria filtering
    if (syncRequest.criteria) {
      if (syncRequest.criteria.types) {
        filteredMemories = filteredMemories.filter((m) =>
          syncRequest.criteria!.types!.includes(m.type),
        );
      }

      if (syncRequest.criteria.tags) {
        filteredMemories = filteredMemories.filter(
          (m) =>
            m.metadata.tags?.some((tag) =>
              syncRequest.criteria!.tags!.includes(tag),
            ),
        );
      }

      if (syncRequest.criteria.timeRange) {
        const start = new Date(syncRequest.criteria.timeRange.start);
        const end = new Date(syncRequest.criteria.timeRange.end);
        filteredMemories = filteredMemories.filter((m) => {
          const memTime = new Date(m.timestamp);
          return memTime >= start && memTime <= end;
        });
      }
    }

    // Convert to shared memories
    return filteredMemories.map((memory) => ({
      originalEntry: memory,
      sharingMetadata: {
        sourceAgent: this.agentId,
        sharedAt: new Date().toISOString(),
        accessCount: 0,
        trustScore: this.calculateInitialTrustScore(memory),
        validatedBy: [],
        conflicts: [],
      },
      transformations: [],
    }));
  }

  private async analyzeTrends(): Promise<CollaborativeInsight[]> {
    // Analyze shared memories to identify trends
    return []; // Placeholder implementation
  }

  private async findConsensusPatterns(): Promise<CollaborativeInsight[]> {
    // Find patterns where multiple agents agree
    return []; // Placeholder implementation
  }

  private async identifyDisagreements(): Promise<CollaborativeInsight[]> {
    // Find areas where agents disagree
    return []; // Placeholder implementation
  }

  private async detectAnomalies(): Promise<CollaborativeInsight[]> {
    // Detect unusual patterns in shared data
    return []; // Placeholder implementation
  }

  private validateDataStructure(entry: MemoryEntry): boolean {
    return Boolean(entry.id && entry.timestamp && entry.type && entry.data);
  }

  private async findSimilarLocalMemories(
    entry: MemoryEntry,
  ): Promise<MemoryEntry[]> {
    // Find similar memories in local storage
    return this.memoryManager.search(entry.metadata.projectId || "", {
      sortBy: "timestamp",
    });
  }

  private calculateConsistency(
    _entry: MemoryEntry,
    _similar: MemoryEntry[],
  ): number {
    // Calculate consistency score (placeholder)
    return 0.8;
  }

  private validateAnonymization(_transformation: any): boolean {
    // Validate anonymization transformation (placeholder)
    return true;
  }

  private isLikelyDuplicate(entry1: MemoryEntry, entry2: MemoryEntry): boolean {
    // Simple duplicate detection
    return (
      entry1.type === entry2.type &&
      entry1.metadata.projectId === entry2.metadata.projectId &&
      Math.abs(
        new Date(entry1.timestamp).getTime() -
          new Date(entry2.timestamp).getTime(),
      ) < 60000
    ); // 1 minute
  }

  private async mergeConflictingEntries(
    _conflict: ConflictResolution,
  ): Promise<void> {
    // Merge conflicting entries (placeholder)
  }

  private async prioritizeTrustedSource(
    _conflict: ConflictResolution,
  ): Promise<void> {
    // Prioritize trusted source (placeholder)
  }

  private async useTemporalPrecedence(
    _conflict: ConflictResolution,
  ): Promise<void> {
    // Use temporal precedence (placeholder)
  }

  private async broadcastToTrustedAgents(
    _sharedMemory: SharedMemory,
  ): Promise<void> {
    // Broadcast to trusted agents (placeholder)
  }

  private startPeriodicSync(): void {
    this.syncInterval = setInterval(
      async () => {
        await this.performPeriodicSync();
      },
      5 * 60 * 1000,
    ); // Every 5 minutes
  }

  private async performPeriodicSync(): Promise<void> {
    // Perform periodic synchronization with trusted agents
  }

  private async loadSharedMemories(): Promise<void> {
    // Load shared memories from persistence
  }

  private async loadKnownAgents(): Promise<void> {
    // Load known agents from persistence
  }

  private async loadPendingSyncRequests(): Promise<void> {
    // Load pending sync requests from persistence
  }

  private async persistSharedMemories(): Promise<void> {
    // Persist shared memories
  }

  private async persistAgentRegistry(): Promise<void> {
    // Persist agent registry
  }

  private async persistSyncRequests(): Promise<void> {
    // Persist sync requests
  }

  private async persistCollaborativeInsights(): Promise<void> {
    // Persist collaborative insights
  }

  private async createSyncRequest(
    _targetAgent: string,
    _type: SyncRequest["requestType"],
    _options: any,
  ): Promise<void> {
    // Create sync request (placeholder)
  }

  /**
   * Cleanup and shutdown
   */
  async shutdown(): Promise<void> {
    if (this.syncInterval) {
      clearInterval(this.syncInterval);
    }

    await this.persistSharedMemories();
    await this.persistAgentRegistry();
    await this.persistSyncRequests();
    await this.persistCollaborativeInsights();

    this.emit("shutdown", { agentId: this.agentId });
  }
}

export default MultiAgentMemorySharing;

```

--------------------------------------------------------------------------------
/docs/how-to/usage-examples.md:
--------------------------------------------------------------------------------

```markdown
---
documcp:
  last_updated: "2025-11-20T00:46:21.957Z"
  last_validated: "2025-11-20T00:46:21.957Z"
  auto_updated: false
  update_frequency: monthly
---

# DocuMCP Usage Examples

This guide provides comprehensive usage examples for DocuMCP functions, organized by common use cases and scenarios.

## 🎯 Repository Analysis Examples

### Basic Repository Analysis

```typescript
import { analyzeRepository } from "./dist/tools/analyze-repository.js";

// Analyze a simple project
const analysis = await analyzeRepository({
  path: "/path/to/my-project",
  depth: "standard",
});

console.log(`Found ${analysis.data.structure.totalFiles} files`);
console.log(
  `Primary language: ${analysis.data.recommendations.primaryLanguage}`,
);
```

### Advanced Repository Analysis

```typescript
// Deep analysis with historical context
const deepAnalysis = await analyzeRepository({
  path: "/path/to/complex-project",
  depth: "deep",
});

// Access detailed information
const { structure, dependencies, documentation } = deepAnalysis.data;

console.log(`Languages: ${Object.keys(structure.languages).join(", ")}`);
console.log(`Has tests: ${structure.hasTests}`);
console.log(`Has CI: ${structure.hasCI}`);
console.log(`Documentation complexity: ${documentation.estimatedComplexity}`);
```

## 🔧 SSG Recommendation Examples

### Basic SSG Recommendation

```typescript
import { recommendSSG } from "./dist/tools/recommend-ssg.js";

// Get recommendation based on analysis
const recommendation = await recommendSSG({
  analysisId: "analysis_abc123_def456",
  userId: "developer123",
});

console.log(`Recommended SSG: ${recommendation.data.recommended}`);
console.log(`Confidence: ${recommendation.data.confidence * 100}%`);
console.log(`Reasoning: ${recommendation.data.reasoning.join(", ")}`);
```

### Personalized SSG Recommendation

```typescript
// With user preferences
const personalized = await recommendSSG({
  analysisId: "analysis_abc123_def456",
  userId: "developer123",
  preferences: {
    priority: "performance",
    ecosystem: "javascript",
  },
});

// Compare alternatives
recommendation.data.alternatives.forEach((alt) => {
  console.log(`${alt.name}: ${alt.score} (${alt.pros.join(", ")})`);
});
```

### Enterprise SSG Recommendation

```typescript
// Enterprise-focused recommendation
const enterprise = await recommendSSG({
  analysisId: "analysis_abc123_def456",
  userId: "enterprise_user",
  preferences: {
    priority: "simplicity",
    ecosystem: "any",
  },
});

// Check historical data
if (recommendation.data.historicalData) {
  const { similarProjectCount, successRates } =
    recommendation.data.historicalData;
  console.log(`Based on ${similarProjectCount} similar projects`);
  console.log(`Success rates: ${JSON.stringify(successRates, null, 2)}`);
}
```

## 📁 Documentation Structure Examples

### Basic Structure Setup

```typescript
import { setupStructure } from "./dist/tools/setup-structure.js";

// Set up Docusaurus structure with Diataxis framework
const structure = await setupStructure({
  path: "./docs",
  ssg: "docusaurus",
  includeExamples: true,
});

console.log(`Created ${structure.data.directoriesCreated.length} directories`);
console.log(`Created ${structure.data.filesCreated.length} files`);
console.log(
  `Diataxis structure: ${Object.keys(structure.data.diataxisStructure).join(
    ", ",
  )}`,
);
```

### Minimal Structure Setup

```typescript
// Minimal structure for existing projects
const minimal = await setupStructure({
  path: "./site",
  ssg: "hugo",
  includeExamples: false,
});

// Check what was created
minimal.data.directoriesCreated.forEach((dir) => {
  console.log(`Created directory: ${dir}`);
});
```

### Custom Structure Setup

```typescript
// Custom structure with specific categories
const custom = await setupStructure({
  path: "./custom-docs",
  ssg: "mkdocs",
  includeExamples: true,
});

// Access structure details
const { diataxisStructure, ssgSpecificFiles } = custom.data;
console.log(
  `Diataxis categories: ${Object.keys(diataxisStructure).join(", ")}`,
);
```

## ⚙️ Configuration Generation Examples

### Docusaurus Configuration

```typescript
import { generateConfig } from "documcp";

// Generate Docusaurus configuration
const config = await generateConfig({
  ssg: "docusaurus",
  projectName: "My Awesome Project",
  projectDescription: "A comprehensive documentation project",
  outputPath: "./docs",
});

console.log(`Generated ${config.data.filesCreated.length} configuration files`);
config.data.filesCreated.forEach((file) => {
  console.log(`Created: ${file}`);
});
```

### Hugo Configuration

```typescript
// Generate Hugo configuration
const hugoConfig = await generateConfig({
  ssg: "hugo",
  projectName: "My Hugo Site",
  outputPath: "./site",
});

// Check configuration details
const { ssg, projectName, filesCreated } = hugoConfig.data;
console.log(`Generated ${ssg} configuration for ${projectName}`);
```

### Multi-SSG Configuration

```typescript
// Generate configurations for multiple SSGs
const ssgs = ["docusaurus", "hugo", "mkdocs"];

for (const ssg of ssgs) {
  const config = await generateConfig({
    ssg: ssg as any,
    projectName: "Multi-SSG Project",
    outputPath: `./docs-${ssg}`,
  });

  console.log(
    `Generated ${ssg} configuration: ${config.data.filesCreated.length} files`,
  );
}
```

## 📝 Content Population Examples

### Basic Content Population

```typescript
import { handlePopulateDiataxisContent } from "documcp";

// Populate documentation content
const population = await handlePopulateDiataxisContent({
  analysisId: "analysis_abc123_def456",
  docsPath: "./docs",
  populationLevel: "comprehensive",
});

console.log(
  `Generated ${population.data.contentGenerated.length} content files`,
);
console.log(
  `Extracted ${population.data.contentExtracted.length} content pieces`,
);
```

### Focused Content Population

```typescript
// Populate with specific focus areas
const focused = await handlePopulateDiataxisContent({
  analysisId: "analysis_abc123_def456",
  docsPath: "./docs",
  populationLevel: "intelligent",
  focusAreas: ["api", "examples", "tutorials"],
});

// Check what was generated
focused.data.contentGenerated.forEach((content) => {
  console.log(`Generated: ${content.category}/${content.filename}`);
});
```

### Technology-Focused Population

```typescript
// Populate with technology focus
const techFocused = await handlePopulateDiataxisContent({
  analysisId: "analysis_abc123_def456",
  docsPath: "./docs",
  technologyFocus: ["React", "TypeScript", "Node.js"],
});

// Access generated content
techFocused.data.contentGenerated.forEach((content) => {
  if (content.technology) {
    console.log(
      `Technology-specific content: ${content.filename} (${content.technology})`,
    );
  }
});
```

## 🚀 Deployment Examples

### Basic GitHub Pages Deployment

```typescript
import { handleDeployPages } from "documcp";

// Deploy to GitHub Pages
const deployment = await handleDeployPages({
  repository: "user/repository",
  ssg: "docusaurus",
});

console.log(`Deployment URL: ${deployment.data.url}`);
console.log(`Status: ${deployment.data.status}`);
```

### Custom Domain Deployment

```typescript
// Deploy with custom domain
const customDomain = await handleDeployPages({
  repository: "user/repository",
  ssg: "docusaurus",
  customDomain: "docs.example.com",
});

// Check deployment details
const { url, status, configuration } = customDomain.data;
console.log(`Deployed to: ${url}`);
console.log(`Custom domain: ${configuration.customDomain}`);
```

### Branch-Specific Deployment

```typescript
// Deploy to specific branch
const branchDeployment = await handleDeployPages({
  repository: "user/repository",
  ssg: "docusaurus",
  branch: "gh-pages",
});

// Monitor deployment
if (branchDeployment.data.status === "success") {
  console.log(`Successfully deployed to ${branchDeployment.data.branch}`);
} else {
  console.log(`Deployment failed: ${branchDeployment.data.error}`);
}
```

## 🧠 Memory System Examples

### Memory Initialization

```typescript
import { initializeMemory } from "documcp/memory";

// Initialize memory system
const memory = await initializeMemory("./custom-memory-storage");

console.log("Memory system initialized");
console.log(`Storage directory: ${memory.storageDir}`);
```

### Storing Analysis Data

```typescript
import { rememberAnalysis } from "documcp/memory";

// Store analysis data
const memoryId = await rememberAnalysis("/path/to/project", {
  id: "analysis_123",
  structure: { totalFiles: 150, languages: { ".ts": 100 } },
  dependencies: { ecosystem: "javascript", packages: ["react"] },
});

console.log(`Stored analysis with ID: ${memoryId}`);
```

### Retrieving Project Insights

```typescript
import { getProjectInsights } from "documcp/memory";

// Get project insights
const insights = await getProjectInsights("project_abc123");

insights.forEach((insight) => {
  console.log(`💡 ${insight}`);
});
```

### Finding Similar Projects

```typescript
import { getSimilarProjects } from "documcp/memory";

// Find similar projects
const similar = await getSimilarProjects(analysisData, 5);

console.log(`Found ${similar.length} similar projects:`);
similar.forEach((project) => {
  console.log(
    `- ${project.metadata.projectId} (${project.similarity}% similar)`,
  );
});
```

## 📊 README Analysis Examples

### Basic README Analysis

```typescript
import { analyzeReadme } from "documcp";

// Analyze README
const analysis = await analyzeReadme({
  project_path: "/path/to/project",
});

const { analysis: readmeAnalysis } = analysis.data;
console.log(`README Score: ${readmeAnalysis.overallScore}/100`);
console.log(
  `Current length: ${readmeAnalysis.lengthAnalysis.currentLines} lines`,
);
console.log(
  `Target length: ${readmeAnalysis.lengthAnalysis.targetLines} lines`,
);
```

### Community-Focused Analysis

```typescript
// Analyze for community contributors
const communityAnalysis = await analyzeReadme({
  project_path: "/path/to/project",
  target_audience: "community_contributors",
  optimization_level: "moderate",
});

const { communityReadiness } = communityAnalysis.data.analysis;
console.log(`Has contributing guide: ${communityReadiness.hasContributing}`);
console.log(`Has code of conduct: ${communityReadiness.hasCodeOfConduct}`);
console.log(`Badge count: ${communityReadiness.badgeCount}`);
```

### Enterprise README Analysis

```typescript
// Analyze for enterprise users
const enterpriseAnalysis = await analyzeReadme({
  project_path: "/path/to/project",
  target_audience: "enterprise_users",
  optimization_level: "aggressive",
  max_length_target: 200,
});

const { optimizationOpportunities } = enterpriseAnalysis.data.analysis;
optimizationOpportunities.forEach((opportunity) => {
  console.log(
    `${opportunity.type}: ${opportunity.description} (${opportunity.priority})`,
  );
});
```

## 🔧 README Optimization Examples

### Basic README Optimization

```typescript
import { optimizeReadme } from "documcp";

// Optimize README
const optimization = await optimizeReadme({
  readme_path: "./README.md",
  strategy: "community_focused",
});

const { optimization: result } = optimization.data;
console.log(
  `Reduced from ${result.originalLength} to ${result.optimizedLength} lines`,
);
console.log(`Reduction: ${result.reductionPercentage}%`);
```

### Enterprise README Optimization

```typescript
// Optimize for enterprise
const enterpriseOptimization = await optimizeReadme({
  readme_path: "./README.md",
  strategy: "enterprise_focused",
  max_length: 200,
  preserve_existing: true,
});

// Check restructuring changes
enterpriseOptimization.data.optimization.restructuringChanges.forEach(
  (change) => {
    console.log(`${change.type}: ${change.section} - ${change.description}`);
  },
);
```

### README Template Generation

```typescript
import { generateReadmeTemplate } from "documcp";

// Generate README template
const template = await generateReadmeTemplate({
  projectName: "MyAwesomeProject",
  description: "A powerful utility library",
  templateType: "library",
  author: "Your Name",
  license: "MIT",
  includeBadges: true,
  outputPath: "./README.md",
});

console.log(`Generated ${template.metadata.estimatedLength} line README`);
console.log(`Sections included: ${template.metadata.sectionsIncluded}`);
```

## 🔗 Link Checking Examples

### Basic Link Checking

```typescript
import { checkDocumentationLinks } from "documcp";

// Check documentation links
const linkCheck = await checkDocumentationLinks({
  documentation_path: "./docs",
  check_external_links: true,
  check_internal_links: true,
  check_anchor_links: true,
});

console.log(`Total links checked: ${linkCheck.data.totalLinks}`);
console.log(`Broken links: ${linkCheck.data.brokenLinks}`);
console.log(`Success rate: ${linkCheck.data.successRate}%`);
```

### Comprehensive Link Checking

```typescript
// Comprehensive link checking
const comprehensive = await checkDocumentationLinks({
  documentation_path: "./docs",
  check_external_links: true,
  check_internal_links: true,
  check_anchor_links: true,
  timeout_ms: 10000,
  max_concurrent_checks: 10,
  fail_on_broken_links: false,
});

// Check specific link types
comprehensive.data.linkTypes.forEach((linkType) => {
  console.log(
    `${linkType.type}: ${linkType.total} total, ${linkType.broken} broken`,
  );
});
```

## 🧪 Local Testing Examples

### Local Documentation Testing

```typescript
import { handleTestLocalDeployment } from "documcp";

// Test local deployment
const test = await handleTestLocalDeployment({
  repositoryPath: "/path/to/project",
  ssg: "docusaurus",
  port: 3000,
  timeout: 60,
});

console.log(`Test status: ${test.data.status}`);
console.log(`Local URL: ${test.data.localUrl}`);
console.log(`Build time: ${test.data.buildTime}ms`);
```

### Docker Testing

```typescript
// Test with Docker
const dockerTest = await handleTestLocalDeployment({
  repositoryPath: "/path/to/project",
  ssg: "hugo",
  port: 8080,
  timeout: 120,
});

if (dockerTest.data.status === "success") {
  console.log(`Docker test successful: ${dockerTest.data.localUrl}`);
} else {
  console.log(`Docker test failed: ${dockerTest.data.error}`);
}
```

## 🔄 Workflow Examples

### Complete Documentation Workflow

```typescript
// Complete workflow from analysis to deployment
async function completeDocumentationWorkflow(projectPath: string) {
  try {
    // 1. Analyze repository
    const analysis = await analyzeRepository({
      path: projectPath,
      depth: "standard",
    });

    const analysisId = analysis.data.id;
    console.log(`Analysis complete: ${analysisId}`);

    // 2. Get SSG recommendation
    const recommendation = await recommendSSG({
      analysisId: analysisId,
      userId: "developer123",
    });

    const ssg = recommendation.data.recommended;
    console.log(`Recommended SSG: ${ssg}`);

    // 3. Set up structure
    const structure = await setupStructure({
      path: "./docs",
      ssg: ssg,
      includeExamples: true,
    });

    console.log(
      `Structure created: ${structure.data.directoriesCreated.length} directories`,
    );

    // 4. Generate configuration
    const config = await generateConfig({
      ssg: ssg,
      projectName: "My Project",
      outputPath: "./docs",
    });

    console.log(
      `Configuration generated: ${config.data.filesCreated.length} files`,
    );

    // 5. Populate content
    const content = await handlePopulateDiataxisContent({
      analysisId: analysisId,
      docsPath: "./docs",
      populationLevel: "comprehensive",
    });

    console.log(
      `Content populated: ${content.data.contentGenerated.length} files`,
    );

    // 6. Deploy to GitHub Pages
    const deployment = await handleDeployPages({
      repository: "user/repository",
      ssg: ssg,
    });

    console.log(`Deployed to: ${deployment.data.url}`);

    return {
      analysisId,
      ssg,
      deploymentUrl: deployment.data.url,
    };
  } catch (error) {
    console.error("Workflow failed:", error);
    throw error;
  }
}

// Usage
completeDocumentationWorkflow("/path/to/project")
  .then((result) => {
    console.log("Workflow completed successfully:", result);
  })
  .catch((error) => {
    console.error("Workflow failed:", error);
  });
```

### Batch Processing Example

```typescript
// Process multiple repositories
async function batchProcessRepositories(repositories: string[]) {
  const results = [];

  for (const repoPath of repositories) {
    try {
      console.log(`Processing: ${repoPath}`);

      const analysis = await analyzeRepository({
        path: repoPath,
        depth: "quick",
      });

      const recommendation = await recommendSSG({
        analysisId: analysis.data.id,
      });

      results.push({
        path: repoPath,
        analysisId: analysis.data.id,
        recommendedSSG: recommendation.data.recommended,
        confidence: recommendation.data.confidence,
      });
    } catch (error) {
      console.error(`Failed to process ${repoPath}:`, error);
      results.push({
        path: repoPath,
        error: error.message,
      });
    }
  }

  return results;
}

// Usage
const repositories = [
  "/path/to/project1",
  "/path/to/project2",
  "/path/to/project3",
];

batchProcessRepositories(repositories).then((results) => {
  console.log("Batch processing complete:", results);
});
```

## 🎯 Error Handling Examples

### Comprehensive Error Handling

```typescript
async function robustAnalysis(projectPath: string) {
  try {
    const analysis = await analyzeRepository({
      path: projectPath,
      depth: "standard",
    });

    if (analysis.success) {
      return analysis.data;
    } else {
      throw new Error(analysis.error.message);
    }
  } catch (error) {
    if (error.code === "EACCES") {
      console.error("Permission denied. Check file permissions.");
    } else if (error.code === "ENOENT") {
      console.error("Directory not found. Check the path.");
    } else if (error.message.includes("analysis failed")) {
      console.error("Analysis failed. Check repository structure.");
    } else {
      console.error("Unexpected error:", error);
    }

    throw error;
  }
}
```

### Retry Logic Example

```typescript
async function retryAnalysis(projectPath: string, maxRetries: number = 3) {
  let lastError;

  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      console.log(`Attempt ${attempt} of ${maxRetries}`);

      const analysis = await analyzeRepository({
        path: projectPath,
        depth: "standard",
      });

      return analysis.data;
    } catch (error) {
      lastError = error;
      console.log(`Attempt ${attempt} failed:`, error.message);

      if (attempt < maxRetries) {
        const delay = Math.pow(2, attempt) * 1000; // Exponential backoff
        console.log(`Retrying in ${delay}ms...`);
        await new Promise((resolve) => setTimeout(resolve, delay));
      }
    }
  }

  throw new Error(
    `Analysis failed after ${maxRetries} attempts: ${lastError.message}`,
  );
}
```

## 🔌 MCP Integration Examples

### Complete MCP Workflow

```typescript
// Real-world example: Complete documentation deployment via MCP
import { analyzeRepository } from "./dist/tools/analyze-repository.js";
import { recommendSSG } from "./dist/tools/recommend-ssg.js";
import { generateConfig } from "./dist/tools/generate-config.js";
import { setupStructure } from "./dist/tools/setup-structure.js";
import { deployPages } from "./dist/tools/deploy-pages.js";

async function completeMCPWorkflow(projectPath: string, githubRepo: string) {
  console.log("🔍 Starting DocuMCP workflow...");

  // Step 1: Analyze repository
  const analysis = await analyzeRepository({
    path: projectPath,
    depth: "comprehensive",
  });

  console.log(
    `📊 Analysis complete: ${analysis.data.structure.totalFiles} files analyzed`,
  );
  console.log(`🏗️ Project type: ${analysis.data.recommendations.projectType}`);
  console.log(
    `💻 Primary language: ${analysis.data.recommendations.primaryLanguage}`,
  );

  // Step 2: Get SSG recommendation
  const ssgRecommendation = await recommendSSG({
    analysisId: analysis.id,
    preferences: {
      ecosystem: "javascript",
      priority: "features",
    },
  });

  console.log(`🎯 Recommended SSG: ${ssgRecommendation.data.recommended}`);
  console.log(
    `✅ Confidence: ${Math.round(ssgRecommendation.data.confidence * 100)}%`,
  );

  // Step 3: Generate configuration
  const config = await generateConfig({
    ssg: ssgRecommendation.data.recommended,
    projectName: analysis.data.structure.projectName,
    outputPath: "./docs",
  });

  console.log(
    `⚙️ Configuration generated: ${config.data.filesGenerated.length} files`,
  );

  // Step 4: Setup Diataxis structure
  const structure = await setupStructure({
    path: "./docs",
    ssg: ssgRecommendation.data.recommended,
    includeExamples: true,
  });

  console.log(
    `📁 Structure created: ${structure.data.directoriesCreated.length} directories`,
  );
  console.log(`📄 Files created: ${structure.data.filesCreated.length} files`);

  // Step 5: Deploy to GitHub Pages
  const deployment = await deployPages({
    repository: githubRepo,
    ssg: ssgRecommendation.data.recommended,
    projectPath: projectPath,
  });

  console.log(`🚀 Deployment initiated: ${deployment.data.workflowUrl}`);
  console.log(`🌐 Site URL: ${deployment.data.siteUrl}`);

  return {
    analysis: analysis.data,
    recommendation: ssgRecommendation.data,
    deployment: deployment.data,
  };
}

// Usage
completeMCPWorkflow("/path/to/your/project", "username/repository-name")
  .then((result) => {
    console.log("🎉 DocuMCP workflow completed successfully!");
    console.log(`📊 Final result:`, result);
  })
  .catch((error) => {
    console.error("❌ Workflow failed:", error.message);
  });
```

### MCP Memory Integration

```typescript
// Example showing DocuMCP's memory system for learning user preferences
import { analyzeRepository } from "./dist/tools/analyze-repository.js";
import { recommendSSG } from "./dist/tools/recommend-ssg.js";

async function intelligentRecommendation(projectPath: string, userId: string) {
  // DocuMCP automatically learns from previous successful deployments
  const analysis = await analyzeRepository({
    path: projectPath,
    depth: "standard",
  });

  // Memory system provides personalized recommendations
  const recommendation = await recommendSSG({
    analysisId: analysis.id,
    userId: userId, // Memory system tracks user preferences
  });

  console.log(
    `🧠 Memory-enhanced recommendation: ${recommendation.data.recommended}`,
  );
  console.log(
    `📈 Based on ${
      recommendation.data.memoryInsights?.similarProjects || 0
    } similar projects`,
  );
  console.log(
    `🎯 Success rate: ${Math.round(
      (recommendation.data.memoryInsights?.successRate || 0) * 100,
    )}%`,
  );

  return recommendation;
}
```

These examples demonstrate the comprehensive capabilities of DocuMCP and provide practical patterns for common use cases. Use them as starting points and adapt them to your specific needs.

```

--------------------------------------------------------------------------------
/src/tools/detect-gaps.ts:
--------------------------------------------------------------------------------

```typescript
import { z } from "zod";
import { promises as fs } from "fs";
import path from "path";
import { MCPToolResponse, formatMCPResponse } from "../types/api.js";
import { analyzeRepository } from "./analyze-repository.js";
import { handleValidateDiataxisContent } from "./validate-content.js";
import { CodeScanner, CodeAnalysisResult } from "../utils/code-scanner.js";

const inputSchema = z.object({
  repositoryPath: z.string().describe("Path to the repository to analyze"),
  documentationPath: z
    .string()
    .optional()
    .describe("Path to existing documentation (if any)"),
  analysisId: z
    .string()
    .optional()
    .describe("Optional existing analysis ID to reuse"),
  depth: z
    .enum(["quick", "standard", "comprehensive"])
    .optional()
    .default("standard"),
});

interface DocumentationGap {
  category: "tutorials" | "how-to" | "reference" | "explanation" | "general";
  gapType:
    | "missing_section"
    | "incomplete_content"
    | "outdated_info"
    | "missing_examples"
    | "poor_structure";
  description: string;
  priority: "critical" | "high" | "medium" | "low";
  recommendation: string;
  suggestedContent?: string;
  relatedFiles?: string[];
  estimatedEffort: "minimal" | "moderate" | "substantial";
}

interface GapAnalysisResult {
  repositoryPath: string;
  documentationPath?: string;
  analysisId: string;
  overallScore: number;
  gaps: DocumentationGap[];
  strengths: string[];
  recommendations: {
    immediate: string[];
    shortTerm: string[];
    longTerm: string[];
  };
  missingStructure: {
    directories: string[];
    files: string[];
  };
  contentCoverage: {
    tutorials: number;
    howTo: number;
    reference: number;
    explanation: number;
  };
}

export async function detectDocumentationGaps(
  args: unknown,
): Promise<{ content: any[] }> {
  const startTime = Date.now();
  const {
    repositoryPath,
    documentationPath,
    analysisId: existingAnalysisId,
    depth,
  } = inputSchema.parse(args);

  try {
    // Step 1: Get or perform repository analysis
    let analysisId = existingAnalysisId;
    let repositoryAnalysis: any;

    if (!analysisId) {
      const analysisResult = await analyzeRepository({
        path: repositoryPath,
        depth,
      });

      if (analysisResult.content && analysisResult.content[0]) {
        // The analyze_repository tool returns the analysis data directly as JSON text
        repositoryAnalysis = JSON.parse(analysisResult.content[0].text);

        // Check if the analysis was successful
        if (repositoryAnalysis.success === false) {
          throw new Error("Repository analysis failed");
        }

        analysisId = repositoryAnalysis.id; // Use the 'id' field from the analysis
      } else {
        throw new Error("Repository analysis failed - no content returned");
      }
    } else {
      // Try to retrieve existing analysis (simplified for this implementation)
      // In a full implementation, this would retrieve from persistent storage
    }

    // Step 2: Perform deep code analysis
    const codeScanner = new CodeScanner(repositoryPath);
    const codeAnalysis = await codeScanner.analyzeRepository();

    // Step 3: Analyze existing documentation structure
    const documentationAnalysis = await analyzeExistingDocumentation(
      documentationPath || path.join(repositoryPath, "docs"),
    );

    // Step 4: Perform content validation if documentation exists
    let validationResult: any = null;
    if (documentationAnalysis.exists && documentationPath) {
      try {
        const validation = await handleValidateDiataxisContent({
          contentPath: documentationPath,
          analysisId: analysisId,
          validationType: "all",
          includeCodeValidation: true,
          confidence: "moderate",
        });

        if (
          validation &&
          (validation as any).content &&
          (validation as any).content[0]
        ) {
          const validationData = JSON.parse(
            (validation as any).content[0].text,
          );
          if (validationData.success) {
            validationResult = validationData.data;
          }
        }
      } catch (error) {
        // Validation errors are non-fatal - continue without validation data
        console.warn(
          "Content validation failed, continuing without validation data:",
          error,
        );
      }
    }

    // Step 5: Identify gaps based on project and code analysis
    const gaps = identifyDocumentationGaps(
      repositoryAnalysis,
      documentationAnalysis,
      validationResult,
      codeAnalysis,
    );

    // Step 6: Generate recommendations
    const recommendations = generateRecommendations(
      gaps,
      repositoryAnalysis,
      codeAnalysis,
    );

    // Step 7: Calculate coverage scores
    const contentCoverage = calculateContentCoverage(
      documentationAnalysis,
      gaps,
    );

    const gapAnalysis: GapAnalysisResult = {
      repositoryPath,
      documentationPath,
      analysisId: analysisId || "unknown",
      overallScore: calculateOverallScore(gaps, contentCoverage),
      gaps,
      strengths: identifyStrengths(documentationAnalysis, validationResult),
      recommendations,
      missingStructure: identifyMissingStructure(documentationAnalysis),
      contentCoverage,
    };

    const response: MCPToolResponse<typeof gapAnalysis> = {
      success: true,
      data: gapAnalysis,
      metadata: {
        toolVersion: "1.0.0",
        executionTime: Date.now() - startTime,
        timestamp: new Date().toISOString(),
      },
      recommendations: [
        {
          type:
            gapAnalysis.overallScore < 60
              ? "critical"
              : gapAnalysis.overallScore < 80
                ? "warning"
                : "info",
          title: "Documentation Gap Analysis Complete",
          description: `Found ${gaps.length} gaps. Overall documentation score: ${gapAnalysis.overallScore}%`,
        },
      ],
      nextSteps: recommendations.immediate.map((rec) => ({
        action: rec,
        toolRequired: getRecommendedTool(rec),
        description: rec,
        priority: "high" as const,
      })),
    };

    return formatMCPResponse(response);
  } catch (error) {
    const errorResponse: MCPToolResponse = {
      success: false,
      error: {
        code: "GAP_DETECTION_FAILED",
        message: `Failed to detect documentation gaps: ${error}`,
        resolution: "Ensure repository and documentation paths are accessible",
      },
      metadata: {
        toolVersion: "1.0.0",
        executionTime: Date.now() - startTime,
        timestamp: new Date().toISOString(),
      },
    };
    return formatMCPResponse(errorResponse);
  }
}

async function analyzeExistingDocumentation(docsPath: string) {
  try {
    const stats = await fs.stat(docsPath);
    if (!stats.isDirectory()) {
      return { exists: false, structure: {}, files: [] };
    }

    const structure = {
      tutorials: { exists: false, files: [] as string[] },
      "how-to": { exists: false, files: [] as string[] },
      reference: { exists: false, files: [] as string[] },
      explanation: { exists: false, files: [] as string[] },
    };

    const allFiles: string[] = [];

    // Check for Diataxis structure
    for (const [category] of Object.entries(structure)) {
      const categoryPath = path.join(docsPath, category);
      try {
        const categoryStats = await fs.stat(categoryPath);
        if (categoryStats.isDirectory()) {
          structure[category as keyof typeof structure].exists = true;
          const files = await fs.readdir(categoryPath);
          const mdFiles = files.filter(
            (f) => f.endsWith(".md") || f.endsWith(".mdx"),
          );
          structure[category as keyof typeof structure].files = mdFiles;
          allFiles.push(...mdFiles.map((f) => path.join(category, f)));
        }
      } catch {
        // Category doesn't exist
      }
    }

    // Also check root level files
    const rootFiles = await fs.readdir(docsPath);
    const rootMdFiles = rootFiles.filter(
      (f) => f.endsWith(".md") || f.endsWith(".mdx"),
    );
    allFiles.push(...rootMdFiles);

    return {
      exists: true,
      structure,
      files: allFiles,
      hasRootIndex:
        rootFiles.includes("index.md") || rootFiles.includes("README.md"),
    };
  } catch {
    return { exists: false, structure: {}, files: [] };
  }
}

function identifyDocumentationGaps(
  repoAnalysis: any,
  docsAnalysis: any,
  validationResult: any,
  codeAnalysis: CodeAnalysisResult,
): DocumentationGap[] {
  const gaps: DocumentationGap[] = [];

  // Check for missing Diataxis structure
  if (!docsAnalysis.exists) {
    gaps.push({
      category: "general",
      gapType: "missing_section",
      description: "No documentation directory found",
      priority: "critical",
      recommendation:
        "Create documentation structure using setup_structure tool",
      estimatedEffort: "moderate",
    });
    return gaps; // If no docs exist, return early
  }

  const diataxisCategories = [
    "tutorials",
    "how-to",
    "reference",
    "explanation",
  ];
  for (const category of diataxisCategories) {
    if (!docsAnalysis.structure[category]?.exists) {
      gaps.push({
        category: category as any,
        gapType: "missing_section",
        description: `Missing ${category} documentation section`,
        priority:
          category === "tutorials" || category === "reference"
            ? "high"
            : "medium",
        recommendation: `Create ${category} directory and add relevant content`,
        estimatedEffort: "moderate",
      });
    } else if (docsAnalysis.structure[category].files.length === 0) {
      gaps.push({
        category: category as any,
        gapType: "incomplete_content",
        description: `${category} section exists but has no content`,
        priority: "high",
        recommendation: `Add content to ${category} section using populate_diataxis_content tool`,
        estimatedEffort: "substantial",
      });
    }
  }

  // Code-based gaps using actual code analysis
  // Check for API documentation gaps based on actual endpoints found
  if (
    codeAnalysis.apiEndpoints.length > 0 &&
    !hasApiDocumentation(docsAnalysis)
  ) {
    gaps.push({
      category: "reference",
      gapType: "missing_section",
      description: `Found ${codeAnalysis.apiEndpoints.length} API endpoints but no API documentation`,
      priority: "critical",
      recommendation:
        "Create API reference documentation for discovered endpoints",
      estimatedEffort: "substantial",
      relatedFiles: [
        ...new Set(codeAnalysis.apiEndpoints.map((ep) => ep.filePath)),
      ],
    });
  }

  // Check for undocumented API endpoints
  const undocumentedEndpoints = codeAnalysis.apiEndpoints.filter(
    (ep) => !ep.hasDocumentation,
  );
  if (undocumentedEndpoints.length > 0) {
    gaps.push({
      category: "reference",
      gapType: "missing_examples",
      description: `${undocumentedEndpoints.length} API endpoints lack inline documentation`,
      priority: "high",
      recommendation: "Add JSDoc comments to API endpoint handlers",
      estimatedEffort: "moderate",
      relatedFiles: [
        ...new Set(undocumentedEndpoints.map((ep) => ep.filePath)),
      ],
    });
  }

  // Check for class/interface documentation
  const undocumentedClasses = codeAnalysis.classes.filter(
    (cls) => cls.exported && !cls.hasJSDoc,
  );
  if (undocumentedClasses.length > 0) {
    gaps.push({
      category: "reference",
      gapType: "incomplete_content",
      description: `${undocumentedClasses.length} exported classes lack documentation`,
      priority: "medium",
      recommendation:
        "Add JSDoc comments to exported classes and create API reference",
      estimatedEffort: "moderate",
      relatedFiles: [
        ...new Set(undocumentedClasses.map((cls) => cls.filePath)),
      ],
    });
  }

  // Check for interface documentation
  const undocumentedInterfaces = codeAnalysis.interfaces.filter(
    (iface) => iface.exported && !iface.hasJSDoc,
  );
  if (undocumentedInterfaces.length > 0) {
    gaps.push({
      category: "reference",
      gapType: "incomplete_content",
      description: `${undocumentedInterfaces.length} exported interfaces lack documentation`,
      priority: "medium",
      recommendation:
        "Add JSDoc comments to exported interfaces and create type documentation",
      estimatedEffort: "moderate",
      relatedFiles: [
        ...new Set(undocumentedInterfaces.map((iface) => iface.filePath)),
      ],
    });
  }

  // Check for function documentation
  const undocumentedFunctions = codeAnalysis.functions.filter(
    (func) => func.exported && !func.hasJSDoc,
  );
  if (undocumentedFunctions.length > 0) {
    gaps.push({
      category: "reference",
      gapType: "incomplete_content",
      description: `${undocumentedFunctions.length} exported functions lack documentation`,
      priority: "medium",
      recommendation:
        "Add JSDoc comments to exported functions and create API reference",
      estimatedEffort: "substantial",
      relatedFiles: [
        ...new Set(undocumentedFunctions.map((func) => func.filePath)),
      ],
    });
  }

  // Framework-specific documentation gaps
  if (
    codeAnalysis.frameworks.includes("React") &&
    !hasFrameworkDocumentation(docsAnalysis, "react")
  ) {
    gaps.push({
      category: "how-to",
      gapType: "missing_section",
      description:
        "React framework detected but no React-specific documentation found",
      priority: "medium",
      recommendation: "Create React component usage and development guides",
      estimatedEffort: "moderate",
    });
  }

  if (
    codeAnalysis.frameworks.includes("Express") &&
    !hasFrameworkDocumentation(docsAnalysis, "express")
  ) {
    gaps.push({
      category: "how-to",
      gapType: "missing_section",
      description:
        "Express framework detected but no Express-specific documentation found",
      priority: "medium",
      recommendation: "Create Express server setup and API development guides",
      estimatedEffort: "moderate",
    });
  }

  // Test documentation gaps
  if (codeAnalysis.hasTests && !hasTestingDocumentation(docsAnalysis)) {
    gaps.push({
      category: "how-to",
      gapType: "missing_section",
      description: "Test files found but no testing documentation",
      priority: "medium",
      recommendation: "Create testing setup and contribution guides",
      estimatedEffort: "moderate",
      relatedFiles: codeAnalysis.testFiles,
    });
  }

  // Technology-specific gaps based on repository analysis (fallback)
  if (repoAnalysis) {
    // Check for setup/installation guides
    if (repoAnalysis.packageManager && !hasInstallationGuide(docsAnalysis)) {
      gaps.push({
        category: "tutorials",
        gapType: "missing_section",
        description: "Package manager detected but no installation guide found",
        priority: "high",
        recommendation: "Create installation and setup tutorial",
        estimatedEffort: "moderate",
      });
    }

    // Check for Docker documentation
    if (repoAnalysis.hasDocker && !hasDockerDocumentation(docsAnalysis)) {
      gaps.push({
        category: "how-to",
        gapType: "missing_section",
        description: "Docker configuration found but no Docker documentation",
        priority: "medium",
        recommendation: "Add Docker deployment and development guides",
        estimatedEffort: "moderate",
      });
    }

    // Check for CI/CD documentation
    if (repoAnalysis.hasCICD && !hasCICDDocumentation(docsAnalysis)) {
      gaps.push({
        category: "explanation",
        gapType: "missing_section",
        description: "CI/CD configuration found but no related documentation",
        priority: "medium",
        recommendation: "Document CI/CD processes and deployment workflows",
        estimatedEffort: "moderate",
      });
    }
  }

  // Add validation-based gaps
  if (validationResult?.validationResults) {
    for (const result of validationResult.validationResults) {
      if (result.status === "fail") {
        gaps.push({
          category: "general",
          gapType: "poor_structure",
          description: result.message,
          priority: "medium",
          recommendation: result.recommendation || "Fix validation issue",
          estimatedEffort: "minimal",
        });
      }
    }
  }

  return gaps;
}

function hasApiDocumentation(docsAnalysis: any): boolean {
  const allFiles = docsAnalysis.files || [];
  return allFiles.some(
    (file: string) =>
      file.toLowerCase().includes("api") ||
      file.toLowerCase().includes("endpoint") ||
      file.toLowerCase().includes("swagger") ||
      file.toLowerCase().includes("openapi"),
  );
}

function hasInstallationGuide(docsAnalysis: any): boolean {
  const allFiles = docsAnalysis.files || [];
  return allFiles.some(
    (file: string) =>
      file.toLowerCase().includes("install") ||
      file.toLowerCase().includes("setup") ||
      file.toLowerCase().includes("getting-started") ||
      file.toLowerCase().includes("quickstart"),
  );
}

function hasDockerDocumentation(docsAnalysis: any): boolean {
  const allFiles = docsAnalysis.files || [];
  return allFiles.some(
    (file: string) =>
      file.toLowerCase().includes("docker") ||
      file.toLowerCase().includes("container") ||
      file.toLowerCase().includes("compose"),
  );
}

function hasCICDDocumentation(docsAnalysis: any): boolean {
  const allFiles = docsAnalysis.files || [];
  return allFiles.some(
    (file: string) =>
      file.toLowerCase().includes("ci") ||
      file.toLowerCase().includes("cd") ||
      file.toLowerCase().includes("deploy") ||
      file.toLowerCase().includes("workflow") ||
      file.toLowerCase().includes("pipeline"),
  );
}

function hasFrameworkDocumentation(
  docsAnalysis: any,
  framework: string,
): boolean {
  const allFiles = docsAnalysis.files || [];
  return allFiles.some(
    (file: string) =>
      file.toLowerCase().includes(framework.toLowerCase()) ||
      file.toLowerCase().includes(`${framework.toLowerCase()}-guide`) ||
      file.toLowerCase().includes(`${framework.toLowerCase()}-setup`),
  );
}

function hasTestingDocumentation(docsAnalysis: any): boolean {
  const allFiles = docsAnalysis.files || [];
  return allFiles.some(
    (file: string) =>
      file.toLowerCase().includes("test") ||
      file.toLowerCase().includes("testing") ||
      file.toLowerCase().includes("jest") ||
      file.toLowerCase().includes("spec") ||
      file.toLowerCase().includes("unit-test") ||
      file.toLowerCase().includes("integration-test"),
  );
}

function generateRecommendations(
  gaps: DocumentationGap[],
  _repoAnalysis: any,
  codeAnalysis: CodeAnalysisResult,
) {
  const immediate: string[] = [];
  const shortTerm: string[] = [];
  const longTerm: string[] = [];

  const criticalGaps = gaps.filter((g) => g.priority === "critical");
  const highGaps = gaps.filter((g) => g.priority === "high");
  const mediumGaps = gaps.filter((g) => g.priority === "medium");

  // Immediate (Critical gaps)
  criticalGaps.forEach((gap) => {
    immediate.push(gap.recommendation);
  });

  // Short-term (High priority gaps)
  highGaps.forEach((gap) => {
    shortTerm.push(gap.recommendation);
  });

  // Long-term (Medium/Low priority gaps)
  mediumGaps.forEach((gap) => {
    longTerm.push(gap.recommendation);
  });

  // Add code-analysis-based recommendations
  if (codeAnalysis.apiEndpoints.length > 0) {
    longTerm.push(
      `Consider generating OpenAPI/Swagger documentation for ${codeAnalysis.apiEndpoints.length} API endpoints`,
    );
  }

  if (
    codeAnalysis.functions.length +
      codeAnalysis.classes.length +
      codeAnalysis.interfaces.length >
    50
  ) {
    longTerm.push(
      "Consider using automated documentation tools like TypeDoc for large codebases",
    );
  }

  // Add general recommendations
  if (immediate.length === 0 && shortTerm.length === 0) {
    immediate.push(
      "Documentation structure looks good - consider content enhancement",
    );
  }

  return { immediate, shortTerm, longTerm };
}

function calculateContentCoverage(docsAnalysis: any, gaps: DocumentationGap[]) {
  const categories = ["tutorials", "howTo", "reference", "explanation"];
  const coverage: any = {};

  categories.forEach((category) => {
    const categoryKey = category === "howTo" ? "how-to" : category;
    const hasContent =
      docsAnalysis.structure?.[categoryKey]?.exists &&
      docsAnalysis.structure[categoryKey].files.length > 0;
    const hasGaps = gaps.some((g) => g.category === categoryKey);

    if (hasContent && !hasGaps) {
      coverage[category] = 100;
    } else if (hasContent && hasGaps) {
      coverage[category] = 60;
    } else {
      coverage[category] = 0;
    }
  });

  return coverage;
}

function calculateOverallScore(
  gaps: DocumentationGap[],
  contentCoverage: any,
): number {
  const coverageScore =
    Object.values(contentCoverage).reduce(
      (acc: number, val: any) => acc + val,
      0,
    ) / 4;
  const gapPenalty = gaps.length * 5; // Each gap reduces score by 5
  const criticalPenalty =
    gaps.filter((g) => g.priority === "critical").length * 15; // Critical gaps have higher penalty

  return Math.max(
    0,
    Math.min(100, coverageScore - gapPenalty - criticalPenalty),
  );
}

function identifyStrengths(docsAnalysis: any, validationResult: any): string[] {
  const strengths: string[] = [];

  if (docsAnalysis.hasRootIndex) {
    strengths.push("Has main documentation index file");
  }

  const existingSections = Object.entries(docsAnalysis.structure || {})
    .filter(([_, data]: [string, any]) => data.exists && data.files.length > 0)
    .map(([section]) => section);

  if (existingSections.length > 0) {
    strengths.push(`Well-organized sections: ${existingSections.join(", ")}`);
  }

  if (validationResult?.overallScore > 80) {
    strengths.push("High-quality existing content");
  }

  return strengths;
}

function identifyMissingStructure(docsAnalysis: any) {
  const missingDirectories: string[] = [];
  const missingFiles: string[] = [];

  const expectedDirectories = [
    "tutorials",
    "how-to",
    "reference",
    "explanation",
  ];
  expectedDirectories.forEach((dir) => {
    if (!docsAnalysis.structure?.[dir]?.exists) {
      missingDirectories.push(dir);
    }
  });

  if (!docsAnalysis.hasRootIndex) {
    missingFiles.push("index.md");
  }

  return { directories: missingDirectories, files: missingFiles };
}

function getRecommendedTool(recommendation: string): string {
  if (recommendation.includes("setup_structure")) return "setup_structure";
  if (recommendation.includes("populate_diataxis_content"))
    return "populate_diataxis_content";
  if (recommendation.includes("validate_diataxis_content"))
    return "validate_diataxis_content";
  if (recommendation.includes("generate_config")) return "generate_config";
  if (recommendation.includes("deploy_pages")) return "deploy_pages";
  return "manual";
}

```

--------------------------------------------------------------------------------
/tests/benchmarks/performance.test.ts:
--------------------------------------------------------------------------------

```typescript
import { PerformanceBenchmarker } from "../../src/benchmarks/performance";
import * as fs from "fs/promises";
import * as path from "path";
import * as os from "os";

describe("Performance Benchmarking System", () => {
  let benchmarker: PerformanceBenchmarker;
  let tempDir: string;

  beforeEach(async () => {
    benchmarker = new PerformanceBenchmarker();
    tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "perf-test-"));
  });

  afterEach(async () => {
    try {
      await fs.rm(tempDir, { recursive: true, force: true });
    } catch (error) {
      // Ignore cleanup errors
    }
  });

  // Helper function to create test repositories
  async function createTestRepo(
    name: string,
    fileCount: number,
  ): Promise<string> {
    const repoPath = path.join(tempDir, name);
    await fs.mkdir(repoPath, { recursive: true });

    // Create package.json to make it look like a real project
    await fs.writeFile(
      path.join(repoPath, "package.json"),
      JSON.stringify({ name, version: "1.0.0" }, null, 2),
    );

    // Create additional files to reach the target count
    for (let i = 1; i < fileCount; i++) {
      const fileName = `file${i}.js`;
      await fs.writeFile(
        path.join(repoPath, fileName),
        `// Test file ${i}\nconsole.log('Hello from file ${i}');\n`,
      );
    }

    return repoPath;
  }

  describe("Repository Size Categorization", () => {
    it("should categorize small repositories correctly", async () => {
      const smallRepoPath = await createTestRepo("small-repo", 25);
      const result = await benchmarker.benchmarkRepository(smallRepoPath);

      expect(result.repoSize).toBe("small");
      expect(result.fileCount).toBe(25);
    });

    it("should categorize medium repositories correctly", async () => {
      const mediumRepoPath = await createTestRepo("medium-repo", 250);
      const result = await benchmarker.benchmarkRepository(mediumRepoPath);

      expect(result.repoSize).toBe("medium");
      expect(result.fileCount).toBe(250);
    });

    it("should categorize large repositories correctly", async () => {
      const largeRepoPath = await createTestRepo("large-repo", 1200);
      const result = await benchmarker.benchmarkRepository(largeRepoPath);

      expect(result.repoSize).toBe("large");
      expect(result.fileCount).toBe(1200);
    });
  });

  describe("Performance Measurement", () => {
    it("should measure execution time accurately", async () => {
      const testRepoPath = await createTestRepo("timing-test", 10);
      const result = await benchmarker.benchmarkRepository(testRepoPath);

      expect(result.executionTime).toBeGreaterThanOrEqual(0);
      expect(typeof result.executionTime).toBe("number");
    });

    it("should calculate performance ratios correctly", async () => {
      const testRepoPath = await createTestRepo("ratio-test", 50);
      const result = await benchmarker.benchmarkRepository(testRepoPath);

      expect(result.performanceRatio).toBeGreaterThanOrEqual(0);
      expect(result.performanceRatio).toBeLessThanOrEqual(100);
    });

    it("should track memory usage", async () => {
      const testRepoPath = await createTestRepo("memory-test", 30);
      const result = await benchmarker.benchmarkRepository(testRepoPath);

      expect(result.details.memoryUsage).toBeDefined();
      // Memory delta can be negative due to GC, just verify it's tracked
      expect(typeof result.details.memoryUsage.heapUsed).toBe("number");
      expect(result.details.memoryUsage.rss).toBeDefined();
      expect(result.details.memoryUsage.heapTotal).toBeDefined();
    });
  });

  describe("PERF-001 Compliance", () => {
    it("should pass for small repositories under 1 second", async () => {
      const testRepoPath = await createTestRepo("perf-test", 10);
      const result = await benchmarker.benchmarkRepository(testRepoPath);

      expect(result.passed).toBe(true);
      expect(result.executionTime).toBeLessThan(1000);
    });

    it("should have correct performance targets", async () => {
      const smallRepo = await createTestRepo("small-perf", 50);
      const mediumRepo = await createTestRepo("medium-perf", 500);
      const largeRepo = await createTestRepo("large-perf", 1500);

      const smallResult = await benchmarker.benchmarkRepository(smallRepo);
      const mediumResult = await benchmarker.benchmarkRepository(mediumRepo);
      const largeResult = await benchmarker.benchmarkRepository(largeRepo);

      expect(smallResult.targetTime).toBe(1000); // 1 second for small
      expect(mediumResult.targetTime).toBe(10000); // 10 seconds for medium
      expect(largeResult.targetTime).toBe(60000); // 60 seconds for large
    });
  });

  describe("Benchmark Suite", () => {
    it("should run multiple repository benchmarks", async () => {
      const testRepos = [
        {
          path: await createTestRepo("suite-test-1", 25),
          name: "Suite Test 1",
        },
        {
          path: await createTestRepo("suite-test-2", 75),
          name: "Suite Test 2",
        },
      ];

      const suite = await benchmarker.runBenchmarkSuite(testRepos);

      expect(suite.results.length).toBe(2);
      expect(suite.testName).toBeDefined();
      expect(suite.overallPassed).toBeDefined();
    });

    it("should generate accurate summaries", async () => {
      const testRepos = [
        { path: await createTestRepo("small-repo", 25), name: "Small Repo" },
        { path: await createTestRepo("medium-repo", 250), name: "Medium Repo" },
      ];

      const suite = await benchmarker.runBenchmarkSuite(testRepos);

      expect(suite.summary).toBeDefined();
      const totalRepos =
        suite.summary.smallRepos.count +
        suite.summary.mediumRepos.count +
        suite.summary.largeRepos.count;
      expect(totalRepos).toBe(2);
      const totalPassed =
        suite.summary.smallRepos.passed +
        suite.summary.mediumRepos.passed +
        suite.summary.largeRepos.passed;
      expect(totalPassed).toBeGreaterThanOrEqual(0);
    });
  });

  describe("Result Export", () => {
    it("should export benchmark results to JSON", async () => {
      const testRepos = [
        { path: await createTestRepo("export-test", 20), name: "Export Test" },
      ];

      const suite = await benchmarker.runBenchmarkSuite(testRepos);
      const exportPath = path.join(tempDir, "benchmark-results.json");

      await benchmarker.exportResults(suite, exportPath);

      const exportedContent = await fs.readFile(exportPath, "utf-8");
      const exportedData = JSON.parse(exportedContent);

      expect(exportedData.suite).toBeDefined();
      expect(exportedData.systemInfo).toBeDefined();
      expect(exportedData.performanceTargets).toBeDefined();
      expect(exportedData.timestamp).toBeDefined();
    });
  });

  describe("Error Handling", () => {
    it("should handle non-existent repository paths gracefully", async () => {
      const nonExistentPath = path.join(tempDir, "does-not-exist");

      const result = await benchmarker.benchmarkRepository(nonExistentPath);

      // Should handle gracefully with 0 files
      expect(result.fileCount).toBe(0);
      expect(result.repoSize).toBe("small");
      expect(result.executionTime).toBeGreaterThanOrEqual(0);
      expect(result.passed).toBe(true); // Fast execution passes performance target
    });

    it("should handle permission denied scenarios gracefully", async () => {
      if (process.platform === "win32") {
        // Skip on Windows as permission handling is different
        return;
      }

      const restrictedPath = path.join(tempDir, "restricted");
      await fs.mkdir(restrictedPath, { recursive: true });

      try {
        await fs.chmod(restrictedPath, 0o000);

        const result = await benchmarker.benchmarkRepository(restrictedPath);

        // Should handle gracefully with 0 files
        expect(result.fileCount).toBe(0);
        expect(result.repoSize).toBe("small");
        expect(result.executionTime).toBeGreaterThanOrEqual(0);
      } finally {
        // Restore permissions for cleanup
        await fs.chmod(restrictedPath, 0o755);
      }
    });

    it("should handle empty repositories", async () => {
      const emptyRepoPath = path.join(tempDir, "empty-repo");
      await fs.mkdir(emptyRepoPath, { recursive: true });

      const result = await benchmarker.benchmarkRepository(emptyRepoPath);

      expect(result.fileCount).toBe(0);
      expect(result.repoSize).toBe("small");
      expect(result.executionTime).toBeGreaterThanOrEqual(0);
    });

    it("should handle suite with all valid repositories", async () => {
      const validRepo1 = await createTestRepo("valid-repo-1", 10);
      const validRepo2 = await createTestRepo("valid-repo-2", 20);

      const testRepos = [
        { path: validRepo1, name: "Valid Repo 1" },
        { path: validRepo2, name: "Valid Repo 2" },
      ];

      const suite = await benchmarker.runBenchmarkSuite(testRepos);

      expect(suite.results.length).toBe(2);
      expect(suite.overallPassed).toBeDefined();
      expect(typeof suite.averagePerformance).toBe("number");
    });

    it("should handle benchmark execution errors in try-catch", async () => {
      // Test the error handling path by mocking analyzeRepository to throw
      const originalAnalyze =
        require("../../src/tools/analyze-repository").analyzeRepository;
      const mockAnalyze = jest.fn().mockRejectedValue(new Error("Mock error"));

      // Replace the function temporarily
      require("../../src/tools/analyze-repository").analyzeRepository =
        mockAnalyze;

      try {
        const testRepoPath = await createTestRepo("error-test", 10);

        await expect(
          benchmarker.benchmarkRepository(testRepoPath),
        ).rejects.toThrow("Mock error");

        // Should still record the failed benchmark
        const results = benchmarker.getResults();
        expect(results.length).toBe(1);
        expect(results[0].passed).toBe(false);
      } finally {
        // Restore original function
        require("../../src/tools/analyze-repository").analyzeRepository =
          originalAnalyze;
      }
    });
  });

  describe("Utility Methods", () => {
    it("should reset benchmark results", async () => {
      const testRepoPath = await createTestRepo("reset-test", 10);
      await benchmarker.benchmarkRepository(testRepoPath);

      expect(benchmarker.getResults().length).toBe(1);

      benchmarker.reset();

      expect(benchmarker.getResults().length).toBe(0);
    });

    it("should return copy of results array", async () => {
      const testRepoPath = await createTestRepo("copy-test", 15);
      await benchmarker.benchmarkRepository(testRepoPath);

      const results1 = benchmarker.getResults();
      const results2 = benchmarker.getResults();

      expect(results1).toEqual(results2);
      expect(results1).not.toBe(results2); // Different array instances
    });

    it("should handle different analysis depths", async () => {
      const testRepoPath = await createTestRepo("depth-test", 20);

      // Test with quick analysis
      const quickResult = await benchmarker.benchmarkRepository(
        testRepoPath,
        "quick",
      );
      expect(quickResult.executionTime).toBeGreaterThanOrEqual(0);

      // Test with deep analysis
      const deepResult = await benchmarker.benchmarkRepository(
        testRepoPath,
        "deep",
      );
      expect(deepResult.executionTime).toBeGreaterThanOrEqual(0);
    });
  });

  describe("Report Generation", () => {
    it("should generate detailed reports without errors", async () => {
      const testRepos = [
        await createTestRepo("report-small", 25),
        await createTestRepo("report-medium", 250),
        await createTestRepo("report-large", 1200),
      ];

      const results: any[] = [];
      for (const repoPath of testRepos) {
        const result = await benchmarker.benchmarkRepository(repoPath);
        results.push(result);
      }

      const suite = benchmarker.generateSuite("Report Test", results);

      // Capture console output
      const originalLog = console.log;
      const logOutput: string[] = [];
      console.log = (...args) => {
        logOutput.push(args.join(" "));
      };

      try {
        benchmarker.printDetailedReport(suite);

        expect(logOutput.length).toBeGreaterThan(0);
        expect(
          logOutput.some((line) =>
            line.includes("Performance Benchmark Report"),
          ),
        ).toBe(true);
      } finally {
        console.log = originalLog;
      }
    });

    it("should handle empty suite reports", async () => {
      const emptySuite = benchmarker.generateSuite("Empty Suite", []);

      // Should not throw when generating report for empty suite
      expect(() => benchmarker.printDetailedReport(emptySuite)).not.toThrow();
    });

    it("should calculate correct averages for mixed results", async () => {
      const repo1 = await createTestRepo("avg-test-1", 10);
      const repo2 = await createTestRepo("avg-test-2", 20);
      const repo3 = await createTestRepo("avg-test-3", 30);

      const results = [
        await benchmarker.benchmarkRepository(repo1),
        await benchmarker.benchmarkRepository(repo2),
        await benchmarker.benchmarkRepository(repo3),
      ];

      const suite = benchmarker.generateSuite("Average Test", results);

      expect(suite.averagePerformance).toBeGreaterThanOrEqual(0);
      expect(suite.averagePerformance).toBeLessThanOrEqual(100);
      expect(typeof suite.averagePerformance).toBe("number");
    });
  });

  describe("Memory Usage Tracking", () => {
    it("should track memory usage differences", async () => {
      const testRepoPath = await createTestRepo("memory-tracking", 100);
      const result = await benchmarker.benchmarkRepository(testRepoPath);

      expect(result.details.memoryUsage).toBeDefined();
      // Memory differences can be negative due to garbage collection
      expect(typeof result.details.memoryUsage.heapUsed).toBe("number");
      expect(typeof result.details.memoryUsage.heapTotal).toBe("number");
      expect(typeof result.details.memoryUsage.rss).toBe("number");
    });

    it("should handle memory tracking in error scenarios", async () => {
      const emptyRepoPath = path.join(tempDir, "empty-memory-test");
      await fs.mkdir(emptyRepoPath, { recursive: true });

      const result = await benchmarker.benchmarkRepository(emptyRepoPath);

      // Even in error scenarios, memory tracking should work
      expect(result.details.memoryUsage).toBeDefined();
      expect(typeof result.details.memoryUsage.heapUsed).toBe("number");
    });
  });

  describe("Edge Cases", () => {
    it("should handle repositories with special characters in paths", async () => {
      const specialCharRepo = path.join(tempDir, "repo with spaces & symbols!");
      await fs.mkdir(specialCharRepo, { recursive: true });
      await fs.writeFile(
        path.join(specialCharRepo, "test.js"),
        'console.log("test");',
      );

      const result = await benchmarker.benchmarkRepository(specialCharRepo);

      expect(result.fileCount).toBe(1);
      expect(result.executionTime).toBeGreaterThanOrEqual(0);
    });

    it("should handle very deep directory structures", async () => {
      const deepRepoPath = path.join(tempDir, "deep-repo");
      let currentPath = deepRepoPath;

      // Create a deep directory structure
      for (let i = 0; i < 10; i++) {
        currentPath = path.join(currentPath, `level-${i}`);
        await fs.mkdir(currentPath, { recursive: true });
        await fs.writeFile(
          path.join(currentPath, `file-${i}.js`),
          `// Level ${i}`,
        );
      }

      const result = await benchmarker.benchmarkRepository(deepRepoPath);

      expect(result.fileCount).toBe(10);
      expect(result.executionTime).toBeGreaterThanOrEqual(0);
    });

    it("should handle concurrent benchmarking", async () => {
      const repo1 = await createTestRepo("concurrent-1", 15);
      const repo2 = await createTestRepo("concurrent-2", 25);
      const repo3 = await createTestRepo("concurrent-3", 35);

      // Run benchmarks concurrently
      const promises = [
        benchmarker.benchmarkRepository(repo1),
        benchmarker.benchmarkRepository(repo2),
        benchmarker.benchmarkRepository(repo3),
      ];

      const results = await Promise.all(promises);

      expect(results.length).toBe(3);
      results.forEach((result) => {
        expect(result.executionTime).toBeGreaterThanOrEqual(0);
        expect(result.fileCount).toBeGreaterThan(0);
      });
    });

    it("should handle extremely deep recursion limit", async () => {
      const deepRepoPath = path.join(tempDir, "extremely-deep");
      let currentPath = deepRepoPath;

      // Create a structure deeper than the 10-level limit
      for (let i = 0; i < 15; i++) {
        currentPath = path.join(currentPath, `level-${i}`);
        await fs.mkdir(currentPath, { recursive: true });
        await fs.writeFile(
          path.join(currentPath, `file-${i}.js`),
          `// Level ${i}`,
        );
      }

      const result = await benchmarker.benchmarkRepository(deepRepoPath);

      // Should stop at recursion limit, so fewer than 15 files
      expect(result.fileCount).toBeLessThanOrEqual(10);
      expect(result.executionTime).toBeGreaterThanOrEqual(0);
    });

    it("should skip node_modules and vendor directories", async () => {
      const repoPath = await createTestRepo("skip-dirs", 5);

      // Add node_modules and vendor directories
      const nodeModulesPath = path.join(repoPath, "node_modules");
      const vendorPath = path.join(repoPath, "vendor");

      await fs.mkdir(nodeModulesPath, { recursive: true });
      await fs.mkdir(vendorPath, { recursive: true });

      // Add files that should be skipped
      await fs.writeFile(
        path.join(nodeModulesPath, "package.js"),
        "module.exports = {};",
      );
      await fs.writeFile(path.join(vendorPath, "library.js"), "var lib = {};");

      const result = await benchmarker.benchmarkRepository(repoPath);

      // Should only count the original 5 files, not the ones in node_modules/vendor
      expect(result.fileCount).toBe(5);
    });

    it("should skip hidden files except .github", async () => {
      const repoPath = await createTestRepo("hidden-files", 3);

      // Add hidden files and .github directory
      await fs.writeFile(path.join(repoPath, ".hidden"), "hidden content");
      await fs.writeFile(path.join(repoPath, ".env"), "SECRET=value");

      const githubPath = path.join(repoPath, ".github");
      await fs.mkdir(githubPath, { recursive: true });
      await fs.writeFile(path.join(githubPath, "workflow.yml"), "name: CI");

      const result = await benchmarker.benchmarkRepository(repoPath);

      // Should count original 3 files + 1 .github file, but not other hidden files
      expect(result.fileCount).toBe(4);
    });
  });

  describe("Factory Function", () => {
    it("should create benchmarker instance via factory", () => {
      const { createBenchmarker } = require("../../src/benchmarks/performance");
      const factoryBenchmarker = createBenchmarker();

      expect(factoryBenchmarker).toBeInstanceOf(PerformanceBenchmarker);
      expect(factoryBenchmarker.getResults()).toEqual([]);
    });
  });

  describe("Export Results Error Handling", () => {
    it("should handle export to invalid path gracefully", async () => {
      const testRepos = [
        {
          path: await createTestRepo("export-error-test", 10),
          name: "Export Error Test",
        },
      ];

      const suite = await benchmarker.runBenchmarkSuite(testRepos);
      const invalidPath = path.join(
        "/invalid/nonexistent/path",
        "results.json",
      );

      await expect(
        benchmarker.exportResults(suite, invalidPath),
      ).rejects.toThrow();
    });

    it("should export complete system information", async () => {
      const testRepos = [
        {
          path: await createTestRepo("system-info-test", 5),
          name: "System Info Test",
        },
      ];

      const suite = await benchmarker.runBenchmarkSuite(testRepos);
      const exportPath = path.join(tempDir, "system-info-results.json");

      await benchmarker.exportResults(suite, exportPath);

      const exportedContent = await fs.readFile(exportPath, "utf-8");
      const exportedData = JSON.parse(exportedContent);

      expect(exportedData.systemInfo.node).toBe(process.version);
      expect(exportedData.systemInfo.platform).toBe(process.platform);
      expect(exportedData.systemInfo.arch).toBe(process.arch);
      expect(exportedData.systemInfo.memoryUsage).toBeDefined();
      expect(exportedData.performanceTargets).toEqual({
        small: 1000,
        medium: 10000,
        large: 60000,
      });
    });
  });

  describe("Detailed Report Coverage", () => {
    it("should print detailed reports with all categories", async () => {
      // Create repos of all sizes to test all report sections
      const smallRepo = await createTestRepo("report-small", 25);
      const mediumRepo = await createTestRepo("report-medium", 250);
      const largeRepo = await createTestRepo("report-large", 1200);

      const results = [
        await benchmarker.benchmarkRepository(smallRepo),
        await benchmarker.benchmarkRepository(mediumRepo),
        await benchmarker.benchmarkRepository(largeRepo),
      ];

      const suite = benchmarker.generateSuite("Complete Report Test", results);

      // Capture console output
      const originalLog = console.log;
      const logOutput: string[] = [];
      console.log = (...args) => {
        logOutput.push(args.join(" "));
      };

      try {
        benchmarker.printDetailedReport(suite);

        // Verify all report sections are present
        const fullOutput = logOutput.join("\n");
        expect(fullOutput).toContain("Performance Benchmark Report");
        expect(fullOutput).toContain("Overall Status:");
        expect(fullOutput).toContain("Average Performance:");
        expect(fullOutput).toContain("Small (<100 files)");
        expect(fullOutput).toContain("Medium (100-1000 files)");
        expect(fullOutput).toContain("Large (1000+ files)");
        expect(fullOutput).toContain("Detailed Results:");
        expect(fullOutput).toContain("Memory:");
      } finally {
        console.log = originalLog;
      }
    });

    it("should handle report generation with no results in some categories", async () => {
      // Only create small repos to test empty category handling
      const results = [
        await benchmarker.benchmarkRepository(
          await createTestRepo("small-only-1", 10),
        ),
        await benchmarker.benchmarkRepository(
          await createTestRepo("small-only-2", 20),
        ),
      ];

      const suite = benchmarker.generateSuite("Small Only Test", results);

      const originalLog = console.log;
      const logOutput: string[] = [];
      console.log = (...args) => {
        logOutput.push(args.join(" "));
      };

      try {
        benchmarker.printDetailedReport(suite);

        const fullOutput = logOutput.join("\n");
        expect(fullOutput).toContain("Small (<100 files)");
        // Medium and Large categories should not appear since count is 0
        expect(fullOutput).not.toContain("Medium (100-1000 files):");
        expect(fullOutput).not.toContain("Large (1000+ files):");
      } finally {
        console.log = originalLog;
      }
    });
  });
});

```

--------------------------------------------------------------------------------
/docs/research/research-questions-2025-01-14.md:
--------------------------------------------------------------------------------

```markdown
---
documcp:
  last_updated: "2025-11-20T00:46:21.969Z"
  last_validated: "2025-11-20T00:46:21.969Z"
  auto_updated: false
  update_frequency: monthly
---

# DocuMCP Implementation Research Questions

**Generated**: January 14, 2025  
**Project**: DocuMCP - Intelligent MCP Server for GitHub Pages Documentation Deployment  
**Phase**: Pre-Implementation Research  
**Context**: Comprehensive validation of ADR decisions and implementation planning

---

## Research Overview

This document contains systematic research questions organized by architectural domain, based on the 6 ADRs established for DocuMCP. Each section includes priority ratings, validation criteria, and expected outcomes to guide effective pre-implementation research.

### Research Objectives

1. **Validate technical feasibility** of ADR decisions
2. **Identify implementation risks** and mitigation strategies
3. **Research best practices** for MCP server development
4. **Investigate SSG ecosystem** integration patterns
5. **Explore Diataxis framework** implementation approaches

### Research Constraints

- TypeScript/Node.js ecosystem limitations
- MCP specification compliance requirements
- GitHub Pages deployment constraints
- Performance and scalability requirements

---

## Domain 1: MCP Server Architecture Research (ADR-001)

### Priority: HIGH - Foundation Critical

#### Core Architecture Questions

**Q1.1: TypeScript MCP SDK Performance Characteristics**

- **Question**: What are the performance benchmarks and limitations of the TypeScript MCP SDK under heavy concurrent usage?
- **Priority**: CRITICAL
- **Research Method**: Performance testing, benchmark analysis
- **Success Criteria**: Documented performance profiles for different load scenarios
- **Timeline**: Week 1
- **Dependencies**: None

**Q1.2: Node.js Memory Management for Repository Analysis**

- **Question**: How can we optimize Node.js memory usage when analyzing large repositories (&gt;10GB)?
- **Priority**: HIGH
- **Research Method**: Memory profiling, stress testing
- **Success Criteria**: Memory optimization strategies with &lt;2GB footprint for 10GB repos
- **Timeline**: Week 1-2
- **Dependencies**: Q1.1

**Q1.3: MCP Tool Orchestration Patterns**

- **Question**: What are the most effective patterns for orchestrating complex multi-tool workflows in MCP?
- **Priority**: HIGH
- **Research Method**: Pattern analysis, prototype development
- **Success Criteria**: Documented orchestration patterns with examples
- **Timeline**: Week 2
- **Dependencies**: Q1.1

**Q1.4: Stateless Session Context Management**

- **Question**: How can we efficiently maintain temporary context across tool calls while preserving stateless architecture?
- **Priority**: MEDIUM
- **Research Method**: Architecture research, implementation prototyping
- **Success Criteria**: Context management strategy that doesn't violate MCP principles
- **Timeline**: Week 2-3
- **Dependencies**: Q1.3

**Q1.5: Error Recovery and Fault Tolerance**

- **Question**: What are the best practices for implementing robust error recovery in MCP servers?
- **Priority**: HIGH
- **Research Method**: Error pattern analysis, resilience testing
- **Success Criteria**: Comprehensive error handling framework
- **Timeline**: Week 3
- **Dependencies**: Q1.1, Q1.3

#### Integration and Deployment Questions

**Q1.6: GitHub Copilot Integration Patterns**

- **Question**: What are the optimal integration patterns for MCP servers with GitHub Copilot?
- **Priority**: MEDIUM
- **Research Method**: Integration testing, user experience research
- **Success Criteria**: Documented integration best practices
- **Timeline**: Week 3-4
- **Dependencies**: Q1.3

**Q1.7: Development Environment Setup**

- **Question**: What tooling and development practices optimize TypeScript MCP server development?
- **Priority**: LOW
- **Research Method**: Tool evaluation, workflow analysis
- **Success Criteria**: Development environment recommendations
- **Timeline**: Week 4
- **Dependencies**: None

---

## Domain 2: Repository Analysis Engine Research (ADR-002)

### Priority: HIGH - Intelligence Foundation

#### Analysis Algorithm Questions

**Q2.1: Multi-layered Analysis Performance**

- **Question**: How can we optimize the performance of parallel multi-layered repository analysis?
- **Priority**: CRITICAL
- **Research Method**: Algorithm optimization, parallel processing research
- **Success Criteria**: Analysis completion &lt;30 seconds for typical repositories
- **Timeline**: Week 1-2
- **Dependencies**: Q1.2

**Q2.2: Language Ecosystem Detection Accuracy**

- **Question**: What are the most reliable methods for detecting and analyzing language ecosystems in repositories?
- **Priority**: HIGH
- **Research Method**: Accuracy testing across diverse repositories
- **Success Criteria**: &gt;95% accuracy for major language ecosystems
- **Timeline**: Week 2
- **Dependencies**: None

**Q2.3: Content Analysis Natural Language Processing**

- **Question**: What NLP techniques are most effective for analyzing documentation quality and gaps?
- **Priority**: MEDIUM
- **Research Method**: NLP library evaluation, accuracy testing
- **Success Criteria**: Reliable content quality assessment methodology
- **Timeline**: Week 3
- **Dependencies**: Q2.1

**Q2.4: Complexity Scoring Algorithm Validation**

- **Question**: How can we validate and calibrate the project complexity scoring algorithm?
- **Priority**: MEDIUM
- **Research Method**: Validation against known project types, expert review
- **Success Criteria**: Complexity scores correlate with manual expert assessment
- **Timeline**: Week 3-4
- **Dependencies**: Q2.1, Q2.2

**Q2.5: Incremental Analysis Capabilities**

- **Question**: How can we implement incremental analysis for repositories that change over time?
- **Priority**: LOW
- **Research Method**: Differential analysis research, caching strategies
- **Success Criteria**: Incremental analysis reduces re-analysis time by &gt;80%
- **Timeline**: Week 4+
- **Dependencies**: Q2.1

#### Scalability and Performance Questions

**Q2.6: Large Repository Handling**

- **Question**: What strategies ensure reliable analysis of enterprise-scale repositories (&gt;100GB)?
- **Priority**: MEDIUM
- **Research Method**: Scalability testing, streaming analysis research
- **Success Criteria**: Successful analysis of repositories up to 100GB
- **Timeline**: Week 2-3
- **Dependencies**: Q1.2, Q2.1

**Q2.7: Analysis Caching Strategies**

- **Question**: What caching strategies provide optimal performance for repository analysis?
- **Priority**: MEDIUM
- **Research Method**: Caching pattern research, performance testing
- **Success Criteria**: Cache hit rates &gt;70% for repeated analysis
- **Timeline**: Week 3
- **Dependencies**: Q2.1

---

## Domain 3: SSG Recommendation Engine Research (ADR-003)

### Priority: HIGH - Core Intelligence

#### Decision Analysis Questions

**Q3.1: Multi-Criteria Decision Algorithm Validation**

- **Question**: How can we validate the accuracy of the MCDA framework for SSG recommendations?
- **Priority**: CRITICAL
- **Research Method**: Validation against expert recommendations, A/B testing
- **Success Criteria**: Algorithm recommendations match expert choices &gt;85% of the time
- **Timeline**: Week 1-2
- **Dependencies**: Q2.4

**Q3.2: SSG Capability Profiling Methodology**

- **Question**: What methodology ensures accurate and up-to-date SSG capability profiles?
- **Priority**: HIGH
- **Research Method**: SSG feature analysis, performance benchmarking
- **Success Criteria**: Comprehensive profiles for 5 major SSGs
- **Timeline**: Week 2-3
- **Dependencies**: None

**Q3.3: Confidence Score Calibration**

- **Question**: How can we calibrate confidence scores to accurately reflect recommendation reliability?
- **Priority**: HIGH
- **Research Method**: Statistical analysis, outcome tracking
- **Success Criteria**: Confidence scores correlate with actual recommendation success
- **Timeline**: Week 3
- **Dependencies**: Q3.1

**Q3.4: Performance Modeling Accuracy**

- **Question**: How accurate are our build time and performance predictions for different SSGs?
- **Priority**: MEDIUM
- **Research Method**: Prediction validation, real-world testing
- **Success Criteria**: Performance predictions within 20% of actual results
- **Timeline**: Week 3-4
- **Dependencies**: Q3.2

**Q3.5: Dynamic Weight Adjustment**

- **Question**: Should recommendation weights be dynamically adjusted based on project characteristics?
- **Priority**: LOW
- **Research Method**: Machine learning research, adaptive algorithm development
- **Success Criteria**: Dynamic weighting improves recommendation accuracy by &gt;10%
- **Timeline**: Week 4+
- **Dependencies**: Q3.1, Q3.3

#### Knowledge Base Maintenance Questions

**Q3.6: Automated SSG Capability Monitoring**

- **Question**: How can we automate the monitoring and updating of SSG capabilities?
- **Priority**: MEDIUM
- **Research Method**: API research, automation tool development
- **Success Criteria**: Automated detection of SSG capability changes
- **Timeline**: Week 4
- **Dependencies**: Q3.2

**Q3.7: Community Feedback Integration**

- **Question**: How can we integrate community feedback to improve recommendation accuracy?
- **Priority**: LOW
- **Research Method**: Feedback system design, data analysis methods
- **Success Criteria**: Community feedback improves recommendations measurably
- **Timeline**: Week 4+
- **Dependencies**: Q3.1

---

## Domain 4: Diataxis Framework Integration Research (ADR-004)

### Priority: MEDIUM - Quality Enhancement

#### Implementation Strategy Questions

**Q4.1: Automated Content Structure Generation**

- **Question**: What are the most effective approaches for automating Diataxis-compliant structure generation?
- **Priority**: HIGH
- **Research Method**: Template system research, automation testing
- **Success Criteria**: Automated generation of compliant structures for all supported SSGs
- **Timeline**: Week 2
- **Dependencies**: Q3.2

**Q4.2: Content Planning Intelligence**

- **Question**: How can we intelligently suggest content based on project analysis and Diataxis principles?
- **Priority**: MEDIUM
- **Research Method**: Content analysis algorithms, suggestion accuracy testing
- **Success Criteria**: Content suggestions deemed useful by documentation experts &gt;80% of time
- **Timeline**: Week 3
- **Dependencies**: Q2.3, Q4.1

**Q4.3: SSG-Specific Diataxis Adaptations**

- **Question**: How should Diataxis implementation be adapted for each SSG's unique capabilities?
- **Priority**: MEDIUM
- **Research Method**: SSG feature analysis, adaptation strategy development
- **Success Criteria**: Optimal Diataxis implementation for each supported SSG
- **Timeline**: Week 3-4
- **Dependencies**: Q3.2, Q4.1

**Q4.4: Navigation Generation Algorithms**

- **Question**: What algorithms generate the most intuitive navigation for Diataxis-organized content?
- **Priority**: MEDIUM
- **Research Method**: UX research, navigation pattern analysis
- **Success Criteria**: Navigation usability scores &gt;90% in user testing
- **Timeline**: Week 4
- **Dependencies**: Q4.1, Q4.3

#### Quality Assurance Questions

**Q4.5: Diataxis Compliance Validation**

- **Question**: How can we automatically validate Diataxis compliance in generated structures?
- **Priority**: MEDIUM
- **Research Method**: Validation algorithm development, compliance testing
- **Success Criteria**: Automated compliance checking with &gt;95% accuracy
- **Timeline**: Week 3
- **Dependencies**: Q4.1

**Q4.6: Content Quality Metrics**

- **Question**: What metrics best measure the quality of Diataxis-organized documentation?
- **Priority**: LOW
- **Research Method**: Quality metric research, correlation analysis
- **Success Criteria**: Validated quality metrics that predict user satisfaction
- **Timeline**: Week 4+
- **Dependencies**: Q4.2, Q4.5

---

## Domain 5: GitHub Pages Deployment Research (ADR-005)

### Priority: HIGH - Implementation Critical

#### Workflow Optimization Questions

**Q5.1: SSG-Specific Workflow Performance**

- **Question**: What are the optimal GitHub Actions configurations for each supported SSG?
- **Priority**: CRITICAL
- **Research Method**: Workflow benchmarking, optimization testing
- **Success Criteria**: Optimized workflows reduce build times by &gt;30%
- **Timeline**: Week 1-2
- **Dependencies**: Q3.2

**Q5.2: Advanced Caching Strategies**

- **Question**: What caching strategies provide maximum build performance in GitHub Actions?
- **Priority**: HIGH
- **Research Method**: Caching pattern research, performance testing
- **Success Criteria**: Cache strategies reduce build times by &gt;50% for incremental changes
- **Timeline**: Week 2
- **Dependencies**: Q5.1

**Q5.3: Build Failure Diagnosis and Recovery**

- **Question**: How can we implement intelligent build failure diagnosis and automatic recovery?
- **Priority**: HIGH
- **Research Method**: Error pattern analysis, recovery strategy development
- **Success Criteria**: Automatic recovery for &gt;70% of common build failures
- **Timeline**: Week 3
- **Dependencies**: Q5.1

**Q5.4: Multi-Environment Deployment Strategies**

- **Question**: What strategies support deployment to multiple environments (staging, production)?
- **Priority**: MEDIUM
- **Research Method**: Deployment pattern research, environment management
- **Success Criteria**: Seamless multi-environment deployment capabilities
- **Timeline**: Week 4
- **Dependencies**: Q5.1, Q5.2

#### Security and Compliance Questions

**Q5.5: Workflow Security Best Practices**

- **Question**: What security best practices should be enforced in generated GitHub Actions workflows?
- **Priority**: HIGH
- **Research Method**: Security research, vulnerability analysis
- **Success Criteria**: Security-hardened workflows with minimal attack surface
- **Timeline**: Week 2-3
- **Dependencies**: Q5.1

**Q5.6: Dependency Vulnerability Management**

- **Question**: How can we automatically manage and update vulnerable dependencies in workflows?
- **Priority**: MEDIUM
- **Research Method**: Dependency scanning research, automation development
- **Success Criteria**: Automated vulnerability detection and resolution
- **Timeline**: Week 3
- **Dependencies**: Q5.5

**Q5.7: Secrets and Environment Management**

- **Question**: What are the best practices for managing secrets and environment variables in automated deployments?
- **Priority**: MEDIUM
- **Research Method**: Security pattern research, credential management
- **Success Criteria**: Secure secrets management without user complexity
- **Timeline**: Week 3
- **Dependencies**: Q5.5

#### Monitoring and Troubleshooting Questions

**Q5.8: Deployment Health Monitoring**

- **Question**: How can we implement comprehensive health monitoring for deployed documentation sites?
- **Priority**: MEDIUM
- **Research Method**: Monitoring tool research, health check development
- **Success Criteria**: Comprehensive health monitoring with actionable alerts
- **Timeline**: Week 4
- **Dependencies**: Q5.1

**Q5.9: Performance Optimization Recommendations**

- **Question**: How can we provide automated performance optimization recommendations for deployed sites?
- **Priority**: LOW
- **Research Method**: Performance analysis research, optimization pattern development
- **Success Criteria**: Automated performance recommendations that improve site speed
- **Timeline**: Week 4+
- **Dependencies**: Q5.8

---

## Domain 6: MCP Tools API Research (ADR-006)

### Priority: HIGH - User Interface Critical

#### API Design and Usability Questions

**Q6.1: Tool Parameter Schema Optimization**

- **Question**: What parameter schema designs provide the best balance of flexibility and usability?
- **Priority**: HIGH
- **Research Method**: API design research, usability testing
- **Success Criteria**: Parameter schemas that are intuitive and comprehensive
- **Timeline**: Week 1-2
- **Dependencies**: None

**Q6.2: Response Format Standardization**

- **Question**: What response formats provide optimal client integration and user experience?
- **Priority**: HIGH
- **Research Method**: Format analysis, client integration testing
- **Success Criteria**: Standardized formats that simplify client development
- **Timeline**: Week 2
- **Dependencies**: Q6.1

**Q6.3: Error Handling and User Guidance**

- **Question**: How can we provide the most helpful error messages and recovery guidance?
- **Priority**: HIGH
- **Research Method**: Error analysis, user experience research
- **Success Criteria**: Error messages that enable users to resolve issues &gt;90% of the time
- **Timeline**: Week 2-3
- **Dependencies**: Q6.1

**Q6.4: Progressive Complexity Disclosure**

- **Question**: How can we design APIs that are simple for beginners but powerful for experts?
- **Priority**: MEDIUM
- **Research Method**: API design pattern research, user journey analysis
- **Success Criteria**: APIs that scale from simple to complex use cases seamlessly
- **Timeline**: Week 3
- **Dependencies**: Q6.1, Q6.2

#### Validation and Security Questions

**Q6.5: Comprehensive Input Validation**

- **Question**: What validation strategies ensure robust security and user-friendly error reporting?
- **Priority**: HIGH
- **Research Method**: Validation framework research, security testing
- **Success Criteria**: Validation that prevents all security issues while providing clear feedback
- **Timeline**: Week 2
- **Dependencies**: Q6.1

**Q6.6: Performance and Caching Optimization**

- **Question**: How can we optimize API performance through intelligent caching and response optimization?
- **Priority**: MEDIUM
- **Research Method**: Performance testing, caching strategy research
- **Success Criteria**: API response times &lt;1 second for all operations
- **Timeline**: Week 3
- **Dependencies**: Q6.2

#### Integration and Extension Questions

**Q6.7: Client Integration Patterns**

- **Question**: What integration patterns work best for different types of MCP clients?
- **Priority**: MEDIUM
- **Research Method**: Integration testing, client developer feedback
- **Success Criteria**: Integration patterns that simplify client development
- **Timeline**: Week 3-4
- **Dependencies**: Q6.2, Q6.4

**Q6.8: API Extension and Versioning**

- **Question**: How can we design APIs that support future extensions without breaking existing clients?
- **Priority**: LOW
- **Research Method**: Versioning strategy research, extension pattern analysis
- **Success Criteria**: Extension mechanisms that maintain backward compatibility
- **Timeline**: Week 4
- **Dependencies**: Q6.1, Q6.2

---

## Cross-Domain Integration Research

### Priority: MEDIUM - System Integration

#### End-to-End Workflow Questions

**Q7.1: Complete Workflow Orchestration**

- **Question**: How can we optimize the complete workflow from repository analysis to deployed documentation?
- **Priority**: HIGH
- **Research Method**: Workflow analysis, performance optimization
- **Success Criteria**: End-to-end workflow completion in &lt;10 minutes for typical projects
- **Timeline**: Week 3-4
- **Dependencies**: All previous domains

**Q7.2: Error Recovery Across Tools**

- **Question**: How can we implement robust error recovery that spans multiple tool invocations?
- **Priority**: MEDIUM
- **Research Method**: Error pattern analysis, recovery strategy development
- **Success Criteria**: Graceful recovery from failures at any workflow stage
- **Timeline**: Week 4
- **Dependencies**: Q7.1

**Q7.3: Performance Monitoring and Optimization**

- **Question**: How can we monitor and optimize performance across the entire system?
- **Priority**: MEDIUM
- **Research Method**: Performance monitoring research, optimization strategies
- **Success Criteria**: System-wide performance monitoring and optimization recommendations
- **Timeline**: Week 4
- **Dependencies**: Q7.1

#### Quality Assurance and Validation

**Q7.4: Integration Testing Strategies**

- **Question**: What testing strategies ensure reliable operation across all components?
- **Priority**: MEDIUM
- **Research Method**: Testing framework research, integration test development
- **Success Criteria**: Comprehensive integration tests with &gt;95% coverage
- **Timeline**: Week 4
- **Dependencies**: All previous domains

**Q7.5: User Acceptance Validation**

- **Question**: How can we validate that the complete system meets user needs and expectations?
- **Priority**: LOW
- **Research Method**: User research, acceptance testing
- **Success Criteria**: User satisfaction scores &gt;85% in testing
- **Timeline**: Week 4+
- **Dependencies**: Q7.1, Q7.4

---

## Research Execution Framework

### Research Methodology

1. **Literature Review**: Systematic review of existing solutions and best practices
2. **Prototype Development**: Small-scale implementations to validate approaches
3. **Performance Testing**: Quantitative analysis of performance characteristics
4. **Expert Consultation**: Validation with domain experts and practitioners
5. **Community Research**: Analysis of community practices and feedback

### Success Criteria Framework

Each research question includes:

- **Quantitative Metrics**: Measurable success criteria
- **Qualitative Assessments**: Expert validation and user feedback
- **Risk Mitigation**: Identification of potential issues and solutions
- **Implementation Guidance**: Actionable recommendations for development

### Documentation Requirements

All research outcomes must be documented with:

- **Executive Summary**: Key findings and recommendations
- **Detailed Analysis**: Comprehensive research methodology and results
- **Implementation Recommendations**: Specific guidance for development
- **Risk Assessment**: Identified risks and mitigation strategies
- **Follow-up Actions**: Additional research or validation needed

### Timeline and Prioritization

**Week 1 Focus**: Critical path items (Q1.1, Q2.1, Q3.1, Q5.1)
**Week 2 Focus**: High priority foundational research
**Week 3 Focus**: Integration and optimization research
**Week 4 Focus**: Advanced features and system integration

### Quality Assurance

- **Peer Review**: All research findings reviewed by team members
- **Expert Validation**: Critical decisions validated by external experts
- **Prototype Validation**: Key approaches validated through working prototypes
- **Documentation Standards**: All research properly documented and archived

---

## Research Output Organization

### File Structure

```
docs/research/
├── research-questions-2025-01-14.md          (this file)
├── domain-1-mcp-architecture/
├── domain-2-repository-analysis/
├── domain-3-ssg-recommendation/
├── domain-4-diataxis-integration/
├── domain-5-github-deployment/
├── domain-6-api-design/
├── cross-domain-integration/
└── research-findings-summary.md
```

### Progress Tracking

Research progress will be tracked using:

- **Weekly Status Reports**: Progress on each research domain
- **Risk Register**: Ongoing tracking of identified risks and mitigations
- **Decision Log**: Record of key decisions made based on research findings
- **Implementation Readiness Assessment**: Regular evaluation of readiness to begin development

---

**Total Research Questions**: 47 questions across 6 domains  
**Critical Path Questions**: 6 questions requiring immediate attention  
**High Priority Questions**: 19 questions for weeks 1-2  
**Estimated Research Duration**: 4 weeks  
**Success Metrics**: Quantitative criteria for each research area

This comprehensive research framework ensures systematic validation of all ADR decisions and provides the foundation for confident implementation of the DocuMCP project.

```

--------------------------------------------------------------------------------
/src/utils/drift-detector.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Documentation Drift Detection System (Phase 3)
 *
 * Detects when code changes invalidate existing documentation
 * Provides automatic update suggestions based on code changes
 */

import { promises as fs } from "fs";
import path from "path";
import { ASTAnalyzer, ASTAnalysisResult, CodeDiff } from "./ast-analyzer.js";

export interface DriftDetectionResult {
  filePath: string;
  hasDrift: boolean;
  severity: "none" | "low" | "medium" | "high" | "critical";
  drifts: DocumentationDrift[];
  suggestions: DriftSuggestion[];
  impactAnalysis: ImpactAnalysis;
}

export interface DocumentationDrift {
  type: "outdated" | "incorrect" | "missing" | "breaking";
  affectedDocs: string[];
  codeChanges: CodeDiff[];
  description: string;
  detectedAt: string;
  severity: "low" | "medium" | "high" | "critical";
}

export interface DriftSuggestion {
  docFile: string;
  section: string;
  currentContent: string;
  suggestedContent: string;
  reasoning: string;
  confidence: number;
  autoApplicable: boolean;
}

export interface ImpactAnalysis {
  breakingChanges: number;
  majorChanges: number;
  minorChanges: number;
  affectedDocFiles: string[];
  estimatedUpdateEffort: "low" | "medium" | "high";
  requiresManualReview: boolean;
}

export interface DriftSnapshot {
  projectPath: string;
  timestamp: string;
  files: Map<string, ASTAnalysisResult>;
  documentation: Map<string, DocumentationSnapshot>;
}

export interface DocumentationSnapshot {
  filePath: string;
  contentHash: string;
  referencedCode: string[];
  lastUpdated: string;
  sections: DocumentationSection[];
}

export interface DocumentationSection {
  title: string;
  content: string;
  referencedFunctions: string[];
  referencedClasses: string[];
  referencedTypes: string[];
  codeExamples: CodeExample[];
  startLine: number;
  endLine: number;
}

export interface CodeExample {
  language: string;
  code: string;
  description: string;
  referencedSymbols: string[];
}

/**
 * Main Drift Detector class
 */
export class DriftDetector {
  private analyzer: ASTAnalyzer;
  private snapshotDir: string;
  private currentSnapshot: DriftSnapshot | null = null;
  private previousSnapshot: DriftSnapshot | null = null;

  constructor(projectPath: string, snapshotDir?: string) {
    this.analyzer = new ASTAnalyzer();
    this.snapshotDir =
      snapshotDir || path.join(projectPath, ".documcp", "snapshots");
  }

  /**
   * Initialize the drift detector
   */
  async initialize(): Promise<void> {
    await this.analyzer.initialize();
    await fs.mkdir(this.snapshotDir, { recursive: true });
  }

  /**
   * Create a snapshot of the current codebase and documentation
   */
  async createSnapshot(
    projectPath: string,
    docsPath: string,
  ): Promise<DriftSnapshot> {
    const files = new Map<string, ASTAnalysisResult>();
    const documentation = new Map<string, DocumentationSnapshot>();

    // Analyze source files
    const sourceFiles = await this.findSourceFiles(projectPath);
    for (const filePath of sourceFiles) {
      const analysis = await this.analyzer.analyzeFile(filePath);
      if (analysis) {
        files.set(filePath, analysis);
      }
    }

    // Analyze documentation files
    const docFiles = await this.findDocumentationFiles(docsPath);
    for (const docPath of docFiles) {
      const docSnapshot = await this.analyzeDocumentation(docPath);
      if (docSnapshot) {
        documentation.set(docPath, docSnapshot);
      }
    }

    const snapshot: DriftSnapshot = {
      projectPath,
      timestamp: new Date().toISOString(),
      files,
      documentation,
    };

    // Save snapshot
    await this.saveSnapshot(snapshot);

    return snapshot;
  }

  /**
   * Detect drift between two snapshots
   */
  async detectDrift(
    oldSnapshot: DriftSnapshot,
    newSnapshot: DriftSnapshot,
  ): Promise<DriftDetectionResult[]> {
    const results: DriftDetectionResult[] = [];

    // Compare each file
    for (const [filePath, newAnalysis] of newSnapshot.files) {
      const oldAnalysis = oldSnapshot.files.get(filePath);

      if (!oldAnalysis) {
        // New file - check if documentation is needed
        continue;
      }

      // Detect code changes
      const codeDiffs = await this.analyzer.detectDrift(
        oldAnalysis,
        newAnalysis,
      );

      if (codeDiffs.length > 0) {
        // Find affected documentation
        const affectedDocs = this.findAffectedDocumentation(
          filePath,
          codeDiffs,
          newSnapshot.documentation,
        );

        // Report drift even if no documentation is affected
        // (missing documentation is also a type of drift)
        const driftResult = await this.analyzeDrift(
          filePath,
          codeDiffs,
          affectedDocs,
          oldSnapshot,
          newSnapshot,
        );

        results.push(driftResult);
      }
    }

    return results;
  }

  /**
   * Analyze drift and generate suggestions
   */
  private async analyzeDrift(
    filePath: string,
    codeDiffs: CodeDiff[],
    affectedDocs: string[],
    oldSnapshot: DriftSnapshot,
    newSnapshot: DriftSnapshot,
  ): Promise<DriftDetectionResult> {
    const drifts: DocumentationDrift[] = [];
    const suggestions: DriftSuggestion[] = [];

    // Categorize drifts by severity
    const breakingChanges = codeDiffs.filter(
      (d) => d.impactLevel === "breaking",
    );
    const majorChanges = codeDiffs.filter((d) => d.impactLevel === "major");
    const minorChanges = codeDiffs.filter((d) => d.impactLevel === "minor");

    // Create drift entries
    for (const diff of codeDiffs) {
      const drift: DocumentationDrift = {
        type: this.determineDriftType(diff),
        affectedDocs,
        codeChanges: [diff],
        description: this.generateDriftDescription(diff),
        detectedAt: new Date().toISOString(),
        severity: this.mapImpactToSeverity(diff.impactLevel),
      };

      drifts.push(drift);

      // Generate suggestions for each affected doc
      for (const docPath of affectedDocs) {
        const docSnapshot = newSnapshot.documentation.get(docPath);
        if (docSnapshot) {
          const docSuggestions = await this.generateSuggestions(
            diff,
            docSnapshot,
            newSnapshot,
          );
          suggestions.push(...docSuggestions);
        }
      }
    }

    const impactAnalysis: ImpactAnalysis = {
      breakingChanges: breakingChanges.length,
      majorChanges: majorChanges.length,
      minorChanges: minorChanges.length,
      affectedDocFiles: affectedDocs,
      estimatedUpdateEffort: this.estimateUpdateEffort(drifts),
      requiresManualReview:
        breakingChanges.length > 0 || majorChanges.length > 3,
    };

    const severity = this.calculateOverallSeverity(drifts);

    return {
      filePath,
      hasDrift: drifts.length > 0,
      severity,
      drifts,
      suggestions,
      impactAnalysis,
    };
  }

  /**
   * Generate update suggestions for documentation
   */
  private async generateSuggestions(
    diff: CodeDiff,
    docSnapshot: DocumentationSnapshot,
    snapshot: DriftSnapshot,
  ): Promise<DriftSuggestion[]> {
    const suggestions: DriftSuggestion[] = [];

    // Find sections that reference the changed code
    for (const section of docSnapshot.sections) {
      const isAffected = this.isSectionAffected(section, diff);

      if (isAffected) {
        const suggestion = await this.createSuggestion(
          diff,
          docSnapshot,
          section,
          snapshot,
        );

        if (suggestion) {
          suggestions.push(suggestion);
        }
      }
    }

    return suggestions;
  }

  /**
   * Create a specific suggestion for a documentation section
   */
  private async createSuggestion(
    diff: CodeDiff,
    docSnapshot: DocumentationSnapshot,
    section: DocumentationSection,
    snapshot: DriftSnapshot,
  ): Promise<DriftSuggestion | null> {
    let suggestedContent = section.content;
    let reasoning = "";
    let confidence = 0.5;
    let autoApplicable = false;

    switch (diff.type) {
      case "removed":
        reasoning = `The ${diff.category} '${diff.name}' has been removed from the codebase. This section should be updated or removed.`;
        suggestedContent = this.generateRemovalSuggestion(section, diff);
        confidence = 0.8;
        autoApplicable = false;
        break;

      case "added":
        reasoning = `A new ${diff.category} '${diff.name}' has been added. Consider documenting it.`;
        suggestedContent = this.generateAdditionSuggestion(
          section,
          diff,
          snapshot,
        );
        confidence = 0.6;
        autoApplicable = false;
        break;

      case "modified":
        reasoning = `The ${diff.category} '${diff.name}' has been modified: ${diff.details}`;
        suggestedContent = this.generateModificationSuggestion(
          section,
          diff,
          snapshot,
        );
        confidence = 0.7;
        autoApplicable = diff.impactLevel === "patch";
        break;
    }

    return {
      docFile: docSnapshot.filePath,
      section: section.title,
      currentContent: section.content,
      suggestedContent,
      reasoning,
      confidence,
      autoApplicable,
    };
  }

  /**
   * Generate suggestion for removed code
   */
  private generateRemovalSuggestion(
    section: DocumentationSection,
    diff: CodeDiff,
  ): string {
    let content = section.content;

    // Remove references to the deleted symbol
    const symbolRegex = new RegExp(`\\b${diff.name}\\b`, "g");
    content = content.replace(symbolRegex, `~~${diff.name}~~ (removed)`);

    // Add deprecation notice
    const notice = `\n\n> **Note**: The \`${diff.name}\` ${diff.category} has been removed in the latest version.\n`;
    content = notice + content;

    return content;
  }

  /**
   * Generate suggestion for added code
   */
  private generateAdditionSuggestion(
    section: DocumentationSection,
    diff: CodeDiff,
    _snapshot: DriftSnapshot,
  ): string {
    let content = section.content;

    // Add new section for the added symbol
    const additionNotice = `\n\n## ${diff.name}\n\nA new ${diff.category} has been added.\n\n`;

    // Try to extract signature if available
    if (diff.newSignature) {
      content +=
        additionNotice + `\`\`\`typescript\n${diff.newSignature}\n\`\`\`\n`;
    } else {
      content +=
        additionNotice +
        `> **Documentation needed**: Please document the \`${diff.name}\` ${diff.category}.\n`;
    }

    return content;
  }

  /**
   * Generate suggestion for modified code
   */
  private generateModificationSuggestion(
    section: DocumentationSection,
    diff: CodeDiff,
    _snapshot: DriftSnapshot,
  ): string {
    let content = section.content;

    // Update signature references
    if (diff.oldSignature && diff.newSignature) {
      content = content.replace(diff.oldSignature, diff.newSignature);
    }

    // Add update notice
    const updateNotice = `\n\n> **Updated**: ${diff.details}\n`;
    content = updateNotice + content;

    return content;
  }

  /**
   * Check if a section is affected by a code change
   */
  private isSectionAffected(
    section: DocumentationSection,
    diff: CodeDiff,
  ): boolean {
    switch (diff.category) {
      case "function":
        return section.referencedFunctions.includes(diff.name);
      case "class":
        return section.referencedClasses.includes(diff.name);
      case "interface":
      case "type":
        return section.referencedTypes.includes(diff.name);
      default:
        return false;
    }
  }

  /**
   * Find documentation files that reference changed code
   */
  private findAffectedDocumentation(
    filePath: string,
    codeDiffs: CodeDiff[],
    documentation: Map<string, DocumentationSnapshot>,
  ): string[] {
    const affected: string[] = [];

    for (const [docPath, docSnapshot] of documentation) {
      // Check if doc references the changed file
      if (docSnapshot.referencedCode.includes(filePath)) {
        affected.push(docPath);
        continue;
      }

      // Check if doc references changed symbols
      for (const diff of codeDiffs) {
        for (const section of docSnapshot.sections) {
          if (this.isSectionAffected(section, diff)) {
            affected.push(docPath);
            break;
          }
        }
      }
    }

    return [...new Set(affected)];
  }

  /**
   * Analyze a documentation file
   */
  private async analyzeDocumentation(
    docPath: string,
  ): Promise<DocumentationSnapshot | null> {
    try {
      const content = await fs.readFile(docPath, "utf-8");
      const crypto = await import("crypto");
      const contentHash = crypto
        .createHash("sha256")
        .update(content)
        .digest("hex");
      const stats = await fs.stat(docPath);

      const sections = this.extractDocSections(content);
      const referencedCode = this.extractCodeReferences(content);

      return {
        filePath: docPath,
        contentHash,
        referencedCode,
        lastUpdated: stats.mtime.toISOString(),
        sections,
      };
    } catch (error) {
      console.warn(`Failed to analyze documentation ${docPath}:`, error);
      return null;
    }
  }

  /**
   * Extract sections from documentation
   */
  private extractDocSections(content: string): DocumentationSection[] {
    const sections: DocumentationSection[] = [];
    const lines = content.split("\n");
    let currentSection: Partial<DocumentationSection> | null = null;
    let currentContent: string[] = [];

    for (let i = 0; i < lines.length; i++) {
      const line = lines[i];

      // Detect headings
      const headingMatch = line.match(/^(#{1,6})\s+(.+)/);
      if (headingMatch) {
        // Save previous section
        if (currentSection) {
          currentSection.content = currentContent.join("\n");
          currentSection.endLine = i - 1;
          sections.push(currentSection as DocumentationSection);
        }

        const title = headingMatch[2];
        const referencedFunctions: string[] = [];
        const referencedClasses: string[] = [];

        // Extract function name from heading if it looks like a function signature
        // e.g., "## calculate(x: number): number" or "## myFunction()"
        const funcMatch = title.match(/^([a-z][A-Za-z0-9_]*)\s*\(/);
        if (funcMatch) {
          referencedFunctions.push(funcMatch[1]);
        }

        // Extract class name from heading if it starts with uppercase
        const classMatch = title.match(/^([A-Z][A-Za-z0-9_]*)/);
        if (classMatch && !funcMatch) {
          referencedClasses.push(classMatch[1]);
        }

        // Start new section
        currentSection = {
          title,
          startLine: i,
          referencedFunctions,
          referencedClasses,
          referencedTypes: [],
          codeExamples: [],
        };
        currentContent = [];
      } else if (currentSection) {
        currentContent.push(line);

        // Extract code examples
        if (line.startsWith("```")) {
          const langMatch = line.match(/```(\w+)/);
          const language = langMatch ? langMatch[1] : "text";
          const codeLines: string[] = [];
          i++;

          while (i < lines.length && !lines[i].startsWith("```")) {
            codeLines.push(lines[i]);
            i++;
          }

          const codeExample: CodeExample = {
            language,
            code: codeLines.join("\n"),
            description: "",
            referencedSymbols: this.extractSymbolsFromCode(
              codeLines.join("\n"),
            ),
          };

          currentSection.codeExamples!.push(codeExample);
        }

        // Extract inline code references (with or without parentheses for functions)
        const inlineCodeMatches = line.matchAll(
          /`([A-Za-z_][A-Za-z0-9_]*)\(\)?`/g,
        );
        for (const match of inlineCodeMatches) {
          const symbol = match[1];
          // Heuristic: CamelCase = class/type, camelCase = function
          if (/^[A-Z]/.test(symbol)) {
            if (!currentSection.referencedClasses!.includes(symbol)) {
              currentSection.referencedClasses!.push(symbol);
            }
          } else {
            if (!currentSection.referencedFunctions!.includes(symbol)) {
              currentSection.referencedFunctions!.push(symbol);
            }
          }
        }

        // Also extract identifiers without parentheses
        const plainIdentifiers = line.matchAll(/`([A-Za-z_][A-Za-z0-9_]*)`/g);
        for (const match of plainIdentifiers) {
          const symbol = match[1];
          if (/^[A-Z]/.test(symbol)) {
            if (!currentSection.referencedClasses!.includes(symbol)) {
              currentSection.referencedClasses!.push(symbol);
            }
          } else {
            if (!currentSection.referencedFunctions!.includes(symbol)) {
              currentSection.referencedFunctions!.push(symbol);
            }
          }
        }
      }
    }

    // Save last section
    if (currentSection) {
      currentSection.content = currentContent.join("\n");
      currentSection.endLine = lines.length - 1;
      sections.push(currentSection as DocumentationSection);
    }

    return sections;
  }

  /**
   * Extract code file references from documentation
   */
  private extractCodeReferences(content: string): string[] {
    const references: string[] = [];

    // Extract from markdown links
    const linkMatches = content.matchAll(
      /\[.*?\]\((.*?\.(ts|js|py|go|rs|java|rb).*?)\)/g,
    );
    for (const match of linkMatches) {
      references.push(match[1]);
    }

    // Extract from inline code
    const codeMatches = content.matchAll(
      /`([^`]+\.(ts|js|py|go|rs|java|rb))`/g,
    );
    for (const match of codeMatches) {
      references.push(match[1]);
    }

    return [...new Set(references)];
  }

  /**
   * Extract symbols from code examples
   */
  private extractSymbolsFromCode(code: string): string[] {
    const symbols: string[] = [];

    // Extract function calls
    const functionMatches = code.matchAll(/\b([a-z][A-Za-z0-9_]*)\s*\(/g);
    for (const match of functionMatches) {
      symbols.push(match[1]);
    }

    // Extract class/type references
    const classMatches = code.matchAll(/\b([A-Z][A-Za-z0-9_]*)\b/g);
    for (const match of classMatches) {
      symbols.push(match[1]);
    }

    return [...new Set(symbols)];
  }

  /**
   * Find all source files in project
   */
  private async findSourceFiles(projectPath: string): Promise<string[]> {
    const files: string[] = [];
    const extensions = [
      ".ts",
      ".tsx",
      ".js",
      ".jsx",
      ".py",
      ".go",
      ".rs",
      ".java",
      ".rb",
    ];

    const walk = async (dir: string) => {
      try {
        const entries = await fs.readdir(dir, { withFileTypes: true });

        for (const entry of entries) {
          const fullPath = path.join(dir, entry.name);

          if (entry.isDirectory()) {
            if (
              !["node_modules", "dist", "build", ".git", ".next"].includes(
                entry.name,
              )
            ) {
              await walk(fullPath);
            }
          } else {
            const ext = path.extname(entry.name);
            if (extensions.includes(ext)) {
              files.push(fullPath);
            }
          }
        }
      } catch (error) {
        console.warn(`Failed to read directory ${dir}:`, error);
      }
    };

    await walk(projectPath);
    return files;
  }

  /**
   * Find all documentation files
   */
  private async findDocumentationFiles(docsPath: string): Promise<string[]> {
    const files: string[] = [];

    const walk = async (dir: string) => {
      try {
        const entries = await fs.readdir(dir, { withFileTypes: true });

        for (const entry of entries) {
          const fullPath = path.join(dir, entry.name);

          if (entry.isDirectory()) {
            await walk(fullPath);
          } else if (
            entry.name.endsWith(".md") ||
            entry.name.endsWith(".mdx")
          ) {
            files.push(fullPath);
          }
        }
      } catch (error) {
        console.warn(`Failed to read documentation directory ${dir}:`, error);
      }
    };

    try {
      await walk(docsPath);
    } catch {
      // Docs path doesn't exist
    }

    return files;
  }

  /**
   * Save snapshot to disk
   */
  private async saveSnapshot(snapshot: DriftSnapshot): Promise<void> {
    const timestamp = new Date().toISOString().replace(/:/g, "-");
    const snapshotPath = path.join(
      this.snapshotDir,
      `snapshot-${timestamp}.json`,
    );

    // Convert Maps to objects for JSON serialization
    const serializable = {
      projectPath: snapshot.projectPath,
      timestamp: snapshot.timestamp,
      files: Object.fromEntries(snapshot.files),
      documentation: Object.fromEntries(snapshot.documentation),
    };

    await fs.writeFile(snapshotPath, JSON.stringify(serializable, null, 2));
  }

  /**
   * Load the latest snapshot
   */
  async loadLatestSnapshot(): Promise<DriftSnapshot | null> {
    try {
      const files = await fs.readdir(this.snapshotDir);
      const snapshotFiles = files
        .filter((f) => f.startsWith("snapshot-"))
        .sort()
        .reverse();

      if (snapshotFiles.length === 0) return null;

      const latestPath = path.join(this.snapshotDir, snapshotFiles[0]);
      const content = await fs.readFile(latestPath, "utf-8");
      const data = JSON.parse(content);

      return {
        projectPath: data.projectPath,
        timestamp: data.timestamp,
        files: new Map(Object.entries(data.files)),
        documentation: new Map(Object.entries(data.documentation)),
      };
    } catch {
      return null;
    }
  }

  // Helper methods

  private determineDriftType(
    diff: CodeDiff,
  ): "outdated" | "incorrect" | "missing" | "breaking" {
    if (diff.impactLevel === "breaking") return "breaking";
    if (diff.type === "removed") return "incorrect";
    if (diff.type === "modified") return "outdated";
    return "missing";
  }

  private generateDriftDescription(diff: CodeDiff): string {
    const action =
      diff.type === "added"
        ? "added"
        : diff.type === "removed"
          ? "removed"
          : "modified";
    return `${diff.category} '${diff.name}' was ${action}: ${diff.details}`;
  }

  private mapImpactToSeverity(
    impact: "breaking" | "major" | "minor" | "patch",
  ): "low" | "medium" | "high" | "critical" {
    switch (impact) {
      case "breaking":
        return "critical";
      case "major":
        return "high";
      case "minor":
        return "medium";
      case "patch":
        return "low";
    }
  }

  private estimateUpdateEffort(
    drifts: DocumentationDrift[],
  ): "low" | "medium" | "high" {
    const critical = drifts.filter((d) => d.severity === "critical").length;
    const high = drifts.filter((d) => d.severity === "high").length;

    if (critical > 0 || high > 5) return "high";
    if (high > 0 || drifts.length > 10) return "medium";
    return "low";
  }

  private calculateOverallSeverity(
    drifts: DocumentationDrift[],
  ): "none" | "low" | "medium" | "high" | "critical" {
    if (drifts.length === 0) return "none";

    const hasCritical = drifts.some((d) => d.severity === "critical");
    if (hasCritical) return "critical";

    const hasHigh = drifts.some((d) => d.severity === "high");
    if (hasHigh) return "high";

    const hasMedium = drifts.some((d) => d.severity === "medium");
    if (hasMedium) return "medium";

    return "low";
  }
}

```
Page 12/20FirstPrevNextLast