This is page 8 of 33. Use http://codebase.md/tosin2013/documcp?lines=true&page={x} to view the full context.
# Directory Structure
```
├── .dockerignore
├── .eslintignore
├── .eslintrc.json
├── .github
│ ├── agents
│ │ ├── documcp-ast.md
│ │ ├── documcp-deploy.md
│ │ ├── documcp-memory.md
│ │ ├── documcp-test.md
│ │ └── documcp-tool.md
│ ├── copilot-instructions.md
│ ├── dependabot.yml
│ ├── ISSUE_TEMPLATE
│ │ ├── automated-changelog.md
│ │ ├── bug_report.md
│ │ ├── bug_report.yml
│ │ ├── documentation_issue.md
│ │ ├── feature_request.md
│ │ ├── feature_request.yml
│ │ ├── npm-publishing-fix.md
│ │ └── release_improvements.md
│ ├── PULL_REQUEST_TEMPLATE.md
│ ├── release-drafter.yml
│ └── workflows
│ ├── auto-merge.yml
│ ├── ci.yml
│ ├── codeql.yml
│ ├── dependency-review.yml
│ ├── deploy-docs.yml
│ ├── README.md
│ ├── release-drafter.yml
│ └── release.yml
├── .gitignore
├── .husky
│ ├── commit-msg
│ └── pre-commit
├── .linkcheck.config.json
├── .markdown-link-check.json
├── .nvmrc
├── .pre-commit-config.yaml
├── .versionrc.json
├── ARCHITECTURAL_CHANGES_SUMMARY.md
├── 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
│ │ ├── adr-0001-mcp-server-architecture.md
│ │ ├── adr-0002-repository-analysis-engine.md
│ │ ├── adr-0003-static-site-generator-recommendation-engine.md
│ │ ├── adr-0004-diataxis-framework-integration.md
│ │ ├── adr-0005-github-pages-deployment-automation.md
│ │ ├── adr-0006-mcp-tools-api-design.md
│ │ ├── adr-0007-mcp-prompts-and-resources-integration.md
│ │ ├── adr-0008-intelligent-content-population-engine.md
│ │ ├── adr-0009-content-accuracy-validation-framework.md
│ │ ├── adr-0010-mcp-resource-pattern-redesign.md
│ │ ├── adr-0011-ce-mcp-compatibility.md
│ │ ├── adr-0012-priority-scoring-system-for-documentation-drift.md
│ │ ├── adr-0013-release-pipeline-and-package-distribution.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
│ ├── CE-MCP-FINDINGS.md
│ ├── 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
│ │ ├── change-watcher.md
│ │ ├── custom-domains.md
│ │ ├── documentation-freshness-tracking.md
│ │ ├── drift-priority-scoring.md
│ │ ├── github-pages-deployment.md
│ │ ├── index.md
│ │ ├── llm-integration.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
├── ISSUE_IMPLEMENTATION_SUMMARY.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
│ │ ├── change-watcher.ts
│ │ ├── check-documentation-links.ts
│ │ ├── cleanup-agent-artifacts.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
│ │ ├── simulate-execution.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
│ │ ├── artifact-detector.ts
│ │ ├── ast-analyzer.ts
│ │ ├── change-watcher.ts
│ │ ├── code-scanner.ts
│ │ ├── content-extractor.ts
│ │ ├── drift-detector.ts
│ │ ├── execution-simulator.ts
│ │ ├── freshness-tracker.ts
│ │ ├── language-parsers-simple.ts
│ │ ├── llm-client.ts
│ │ ├── permission-checker.ts
│ │ ├── semantic-analyzer.ts
│ │ ├── sitemap-generator.ts
│ │ ├── usage-metadata.ts
│ │ └── user-feedback-integration.ts
│ └── workflows
│ └── documentation-workflow.ts
├── test-docs-local.sh
├── tests
│ ├── api
│ │ └── mcp-responses.test.ts
│ ├── benchmarks
│ │ └── performance.test.ts
│ ├── call-graph-builder.test.ts
│ ├── change-watcher-priority.integration.test.ts
│ ├── change-watcher.test.ts
│ ├── edge-cases
│ │ └── error-handling.test.ts
│ ├── execution-simulator.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-documentation-examples.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-documentation-examples.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
│ │ ├── cleanup-agent-artifacts.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
│ ├── artifact-detector.test.ts
│ ├── ast-analyzer.test.ts
│ ├── content-extractor.test.ts
│ ├── drift-detector-diataxis.test.ts
│ ├── drift-detector-priority.test.ts
│ ├── drift-detector.test.ts
│ ├── freshness-tracker.test.ts
│ ├── llm-client.test.ts
│ ├── semantic-analyzer.test.ts
│ ├── sitemap-generator.test.ts
│ ├── usage-metadata.test.ts
│ └── user-feedback-integration.test.ts
├── tsconfig.json
└── typedoc.json
```
# Files
--------------------------------------------------------------------------------
/docs/api/assets/icons.js:
--------------------------------------------------------------------------------
```javascript
1 | (function () {
2 | addIcons();
3 | function addIcons() {
4 | if (document.readyState === "loading")
5 | return document.addEventListener("DOMContentLoaded", addIcons);
6 | const svg = document.body.appendChild(
7 | document.createElementNS("http://www.w3.org/2000/svg", "svg"),
8 | );
9 | svg.innerHTML = `<g id="icon-1" class="tsd-no-select"><rect fill="var(--color-icon-background)" stroke="var(--color-ts-module)" stroke-width="1.5" x="1" y="1" width="22" height="22" rx="6"></rect><text fill="var(--color-icon-text)" x="50%" y="50%" dominant-baseline="central" text-anchor="middle">M</text></g><g id="icon-2" class="tsd-no-select"><rect fill="var(--color-icon-background)" stroke="var(--color-ts-module)" stroke-width="1.5" x="1" y="1" width="22" height="22" rx="6"></rect><text fill="var(--color-icon-text)" x="50%" y="50%" dominant-baseline="central" text-anchor="middle">M</text></g><g id="icon-4" class="tsd-no-select"><rect fill="var(--color-icon-background)" stroke="var(--color-ts-namespace)" stroke-width="1.5" x="1" y="1" width="22" height="22" rx="6"></rect><text fill="var(--color-icon-text)" x="50%" y="50%" dominant-baseline="central" text-anchor="middle">N</text></g><g id="icon-8" class="tsd-no-select"><rect fill="var(--color-icon-background)" stroke="var(--color-ts-enum)" stroke-width="1.5" x="1" y="1" width="22" height="22" rx="6"></rect><text fill="var(--color-icon-text)" x="50%" y="50%" dominant-baseline="central" text-anchor="middle">E</text></g><g id="icon-16" class="tsd-no-select"><rect fill="var(--color-icon-background)" stroke="var(--color-ts-property)" stroke-width="1.5" x="1" y="1" width="22" height="22" rx="12"></rect><text fill="var(--color-icon-text)" x="50%" y="50%" dominant-baseline="central" text-anchor="middle">P</text></g><g id="icon-32" class="tsd-no-select"><rect fill="var(--color-icon-background)" stroke="var(--color-ts-variable)" stroke-width="1.5" x="1" y="1" width="22" height="22" rx="6"></rect><text fill="var(--color-icon-text)" x="50%" y="50%" dominant-baseline="central" text-anchor="middle">V</text></g><g id="icon-64" class="tsd-no-select"><rect fill="var(--color-icon-background)" stroke="var(--color-ts-function)" stroke-width="1.5" x="1" y="1" width="22" height="22" rx="6"></rect><text fill="var(--color-icon-text)" x="50%" y="50%" dominant-baseline="central" text-anchor="middle">F</text></g><g id="icon-128" class="tsd-no-select"><rect fill="var(--color-icon-background)" stroke="var(--color-ts-class)" stroke-width="1.5" x="1" y="1" width="22" height="22" rx="6"></rect><text fill="var(--color-icon-text)" x="50%" y="50%" dominant-baseline="central" text-anchor="middle">C</text></g><g id="icon-256" class="tsd-no-select"><rect fill="var(--color-icon-background)" stroke="var(--color-ts-interface)" stroke-width="1.5" x="1" y="1" width="22" height="22" rx="6"></rect><text fill="var(--color-icon-text)" x="50%" y="50%" dominant-baseline="central" text-anchor="middle">I</text></g><g id="icon-512" class="tsd-no-select"><rect fill="var(--color-icon-background)" stroke="var(--color-ts-constructor)" stroke-width="1.5" x="1" y="1" width="22" height="22" rx="12"></rect><text fill="var(--color-icon-text)" x="50%" y="50%" dominant-baseline="central" text-anchor="middle">C</text></g><g id="icon-1024" class="tsd-no-select"><rect fill="var(--color-icon-background)" stroke="var(--color-ts-property)" stroke-width="1.5" x="1" y="1" width="22" height="22" rx="12"></rect><text fill="var(--color-icon-text)" x="50%" y="50%" dominant-baseline="central" text-anchor="middle">P</text></g><g id="icon-2048" class="tsd-no-select"><rect fill="var(--color-icon-background)" stroke="var(--color-ts-method)" stroke-width="1.5" x="1" y="1" width="22" height="22" rx="12"></rect><text fill="var(--color-icon-text)" x="50%" y="50%" dominant-baseline="central" text-anchor="middle">M</text></g><g id="icon-4096" class="tsd-no-select"><rect fill="var(--color-icon-background)" stroke="var(--color-ts-function)" stroke-width="1.5" x="1" y="1" width="22" height="22" rx="6"></rect><text fill="var(--color-icon-text)" x="50%" y="50%" dominant-baseline="central" text-anchor="middle">F</text></g><g id="icon-8192" class="tsd-no-select"><rect fill="var(--color-icon-background)" stroke="var(--color-ts-property)" stroke-width="1.5" x="1" y="1" width="22" height="22" rx="12"></rect><text fill="var(--color-icon-text)" x="50%" y="50%" dominant-baseline="central" text-anchor="middle">P</text></g><g id="icon-16384" class="tsd-no-select"><rect fill="var(--color-icon-background)" stroke="var(--color-ts-constructor)" stroke-width="1.5" x="1" y="1" width="22" height="22" rx="12"></rect><text fill="var(--color-icon-text)" x="50%" y="50%" dominant-baseline="central" text-anchor="middle">C</text></g><g id="icon-32768" class="tsd-no-select"><rect fill="var(--color-icon-background)" stroke="var(--color-ts-property)" stroke-width="1.5" x="1" y="1" width="22" height="22" rx="12"></rect><text fill="var(--color-icon-text)" x="50%" y="50%" dominant-baseline="central" text-anchor="middle">P</text></g><g id="icon-65536" class="tsd-no-select"><rect fill="var(--color-icon-background)" stroke="var(--color-ts-type-alias)" stroke-width="1.5" x="1" y="1" width="22" height="22" rx="6"></rect><text fill="var(--color-icon-text)" x="50%" y="50%" dominant-baseline="central" text-anchor="middle">T</text></g><g id="icon-131072" class="tsd-no-select"><rect fill="var(--color-icon-background)" stroke="var(--color-ts-type-alias)" stroke-width="1.5" x="1" y="1" width="22" height="22" rx="6"></rect><text fill="var(--color-icon-text)" x="50%" y="50%" dominant-baseline="central" text-anchor="middle">T</text></g><g id="icon-262144" class="tsd-no-select"><rect fill="var(--color-icon-background)" stroke="var(--color-ts-accessor)" stroke-width="1.5" x="1" y="1" width="22" height="22" rx="12"></rect><text fill="var(--color-icon-text)" x="50%" y="50%" dominant-baseline="central" text-anchor="middle">A</text></g><g id="icon-524288" class="tsd-no-select"><rect fill="var(--color-icon-background)" stroke="var(--color-ts-accessor)" stroke-width="1.5" x="1" y="1" width="22" height="22" rx="12"></rect><text fill="var(--color-icon-text)" x="50%" y="50%" dominant-baseline="central" text-anchor="middle">A</text></g><g id="icon-1048576" class="tsd-no-select"><rect fill="var(--color-icon-background)" stroke="var(--color-ts-accessor)" stroke-width="1.5" x="1" y="1" width="22" height="22" rx="12"></rect><text fill="var(--color-icon-text)" x="50%" y="50%" dominant-baseline="central" text-anchor="middle">A</text></g><g id="icon-2097152" class="tsd-no-select"><rect fill="var(--color-icon-background)" stroke="var(--color-ts-type-alias)" stroke-width="1.5" x="1" y="1" width="22" height="22" rx="6"></rect><text fill="var(--color-icon-text)" x="50%" y="50%" dominant-baseline="central" text-anchor="middle">T</text></g><g id="icon-4194304" class="tsd-no-select"><rect fill="var(--color-icon-background)" stroke="var(--color-ts-reference)" stroke-width="1.5" x="1" y="1" width="22" height="22" rx="12"></rect><text fill="var(--color-icon-text)" x="50%" y="50%" dominant-baseline="central" text-anchor="middle">R</text></g><g id="icon-8388608" class="tsd-no-select"><rect fill="var(--color-icon-background)" stroke="var(--color-document)" stroke-width="1.5" x="1" y="1" width="22" height="22" rx="6"></rect><g stroke="var(--color-icon-text)" fill="none" stroke-width="1.5"><polygon points="6,5 6,19 18,19, 18,10 13,5"></polygon><line x1="9" y1="9" x2="13" y2="9"></line><line x1="9" y1="12" x2="15" y2="12"></line><line x1="9" y1="15" x2="15" y2="15"></line></g></g><g id="icon-folder" class="tsd-no-select"><rect fill="var(--color-icon-background)" stroke="var(--color-document)" stroke-width="1.5" x="1" y="1" width="22" height="22" rx="6"></rect><g stroke="var(--color-icon-text)" fill="none" stroke-width="1.5"><polygon points="5,5 10,5 12,8 19,8 19,18 5,18"></polygon></g></g><g id="icon-chevronDown" class="tsd-no-select"><path d="M4.93896 8.531L12 15.591L19.061 8.531L16.939 6.409L12 11.349L7.06098 6.409L4.93896 8.531Z" fill="var(--color-icon-text)"></path></g><g id="icon-chevronSmall" class="tsd-no-select"><path d="M1.5 5.50969L8 11.6609L14.5 5.50969L12.5466 3.66086L8 7.96494L3.45341 3.66086L1.5 5.50969Z" fill="var(--color-icon-text)"></path></g><g id="icon-checkbox" class="tsd-no-select"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></g><g id="icon-menu" class="tsd-no-select"><rect x="1" y="3" width="14" height="2" fill="var(--color-icon-text)"></rect><rect x="1" y="7" width="14" height="2" fill="var(--color-icon-text)"></rect><rect x="1" y="11" width="14" height="2" fill="var(--color-icon-text)"></rect></g><g id="icon-search" class="tsd-no-select"><path d="M15.7824 13.833L12.6666 10.7177C12.5259 10.5771 12.3353 10.499 12.1353 10.499H11.6259C12.4884 9.39596 13.001 8.00859 13.001 6.49937C13.001 2.90909 10.0914 0 6.50048 0C2.90959 0 0 2.90909 0 6.49937C0 10.0896 2.90959 12.9987 6.50048 12.9987C8.00996 12.9987 9.39756 12.4863 10.5008 11.6239V12.1332C10.5008 12.3332 10.5789 12.5238 10.7195 12.6644L13.8354 15.7797C14.1292 16.0734 14.6042 16.0734 14.8948 15.7797L15.7793 14.8954C16.0731 14.6017 16.0731 14.1267 15.7824 13.833ZM6.50048 10.499C4.29094 10.499 2.50018 8.71165 2.50018 6.49937C2.50018 4.29021 4.28781 2.49976 6.50048 2.49976C8.71001 2.49976 10.5008 4.28708 10.5008 6.49937C10.5008 8.70852 8.71314 10.499 6.50048 10.499Z" fill="var(--color-icon-text)"></path></g><g id="icon-anchor" class="tsd-no-select"><g stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M10 14a3.5 3.5 0 0 0 5 0l4 -4a3.5 3.5 0 0 0 -5 -5l-.5 .5"></path><path d="M14 10a3.5 3.5 0 0 0 -5 0l-4 4a3.5 3.5 0 0 0 5 5l.5 -.5"></path></g></g><g id="icon-alertNote" class="tsd-no-select"><path fill="var(--color-alert-note)" d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"></path></g><g id="icon-alertTip" class="tsd-no-select"><path fill="var(--color-alert-tip)" d="M8 1.5c-2.363 0-4 1.69-4 3.75 0 .984.424 1.625.984 2.304l.214.253c.223.264.47.556.673.848.284.411.537.896.621 1.49a.75.75 0 0 1-1.484.211c-.04-.282-.163-.547-.37-.847a8.456 8.456 0 0 0-.542-.68c-.084-.1-.173-.205-.268-.32C3.201 7.75 2.5 6.766 2.5 5.25 2.5 2.31 4.863 0 8 0s5.5 2.31 5.5 5.25c0 1.516-.701 2.5-1.328 3.259-.095.115-.184.22-.268.319-.207.245-.383.453-.541.681-.208.3-.33.565-.37.847a.751.751 0 0 1-1.485-.212c.084-.593.337-1.078.621-1.489.203-.292.45-.584.673-.848.075-.088.147-.173.213-.253.561-.679.985-1.32.985-2.304 0-2.06-1.637-3.75-4-3.75ZM5.75 12h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1 0-1.5ZM6 15.25a.75.75 0 0 1 .75-.75h2.5a.75.75 0 0 1 0 1.5h-2.5a.75.75 0 0 1-.75-.75Z"></path></g><g id="icon-alertImportant" class="tsd-no-select"><path fill="var(--color-alert-important)" d="M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v9.5A1.75 1.75 0 0 1 14.25 13H8.06l-2.573 2.573A1.458 1.458 0 0 1 3 14.543V13H1.75A1.75 1.75 0 0 1 0 11.25Zm1.75-.25a.25.25 0 0 0-.25.25v9.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h6.5a.25.25 0 0 0 .25-.25v-9.5a.25.25 0 0 0-.25-.25Zm7 2.25v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 9a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path></g><g id="icon-alertWarning" class="tsd-no-select"><path fill="var(--color-alert-warning)" d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path></g><g id="icon-alertCaution" class="tsd-no-select"><path fill="var(--color-alert-caution)" d="M4.47.22A.749.749 0 0 1 5 0h6c.199 0 .389.079.53.22l4.25 4.25c.141.14.22.331.22.53v6a.749.749 0 0 1-.22.53l-4.25 4.25A.749.749 0 0 1 11 16H5a.749.749 0 0 1-.53-.22L.22 11.53A.749.749 0 0 1 0 11V5c0-.199.079-.389.22-.53Zm.84 1.28L1.5 5.31v5.38l3.81 3.81h5.38l3.81-3.81V5.31L10.69 1.5ZM8 4a.75.75 0 0 1 .75.75v3.5a.75.75 0 0 1-1.5 0v-3.5A.75.75 0 0 1 8 4Zm0 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"></path></g>`;
10 | svg.style.display = "none";
11 | if (location.protocol === "file:") updateUseElements();
12 | }
13 |
14 | function updateUseElements() {
15 | document.querySelectorAll("use").forEach((el) => {
16 | if (el.getAttribute("href").includes("#icon-")) {
17 | el.setAttribute("href", el.getAttribute("href").replace(/.*#/, "#"));
18 | }
19 | });
20 | }
21 | })();
22 |
```
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
```yaml
1 | name: Release
2 |
3 | on:
4 | push:
5 | tags:
6 | - "v*.*.*"
7 | workflow_dispatch:
8 | inputs:
9 | version_type:
10 | description: "Version bump type"
11 | required: true
12 | default: "patch"
13 | type: choice
14 | options:
15 | - patch
16 | - minor
17 | - major
18 |
19 | jobs:
20 | test:
21 | name: Pre-release Tests
22 | runs-on: ubuntu-latest
23 |
24 | steps:
25 | - name: Checkout code
26 | uses: actions/checkout@v4
27 |
28 | - name: Setup Node.js
29 | uses: actions/setup-node@v4
30 | with:
31 | node-version: "20.x"
32 | cache: "npm"
33 |
34 | - name: Install dependencies
35 | run: npm ci
36 |
37 | - name: Run full test suite
38 | run: npm test -- --coverage
39 |
40 | - name: Verify 85% coverage threshold
41 | run: |
42 | coverage=$(npm test -- --coverage --silent 2>&1 | grep "All files" | awk '{print $4}' | sed 's/%//')
43 | if (( $(echo "$coverage < 85" | bc -l) )); then
44 | echo "Coverage $coverage% is below 85% threshold"
45 | exit 1
46 | fi
47 | echo "Coverage $coverage% meets requirement (target: 85%)"
48 |
49 | - name: Performance benchmarks
50 | run: npm run test:performance
51 |
52 | - name: Build verification
53 | run: npm run build
54 |
55 | release:
56 | name: Create Release
57 | runs-on: ubuntu-latest
58 | needs: test
59 | permissions:
60 | contents: write
61 | packages: write
62 | id-token: write # Required for OIDC trusted publishing
63 |
64 | steps:
65 | - name: Checkout code
66 | uses: actions/checkout@v4
67 | with:
68 | fetch-depth: 0
69 |
70 | - name: Setup Node.js
71 | uses: actions/setup-node@v4
72 | with:
73 | node-version: "20.x"
74 | cache: "npm"
75 | registry-url: "https://registry.npmjs.org"
76 |
77 | - name: Update npm to latest version
78 | run: npm install -g npm@latest
79 | # npm 11.5.1+ required for trusted publishing (OIDC)
80 |
81 | - name: Install dependencies
82 | run: npm ci
83 |
84 | - name: Build project
85 | run: npm run build
86 |
87 | - name: Validate commit messages
88 | run: |
89 | echo "Validating commit messages follow conventional format..."
90 | if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
91 | # For manual releases, validate commits since last tag
92 | LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
93 | if [ -n "$LAST_TAG" ]; then
94 | npx commitlint --from "$LAST_TAG" --to HEAD --verbose || {
95 | echo "Commit message validation failed"
96 | echo "All commits must follow conventional commit format: type(scope): subject"
97 | exit 1
98 | }
99 | fi
100 | else
101 | # For tag-based releases, validate the tag commit
102 | npx commitlint --from HEAD~1 --to HEAD --verbose || {
103 | echo "Commit message validation failed"
104 | exit 1
105 | }
106 | fi
107 | echo "✅ All commit messages are valid"
108 |
109 | - name: Generate changelog and release
110 | id: release
111 | run: |
112 | git config --local user.email "[email protected]"
113 | git config --local user.name "GitHub Action"
114 |
115 | if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
116 | printf "Manual release triggered with version type: %s\n" "${{ github.event.inputs.version_type }}"
117 |
118 | # Fetch latest changes and ensure we're up to date before creating release
119 | echo "Fetching latest changes from remote..."
120 | git fetch origin main || {
121 | echo "Failed to fetch from remote"
122 | exit 1
123 | }
124 |
125 | # Pull latest changes to ensure we're on the latest commit
126 | # Use rebase to avoid merge commits in release workflow
127 | git pull --rebase origin main || {
128 | echo "Failed to pull latest changes. Remote may have diverged."
129 | echo "Attempting to merge instead..."
130 | git pull origin main || {
131 | echo "Failed to sync with remote repository"
132 | exit 1
133 | }
134 | }
135 |
136 | # Disable husky hooks for automated standard-version commits
137 | # These commits are already validated by CI pipeline
138 | export HUSKY=0
139 | export CI=true
140 | export GITHUB_ACTIONS=true
141 | # Also disable git hooks entirely for standard-version commits
142 | git config core.hooksPath /dev/null || true
143 |
144 | # Run standard-version to generate changelog and bump version
145 | npm run "release:${{ github.event.inputs.version_type }}" || {
146 | echo "standard-version failed"
147 | exit 1
148 | }
149 |
150 | # Restore git hooks path after standard-version
151 | git config --unset core.hooksPath || true
152 |
153 | # Get the new version and changelog
154 | NEW_VERSION=$(node -p "require('./package.json').version")
155 | printf "new_version=v%s\n" "$NEW_VERSION" >> "$GITHUB_OUTPUT"
156 |
157 | # Extract changelog for this version from CHANGELOG.md
158 | if [ -f "CHANGELOG.md" ]; then
159 | # Get changelog section for current version (between ## [version] and next ##)
160 | CHANGELOG_CONTENT=$(awk "/## \[$NEW_VERSION\]/{flag=1; next} /^## \[/{flag=0} flag" CHANGELOG.md | sed '/^$/d' || printf "## Changes\n\nAutomated release %s\n" "$NEW_VERSION")
161 | {
162 | echo "changelog_content<<EOF"
163 | printf "%s\n" "$CHANGELOG_CONTENT"
164 | echo "EOF"
165 | } >> "$GITHUB_OUTPUT"
166 | else
167 | echo "Warning: CHANGELOG.md not found after standard-version"
168 | printf "changelog_content=Automated release v%s\n" "$NEW_VERSION" >> "$GITHUB_OUTPUT"
169 | fi
170 |
171 | # Push the changes (version bump, changelog, and tag)
172 | git push --follow-tags origin main || {
173 | echo "Failed to push changes to repository"
174 | exit 1
175 | }
176 | else
177 | echo "Tag-based release"
178 | tag="${GITHUB_REF#refs/tags/}"
179 | printf "new_version=%s\n" "$tag" >> "$GITHUB_OUTPUT"
180 |
181 | # Extract changelog for tagged version
182 | if [ -f "CHANGELOG.md" ]; then
183 | VERSION_NUM=$(echo "$tag" | sed 's/^v//')
184 | CHANGELOG_CONTENT=$(awk "/## \[$VERSION_NUM\]/{flag=1; next} /^## \[/{flag=0} flag" CHANGELOG.md | sed '/^$/d' || printf "Release %s\n" "$tag")
185 | {
186 | echo "changelog_content<<EOF"
187 | printf "%s\n" "$CHANGELOG_CONTENT"
188 | echo "EOF"
189 | } >> "$GITHUB_OUTPUT"
190 | else
191 | printf "changelog_content=Release %s\n" "$tag" >> "$GITHUB_OUTPUT"
192 | fi
193 | fi
194 |
195 | - name: Create GitHub Release
196 | uses: ncipollo/release-action@v1
197 | with:
198 | token: ${{ secrets.GITHUB_TOKEN }}
199 | tag: ${{ steps.release.outputs.new_version }}
200 | name: Release ${{ steps.release.outputs.new_version }}
201 | body: |
202 | ## DocuMCP Release ${{ steps.release.outputs.new_version }}
203 |
204 | ${{ steps.release.outputs.changelog_content }}
205 |
206 | ### Installation
207 | ```bash
208 | npm install -g documcp@${{ steps.release.outputs.new_version }}
209 | ```
210 |
211 | ### System Requirements
212 | - Node.js 20.x or higher
213 | - npm 9.x or higher
214 |
215 | ### Quick Start
216 | ```bash
217 | # Install globally
218 | npm install -g documcp
219 |
220 | # Use with MCP client
221 | documcp analyze-repository --path ./my-project
222 | ```
223 | draft: false
224 | prerelease: false
225 | skipIfReleaseExists: true
226 | makeLatest: true
227 |
228 | - name: Publish to npm
229 | if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
230 | id: publish
231 | run: |
232 | echo "Publishing to npm using trusted publishing (OIDC)..."
233 |
234 | # Verify npm version supports trusted publishing (11.5.1+ required)
235 | NPM_VERSION=$(npm --version)
236 | echo "npm version: $NPM_VERSION"
237 | # Simple version check: compare major.minor.patch
238 | NPM_MAJOR=$(echo "$NPM_VERSION" | cut -d. -f1)
239 | NPM_MINOR=$(echo "$NPM_VERSION" | cut -d. -f2)
240 | NPM_PATCH=$(echo "$NPM_VERSION" | cut -d. -f3)
241 |
242 | if [ "$NPM_MAJOR" -lt 11 ] || ([ "$NPM_MAJOR" -eq 11 ] && [ "$NPM_MINOR" -lt 5 ]) || ([ "$NPM_MAJOR" -eq 11 ] && [ "$NPM_MINOR" -eq 5 ] && [ "$NPM_PATCH" -lt 1 ]); then
243 | echo "Warning: npm version $NPM_VERSION may not support trusted publishing"
244 | echo "npm 11.5.1+ is required for trusted publishing (OIDC)"
245 | else
246 | echo "✅ npm version $NPM_VERSION supports trusted publishing"
247 | fi
248 |
249 | # Get package version
250 | PACKAGE_VERSION=$(node -p "require('./package.json').version")
251 | echo "Publishing version: $PACKAGE_VERSION"
252 |
253 | # Publish with retry mechanism
254 | # Trusted publishing uses OIDC - no NODE_AUTH_TOKEN needed
255 | MAX_RETRIES=3
256 | RETRY_COUNT=0
257 | PUBLISH_SUCCESS=false
258 |
259 | while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
260 | if npm publish --access public; then
261 | PUBLISH_SUCCESS=true
262 | break
263 | else
264 | RETRY_COUNT=$((RETRY_COUNT + 1))
265 | if [ $RETRY_COUNT -lt $MAX_RETRIES ]; then
266 | echo "Publication attempt $RETRY_COUNT failed, retrying in 5 seconds..."
267 | sleep 5
268 | else
269 | echo "Publication failed after $MAX_RETRIES attempts"
270 | echo ""
271 | echo "Troubleshooting tips:"
272 | echo "1. Verify trusted publisher is configured on npmjs.com"
273 | echo "2. Check that workflow filename matches exactly: release.yml"
274 | echo "3. Ensure repository and organization match npmjs.com configuration"
275 | echo "4. Verify id-token: write permission is set in workflow"
276 | exit 1
277 | fi
278 | fi
279 | done
280 |
281 | if [ "$PUBLISH_SUCCESS" = true ]; then
282 | echo "✅ Successfully published to npm using trusted publishing!"
283 | echo "package_version=$PACKAGE_VERSION" >> "$GITHUB_OUTPUT"
284 | fi
285 |
286 | - name: Verify npm publication
287 | if: steps.publish.outcome == 'success'
288 | run: |
289 | PACKAGE_VERSION="${{ steps.publish.outputs.package_version }}"
290 | echo "Verifying package availability: documcp@$PACKAGE_VERSION"
291 |
292 | # Wait a moment for npm registry to update
293 | sleep 10
294 |
295 | # Verify package exists on npm registry
296 | if npm view "documcp@$PACKAGE_VERSION" version > /dev/null 2>&1; then
297 | echo "✅ Package verification successful: documcp@$PACKAGE_VERSION is available on npm"
298 | npm view "documcp@$PACKAGE_VERSION"
299 | else
300 | echo "❌ Package verification failed: documcp@$PACKAGE_VERSION not found on npm registry"
301 | echo "This may be a temporary registry delay. Please verify manually:"
302 | echo " npm view documcp@$PACKAGE_VERSION"
303 | exit 1
304 | fi
305 |
306 | - name: Test package installation
307 | if: steps.publish.outcome == 'success'
308 | run: |
309 | PACKAGE_VERSION="${{ steps.publish.outputs.package_version }}"
310 | echo "Testing package installation: documcp@$PACKAGE_VERSION"
311 |
312 | # Install the published package globally in a clean environment
313 | npm install -g "documcp@$PACKAGE_VERSION" || {
314 | echo "Package installation test failed"
315 | exit 1
316 | }
317 |
318 | # Verify the installed package works
319 | if command -v documcp > /dev/null 2>&1; then
320 | echo "✅ Package installation successful"
321 | documcp --version || echo "Version command available"
322 | else
323 | echo "❌ Package installation test failed: documcp command not found"
324 | exit 1
325 | fi
326 |
327 | docs:
328 | name: Deploy Documentation
329 | runs-on: ubuntu-latest
330 | needs: [test, release]
331 | permissions:
332 | pages: write
333 | id-token: write
334 |
335 | steps:
336 | - name: Checkout code
337 | uses: actions/checkout@v4
338 |
339 | - name: Setup Node.js
340 | uses: actions/setup-node@v4
341 | with:
342 | node-version: "20.x"
343 | cache: "npm"
344 |
345 | - name: Install dependencies
346 | run: npm ci
347 |
348 | - name: Generate API documentation
349 | run: npm run docs:generate
350 |
351 | - name: Remove problematic media directory
352 | run: rm -rf docs/api/media
353 |
354 | - name: Install Docusaurus dependencies
355 | run: cd docs && npm ci
356 |
357 | - name: Build Docusaurus site
358 | run: cd docs && npm run build
359 | env:
360 | NODE_ENV: production
361 |
362 | - name: Setup Pages
363 | uses: actions/configure-pages@v4
364 |
365 | - name: Upload to GitHub Pages
366 | uses: actions/upload-pages-artifact@v4
367 | with:
368 | path: ./docs/build
369 |
370 | - name: Deploy to GitHub Pages
371 | id: deployment
372 | uses: actions/deploy-pages@v4
373 |
```
--------------------------------------------------------------------------------
/tests/integration/knowledge-graph-workflow.test.ts:
--------------------------------------------------------------------------------
```typescript
1 | /**
2 | * Integration Tests for Knowledge Graph Workflow
3 | * Phase 1: End-to-End KG-Analysis Integration
4 | */
5 |
6 | import { describe, it, expect, beforeEach, afterEach } from "@jest/globals";
7 | import { promises as fs } from "fs";
8 | import { join } from "path";
9 | import { tmpdir } from "os";
10 | import {
11 | initializeKnowledgeGraph,
12 | getKnowledgeGraph,
13 | saveKnowledgeGraph,
14 | createOrUpdateProject,
15 | getProjectContext,
16 | trackDeployment,
17 | getKGStatistics,
18 | } from "../../src/memory/kg-integration.js";
19 |
20 | describe("Knowledge Graph Workflow Integration", () => {
21 | let testDir: string;
22 | let originalEnv: string | undefined;
23 |
24 | beforeEach(async () => {
25 | // Create temporary test directory
26 | testDir = join(tmpdir(), `kg-workflow-test-${Date.now()}`);
27 | await fs.mkdir(testDir, { recursive: true });
28 |
29 | // Set environment variable for storage
30 | originalEnv = process.env.DOCUMCP_STORAGE_DIR;
31 | process.env.DOCUMCP_STORAGE_DIR = testDir;
32 |
33 | // Initialize KG
34 | await initializeKnowledgeGraph(testDir);
35 | });
36 |
37 | afterEach(async () => {
38 | // Restore environment
39 | if (originalEnv) {
40 | process.env.DOCUMCP_STORAGE_DIR = originalEnv;
41 | } else {
42 | delete process.env.DOCUMCP_STORAGE_DIR;
43 | }
44 |
45 | // Clean up test directory
46 | try {
47 | await fs.rm(testDir, { recursive: true, force: true });
48 | } catch (error) {
49 | console.warn("Failed to clean up test directory:", error);
50 | }
51 | });
52 |
53 | describe("Complete Analysis Workflow", () => {
54 | it("should handle first-time project analysis", async () => {
55 | const analysis = {
56 | id: "analysis_001",
57 | timestamp: new Date().toISOString(),
58 | path: "/test/project",
59 | projectName: "Test Project",
60 | structure: {
61 | totalFiles: 100,
62 | totalDirectories: 10,
63 | languages: {
64 | typescript: 60,
65 | javascript: 30,
66 | json: 10,
67 | },
68 | hasTests: true,
69 | hasCI: true,
70 | hasDocs: false,
71 | },
72 | };
73 |
74 | // Create project in KG
75 | const projectNode = await createOrUpdateProject(analysis);
76 |
77 | expect(projectNode).toBeDefined();
78 | expect(projectNode.type).toBe("project");
79 | expect(projectNode.properties.name).toBe("Test Project");
80 | expect(projectNode.properties.analysisCount).toBe(1);
81 |
82 | // Get context (should be empty for first analysis)
83 | const context = await getProjectContext("/test/project");
84 | expect(context.previousAnalyses).toBe(1);
85 | expect(context.knownTechnologies).toContain("typescript");
86 | });
87 |
88 | it("should track returning project with historical context", async () => {
89 | const analysis1 = {
90 | id: "analysis_001",
91 | timestamp: new Date().toISOString(),
92 | path: "/test/project",
93 | projectName: "Test Project",
94 | structure: {
95 | totalFiles: 100,
96 | languages: { typescript: 60, javascript: 40 },
97 | hasTests: true,
98 | hasCI: false,
99 | hasDocs: false,
100 | },
101 | };
102 |
103 | const analysis2 = {
104 | id: "analysis_002",
105 | timestamp: new Date().toISOString(),
106 | path: "/test/project",
107 | projectName: "Test Project",
108 | structure: {
109 | totalFiles: 120,
110 | languages: { typescript: 80, javascript: 40 },
111 | hasTests: true,
112 | hasCI: true,
113 | hasDocs: true,
114 | },
115 | };
116 |
117 | // First analysis
118 | await createOrUpdateProject(analysis1);
119 |
120 | // Second analysis
121 | const projectNode = await createOrUpdateProject(analysis2);
122 |
123 | expect(projectNode.properties.analysisCount).toBe(2);
124 |
125 | // Get context
126 | const context = await getProjectContext("/test/project");
127 | expect(context.previousAnalyses).toBe(2);
128 | expect(context.lastAnalyzed).toBeDefined();
129 | });
130 |
131 | it("should find similar projects based on technologies", async () => {
132 | // Create multiple projects with shared technologies
133 | const project1 = {
134 | id: "analysis_001",
135 | timestamp: new Date().toISOString(),
136 | path: "/test/project1",
137 | projectName: "React App",
138 | structure: {
139 | totalFiles: 50,
140 | languages: { typescript: 30, javascript: 20 },
141 | hasTests: true,
142 | hasCI: false,
143 | hasDocs: false,
144 | },
145 | };
146 |
147 | const project2 = {
148 | id: "analysis_002",
149 | timestamp: new Date().toISOString(),
150 | path: "/test/project2",
151 | projectName: "Another React App",
152 | structure: {
153 | totalFiles: 75,
154 | languages: { typescript: 50, javascript: 25 },
155 | hasTests: true,
156 | hasCI: true,
157 | hasDocs: false,
158 | },
159 | };
160 |
161 | const project3 = {
162 | id: "analysis_003",
163 | timestamp: new Date().toISOString(),
164 | path: "/test/project3",
165 | projectName: "Python Project",
166 | structure: {
167 | totalFiles: 40,
168 | languages: { python: 40 },
169 | hasTests: true,
170 | hasCI: false,
171 | hasDocs: false,
172 | },
173 | };
174 |
175 | // Create all projects
176 | await createOrUpdateProject(project1);
177 | await createOrUpdateProject(project2);
178 | await createOrUpdateProject(project3);
179 |
180 | // Get context for project1
181 | const context = await getProjectContext("/test/project1");
182 |
183 | // Should find project2 as similar (shares typescript/javascript)
184 | // Should not find project3 (uses different stack)
185 | expect(context.similarProjects.length).toBeGreaterThan(0);
186 |
187 | const similarProject = context.similarProjects.find(
188 | (p) => p.properties.name === "Another React App",
189 | );
190 | expect(similarProject).toBeDefined();
191 | });
192 | });
193 |
194 | describe("Deployment Tracking Workflow", () => {
195 | it("should track successful deployment", async () => {
196 | // Create project
197 | const analysis = {
198 | id: "project_001",
199 | timestamp: new Date().toISOString(),
200 | path: "/test/project",
201 | projectName: "Test Project",
202 | structure: {
203 | totalFiles: 50,
204 | languages: { typescript: 50 },
205 | hasTests: true,
206 | hasCI: false,
207 | hasDocs: false,
208 | },
209 | };
210 |
211 | const projectNode = await createOrUpdateProject(analysis);
212 |
213 | // Track successful deployment
214 | await trackDeployment(projectNode.id, "docusaurus", true, {
215 | buildTime: 45,
216 | deploymentUrl: "https://test.github.io",
217 | });
218 |
219 | // Verify deployment was tracked
220 | const kg = await getKnowledgeGraph();
221 | const edges = await kg.findEdges({
222 | source: projectNode.id,
223 | properties: { baseType: "project_deployed_with" },
224 | });
225 |
226 | expect(edges.length).toBeGreaterThan(0);
227 | expect(edges[0].properties.success).toBe(true);
228 | expect(edges[0].properties.buildTime).toBe(45);
229 | });
230 |
231 | it("should track failed deployment", async () => {
232 | const analysis = {
233 | id: "project_002",
234 | timestamp: new Date().toISOString(),
235 | path: "/test/project2",
236 | projectName: "Test Project 2",
237 | structure: {
238 | totalFiles: 50,
239 | languages: { javascript: 50 },
240 | hasTests: false,
241 | hasCI: false,
242 | hasDocs: false,
243 | },
244 | };
245 |
246 | const projectNode = await createOrUpdateProject(analysis);
247 |
248 | // Track failed deployment
249 | await trackDeployment(projectNode.id, "jekyll", false, {
250 | errorMessage: "Ruby version mismatch",
251 | });
252 |
253 | const kg = await getKnowledgeGraph();
254 | const edges = await kg.findEdges({
255 | source: projectNode.id,
256 | properties: { baseType: "project_deployed_with" },
257 | });
258 |
259 | expect(edges.length).toBeGreaterThan(0);
260 | expect(edges[0].properties.success).toBe(false);
261 | expect(edges[0].properties.errorMessage).toContain("Ruby version");
262 | });
263 |
264 | it("should update configuration success rate over time", async () => {
265 | const analysis = {
266 | id: "project_003",
267 | timestamp: new Date().toISOString(),
268 | path: "/test/project3",
269 | projectName: "Test Project 3",
270 | structure: {
271 | totalFiles: 50,
272 | languages: { typescript: 50 },
273 | hasTests: false,
274 | hasCI: false,
275 | hasDocs: false,
276 | },
277 | };
278 |
279 | const projectNode = await createOrUpdateProject(analysis);
280 |
281 | // Track multiple deployments
282 | await trackDeployment(projectNode.id, "hugo", true);
283 | await trackDeployment(projectNode.id, "hugo", true);
284 | await trackDeployment(projectNode.id, "hugo", false);
285 |
286 | const kg = await getKnowledgeGraph();
287 | const configNode = await kg.findNode({
288 | type: "configuration",
289 | properties: { ssg: "hugo" },
290 | });
291 |
292 | expect(configNode).toBeDefined();
293 | expect(configNode!.properties.usageCount).toBe(3);
294 | // Success rate: 2/3 = 0.666...
295 | expect(configNode!.properties.deploymentSuccessRate).toBeCloseTo(
296 | 0.666,
297 | 2,
298 | );
299 | });
300 | });
301 |
302 | describe("Knowledge Graph Statistics", () => {
303 | it("should return accurate statistics", async () => {
304 | // Create multiple projects
305 | for (let i = 0; i < 5; i++) {
306 | const analysis = {
307 | id: `project_00${i}`,
308 | timestamp: new Date().toISOString(),
309 | path: `/test/project${i}`,
310 | projectName: `Project ${i}`,
311 | structure: {
312 | totalFiles: 50,
313 | languages: { typescript: 30, javascript: 20 },
314 | hasTests: true,
315 | hasCI: false,
316 | hasDocs: false,
317 | },
318 | };
319 | await createOrUpdateProject(analysis);
320 | }
321 |
322 | const stats = await getKGStatistics();
323 |
324 | expect(stats.projectCount).toBe(5);
325 | expect(stats.technologyCount).toBeGreaterThan(0);
326 | expect(stats.nodeCount).toBeGreaterThan(5); // Projects + technologies
327 | expect(stats.edgeCount).toBeGreaterThan(0); // project_uses_technology edges
328 | });
329 | });
330 |
331 | describe("Persistence Workflow", () => {
332 | it("should persist data across sessions", async () => {
333 | const analysis = {
334 | id: "persistent_project",
335 | timestamp: new Date().toISOString(),
336 | path: "/test/persistent",
337 | projectName: "Persistent Project",
338 | structure: {
339 | totalFiles: 50,
340 | languages: { typescript: 50 },
341 | hasTests: true,
342 | hasCI: false,
343 | hasDocs: false,
344 | },
345 | };
346 |
347 | // Create project and save
348 | await createOrUpdateProject(analysis);
349 | await saveKnowledgeGraph();
350 |
351 | // Reinitialize (simulating new session)
352 | await initializeKnowledgeGraph(testDir);
353 |
354 | // Verify data was loaded
355 | const context = await getProjectContext("/test/persistent");
356 | expect(context.previousAnalyses).toBe(1);
357 | expect(context.knownTechnologies).toContain("typescript");
358 | });
359 | });
360 |
361 | describe("Complex Multi-Step Workflow", () => {
362 | it("should handle complete project lifecycle", async () => {
363 | // Step 1: Initial analysis
364 | const initialAnalysis = {
365 | id: "lifecycle_project",
366 | timestamp: new Date().toISOString(),
367 | path: "/test/lifecycle",
368 | projectName: "Lifecycle Project",
369 | structure: {
370 | totalFiles: 30,
371 | languages: { javascript: 30 },
372 | hasTests: false,
373 | hasCI: false,
374 | hasDocs: false,
375 | },
376 | };
377 |
378 | const project1 = await createOrUpdateProject(initialAnalysis);
379 | expect(project1.properties.analysisCount).toBe(1);
380 |
381 | // Step 2: Track deployment attempt (failed)
382 | await trackDeployment(project1.id, "jekyll", false, {
383 | errorMessage: "Missing dependencies",
384 | });
385 |
386 | // Step 3: Re-analysis after fixes
387 | const updatedAnalysis = {
388 | ...initialAnalysis,
389 | id: "lifecycle_project_2",
390 | timestamp: new Date().toISOString(),
391 | structure: {
392 | totalFiles: 35,
393 | languages: { javascript: 30, json: 5 },
394 | hasTests: true,
395 | hasCI: true,
396 | hasDocs: true,
397 | },
398 | };
399 |
400 | const project2 = await createOrUpdateProject(updatedAnalysis);
401 | expect(project2.properties.analysisCount).toBe(2);
402 | expect(project2.properties.hasCI).toBe(true);
403 |
404 | // Step 4: Successful deployment
405 | await trackDeployment(project2.id, "eleventy", true, {
406 | buildTime: 30,
407 | deploymentUrl: "https://lifecycle.github.io",
408 | });
409 |
410 | // Verify complete lifecycle
411 | const kg = await getKnowledgeGraph();
412 |
413 | // Check project node
414 | const projectNode = await kg.findNode({
415 | type: "project",
416 | properties: { path: "/test/lifecycle" },
417 | });
418 | expect(projectNode).toBeDefined();
419 | expect(projectNode!.properties.analysisCount).toBe(2);
420 |
421 | // Check deployments
422 | const deployments = await kg.findEdges({
423 | source: projectNode!.id,
424 | properties: { baseType: "project_deployed_with" },
425 | });
426 | expect(deployments).toHaveLength(2);
427 |
428 | // Check technologies
429 | const techEdges = await kg.findEdges({
430 | source: projectNode!.id,
431 | type: "project_uses_technology",
432 | });
433 | expect(techEdges.length).toBeGreaterThan(0);
434 |
435 | // Get final context
436 | const context = await getProjectContext("/test/lifecycle");
437 | expect(context.previousAnalyses).toBe(2);
438 | expect(context.knownTechnologies).toContain("javascript");
439 | });
440 | });
441 | });
442 |
```
--------------------------------------------------------------------------------
/docs/sitemap.xml:
--------------------------------------------------------------------------------
```
1 | <?xml version="1.0" encoding="UTF-8"?>
2 | <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
3 | <url>
4 | <loc>https://tosin2013.github.io/documcp/</loc>
5 | <lastmod>2025-10-01</lastmod>
6 | <changefreq>weekly</changefreq>
7 | <priority>1.0</priority>
8 | </url>
9 | <url>
10 | <loc>https://tosin2013.github.io/documcp/tutorials/</loc>
11 | <lastmod>2025-10-02</lastmod>
12 | <changefreq>monthly</changefreq>
13 | <priority>1.0</priority>
14 | </url>
15 | <url>
16 | <loc>https://tosin2013.github.io/documcp/tutorials/development-setup.html</loc>
17 | <lastmod>2025-10-01</lastmod>
18 | <changefreq>monthly</changefreq>
19 | <priority>1.0</priority>
20 | </url>
21 | <url>
22 | <loc>https://tosin2013.github.io/documcp/tutorials/environment-setup.html</loc>
23 | <lastmod>2025-10-02</lastmod>
24 | <changefreq>monthly</changefreq>
25 | <priority>1.0</priority>
26 | </url>
27 | <url>
28 | <loc>https://tosin2013.github.io/documcp/tutorials/first-deployment.html</loc>
29 | <lastmod>2025-10-01</lastmod>
30 | <changefreq>monthly</changefreq>
31 | <priority>1.0</priority>
32 | </url>
33 | <url>
34 | <loc>https://tosin2013.github.io/documcp/tutorials/getting-started.html</loc>
35 | <lastmod>2025-10-12</lastmod>
36 | <changefreq>monthly</changefreq>
37 | <priority>1.0</priority>
38 | </url>
39 | <url>
40 | <loc>https://tosin2013.github.io/documcp/tutorials/memory-workflows.html</loc>
41 | <lastmod>2025-10-02</lastmod>
42 | <changefreq>monthly</changefreq>
43 | <priority>1.0</priority>
44 | </url>
45 | <url>
46 | <loc>https://tosin2013.github.io/documcp/tutorials/user-onboarding.html</loc>
47 | <lastmod>2025-10-12</lastmod>
48 | <changefreq>monthly</changefreq>
49 | <priority>1.0</priority>
50 | </url>
51 | <url>
52 | <loc>https://tosin2013.github.io/documcp/how-to/</loc>
53 | <lastmod>2025-10-02</lastmod>
54 | <changefreq>monthly</changefreq>
55 | <priority>0.9</priority>
56 | </url>
57 | <url>
58 | <loc>https://tosin2013.github.io/documcp/how-to/analytics-setup.html</loc>
59 | <lastmod>2025-10-02</lastmod>
60 | <changefreq>monthly</changefreq>
61 | <priority>0.9</priority>
62 | </url>
63 | <url>
64 | <loc>https://tosin2013.github.io/documcp/how-to/custom-domains.html</loc>
65 | <lastmod>2025-10-02</lastmod>
66 | <changefreq>monthly</changefreq>
67 | <priority>0.9</priority>
68 | </url>
69 | <url>
70 | <loc>https://tosin2013.github.io/documcp/how-to/github-pages-deployment.html</loc>
71 | <lastmod>2025-10-02</lastmod>
72 | <changefreq>monthly</changefreq>
73 | <priority>0.9</priority>
74 | </url>
75 | <url>
76 | <loc>https://tosin2013.github.io/documcp/how-to/local-testing.html</loc>
77 | <lastmod>2025-10-12</lastmod>
78 | <changefreq>monthly</changefreq>
79 | <priority>0.9</priority>
80 | </url>
81 | <url>
82 | <loc>https://tosin2013.github.io/documcp/how-to/performance-optimization.html</loc>
83 | <lastmod>2025-10-02</lastmod>
84 | <changefreq>monthly</changefreq>
85 | <priority>0.9</priority>
86 | </url>
87 | <url>
88 | <loc>https://tosin2013.github.io/documcp/how-to/prompting-guide.html</loc>
89 | <lastmod>2025-10-12</lastmod>
90 | <changefreq>monthly</changefreq>
91 | <priority>0.9</priority>
92 | </url>
93 | <url>
94 | <loc>https://tosin2013.github.io/documcp/how-to/repository-analysis.html</loc>
95 | <lastmod>2025-09-30</lastmod>
96 | <changefreq>monthly</changefreq>
97 | <priority>0.9</priority>
98 | </url>
99 | <url>
100 | <loc>https://tosin2013.github.io/documcp/how-to/seo-optimization.html</loc>
101 | <lastmod>2025-10-02</lastmod>
102 | <changefreq>monthly</changefreq>
103 | <priority>0.9</priority>
104 | </url>
105 | <url>
106 | <loc>https://tosin2013.github.io/documcp/how-to/site-monitoring.html</loc>
107 | <lastmod>2025-10-02</lastmod>
108 | <changefreq>monthly</changefreq>
109 | <priority>0.9</priority>
110 | </url>
111 | <url>
112 | <loc>https://tosin2013.github.io/documcp/how-to/troubleshooting.html</loc>
113 | <lastmod>2025-10-01</lastmod>
114 | <changefreq>monthly</changefreq>
115 | <priority>0.9</priority>
116 | </url>
117 | <url>
118 | <loc>https://tosin2013.github.io/documcp/how-to/usage-examples.html</loc>
119 | <lastmod>2025-10-02</lastmod>
120 | <changefreq>monthly</changefreq>
121 | <priority>0.9</priority>
122 | </url>
123 | <url>
124 | <loc>https://tosin2013.github.io/documcp/research/domain-1-mcp-architecture/</loc>
125 | <lastmod>2025-10-02</lastmod>
126 | <changefreq>weekly</changefreq>
127 | <priority>0.9</priority>
128 | </url>
129 | <url>
130 | <loc>https://tosin2013.github.io/documcp/research/domain-3-ssg-recommendation/</loc>
131 | <lastmod>2025-10-02</lastmod>
132 | <changefreq>weekly</changefreq>
133 | <priority>0.9</priority>
134 | </url>
135 | <url>
136 | <loc>https://tosin2013.github.io/documcp/research/domain-5-github-deployment/</loc>
137 | <lastmod>2025-10-02</lastmod>
138 | <changefreq>weekly</changefreq>
139 | <priority>0.9</priority>
140 | </url>
141 | <url>
142 | <loc>https://tosin2013.github.io/documcp/adrs/adr-0006-mcp-tools-api-design.html</loc>
143 | <lastmod>2025-10-01</lastmod>
144 | <changefreq>weekly</changefreq>
145 | <priority>0.8</priority>
146 | </url>
147 | <url>
148 | <loc>https://tosin2013.github.io/documcp/api/</loc>
149 | <lastmod>2025-10-12</lastmod>
150 | <changefreq>weekly</changefreq>
151 | <priority>0.8</priority>
152 | </url>
153 | <url>
154 | <loc>https://tosin2013.github.io/documcp/api/hierarchy.html</loc>
155 | <lastmod>2025-10-12</lastmod>
156 | <changefreq>weekly</changefreq>
157 | <priority>0.8</priority>
158 | </url>
159 | <url>
160 | <loc>https://tosin2013.github.io/documcp/api/modules.html</loc>
161 | <lastmod>2025-10-12</lastmod>
162 | <changefreq>weekly</changefreq>
163 | <priority>0.8</priority>
164 | </url>
165 | <url>
166 | <loc>https://tosin2013.github.io/documcp/api/variables/TOOLS.html</loc>
167 | <lastmod>2025-10-12</lastmod>
168 | <changefreq>weekly</changefreq>
169 | <priority>0.8</priority>
170 | </url>
171 | <url>
172 | <loc>https://tosin2013.github.io/documcp/reference/</loc>
173 | <lastmod>2025-10-12</lastmod>
174 | <changefreq>weekly</changefreq>
175 | <priority>0.8</priority>
176 | </url>
177 | <url>
178 | <loc>https://tosin2013.github.io/documcp/reference/api-overview.html</loc>
179 | <lastmod>2025-10-12</lastmod>
180 | <changefreq>weekly</changefreq>
181 | <priority>0.8</priority>
182 | </url>
183 | <url>
184 | <loc>https://tosin2013.github.io/documcp/reference/cli.html</loc>
185 | <lastmod>2025-10-01</lastmod>
186 | <changefreq>weekly</changefreq>
187 | <priority>0.8</priority>
188 | </url>
189 | <url>
190 | <loc>https://tosin2013.github.io/documcp/reference/configuration.html</loc>
191 | <lastmod>2025-10-01</lastmod>
192 | <changefreq>weekly</changefreq>
193 | <priority>0.8</priority>
194 | </url>
195 | <url>
196 | <loc>https://tosin2013.github.io/documcp/reference/mcp-tools.html</loc>
197 | <lastmod>2025-09-30</lastmod>
198 | <changefreq>weekly</changefreq>
199 | <priority>0.8</priority>
200 | </url>
201 | <url>
202 | <loc>https://tosin2013.github.io/documcp/reference/prompt-templates.html</loc>
203 | <lastmod>2025-09-30</lastmod>
204 | <changefreq>weekly</changefreq>
205 | <priority>0.8</priority>
206 | </url>
207 | <url>
208 | <loc>https://tosin2013.github.io/documcp/research/domain-6-api-design/README.html</loc>
209 | <lastmod>2025-10-02</lastmod>
210 | <changefreq>weekly</changefreq>
211 | <priority>0.8</priority>
212 | </url>
213 | <url>
214 | <loc>https://tosin2013.github.io/documcp/explanation/</loc>
215 | <lastmod>2025-10-12</lastmod>
216 | <changefreq>monthly</changefreq>
217 | <priority>0.7</priority>
218 | </url>
219 | <url>
220 | <loc>https://tosin2013.github.io/documcp/explanation/architecture.html</loc>
221 | <lastmod>2025-10-01</lastmod>
222 | <changefreq>monthly</changefreq>
223 | <priority>0.7</priority>
224 | </url>
225 | <url>
226 | <loc>https://tosin2013.github.io/documcp/adrs/adr-0001-mcp-server-architecture.html</loc>
227 | <lastmod>2025-10-01</lastmod>
228 | <changefreq>monthly</changefreq>
229 | <priority>0.5</priority>
230 | </url>
231 | <url>
232 | <loc>https://tosin2013.github.io/documcp/adrs/adr-0002-repository-analysis-engine.html</loc>
233 | <lastmod>2025-10-02</lastmod>
234 | <changefreq>monthly</changefreq>
235 | <priority>0.5</priority>
236 | </url>
237 | <url>
238 | <loc>https://tosin2013.github.io/documcp/adrs/adr-0003-static-site-generator-recommendation-engine.html</loc>
239 | <lastmod>2025-10-02</lastmod>
240 | <changefreq>monthly</changefreq>
241 | <priority>0.5</priority>
242 | </url>
243 | <url>
244 | <loc>https://tosin2013.github.io/documcp/adrs/adr-0004-diataxis-framework-integration.html</loc>
245 | <lastmod>2025-10-02</lastmod>
246 | <changefreq>monthly</changefreq>
247 | <priority>0.5</priority>
248 | </url>
249 | <url>
250 | <loc>https://tosin2013.github.io/documcp/adrs/adr-0005-github-pages-deployment-automation.html</loc>
251 | <lastmod>2025-10-02</lastmod>
252 | <changefreq>monthly</changefreq>
253 | <priority>0.5</priority>
254 | </url>
255 | <url>
256 | <loc>https://tosin2013.github.io/documcp/adrs/adr-0007-mcp-prompts-and-resources-integration.html</loc>
257 | <lastmod>2025-10-02</lastmod>
258 | <changefreq>monthly</changefreq>
259 | <priority>0.5</priority>
260 | </url>
261 | <url>
262 | <loc>https://tosin2013.github.io/documcp/adrs/adr-0008-intelligent-content-population-engine.html</loc>
263 | <lastmod>2025-10-02</lastmod>
264 | <changefreq>monthly</changefreq>
265 | <priority>0.5</priority>
266 | </url>
267 | <url>
268 | <loc>https://tosin2013.github.io/documcp/adrs/adr-0009-content-accuracy-validation-framework.html</loc>
269 | <lastmod>2025-10-02</lastmod>
270 | <changefreq>monthly</changefreq>
271 | <priority>0.5</priority>
272 | </url>
273 | <url>
274 | <loc>https://tosin2013.github.io/documcp/adrs/adr-0010-mcp-resource-pattern-redesign.html</loc>
275 | <lastmod>2025-10-09</lastmod>
276 | <changefreq>monthly</changefreq>
277 | <priority>0.5</priority>
278 | </url>
279 | <url>
280 | <loc>https://tosin2013.github.io/documcp/adrs/adr-0011-ce-mcp-compatibility.html</loc>
281 | <lastmod>2025-10-09</lastmod>
282 | <changefreq>monthly</changefreq>
283 | <priority>0.5</priority>
284 | </url>
285 | <url>
286 | <loc>https://tosin2013.github.io/documcp/adrs/adr-0012-priority-scoring-system-for-documentation-drift.html</loc>
287 | <lastmod>2025-10-09</lastmod>
288 | <changefreq>monthly</changefreq>
289 | <priority>0.5</priority>
290 | </url>
291 | <url>
292 | <loc>https://tosin2013.github.io/documcp/adrs/adr-0013-release-pipeline-and-package-distribution.html</loc>
293 | <lastmod>2025-10-09</lastmod>
294 | <changefreq>monthly</changefreq>
295 | <priority>0.5</priority>
296 | </url>
297 | <url>
298 | <loc>https://tosin2013.github.io/documcp/adrs/README.html</loc>
299 | <lastmod>2025-10-01</lastmod>
300 | <changefreq>monthly</changefreq>
301 | <priority>0.5</priority>
302 | </url>
303 | <url>
304 | <loc>https://tosin2013.github.io/documcp/development/MCP_INSPECTOR_TESTING.html</loc>
305 | <lastmod>2025-10-09</lastmod>
306 | <changefreq>monthly</changefreq>
307 | <priority>0.5</priority>
308 | </url>
309 | <url>
310 | <loc>https://tosin2013.github.io/documcp/guides/link-validation.html</loc>
311 | <lastmod>2025-10-12</lastmod>
312 | <changefreq>monthly</changefreq>
313 | <priority>0.5</priority>
314 | </url>
315 | <url>
316 | <loc>https://tosin2013.github.io/documcp/guides/playwright-integration.html</loc>
317 | <lastmod>2025-10-04</lastmod>
318 | <changefreq>monthly</changefreq>
319 | <priority>0.5</priority>
320 | </url>
321 | <url>
322 | <loc>https://tosin2013.github.io/documcp/guides/playwright-testing-workflow.html</loc>
323 | <lastmod>2025-10-12</lastmod>
324 | <changefreq>monthly</changefreq>
325 | <priority>0.5</priority>
326 | </url>
327 | <url>
328 | <loc>https://tosin2013.github.io/documcp/phase-2-intelligence.html</loc>
329 | <lastmod>2025-10-02</lastmod>
330 | <changefreq>monthly</changefreq>
331 | <priority>0.5</priority>
332 | </url>
333 | <url>
334 | <loc>https://tosin2013.github.io/documcp/research/cross-domain-integration/README.html</loc>
335 | <lastmod>2025-10-02</lastmod>
336 | <changefreq>monthly</changefreq>
337 | <priority>0.5</priority>
338 | </url>
339 | <url>
340 | <loc>https://tosin2013.github.io/documcp/research/domain-1-mcp-architecture/mcp-performance-research.html</loc>
341 | <lastmod>2025-10-01</lastmod>
342 | <changefreq>monthly</changefreq>
343 | <priority>0.5</priority>
344 | </url>
345 | <url>
346 | <loc>https://tosin2013.github.io/documcp/research/domain-2-repository-analysis/README.html</loc>
347 | <lastmod>2025-10-02</lastmod>
348 | <changefreq>monthly</changefreq>
349 | <priority>0.5</priority>
350 | </url>
351 | <url>
352 | <loc>https://tosin2013.github.io/documcp/research/domain-3-ssg-recommendation/ssg-performance-analysis.html</loc>
353 | <lastmod>2025-10-01</lastmod>
354 | <changefreq>monthly</changefreq>
355 | <priority>0.5</priority>
356 | </url>
357 | <url>
358 | <loc>https://tosin2013.github.io/documcp/research/domain-4-diataxis-integration/README.html</loc>
359 | <lastmod>2025-10-02</lastmod>
360 | <changefreq>monthly</changefreq>
361 | <priority>0.5</priority>
362 | </url>
363 | <url>
364 | <loc>https://tosin2013.github.io/documcp/research/domain-5-github-deployment/github-pages-security-analysis.html</loc>
365 | <lastmod>2025-10-01</lastmod>
366 | <changefreq>monthly</changefreq>
367 | <priority>0.5</priority>
368 | </url>
369 | <url>
370 | <loc>https://tosin2013.github.io/documcp/research/README.html</loc>
371 | <lastmod>2025-10-01</lastmod>
372 | <changefreq>monthly</changefreq>
373 | <priority>0.5</priority>
374 | </url>
375 | <url>
376 | <loc>https://tosin2013.github.io/documcp/research/research-integration-summary-2025-01-14.html</loc>
377 | <lastmod>2025-10-01</lastmod>
378 | <changefreq>monthly</changefreq>
379 | <priority>0.5</priority>
380 | </url>
381 | <url>
382 | <loc>https://tosin2013.github.io/documcp/research/research-progress-template.html</loc>
383 | <lastmod>2025-10-01</lastmod>
384 | <changefreq>monthly</changefreq>
385 | <priority>0.5</priority>
386 | </url>
387 | <url>
388 | <loc>https://tosin2013.github.io/documcp/research/research-questions-2025-01-14.html</loc>
389 | <lastmod>2025-10-01</lastmod>
390 | <changefreq>monthly</changefreq>
391 | <priority>0.5</priority>
392 | </url>
393 | </urlset>
394 |
```
--------------------------------------------------------------------------------
/src/memory/user-preferences.ts:
--------------------------------------------------------------------------------
```typescript
1 | /**
2 | * User Preference Management Module
3 | * Phase 2.2: User Preference Learning and Application
4 | *
5 | * Tracks and applies user preferences across DocuMCP operations
6 | */
7 |
8 | import { getKnowledgeGraph, saveKnowledgeGraph } from "./kg-integration.js";
9 | import { GraphNode } from "./knowledge-graph.js";
10 |
11 | export interface UserPreferences {
12 | userId: string;
13 | preferredSSGs: string[];
14 | documentationStyle: "minimal" | "comprehensive" | "tutorial-heavy";
15 | expertiseLevel: "beginner" | "intermediate" | "advanced";
16 | preferredTechnologies: string[];
17 | preferredDiataxisCategories: Array<
18 | "tutorials" | "how-to" | "reference" | "explanation"
19 | >;
20 | autoApplyPreferences: boolean;
21 | lastUpdated: string;
22 | }
23 |
24 | export interface SSGUsageEvent {
25 | ssg: string;
26 | success: boolean;
27 | timestamp: string;
28 | projectType?: string;
29 | }
30 |
31 | /**
32 | * User Preference Manager
33 | * Handles storage, retrieval, and inference of user preferences
34 | */
35 | export class UserPreferenceManager {
36 | private userId: string;
37 | private preferences: UserPreferences | null = null;
38 |
39 | constructor(userId: string = "default") {
40 | this.userId = userId;
41 | }
42 |
43 | /**
44 | * Initialize and load user preferences from knowledge graph
45 | */
46 | async initialize(): Promise<void> {
47 | const kg = await getKnowledgeGraph();
48 |
49 | // Find existing user node
50 | const userNode = await kg.findNode({
51 | type: "user",
52 | properties: { userId: this.userId },
53 | });
54 |
55 | if (userNode) {
56 | this.preferences = {
57 | userId: this.userId,
58 | preferredSSGs: userNode.properties.preferredSSGs || [],
59 | documentationStyle:
60 | userNode.properties.documentationStyle || "comprehensive",
61 | expertiseLevel: userNode.properties.expertiseLevel || "intermediate",
62 | preferredTechnologies: userNode.properties.preferredTechnologies || [],
63 | preferredDiataxisCategories:
64 | userNode.properties.preferredDiataxisCategories || [],
65 | autoApplyPreferences:
66 | userNode.properties.autoApplyPreferences !== false,
67 | lastUpdated: userNode.properties.lastActive || new Date().toISOString(),
68 | };
69 | } else {
70 | // Create default preferences
71 | this.preferences = {
72 | userId: this.userId,
73 | preferredSSGs: [],
74 | documentationStyle: "comprehensive",
75 | expertiseLevel: "intermediate",
76 | preferredTechnologies: [],
77 | preferredDiataxisCategories: [],
78 | autoApplyPreferences: true,
79 | lastUpdated: new Date().toISOString(),
80 | };
81 |
82 | // Store in knowledge graph
83 | await this.save();
84 | }
85 | }
86 |
87 | /**
88 | * Get current user preferences
89 | */
90 | async getPreferences(): Promise<UserPreferences> {
91 | if (!this.preferences) {
92 | await this.initialize();
93 | }
94 | return this.preferences!;
95 | }
96 |
97 | /**
98 | * Update user preferences
99 | */
100 | async updatePreferences(
101 | updates: Partial<Omit<UserPreferences, "userId" | "lastUpdated">>,
102 | ): Promise<UserPreferences> {
103 | if (!this.preferences) {
104 | await this.initialize();
105 | }
106 |
107 | this.preferences = {
108 | ...this.preferences!,
109 | ...updates,
110 | lastUpdated: new Date().toISOString(),
111 | };
112 |
113 | await this.save();
114 | return this.preferences;
115 | }
116 |
117 | /**
118 | * Track SSG usage and infer preferences
119 | */
120 | async trackSSGUsage(event: SSGUsageEvent): Promise<void> {
121 | if (!this.preferences) {
122 | await this.initialize();
123 | }
124 |
125 | const kg = await getKnowledgeGraph();
126 |
127 | // Find user node
128 | const userNodeId = `user:${this.userId}`;
129 | let userNode = await kg.findNode({
130 | type: "user",
131 | properties: { userId: this.userId },
132 | });
133 |
134 | if (!userNode) {
135 | userNode = kg.addNode({
136 | id: userNodeId,
137 | type: "user",
138 | label: this.userId,
139 | properties: {
140 | userId: this.userId,
141 | expertiseLevel: this.preferences!.expertiseLevel,
142 | preferredSSGs: [],
143 | preferredTechnologies: [],
144 | documentationStyle: this.preferences!.documentationStyle,
145 | projectCount: 0,
146 | lastActive: new Date().toISOString(),
147 | createdAt: new Date().toISOString(),
148 | },
149 | weight: 1.0,
150 | });
151 | }
152 |
153 | // Find or create configuration node
154 | const configNodeId = `configuration:${event.ssg}`;
155 | let configNode = await kg.findNode({
156 | type: "configuration",
157 | properties: { ssg: event.ssg },
158 | });
159 |
160 | if (!configNode) {
161 | configNode = kg.addNode({
162 | id: configNodeId,
163 | type: "configuration",
164 | label: `${event.ssg} configuration`,
165 | properties: {
166 | ssg: event.ssg,
167 | settings: {},
168 | deploymentSuccessRate: event.success ? 1.0 : 0.0,
169 | usageCount: 1,
170 | lastUsed: event.timestamp,
171 | },
172 | weight: 1.0,
173 | });
174 | }
175 |
176 | // Create or update preference relationship
177 | const existingEdges = await kg.findEdges({
178 | source: userNode.id,
179 | target: configNode.id,
180 | type: "user_prefers_ssg",
181 | });
182 |
183 | if (existingEdges.length > 0) {
184 | // Update existing preference
185 | const edge = existingEdges[0];
186 | const currentCount = edge.properties.usageCount || 1;
187 | const currentRate = edge.properties.successRate || 0.5;
188 |
189 | edge.properties.usageCount = currentCount + 1;
190 | edge.properties.successRate =
191 | (currentRate * currentCount + (event.success ? 1.0 : 0.0)) /
192 | (currentCount + 1);
193 | edge.properties.lastUsed = event.timestamp;
194 | edge.weight = edge.properties.successRate;
195 | } else {
196 | // Create new preference relationship
197 | kg.addEdge({
198 | source: userNode.id,
199 | target: configNode.id,
200 | type: "user_prefers_ssg",
201 | weight: event.success ? 1.0 : 0.5,
202 | confidence: 1.0,
203 | properties: {
204 | usageCount: 1,
205 | lastUsed: event.timestamp,
206 | successRate: event.success ? 1.0 : 0.0,
207 | },
208 | });
209 | }
210 |
211 | // Update user's preferred SSGs list based on success rate
212 | await this.inferPreferredSSGs();
213 |
214 | await saveKnowledgeGraph();
215 | }
216 |
217 | /**
218 | * Infer preferred SSGs from usage history
219 | */
220 | private async inferPreferredSSGs(): Promise<void> {
221 | if (!this.preferences) {
222 | await this.initialize();
223 | }
224 |
225 | const kg = await getKnowledgeGraph();
226 |
227 | // Find user node
228 | const userNode = await kg.findNode({
229 | type: "user",
230 | properties: { userId: this.userId },
231 | });
232 |
233 | if (!userNode) return;
234 |
235 | // Get all SSG preference edges
236 | const preferenceEdges = await kg.findEdges({
237 | source: userNode.id,
238 | type: "user_prefers_ssg",
239 | });
240 |
241 | // Calculate preference scores (usage count * success rate)
242 | const ssgScores = new Map<string, number>();
243 |
244 | for (const edge of preferenceEdges) {
245 | const configNode = (await kg.getAllNodes()).find(
246 | (n) => n.id === edge.target,
247 | );
248 | if (configNode && configNode.type === "configuration") {
249 | const ssg = configNode.properties.ssg;
250 | const usageCount = edge.properties.usageCount || 1;
251 | const successRate = edge.properties.successRate || 0.5;
252 |
253 | // Score = usage frequency * success rate
254 | const score = usageCount * successRate;
255 | ssgScores.set(ssg, score);
256 | }
257 | }
258 |
259 | // Sort by score and take top 3
260 | const topSSGs = Array.from(ssgScores.entries())
261 | .sort((a, b) => b[1] - a[1])
262 | .slice(0, 3)
263 | .map(([ssg]) => ssg);
264 |
265 | // Update preferences
266 | this.preferences!.preferredSSGs = topSSGs;
267 | this.preferences!.lastUpdated = new Date().toISOString();
268 |
269 | // Update user node
270 | userNode.properties.preferredSSGs = topSSGs;
271 | }
272 |
273 | /**
274 | * Get SSG recommendations based on user preferences
275 | */
276 | async getSSGRecommendations(): Promise<
277 | Array<{ ssg: string; score: number; reason: string }>
278 | > {
279 | if (!this.preferences) {
280 | await this.initialize();
281 | }
282 |
283 | const kg = await getKnowledgeGraph();
284 |
285 | // Find user node
286 | const userNode = await kg.findNode({
287 | type: "user",
288 | properties: { userId: this.userId },
289 | });
290 |
291 | if (!userNode) {
292 | return [];
293 | }
294 |
295 | // Get all SSG preference edges
296 | const preferenceEdges = await kg.findEdges({
297 | source: userNode.id,
298 | type: "user_prefers_ssg",
299 | });
300 |
301 | const recommendations: Array<{
302 | ssg: string;
303 | score: number;
304 | reason: string;
305 | }> = [];
306 |
307 | for (const edge of preferenceEdges) {
308 | const configNode = (await kg.getAllNodes()).find(
309 | (n) => n.id === edge.target,
310 | );
311 |
312 | if (configNode && configNode.type === "configuration") {
313 | const ssg = configNode.properties.ssg;
314 | const usageCount = edge.properties.usageCount || 1;
315 | const successRate = edge.properties.successRate || 0.5;
316 |
317 | // Calculate recommendation score
318 | const score = usageCount * successRate;
319 |
320 | let reason = `Used ${usageCount} time(s)`;
321 | if (successRate >= 0.8) {
322 | reason += `, ${(successRate * 100).toFixed(0)}% success rate`;
323 | } else if (successRate < 0.5) {
324 | reason += `, only ${(successRate * 100).toFixed(0)}% success rate`;
325 | }
326 |
327 | recommendations.push({ ssg, score, reason });
328 | }
329 | }
330 |
331 | return recommendations.sort((a, b) => b.score - a.score);
332 | }
333 |
334 | /**
335 | * Apply user preferences to a recommendation
336 | */
337 | applyPreferencesToRecommendation(
338 | recommendation: string,
339 | alternatives: string[],
340 | ): { recommended: string; adjustmentReason?: string } {
341 | if (!this.preferences || !this.preferences.autoApplyPreferences) {
342 | return { recommended: recommendation };
343 | }
344 |
345 | // Check if user has a strong preference
346 | const preferredSSGs = this.preferences.preferredSSGs;
347 |
348 | if (preferredSSGs.length > 0) {
349 | // If recommended SSG is already in preferences, keep it
350 | if (preferredSSGs.includes(recommendation)) {
351 | return {
352 | recommended: recommendation,
353 | adjustmentReason: "Matches your preferred SSG",
354 | };
355 | }
356 |
357 | // Check if any preferred SSG is in alternatives
358 | for (const preferred of preferredSSGs) {
359 | if (alternatives.includes(preferred)) {
360 | return {
361 | recommended: preferred,
362 | adjustmentReason: `Switched to ${preferred} based on your usage history`,
363 | };
364 | }
365 | }
366 | }
367 |
368 | return { recommended: recommendation };
369 | }
370 |
371 | /**
372 | * Save preferences to knowledge graph
373 | */
374 | private async save(): Promise<void> {
375 | if (!this.preferences) return;
376 |
377 | const kg = await getKnowledgeGraph();
378 |
379 | const userNodeId = `user:${this.userId}`;
380 | const existingNode = await kg.findNode({
381 | type: "user",
382 | properties: { userId: this.userId },
383 | });
384 |
385 | const userNode: GraphNode = {
386 | id: existingNode?.id || userNodeId,
387 | type: "user",
388 | label: this.userId,
389 | properties: {
390 | userId: this.preferences.userId,
391 | expertiseLevel: this.preferences.expertiseLevel,
392 | preferredSSGs: this.preferences.preferredSSGs,
393 | preferredTechnologies: this.preferences.preferredTechnologies,
394 | documentationStyle: this.preferences.documentationStyle,
395 | preferredDiataxisCategories:
396 | this.preferences.preferredDiataxisCategories,
397 | autoApplyPreferences: this.preferences.autoApplyPreferences,
398 | projectCount: existingNode?.properties.projectCount || 0,
399 | lastActive: this.preferences.lastUpdated,
400 | createdAt:
401 | existingNode?.properties.createdAt || this.preferences.lastUpdated,
402 | },
403 | weight: 1.0,
404 | lastUpdated: this.preferences.lastUpdated,
405 | };
406 |
407 | kg.addNode(userNode);
408 | await saveKnowledgeGraph();
409 | }
410 |
411 | /**
412 | * Reset preferences to defaults
413 | */
414 | async resetPreferences(): Promise<UserPreferences> {
415 | this.preferences = {
416 | userId: this.userId,
417 | preferredSSGs: [],
418 | documentationStyle: "comprehensive",
419 | expertiseLevel: "intermediate",
420 | preferredTechnologies: [],
421 | preferredDiataxisCategories: [],
422 | autoApplyPreferences: true,
423 | lastUpdated: new Date().toISOString(),
424 | };
425 |
426 | await this.save();
427 | return this.preferences;
428 | }
429 |
430 | /**
431 | * Export preferences as JSON
432 | */
433 | async exportPreferences(): Promise<string> {
434 | if (!this.preferences) {
435 | await this.initialize();
436 | }
437 | return JSON.stringify(this.preferences, null, 2);
438 | }
439 |
440 | /**
441 | * Import preferences from JSON
442 | */
443 | async importPreferences(json: string): Promise<UserPreferences> {
444 | const imported = JSON.parse(json) as UserPreferences;
445 |
446 | // Validate userId matches
447 | if (imported.userId !== this.userId) {
448 | throw new Error(
449 | `User ID mismatch: expected ${this.userId}, got ${imported.userId}`,
450 | );
451 | }
452 |
453 | this.preferences = {
454 | ...imported,
455 | lastUpdated: new Date().toISOString(),
456 | };
457 |
458 | await this.save();
459 | return this.preferences;
460 | }
461 | }
462 |
463 | /**
464 | * Get or create a user preference manager instance
465 | */
466 | const userPreferenceManagers = new Map<string, UserPreferenceManager>();
467 |
468 | export async function getUserPreferenceManager(
469 | userId: string = "default",
470 | ): Promise<UserPreferenceManager> {
471 | if (!userPreferenceManagers.has(userId)) {
472 | const manager = new UserPreferenceManager(userId);
473 | await manager.initialize();
474 | userPreferenceManagers.set(userId, manager);
475 | }
476 | return userPreferenceManagers.get(userId)!;
477 | }
478 |
479 | /**
480 | * Clear all cached preference managers (for testing)
481 | */
482 | export function clearPreferenceManagerCache(): void {
483 | userPreferenceManagers.clear();
484 | }
485 |
```
--------------------------------------------------------------------------------
/src/workflows/documentation-workflow.ts:
--------------------------------------------------------------------------------
```typescript
1 | // Documentation Workflow Guide for LLMs using DocuMCP MCP Server
2 |
3 | export interface WorkflowStep {
4 | tool: string;
5 | description: string;
6 | requiredInputs: string[];
7 | outputs: string[];
8 | optional: boolean;
9 | alternatives?: string[];
10 | }
11 |
12 | export interface DocumentationWorkflow {
13 | name: string;
14 | description: string;
15 | useCase: string;
16 | steps: WorkflowStep[];
17 | estimatedTime: string;
18 | complexity: "simple" | "moderate" | "complex";
19 | }
20 |
21 | // Primary Documentation Creation Workflows
22 | export const DOCUMENTATION_WORKFLOWS: Record<string, DocumentationWorkflow> = {
23 | // Complete end-to-end documentation setup
24 | "full-documentation-setup": {
25 | name: "Complete Documentation Setup",
26 | description:
27 | "Analyze repository, recommend SSG, create structure, populate content, and deploy",
28 | useCase:
29 | "Starting from scratch with a new project that needs comprehensive documentation",
30 | complexity: "complex",
31 | estimatedTime: "5-10 minutes",
32 | steps: [
33 | {
34 | tool: "analyze_repository",
35 | description:
36 | "Analyze the repository structure, dependencies, and documentation needs",
37 | requiredInputs: ["path"],
38 | outputs: ["analysisId", "projectMetadata", "technologyStack"],
39 | optional: false,
40 | },
41 | {
42 | tool: "recommend_ssg",
43 | description:
44 | "Get intelligent SSG recommendation based on project analysis",
45 | requiredInputs: ["analysisId"],
46 | outputs: ["recommendedSSG", "justification", "alternatives"],
47 | optional: false,
48 | },
49 | {
50 | tool: "generate_config",
51 | description: "Generate configuration files for the recommended SSG",
52 | requiredInputs: ["ssg", "projectName", "outputPath"],
53 | outputs: ["configFiles", "setupInstructions"],
54 | optional: false,
55 | },
56 | {
57 | tool: "setup_structure",
58 | description: "Create Diataxis-compliant documentation structure",
59 | requiredInputs: ["path", "ssg"],
60 | outputs: ["directoryStructure", "templateFiles"],
61 | optional: false,
62 | },
63 | {
64 | tool: "populate_diataxis_content",
65 | description: "Intelligently populate content based on project analysis",
66 | requiredInputs: ["analysisId", "docsPath"],
67 | outputs: ["generatedContent", "populationMetrics"],
68 | optional: false,
69 | },
70 | {
71 | tool: "validate_diataxis_content",
72 | description: "Validate generated content for accuracy and compliance",
73 | requiredInputs: ["contentPath"],
74 | outputs: ["validationResults", "recommendations"],
75 | optional: true,
76 | },
77 | {
78 | tool: "deploy_pages",
79 | description: "Set up GitHub Pages deployment workflow",
80 | requiredInputs: ["repository", "ssg"],
81 | outputs: ["deploymentWorkflow", "deploymentInstructions"],
82 | optional: true,
83 | },
84 | ],
85 | },
86 |
87 | // Quick documentation setup for existing projects
88 | "quick-documentation-setup": {
89 | name: "Quick Documentation Setup",
90 | description: "Rapid documentation creation using intelligent defaults",
91 | useCase:
92 | "Existing project needs documentation quickly with minimal customization",
93 | complexity: "simple",
94 | estimatedTime: "2-3 minutes",
95 | steps: [
96 | {
97 | tool: "analyze_repository",
98 | description: "Quick analysis of repository",
99 | requiredInputs: ["path"],
100 | outputs: ["analysisId"],
101 | optional: false,
102 | },
103 | {
104 | tool: "setup_structure",
105 | description:
106 | "Create documentation structure with intelligent SSG selection",
107 | requiredInputs: ["path"],
108 | outputs: ["directoryStructure"],
109 | optional: false,
110 | alternatives: ["Use analyze_repository output to auto-select SSG"],
111 | },
112 | {
113 | tool: "populate_diataxis_content",
114 | description: "Auto-populate with project-specific content",
115 | requiredInputs: ["analysisId", "docsPath"],
116 | outputs: ["generatedContent"],
117 | optional: false,
118 | },
119 | ],
120 | },
121 |
122 | // Content-focused workflow for existing documentation
123 | "enhance-existing-documentation": {
124 | name: "Enhance Existing Documentation",
125 | description: "Improve and populate existing documentation structure",
126 | useCase:
127 | "Project already has basic documentation that needs content and validation",
128 | complexity: "moderate",
129 | estimatedTime: "3-5 minutes",
130 | steps: [
131 | {
132 | tool: "analyze_repository",
133 | description: "Analyze repository and existing documentation",
134 | requiredInputs: ["path"],
135 | outputs: ["analysisId", "existingDocsAnalysis"],
136 | optional: false,
137 | },
138 | {
139 | tool: "validate_diataxis_content",
140 | description: "Validate existing content and identify gaps",
141 | requiredInputs: ["contentPath", "analysisId"],
142 | outputs: ["validationResults", "contentGaps"],
143 | optional: false,
144 | },
145 | {
146 | tool: "populate_diataxis_content",
147 | description: "Fill content gaps with intelligent population",
148 | requiredInputs: ["analysisId", "docsPath", "preserveExisting: true"],
149 | outputs: ["enhancedContent"],
150 | optional: false,
151 | },
152 | {
153 | tool: "validate_diataxis_content",
154 | description: "Final validation of enhanced content",
155 | requiredInputs: ["contentPath"],
156 | outputs: ["finalValidation"],
157 | optional: true,
158 | },
159 | ],
160 | },
161 |
162 | // Deployment-focused workflow
163 | "deployment-only": {
164 | name: "Documentation Deployment Setup",
165 | description: "Set up deployment for existing documentation",
166 | useCase: "Documentation exists but needs automated deployment setup",
167 | complexity: "simple",
168 | estimatedTime: "1-2 minutes",
169 | steps: [
170 | {
171 | tool: "analyze_repository",
172 | description:
173 | "Analyze repository structure for deployment configuration",
174 | requiredInputs: ["path"],
175 | outputs: ["deploymentContext"],
176 | optional: true,
177 | },
178 | {
179 | tool: "deploy_pages",
180 | description: "Set up GitHub Pages deployment workflow",
181 | requiredInputs: ["repository", "ssg"],
182 | outputs: ["deploymentWorkflow"],
183 | optional: false,
184 | },
185 | {
186 | tool: "verify_deployment",
187 | description: "Verify deployment configuration and test",
188 | requiredInputs: ["repository"],
189 | outputs: ["deploymentStatus", "troubleshootingInfo"],
190 | optional: true,
191 | },
192 | ],
193 | },
194 |
195 | // Validation and quality assurance workflow
196 | "documentation-audit": {
197 | name: "Documentation Quality Audit",
198 | description: "Comprehensive validation and quality assessment",
199 | useCase:
200 | "Existing documentation needs quality assessment and improvement recommendations",
201 | complexity: "moderate",
202 | estimatedTime: "2-3 minutes",
203 | steps: [
204 | {
205 | tool: "analyze_repository",
206 | description: "Analyze repository for context-aware validation",
207 | requiredInputs: ["path"],
208 | outputs: ["analysisId", "projectContext"],
209 | optional: false,
210 | },
211 | {
212 | tool: "validate_diataxis_content",
213 | description: "Comprehensive content validation with all checks",
214 | requiredInputs: [
215 | "contentPath",
216 | "analysisId",
217 | "validationType: all",
218 | "confidence: strict",
219 | ],
220 | outputs: ["detailedValidation", "improvementPlan"],
221 | optional: false,
222 | },
223 | {
224 | tool: "verify_deployment",
225 | description: "Validate deployment if applicable",
226 | requiredInputs: ["repository"],
227 | outputs: ["deploymentHealth"],
228 | optional: true,
229 | },
230 | ],
231 | },
232 | };
233 |
234 | // Workflow Decision Helper
235 | export interface WorkflowRecommendation {
236 | recommendedWorkflow: string;
237 | reason: string;
238 | alternativeWorkflows: string[];
239 | customizationSuggestions: string[];
240 | }
241 |
242 | export function recommendWorkflow(
243 | projectStatus:
244 | | "new"
245 | | "existing-no-docs"
246 | | "existing-basic-docs"
247 | | "existing-full-docs",
248 | requirements: {
249 | needsDeployment?: boolean;
250 | timeConstraint?: "minimal" | "moderate" | "comprehensive";
251 | qualityFocus?: boolean;
252 | customization?: "minimal" | "moderate" | "high";
253 | },
254 | ): WorkflowRecommendation {
255 | // New project or no documentation
256 | if (projectStatus === "new" || projectStatus === "existing-no-docs") {
257 | if (requirements.timeConstraint === "minimal") {
258 | return {
259 | recommendedWorkflow: "quick-documentation-setup",
260 | reason:
261 | "Fast setup with intelligent defaults for time-constrained scenario",
262 | alternativeWorkflows: ["full-documentation-setup"],
263 | customizationSuggestions: [
264 | "Consider full-documentation-setup if time allows for better customization",
265 | "Add deployment-only workflow later if needed",
266 | ],
267 | };
268 | } else {
269 | return {
270 | recommendedWorkflow: "full-documentation-setup",
271 | reason:
272 | "Comprehensive setup provides best foundation for new documentation",
273 | alternativeWorkflows: ["quick-documentation-setup"],
274 | customizationSuggestions: [
275 | "Skip deploy_pages step if deployment not needed immediately",
276 | "Use validate_diataxis_content for quality assurance",
277 | ],
278 | };
279 | }
280 | }
281 |
282 | // Existing documentation that needs enhancement
283 | if (projectStatus === "existing-basic-docs") {
284 | if (requirements.qualityFocus) {
285 | return {
286 | recommendedWorkflow: "documentation-audit",
287 | reason: "Quality-focused validation and improvement recommendations",
288 | alternativeWorkflows: ["enhance-existing-documentation"],
289 | customizationSuggestions: [
290 | "Follow up with enhance-existing-documentation based on audit results",
291 | "Consider deployment-only if deployment setup is needed",
292 | ],
293 | };
294 | } else {
295 | return {
296 | recommendedWorkflow: "enhance-existing-documentation",
297 | reason: "Improve and expand existing documentation content",
298 | alternativeWorkflows: ["documentation-audit"],
299 | customizationSuggestions: [
300 | "Run documentation-audit first if quality is uncertain",
301 | "Set preserveExisting: true in populate_diataxis_content",
302 | ],
303 | };
304 | }
305 | }
306 |
307 | // Full documentation that needs deployment or validation
308 | if (projectStatus === "existing-full-docs") {
309 | if (requirements.needsDeployment) {
310 | return {
311 | recommendedWorkflow: "deployment-only",
312 | reason: "Focus on deployment setup for complete documentation",
313 | alternativeWorkflows: ["documentation-audit"],
314 | customizationSuggestions: [
315 | "Run documentation-audit if quality validation is also needed",
316 | "Consider verify_deployment for troubleshooting",
317 | ],
318 | };
319 | } else {
320 | return {
321 | recommendedWorkflow: "documentation-audit",
322 | reason:
323 | "Quality assurance and validation for existing complete documentation",
324 | alternativeWorkflows: ["deployment-only"],
325 | customizationSuggestions: [
326 | "Focus on validation aspects most relevant to your concerns",
327 | "Use strict confidence level for thorough quality checking",
328 | ],
329 | };
330 | }
331 | }
332 |
333 | // Fallback
334 | return {
335 | recommendedWorkflow: "full-documentation-setup",
336 | reason: "Default comprehensive workflow for unclear requirements",
337 | alternativeWorkflows: ["quick-documentation-setup", "documentation-audit"],
338 | customizationSuggestions: [
339 | "Analyze your specific needs to choose a more targeted workflow",
340 | "Consider running analyze_repository first to understand your project better",
341 | ],
342 | };
343 | }
344 |
345 | // Workflow execution guidance for LLMs
346 | export const WORKFLOW_EXECUTION_GUIDANCE = {
347 | description: "How LLMs should execute DocuMCP workflows",
348 | principles: [
349 | "Each tool can be called independently - workflows are guidance, not rigid requirements",
350 | "Always check tool outputs before proceeding to next step",
351 | "Adapt workflows based on user feedback and tool results",
352 | "Skip optional steps if user has time constraints or different priorities",
353 | "Use tool outputs (like analysisId) as inputs for subsequent tools",
354 | "Validate critical assumptions before proceeding with deployment steps",
355 | ],
356 | errorHandling: [
357 | "If a tool fails, provide clear error information to user",
358 | "Suggest alternative approaches or simplified workflows",
359 | "Don't abandon the entire workflow - adapt and continue with available information",
360 | "Use verify_deployment and validate_diataxis_content for troubleshooting",
361 | ],
362 | customization: [
363 | "Ask users about their priorities (speed vs quality, deployment needs, etc.)",
364 | "Adapt tool parameters based on project analysis results",
365 | "Suggest workflow modifications based on repository characteristics",
366 | "Allow users to skip or modify steps based on their specific needs",
367 | ],
368 | };
369 |
370 | // Export workflow metadata for MCP resource exposure
371 | export const WORKFLOW_METADATA = {
372 | totalWorkflows: Object.keys(DOCUMENTATION_WORKFLOWS).length,
373 | workflowNames: Object.keys(DOCUMENTATION_WORKFLOWS),
374 | complexityLevels: ["simple", "moderate", "complex"],
375 | estimatedTimeRange: "1-10 minutes depending on workflow and project size",
376 | toolsUsed: [
377 | "analyze_repository",
378 | "recommend_ssg",
379 | "generate_config",
380 | "setup_structure",
381 | "populate_diataxis_content",
382 | "validate_diataxis_content",
383 | "deploy_pages",
384 | "verify_deployment",
385 | ],
386 | };
387 |
```
--------------------------------------------------------------------------------
/src/memory/freshness-kg-integration.ts:
--------------------------------------------------------------------------------
```typescript
1 | /**
2 | * Documentation Freshness Knowledge Graph Integration
3 | *
4 | * Provides functions for storing and retrieving documentation freshness
5 | * tracking events in the Knowledge Graph for historical analysis and insights.
6 | */
7 |
8 | import { getKnowledgeGraph, getKGStorage } from "./kg-integration.js";
9 | import type {
10 | DocumentationFreshnessEventEntity,
11 | ProjectHasFreshnessEventRelationship,
12 | } from "./schemas.js";
13 | import type { FreshnessScanReport } from "../utils/freshness-tracker.js";
14 | import crypto from "crypto";
15 |
16 | /**
17 | * Generate a unique ID for a freshness event
18 | */
19 | function generateFreshnessEventId(
20 | projectPath: string,
21 | timestamp: string,
22 | ): string {
23 | const hash = crypto
24 | .createHash("sha256")
25 | .update(`${projectPath}:${timestamp}`)
26 | .digest("hex")
27 | .substring(0, 16);
28 | return `freshness_event:${hash}`;
29 | }
30 |
31 | /**
32 | * Generate a project ID from project path
33 | */
34 | function generateProjectId(projectPath: string): string {
35 | const hash = crypto
36 | .createHash("sha256")
37 | .update(projectPath)
38 | .digest("hex")
39 | .substring(0, 16);
40 | return `project:${hash}`;
41 | }
42 |
43 | /**
44 | * Store a documentation freshness scan event in the Knowledge Graph
45 | */
46 | export async function storeFreshnessEvent(
47 | projectPath: string,
48 | docsPath: string,
49 | report: FreshnessScanReport,
50 | eventType: "scan" | "validation" | "initialization" | "update" = "scan",
51 | ): Promise<string> {
52 | const kg = await getKnowledgeGraph();
53 | const storage = await getKGStorage();
54 |
55 | const timestamp = new Date().toISOString();
56 | const eventId = generateFreshnessEventId(projectPath, timestamp);
57 | const projectId = generateProjectId(projectPath);
58 |
59 | // Calculate average age in days
60 | const filesWithAge = report.files.filter((f) => f.ageInMs !== undefined);
61 | const averageAge =
62 | filesWithAge.length > 0
63 | ? filesWithAge.reduce((sum, f) => sum + (f.ageInMs || 0), 0) /
64 | filesWithAge.length /
65 | (1000 * 60 * 60 * 24)
66 | : undefined;
67 |
68 | // Find oldest file
69 | const oldestFile =
70 | filesWithAge.length > 0
71 | ? filesWithAge.reduce((oldest, current) =>
72 | (current.ageInMs || 0) > (oldest.ageInMs || 0) ? current : oldest,
73 | )
74 | : undefined;
75 |
76 | // Get most stale files (critical and stale)
77 | const mostStaleFiles = report.files
78 | .filter(
79 | (f) => f.stalenessLevel === "critical" || f.stalenessLevel === "stale",
80 | )
81 | .sort((a, b) => (b.ageInMs || 0) - (a.ageInMs || 0))
82 | .slice(0, 10)
83 | .map((f) => f.relativePath);
84 |
85 | // Create freshness event entity
86 | const freshnessEntity: DocumentationFreshnessEventEntity = {
87 | docsPath,
88 | projectPath,
89 | scannedAt: report.scannedAt,
90 | totalFiles: report.totalFiles,
91 | freshFiles: report.freshFiles,
92 | warningFiles: report.warningFiles,
93 | staleFiles: report.staleFiles,
94 | criticalFiles: report.criticalFiles,
95 | filesWithoutMetadata: report.filesWithoutMetadata,
96 | thresholds: report.thresholds,
97 | averageAge,
98 | oldestFile: oldestFile
99 | ? {
100 | path: oldestFile.relativePath,
101 | ageInDays: (oldestFile.ageInMs || 0) / (1000 * 60 * 60 * 24),
102 | }
103 | : undefined,
104 | mostStaleFiles,
105 | eventType,
106 | };
107 |
108 | // Add entity to knowledge graph
109 | kg.addNode({
110 | id: eventId,
111 | type: "documentation_freshness_event",
112 | label: `Freshness Event ${timestamp}`,
113 | properties: freshnessEntity,
114 | weight: 1.0,
115 | });
116 |
117 | // Check if project node exists via async findNode, if not, create a minimal one
118 | const projectNode = await kg.findNode({
119 | type: "project",
120 | properties: { path: projectPath },
121 | });
122 | if (!projectNode) {
123 | kg.addNode({
124 | id: projectId,
125 | type: "project",
126 | label: projectPath.split("/").pop() || "Unknown Project",
127 | properties: {
128 | name: projectPath.split("/").pop() || "Unknown",
129 | path: projectPath,
130 | createdAt: timestamp,
131 | },
132 | weight: 1.0,
133 | });
134 | }
135 |
136 | // Calculate improvement score (0-1, higher is better)
137 | const improvementScore =
138 | report.totalFiles > 0
139 | ? (report.freshFiles +
140 | report.warningFiles * 0.7 +
141 | report.staleFiles * 0.3) /
142 | report.totalFiles
143 | : 1.0;
144 |
145 | // Create relationship between project and freshness event
146 | const relationship: ProjectHasFreshnessEventRelationship = {
147 | type: "project_has_freshness_event",
148 | eventType,
149 | filesScanned: report.totalFiles,
150 | freshFiles: report.freshFiles,
151 | staleFiles: report.staleFiles,
152 | criticalFiles: report.criticalFiles,
153 | filesInitialized: 0, // This will be updated by validation events
154 | filesUpdated: 0, // This will be updated by update events
155 | averageStaleness: averageAge,
156 | improvementScore,
157 | weight: 1.0,
158 | confidence: 1.0,
159 | createdAt: timestamp,
160 | lastUpdated: timestamp,
161 | metadata: {
162 | docsPath,
163 | thresholds: report.thresholds,
164 | },
165 | };
166 |
167 | kg.addEdge({
168 | source: projectId,
169 | target: eventId,
170 | type: "project_has_freshness_event",
171 | weight: 1.0,
172 | confidence: 1.0,
173 | properties: relationship,
174 | });
175 |
176 | // Persist to storage
177 | const nodes = await kg.getAllNodes();
178 | const edges = await kg.getAllEdges();
179 | await storage.saveGraph(nodes, edges);
180 |
181 | return eventId;
182 | }
183 |
184 | /**
185 | * Update a freshness event with validation/update results
186 | */
187 | export async function updateFreshnessEvent(
188 | eventId: string,
189 | updates: {
190 | filesInitialized?: number;
191 | filesUpdated?: number;
192 | eventType?: "scan" | "validation" | "initialization" | "update";
193 | },
194 | ): Promise<void> {
195 | const kg = await getKnowledgeGraph();
196 | const storage = await getKGStorage();
197 |
198 | // Find event node by ID
199 | const eventNode = await kg.getNodeById(eventId);
200 | if (!eventNode) {
201 | throw new Error(`Freshness event not found: ${eventId}`);
202 | }
203 |
204 | // Update entity properties
205 | if (updates.eventType) {
206 | eventNode.properties.eventType = updates.eventType;
207 | }
208 | eventNode.lastUpdated = new Date().toISOString();
209 |
210 | // Find and update the relationship
211 | const relEdges = await kg.findEdges({
212 | target: eventId,
213 | type: "project_has_freshness_event",
214 | });
215 |
216 | for (const edge of relEdges) {
217 | const props = edge.properties as ProjectHasFreshnessEventRelationship;
218 | if (updates.filesInitialized !== undefined) {
219 | props.filesInitialized = updates.filesInitialized;
220 | }
221 | if (updates.filesUpdated !== undefined) {
222 | props.filesUpdated = updates.filesUpdated;
223 | }
224 | if (updates.eventType) {
225 | props.eventType = updates.eventType;
226 | }
227 | edge.lastUpdated = new Date().toISOString();
228 | }
229 |
230 | // Persist to storage
231 | const allNodes = await kg.getAllNodes();
232 | const allEdges = await kg.getAllEdges();
233 | await storage.saveGraph(allNodes, allEdges);
234 | }
235 |
236 | /**
237 | * Get freshness event history for a project
238 | */
239 | export async function getFreshnessHistory(
240 | projectPath: string,
241 | limit: number = 10,
242 | ): Promise<
243 | Array<{
244 | eventId: string;
245 | event: DocumentationFreshnessEventEntity;
246 | relationship: ProjectHasFreshnessEventRelationship;
247 | }>
248 | > {
249 | const kg = await getKnowledgeGraph();
250 | const projectId = generateProjectId(projectPath);
251 |
252 | const edges = await kg.findEdges({
253 | source: projectId,
254 | type: "project_has_freshness_event",
255 | });
256 |
257 | // Sort by timestamp (most recent first)
258 | const sorted = await Promise.all(
259 | edges.map(async (edge) => {
260 | const eventNode = await kg.getNodeById(edge.target);
261 | if (!eventNode || eventNode.type !== "documentation_freshness_event") {
262 | return null;
263 | }
264 |
265 | return {
266 | eventId: edge.target,
267 | event: eventNode.properties as DocumentationFreshnessEventEntity,
268 | relationship: edge.properties as ProjectHasFreshnessEventRelationship,
269 | timestamp: (eventNode.properties as DocumentationFreshnessEventEntity)
270 | .scannedAt,
271 | };
272 | }),
273 | );
274 |
275 | const filtered = sorted
276 | .filter((item): item is NonNullable<typeof item> => item !== null)
277 | .sort(
278 | (a, b) =>
279 | new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime(),
280 | )
281 | .slice(0, limit);
282 |
283 | return filtered.map(({ eventId, event, relationship }) => ({
284 | eventId,
285 | event,
286 | relationship,
287 | }));
288 | }
289 |
290 | /**
291 | * Get staleness insights for a project
292 | */
293 | export async function getStalenessInsights(projectPath: string): Promise<{
294 | totalEvents: number;
295 | averageImprovementScore: number;
296 | trend: "improving" | "declining" | "stable";
297 | currentStatus: {
298 | freshFiles: number;
299 | staleFiles: number;
300 | criticalFiles: number;
301 | totalFiles: number;
302 | } | null;
303 | recommendations: string[];
304 | }> {
305 | const history = await getFreshnessHistory(projectPath, 100);
306 |
307 | if (history.length === 0) {
308 | return {
309 | totalEvents: 0,
310 | averageImprovementScore: 0,
311 | trend: "stable",
312 | currentStatus: null,
313 | recommendations: [
314 | "No freshness tracking history found. Run track_documentation_freshness to begin monitoring.",
315 | ],
316 | };
317 | }
318 |
319 | // Calculate average improvement score
320 | const avgScore =
321 | history.reduce(
322 | (sum, h) => sum + (h.relationship.improvementScore || 0),
323 | 0,
324 | ) / history.length;
325 |
326 | // Determine trend (compare first half to second half)
327 | const midpoint = Math.floor(history.length / 2);
328 | const recentScore =
329 | history
330 | .slice(0, midpoint)
331 | .reduce((sum, h) => sum + (h.relationship.improvementScore || 0), 0) /
332 | Math.max(midpoint, 1);
333 | const olderScore =
334 | history
335 | .slice(midpoint)
336 | .reduce((sum, h) => sum + (h.relationship.improvementScore || 0), 0) /
337 | Math.max(history.length - midpoint, 1);
338 |
339 | let trend: "improving" | "declining" | "stable";
340 | if (recentScore > olderScore + 0.1) {
341 | trend = "improving";
342 | } else if (recentScore < olderScore - 0.1) {
343 | trend = "declining";
344 | } else {
345 | trend = "stable";
346 | }
347 |
348 | // Get current status from most recent event
349 | const latest = history[0];
350 | const currentStatus = {
351 | freshFiles: latest.event.freshFiles,
352 | staleFiles: latest.event.staleFiles,
353 | criticalFiles: latest.event.criticalFiles,
354 | totalFiles: latest.event.totalFiles,
355 | };
356 |
357 | // Generate recommendations
358 | const recommendations: string[] = [];
359 |
360 | if (currentStatus.criticalFiles > 0) {
361 | recommendations.push(
362 | `🔴 ${currentStatus.criticalFiles} files are critically stale and need immediate attention`,
363 | );
364 | }
365 |
366 | if (currentStatus.staleFiles > currentStatus.totalFiles * 0.3) {
367 | recommendations.push(
368 | `🟠 Over 30% of documentation is stale. Consider running validate_documentation_freshness`,
369 | );
370 | }
371 |
372 | if (trend === "declining") {
373 | recommendations.push(
374 | "📉 Documentation freshness is declining. Review update processes and automation",
375 | );
376 | } else if (trend === "improving") {
377 | recommendations.push(
378 | "📈 Documentation freshness is improving. Keep up the good work!",
379 | );
380 | }
381 |
382 | if (latest.event.filesWithoutMetadata > 0) {
383 | recommendations.push(
384 | `⚠️ ${latest.event.filesWithoutMetadata} files lack freshness metadata. Run validate_documentation_freshness with initializeMissing=true`,
385 | );
386 | }
387 |
388 | // Analyze most commonly stale files
389 | const allStaleFiles = history.flatMap((h) => h.event.mostStaleFiles);
390 | const staleFileCounts = new Map<string, number>();
391 | for (const file of allStaleFiles) {
392 | staleFileCounts.set(file, (staleFileCounts.get(file) || 0) + 1);
393 | }
394 |
395 | const chronicallyStale = Array.from(staleFileCounts.entries())
396 | .filter(([_, count]) => count >= Math.min(3, history.length * 0.5))
397 | .map(([file]) => file);
398 |
399 | if (chronicallyStale.length > 0) {
400 | recommendations.push(
401 | `🔄 ${
402 | chronicallyStale.length
403 | } files are chronically stale: ${chronicallyStale
404 | .slice(0, 3)
405 | .join(", ")}${chronicallyStale.length > 3 ? "..." : ""}`,
406 | );
407 | }
408 |
409 | return {
410 | totalEvents: history.length,
411 | averageImprovementScore: avgScore,
412 | trend,
413 | currentStatus,
414 | recommendations,
415 | };
416 | }
417 |
418 | /**
419 | * Compare freshness across similar projects
420 | */
421 | export async function compareFreshnessAcrossProjects(
422 | projectPath: string,
423 | ): Promise<{
424 | currentProject: {
425 | path: string;
426 | improvementScore: number;
427 | };
428 | similarProjects: Array<{
429 | path: string;
430 | improvementScore: number;
431 | similarity: number;
432 | }>;
433 | ranking: number; // 1-based ranking (1 = best)
434 | }> {
435 | const kg = await getKnowledgeGraph();
436 | const projectId = generateProjectId(projectPath);
437 |
438 | // Get current project's latest score
439 | const history = await getFreshnessHistory(projectPath, 1);
440 | const currentScore =
441 | history.length > 0 ? history[0].relationship.improvementScore || 0 : 0;
442 |
443 | // Find similar projects
444 | const similarEdges = await kg.findEdges({
445 | source: projectId,
446 | type: "similar_to",
447 | });
448 |
449 | const similarProjectsPromises = similarEdges.map(async (edge) => {
450 | const similarProjectNode = await kg.getNodeById(edge.target);
451 | if (!similarProjectNode || similarProjectNode.type !== "project") {
452 | return null;
453 | }
454 |
455 | const similarPath = (similarProjectNode.properties as any).path || "";
456 | const similarHistory = await getFreshnessHistory(similarPath, 1);
457 | const similarScore =
458 | similarHistory.length > 0
459 | ? similarHistory[0].relationship.improvementScore || 0
460 | : 0;
461 |
462 | return {
463 | path: similarPath,
464 | improvementScore: similarScore,
465 | similarity: (edge.properties as any).similarityScore || 0,
466 | };
467 | });
468 |
469 | const similarProjects = await Promise.all(similarProjectsPromises);
470 | const validSimilarProjects = similarProjects.filter(
471 | (p): p is NonNullable<typeof p> => p !== null,
472 | );
473 |
474 | // Calculate ranking
475 | const allScores = [
476 | currentScore,
477 | ...validSimilarProjects.map((p) => p.improvementScore),
478 | ];
479 | const sortedScores = [...allScores].sort((a, b) => b - a);
480 | const ranking = sortedScores.indexOf(currentScore) + 1;
481 |
482 | return {
483 | currentProject: {
484 | path: projectPath,
485 | improvementScore: currentScore,
486 | },
487 | similarProjects: validSimilarProjects,
488 | ranking,
489 | };
490 | }
491 |
```
--------------------------------------------------------------------------------
/docs/tutorials/environment-setup.md:
--------------------------------------------------------------------------------
```markdown
1 | ---
2 | documcp:
3 | last_updated: "2025-11-20T00:46:21.971Z"
4 | last_validated: "2025-12-09T19:41:38.602Z"
5 | auto_updated: false
6 | update_frequency: monthly
7 | validated_against_commit: 306567b32114502c606244ad6c2930360bcd4201
8 | ---
9 |
10 | # DocuMCP Environment Setup Guide
11 |
12 | This guide will help you set up DocuMCP in your own environment, from basic installation to advanced configuration for team collaboration.
13 |
14 | ## 🚀 Quick Setup
15 |
16 | ### Prerequisites Check
17 |
18 | Before installing DocuMCP, ensure you have the required software:
19 |
20 | ```bash
21 | # Check Node.js version (requires 20.0.0+)
22 | node --version
23 |
24 | # Check npm version (requires 8.0.0+)
25 | npm --version
26 |
27 | # Check Git version
28 | git --version
29 |
30 | # Check GitHub CLI (optional but recommended)
31 | gh --version
32 | ```
33 |
34 | ### Installation Methods
35 |
36 | #### Method 1: Global Installation (Recommended)
37 |
38 | ```bash
39 | # Install DocuMCP globally
40 | npm install -g documcp
41 |
42 | # Verify installation
43 | documcp --version
44 | # Should output: DocuMCP v0.5.0
45 | ```
46 |
47 | #### Method 2: Local Project Installation
48 |
49 | ```bash
50 | # Navigate to your project directory
51 | cd /path/to/your/project
52 |
53 | # Install DocuMCP as a dev dependency
54 | npm install documcp --save-dev
55 |
56 | # Add to package.json scripts
57 | npm pkg set scripts.docs="documcp"
58 | npm pkg set scripts.docs:analyze="documcp analyze-repository --path ."
59 | npm pkg set scripts.docs:deploy="documcp deploy-pages --repository $(git remote get-url origin | sed 's/.*github.com[:/]\([^.]*\).*/\1/')"
60 | ```
61 |
62 | #### Method 3: Docker Installation
63 |
64 | ```bash
65 | # Pull the official DocuMCP Docker image
66 | docker pull documcp/documcp:latest
67 |
68 | # Run DocuMCP in a container
69 | docker run -it --rm -v $(pwd):/workspace documcp/documcp:latest
70 | ```
71 |
72 | ## 🔧 Basic Configuration
73 |
74 | ### Environment Variables
75 |
76 | Create a `.env` file in your project root:
77 |
78 | ```bash
79 | # DocuMCP Configuration
80 | export DOCUMCP_STORAGE_DIR="./.documcp"
81 | export DOCUMCP_LOG_LEVEL="info"
82 | export DOCUMCP_CACHE_ENABLED="true"
83 |
84 | # GitHub Integration
85 | export GITHUB_TOKEN="your_github_token_here"
86 | export GITHUB_USERNAME="your_username"
87 |
88 | # Optional: Custom configuration
89 | export DOCUMCP_DEFAULT_SSG="docusaurus"
90 | export DOCUMCP_DEFAULT_DEPTH="standard"
91 | ```
92 |
93 | ### Configuration File
94 |
95 | Create a `documcp.config.json` file:
96 |
97 | ```json
98 | {
99 | "storage": {
100 | "directory": "./.documcp",
101 | "enableCache": true,
102 | "maxCacheSize": "100MB"
103 | },
104 | "github": {
105 | "token": "${GITHUB_TOKEN}",
106 | "username": "${GITHUB_USERNAME}",
107 | "defaultBranch": "main"
108 | },
109 | "defaults": {
110 | "ssg": "docusaurus",
111 | "analysisDepth": "standard",
112 | "includeExamples": true,
113 | "targetAudience": "community_contributors"
114 | },
115 | "memory": {
116 | "enableLearning": true,
117 | "retentionDays": 90,
118 | "enableAnalytics": true
119 | }
120 | }
121 | ```
122 |
123 | ## 🏗️ Project Structure Setup
124 |
125 | ### Recommended Project Structure
126 |
127 | ```
128 | your-project/
129 | ├── .documcp/ # DocuMCP storage and cache
130 | │ ├── memory/ # Memory system data
131 | │ ├── cache/ # Analysis cache
132 | │ └── config/ # Local configuration
133 | ├── docs/ # Generated documentation
134 | │ ├── api/ # API documentation
135 | │ ├── tutorials/ # Tutorial content
136 | │ ├── how-to/ # How-to guides
137 | │ ├── reference/ # Reference documentation
138 | │ └── explanation/ # Explanatory content
139 | ├── src/ # Source code
140 | ├── README.md # Project README
141 | ├── documcp.config.json # DocuMCP configuration
142 | ├── .env # Environment variables
143 | └── package.json # Node.js dependencies
144 | ```
145 |
146 | ### Initialize DocuMCP in Your Project
147 |
148 | ```bash
149 | # Initialize DocuMCP in your project
150 | documcp init
151 |
152 | # This creates:
153 | # - .documcp/ directory
154 | # - documcp.config.json
155 | # - .env template
156 | # - .gitignore entries
157 | ```
158 |
159 | ## 🔐 GitHub Integration Setup
160 |
161 | ### GitHub Token Setup
162 |
163 | 1. **Create a GitHub Personal Access Token:**
164 |
165 | Go to GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic)
166 |
167 | Required permissions:
168 |
169 | - `repo` (Full control of private repositories)
170 | - `pages` (Write access to GitHub Pages)
171 | - `workflow` (Update GitHub Action workflows)
172 | - `read:org` (Read organization membership)
173 |
174 | 2. **Set the token in your environment:**
175 |
176 | ```bash
177 | # Add to your shell profile (.bashrc, .zshrc, etc.)
178 | export GITHUB_TOKEN="ghp_your_token_here"
179 |
180 | # Or add to .env file
181 | echo "GITHUB_TOKEN=ghp_your_token_here" >> .env
182 | ```
183 |
184 | 3. **Verify GitHub integration:**
185 |
186 | ```bash
187 | # Test GitHub connection
188 | documcp github test
189 |
190 | # Should output: ✅ GitHub connection successful
191 | ```
192 |
193 | ### GitHub Pages Setup
194 |
195 | 1. **Enable GitHub Pages in your repository:**
196 |
197 | Go to your repository → Settings → Pages
198 |
199 | - Source: GitHub Actions
200 | - Branch: main (or your preferred branch)
201 |
202 | 2. **Configure deployment:**
203 |
204 | ```bash
205 | # Configure GitHub Pages deployment
206 | documcp github configure-pages --repository "username/repository"
207 | ```
208 |
209 | ## 🧠 Memory System Setup
210 |
211 | ### Initialize Memory System
212 |
213 | ```bash
214 | # Initialize memory system with custom storage
215 | documcp memory init --storage-dir ./.documcp/memory
216 |
217 | # Initialize with specific configuration
218 | documcp memory init --storage-dir ./.documcp/memory --enable-learning --retention-days 90
219 | ```
220 |
221 | ### Memory System Configuration
222 |
223 | Create a memory configuration file:
224 |
225 | ```json
226 | {
227 | "storage": {
228 | "directory": "./.documcp/memory",
229 | "enableCompression": true,
230 | "maxSize": "500MB"
231 | },
232 | "learning": {
233 | "enabled": true,
234 | "retentionDays": 90,
235 | "enableAnalytics": true,
236 | "enablePatternRecognition": true
237 | },
238 | "userPreferences": {
239 | "enablePersonalization": true,
240 | "defaultUserId": "developer123"
241 | }
242 | }
243 | ```
244 |
245 | ### Memory System Testing
246 |
247 | ```bash
248 | # Test memory system
249 | documcp memory test
250 |
251 | # Check memory statistics
252 | documcp memory stats
253 |
254 | # Export memories for backup
255 | documcp memory export --format json --output ./documcp-memories-backup.json
256 | ```
257 |
258 | ## 🔧 Advanced Configuration
259 |
260 | ### Custom SSG Configuration
261 |
262 | ```bash
263 | # Configure custom SSG settings
264 | documcp config set --key "ssg.docusaurus.theme" --value "classic"
265 | documcp config set --key "ssg.hugo.baseURL" --value "https://docs.example.com"
266 | documcp config set --key "ssg.mkdocs.theme" --value "material"
267 | ```
268 |
269 | ### User Preferences Setup
270 |
271 | ```bash
272 | # Set user preferences
273 | documcp preferences set --user-id "developer123" --priority performance --ecosystem javascript
274 |
275 | # Set team preferences
276 | documcp preferences set --user-id "team" --priority simplicity --ecosystem any
277 |
278 | # Export preferences
279 | documcp preferences export --user-id "developer123" --output ./preferences.json
280 | ```
281 |
282 | ### Cache Configuration
283 |
284 | ```bash
285 | # Configure caching
286 | documcp cache config --enable --max-size "200MB" --ttl "24h"
287 |
288 | # Clear cache
289 | documcp cache clear
290 |
291 | # Cache statistics
292 | documcp cache stats
293 | ```
294 |
295 | ## 🐳 Docker Setup
296 |
297 | ### Docker Compose Configuration
298 |
299 | Create a `docker-compose.yml` file:
300 |
301 | ```yaml
302 | version: "3.8"
303 |
304 | services:
305 | documcp:
306 | image: documcp/documcp:latest
307 | container_name: documcp
308 | volumes:
309 | - ./:/workspace
310 | - ./documcp-data:/app/.documcp
311 | environment:
312 | - GITHUB_TOKEN=${GITHUB_TOKEN}
313 | - DOCUMCP_STORAGE_DIR=/app/.documcp
314 | working_dir: /workspace
315 | command: ["documcp", "serve", "--port", "3000", "--host", "0.0.0.0"]
316 | ports:
317 | - "3000:3000"
318 | ```
319 |
320 | ### Docker Usage
321 |
322 | ```bash
323 | # Start DocuMCP with Docker Compose
324 | docker-compose up -d
325 |
326 | # Run specific commands
327 | docker-compose exec documcp documcp analyze-repository --path .
328 |
329 | # Stop services
330 | docker-compose down
331 | ```
332 |
333 | ## 🔄 CI/CD Integration
334 |
335 | ### GitHub Actions Setup
336 |
337 | Create `.github/workflows/docs.yml`:
338 |
339 | ```yaml
340 | name: Documentation Deployment
341 |
342 | on:
343 | push:
344 | branches: [main]
345 | paths: ["docs/**", "src/**", "README.md"]
346 | pull_request:
347 | branches: [main]
348 |
349 | jobs:
350 | analyze:
351 | runs-on: ubuntu-latest
352 | steps:
353 | - uses: actions/checkout@v4
354 |
355 | - name: Setup Node.js
356 | uses: actions/setup-node@v4
357 | with:
358 | node-version: "20"
359 |
360 | - name: Install DocuMCP
361 | run: npm install -g documcp
362 |
363 | - name: Analyze Repository
364 | run: |
365 | ANALYSIS_ID=$(documcp analyze-repository --path . --depth standard | jq -r '.data.id')
366 | echo "analysis_id=$ANALYSIS_ID" >> $GITHUB_OUTPUT
367 | id: analyze
368 |
369 | - name: Validate Documentation
370 | run: |
371 | documcp validate-content --docs-path ./docs
372 |
373 | deploy:
374 | needs: analyze
375 | runs-on: ubuntu-latest
376 | if: github.ref == 'refs/heads/main'
377 | steps:
378 | - uses: actions/checkout@v4
379 |
380 | - name: Setup Node.js
381 | uses: actions/setup-node@v4
382 | with:
383 | node-version: "20"
384 |
385 | - name: Install DocuMCP
386 | run: npm install -g documcp
387 |
388 | - name: Deploy Documentation
389 | run: |
390 | documcp deploy-pages --repository ${{ github.repository }} --ssg docusaurus
391 | env:
392 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
393 | ```
394 |
395 | ### GitLab CI Setup
396 |
397 | Create `.gitlab-ci.yml`:
398 |
399 | ```yaml
400 | stages:
401 | - analyze
402 | - deploy
403 |
404 | variables:
405 | NODE_VERSION: "20"
406 |
407 | analyze:
408 | stage: analyze
409 | image: node:${NODE_VERSION}-alpine
410 | before_script:
411 | - npm install -g documcp
412 | script:
413 | - documcp analyze-repository --path . --depth standard
414 | - documcp validate-content --docs-path ./docs
415 | artifacts:
416 | reports:
417 | junit: documcp-results.xml
418 | paths:
419 | - .documcp/
420 | expire_in: 1 hour
421 |
422 | deploy:
423 | stage: deploy
424 | image: node:${NODE_VERSION}-alpine
425 | before_script:
426 | - npm install -g documcp
427 | script:
428 | - documcp deploy-pages --repository $CI_PROJECT_PATH --ssg docusaurus
429 | only:
430 | - main
431 | environment:
432 | name: production
433 | url: https://$CI_PROJECT_NAMESPACE.gitlab.io/$CI_PROJECT_NAME
434 | ```
435 |
436 | ## 🔍 Development Setup
437 |
438 | ### Local Development
439 |
440 | ```bash
441 | # Clone DocuMCP repository
442 | git clone https://github.com/tosin2013/documcp.git
443 | cd documcp
444 |
445 | # Install dependencies
446 | npm install
447 |
448 | # Build the project
449 | npm run build
450 |
451 | # Run in development mode
452 | npm run dev
453 |
454 | # Run tests
455 | npm test
456 |
457 | # Run linting
458 | npm run lint
459 | ```
460 |
461 | ### IDE Configuration
462 |
463 | #### VS Code Configuration
464 |
465 | Create `.vscode/settings.json`:
466 |
467 | ```json
468 | {
469 | "typescript.preferences.importModuleSpecifier": "relative",
470 | "typescript.suggest.autoImports": true,
471 | "editor.formatOnSave": true,
472 | "editor.codeActionsOnSave": {
473 | "source.fixAll.eslint": true
474 | },
475 | "files.associations": {
476 | "*.mcp": "json"
477 | }
478 | }
479 | ```
480 |
481 | #### VS Code Extensions
482 |
483 | Recommended extensions:
484 |
485 | - TypeScript and JavaScript Language Features
486 | - ESLint
487 | - Prettier
488 | - GitLens
489 | - REST Client (for testing API endpoints)
490 |
491 | ## 🧪 Testing Setup
492 |
493 | ### Unit Testing
494 |
495 | ```bash
496 | # Install testing dependencies
497 | npm install --save-dev jest @types/jest ts-jest
498 |
499 | # Create jest.config.js
500 | cat > jest.config.js << EOF
501 | module.exports = {
502 | preset: 'ts-jest',
503 | testEnvironment: 'node',
504 | testMatch: ['**/__tests__/**/*.test.ts'],
505 | collectCoverage: true,
506 | coverageDirectory: 'coverage',
507 | coverageReporters: ['text', 'lcov', 'html']
508 | };
509 | EOF
510 |
511 | # Run tests
512 | npm test
513 | ```
514 |
515 | ### Integration Testing
516 |
517 | ```bash
518 | # Create test repository
519 | mkdir test-repo
520 | cd test-repo
521 | git init
522 | echo "# Test Repository" > README.md
523 | git add README.md
524 | git commit -m "Initial commit"
525 |
526 | # Test DocuMCP with test repository
527 | cd ..
528 | documcp analyze-repository --path ./test-repo --depth quick
529 | ```
530 |
531 | ### Performance Testing
532 |
533 | ```bash
534 | # Run performance benchmarks
535 | documcp benchmark run --repository ./test-repo --iterations 10
536 |
537 | # Check performance metrics
538 | documcp benchmark current
539 | ```
540 |
541 | ## 🔧 Troubleshooting
542 |
543 | ### Common Issues
544 |
545 | #### Issue 1: Permission Denied
546 |
547 | **Problem:** `Permission denied: Cannot read directory`
548 |
549 | **Solution:**
550 |
551 | ```bash
552 | # Check permissions
553 | ls -la /path/to/repository
554 |
555 | # Fix permissions
556 | chmod -R 755 /path/to/repository
557 |
558 | # Or run with sudo (not recommended for production)
559 | sudo documcp analyze-repository --path /path/to/repository
560 | ```
561 |
562 | #### Issue 2: GitHub Token Invalid
563 |
564 | **Problem:** `GitHub authentication failed`
565 |
566 | **Solution:**
567 |
568 | ```bash
569 | # Check token validity
570 | curl -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/user
571 |
572 | # Regenerate token with correct permissions
573 | # Go to GitHub → Settings → Developer settings → Personal access tokens
574 |
575 | # Update environment variable
576 | export GITHUB_TOKEN="new_token_here"
577 | ```
578 |
579 | #### Issue 3: Memory System Errors
580 |
581 | **Problem:** `Memory system initialization failed`
582 |
583 | **Solution:**
584 |
585 | ```bash
586 | # Clear memory storage
587 | rm -rf ./.documcp/memory
588 |
589 | # Reinitialize memory system
590 | documcp memory init --storage-dir ./.documcp/memory
591 |
592 | # Check memory system status
593 | documcp memory status
594 | ```
595 |
596 | #### Issue 4: Build Failures
597 |
598 | **Problem:** `Documentation build failed`
599 |
600 | **Solution:**
601 |
602 | ```bash
603 | # Check for syntax errors
604 | documcp validate-content --docs-path ./docs
605 |
606 | # Test local build
607 | documcp test-local --docs-path ./docs --ssg docusaurus
608 |
609 | # Check SSG configuration
610 | cat ./docs/docusaurus.config.js
611 | ```
612 |
613 | ### Debug Mode
614 |
615 | ```bash
616 | # Enable debug logging
617 | export DOCUMCP_LOG_LEVEL="debug"
618 |
619 | # Run with verbose output
620 | documcp analyze-repository --path . --depth standard --verbose
621 |
622 | # Check logs
623 | tail -f ./.documcp/logs/documcp.log
624 | ```
625 |
626 | ### Health Check
627 |
628 | ```bash
629 | # Run comprehensive health check
630 | documcp health-check
631 |
632 | # Should output:
633 | # ✅ Node.js version: v20.0.0
634 | # ✅ npm version: 8.0.0
635 | # ✅ Git version: 2.30.0
636 | # ✅ GitHub token: valid
637 | # ✅ Memory system: healthy
638 | # ✅ Cache system: healthy
639 | ```
640 |
641 | ## 📚 Next Steps
642 |
643 | After completing the environment setup:
644 |
645 | 1. **Read the [User Onboarding Guide](./user-onboarding.md)** for usage patterns
646 | 2. **Explore [Usage Examples](../how-to/usage-examples.md)** for practical examples
647 | 3. **Check the [API Reference](../api/)** for complete function documentation
648 | 4. **Join the [GitHub Issues](https://github.com/tosin2013/documcp/issues)** for community support and feature requests
649 |
650 | ## 🆘 Getting Help
651 |
652 | - **Documentation**: Check the comprehensive documentation
653 | - **GitHub Issues**: Report bugs and request features
654 | - **GitHub Discussions**: Ask questions and share ideas
655 | - **Community**: Join the DocuMCP community for support
656 |
657 | Your DocuMCP environment is now ready! 🎉
658 |
```
--------------------------------------------------------------------------------
/docs/how-to/troubleshooting.md:
--------------------------------------------------------------------------------
```markdown
1 | ---
2 | documcp:
3 | last_updated: "2025-11-20T00:46:21.956Z"
4 | last_validated: "2025-12-09T19:41:38.587Z"
5 | auto_updated: false
6 | update_frequency: monthly
7 | validated_against_commit: 306567b32114502c606244ad6c2930360bcd4201
8 | ---
9 |
10 | # Troubleshooting Common Issues
11 |
12 | This guide helps you diagnose and fix common problems when using DocuMCP for documentation deployment.
13 |
14 | ## Quick Diagnostic Commands
15 |
16 | Use these DocuMCP prompts for immediate diagnosis:
17 |
18 | ```bash
19 | # General troubleshooting
20 | "diagnose issues with my documentation deployment"
21 |
22 | # Specific verification
23 | "verify my GitHub Pages deployment and identify any problems"
24 |
25 | # Link validation
26 | "check all my documentation links for broken references"
27 |
28 | # Content validation
29 | "validate my documentation content for errors and inconsistencies"
30 | ```
31 |
32 | ## Repository Analysis Issues
33 |
34 | ### Problem: Analysis Returns Empty or Incomplete Results
35 |
36 | **Symptoms:**
37 |
38 | - Analysis shows 0 files or minimal structure
39 | - Missing language detection
40 | - No dependency information
41 |
42 | **Solutions:**
43 |
44 | 1. **Check directory permissions:**
45 |
46 | ```bash
47 | ls -la /path/to/your/repository
48 | # Ensure read permissions exist
49 | ```
50 |
51 | 2. **Verify Git repository:**
52 |
53 | ```bash
54 | git status
55 | # Must be in a valid Git repository
56 | ```
57 |
58 | 3. **Use deeper analysis:**
59 |
60 | ```bash
61 | "analyze my repository with deep analysis to get comprehensive results"
62 | ```
63 |
64 | 4. **Check for hidden files:**
65 |
66 | ```bash
67 | # Include hidden files in analysis
68 | ls -la
69 | # Look for .gitignore excluding important files
70 | ```
71 |
72 | ### Problem: Wrong Project Type Detection
73 |
74 | **Symptoms:**
75 |
76 | - Library detected as application
77 | - Wrong primary language
78 | - Incorrect team size estimation
79 |
80 | **Solutions:**
81 |
82 | 1. **Provide more context:**
83 |
84 | ```bash
85 | "analyze my TypeScript library project with focus on API documentation"
86 | ```
87 |
88 | 2. **Check file extensions:**
89 |
90 | ```bash
91 | # Ensure your main files have correct extensions
92 | find . -name "*.ts" -o -name "*.js" -o -name "*.py" | head -20
93 | ```
94 |
95 | 3. **Update package.json:**
96 |
97 | ```json
98 | {
99 | "type": "module",
100 | "main": "dist/index.js",
101 | "types": "dist/index.d.ts",
102 | "keywords": ["library", "typescript", "api"]
103 | }
104 | ```
105 |
106 | ## Static Site Generator Recommendation Issues
107 |
108 | ### Problem: No Recommendations or Low Confidence Scores
109 |
110 | **Symptoms:**
111 |
112 | - Empty recommendation list
113 | - All SSGs have similar low scores
114 | - Recommendation doesn't match project needs
115 |
116 | **Solutions:**
117 |
118 | 1. **Provide preferences:**
119 |
120 | ```bash
121 | "recommend SSG for my project with preferences for JavaScript ecosystem and feature-rich capabilities"
122 | ```
123 |
124 | 2. **Re-analyze with specific focus:**
125 |
126 | ```bash
127 | "analyze my repository focusing on documentation needs and complexity"
128 | ```
129 |
130 | 3. **Check project characteristics:**
131 |
132 | - Ensure sufficient code files exist
133 | - Verify dependencies are in package.json/requirements.txt
134 | - Add README with project description
135 |
136 | ### Problem: Recommended SSG Doesn't Match Expectations
137 |
138 | **Symptoms:**
139 |
140 | - Hugo recommended for React project
141 | - MkDocs suggested for JavaScript library
142 | - Jekyll proposed for Python project
143 |
144 | **Solutions:**
145 |
146 | 1. **Specify ecosystem preference:**
147 |
148 | ```bash
149 | "recommend SSG for my project with JavaScript ecosystem preference"
150 | ```
151 |
152 | 2. **Review analysis results:**
153 |
154 | ```bash
155 | "explain why you recommended Hugo instead of Docusaurus for my React project"
156 | ```
157 |
158 | 3. **Override with specific request:**
159 |
160 | ```bash
161 | "generate Docusaurus configuration for my project despite the Hugo recommendation"
162 | ```
163 |
164 | ## Configuration Generation Issues
165 |
166 | ### Problem: Configuration Files Not Created
167 |
168 | **Symptoms:**
169 |
170 | - No config files generated
171 | - Empty configuration
172 | - Missing dependencies
173 |
174 | **Solutions:**
175 |
176 | 1. **Check output path:**
177 |
178 | ```bash
179 | # Ensure output path exists and is writable
180 | mkdir -p ./docs
181 | chmod 755 ./docs
182 | ```
183 |
184 | 2. **Specify absolute path:**
185 |
186 | ```bash
187 | "generate Hugo configuration files at /full/path/to/project"
188 | ```
189 |
190 | 3. **Check project name format:**
191 |
192 | ```bash
193 | # Avoid special characters in project names
194 | "generate config for project 'My-Simple-Docs' not 'My Project (v2.0)'"
195 | ```
196 |
197 | ### Problem: Invalid Configuration Generated
198 |
199 | **Symptoms:**
200 |
201 | - Build fails with config errors
202 | - Missing required fields
203 | - Wrong file format
204 |
205 | **Solutions:**
206 |
207 | 1. **Validate generated config:**
208 |
209 | ```bash
210 | # For Docusaurus
211 | npm run docusaurus --version
212 |
213 | # For Hugo
214 | hugo version && hugo config
215 |
216 | # For MkDocs
217 | mkdocs --version && mkdocs build --strict
218 | ```
219 |
220 | 2. **Regenerate with project details:**
221 |
222 | ```bash
223 | "generate detailed Hugo configuration with custom theme and GitHub integration"
224 | ```
225 |
226 | 3. **Fix common issues:**
227 |
228 | **Docusaurus baseUrl fix:**
229 |
230 | ```javascript
231 | // Fix in docusaurus.config.js
232 | const config = {
233 | baseUrl: "/your-repo-name/", // Must match repository name
234 | url: "https://yourusername.github.io",
235 | };
236 | ```
237 |
238 | **Hugo baseURL fix:**
239 |
240 | ```yaml
241 | # Fix in config.yml
242 | baseURL: "https://yourusername.github.io/your-repo-name/"
243 | ```
244 |
245 | ## Documentation Structure Issues
246 |
247 | ### Problem: Diataxis Structure Not Created
248 |
249 | **Symptoms:**
250 |
251 | - Missing directories
252 | - Empty folders
253 | - No example content
254 |
255 | **Solutions:**
256 |
257 | 1. **Check path permissions:**
258 |
259 | ```bash
260 | ls -ld /path/to/docs
261 | # Ensure write permissions
262 | ```
263 |
264 | 2. **Use absolute path:**
265 |
266 | ```bash
267 | "set up Diataxis structure at /absolute/path/to/docs"
268 | ```
269 |
270 | 3. **Force recreation:**
271 |
272 | ```bash
273 | "recreate documentation structure with examples for my SSG"
274 | ```
275 |
276 | ### Problem: Content Population Fails
277 |
278 | **Symptoms:**
279 |
280 | - Empty documentation files
281 | - Generic content only
282 | - Missing project-specific information
283 |
284 | **Solutions:**
285 |
286 | 1. **Provide analysis context:**
287 |
288 | ```bash
289 | "populate documentation using analysis ID analysis_abc123 with comprehensive content"
290 | ```
291 |
292 | 2. **Specify technology focus:**
293 |
294 | ```bash
295 | "populate docs focusing on TypeScript, React, and API documentation"
296 | ```
297 |
298 | 3. **Check source code structure:**
299 |
300 | ```bash
301 | # Ensure code has discoverable patterns
302 | find . -name "*.ts" -exec grep -l "export" {} \;
303 | ```
304 |
305 | ## GitHub Pages Deployment Issues
306 |
307 | ### Problem: Deployment Workflow Fails
308 |
309 | **Symptoms:**
310 |
311 | - GitHub Actions shows red X
312 | - Build fails with errors
313 | - Deployment never completes
314 |
315 | **Solutions:**
316 |
317 | 1. **Check workflow logs:**
318 |
319 | - Go to Actions tab in GitHub
320 | - Click on failed workflow
321 | - Review step-by-step logs
322 |
323 | 2. **Common fixes:**
324 |
325 | **Node.js version mismatch:**
326 |
327 | ```yaml
328 | # Fix in .github/workflows/deploy.yml
329 | - name: Setup Node.js
330 | uses: actions/setup-node@v4
331 | with:
332 | node-version: "20" # Match your local version
333 | ```
334 |
335 | **Missing dependencies:**
336 |
337 | ```json
338 | # Ensure all dependencies in package.json
339 | {
340 | "dependencies": {
341 | "@docusaurus/core": "^3.0.0",
342 | "@docusaurus/preset-classic": "^3.0.0"
343 | }
344 | }
345 | ```
346 |
347 | **Build command issues:**
348 |
349 | ```yaml
350 | # Fix build command
351 | - name: Build
352 | run: npm run build # Ensure this command exists in package.json
353 | ```
354 |
355 | ### Problem: Site Shows 404 Error
356 |
357 | **Symptoms:**
358 |
359 | - GitHub Pages URL returns 404
360 | - Site deployed but not accessible
361 | - Some pages work, others don't
362 |
363 | **Solutions:**
364 |
365 | 1. **Check GitHub Pages settings:**
366 |
367 | - Repository Settings > Pages
368 | - Source should be "GitHub Actions"
369 | - Custom domain configured correctly (if used)
370 |
371 | 2. **Fix baseURL configuration:**
372 |
373 | **Docusaurus:**
374 |
375 | ```javascript
376 | const config = {
377 | baseUrl: "/repository-name/", // Must match your repo name exactly
378 | url: "https://username.github.io",
379 | };
380 | ```
381 |
382 | **Hugo:**
383 |
384 | ```yaml
385 | baseURL: "https://username.github.io/repository-name/"
386 | ```
387 |
388 | **MkDocs:**
389 |
390 | ```yaml
391 | site_url: "https://username.github.io/repository-name/"
392 | ```
393 |
394 | 3. **Check file naming:**
395 |
396 | ```bash
397 | # Ensure index.html or index.md exists
398 | ls docs/index.*
399 | ```
400 |
401 | ### Problem: Assets Not Loading (CSS/JS/Images)
402 |
403 | **Symptoms:**
404 |
405 | - Site loads but no styling
406 | - Images show as broken
407 | - JavaScript functionality missing
408 |
409 | **Solutions:**
410 |
411 | 1. **Check asset paths:**
412 |
413 | ```javascript
414 | // Use relative paths
415 | <img src="./images/logo.png" /> // Good
416 | <img src="/images/logo.png" /> // May fail
417 | ```
418 |
419 | 2. **Configure public path:**
420 |
421 | **Docusaurus:**
422 |
423 | ```javascript
424 | const config = {
425 | baseUrl: "/repo-name/",
426 | staticDirectories: ["static"],
427 | };
428 | ```
429 |
430 | **Hugo:**
431 |
432 | ```yaml
433 | # In config.yml
434 | baseURL: "https://username.github.io/repo-name/"
435 | canonifyURLs: true
436 | ```
437 |
438 | 3. **Verify asset directories:**
439 |
440 | ```bash
441 | # Check assets exist in build output
442 | ls -la build/assets/ # Docusaurus
443 | ls -la public/css/ # Hugo
444 | ls -la site/css/ # MkDocs
445 | ```
446 |
447 | ## Content Validation Issues
448 |
449 | ### Problem: Link Validation Shows False Positives
450 |
451 | **Symptoms:**
452 |
453 | - Valid links reported as broken
454 | - External links fail intermittently
455 | - Anchor links not found
456 |
457 | **Solutions:**
458 |
459 | 1. **Configure link checking:**
460 |
461 | ```bash
462 | "check documentation links with timeout of 10 seconds and ignore external domains github.com"
463 | ```
464 |
465 | 2. **Check anchor links:**
466 |
467 | ```markdown
468 | <!-- Ensure anchors exist -->
469 |
470 | ## My Section
471 |
472 | Link to [My Section](#my-section) <!-- Correct -->
473 | Link to [My Section](#my_section) <!-- May fail -->
474 | ```
475 |
476 | 3. **Handle external link timeouts:**
477 |
478 | ```bash
479 | "validate content with longer timeout for external links and retry failed checks"
480 | ```
481 |
482 | ### Problem: Code Block Validation Fails
483 |
484 | **Symptoms:**
485 |
486 | - Valid code marked as invalid
487 | - Syntax highlighting not working
488 | - Code examples cause build failures
489 |
490 | **Solutions:**
491 |
492 | 1. **Check language tags:**
493 |
494 | ````markdown
495 | <!-- Correct -->
496 |
497 | ```javascript
498 | const example = "Hello World";
499 | ```
500 | ````
501 |
502 | <!-- Incorrect - missing language -->
503 |
504 | ```
505 | const example = "Hello World";
506 | ```
507 |
508 | ````
509 |
510 | 2. **Validate code syntax:**
511 | ```bash
512 | # Test code blocks separately
513 | node -e "const example = 'Hello World'; console.log(example);"
514 | ````
515 |
516 | 3. **Configure code validation:**
517 |
518 | ```bash
519 | "validate content with permissive code validation and syntax checking disabled"
520 | ```
521 |
522 | ## Memory System Issues
523 |
524 | ### Problem: Memory System Not Initializing
525 |
526 | **Symptoms:**
527 |
528 | - Memory tools return errors
529 | - No historical data available
530 | - Analysis doesn't include insights
531 |
532 | **Solutions:**
533 |
534 | 1. **Check storage directory:**
535 |
536 | ```bash
537 | ls -la .documcp/memory/
538 | # Should contain analysis files
539 | ```
540 |
541 | 2. **Initialize manually:**
542 |
543 | ```bash
544 | "recall all memories to initialize the memory system"
545 | ```
546 |
547 | 3. **Check permissions:**
548 |
549 | ```bash
550 | chmod -R 755 .documcp/
551 | ```
552 |
553 | ### Problem: Similar Projects Not Found
554 |
555 | **Symptoms:**
556 |
557 | - No similar projects in results
558 | - Low-quality recommendations
559 | - Missing historical patterns
560 |
561 | **Solutions:**
562 |
563 | 1. **Build memory with more analyses:**
564 |
565 | ```bash
566 | "analyze multiple repositories to build memory patterns"
567 | ```
568 |
569 | 2. **Export and import memory:**
570 |
571 | ```bash
572 | "export memories in JSON format for backup"
573 | ```
574 |
575 | 3. **Clean and rebuild:**
576 |
577 | ```bash
578 | "cleanup old memories and rebuild with recent analyses"
579 | ```
580 |
581 | ## Performance Issues
582 |
583 | ### Problem: Slow Build Times
584 |
585 | **Symptoms:**
586 |
587 | - Builds take too long
588 | - GitHub Actions timeout
589 | - Local development is slow
590 |
591 | **Solutions:**
592 |
593 | 1. **Optimize build configuration:**
594 |
595 | **Docusaurus:**
596 |
597 | ```javascript
598 | const config = {
599 | future: {
600 | experimental_faster: true,
601 | },
602 | webpack: {
603 | jsLoader: (isServer) => ({
604 | loader: "esbuild-loader",
605 | options: {
606 | loader: "tsx",
607 | target: isServer ? "node12" : "es2017",
608 | },
609 | }),
610 | },
611 | };
612 | ```
613 |
614 | **Hugo:**
615 |
616 | ```yaml
617 | # config.yml
618 | build:
619 | writeStats: false
620 | noJSConfigInAssets: true
621 | ```
622 |
623 | 2. **Enable caching:**
624 |
625 | ```yaml
626 | # In GitHub Actions
627 | - name: Cache dependencies
628 | uses: actions/cache@v4
629 | with:
630 | path: ~/.npm
631 | key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
632 | ```
633 |
634 | 3. **Reduce build scope:**
635 |
636 | ```bash
637 | # Build only changed files
638 | npm run build -- --locale en
639 | ```
640 |
641 | ### Problem: Large Bundle Sizes
642 |
643 | **Symptoms:**
644 |
645 | - Slow page loads
646 | - High bandwidth usage
647 | - Poor mobile performance
648 |
649 | **Solutions:**
650 |
651 | 1. **Analyze bundle:**
652 |
653 | ```bash
654 | # Docusaurus
655 | npm run build -- --bundle-analyzer
656 |
657 | # Check generated files
658 | ls -lh build/assets/
659 | ```
660 |
661 | 2. **Optimize images:**
662 |
663 | ```bash
664 | # Convert images to WebP
665 | find docs -name "*.png" -exec cwebp {} -o {}.webp \;
666 | ```
667 |
668 | 3. **Enable code splitting:**
669 |
670 | ```javascript
671 | // Docusaurus config
672 | const config = {
673 | webpack: {
674 | splitChunks: {
675 | chunks: "all",
676 | cacheGroups: {
677 | default: {
678 | minChunks: 2,
679 | reuseExistingChunk: true,
680 | },
681 | },
682 | },
683 | },
684 | };
685 | ```
686 |
687 | ## Getting Help
688 |
689 | ### Diagnostic Information
690 |
691 | When reporting issues, include:
692 |
693 | 1. **DocuMCP version:**
694 |
695 | ```bash
696 | npm list documcp
697 | ```
698 |
699 | 2. **System information:**
700 |
701 | ```bash
702 | node --version
703 | npm --version
704 | git --version
705 | ```
706 |
707 | 3. **Error logs:**
708 |
709 | ```bash
710 | # GitHub Actions logs
711 | # Local build output
712 | # Browser console errors
713 | ```
714 |
715 | ### Support Channels
716 |
717 | - **GitHub Issues**: [Report bugs and feature requests](https://github.com/tosin2013/documcp/issues)
718 | - **Documentation**: Check other guides in this documentation
719 | - **Community**: Search existing issues for solutions
720 |
721 | ### Self-Diagnostic Commands
722 |
723 | ```bash
724 | # Complete health check
725 | "verify my entire documentation setup and identify all issues"
726 |
727 | # Performance analysis
728 | "analyze my documentation build performance and suggest optimizations"
729 |
730 | # Security check
731 | "validate my GitHub Pages deployment for security best practices"
732 | ```
733 |
734 | ## Prevention Tips
735 |
736 | ### Regular Maintenance
737 |
738 | 1. **Weekly validation:**
739 |
740 | ```bash
741 | "check all documentation links and validate content quality"
742 | ```
743 |
744 | 2. **Monthly updates:**
745 |
746 | ```bash
747 | # Update dependencies
748 | npm update
749 | # Regenerate configurations if needed
750 | ```
751 |
752 | 3. **Monitor deployment:**
753 |
754 | - Set up GitHub Actions notifications
755 | - Check site accessibility regularly
756 | - Monitor build times and performance
757 |
758 | ### Best Practices
759 |
760 | 1. **Always test locally before deploying**
761 | 2. **Use DocuMCP validation before committing**
762 | 3. **Keep dependencies updated**
763 | 4. **Monitor GitHub Actions for failures**
764 | 5. **Backup memory and configurations**
765 |
766 | ## Summary
767 |
768 | Common issue categories and solutions:
769 | ✅ Repository analysis problems - permissions and context
770 | ✅ SSG recommendation issues - preferences and project type
771 | ✅ Configuration generation - paths and project details
772 | ✅ Deployment failures - workflows and settings
773 | ✅ Content validation - links and code blocks
774 | ✅ Performance optimization - builds and bundles
775 | ✅ Memory system troubleshooting - initialization and data
776 |
777 | Most issues can be resolved by providing more context to DocuMCP or fixing configuration details!
778 |
```
--------------------------------------------------------------------------------
/src/tools/generate-readme-template.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { z } from "zod";
2 |
3 | // Template types
4 | export const TemplateType = z.enum([
5 | "library",
6 | "application",
7 | "cli-tool",
8 | "api",
9 | "documentation",
10 | ]);
11 | export type TemplateType = z.infer<typeof TemplateType>;
12 |
13 | // Input schema
14 | export const GenerateReadmeTemplateSchema = z.object({
15 | projectName: z.string().min(1, "Project name is required"),
16 | description: z.string().min(1, "Project description is required"),
17 | templateType: TemplateType,
18 | author: z.string().optional(),
19 | license: z.string().default("MIT"),
20 | includeScreenshots: z.boolean().default(false),
21 | includeBadges: z.boolean().default(true),
22 | includeContributing: z.boolean().default(true),
23 | outputPath: z.string().optional(),
24 | });
25 |
26 | export type GenerateReadmeTemplateInput = z.infer<
27 | typeof GenerateReadmeTemplateSchema
28 | >;
29 |
30 | interface TemplateSection {
31 | title: string;
32 | content: string;
33 | required: boolean;
34 | }
35 |
36 | interface ReadmeTemplate {
37 | sections: TemplateSection[];
38 | badges: string[];
39 | metadata: {
40 | type: TemplateType;
41 | estimatedLength: number;
42 | };
43 | }
44 |
45 | export class ReadmeTemplateGenerator {
46 | private templates: Map<TemplateType, ReadmeTemplate> = new Map();
47 |
48 | constructor() {
49 | this.initializeTemplates();
50 | }
51 |
52 | private initializeTemplates(): void {
53 | // Library/Package Template
54 | this.templates.set("library", {
55 | sections: [
56 | {
57 | title: "Header",
58 | content: "# {{projectName}}\n\n> {{description}}",
59 | required: true,
60 | },
61 | {
62 | title: "Badges",
63 | content: "{{badges}}",
64 | required: false,
65 | },
66 | {
67 | title: "TL;DR",
68 | content:
69 | "## TL;DR\n\nWhat it does in 2-3 sentences. Who should use it.\n\n- ✅ Perfect for X use cases\n- ✅ Solves Y problems\n- ❌ Not suitable for Z (consider [alternative] instead)",
70 | required: true,
71 | },
72 | {
73 | title: "Quick Start",
74 | content:
75 | "## Quick Start\n\n### Install\n\n```bash\nnpm install {{projectName}}\n```\n\n### Use\n\n```javascript\nconst {{camelCaseName}} = require('{{projectName}}');\n\n// Basic usage example\nconst result = {{camelCaseName}}.doSomething();\nconsole.log(result);\n```",
76 | required: true,
77 | },
78 | {
79 | title: "API Documentation",
80 | content:
81 | "## API Documentation\n\n[Link to full API documentation]\n\n### Core Methods\n\n#### `methodName(param)`\n\n- **param** `{Type}` - Description\n- **Returns** `{Type}` - Description\n\nExample:\n```javascript\n// Example usage\n```",
82 | required: true,
83 | },
84 | {
85 | title: "Contributing",
86 | content:
87 | "## Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.\n\n### Development Setup\n\n```bash\ngit clone https://github.com/{{author}}/{{projectName}}.git\ncd {{projectName}}\nnpm install\nnpm test\n```",
88 | required: false,
89 | },
90 | {
91 | title: "License",
92 | content: "## License\n\n{{license}} © {{author}}",
93 | required: true,
94 | },
95 | ],
96 | badges: [
97 | "[](https://badge.fury.io/js/{{projectName}})",
98 | "[](https://travis-ci.org/{{author}}/{{projectName}})",
99 | "[](https://opensource.org/licenses/{{license}})",
100 | ],
101 | metadata: {
102 | type: "library",
103 | estimatedLength: 150,
104 | },
105 | });
106 |
107 | // Application Template
108 | this.templates.set("application", {
109 | sections: [
110 | {
111 | title: "Header",
112 | content: "# {{projectName}}\n\n> {{description}}",
113 | required: true,
114 | },
115 | {
116 | title: "Screenshot",
117 | content: "{{screenshot}}",
118 | required: false,
119 | },
120 | {
121 | title: "What This Does",
122 | content:
123 | "## What This Does\n\n{{projectName}} helps you:\n\n- 🎯 **Feature 1** - Brief explanation\n- ⚡ **Feature 2** - Brief explanation\n- 🔧 **Feature 3** - Brief explanation",
124 | required: true,
125 | },
126 | {
127 | title: "Quick Start",
128 | content:
129 | "## Quick Start\n\n### Prerequisites\n\n- Node.js 18+ \n- npm or yarn\n- [Additional requirements]\n\n### Install & Run\n\n```bash\ngit clone https://github.com/{{author}}/{{projectName}}.git\ncd {{projectName}}\nnpm install\nnpm start\n```\n\nOpen http://localhost:3000 in your browser.",
130 | required: true,
131 | },
132 | {
133 | title: "Configuration",
134 | content:
135 | "## Configuration\n\nCreate a `.env` file in the root directory:\n\n```env\n# Required settings\nPORT=3000\nNODE_ENV=development\n\n# Optional settings\nDATABASE_URL=your_database_url\nAPI_KEY=your_api_key\n```\n\nSee [Configuration Guide](docs/configuration.md) for all options.",
136 | required: true,
137 | },
138 | {
139 | title: "Usage",
140 | content:
141 | "## Usage\n\n### Basic Operations\n\n1. **Step 1** - Description\n2. **Step 2** - Description\n3. **Step 3** - Description\n\n### Advanced Features\n\n[Link to advanced documentation]",
142 | required: true,
143 | },
144 | {
145 | title: "Contributing",
146 | content:
147 | "## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and contribution guidelines.",
148 | required: false,
149 | },
150 | {
151 | title: "License",
152 | content: "## License\n\n{{license}} © {{author}}",
153 | required: true,
154 | },
155 | ],
156 | badges: [
157 | "[](https://github.com/{{author}}/{{projectName}}/actions)",
158 | "[](LICENSE)",
159 | ],
160 | metadata: {
161 | type: "application",
162 | estimatedLength: 200,
163 | },
164 | });
165 |
166 | // CLI Tool Template
167 | this.templates.set("cli-tool", {
168 | sections: [
169 | {
170 | title: "Header",
171 | content: "# {{projectName}}\n\n> {{description}}",
172 | required: true,
173 | },
174 | {
175 | title: "Installation",
176 | content:
177 | "## Installation\n\n```bash\n# Global installation\nnpm install -g {{projectName}}\n\n# Or use with npx\nnpx {{projectName}} --help\n```",
178 | required: true,
179 | },
180 | {
181 | title: "Usage",
182 | content:
183 | "## Usage\n\n### Basic Commands\n\n```bash\n# Basic usage\n{{projectName}} [options] [arguments]\n\n# Show help\n{{projectName}} --help\n\n# Show version\n{{projectName}} --version\n```\n\n### Examples\n\n```bash\n# Example 1\n{{projectName}} command --option value\n\n# Example 2\n{{projectName}} another-command file.txt\n```",
184 | required: true,
185 | },
186 | {
187 | title: "Options",
188 | content:
189 | "## Options\n\n| Option | Description | Default |\n|--------|-------------|----------|\n| `-h, --help` | Show help | |\n| `-v, --version` | Show version | |\n| `--config <path>` | Config file path | `./config.json` |\n| `--verbose` | Verbose output | `false` |",
190 | required: true,
191 | },
192 | {
193 | title: "Configuration",
194 | content:
195 | '## Configuration\n\nCreate a config file:\n\n```json\n{\n "setting1": "value1",\n "setting2": "value2"\n}\n```',
196 | required: false,
197 | },
198 | {
199 | title: "Contributing",
200 | content:
201 | "## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for development guidelines.",
202 | required: false,
203 | },
204 | {
205 | title: "License",
206 | content: "## License\n\n{{license}} © {{author}}",
207 | required: true,
208 | },
209 | ],
210 | badges: [
211 | "[](https://www.npmjs.com/package/{{projectName}})",
212 | "[](LICENSE)",
213 | ],
214 | metadata: {
215 | type: "cli-tool",
216 | estimatedLength: 180,
217 | },
218 | });
219 | }
220 |
221 | generateTemplate(input: GenerateReadmeTemplateInput): string {
222 | const template = this.templates.get(input.templateType);
223 | if (!template) {
224 | throw new Error(`Template type "${input.templateType}" not supported`);
225 | }
226 |
227 | let readme = "";
228 | const camelCaseName = this.toCamelCase(input.projectName);
229 |
230 | // Process each section
231 | for (const section of template.sections) {
232 | if (section.title === "Badges" && input.includeBadges) {
233 | readme += this.processBadges(template.badges, input) + "\n\n";
234 | } else if (section.title === "Screenshot" && input.includeScreenshots) {
235 | readme += this.processScreenshot(input) + "\n\n";
236 | } else if (
237 | section.title === "Contributing" &&
238 | !input.includeContributing
239 | ) {
240 | continue;
241 | } else {
242 | readme +=
243 | this.processSection(section.content, input, camelCaseName) + "\n\n";
244 | }
245 | }
246 |
247 | return readme.trim();
248 | }
249 |
250 | private processBadges(
251 | badges: string[],
252 | input: GenerateReadmeTemplateInput,
253 | ): string {
254 | return badges
255 | .map((badge) => this.replaceVariables(badge, input))
256 | .join("\n");
257 | }
258 |
259 | private processScreenshot(input: GenerateReadmeTemplateInput): string {
260 | return `\n\n*Add a screenshot or demo GIF here*`;
261 | }
262 |
263 | private processSection(
264 | content: string,
265 | input: GenerateReadmeTemplateInput,
266 | camelCaseName: string,
267 | ): string {
268 | let processed = this.replaceVariables(content, input);
269 | processed = processed.replace(/\{\{camelCaseName\}\}/g, camelCaseName);
270 | return processed;
271 | }
272 |
273 | private replaceVariables(
274 | content: string,
275 | input: GenerateReadmeTemplateInput,
276 | ): string {
277 | return content
278 | .replace(/\{\{projectName\}\}/g, input.projectName)
279 | .replace(/\{\{description\}\}/g, input.description)
280 | .replace(/\{\{author\}\}/g, input.author || "your-username")
281 | .replace(/\{\{license\}\}/g, input.license);
282 | }
283 |
284 | private toCamelCase(str: string): string {
285 | return str
286 | .replace(/[-_\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ""))
287 | .replace(/^./, (c) => c.toLowerCase());
288 | }
289 |
290 | getAvailableTemplates(): TemplateType[] {
291 | return Array.from(this.templates.keys());
292 | }
293 |
294 | getTemplateInfo(type: TemplateType): ReadmeTemplate["metadata"] | null {
295 | const template = this.templates.get(type);
296 | return template ? template.metadata : null;
297 | }
298 | }
299 |
300 | /**
301 | * Generates standardized README templates for different project types with best practices.
302 | *
303 | * Creates comprehensive README templates tailored to specific project types (library,
304 | * application, CLI tool, API, documentation) following community best practices. Includes
305 | * customizable sections, badges, contributing guidelines, and project-specific content
306 | * to ensure professional documentation standards.
307 | *
308 | * @param input - The input parameters for README template generation
309 | * @param input.projectName - Name of the project (required)
310 | * @param input.description - Brief description of what the project does (required)
311 | * @param input.templateType - Type of project template to generate
312 | * @param input.author - Optional project author/organization name
313 | * @param input.license - Project license (default: "MIT")
314 | * @param input.includeScreenshots - Whether to include screenshot placeholders (default: false)
315 | * @param input.includeBadges - Whether to include status badges (default: true)
316 | * @param input.includeContributing - Whether to include contributing section (default: true)
317 | * @param input.outputPath - Optional path to write the generated README.md file
318 | *
319 | * @returns Promise resolving to README template generation results
320 | * @returns template - The generated README template content
321 | * @returns metadata - Template metadata including type and estimated length
322 | * @returns filePath - Path where the README was written (if outputPath provided)
323 | *
324 | * @throws {Error} When required parameters are missing
325 | * @throws {Error} When output path is inaccessible
326 | * @throws {Error} When template generation fails
327 | *
328 | * @example
329 | * ```typescript
330 | * // Generate library README template
331 | * const result = await generateReadmeTemplate({
332 | * projectName: "MyAwesomeLibrary",
333 | * description: "A powerful utility library for data processing",
334 | * templateType: "library",
335 | * author: "Your Name",
336 | * license: "MIT",
337 | * includeBadges: true
338 | * });
339 | *
340 | * console.log(`Generated ${result.metadata.estimatedLength} line README`);
341 | *
342 | * // Generate CLI tool template with output file
343 | * const cliTemplate = await generateReadmeTemplate({
344 | * projectName: "my-cli-tool",
345 | * description: "Command-line interface for project management",
346 | * templateType: "cli-tool",
347 | * outputPath: "./README.md"
348 | * });
349 | * ```
350 | *
351 | * @since 1.0.0
352 | */
353 | export async function generateReadmeTemplate(
354 | input: GenerateReadmeTemplateInput,
355 | ): Promise<{
356 | content: string;
357 | metadata: {
358 | templateType: TemplateType;
359 | estimatedLength: number;
360 | sectionsIncluded: number;
361 | };
362 | }> {
363 | const validatedInput = GenerateReadmeTemplateSchema.parse(input);
364 | const generator = new ReadmeTemplateGenerator();
365 |
366 | const content = generator.generateTemplate(validatedInput);
367 | const templateInfo = generator.getTemplateInfo(validatedInput.templateType);
368 |
369 | if (!templateInfo) {
370 | throw new Error(`Template type "${validatedInput.templateType}" not found`);
371 | }
372 |
373 | // Write to file if output path specified
374 | if (validatedInput.outputPath) {
375 | const fs = await import("fs/promises");
376 | await fs.writeFile(validatedInput.outputPath, content, "utf-8");
377 | }
378 |
379 | return {
380 | content,
381 | metadata: {
382 | templateType: validatedInput.templateType,
383 | estimatedLength: templateInfo.estimatedLength,
384 | sectionsIncluded: content.split("##").length - 1,
385 | },
386 | };
387 | }
388 |
```