aios-core 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.aios-core/.session/current-session.json +14 -0
- package/.aios-core/cli/commands/generate/index.js +222 -0
- package/.aios-core/cli/commands/manifest/index.js +46 -0
- package/.aios-core/cli/commands/manifest/regenerate.js +96 -0
- package/.aios-core/cli/commands/manifest/validate.js +66 -0
- package/.aios-core/cli/commands/mcp/add.js +234 -0
- package/.aios-core/cli/commands/mcp/index.js +76 -0
- package/.aios-core/cli/commands/mcp/link.js +217 -0
- package/.aios-core/cli/commands/mcp/setup.js +164 -0
- package/.aios-core/cli/commands/mcp/status.js +183 -0
- package/.aios-core/cli/commands/metrics/cleanup.js +91 -0
- package/.aios-core/cli/commands/metrics/index.js +65 -0
- package/.aios-core/cli/commands/metrics/record.js +154 -0
- package/.aios-core/cli/commands/metrics/seed.js +126 -0
- package/.aios-core/cli/commands/metrics/show.js +209 -0
- package/.aios-core/cli/commands/migrate/analyze.js +353 -0
- package/.aios-core/cli/commands/migrate/backup.js +352 -0
- package/.aios-core/cli/commands/migrate/execute.js +292 -0
- package/.aios-core/cli/commands/migrate/index.js +441 -0
- package/.aios-core/cli/commands/migrate/rollback.js +323 -0
- package/.aios-core/cli/commands/migrate/update-imports.js +396 -0
- package/.aios-core/cli/commands/migrate/validate.js +452 -0
- package/.aios-core/cli/commands/qa/index.js +56 -0
- package/.aios-core/cli/commands/qa/run.js +163 -0
- package/.aios-core/cli/commands/qa/status.js +195 -0
- package/.aios-core/cli/commands/workers/formatters/info-formatter.js +274 -0
- package/.aios-core/cli/commands/workers/formatters/list-table.js +265 -0
- package/.aios-core/cli/commands/workers/formatters/list-tree.js +159 -0
- package/.aios-core/cli/commands/workers/index.js +56 -0
- package/.aios-core/cli/commands/workers/info.js +194 -0
- package/.aios-core/cli/commands/workers/list.js +214 -0
- package/.aios-core/cli/commands/workers/search-filters.js +185 -0
- package/.aios-core/cli/commands/workers/search-keyword.js +310 -0
- package/.aios-core/cli/commands/workers/search-semantic.js +293 -0
- package/.aios-core/cli/commands/workers/search.js +154 -0
- package/.aios-core/cli/commands/workers/utils/pagination.js +102 -0
- package/.aios-core/cli/index.js +128 -0
- package/.aios-core/cli/utils/output-formatter-cli.js +232 -0
- package/.aios-core/cli/utils/score-calculator.js +221 -0
- package/.aios-core/core/README.md +229 -0
- package/.aios-core/core/config/config-cache.js +233 -0
- package/.aios-core/core/config/config-loader.js +277 -0
- package/.aios-core/core/data/agent-config-requirements.yaml +368 -0
- package/.aios-core/core/data/aios-kb.md +924 -0
- package/.aios-core/core/data/workflow-patterns.yaml +267 -0
- package/.aios-core/core/docs/SHARD-TRANSLATION-GUIDE.md +335 -0
- package/.aios-core/core/docs/component-creation-guide.md +458 -0
- package/.aios-core/core/docs/session-update-pattern.md +307 -0
- package/.aios-core/core/docs/template-syntax.md +267 -0
- package/.aios-core/core/docs/troubleshooting-guide.md +625 -0
- package/.aios-core/core/elicitation/agent-elicitation.js +272 -0
- package/.aios-core/core/elicitation/elicitation-engine.js +479 -0
- package/.aios-core/core/elicitation/session-manager.js +320 -0
- package/.aios-core/core/elicitation/task-elicitation.js +281 -0
- package/.aios-core/core/elicitation/workflow-elicitation.js +315 -0
- package/.aios-core/core/index.esm.js +42 -0
- package/.aios-core/core/index.js +76 -0
- package/.aios-core/core/manifest/manifest-generator.js +386 -0
- package/.aios-core/core/manifest/manifest-validator.js +429 -0
- package/.aios-core/core/mcp/config-migrator.js +340 -0
- package/.aios-core/core/mcp/global-config-manager.js +369 -0
- package/.aios-core/core/mcp/index.js +34 -0
- package/.aios-core/core/mcp/os-detector.js +188 -0
- package/.aios-core/core/mcp/symlink-manager.js +413 -0
- package/.aios-core/core/migration/migration-config.yaml +83 -0
- package/.aios-core/core/migration/module-mapping.yaml +89 -0
- package/.aios-core/core/quality-gates/base-layer.js +134 -0
- package/.aios-core/core/quality-gates/checklist-generator.js +329 -0
- package/.aios-core/core/quality-gates/focus-area-recommender.js +359 -0
- package/.aios-core/core/quality-gates/human-review-orchestrator.js +529 -0
- package/.aios-core/core/quality-gates/layer1-precommit.js +336 -0
- package/.aios-core/core/quality-gates/layer2-pr-automation.js +324 -0
- package/.aios-core/core/quality-gates/layer3-human-review.js +348 -0
- package/.aios-core/core/quality-gates/notification-manager.js +550 -0
- package/.aios-core/core/quality-gates/quality-gate-config.yaml +86 -0
- package/.aios-core/core/quality-gates/quality-gate-manager.js +601 -0
- package/.aios-core/core/registry/README.md +179 -0
- package/.aios-core/core/registry/build-registry.js +452 -0
- package/.aios-core/core/registry/registry-loader.js +330 -0
- package/.aios-core/core/registry/registry-schema.json +166 -0
- package/.aios-core/core/registry/service-registry.json +6586 -0
- package/.aios-core/core/registry/validate-registry.js +340 -0
- package/.aios-core/core/session/context-detector.js +229 -0
- package/.aios-core/core/session/context-loader.js +288 -0
- package/.aios-core/core/utils/output-formatter.js +298 -0
- package/.aios-core/core/utils/security-utils.js +333 -0
- package/.aios-core/core/utils/yaml-validator.js +419 -0
- package/.aios-core/core-config.yaml +382 -0
- package/.aios-core/data/agent-config-requirements.yaml +368 -0
- package/.aios-core/data/aios-kb.md +924 -0
- package/.aios-core/data/technical-preferences.md +4 -0
- package/.aios-core/data/workflow-patterns.yaml +267 -0
- package/.aios-core/development/README.md +142 -0
- package/.aios-core/development/agent-teams/team-all.yaml +15 -0
- package/.aios-core/development/agent-teams/team-fullstack.yaml +18 -0
- package/.aios-core/development/agent-teams/team-ide-minimal.yaml +10 -0
- package/.aios-core/development/agent-teams/team-no-ui.yaml +13 -0
- package/.aios-core/development/agent-teams/team-qa-focused.yaml +155 -0
- package/.aios-core/development/agents/aios-master.md +339 -0
- package/.aios-core/development/agents/analyst.md +195 -0
- package/.aios-core/development/agents/architect.md +359 -0
- package/.aios-core/development/agents/data-engineer.md +468 -0
- package/.aios-core/development/agents/dev.md +390 -0
- package/.aios-core/development/agents/devops.md +398 -0
- package/.aios-core/development/agents/pm.md +198 -0
- package/.aios-core/development/agents/po.md +256 -0
- package/.aios-core/development/agents/qa.md +312 -0
- package/.aios-core/development/agents/sm.md +220 -0
- package/.aios-core/development/agents/ux-design-expert.md +451 -0
- package/.aios-core/development/scripts/agent-assignment-resolver.js +231 -0
- package/.aios-core/development/scripts/agent-config-loader.js +624 -0
- package/.aios-core/development/scripts/agent-exit-hooks.js +96 -0
- package/.aios-core/development/scripts/apply-inline-greeting-all-agents.js +146 -0
- package/.aios-core/development/scripts/audit-agent-config.js +380 -0
- package/.aios-core/development/scripts/backlog-manager.js +404 -0
- package/.aios-core/development/scripts/batch-update-agents-session-context.js +95 -0
- package/.aios-core/development/scripts/decision-context.js +228 -0
- package/.aios-core/development/scripts/decision-log-generator.js +293 -0
- package/.aios-core/development/scripts/decision-log-indexer.js +284 -0
- package/.aios-core/development/scripts/decision-recorder.js +168 -0
- package/.aios-core/development/scripts/dev-context-loader.js +297 -0
- package/.aios-core/development/scripts/generate-greeting.js +160 -0
- package/.aios-core/development/scripts/greeting-builder.js +866 -0
- package/.aios-core/development/scripts/greeting-config-cli.js +85 -0
- package/.aios-core/development/scripts/greeting-preference-manager.js +145 -0
- package/.aios-core/development/scripts/migrate-task-to-v2.js +377 -0
- package/.aios-core/development/scripts/story-index-generator.js +337 -0
- package/.aios-core/development/scripts/story-manager.js +375 -0
- package/.aios-core/development/scripts/story-update-hook.js +259 -0
- package/.aios-core/development/scripts/task-identifier-resolver.js +145 -0
- package/.aios-core/development/scripts/test-greeting-system.js +142 -0
- package/.aios-core/development/scripts/validate-task-v2.js +319 -0
- package/.aios-core/development/scripts/workflow-navigator.js +214 -0
- package/.aios-core/development/tasks/add-mcp.md +319 -0
- package/.aios-core/development/tasks/advanced-elicitation.md +319 -0
- package/.aios-core/development/tasks/analyst-facilitate-brainstorming.md +342 -0
- package/.aios-core/development/tasks/analyze-framework.md +697 -0
- package/.aios-core/development/tasks/analyze-performance.md +637 -0
- package/.aios-core/development/tasks/apply-qa-fixes.md +340 -0
- package/.aios-core/development/tasks/architect-analyze-impact.md +827 -0
- package/.aios-core/development/tasks/audit-codebase.md +429 -0
- package/.aios-core/development/tasks/audit-tailwind-config.md +270 -0
- package/.aios-core/development/tasks/audit-utilities.md +358 -0
- package/.aios-core/development/tasks/bootstrap-shadcn-library.md +286 -0
- package/.aios-core/development/tasks/brownfield-create-epic.md +486 -0
- package/.aios-core/development/tasks/brownfield-create-story.md +357 -0
- package/.aios-core/development/tasks/build-component.md +478 -0
- package/.aios-core/development/tasks/calculate-roi.md +455 -0
- package/.aios-core/development/tasks/ci-cd-configuration.md +764 -0
- package/.aios-core/development/tasks/cleanup-utilities.md +670 -0
- package/.aios-core/development/tasks/collaborative-edit.md +1109 -0
- package/.aios-core/development/tasks/compose-molecule.md +284 -0
- package/.aios-core/development/tasks/consolidate-patterns.md +414 -0
- package/.aios-core/development/tasks/correct-course.md +280 -0
- package/.aios-core/development/tasks/create-agent.md +322 -0
- package/.aios-core/development/tasks/create-brownfield-story.md +727 -0
- package/.aios-core/development/tasks/create-deep-research-prompt.md +499 -0
- package/.aios-core/development/tasks/create-doc.md +316 -0
- package/.aios-core/development/tasks/create-next-story.md +774 -0
- package/.aios-core/development/tasks/create-suite.md +284 -0
- package/.aios-core/development/tasks/create-task.md +372 -0
- package/.aios-core/development/tasks/create-workflow.md +371 -0
- package/.aios-core/development/tasks/db-analyze-hotpaths.md +572 -0
- package/.aios-core/development/tasks/db-apply-migration.md +381 -0
- package/.aios-core/development/tasks/db-bootstrap.md +642 -0
- package/.aios-core/development/tasks/db-domain-modeling.md +693 -0
- package/.aios-core/development/tasks/db-dry-run.md +293 -0
- package/.aios-core/development/tasks/db-env-check.md +260 -0
- package/.aios-core/development/tasks/db-expansion-pack-integration.md +663 -0
- package/.aios-core/development/tasks/db-explain.md +631 -0
- package/.aios-core/development/tasks/db-impersonate.md +495 -0
- package/.aios-core/development/tasks/db-load-csv.md +593 -0
- package/.aios-core/development/tasks/db-policy-apply.md +653 -0
- package/.aios-core/development/tasks/db-rls-audit.md +411 -0
- package/.aios-core/development/tasks/db-rollback.md +739 -0
- package/.aios-core/development/tasks/db-run-sql.md +613 -0
- package/.aios-core/development/tasks/db-schema-audit.md +1011 -0
- package/.aios-core/development/tasks/db-seed.md +390 -0
- package/.aios-core/development/tasks/db-smoke-test.md +351 -0
- package/.aios-core/development/tasks/db-snapshot.md +569 -0
- package/.aios-core/development/tasks/db-supabase-setup.md +712 -0
- package/.aios-core/development/tasks/db-verify-order.md +515 -0
- package/.aios-core/development/tasks/deprecate-component.md +957 -0
- package/.aios-core/development/tasks/dev-apply-qa-fixes.md +318 -0
- package/.aios-core/development/tasks/dev-backlog-debt.md +469 -0
- package/.aios-core/development/tasks/dev-develop-story.md +846 -0
- package/.aios-core/development/tasks/dev-improve-code-quality.md +873 -0
- package/.aios-core/development/tasks/dev-optimize-performance.md +1034 -0
- package/.aios-core/development/tasks/dev-suggest-refactoring.md +871 -0
- package/.aios-core/development/tasks/dev-validate-next-story.md +349 -0
- package/.aios-core/development/tasks/document-project.md +553 -0
- package/.aios-core/development/tasks/environment-bootstrap.md +1311 -0
- package/.aios-core/development/tasks/execute-checklist.md +301 -0
- package/.aios-core/development/tasks/export-design-tokens-dtcg.md +274 -0
- package/.aios-core/development/tasks/extend-pattern.md +269 -0
- package/.aios-core/development/tasks/extract-tokens.md +467 -0
- package/.aios-core/development/tasks/facilitate-brainstorming-session.md +518 -0
- package/.aios-core/development/tasks/generate-ai-frontend-prompt.md +261 -0
- package/.aios-core/development/tasks/generate-documentation.md +284 -0
- package/.aios-core/development/tasks/generate-migration-strategy.md +522 -0
- package/.aios-core/development/tasks/generate-shock-report.md +501 -0
- package/.aios-core/development/tasks/github-devops-github-pr-automation.md +427 -0
- package/.aios-core/development/tasks/github-devops-pre-push-quality-gate.md +733 -0
- package/.aios-core/development/tasks/github-devops-repository-cleanup.md +374 -0
- package/.aios-core/development/tasks/github-devops-version-management.md +483 -0
- package/.aios-core/development/tasks/improve-self.md +823 -0
- package/.aios-core/development/tasks/index-docs.md +388 -0
- package/.aios-core/development/tasks/init-project-status.md +506 -0
- package/.aios-core/development/tasks/integrate-expansion-pack.md +314 -0
- package/.aios-core/development/tasks/kb-mode-interaction.md +284 -0
- package/.aios-core/development/tasks/learn-patterns.md +901 -0
- package/.aios-core/development/tasks/mcp-workflow.md +437 -0
- package/.aios-core/development/tasks/modify-agent.md +382 -0
- package/.aios-core/development/tasks/modify-task.md +425 -0
- package/.aios-core/development/tasks/modify-workflow.md +466 -0
- package/.aios-core/development/tasks/po-backlog-add.md +370 -0
- package/.aios-core/development/tasks/po-manage-story-backlog.md +523 -0
- package/.aios-core/development/tasks/po-pull-story-from-clickup.md +540 -0
- package/.aios-core/development/tasks/po-pull-story.md +316 -0
- package/.aios-core/development/tasks/po-stories-index.md +351 -0
- package/.aios-core/development/tasks/po-sync-story-to-clickup.md +457 -0
- package/.aios-core/development/tasks/po-sync-story.md +303 -0
- package/.aios-core/development/tasks/pr-automation.md +701 -0
- package/.aios-core/development/tasks/propose-modification.md +843 -0
- package/.aios-core/development/tasks/qa-backlog-add-followup.md +425 -0
- package/.aios-core/development/tasks/qa-gate.md +374 -0
- package/.aios-core/development/tasks/qa-generate-tests.md +1175 -0
- package/.aios-core/development/tasks/qa-nfr-assess.md +558 -0
- package/.aios-core/development/tasks/qa-review-proposal.md +1158 -0
- package/.aios-core/development/tasks/qa-review-story.md +683 -0
- package/.aios-core/development/tasks/qa-risk-profile.md +567 -0
- package/.aios-core/development/tasks/qa-run-tests.md +277 -0
- package/.aios-core/development/tasks/qa-test-design.md +388 -0
- package/.aios-core/development/tasks/qa-trace-requirements.md +477 -0
- package/.aios-core/development/tasks/release-management.md +723 -0
- package/.aios-core/development/tasks/security-audit.md +554 -0
- package/.aios-core/development/tasks/security-scan.md +790 -0
- package/.aios-core/development/tasks/setup-database.md +741 -0
- package/.aios-core/development/tasks/setup-design-system.md +462 -0
- package/.aios-core/development/tasks/setup-github.md +874 -0
- package/.aios-core/development/tasks/setup-llm-routing.md +229 -0
- package/.aios-core/development/tasks/setup-mcp-docker.md +584 -0
- package/.aios-core/development/tasks/shard-doc.md +538 -0
- package/.aios-core/development/tasks/sm-create-next-story.md +480 -0
- package/.aios-core/development/tasks/sync-documentation.md +865 -0
- package/.aios-core/development/tasks/tailwind-upgrade.md +294 -0
- package/.aios-core/development/tasks/test-as-user.md +621 -0
- package/.aios-core/development/tasks/test-validation-task.md +171 -0
- package/.aios-core/development/tasks/undo-last.md +347 -0
- package/.aios-core/development/tasks/update-manifest.md +410 -0
- package/.aios-core/development/tasks/ux-create-wireframe.md +617 -0
- package/.aios-core/development/tasks/ux-ds-scan-artifact.md +672 -0
- package/.aios-core/development/tasks/ux-user-research.md +559 -0
- package/.aios-core/development/tasks/validate-next-story.md +423 -0
- package/.aios-core/development/tasks/validate-structure.md +243 -0
- package/.aios-core/development/workflows/README.md +84 -0
- package/.aios-core/development/workflows/brownfield-fullstack.yaml +297 -0
- package/.aios-core/development/workflows/brownfield-service.yaml +187 -0
- package/.aios-core/development/workflows/brownfield-ui.yaml +197 -0
- package/.aios-core/development/workflows/greenfield-fullstack.yaml +333 -0
- package/.aios-core/development/workflows/greenfield-service.yaml +206 -0
- package/.aios-core/development/workflows/greenfield-ui.yaml +235 -0
- package/.aios-core/docs/SHARD-TRANSLATION-GUIDE.md +335 -0
- package/.aios-core/docs/component-creation-guide.md +458 -0
- package/.aios-core/docs/session-update-pattern.md +307 -0
- package/.aios-core/docs/standards/AGENT-PERSONALIZATION-STANDARD-V1.md +572 -0
- package/.aios-core/docs/standards/AIOS-COLOR-PALETTE-QUICK-REFERENCE.md +185 -0
- package/.aios-core/docs/standards/AIOS-COLOR-PALETTE-V2.1.md +354 -0
- package/.aios-core/docs/standards/AIOS-FRAMEWORK-MASTER.md +1963 -0
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1-COMPLETE.md +821 -0
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1-SUMMARY.md +1190 -0
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1.md +439 -0
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.2-SUMMARY.md +1339 -0
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO.md +5398 -0
- package/.aios-core/docs/standards/EXECUTOR-DECISION-TREE.md +697 -0
- package/.aios-core/docs/standards/OPEN-SOURCE-VS-SERVICE-DIFFERENCES.md +511 -0
- package/.aios-core/docs/standards/QUALITY-GATES-SPECIFICATION.md +556 -0
- package/.aios-core/docs/standards/STANDARDS-INDEX.md +210 -0
- package/.aios-core/docs/standards/STORY-TEMPLATE-V2-SPECIFICATION.md +550 -0
- package/.aios-core/docs/standards/TASK-FORMAT-SPECIFICATION-V1.md +1414 -0
- package/.aios-core/docs/standards/V3-ARCHITECTURAL-DECISIONS.md +523 -0
- package/.aios-core/docs/template-syntax.md +267 -0
- package/.aios-core/docs/troubleshooting-guide.md +625 -0
- package/.aios-core/elicitation/agent-elicitation.js +272 -0
- package/.aios-core/elicitation/task-elicitation.js +281 -0
- package/.aios-core/elicitation/workflow-elicitation.js +315 -0
- package/.aios-core/index.d.ts +8 -0
- package/.aios-core/index.esm.js +16 -0
- package/.aios-core/index.js +16 -0
- package/.aios-core/infrastructure/README.md +126 -0
- package/.aios-core/infrastructure/index.js +199 -0
- package/.aios-core/infrastructure/integrations/pm-adapters/README.md +59 -0
- package/.aios-core/infrastructure/integrations/pm-adapters/clickup-adapter.js +345 -0
- package/.aios-core/infrastructure/integrations/pm-adapters/github-adapter.js +392 -0
- package/.aios-core/infrastructure/integrations/pm-adapters/jira-adapter.js +448 -0
- package/.aios-core/infrastructure/integrations/pm-adapters/local-adapter.js +175 -0
- package/.aios-core/infrastructure/scripts/_archived/final-todo-count.js +122 -0
- package/.aios-core/infrastructure/scripts/_archived/fix-yaml-formatting.js +89 -0
- package/.aios-core/infrastructure/scripts/_archived/migration-generator.js +780 -0
- package/.aios-core/infrastructure/scripts/_archived/migration-path-generator.js +950 -0
- package/.aios-core/infrastructure/scripts/_archived/phase2-entrada-saida-errors.js +425 -0
- package/.aios-core/infrastructure/scripts/_archived/phase2-spot-check.js +132 -0
- package/.aios-core/infrastructure/scripts/_archived/phase3-tools-scripts-validation.js +381 -0
- package/.aios-core/infrastructure/scripts/_archived/phase4-metadata-performance.js +203 -0
- package/.aios-core/infrastructure/scripts/_archived/test-yaml-parsing.js +24 -0
- package/.aios-core/infrastructure/scripts/_archived/verify-yaml-fix.js +51 -0
- package/.aios-core/infrastructure/scripts/aios-validator.js +294 -0
- package/.aios-core/infrastructure/scripts/approval-workflow.js +643 -0
- package/.aios-core/infrastructure/scripts/atomic-layer-classifier.js +308 -0
- package/.aios-core/infrastructure/scripts/backup-manager.js +607 -0
- package/.aios-core/infrastructure/scripts/batch-creator.js +608 -0
- package/.aios-core/infrastructure/scripts/branch-manager.js +391 -0
- package/.aios-core/infrastructure/scripts/capability-analyzer.js +535 -0
- package/.aios-core/infrastructure/scripts/clickup-helpers.js +226 -0
- package/.aios-core/infrastructure/scripts/code-quality-improver.js +1312 -0
- package/.aios-core/infrastructure/scripts/commit-message-generator.js +850 -0
- package/.aios-core/infrastructure/scripts/component-generator.js +738 -0
- package/.aios-core/infrastructure/scripts/component-metadata.js +627 -0
- package/.aios-core/infrastructure/scripts/component-search.js +277 -0
- package/.aios-core/infrastructure/scripts/config-cache.js +322 -0
- package/.aios-core/infrastructure/scripts/config-loader.js +349 -0
- package/.aios-core/infrastructure/scripts/conflict-resolver.js +675 -0
- package/.aios-core/infrastructure/scripts/coverage-analyzer.js +882 -0
- package/.aios-core/infrastructure/scripts/dependency-analyzer.js +638 -0
- package/.aios-core/infrastructure/scripts/dependency-impact-analyzer.js +703 -0
- package/.aios-core/infrastructure/scripts/diff-generator.js +129 -0
- package/.aios-core/infrastructure/scripts/documentation-integrity/brownfield-analyzer.js +501 -0
- package/.aios-core/infrastructure/scripts/documentation-integrity/config-generator.js +329 -0
- package/.aios-core/infrastructure/scripts/documentation-integrity/deployment-config-loader.js +282 -0
- package/.aios-core/infrastructure/scripts/documentation-integrity/doc-generator.js +331 -0
- package/.aios-core/infrastructure/scripts/documentation-integrity/gitignore-generator.js +313 -0
- package/.aios-core/infrastructure/scripts/documentation-integrity/index.js +74 -0
- package/.aios-core/infrastructure/scripts/documentation-integrity/mode-detector.js +358 -0
- package/.aios-core/infrastructure/scripts/documentation-synchronizer.js +1432 -0
- package/.aios-core/infrastructure/scripts/framework-analyzer.js +746 -0
- package/.aios-core/infrastructure/scripts/git-config-detector.js +293 -0
- package/.aios-core/infrastructure/scripts/git-wrapper.js +443 -0
- package/.aios-core/infrastructure/scripts/improvement-engine.js +758 -0
- package/.aios-core/infrastructure/scripts/improvement-validator.js +710 -0
- package/.aios-core/infrastructure/scripts/llm-routing/install-llm-routing.js +267 -0
- package/.aios-core/infrastructure/scripts/llm-routing/templates/claude-free.cmd +80 -0
- package/.aios-core/infrastructure/scripts/llm-routing/templates/claude-free.sh +62 -0
- package/.aios-core/infrastructure/scripts/llm-routing/templates/claude-max.cmd +26 -0
- package/.aios-core/infrastructure/scripts/llm-routing/templates/claude-max.sh +18 -0
- package/.aios-core/infrastructure/scripts/modification-risk-assessment.js +970 -0
- package/.aios-core/infrastructure/scripts/modification-validator.js +555 -0
- package/.aios-core/infrastructure/scripts/output-formatter.js +297 -0
- package/.aios-core/infrastructure/scripts/performance-analyzer.js +758 -0
- package/.aios-core/infrastructure/scripts/performance-and-error-resolver.js +258 -0
- package/.aios-core/infrastructure/scripts/performance-optimizer.js +1902 -0
- package/.aios-core/infrastructure/scripts/performance-tracker.js +452 -0
- package/.aios-core/infrastructure/scripts/pm-adapter-factory.js +181 -0
- package/.aios-core/infrastructure/scripts/pm-adapter.js +134 -0
- package/.aios-core/infrastructure/scripts/project-status-loader.js +445 -0
- package/.aios-core/infrastructure/scripts/refactoring-suggester.js +1139 -0
- package/.aios-core/infrastructure/scripts/repository-detector.js +64 -0
- package/.aios-core/infrastructure/scripts/sandbox-tester.js +618 -0
- package/.aios-core/infrastructure/scripts/security-checker.js +359 -0
- package/.aios-core/infrastructure/scripts/source-tree-guardian/index.js +375 -0
- package/.aios-core/infrastructure/scripts/source-tree-guardian/manifest-generator.js +410 -0
- package/.aios-core/infrastructure/scripts/source-tree-guardian/rules/naming-rules.yaml +285 -0
- package/.aios-core/infrastructure/scripts/source-tree-guardian/rules/placement-rules.yaml +262 -0
- package/.aios-core/infrastructure/scripts/source-tree-guardian/validator.js +468 -0
- package/.aios-core/infrastructure/scripts/spot-check-validator.js +149 -0
- package/.aios-core/infrastructure/scripts/status-mapper.js +115 -0
- package/.aios-core/infrastructure/scripts/template-engine.js +240 -0
- package/.aios-core/infrastructure/scripts/template-validator.js +279 -0
- package/.aios-core/infrastructure/scripts/test-generator.js +844 -0
- package/.aios-core/infrastructure/scripts/test-quality-assessment.js +1081 -0
- package/.aios-core/infrastructure/scripts/test-utilities-fast.js +126 -0
- package/.aios-core/infrastructure/scripts/test-utilities.js +200 -0
- package/.aios-core/infrastructure/scripts/tool-resolver.js +360 -0
- package/.aios-core/infrastructure/scripts/transaction-manager.js +590 -0
- package/.aios-core/infrastructure/scripts/usage-analytics.js +634 -0
- package/.aios-core/infrastructure/scripts/validate-output-pattern.js +213 -0
- package/.aios-core/infrastructure/scripts/visual-impact-generator.js +1056 -0
- package/.aios-core/infrastructure/scripts/yaml-validator.js +397 -0
- package/.aios-core/infrastructure/templates/coderabbit.yaml.template +279 -0
- package/.aios-core/infrastructure/templates/core-config/core-config-brownfield.tmpl.yaml +182 -0
- package/.aios-core/infrastructure/templates/core-config/core-config-greenfield.tmpl.yaml +127 -0
- package/.aios-core/infrastructure/templates/github-workflows/README.md +109 -0
- package/.aios-core/infrastructure/templates/github-workflows/ci.yml.template +169 -0
- package/.aios-core/infrastructure/templates/github-workflows/pr-automation.yml.template +330 -0
- package/.aios-core/infrastructure/templates/github-workflows/release.yml.template +196 -0
- package/.aios-core/infrastructure/templates/gitignore/gitignore-aios-base.tmpl +63 -0
- package/.aios-core/infrastructure/templates/gitignore/gitignore-brownfield-merge.tmpl +18 -0
- package/.aios-core/infrastructure/templates/gitignore/gitignore-node.tmpl +85 -0
- package/.aios-core/infrastructure/templates/gitignore/gitignore-python.tmpl +145 -0
- package/.aios-core/infrastructure/templates/project-docs/coding-standards-tmpl.md +346 -0
- package/.aios-core/infrastructure/templates/project-docs/source-tree-tmpl.md +177 -0
- package/.aios-core/infrastructure/templates/project-docs/tech-stack-tmpl.md +267 -0
- package/.aios-core/infrastructure/tests/project-status-loader.test.js +394 -0
- package/.aios-core/infrastructure/tests/regression-suite-v2.md +621 -0
- package/.aios-core/infrastructure/tests/utilities-audit-results.json +501 -0
- package/.aios-core/infrastructure/tests/validate-module.js +97 -0
- package/.aios-core/infrastructure/tools/README.md +222 -0
- package/.aios-core/infrastructure/tools/cli/github-cli.yaml +200 -0
- package/.aios-core/infrastructure/tools/cli/llm-routing.yaml +126 -0
- package/.aios-core/infrastructure/tools/cli/railway-cli.yaml +260 -0
- package/.aios-core/infrastructure/tools/cli/supabase-cli.yaml +224 -0
- package/.aios-core/infrastructure/tools/local/ffmpeg.yaml +261 -0
- package/.aios-core/infrastructure/tools/mcp/21st-dev-magic.yaml +127 -0
- package/.aios-core/infrastructure/tools/mcp/browser.yaml +103 -0
- package/.aios-core/infrastructure/tools/mcp/clickup.yaml +534 -0
- package/.aios-core/infrastructure/tools/mcp/context7.yaml +78 -0
- package/.aios-core/infrastructure/tools/mcp/desktop-commander.yaml +180 -0
- package/.aios-core/infrastructure/tools/mcp/exa.yaml +103 -0
- package/.aios-core/infrastructure/tools/mcp/google-workspace.yaml +930 -0
- package/.aios-core/infrastructure/tools/mcp/n8n.yaml +551 -0
- package/.aios-core/infrastructure/tools/mcp/supabase.yaml +808 -0
- package/.aios-core/install-manifest.yaml +347 -0
- package/.aios-core/manifests/agents.csv +1 -0
- package/.aios-core/manifests/schema/manifest-schema.json +190 -0
- package/.aios-core/manifests/tasks.csv +121 -0
- package/.aios-core/manifests/workers.csv +204 -0
- package/.aios-core/package.json +103 -0
- package/.aios-core/product/README.md +56 -0
- package/.aios-core/product/checklists/architect-checklist.md +444 -0
- package/.aios-core/product/checklists/change-checklist.md +183 -0
- package/.aios-core/product/checklists/database-design-checklist.md +119 -0
- package/.aios-core/product/checklists/dba-predeploy-checklist.md +97 -0
- package/.aios-core/product/checklists/dba-rollback-checklist.md +99 -0
- package/.aios-core/product/checklists/pm-checklist.md +376 -0
- package/.aios-core/product/checklists/po-master-checklist.md +442 -0
- package/.aios-core/product/checklists/pre-push-checklist.md +108 -0
- package/.aios-core/product/checklists/release-checklist.md +122 -0
- package/.aios-core/product/checklists/story-dod-checklist.md +102 -0
- package/.aios-core/product/checklists/story-draft-checklist.md +216 -0
- package/.aios-core/product/data/brainstorming-techniques.md +37 -0
- package/.aios-core/product/data/elicitation-methods.md +135 -0
- package/.aios-core/product/data/mode-selection-best-practices.md +471 -0
- package/.aios-core/product/data/test-levels-framework.md +149 -0
- package/.aios-core/product/data/test-priorities-matrix.md +175 -0
- package/.aios-core/product/templates/1mcp-config.yaml +225 -0
- package/.aios-core/product/templates/activation-instructions-inline-greeting.yaml +63 -0
- package/.aios-core/product/templates/activation-instructions-template.md +258 -0
- package/.aios-core/product/templates/adr.hbs +125 -0
- package/.aios-core/product/templates/agent-template.yaml +121 -0
- package/.aios-core/product/templates/architecture-tmpl.yaml +651 -0
- package/.aios-core/product/templates/brainstorming-output-tmpl.yaml +156 -0
- package/.aios-core/product/templates/brownfield-architecture-tmpl.yaml +476 -0
- package/.aios-core/product/templates/brownfield-prd-tmpl.yaml +280 -0
- package/.aios-core/product/templates/changelog-template.md +134 -0
- package/.aios-core/product/templates/command-rationalization-matrix.md +152 -0
- package/.aios-core/product/templates/competitor-analysis-tmpl.yaml +293 -0
- package/.aios-core/product/templates/component-react-tmpl.tsx +98 -0
- package/.aios-core/product/templates/dbdr.hbs +241 -0
- package/.aios-core/product/templates/design-story-tmpl.yaml +587 -0
- package/.aios-core/product/templates/ds-artifact-analysis.md +70 -0
- package/.aios-core/product/templates/engine/elicitation.js +298 -0
- package/.aios-core/product/templates/engine/index.js +308 -0
- package/.aios-core/product/templates/engine/loader.js +231 -0
- package/.aios-core/product/templates/engine/renderer.js +343 -0
- package/.aios-core/product/templates/engine/schemas/adr.schema.json +102 -0
- package/.aios-core/product/templates/engine/schemas/dbdr.schema.json +205 -0
- package/.aios-core/product/templates/engine/schemas/epic.schema.json +175 -0
- package/.aios-core/product/templates/engine/schemas/pmdr.schema.json +175 -0
- package/.aios-core/product/templates/engine/schemas/prd-v2.schema.json +300 -0
- package/.aios-core/product/templates/engine/schemas/prd.schema.json +152 -0
- package/.aios-core/product/templates/engine/schemas/story.schema.json +222 -0
- package/.aios-core/product/templates/engine/schemas/task.schema.json +154 -0
- package/.aios-core/product/templates/engine/validator.js +294 -0
- package/.aios-core/product/templates/epic.hbs +212 -0
- package/.aios-core/product/templates/eslintrc-security.json +32 -0
- package/.aios-core/product/templates/front-end-architecture-tmpl.yaml +206 -0
- package/.aios-core/product/templates/front-end-spec-tmpl.yaml +349 -0
- package/.aios-core/product/templates/fullstack-architecture-tmpl.yaml +805 -0
- package/.aios-core/product/templates/github-actions-cd.yml +212 -0
- package/.aios-core/product/templates/github-actions-ci.yml +172 -0
- package/.aios-core/product/templates/github-pr-template.md +67 -0
- package/.aios-core/product/templates/gordon-mcp.yaml +140 -0
- package/.aios-core/product/templates/ide-rules/antigravity-rules.md +115 -0
- package/.aios-core/product/templates/ide-rules/claude-rules.md +221 -0
- package/.aios-core/product/templates/ide-rules/cline-rules.md +84 -0
- package/.aios-core/product/templates/ide-rules/copilot-rules.md +92 -0
- package/.aios-core/product/templates/ide-rules/cursor-rules.md +115 -0
- package/.aios-core/product/templates/ide-rules/gemini-rules.md +85 -0
- package/.aios-core/product/templates/ide-rules/roo-rules.md +86 -0
- package/.aios-core/product/templates/ide-rules/trae-rules.md +104 -0
- package/.aios-core/product/templates/ide-rules/windsurf-rules.md +80 -0
- package/.aios-core/product/templates/index-strategy-tmpl.yaml +53 -0
- package/.aios-core/product/templates/market-research-tmpl.yaml +252 -0
- package/.aios-core/product/templates/mcp-workflow.js +271 -0
- package/.aios-core/product/templates/migration-plan-tmpl.yaml +1022 -0
- package/.aios-core/product/templates/migration-strategy-tmpl.md +524 -0
- package/.aios-core/product/templates/personalized-agent-template.md +258 -0
- package/.aios-core/product/templates/personalized-checklist-template.md +340 -0
- package/.aios-core/product/templates/personalized-task-template-v2.md +905 -0
- package/.aios-core/product/templates/personalized-task-template.md +344 -0
- package/.aios-core/product/templates/personalized-template-file.yaml +322 -0
- package/.aios-core/product/templates/personalized-workflow-template.yaml +460 -0
- package/.aios-core/product/templates/pmdr.hbs +186 -0
- package/.aios-core/product/templates/prd-tmpl.yaml +202 -0
- package/.aios-core/product/templates/prd-v2.0.hbs +216 -0
- package/.aios-core/product/templates/prd.hbs +201 -0
- package/.aios-core/product/templates/project-brief-tmpl.yaml +221 -0
- package/.aios-core/product/templates/qa-gate-tmpl.yaml +240 -0
- package/.aios-core/product/templates/rls-policies-tmpl.yaml +1203 -0
- package/.aios-core/product/templates/schema-design-tmpl.yaml +428 -0
- package/.aios-core/product/templates/shock-report-tmpl.html +502 -0
- package/.aios-core/product/templates/state-persistence-tmpl.yaml +219 -0
- package/.aios-core/product/templates/story-tmpl.yaml +332 -0
- package/.aios-core/product/templates/story.hbs +263 -0
- package/.aios-core/product/templates/task-execution-report.md +495 -0
- package/.aios-core/product/templates/task-template.md +123 -0
- package/.aios-core/product/templates/task.hbs +170 -0
- package/.aios-core/product/templates/tmpl-comment-on-examples.sql +158 -0
- package/.aios-core/product/templates/tmpl-migration-script.sql +91 -0
- package/.aios-core/product/templates/tmpl-rls-granular-policies.sql +104 -0
- package/.aios-core/product/templates/tmpl-rls-kiss-policy.sql +10 -0
- package/.aios-core/product/templates/tmpl-rls-roles.sql +135 -0
- package/.aios-core/product/templates/tmpl-rls-simple.sql +77 -0
- package/.aios-core/product/templates/tmpl-rls-tenant.sql +152 -0
- package/.aios-core/product/templates/tmpl-rollback-script.sql +77 -0
- package/.aios-core/product/templates/tmpl-seed-data.sql +140 -0
- package/.aios-core/product/templates/tmpl-smoke-test.sql +16 -0
- package/.aios-core/product/templates/tmpl-staging-copy-merge.sql +139 -0
- package/.aios-core/product/templates/tmpl-stored-proc.sql +140 -0
- package/.aios-core/product/templates/tmpl-trigger.sql +152 -0
- package/.aios-core/product/templates/tmpl-view-materialized.sql +133 -0
- package/.aios-core/product/templates/tmpl-view.sql +177 -0
- package/.aios-core/product/templates/token-exports-css-tmpl.css +240 -0
- package/.aios-core/product/templates/token-exports-tailwind-tmpl.js +395 -0
- package/.aios-core/product/templates/tokens-schema-tmpl.yaml +305 -0
- package/.aios-core/product/templates/workflow-template.yaml +134 -0
- package/.aios-core/quality/metrics-collector.js +572 -0
- package/.aios-core/quality/metrics-hook.js +260 -0
- package/.aios-core/quality/schemas/quality-metrics.schema.json +233 -0
- package/.aios-core/quality/seed-metrics.js +336 -0
- package/.aios-core/scripts/README.md +354 -0
- package/.aios-core/scripts/aios-doc-template.md +325 -0
- package/.aios-core/scripts/batch-migrate-phase1.ps1 +36 -0
- package/.aios-core/scripts/batch-migrate-phase2.ps1 +88 -0
- package/.aios-core/scripts/batch-migrate-phase3.ps1 +45 -0
- package/.aios-core/scripts/command-execution-hook.js +201 -0
- package/.aios-core/scripts/context-detector.js +226 -0
- package/.aios-core/scripts/elicitation-engine.js +385 -0
- package/.aios-core/scripts/elicitation-session-manager.js +300 -0
- package/.aios-core/scripts/migrate-framework-docs.sh +300 -0
- package/.aios-core/scripts/session-context-loader.js +286 -0
- package/.aios-core/scripts/test-template-system.js +941 -0
- package/.aios-core/scripts/validate-phase1.ps1 +35 -0
- package/.aios-core/scripts/workflow-management.md +69 -0
- package/.aios-core/tasks/find-component.md.legacy +391 -0
- package/.aios-core/tasks/generate-commit-message.md.legacy +426 -0
- package/.aios-core/tasks/generate-migration.md.legacy +382 -0
- package/.aios-core/tasks/rollback-modification.md.legacy +307 -0
- package/.aios-core/tasks/update-tests.md.legacy +283 -0
- package/.aios-core/user-guide.md +1413 -0
- package/.aios-core/working-in-the-brownfield.md +361 -0
- package/.claude/CLAUDE.md +221 -0
- package/LICENSE +48 -0
- package/README.md +703 -0
- package/bin/aios-init-old.js +532 -0
- package/bin/aios-init-v4.js +390 -0
- package/bin/aios-init.backup-v1.1.4.js +352 -0
- package/bin/aios-init.js +736 -0
- package/bin/aios-minimal.js +26 -0
- package/bin/aios.js +279 -0
- package/bin/migrate-pm-config.js +219 -0
- package/bin/modules/env-config.js +436 -0
- package/bin/modules/mcp-installer.js +383 -0
- package/bin/utils/install-errors.js +339 -0
- package/bin/utils/install-transaction.js +445 -0
- package/index.d.ts +19 -0
- package/index.esm.js +21 -0
- package/index.js +94 -0
- package/package.json +161 -0
- package/packages/installer/package.json +39 -0
- package/packages/installer/src/config/configure-environment.js +312 -0
- package/packages/installer/src/config/templates/core-config-template.js +183 -0
- package/packages/installer/src/config/templates/env-template.js +127 -0
- package/packages/installer/src/config/validation/config-validator.js +243 -0
- package/packages/installer/src/detection/detect-project-type.js +81 -0
- package/packages/installer/src/wizard/wizard.js +244 -0
- package/packages/installer/tests/integration/environment-configuration.test.js +328 -0
- package/packages/installer/tests/integration/wizard-detection.test.js +349 -0
- package/packages/installer/tests/unit/config-validator.test.js +315 -0
- package/packages/installer/tests/unit/detection/detect-project-type.test.js +401 -0
- package/packages/installer/tests/unit/env-template.test.js +185 -0
- package/src/config/ide-configs.js +189 -0
- package/src/installer/aios-core-installer.js +319 -0
- package/src/installer/dependency-installer.js +335 -0
- package/src/utils/aios-colors.js +234 -0
- package/src/wizard/feedback.js +218 -0
- package/src/wizard/ide-config-generator.js +488 -0
- package/src/wizard/ide-selector.js +84 -0
- package/src/wizard/index.js +589 -0
- package/src/wizard/questions.js +249 -0
- package/src/wizard/validation/index.js +120 -0
- package/src/wizard/validation/report-generator.js +269 -0
- package/src/wizard/validation/troubleshooting-system.js +346 -0
- package/src/wizard/validation/validators/config-validator.js +362 -0
- package/src/wizard/validation/validators/dependency-validator.js +333 -0
- package/src/wizard/validation/validators/file-structure-validator.js +181 -0
- package/src/wizard/validation/validators/mcp-health-checker.js +310 -0
- package/src/wizard/validators.js +274 -0
- package/templates/squad/LICENSE +21 -0
- package/templates/squad/README.md +37 -0
- package/templates/squad/agents/example-agent.yaml +36 -0
- package/templates/squad/package.json +19 -0
- package/templates/squad/squad.yaml +25 -0
- package/templates/squad/tasks/example-task.yaml +46 -0
- package/templates/squad/templates/example-template.md +24 -0
- package/templates/squad/tests/example-agent.test.js +53 -0
- package/templates/squad/workflows/example-workflow.yaml +54 -0
- package/tools/package-builder.js +35 -0
|
@@ -0,0 +1,1432 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AIOS Documentation Synchronizer
|
|
3
|
+
*
|
|
4
|
+
* Automatically synchronizes documentation with code changes,
|
|
5
|
+
* ensuring documentation stays up-to-date with implementation.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs').promises;
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const { EventEmitter } = require('events');
|
|
11
|
+
const parser = require('@babel/parser');
|
|
12
|
+
const traverse = require('@babel/traverse').default;
|
|
13
|
+
const generate = require('@babel/generator').default;
|
|
14
|
+
const t = require('@babel/types');
|
|
15
|
+
const yaml = require('yaml');
|
|
16
|
+
const marked = require('marked');
|
|
17
|
+
|
|
18
|
+
class DocumentationSynchronizer extends EventEmitter {
|
|
19
|
+
constructor(options = {}) {
|
|
20
|
+
super();
|
|
21
|
+
this.rootPath = options.rootPath || process.cwd();
|
|
22
|
+
this.syncedComponents = new Map();
|
|
23
|
+
this.documentationIndex = new Map();
|
|
24
|
+
this.syncHistory = [];
|
|
25
|
+
this.options = {
|
|
26
|
+
autoSync: options.autoSync !== false,
|
|
27
|
+
syncInterval: options.syncInterval || 60000, // 1 minute
|
|
28
|
+
docFormats: options.docFormats || ['.md', '.yaml', '.yml', '.json'],
|
|
29
|
+
codeFormats: options.codeFormats || ['.js', '.jsx', '.ts', '.tsx'],
|
|
30
|
+
syncStrategies: options.syncStrategies || ['jsdoc', 'markdown', 'schema', 'api', 'examples'],
|
|
31
|
+
...options,
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
this.syncStrategies = new Map();
|
|
35
|
+
this.initializeSyncStrategies();
|
|
36
|
+
|
|
37
|
+
if (this.options.autoSync) {
|
|
38
|
+
this.startAutoSync();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
initializeSyncStrategies() {
|
|
43
|
+
// JSDoc synchronization
|
|
44
|
+
this.syncStrategies.set('jsdoc', {
|
|
45
|
+
name: 'JSDoc Synchronization',
|
|
46
|
+
description: 'Sync JSDoc comments with markdown documentation',
|
|
47
|
+
detector: this.detectJSDocChanges.bind(this),
|
|
48
|
+
synchronizer: this.syncJSDoc.bind(this),
|
|
49
|
+
priority: 'high',
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// Markdown documentation
|
|
53
|
+
this.syncStrategies.set('markdown', {
|
|
54
|
+
name: 'Markdown Documentation',
|
|
55
|
+
description: 'Update markdown files with code changes',
|
|
56
|
+
detector: this.detectMarkdownChanges.bind(this),
|
|
57
|
+
synchronizer: this.syncMarkdown.bind(this),
|
|
58
|
+
priority: 'medium',
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Schema synchronization
|
|
62
|
+
this.syncStrategies.set('schema', {
|
|
63
|
+
name: 'Schema Documentation',
|
|
64
|
+
description: 'Sync YAML/JSON schemas with code structures',
|
|
65
|
+
detector: this.detectSchemaChanges.bind(this),
|
|
66
|
+
synchronizer: this.syncSchema.bind(this),
|
|
67
|
+
priority: 'high',
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// API documentation
|
|
71
|
+
this.syncStrategies.set('api', {
|
|
72
|
+
name: 'API Documentation',
|
|
73
|
+
description: 'Update API documentation with endpoint changes',
|
|
74
|
+
detector: this.detectAPIChanges.bind(this),
|
|
75
|
+
synchronizer: this.syncAPI.bind(this),
|
|
76
|
+
priority: 'high',
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Code examples
|
|
80
|
+
this.syncStrategies.set('examples', {
|
|
81
|
+
name: 'Code Examples',
|
|
82
|
+
description: 'Update code examples in documentation',
|
|
83
|
+
detector: this.detectExampleChanges.bind(this),
|
|
84
|
+
synchronizer: this.syncExamples.bind(this),
|
|
85
|
+
priority: 'medium',
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async initialize() {
|
|
90
|
+
try {
|
|
91
|
+
// Build documentation index
|
|
92
|
+
await this.buildDocumentationIndex();
|
|
93
|
+
|
|
94
|
+
// Analyze code-documentation relationships
|
|
95
|
+
await this.analyzeRelationships();
|
|
96
|
+
|
|
97
|
+
this.emit('initialized', {
|
|
98
|
+
documentationFiles: this.documentationIndex.size,
|
|
99
|
+
syncedComponents: this.syncedComponents.size,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
} catch (error) {
|
|
103
|
+
this.emit('error', { phase: 'initialization', error });
|
|
104
|
+
throw error;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async buildDocumentationIndex() {
|
|
109
|
+
const docFiles = await this.findDocumentationFiles();
|
|
110
|
+
|
|
111
|
+
for (const docFile of docFiles) {
|
|
112
|
+
try {
|
|
113
|
+
const content = await fs.readFile(docFile, 'utf-8');
|
|
114
|
+
const metadata = await this.extractDocumentationMetadata(docFile, content);
|
|
115
|
+
|
|
116
|
+
this.documentationIndex.set(docFile, {
|
|
117
|
+
path: docFile,
|
|
118
|
+
content,
|
|
119
|
+
metadata,
|
|
120
|
+
lastSync: null,
|
|
121
|
+
linkedComponents: [],
|
|
122
|
+
});
|
|
123
|
+
} catch (error) {
|
|
124
|
+
console.warn(`Failed to index documentation: ${docFile}`, error);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async findDocumentationFiles() {
|
|
130
|
+
const files = [];
|
|
131
|
+
const docsDir = path.join(this.rootPath, 'docs');
|
|
132
|
+
const readmeFiles = ['README.md', 'readme.md', 'README.MD'];
|
|
133
|
+
|
|
134
|
+
// Find documentation in docs directory
|
|
135
|
+
if (await this.exists(docsDir)) {
|
|
136
|
+
await this.scanDirectory(docsDir, files);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Find README files throughout the project
|
|
140
|
+
await this.scanForReadme(this.rootPath, files, readmeFiles);
|
|
141
|
+
|
|
142
|
+
// Find inline documentation (markdown in code directories)
|
|
143
|
+
await this.scanForInlineDocs(this.rootPath, files);
|
|
144
|
+
|
|
145
|
+
return files;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
async scanDirectory(dir, files) {
|
|
149
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
150
|
+
|
|
151
|
+
for (const entry of entries) {
|
|
152
|
+
const fullPath = path.join(dir, entry.name);
|
|
153
|
+
|
|
154
|
+
if (entry.isDirectory() && !entry.name.startsWith('.')) {
|
|
155
|
+
await this.scanDirectory(fullPath, files);
|
|
156
|
+
} else if (entry.isFile()) {
|
|
157
|
+
const ext = path.extname(entry.name);
|
|
158
|
+
if (this.options.docFormats.includes(ext)) {
|
|
159
|
+
files.push(fullPath);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
async extractDocumentationMetadata(filePath, content) {
|
|
166
|
+
const metadata = {
|
|
167
|
+
title: null,
|
|
168
|
+
description: null,
|
|
169
|
+
linkedFiles: [],
|
|
170
|
+
codeBlocks: [],
|
|
171
|
+
schemas: [],
|
|
172
|
+
apis: [],
|
|
173
|
+
lastModified: null,
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
const ext = path.extname(filePath);
|
|
177
|
+
|
|
178
|
+
if (ext === '.md') {
|
|
179
|
+
// Extract markdown metadata
|
|
180
|
+
const lines = content.split('\n');
|
|
181
|
+
|
|
182
|
+
// Find title
|
|
183
|
+
const titleMatch = lines.find(line => line.startsWith('# '));
|
|
184
|
+
if (titleMatch) {
|
|
185
|
+
metadata.title = titleMatch.substring(2).trim();
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Find code blocks
|
|
189
|
+
const codeBlockRegex = /```(\w+)?\n([\s\S]*?)```/g;
|
|
190
|
+
let match;
|
|
191
|
+
while ((match = codeBlockRegex.exec(content)) !== null) {
|
|
192
|
+
metadata.codeBlocks.push({
|
|
193
|
+
language: match[1] || 'text',
|
|
194
|
+
code: match[2].trim(),
|
|
195
|
+
startIndex: match.index,
|
|
196
|
+
endIndex: match.index + match[0].length,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Find file references
|
|
201
|
+
const fileRefRegex = /\[([^\]]+)\]\(([^)]+)\)/g;
|
|
202
|
+
while ((match = fileRefRegex.exec(content)) !== null) {
|
|
203
|
+
if (match[2].endsWith('.js') || match[2].endsWith('.ts')) {
|
|
204
|
+
metadata.linkedFiles.push({
|
|
205
|
+
text: match[1],
|
|
206
|
+
path: match[2],
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
} else if (ext === '.yaml' || ext === '.yml') {
|
|
211
|
+
// Extract YAML metadata
|
|
212
|
+
try {
|
|
213
|
+
const data = yaml.parse(content);
|
|
214
|
+
metadata.title = data.name || data.title || path.basename(filePath, ext);
|
|
215
|
+
metadata.description = data.description;
|
|
216
|
+
metadata.schemas.push(data);
|
|
217
|
+
} catch (error) {
|
|
218
|
+
console.warn(`Failed to parse YAML: ${filePath}`, error);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Get file stats
|
|
223
|
+
const stats = await fs.stat(filePath);
|
|
224
|
+
metadata.lastModified = stats.mtime;
|
|
225
|
+
|
|
226
|
+
return metadata;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
async analyzeRelationships() {
|
|
230
|
+
// Find relationships between code and documentation
|
|
231
|
+
for (const [docPath, docInfo] of this.documentationIndex) {
|
|
232
|
+
const relationships = await this.findCodeRelationships(docPath, docInfo);
|
|
233
|
+
|
|
234
|
+
for (const relationship of relationships) {
|
|
235
|
+
this.syncedComponents.set(relationship.codePath, {
|
|
236
|
+
codePath: relationship.codePath,
|
|
237
|
+
docPath: docPath,
|
|
238
|
+
type: relationship.type,
|
|
239
|
+
lastSync: null,
|
|
240
|
+
syncStrategies: relationship.strategies,
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
docInfo.linkedComponents.push(relationship.codePath);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
async findCodeRelationships(docPath, docInfo) {
|
|
249
|
+
const relationships = [];
|
|
250
|
+
const docDir = path.dirname(docPath);
|
|
251
|
+
const docName = path.basename(docPath, path.extname(docPath));
|
|
252
|
+
|
|
253
|
+
// Strategy 1: Same directory, same name
|
|
254
|
+
const codeExtensions = ['.js', '.jsx', '.ts', '.tsx'];
|
|
255
|
+
for (const ext of codeExtensions) {
|
|
256
|
+
const codePath = path.join(docDir, docName + ext);
|
|
257
|
+
if (await this.exists(codePath)) {
|
|
258
|
+
relationships.push({
|
|
259
|
+
codePath,
|
|
260
|
+
type: 'same-name',
|
|
261
|
+
strategies: ['jsdoc', 'examples'],
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Strategy 2: Referenced files in documentation
|
|
267
|
+
for (const linkedFile of docInfo.metadata.linkedFiles) {
|
|
268
|
+
const codePath = path.resolve(docDir, linkedFile.path);
|
|
269
|
+
if (await this.exists(codePath)) {
|
|
270
|
+
relationships.push({
|
|
271
|
+
codePath,
|
|
272
|
+
type: 'referenced',
|
|
273
|
+
strategies: ['jsdoc', 'api', 'examples'],
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Strategy 3: Agent/Task/Workflow documentation
|
|
279
|
+
if (docPath.includes('agents') || docPath.includes('tasks') || docPath.includes('workflows')) {
|
|
280
|
+
const componentType = docPath.includes('agents') ? 'agent' :
|
|
281
|
+
docPath.includes('tasks') ? 'task' : 'workflow';
|
|
282
|
+
|
|
283
|
+
// Find manifest file
|
|
284
|
+
const manifestPath = path.join(docDir, 'manifest.yaml');
|
|
285
|
+
if (await this.exists(manifestPath)) {
|
|
286
|
+
relationships.push({
|
|
287
|
+
codePath: manifestPath,
|
|
288
|
+
type: componentType,
|
|
289
|
+
strategies: ['schema', 'markdown'],
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return relationships;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
async synchronizeComponent(componentPath, options = {}) {
|
|
298
|
+
const component = this.syncedComponents.get(componentPath);
|
|
299
|
+
if (!component) {
|
|
300
|
+
throw new Error(`Component not found in sync registry: ${componentPath}`);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const doc = this.documentationIndex.get(component.docPath);
|
|
304
|
+
if (!doc) {
|
|
305
|
+
throw new Error(`Documentation not found: ${component.docPath}`);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const changes = [];
|
|
309
|
+
const strategies = options.strategies || component.syncStrategies;
|
|
310
|
+
|
|
311
|
+
for (const strategyName of strategies) {
|
|
312
|
+
const strategy = this.syncStrategies.get(strategyName);
|
|
313
|
+
if (!strategy) continue;
|
|
314
|
+
|
|
315
|
+
try {
|
|
316
|
+
// Detect changes
|
|
317
|
+
const detected = await strategy.detector(componentPath, component.docPath);
|
|
318
|
+
|
|
319
|
+
if (detected && detected.length > 0) {
|
|
320
|
+
// Apply synchronization
|
|
321
|
+
const result = await strategy.synchronizer(
|
|
322
|
+
componentPath,
|
|
323
|
+
component.docPath,
|
|
324
|
+
detected,
|
|
325
|
+
options,
|
|
326
|
+
);
|
|
327
|
+
|
|
328
|
+
changes.push({
|
|
329
|
+
strategy: strategyName,
|
|
330
|
+
changes: result.changes,
|
|
331
|
+
success: result.success,
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
} catch (error) {
|
|
335
|
+
changes.push({
|
|
336
|
+
strategy: strategyName,
|
|
337
|
+
error: error.message,
|
|
338
|
+
success: false,
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Update sync metadata
|
|
344
|
+
component.lastSync = new Date().toISOString();
|
|
345
|
+
doc.lastSync = new Date().toISOString();
|
|
346
|
+
|
|
347
|
+
// Record in history
|
|
348
|
+
this.syncHistory.push({
|
|
349
|
+
timestamp: new Date().toISOString(),
|
|
350
|
+
componentPath,
|
|
351
|
+
docPath: component.docPath,
|
|
352
|
+
changes,
|
|
353
|
+
success: changes.every(c => c.success),
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
this.emit('synchronized', {
|
|
357
|
+
componentPath,
|
|
358
|
+
docPath: component.docPath,
|
|
359
|
+
changes,
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
return changes;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
async detectJSDocChanges(codePath, docPath) {
|
|
366
|
+
const changes = [];
|
|
367
|
+
|
|
368
|
+
try {
|
|
369
|
+
const codeContent = await fs.readFile(codePath, 'utf-8');
|
|
370
|
+
const docContent = await fs.readFile(docPath, 'utf-8');
|
|
371
|
+
|
|
372
|
+
// Parse code for JSDoc comments
|
|
373
|
+
const jsdocComments = await this.extractJSDocComments(codeContent);
|
|
374
|
+
|
|
375
|
+
// Find corresponding sections in documentation
|
|
376
|
+
for (const jsdoc of jsdocComments) {
|
|
377
|
+
const docSection = this.findDocumentationSection(
|
|
378
|
+
docContent,
|
|
379
|
+
jsdoc.name,
|
|
380
|
+
jsdoc.type,
|
|
381
|
+
);
|
|
382
|
+
|
|
383
|
+
if (docSection) {
|
|
384
|
+
// Compare and detect changes
|
|
385
|
+
const diff = this.compareJSDocWithDoc(jsdoc, docSection);
|
|
386
|
+
if (diff) {
|
|
387
|
+
changes.push({
|
|
388
|
+
type: 'jsdoc-update',
|
|
389
|
+
name: jsdoc.name,
|
|
390
|
+
jsdoc,
|
|
391
|
+
docSection,
|
|
392
|
+
diff,
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
} else {
|
|
396
|
+
// New function/class not in documentation
|
|
397
|
+
changes.push({
|
|
398
|
+
type: 'jsdoc-new',
|
|
399
|
+
name: jsdoc.name,
|
|
400
|
+
jsdoc,
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
} catch (error) {
|
|
405
|
+
console.error(`Error detecting JSDoc changes: ${error.message}`);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
return changes;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
async extractJSDocComments(codeContent) {
|
|
412
|
+
const comments = [];
|
|
413
|
+
|
|
414
|
+
try {
|
|
415
|
+
const ast = parser.parse(codeContent, {
|
|
416
|
+
sourceType: 'module',
|
|
417
|
+
plugins: ['jsx', 'typescript'],
|
|
418
|
+
attachComment: true,
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
traverse(ast, {
|
|
422
|
+
enter(path) {
|
|
423
|
+
if (path.node.leadingComments) {
|
|
424
|
+
for (const comment of path.node.leadingComments) {
|
|
425
|
+
if (comment.type === 'CommentBlock' && comment.value.startsWith('*')) {
|
|
426
|
+
const jsdoc = this.parseJSDoc(comment.value);
|
|
427
|
+
if (jsdoc) {
|
|
428
|
+
// Attach the associated node info
|
|
429
|
+
if (t.isFunctionDeclaration(path.node) || t.isClassDeclaration(path.node)) {
|
|
430
|
+
jsdoc.name = path.node.id?.name;
|
|
431
|
+
jsdoc.type = path.node.type;
|
|
432
|
+
} else if (t.isVariableDeclarator(path.node)) {
|
|
433
|
+
jsdoc.name = path.node.id?.name;
|
|
434
|
+
jsdoc.type = 'VariableDeclarator';
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
if (jsdoc.name) {
|
|
438
|
+
comments.push(jsdoc);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
},
|
|
445
|
+
});
|
|
446
|
+
} catch (error) {
|
|
447
|
+
console.error(`Error parsing code: ${error.message}`);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
return comments;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
parseJSDoc(commentText) {
|
|
454
|
+
const jsdoc = {
|
|
455
|
+
description: '',
|
|
456
|
+
params: [],
|
|
457
|
+
returns: null,
|
|
458
|
+
examples: [],
|
|
459
|
+
tags: {},
|
|
460
|
+
};
|
|
461
|
+
|
|
462
|
+
const lines = commentText.split('\n').map(line =>
|
|
463
|
+
line.trim().replace(/^\* ?/, ''),
|
|
464
|
+
);
|
|
465
|
+
|
|
466
|
+
let currentSection = 'description';
|
|
467
|
+
let currentParam = null;
|
|
468
|
+
|
|
469
|
+
for (const line of lines) {
|
|
470
|
+
if (line.startsWith('@param')) {
|
|
471
|
+
const paramMatch = line.match(/@param\s+(?:\{([^}]+)\}\s+)?(\w+)(?:\s+-\s+(.*))?/);
|
|
472
|
+
if (paramMatch) {
|
|
473
|
+
currentParam = {
|
|
474
|
+
type: paramMatch[1],
|
|
475
|
+
name: paramMatch[2],
|
|
476
|
+
description: paramMatch[3] || '',
|
|
477
|
+
};
|
|
478
|
+
jsdoc.params.push(currentParam);
|
|
479
|
+
currentSection = 'param';
|
|
480
|
+
}
|
|
481
|
+
} else if (line.startsWith('@returns') || line.startsWith('@return')) {
|
|
482
|
+
const returnMatch = line.match(/@returns?\s+(?:\{([^}]+)\}\s+)?(.*)$/);
|
|
483
|
+
if (returnMatch) {
|
|
484
|
+
jsdoc.returns = {
|
|
485
|
+
type: returnMatch[1],
|
|
486
|
+
description: returnMatch[2] || '',
|
|
487
|
+
};
|
|
488
|
+
currentSection = 'returns';
|
|
489
|
+
}
|
|
490
|
+
} else if (line.startsWith('@example')) {
|
|
491
|
+
currentSection = 'example';
|
|
492
|
+
jsdoc.examples.push('');
|
|
493
|
+
} else if (line.startsWith('@')) {
|
|
494
|
+
const tagMatch = line.match(/@(\w+)(?:\s+(.*))?/);
|
|
495
|
+
if (tagMatch) {
|
|
496
|
+
jsdoc.tags[tagMatch[1]] = tagMatch[2] || true;
|
|
497
|
+
currentSection = tagMatch[1];
|
|
498
|
+
}
|
|
499
|
+
} else if (line) {
|
|
500
|
+
// Continue current section
|
|
501
|
+
if (currentSection === 'description') {
|
|
502
|
+
jsdoc.description += (jsdoc.description ? '\n' : '') + line;
|
|
503
|
+
} else if (currentSection === 'param' && currentParam) {
|
|
504
|
+
currentParam.description += (currentParam.description ? '\n' : '') + line;
|
|
505
|
+
} else if (currentSection === 'returns' && jsdoc.returns) {
|
|
506
|
+
jsdoc.returns.description += (jsdoc.returns.description ? '\n' : '') + line;
|
|
507
|
+
} else if (currentSection === 'example' && jsdoc.examples.length > 0) {
|
|
508
|
+
const lastExample = jsdoc.examples.length - 1;
|
|
509
|
+
jsdoc.examples[lastExample] += (jsdoc.examples[lastExample] ? '\n' : '') + line;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
return jsdoc;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
async syncJSDoc(codePath, docPath, changes, options = {}) {
|
|
518
|
+
const result = {
|
|
519
|
+
changes: [],
|
|
520
|
+
success: true,
|
|
521
|
+
};
|
|
522
|
+
|
|
523
|
+
try {
|
|
524
|
+
let docContent = await fs.readFile(docPath, 'utf-8');
|
|
525
|
+
const backup = docContent; // Keep backup for rollback
|
|
526
|
+
|
|
527
|
+
for (const change of changes) {
|
|
528
|
+
if (change.type === 'jsdoc-update') {
|
|
529
|
+
// Update existing documentation section
|
|
530
|
+
docContent = this.updateDocumentationSection(
|
|
531
|
+
docContent,
|
|
532
|
+
change.name,
|
|
533
|
+
change.jsdoc,
|
|
534
|
+
change.docSection,
|
|
535
|
+
);
|
|
536
|
+
|
|
537
|
+
result.changes.push({
|
|
538
|
+
type: 'updated',
|
|
539
|
+
name: change.name,
|
|
540
|
+
description: `Updated documentation for ${change.name}`,
|
|
541
|
+
});
|
|
542
|
+
} else if (change.type === 'jsdoc-new') {
|
|
543
|
+
// Add new documentation section
|
|
544
|
+
docContent = this.addDocumentationSection(
|
|
545
|
+
docContent,
|
|
546
|
+
change.jsdoc,
|
|
547
|
+
);
|
|
548
|
+
|
|
549
|
+
result.changes.push({
|
|
550
|
+
type: 'added',
|
|
551
|
+
name: change.name,
|
|
552
|
+
description: `Added documentation for ${change.name}`,
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
// Write updated documentation
|
|
558
|
+
if (docContent !== backup) {
|
|
559
|
+
await fs.writeFile(docPath, docContent);
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
} catch (error) {
|
|
563
|
+
result.success = false;
|
|
564
|
+
result.error = error.message;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
return result;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
findDocumentationSection(docContent, name, type) {
|
|
571
|
+
// Look for section headers that match the function/class name
|
|
572
|
+
const patterns = [
|
|
573
|
+
new RegExp(`^#+\\s*${name}\\s*$`, 'gm'),
|
|
574
|
+
new RegExp(`^#+\\s*\\W?${name}\\(`, 'gm'),
|
|
575
|
+
new RegExp(`^#+\\s*class\\s+${name}`, 'gm'),
|
|
576
|
+
new RegExp(`^#+\\s*function\\s+${name}`, 'gm'),
|
|
577
|
+
];
|
|
578
|
+
|
|
579
|
+
for (const pattern of patterns) {
|
|
580
|
+
const match = pattern.exec(docContent);
|
|
581
|
+
if (match) {
|
|
582
|
+
// Extract section content
|
|
583
|
+
const startIndex = match.index;
|
|
584
|
+
const headerLevel = match[0].match(/^#+/)[0].length;
|
|
585
|
+
|
|
586
|
+
// Find end of section (next header of same or higher level)
|
|
587
|
+
const endPattern = new RegExp(`^#{1,${headerLevel}}\\s`, 'gm');
|
|
588
|
+
endPattern.lastIndex = startIndex + match[0].length;
|
|
589
|
+
|
|
590
|
+
const endMatch = endPattern.exec(docContent);
|
|
591
|
+
const endIndex = endMatch ? endMatch.index : docContent.length;
|
|
592
|
+
|
|
593
|
+
return {
|
|
594
|
+
startIndex,
|
|
595
|
+
endIndex,
|
|
596
|
+
content: docContent.substring(startIndex, endIndex),
|
|
597
|
+
headerLevel,
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
return null;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
updateDocumentationSection(docContent, name, jsdoc, docSection) {
|
|
606
|
+
// Generate updated documentation
|
|
607
|
+
const updatedSection = this.generateDocumentationSection(jsdoc, docSection.headerLevel);
|
|
608
|
+
|
|
609
|
+
// Replace the section
|
|
610
|
+
return docContent.substring(0, docSection.startIndex) +
|
|
611
|
+
updatedSection +
|
|
612
|
+
docContent.substring(docSection.endIndex);
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
addDocumentationSection(docContent, jsdoc) {
|
|
616
|
+
// Find appropriate place to add the new section
|
|
617
|
+
const sectionHeader = this.generateDocumentationSection(jsdoc, 3);
|
|
618
|
+
|
|
619
|
+
// Try to find a suitable location (e.g., after "## API" or "## Functions")
|
|
620
|
+
const apiMatch = /^##\s*(API|Functions|Methods)/gm.exec(docContent);
|
|
621
|
+
|
|
622
|
+
if (apiMatch) {
|
|
623
|
+
// Find the end of the API section
|
|
624
|
+
const nextSectionMatch = /^#{1,2}\s/gm.exec(
|
|
625
|
+
docContent.substring(apiMatch.index + apiMatch[0].length),
|
|
626
|
+
);
|
|
627
|
+
|
|
628
|
+
const insertIndex = nextSectionMatch ?
|
|
629
|
+
apiMatch.index + apiMatch[0].length + nextSectionMatch.index :
|
|
630
|
+
docContent.length;
|
|
631
|
+
|
|
632
|
+
return docContent.substring(0, insertIndex) +
|
|
633
|
+
'\n\n' + sectionHeader +
|
|
634
|
+
docContent.substring(insertIndex);
|
|
635
|
+
} else {
|
|
636
|
+
// Append to end
|
|
637
|
+
return docContent + '\n\n## API\n\n' + sectionHeader;
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
generateDocumentationSection(jsdoc, headerLevel = 3) {
|
|
642
|
+
const header = '#'.repeat(headerLevel);
|
|
643
|
+
let section = `${header} ${jsdoc.name}\n\n`;
|
|
644
|
+
|
|
645
|
+
if (jsdoc.description) {
|
|
646
|
+
section += `${jsdoc.description}\n\n`;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
if (jsdoc.params.length > 0) {
|
|
650
|
+
section += '**Parameters:**\n';
|
|
651
|
+
for (const param of jsdoc.params) {
|
|
652
|
+
section += `- \`${param.name}\``;
|
|
653
|
+
if (param.type) section += ` _{${param.type}}_`;
|
|
654
|
+
if (param.description) section += ` - ${param.description}`;
|
|
655
|
+
section += '\n';
|
|
656
|
+
}
|
|
657
|
+
section += '\n';
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
if (jsdoc.returns) {
|
|
661
|
+
section += '**Returns:**\n';
|
|
662
|
+
if (jsdoc.returns.type) section += `_{${jsdoc.returns.type}}_ `;
|
|
663
|
+
section += jsdoc.returns.description + '\n\n';
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
if (jsdoc.examples.length > 0) {
|
|
667
|
+
section += '**Examples:**\n';
|
|
668
|
+
for (const example of jsdoc.examples) {
|
|
669
|
+
section += '```javascript\n';
|
|
670
|
+
section += example + '\n';
|
|
671
|
+
section += '```\n\n';
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
return section;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
async detectMarkdownChanges(codePath, docPath) {
|
|
679
|
+
// Detect changes that affect markdown documentation
|
|
680
|
+
const changes = [];
|
|
681
|
+
|
|
682
|
+
try {
|
|
683
|
+
const codeContent = await fs.readFile(codePath, 'utf-8');
|
|
684
|
+
const docContent = await fs.readFile(docPath, 'utf-8');
|
|
685
|
+
|
|
686
|
+
// Check for command pattern changes in tasks
|
|
687
|
+
if (codePath.endsWith('.md') && codePath.includes('tasks')) {
|
|
688
|
+
const commandPattern = this.extractCommandPattern(codeContent);
|
|
689
|
+
const docCommandPattern = this.extractCommandPattern(docContent);
|
|
690
|
+
|
|
691
|
+
if (commandPattern && docCommandPattern && commandPattern !== docCommandPattern) {
|
|
692
|
+
changes.push({
|
|
693
|
+
type: 'command-pattern',
|
|
694
|
+
oldPattern: docCommandPattern,
|
|
695
|
+
newPattern: commandPattern,
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
// Check for implementation changes
|
|
701
|
+
const codeBlocks = this.extractCodeBlocks(docContent);
|
|
702
|
+
for (const block of codeBlocks) {
|
|
703
|
+
if (block.language === 'javascript' || block.language === 'typescript') {
|
|
704
|
+
// Check if code block references actual implementation
|
|
705
|
+
const referenced = this.findReferencedCode(block.code, codeContent);
|
|
706
|
+
if (referenced && referenced.changed) {
|
|
707
|
+
changes.push({
|
|
708
|
+
type: 'code-block',
|
|
709
|
+
block,
|
|
710
|
+
referenced,
|
|
711
|
+
});
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
} catch (error) {
|
|
716
|
+
console.error(`Error detecting markdown changes: ${error.message}`);
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
return changes;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
async syncMarkdown(codePath, docPath, changes, options = {}) {
|
|
723
|
+
const result = {
|
|
724
|
+
changes: [],
|
|
725
|
+
success: true,
|
|
726
|
+
};
|
|
727
|
+
|
|
728
|
+
try {
|
|
729
|
+
let docContent = await fs.readFile(docPath, 'utf-8');
|
|
730
|
+
const backup = docContent;
|
|
731
|
+
|
|
732
|
+
for (const change of changes) {
|
|
733
|
+
if (change.type === 'command-pattern') {
|
|
734
|
+
// Update command pattern
|
|
735
|
+
docContent = docContent.replace(
|
|
736
|
+
change.oldPattern,
|
|
737
|
+
change.newPattern,
|
|
738
|
+
);
|
|
739
|
+
|
|
740
|
+
result.changes.push({
|
|
741
|
+
type: 'command-pattern',
|
|
742
|
+
description: 'Updated command pattern',
|
|
743
|
+
});
|
|
744
|
+
} else if (change.type === 'code-block') {
|
|
745
|
+
// Update code block
|
|
746
|
+
docContent = this.updateCodeBlock(
|
|
747
|
+
docContent,
|
|
748
|
+
change.block,
|
|
749
|
+
change.referenced.newCode,
|
|
750
|
+
);
|
|
751
|
+
|
|
752
|
+
result.changes.push({
|
|
753
|
+
type: 'code-block',
|
|
754
|
+
description: 'Updated code example',
|
|
755
|
+
});
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
if (docContent !== backup) {
|
|
760
|
+
await fs.writeFile(docPath, docContent);
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
} catch (error) {
|
|
764
|
+
result.success = false;
|
|
765
|
+
result.error = error.message;
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
return result;
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
extractCommandPattern(content) {
|
|
772
|
+
const match = content.match(/^\*[\w-]+(?:\s+<[^>]+>)*(?:\s+\[[^\]]+\])*/m);
|
|
773
|
+
return match ? match[0] : null;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
extractCodeBlocks(content) {
|
|
777
|
+
const blocks = [];
|
|
778
|
+
const regex = /```(\w+)?\n([\s\S]*?)```/g;
|
|
779
|
+
let match;
|
|
780
|
+
|
|
781
|
+
while ((match = regex.exec(content)) !== null) {
|
|
782
|
+
blocks.push({
|
|
783
|
+
language: match[1] || 'text',
|
|
784
|
+
code: match[2].trim(),
|
|
785
|
+
startIndex: match.index,
|
|
786
|
+
endIndex: match.index + match[0].length,
|
|
787
|
+
fullMatch: match[0],
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
return blocks;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
updateCodeBlock(docContent, block, newCode) {
|
|
795
|
+
const newBlock = '```' + block.language + '\n' + newCode + '\n```';
|
|
796
|
+
|
|
797
|
+
return docContent.substring(0, block.startIndex) +
|
|
798
|
+
newBlock +
|
|
799
|
+
docContent.substring(block.endIndex);
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
async detectSchemaChanges(codePath, docPath) {
|
|
803
|
+
// Detect changes in YAML/JSON schemas
|
|
804
|
+
const changes = [];
|
|
805
|
+
|
|
806
|
+
if (!codePath.endsWith('.yaml') && !codePath.endsWith('.yml') && !codePath.endsWith('.json')) {
|
|
807
|
+
return changes;
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
try {
|
|
811
|
+
const schemaContent = await fs.readFile(codePath, 'utf-8');
|
|
812
|
+
const docContent = await fs.readFile(docPath, 'utf-8');
|
|
813
|
+
|
|
814
|
+
// Parse schema
|
|
815
|
+
const schema = codePath.endsWith('.json') ?
|
|
816
|
+
JSON.parse(schemaContent) :
|
|
817
|
+
yaml.parse(schemaContent);
|
|
818
|
+
|
|
819
|
+
// Find schema documentation
|
|
820
|
+
if (docPath.endsWith('.md')) {
|
|
821
|
+
// Look for schema tables or descriptions in markdown
|
|
822
|
+
const schemaTables = this.extractSchemaTables(docContent);
|
|
823
|
+
const schemaFields = this.extractSchemaFields(schema);
|
|
824
|
+
|
|
825
|
+
// Compare fields
|
|
826
|
+
for (const field of schemaFields) {
|
|
827
|
+
const documented = schemaTables.find(t => t.fields.includes(field.name));
|
|
828
|
+
if (!documented) {
|
|
829
|
+
changes.push({
|
|
830
|
+
type: 'schema-field-new',
|
|
831
|
+
field,
|
|
832
|
+
});
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
} catch (error) {
|
|
837
|
+
console.error(`Error detecting schema changes: ${error.message}`);
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
return changes;
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
async syncSchema(codePath, docPath, changes, options = {}) {
|
|
844
|
+
const result = {
|
|
845
|
+
changes: [],
|
|
846
|
+
success: true,
|
|
847
|
+
};
|
|
848
|
+
|
|
849
|
+
try {
|
|
850
|
+
let docContent = await fs.readFile(docPath, 'utf-8');
|
|
851
|
+
const backup = docContent;
|
|
852
|
+
|
|
853
|
+
for (const change of changes) {
|
|
854
|
+
if (change.type === 'schema-field-new') {
|
|
855
|
+
// Add new field to documentation
|
|
856
|
+
docContent = this.addSchemaFieldDoc(docContent, change.field);
|
|
857
|
+
|
|
858
|
+
result.changes.push({
|
|
859
|
+
type: 'schema-field',
|
|
860
|
+
description: `Added documentation for field: ${change.field.name}`,
|
|
861
|
+
});
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
if (docContent !== backup) {
|
|
866
|
+
await fs.writeFile(docPath, docContent);
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
} catch (error) {
|
|
870
|
+
result.success = false;
|
|
871
|
+
result.error = error.message;
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
return result;
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
extractSchemaFields(schema, prefix = '') {
|
|
878
|
+
const fields = [];
|
|
879
|
+
|
|
880
|
+
function traverse(obj, path) {
|
|
881
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
882
|
+
const fieldPath = path ? `${path}.${key}` : key;
|
|
883
|
+
|
|
884
|
+
fields.push({
|
|
885
|
+
name: key,
|
|
886
|
+
path: fieldPath,
|
|
887
|
+
type: typeof value,
|
|
888
|
+
required: obj.required?.includes(key),
|
|
889
|
+
description: value.description || '',
|
|
890
|
+
});
|
|
891
|
+
|
|
892
|
+
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
893
|
+
if (!value.type || value.properties) {
|
|
894
|
+
traverse(value.properties || value, fieldPath);
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
traverse(schema.properties || schema, prefix);
|
|
901
|
+
return fields;
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
async detectAPIChanges(codePath, docPath) {
|
|
905
|
+
// Detect API endpoint changes
|
|
906
|
+
const changes = [];
|
|
907
|
+
|
|
908
|
+
try {
|
|
909
|
+
const codeContent = await fs.readFile(codePath, 'utf-8');
|
|
910
|
+
|
|
911
|
+
// Look for Express/Koa route definitions
|
|
912
|
+
const routes = this.extractAPIRoutes(codeContent);
|
|
913
|
+
|
|
914
|
+
if (routes.length > 0) {
|
|
915
|
+
const docContent = await fs.readFile(docPath, 'utf-8');
|
|
916
|
+
const documentedRoutes = this.extractDocumentedRoutes(docContent);
|
|
917
|
+
|
|
918
|
+
// Compare routes
|
|
919
|
+
for (const route of routes) {
|
|
920
|
+
const documented = documentedRoutes.find(
|
|
921
|
+
r => r.method === route.method && r.path === route.path,
|
|
922
|
+
);
|
|
923
|
+
|
|
924
|
+
if (!documented) {
|
|
925
|
+
changes.push({
|
|
926
|
+
type: 'api-route-new',
|
|
927
|
+
route,
|
|
928
|
+
});
|
|
929
|
+
} else if (this.routeChanged(route, documented)) {
|
|
930
|
+
changes.push({
|
|
931
|
+
type: 'api-route-update',
|
|
932
|
+
route,
|
|
933
|
+
documented,
|
|
934
|
+
});
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
} catch (error) {
|
|
939
|
+
console.error(`Error detecting API changes: ${error.message}`);
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
return changes;
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
extractAPIRoutes(codeContent) {
|
|
946
|
+
const routes = [];
|
|
947
|
+
|
|
948
|
+
// Express pattern: app.get('/path', ...)
|
|
949
|
+
const expressPattern = /app\.(get|post|put|delete|patch)\s*\(\s*['"`]([^'"`]+)['"`]/g;
|
|
950
|
+
let match;
|
|
951
|
+
|
|
952
|
+
while ((match = expressPattern.exec(codeContent)) !== null) {
|
|
953
|
+
routes.push({
|
|
954
|
+
method: match[1].toUpperCase(),
|
|
955
|
+
path: match[2],
|
|
956
|
+
lineNumber: codeContent.substring(0, match.index).split('\n').length,
|
|
957
|
+
});
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
// Router pattern: router.get('/path', ...)
|
|
961
|
+
const routerPattern = /router\.(get|post|put|delete|patch)\s*\(\s*['"`]([^'"`]+)['"`]/g;
|
|
962
|
+
|
|
963
|
+
while ((match = routerPattern.exec(codeContent)) !== null) {
|
|
964
|
+
routes.push({
|
|
965
|
+
method: match[1].toUpperCase(),
|
|
966
|
+
path: match[2],
|
|
967
|
+
lineNumber: codeContent.substring(0, match.index).split('\n').length,
|
|
968
|
+
});
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
return routes;
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
async syncAPI(codePath, docPath, changes, options = {}) {
|
|
975
|
+
const result = {
|
|
976
|
+
changes: [],
|
|
977
|
+
success: true,
|
|
978
|
+
};
|
|
979
|
+
|
|
980
|
+
try {
|
|
981
|
+
let docContent = await fs.readFile(docPath, 'utf-8');
|
|
982
|
+
const backup = docContent;
|
|
983
|
+
|
|
984
|
+
for (const change of changes) {
|
|
985
|
+
if (change.type === 'api-route-new') {
|
|
986
|
+
// Add new route documentation
|
|
987
|
+
docContent = this.addAPIRouteDoc(docContent, change.route);
|
|
988
|
+
|
|
989
|
+
result.changes.push({
|
|
990
|
+
type: 'api-route',
|
|
991
|
+
description: `Added documentation for ${change.route.method} ${change.route.path}`,
|
|
992
|
+
});
|
|
993
|
+
} else if (change.type === 'api-route-update') {
|
|
994
|
+
// Update existing route documentation
|
|
995
|
+
docContent = this.updateAPIRouteDoc(
|
|
996
|
+
docContent,
|
|
997
|
+
change.route,
|
|
998
|
+
change.documented,
|
|
999
|
+
);
|
|
1000
|
+
|
|
1001
|
+
result.changes.push({
|
|
1002
|
+
type: 'api-route',
|
|
1003
|
+
description: `Updated documentation for ${change.route.method} ${change.route.path}`,
|
|
1004
|
+
});
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
if (docContent !== backup) {
|
|
1009
|
+
await fs.writeFile(docPath, docContent);
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
} catch (error) {
|
|
1013
|
+
result.success = false;
|
|
1014
|
+
result.error = error.message;
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
return result;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
async detectExampleChanges(codePath, docPath) {
|
|
1021
|
+
// Detect changes in code examples
|
|
1022
|
+
const changes = [];
|
|
1023
|
+
|
|
1024
|
+
try {
|
|
1025
|
+
const docContent = await fs.readFile(docPath, 'utf-8');
|
|
1026
|
+
const codeBlocks = this.extractCodeBlocks(docContent);
|
|
1027
|
+
|
|
1028
|
+
for (const block of codeBlocks) {
|
|
1029
|
+
if (block.code.includes('// Example') || block.code.includes('// Usage')) {
|
|
1030
|
+
// Check if example is still valid
|
|
1031
|
+
const validation = await this.validateExample(block.code, codePath);
|
|
1032
|
+
|
|
1033
|
+
if (!validation.valid) {
|
|
1034
|
+
changes.push({
|
|
1035
|
+
type: 'example-invalid',
|
|
1036
|
+
block,
|
|
1037
|
+
validation,
|
|
1038
|
+
});
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
} catch (error) {
|
|
1043
|
+
console.error(`Error detecting example changes: ${error.message}`);
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
return changes;
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
async syncExamples(codePath, docPath, changes, options = {}) {
|
|
1050
|
+
const result = {
|
|
1051
|
+
changes: [],
|
|
1052
|
+
success: true,
|
|
1053
|
+
};
|
|
1054
|
+
|
|
1055
|
+
try {
|
|
1056
|
+
let docContent = await fs.readFile(docPath, 'utf-8');
|
|
1057
|
+
const backup = docContent;
|
|
1058
|
+
|
|
1059
|
+
for (const change of changes) {
|
|
1060
|
+
if (change.type === 'example-invalid') {
|
|
1061
|
+
// Update invalid example
|
|
1062
|
+
const updatedExample = await this.updateExample(
|
|
1063
|
+
change.block.code,
|
|
1064
|
+
change.validation,
|
|
1065
|
+
);
|
|
1066
|
+
|
|
1067
|
+
if (updatedExample) {
|
|
1068
|
+
docContent = this.updateCodeBlock(
|
|
1069
|
+
docContent,
|
|
1070
|
+
change.block,
|
|
1071
|
+
updatedExample,
|
|
1072
|
+
);
|
|
1073
|
+
|
|
1074
|
+
result.changes.push({
|
|
1075
|
+
type: 'example',
|
|
1076
|
+
description: 'Updated code example',
|
|
1077
|
+
});
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
if (docContent !== backup) {
|
|
1083
|
+
await fs.writeFile(docPath, docContent);
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
} catch (error) {
|
|
1087
|
+
result.success = false;
|
|
1088
|
+
result.error = error.message;
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
return result;
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
async validateExample(exampleCode, referencedFile) {
|
|
1095
|
+
const validation = {
|
|
1096
|
+
valid: true,
|
|
1097
|
+
errors: [],
|
|
1098
|
+
warnings: [],
|
|
1099
|
+
};
|
|
1100
|
+
|
|
1101
|
+
try {
|
|
1102
|
+
// Parse the example
|
|
1103
|
+
const ast = parser.parse(exampleCode, {
|
|
1104
|
+
sourceType: 'module',
|
|
1105
|
+
plugins: ['jsx', 'typescript'],
|
|
1106
|
+
errorRecovery: true,
|
|
1107
|
+
});
|
|
1108
|
+
|
|
1109
|
+
// Check for undefined references
|
|
1110
|
+
const referencedCode = await fs.readFile(referencedFile, 'utf-8');
|
|
1111
|
+
|
|
1112
|
+
traverse(ast, {
|
|
1113
|
+
Identifier(path) {
|
|
1114
|
+
const name = path.node.name;
|
|
1115
|
+
|
|
1116
|
+
// Check if identifier exists in referenced file
|
|
1117
|
+
if (!referencedCode.includes(name)) {
|
|
1118
|
+
validation.warnings.push({
|
|
1119
|
+
type: 'undefined-reference',
|
|
1120
|
+
name,
|
|
1121
|
+
line: path.node.loc?.start.line,
|
|
1122
|
+
});
|
|
1123
|
+
}
|
|
1124
|
+
},
|
|
1125
|
+
});
|
|
1126
|
+
|
|
1127
|
+
if (validation.errors.length > 0) {
|
|
1128
|
+
validation.valid = false;
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
} catch (error) {
|
|
1132
|
+
validation.valid = false;
|
|
1133
|
+
validation.errors.push({
|
|
1134
|
+
type: 'parse-error',
|
|
1135
|
+
message: error.message,
|
|
1136
|
+
});
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
return validation;
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
async startAutoSync() {
|
|
1143
|
+
this.syncInterval = setInterval(async () => {
|
|
1144
|
+
try {
|
|
1145
|
+
await this.checkForChanges();
|
|
1146
|
+
} catch (error) {
|
|
1147
|
+
this.emit('error', { phase: 'auto-sync', error });
|
|
1148
|
+
}
|
|
1149
|
+
}, this.options.syncInterval);
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
async checkForChanges() {
|
|
1153
|
+
const changes = [];
|
|
1154
|
+
|
|
1155
|
+
for (const [componentPath, component] of this.syncedComponents) {
|
|
1156
|
+
try {
|
|
1157
|
+
const stats = await fs.stat(componentPath);
|
|
1158
|
+
const lastModified = stats.mtime.toISOString();
|
|
1159
|
+
|
|
1160
|
+
if (!component.lastSync || lastModified > component.lastSync) {
|
|
1161
|
+
// Component changed since last sync
|
|
1162
|
+
const syncResult = await this.synchronizeComponent(componentPath);
|
|
1163
|
+
|
|
1164
|
+
if (syncResult.length > 0) {
|
|
1165
|
+
changes.push({
|
|
1166
|
+
componentPath,
|
|
1167
|
+
syncResult,
|
|
1168
|
+
});
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
} catch (error) {
|
|
1172
|
+
console.warn(`Failed to check component: ${componentPath}`, error);
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
if (changes.length > 0) {
|
|
1177
|
+
this.emit('auto-sync', { changes });
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
async generateSyncReport() {
|
|
1182
|
+
const report = {
|
|
1183
|
+
timestamp: new Date().toISOString(),
|
|
1184
|
+
summary: {
|
|
1185
|
+
totalComponents: this.syncedComponents.size,
|
|
1186
|
+
totalDocumentation: this.documentationIndex.size,
|
|
1187
|
+
syncHistory: this.syncHistory.length,
|
|
1188
|
+
lastSync: this.syncHistory[this.syncHistory.length - 1]?.timestamp,
|
|
1189
|
+
},
|
|
1190
|
+
components: [],
|
|
1191
|
+
documentation: [],
|
|
1192
|
+
recentSync: this.syncHistory.slice(-10),
|
|
1193
|
+
};
|
|
1194
|
+
|
|
1195
|
+
// Component details
|
|
1196
|
+
for (const [path, component] of this.syncedComponents) {
|
|
1197
|
+
report.components.push({
|
|
1198
|
+
path: path.replace(this.rootPath, '.'),
|
|
1199
|
+
docPath: component.docPath.replace(this.rootPath, '.'),
|
|
1200
|
+
type: component.type,
|
|
1201
|
+
lastSync: component.lastSync,
|
|
1202
|
+
strategies: component.syncStrategies,
|
|
1203
|
+
});
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
// Documentation details
|
|
1207
|
+
for (const [path, doc] of this.documentationIndex) {
|
|
1208
|
+
report.documentation.push({
|
|
1209
|
+
path: path.replace(this.rootPath, '.'),
|
|
1210
|
+
title: doc.metadata.title,
|
|
1211
|
+
linkedComponents: doc.linkedComponents.length,
|
|
1212
|
+
lastSync: doc.lastSync,
|
|
1213
|
+
});
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
return report;
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
async exists(filePath) {
|
|
1220
|
+
try {
|
|
1221
|
+
await fs.access(filePath);
|
|
1222
|
+
return true;
|
|
1223
|
+
} catch {
|
|
1224
|
+
return false;
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
compareJSDocWithDoc(jsdoc, docSection) {
|
|
1229
|
+
// Simple comparison - could be made more sophisticated
|
|
1230
|
+
const docText = docSection.content.toLowerCase();
|
|
1231
|
+
const jsdocText = JSON.stringify(jsdoc).toLowerCase();
|
|
1232
|
+
|
|
1233
|
+
// Check if key information is missing
|
|
1234
|
+
const differences = [];
|
|
1235
|
+
|
|
1236
|
+
if (jsdoc.params.length > 0) {
|
|
1237
|
+
for (const param of jsdoc.params) {
|
|
1238
|
+
if (!docText.includes(param.name.toLowerCase())) {
|
|
1239
|
+
differences.push({ type: 'missing-param', param: param.name });
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
if (jsdoc.returns && !docText.includes('return')) {
|
|
1245
|
+
differences.push({ type: 'missing-returns' });
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
return differences.length > 0 ? differences : null;
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
findReferencedCode(codeBlock, actualCode) {
|
|
1252
|
+
// Try to find the code block in the actual implementation
|
|
1253
|
+
const normalizedBlock = codeBlock.replace(/\s+/g, ' ').trim();
|
|
1254
|
+
const normalizedActual = actualCode.replace(/\s+/g, ' ');
|
|
1255
|
+
|
|
1256
|
+
if (normalizedActual.includes(normalizedBlock)) {
|
|
1257
|
+
return { changed: false };
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
// Try to find similar code (this is simplified)
|
|
1261
|
+
const blockLines = codeBlock.split('\n').filter(l => l.trim());
|
|
1262
|
+
let matchCount = 0;
|
|
1263
|
+
|
|
1264
|
+
for (const line of blockLines) {
|
|
1265
|
+
if (actualCode.includes(line.trim())) {
|
|
1266
|
+
matchCount++;
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
const matchRatio = matchCount / blockLines.length;
|
|
1271
|
+
|
|
1272
|
+
if (matchRatio < 0.8) {
|
|
1273
|
+
return {
|
|
1274
|
+
changed: true,
|
|
1275
|
+
matchRatio,
|
|
1276
|
+
newCode: this.findSimilarCode(codeBlock, actualCode),
|
|
1277
|
+
};
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1280
|
+
return { changed: false };
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
findSimilarCode(codeBlock, actualCode) {
|
|
1284
|
+
// This is a placeholder - real implementation would use more sophisticated matching
|
|
1285
|
+
return codeBlock;
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
extractSchemaTables(markdown) {
|
|
1289
|
+
const tables = [];
|
|
1290
|
+
const tableRegex = /\|(.+)\|[\s\S]+?\|(.+)\|/g;
|
|
1291
|
+
|
|
1292
|
+
let match;
|
|
1293
|
+
while ((match = tableRegex.exec(markdown)) !== null) {
|
|
1294
|
+
// Simple table extraction - could be improved
|
|
1295
|
+
tables.push({
|
|
1296
|
+
content: match[0],
|
|
1297
|
+
fields: [], // Would need to parse table properly
|
|
1298
|
+
});
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
return tables;
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
addSchemaFieldDoc(docContent, field) {
|
|
1305
|
+
// Find schema documentation section
|
|
1306
|
+
const schemaSection = /^##\s*Schema/m.exec(docContent);
|
|
1307
|
+
|
|
1308
|
+
if (schemaSection) {
|
|
1309
|
+
// Add to existing schema section
|
|
1310
|
+
const insertion = `\n- \`${field.name}\` _(${field.type})_ - ${field.description || 'No description'}${field.required ? ' **Required**' : ''}`;
|
|
1311
|
+
|
|
1312
|
+
return docContent.substring(0, schemaSection.index + schemaSection[0].length) +
|
|
1313
|
+
insertion +
|
|
1314
|
+
docContent.substring(schemaSection.index + schemaSection[0].length);
|
|
1315
|
+
} else {
|
|
1316
|
+
// Add new schema section
|
|
1317
|
+
return docContent + '\n\n## Schema\n\n' +
|
|
1318
|
+
`- \`${field.name}\` _(${field.type})_ - ${field.description || 'No description'}${field.required ? ' **Required**' : ''}`;
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
extractDocumentedRoutes(docContent) {
|
|
1323
|
+
const routes = [];
|
|
1324
|
+
|
|
1325
|
+
// Look for API documentation patterns
|
|
1326
|
+
// Example: ### GET /api/users
|
|
1327
|
+
const routePattern = /^###\s*(GET|POST|PUT|DELETE|PATCH)\s+([^\s]+)/gm;
|
|
1328
|
+
let match;
|
|
1329
|
+
|
|
1330
|
+
while ((match = routePattern.exec(docContent)) !== null) {
|
|
1331
|
+
routes.push({
|
|
1332
|
+
method: match[1],
|
|
1333
|
+
path: match[2],
|
|
1334
|
+
startIndex: match.index,
|
|
1335
|
+
});
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
return routes;
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1341
|
+
routeChanged(route, documented) {
|
|
1342
|
+
// Simple comparison - could check parameters, responses, etc.
|
|
1343
|
+
return false;
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1346
|
+
addAPIRouteDoc(docContent, route) {
|
|
1347
|
+
// Find API section
|
|
1348
|
+
const apiSection = /^##\s*API/m.exec(docContent);
|
|
1349
|
+
|
|
1350
|
+
const routeDoc = `\n\n### ${route.method} ${route.path}\n\n` +
|
|
1351
|
+
'Description of the endpoint.\n\n' +
|
|
1352
|
+
'**Parameters:**\n' +
|
|
1353
|
+
'- None\n\n' +
|
|
1354
|
+
'**Response:**\n' +
|
|
1355
|
+
'```json\n{\n // Response structure\n}\n```\n';
|
|
1356
|
+
|
|
1357
|
+
if (apiSection) {
|
|
1358
|
+
// Find insertion point
|
|
1359
|
+
const nextSection = /^##\s/m.exec(
|
|
1360
|
+
docContent.substring(apiSection.index + apiSection[0].length),
|
|
1361
|
+
);
|
|
1362
|
+
|
|
1363
|
+
const insertIndex = nextSection ?
|
|
1364
|
+
apiSection.index + apiSection[0].length + nextSection.index :
|
|
1365
|
+
docContent.length;
|
|
1366
|
+
|
|
1367
|
+
return docContent.substring(0, insertIndex) +
|
|
1368
|
+
routeDoc +
|
|
1369
|
+
docContent.substring(insertIndex);
|
|
1370
|
+
} else {
|
|
1371
|
+
// Add API section
|
|
1372
|
+
return docContent + '\n\n## API\n' + routeDoc;
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
|
|
1376
|
+
updateAPIRouteDoc(docContent, route, documented) {
|
|
1377
|
+
// This would update existing route documentation
|
|
1378
|
+
// For now, just return unchanged
|
|
1379
|
+
return docContent;
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
updateExample(exampleCode, validation) {
|
|
1383
|
+
// This would fix the example based on validation errors
|
|
1384
|
+
// For now, just return the original
|
|
1385
|
+
return exampleCode;
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
async scanForReadme(dir, files, readmeNames) {
|
|
1389
|
+
try {
|
|
1390
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
1391
|
+
|
|
1392
|
+
for (const entry of entries) {
|
|
1393
|
+
const fullPath = path.join(dir, entry.name);
|
|
1394
|
+
|
|
1395
|
+
if (entry.isFile() && readmeNames.includes(entry.name)) {
|
|
1396
|
+
files.push(fullPath);
|
|
1397
|
+
} else if (entry.isDirectory() && !entry.name.startsWith('.') && entry.name !== 'node_modules') {
|
|
1398
|
+
await this.scanForReadme(fullPath, files, readmeNames);
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
} catch (error) {
|
|
1402
|
+
// Ignore permission errors
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
async scanForInlineDocs(dir, files) {
|
|
1407
|
+
try {
|
|
1408
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
1409
|
+
|
|
1410
|
+
for (const entry of entries) {
|
|
1411
|
+
const fullPath = path.join(dir, entry.name);
|
|
1412
|
+
|
|
1413
|
+
if (entry.isDirectory() && !entry.name.startsWith('.') && entry.name !== 'node_modules' && entry.name !== 'docs') {
|
|
1414
|
+
await this.scanForInlineDocs(fullPath, files);
|
|
1415
|
+
} else if (entry.isFile() && entry.name.endsWith('.md') && !entry.name.toLowerCase().startsWith('readme')) {
|
|
1416
|
+
files.push(fullPath);
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
} catch (error) {
|
|
1420
|
+
// Ignore permission errors
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1424
|
+
stopAutoSync() {
|
|
1425
|
+
if (this.syncInterval) {
|
|
1426
|
+
clearInterval(this.syncInterval);
|
|
1427
|
+
this.syncInterval = null;
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
module.exports = DocumentationSynchronizer;
|