@claude-flow/cli 3.0.0-alpha.6 → 3.0.0-alpha.60
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/.claude/agents/analysis/analyze-code-quality.md +181 -0
- package/.claude/agents/analysis/code-analyzer.md +210 -0
- package/.claude/agents/architecture/arch-system-design.md +157 -0
- package/.claude/agents/consensus/byzantine-coordinator.md +63 -0
- package/.claude/agents/consensus/crdt-synchronizer.md +997 -0
- package/.claude/agents/consensus/gossip-coordinator.md +63 -0
- package/.claude/agents/consensus/performance-benchmarker.md +851 -0
- package/.claude/agents/consensus/quorum-manager.md +823 -0
- package/.claude/agents/consensus/raft-manager.md +63 -0
- package/.claude/agents/consensus/security-manager.md +622 -0
- package/.claude/agents/core/coder.md +453 -0
- package/.claude/agents/core/planner.md +375 -0
- package/.claude/agents/core/researcher.md +369 -0
- package/.claude/agents/core/reviewer.md +520 -0
- package/.claude/agents/core/tester.md +512 -0
- package/.claude/agents/custom/test-long-runner.md +44 -0
- package/.claude/agents/data/data-ml-model.md +445 -0
- package/.claude/agents/development/dev-backend-api.md +346 -0
- package/.claude/agents/devops/ops-cicd-github.md +165 -0
- package/.claude/agents/documentation/docs-api-openapi.md +355 -0
- package/.claude/agents/flow-nexus/app-store.md +88 -0
- package/.claude/agents/flow-nexus/authentication.md +69 -0
- package/.claude/agents/flow-nexus/challenges.md +81 -0
- package/.claude/agents/flow-nexus/neural-network.md +88 -0
- package/.claude/agents/flow-nexus/payments.md +83 -0
- package/.claude/agents/flow-nexus/sandbox.md +76 -0
- package/.claude/agents/flow-nexus/swarm.md +76 -0
- package/.claude/agents/flow-nexus/user-tools.md +96 -0
- package/.claude/agents/flow-nexus/workflow.md +84 -0
- package/.claude/agents/github/code-review-swarm.md +377 -0
- package/.claude/agents/github/github-modes.md +173 -0
- package/.claude/agents/github/issue-tracker.md +576 -0
- package/.claude/agents/github/multi-repo-swarm.md +553 -0
- package/.claude/agents/github/pr-manager.md +438 -0
- package/.claude/agents/github/project-board-sync.md +509 -0
- package/.claude/agents/github/release-manager.md +605 -0
- package/.claude/agents/github/release-swarm.md +583 -0
- package/.claude/agents/github/repo-architect.md +398 -0
- package/.claude/agents/github/swarm-issue.md +573 -0
- package/.claude/agents/github/swarm-pr.md +428 -0
- package/.claude/agents/github/sync-coordinator.md +452 -0
- package/.claude/agents/github/workflow-automation.md +903 -0
- package/.claude/agents/goal/agent.md +816 -0
- package/.claude/agents/goal/goal-planner.md +73 -0
- package/.claude/agents/optimization/benchmark-suite.md +665 -0
- package/.claude/agents/optimization/load-balancer.md +431 -0
- package/.claude/agents/optimization/performance-monitor.md +672 -0
- package/.claude/agents/optimization/resource-allocator.md +674 -0
- package/.claude/agents/optimization/topology-optimizer.md +808 -0
- package/.claude/agents/payments/agentic-payments.md +126 -0
- package/.claude/agents/sona/sona-learning-optimizer.md +254 -0
- package/.claude/agents/sparc/architecture.md +699 -0
- package/.claude/agents/sparc/pseudocode.md +520 -0
- package/.claude/agents/sparc/refinement.md +802 -0
- package/.claude/agents/sparc/specification.md +478 -0
- package/.claude/agents/specialized/spec-mobile-react-native.md +227 -0
- package/.claude/agents/sublinear/consensus-coordinator.md +338 -0
- package/.claude/agents/sublinear/matrix-optimizer.md +185 -0
- package/.claude/agents/sublinear/pagerank-analyzer.md +299 -0
- package/.claude/agents/sublinear/performance-optimizer.md +368 -0
- package/.claude/agents/sublinear/trading-predictor.md +246 -0
- package/.claude/agents/swarm/adaptive-coordinator.md +1127 -0
- package/.claude/agents/swarm/hierarchical-coordinator.md +710 -0
- package/.claude/agents/swarm/mesh-coordinator.md +963 -0
- package/.claude/agents/templates/automation-smart-agent.md +205 -0
- package/.claude/agents/templates/base-template-generator.md +268 -0
- package/.claude/agents/templates/coordinator-swarm-init.md +90 -0
- package/.claude/agents/templates/github-pr-manager.md +177 -0
- package/.claude/agents/templates/implementer-sparc-coder.md +259 -0
- package/.claude/agents/templates/memory-coordinator.md +187 -0
- package/.claude/agents/templates/orchestrator-task.md +139 -0
- package/.claude/agents/templates/performance-analyzer.md +199 -0
- package/.claude/agents/templates/sparc-coordinator.md +514 -0
- package/.claude/agents/testing/production-validator.md +395 -0
- package/.claude/agents/testing/tdd-london-swarm.md +244 -0
- package/.claude/agents/v3/adr-architect.md +184 -0
- package/.claude/agents/v3/claims-authorizer.md +208 -0
- package/.claude/agents/v3/collective-intelligence-coordinator.md +993 -0
- package/.claude/agents/v3/ddd-domain-expert.md +220 -0
- package/.claude/agents/v3/memory-specialist.md +995 -0
- package/.claude/agents/v3/performance-engineer.md +1233 -0
- package/.claude/agents/v3/reasoningbank-learner.md +213 -0
- package/.claude/agents/v3/security-architect.md +867 -0
- package/.claude/agents/v3/security-auditor.md +771 -0
- package/.claude/agents/v3/sparc-orchestrator.md +182 -0
- package/.claude/agents/v3/swarm-memory-manager.md +157 -0
- package/.claude/agents/v3/v3-integration-architect.md +205 -0
- package/.claude/commands/agents/README.md +50 -0
- package/.claude/commands/agents/agent-capabilities.md +140 -0
- package/.claude/commands/agents/agent-coordination.md +28 -0
- package/.claude/commands/agents/agent-spawning.md +28 -0
- package/.claude/commands/agents/agent-types.md +216 -0
- package/.claude/commands/agents/health.md +139 -0
- package/.claude/commands/agents/list.md +100 -0
- package/.claude/commands/agents/logs.md +130 -0
- package/.claude/commands/agents/metrics.md +122 -0
- package/.claude/commands/agents/pool.md +127 -0
- package/.claude/commands/agents/spawn.md +140 -0
- package/.claude/commands/agents/status.md +115 -0
- package/.claude/commands/agents/stop.md +102 -0
- package/.claude/commands/analysis/COMMAND_COMPLIANCE_REPORT.md +54 -0
- package/.claude/commands/analysis/README.md +9 -0
- package/.claude/commands/analysis/bottleneck-detect.md +162 -0
- package/.claude/commands/analysis/performance-bottlenecks.md +59 -0
- package/.claude/commands/analysis/performance-report.md +25 -0
- package/.claude/commands/analysis/token-efficiency.md +45 -0
- package/.claude/commands/analysis/token-usage.md +25 -0
- package/.claude/commands/automation/README.md +9 -0
- package/.claude/commands/automation/auto-agent.md +122 -0
- package/.claude/commands/automation/self-healing.md +106 -0
- package/.claude/commands/automation/session-memory.md +90 -0
- package/.claude/commands/automation/smart-agents.md +73 -0
- package/.claude/commands/automation/smart-spawn.md +25 -0
- package/.claude/commands/automation/workflow-select.md +25 -0
- package/.claude/commands/claude-flow-help.md +103 -0
- package/.claude/commands/claude-flow-memory.md +107 -0
- package/.claude/commands/claude-flow-swarm.md +205 -0
- package/.claude/commands/coordination/README.md +9 -0
- package/.claude/commands/coordination/agent-spawn.md +25 -0
- package/.claude/commands/coordination/init.md +44 -0
- package/.claude/commands/coordination/orchestrate.md +43 -0
- package/.claude/commands/coordination/spawn.md +45 -0
- package/.claude/commands/coordination/swarm-init.md +85 -0
- package/.claude/commands/coordination/task-orchestrate.md +25 -0
- package/.claude/commands/flow-nexus/app-store.md +124 -0
- package/.claude/commands/flow-nexus/challenges.md +120 -0
- package/.claude/commands/flow-nexus/login-registration.md +65 -0
- package/.claude/commands/flow-nexus/neural-network.md +134 -0
- package/.claude/commands/flow-nexus/payments.md +116 -0
- package/.claude/commands/flow-nexus/sandbox.md +83 -0
- package/.claude/commands/flow-nexus/swarm.md +87 -0
- package/.claude/commands/flow-nexus/user-tools.md +152 -0
- package/.claude/commands/flow-nexus/workflow.md +115 -0
- package/.claude/commands/github/README.md +11 -0
- package/.claude/commands/github/code-review-swarm.md +514 -0
- package/.claude/commands/github/code-review.md +25 -0
- package/.claude/commands/github/github-modes.md +147 -0
- package/.claude/commands/github/github-swarm.md +121 -0
- package/.claude/commands/github/issue-tracker.md +292 -0
- package/.claude/commands/github/issue-triage.md +25 -0
- package/.claude/commands/github/multi-repo-swarm.md +519 -0
- package/.claude/commands/github/pr-enhance.md +26 -0
- package/.claude/commands/github/pr-manager.md +170 -0
- package/.claude/commands/github/project-board-sync.md +471 -0
- package/.claude/commands/github/release-manager.md +338 -0
- package/.claude/commands/github/release-swarm.md +544 -0
- package/.claude/commands/github/repo-analyze.md +25 -0
- package/.claude/commands/github/repo-architect.md +367 -0
- package/.claude/commands/github/swarm-issue.md +482 -0
- package/.claude/commands/github/swarm-pr.md +285 -0
- package/.claude/commands/github/sync-coordinator.md +301 -0
- package/.claude/commands/github/workflow-automation.md +442 -0
- package/.claude/commands/hive-mind/README.md +17 -0
- package/.claude/commands/hive-mind/hive-mind-consensus.md +8 -0
- package/.claude/commands/hive-mind/hive-mind-init.md +18 -0
- package/.claude/commands/hive-mind/hive-mind-memory.md +8 -0
- package/.claude/commands/hive-mind/hive-mind-metrics.md +8 -0
- package/.claude/commands/hive-mind/hive-mind-resume.md +8 -0
- package/.claude/commands/hive-mind/hive-mind-sessions.md +8 -0
- package/.claude/commands/hive-mind/hive-mind-spawn.md +21 -0
- package/.claude/commands/hive-mind/hive-mind-status.md +8 -0
- package/.claude/commands/hive-mind/hive-mind-stop.md +8 -0
- package/.claude/commands/hive-mind/hive-mind-wizard.md +8 -0
- package/.claude/commands/hive-mind/hive-mind.md +27 -0
- package/.claude/commands/hooks/README.md +11 -0
- package/.claude/commands/hooks/overview.md +58 -0
- package/.claude/commands/hooks/post-edit.md +117 -0
- package/.claude/commands/hooks/post-task.md +112 -0
- package/.claude/commands/hooks/pre-edit.md +113 -0
- package/.claude/commands/hooks/pre-task.md +111 -0
- package/.claude/commands/hooks/session-end.md +118 -0
- package/.claude/commands/hooks/setup.md +103 -0
- package/.claude/commands/memory/README.md +9 -0
- package/.claude/commands/memory/memory-persist.md +25 -0
- package/.claude/commands/memory/memory-search.md +25 -0
- package/.claude/commands/memory/memory-usage.md +25 -0
- package/.claude/commands/memory/neural.md +47 -0
- package/.claude/commands/monitoring/README.md +9 -0
- package/.claude/commands/monitoring/agent-metrics.md +25 -0
- package/.claude/commands/monitoring/agents.md +44 -0
- package/.claude/commands/monitoring/real-time-view.md +25 -0
- package/.claude/commands/monitoring/status.md +46 -0
- package/.claude/commands/monitoring/swarm-monitor.md +25 -0
- package/.claude/commands/optimization/README.md +9 -0
- package/.claude/commands/optimization/auto-topology.md +62 -0
- package/.claude/commands/optimization/cache-manage.md +25 -0
- package/.claude/commands/optimization/parallel-execute.md +25 -0
- package/.claude/commands/optimization/parallel-execution.md +50 -0
- package/.claude/commands/optimization/topology-optimize.md +25 -0
- package/.claude/commands/pair/README.md +261 -0
- package/.claude/commands/pair/commands.md +546 -0
- package/.claude/commands/pair/config.md +510 -0
- package/.claude/commands/pair/examples.md +512 -0
- package/.claude/commands/pair/modes.md +348 -0
- package/.claude/commands/pair/session.md +407 -0
- package/.claude/commands/pair/start.md +209 -0
- package/.claude/commands/sparc/analyzer.md +52 -0
- package/.claude/commands/sparc/architect.md +53 -0
- package/.claude/commands/sparc/ask.md +97 -0
- package/.claude/commands/sparc/batch-executor.md +54 -0
- package/.claude/commands/sparc/code.md +89 -0
- package/.claude/commands/sparc/coder.md +54 -0
- package/.claude/commands/sparc/debug.md +83 -0
- package/.claude/commands/sparc/debugger.md +54 -0
- package/.claude/commands/sparc/designer.md +53 -0
- package/.claude/commands/sparc/devops.md +109 -0
- package/.claude/commands/sparc/docs-writer.md +80 -0
- package/.claude/commands/sparc/documenter.md +54 -0
- package/.claude/commands/sparc/innovator.md +54 -0
- package/.claude/commands/sparc/integration.md +83 -0
- package/.claude/commands/sparc/mcp.md +117 -0
- package/.claude/commands/sparc/memory-manager.md +54 -0
- package/.claude/commands/sparc/optimizer.md +54 -0
- package/.claude/commands/sparc/orchestrator.md +132 -0
- package/.claude/commands/sparc/post-deployment-monitoring-mode.md +83 -0
- package/.claude/commands/sparc/refinement-optimization-mode.md +83 -0
- package/.claude/commands/sparc/researcher.md +54 -0
- package/.claude/commands/sparc/reviewer.md +54 -0
- package/.claude/commands/sparc/security-review.md +80 -0
- package/.claude/commands/sparc/sparc-modes.md +174 -0
- package/.claude/commands/sparc/sparc.md +111 -0
- package/.claude/commands/sparc/spec-pseudocode.md +80 -0
- package/.claude/commands/sparc/supabase-admin.md +348 -0
- package/.claude/commands/sparc/swarm-coordinator.md +54 -0
- package/.claude/commands/sparc/tdd.md +54 -0
- package/.claude/commands/sparc/tester.md +54 -0
- package/.claude/commands/sparc/tutorial.md +79 -0
- package/.claude/commands/sparc/workflow-manager.md +54 -0
- package/.claude/commands/sparc.md +166 -0
- package/.claude/commands/stream-chain/pipeline.md +121 -0
- package/.claude/commands/stream-chain/run.md +70 -0
- package/.claude/commands/swarm/README.md +15 -0
- package/.claude/commands/swarm/analysis.md +95 -0
- package/.claude/commands/swarm/development.md +96 -0
- package/.claude/commands/swarm/examples.md +168 -0
- package/.claude/commands/swarm/maintenance.md +102 -0
- package/.claude/commands/swarm/optimization.md +117 -0
- package/.claude/commands/swarm/research.md +136 -0
- package/.claude/commands/swarm/swarm-analysis.md +8 -0
- package/.claude/commands/swarm/swarm-background.md +8 -0
- package/.claude/commands/swarm/swarm-init.md +19 -0
- package/.claude/commands/swarm/swarm-modes.md +8 -0
- package/.claude/commands/swarm/swarm-monitor.md +8 -0
- package/.claude/commands/swarm/swarm-spawn.md +19 -0
- package/.claude/commands/swarm/swarm-status.md +8 -0
- package/.claude/commands/swarm/swarm-strategies.md +8 -0
- package/.claude/commands/swarm/swarm.md +87 -0
- package/.claude/commands/swarm/testing.md +131 -0
- package/.claude/commands/training/README.md +9 -0
- package/.claude/commands/training/model-update.md +25 -0
- package/.claude/commands/training/neural-patterns.md +74 -0
- package/.claude/commands/training/neural-train.md +25 -0
- package/.claude/commands/training/pattern-learn.md +25 -0
- package/.claude/commands/training/specialization.md +63 -0
- package/.claude/commands/truth/start.md +143 -0
- package/.claude/commands/verify/check.md +50 -0
- package/.claude/commands/verify/start.md +128 -0
- package/.claude/commands/workflows/README.md +9 -0
- package/.claude/commands/workflows/development.md +78 -0
- package/.claude/commands/workflows/research.md +63 -0
- package/.claude/commands/workflows/workflow-create.md +25 -0
- package/.claude/commands/workflows/workflow-execute.md +25 -0
- package/.claude/commands/workflows/workflow-export.md +25 -0
- package/.claude/helpers/README.md +97 -0
- package/.claude/helpers/adr-compliance.sh +186 -0
- package/.claude/helpers/auto-commit.sh +178 -0
- package/.claude/helpers/checkpoint-manager.sh +251 -0
- package/.claude/helpers/daemon-manager.sh +252 -0
- package/.claude/helpers/ddd-tracker.sh +144 -0
- package/.claude/helpers/github-safe.js +106 -0
- package/.claude/helpers/github-setup.sh +28 -0
- package/.claude/helpers/guidance-hook.sh +13 -0
- package/.claude/helpers/guidance-hooks.sh +102 -0
- package/.claude/helpers/health-monitor.sh +108 -0
- package/.claude/helpers/learning-hooks.sh +329 -0
- package/.claude/helpers/learning-optimizer.sh +127 -0
- package/.claude/helpers/learning-service.mjs +1144 -0
- package/.claude/helpers/memory.js +83 -0
- package/.claude/helpers/metrics-db.mjs +488 -0
- package/.claude/helpers/pattern-consolidator.sh +86 -0
- package/.claude/helpers/perf-worker.sh +160 -0
- package/.claude/helpers/post-commit +16 -0
- package/.claude/helpers/pre-commit +26 -0
- package/.claude/helpers/quick-start.sh +19 -0
- package/.claude/helpers/router.js +66 -0
- package/.claude/helpers/security-scanner.sh +127 -0
- package/.claude/helpers/session.js +127 -0
- package/.claude/helpers/setup-mcp.sh +18 -0
- package/.claude/helpers/standard-checkpoint-hooks.sh +189 -0
- package/.claude/helpers/statusline-hook.sh +21 -0
- package/.claude/helpers/statusline.js +316 -0
- package/.claude/helpers/swarm-comms.sh +353 -0
- package/.claude/helpers/swarm-hooks.sh +761 -0
- package/.claude/helpers/swarm-monitor.sh +211 -0
- package/.claude/helpers/sync-v3-metrics.sh +245 -0
- package/.claude/helpers/update-v3-progress.sh +166 -0
- package/.claude/helpers/v3-quick-status.sh +58 -0
- package/.claude/helpers/v3.sh +111 -0
- package/.claude/helpers/validate-v3-config.sh +216 -0
- package/.claude/helpers/worker-manager.sh +170 -0
- package/.claude/settings.json +259 -0
- package/.claude/skills/agentdb-advanced/SKILL.md +550 -0
- package/.claude/skills/agentdb-learning/SKILL.md +545 -0
- package/.claude/skills/agentdb-memory-patterns/SKILL.md +339 -0
- package/.claude/skills/agentdb-optimization/SKILL.md +509 -0
- package/.claude/skills/agentdb-vector-search/SKILL.md +339 -0
- package/.claude/skills/agentic-jujutsu/SKILL.md +645 -0
- package/.claude/skills/flow-nexus-neural/SKILL.md +738 -0
- package/.claude/skills/flow-nexus-platform/SKILL.md +1157 -0
- package/.claude/skills/flow-nexus-swarm/SKILL.md +610 -0
- package/.claude/skills/github-code-review/SKILL.md +1140 -0
- package/.claude/skills/github-multi-repo/SKILL.md +874 -0
- package/.claude/skills/github-project-management/SKILL.md +1277 -0
- package/.claude/skills/github-release-management/SKILL.md +1081 -0
- package/.claude/skills/github-workflow-automation/SKILL.md +1065 -0
- package/.claude/skills/hive-mind-advanced/SKILL.md +712 -0
- package/.claude/skills/hooks-automation/SKILL.md +1201 -0
- package/.claude/skills/pair-programming/SKILL.md +1202 -0
- package/.claude/skills/performance-analysis/SKILL.md +563 -0
- package/.claude/skills/reasoningbank-agentdb/SKILL.md +446 -0
- package/.claude/skills/reasoningbank-intelligence/SKILL.md +201 -0
- package/{.claude-flow → .claude/skills/skill-builder/.claude-flow}/metrics/performance.json +3 -3
- package/.claude/skills/skill-builder/.claude-flow/metrics/task-metrics.json +10 -0
- package/.claude/skills/skill-builder/SKILL.md +910 -0
- package/.claude/skills/sparc-methodology/SKILL.md +1115 -0
- package/.claude/skills/stream-chain/SKILL.md +563 -0
- package/.claude/skills/swarm-advanced/SKILL.md +973 -0
- package/.claude/skills/swarm-orchestration/SKILL.md +179 -0
- package/.claude/skills/v3-cli-modernization/SKILL.md +872 -0
- package/.claude/skills/v3-core-implementation/SKILL.md +797 -0
- package/.claude/skills/v3-ddd-architecture/SKILL.md +442 -0
- package/.claude/skills/v3-integration-deep/SKILL.md +241 -0
- package/.claude/skills/v3-mcp-optimization/SKILL.md +777 -0
- package/.claude/skills/v3-memory-unification/SKILL.md +174 -0
- package/.claude/skills/v3-performance-optimization/SKILL.md +390 -0
- package/.claude/skills/v3-security-overhaul/SKILL.md +82 -0
- package/.claude/skills/v3-swarm-coordination/SKILL.md +340 -0
- package/.claude/skills/verification-quality/SKILL.md +649 -0
- package/.claude/skills/worker-benchmarks/skill.md +135 -0
- package/.claude/skills/worker-integration/skill.md +154 -0
- package/README.md +428 -6
- package/bin/cli.js +142 -6
- package/bin/mcp-server.js +188 -0
- package/dist/src/commands/agent.d.ts.map +1 -1
- package/dist/src/commands/agent.js +42 -26
- package/dist/src/commands/agent.js.map +1 -1
- package/dist/src/commands/analyze.d.ts +19 -0
- package/dist/src/commands/analyze.d.ts.map +1 -0
- package/dist/src/commands/analyze.js +1823 -0
- package/dist/src/commands/analyze.js.map +1 -0
- package/dist/src/commands/claims.d.ts +10 -0
- package/dist/src/commands/claims.d.ts.map +1 -0
- package/dist/src/commands/claims.js +288 -0
- package/dist/src/commands/claims.js.map +1 -0
- package/dist/src/commands/completions.d.ts +10 -0
- package/dist/src/commands/completions.d.ts.map +1 -0
- package/dist/src/commands/completions.js +539 -0
- package/dist/src/commands/completions.js.map +1 -0
- package/dist/src/commands/daemon.d.ts +8 -0
- package/dist/src/commands/daemon.d.ts.map +1 -0
- package/dist/src/commands/daemon.js +593 -0
- package/dist/src/commands/daemon.js.map +1 -0
- package/dist/src/commands/deployment.d.ts +10 -0
- package/dist/src/commands/deployment.d.ts.map +1 -0
- package/dist/src/commands/deployment.js +289 -0
- package/dist/src/commands/deployment.js.map +1 -0
- package/dist/src/commands/doctor.d.ts +10 -0
- package/dist/src/commands/doctor.d.ts.map +1 -0
- package/dist/src/commands/doctor.js +448 -0
- package/dist/src/commands/doctor.js.map +1 -0
- package/dist/src/commands/embeddings.d.ts +18 -0
- package/dist/src/commands/embeddings.d.ts.map +1 -0
- package/dist/src/commands/embeddings.js +616 -0
- package/dist/src/commands/embeddings.js.map +1 -0
- package/dist/src/commands/hive-mind.d.ts.map +1 -1
- package/dist/src/commands/hive-mind.js +252 -35
- package/dist/src/commands/hive-mind.js.map +1 -1
- package/dist/src/commands/hooks.d.ts.map +1 -1
- package/dist/src/commands/hooks.js +729 -6
- package/dist/src/commands/hooks.js.map +1 -1
- package/dist/src/commands/index.d.ts +52 -14
- package/dist/src/commands/index.d.ts.map +1 -1
- package/dist/src/commands/index.js +191 -38
- package/dist/src/commands/index.js.map +1 -1
- package/dist/src/commands/init.d.ts.map +1 -1
- package/dist/src/commands/init.js +80 -9
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/issues.d.ts +21 -0
- package/dist/src/commands/issues.d.ts.map +1 -0
- package/dist/src/commands/issues.js +567 -0
- package/dist/src/commands/issues.js.map +1 -0
- package/dist/src/commands/mcp.js +3 -3
- package/dist/src/commands/mcp.js.map +1 -1
- package/dist/src/commands/memory.d.ts.map +1 -1
- package/dist/src/commands/memory.js +223 -4
- package/dist/src/commands/memory.js.map +1 -1
- package/dist/src/commands/neural.d.ts +10 -0
- package/dist/src/commands/neural.d.ts.map +1 -0
- package/dist/src/commands/neural.js +224 -0
- package/dist/src/commands/neural.js.map +1 -0
- package/dist/src/commands/performance.d.ts +10 -0
- package/dist/src/commands/performance.d.ts.map +1 -0
- package/dist/src/commands/performance.js +262 -0
- package/dist/src/commands/performance.js.map +1 -0
- package/dist/src/commands/plugins.d.ts +11 -0
- package/dist/src/commands/plugins.d.ts.map +1 -0
- package/dist/src/commands/plugins.js +630 -0
- package/dist/src/commands/plugins.js.map +1 -0
- package/dist/src/commands/progress.d.ts +11 -0
- package/dist/src/commands/progress.d.ts.map +1 -0
- package/dist/src/commands/progress.js +259 -0
- package/dist/src/commands/progress.js.map +1 -0
- package/dist/src/commands/providers.d.ts +10 -0
- package/dist/src/commands/providers.d.ts.map +1 -0
- package/dist/src/commands/providers.js +232 -0
- package/dist/src/commands/providers.js.map +1 -0
- package/dist/src/commands/route.d.ts +16 -0
- package/dist/src/commands/route.d.ts.map +1 -0
- package/dist/src/commands/route.js +813 -0
- package/dist/src/commands/route.js.map +1 -0
- package/dist/src/commands/security.d.ts +10 -0
- package/dist/src/commands/security.d.ts.map +1 -0
- package/dist/src/commands/security.js +261 -0
- package/dist/src/commands/security.js.map +1 -0
- package/dist/src/commands/start.d.ts.map +1 -1
- package/dist/src/commands/start.js +22 -2
- package/dist/src/commands/start.js.map +1 -1
- package/dist/src/commands/swarm.d.ts.map +1 -1
- package/dist/src/commands/swarm.js +185 -32
- package/dist/src/commands/swarm.js.map +1 -1
- package/dist/src/commands/transfer-store.d.ts +13 -0
- package/dist/src/commands/transfer-store.d.ts.map +1 -0
- package/dist/src/commands/transfer-store.js +428 -0
- package/dist/src/commands/transfer-store.js.map +1 -0
- package/dist/src/index.d.ts +3 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +69 -10
- package/dist/src/index.js.map +1 -1
- package/dist/src/init/claudemd-generator.d.ts.map +1 -1
- package/dist/src/init/claudemd-generator.js +407 -405
- package/dist/src/init/claudemd-generator.js.map +1 -1
- package/dist/src/init/executor.d.ts.map +1 -1
- package/dist/src/init/executor.js +142 -31
- package/dist/src/init/executor.js.map +1 -1
- package/dist/src/init/helpers-generator.js +1 -1
- package/dist/src/init/helpers-generator.js.map +1 -1
- package/dist/src/init/mcp-generator.d.ts +9 -0
- package/dist/src/init/mcp-generator.d.ts.map +1 -1
- package/dist/src/init/mcp-generator.js +57 -28
- package/dist/src/init/mcp-generator.js.map +1 -1
- package/dist/src/init/settings-generator.d.ts.map +1 -1
- package/dist/src/init/settings-generator.js +116 -62
- package/dist/src/init/settings-generator.js.map +1 -1
- package/dist/src/init/statusline-generator.d.ts +6 -0
- package/dist/src/init/statusline-generator.d.ts.map +1 -1
- package/dist/src/init/statusline-generator.js +252 -89
- package/dist/src/init/statusline-generator.js.map +1 -1
- package/dist/src/init/types.d.ts +6 -0
- package/dist/src/init/types.d.ts.map +1 -1
- package/dist/src/init/types.js +8 -2
- package/dist/src/init/types.js.map +1 -1
- package/dist/src/mcp-client.d.ts.map +1 -1
- package/dist/src/mcp-client.js +17 -1
- package/dist/src/mcp-client.js.map +1 -1
- package/dist/src/mcp-server.d.ts +6 -1
- package/dist/src/mcp-server.d.ts.map +1 -1
- package/dist/src/mcp-server.js +169 -38
- package/dist/src/mcp-server.js.map +1 -1
- package/dist/src/mcp-tools/agent-tools.d.ts +1 -1
- package/dist/src/mcp-tools/agent-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/agent-tools.js +350 -14
- package/dist/src/mcp-tools/agent-tools.js.map +1 -1
- package/dist/src/mcp-tools/analyze-tools.d.ts +38 -0
- package/dist/src/mcp-tools/analyze-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/analyze-tools.js +317 -0
- package/dist/src/mcp-tools/analyze-tools.js.map +1 -0
- package/dist/src/mcp-tools/config-tools.d.ts +1 -1
- package/dist/src/mcp-tools/config-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/config-tools.js +262 -15
- package/dist/src/mcp-tools/config-tools.js.map +1 -1
- package/dist/src/mcp-tools/hive-mind-tools.d.ts +8 -0
- package/dist/src/mcp-tools/hive-mind-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/hive-mind-tools.js +447 -0
- package/dist/src/mcp-tools/hive-mind-tools.js.map +1 -0
- package/dist/src/mcp-tools/hooks-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/hooks-tools.js +195 -31
- package/dist/src/mcp-tools/hooks-tools.js.map +1 -1
- package/dist/src/mcp-tools/index.d.ts +6 -0
- package/dist/src/mcp-tools/index.d.ts.map +1 -1
- package/dist/src/mcp-tools/index.js +6 -0
- package/dist/src/mcp-tools/index.js.map +1 -1
- package/dist/src/mcp-tools/progress-tools.d.ts +14 -0
- package/dist/src/mcp-tools/progress-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/progress-tools.js +343 -0
- package/dist/src/mcp-tools/progress-tools.js.map +1 -0
- package/dist/src/mcp-tools/session-tools.d.ts +1 -1
- package/dist/src/mcp-tools/session-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/session-tools.js +237 -22
- package/dist/src/mcp-tools/session-tools.js.map +1 -1
- package/dist/src/mcp-tools/task-tools.d.ts +1 -1
- package/dist/src/mcp-tools/task-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/task-tools.js +219 -17
- package/dist/src/mcp-tools/task-tools.js.map +1 -1
- package/dist/src/mcp-tools/transfer-tools.d.ts +14 -0
- package/dist/src/mcp-tools/transfer-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/transfer-tools.js +396 -0
- package/dist/src/mcp-tools/transfer-tools.js.map +1 -0
- package/dist/src/mcp-tools/workflow-tools.d.ts +8 -0
- package/dist/src/mcp-tools/workflow-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/workflow-tools.js +481 -0
- package/dist/src/mcp-tools/workflow-tools.js.map +1 -0
- package/dist/src/output.d.ts +16 -0
- package/dist/src/output.d.ts.map +1 -1
- package/dist/src/output.js +42 -0
- package/dist/src/output.js.map +1 -1
- package/dist/src/plugins/store/discovery.d.ts +73 -0
- package/dist/src/plugins/store/discovery.d.ts.map +1 -0
- package/dist/src/plugins/store/discovery.js +568 -0
- package/dist/src/plugins/store/discovery.js.map +1 -0
- package/dist/src/plugins/store/index.d.ts +76 -0
- package/dist/src/plugins/store/index.d.ts.map +1 -0
- package/dist/src/plugins/store/index.js +141 -0
- package/dist/src/plugins/store/index.js.map +1 -0
- package/dist/src/plugins/store/search.d.ts +46 -0
- package/dist/src/plugins/store/search.d.ts.map +1 -0
- package/dist/src/plugins/store/search.js +230 -0
- package/dist/src/plugins/store/search.js.map +1 -0
- package/dist/src/plugins/store/types.d.ts +274 -0
- package/dist/src/plugins/store/types.d.ts.map +1 -0
- package/dist/src/plugins/store/types.js +7 -0
- package/dist/src/plugins/store/types.js.map +1 -0
- package/dist/src/plugins/tests/demo-plugin-store.d.ts +7 -0
- package/dist/src/plugins/tests/demo-plugin-store.d.ts.map +1 -0
- package/dist/src/plugins/tests/demo-plugin-store.js +126 -0
- package/dist/src/plugins/tests/demo-plugin-store.js.map +1 -0
- package/dist/src/plugins/tests/standalone-test.d.ts +12 -0
- package/dist/src/plugins/tests/standalone-test.d.ts.map +1 -0
- package/dist/src/plugins/tests/standalone-test.js +188 -0
- package/dist/src/plugins/tests/standalone-test.js.map +1 -0
- package/dist/src/plugins/tests/test-plugin-store.d.ts +7 -0
- package/dist/src/plugins/tests/test-plugin-store.d.ts.map +1 -0
- package/dist/src/plugins/tests/test-plugin-store.js +206 -0
- package/dist/src/plugins/tests/test-plugin-store.js.map +1 -0
- package/dist/src/ruvector/ast-analyzer.d.ts +67 -0
- package/dist/src/ruvector/ast-analyzer.d.ts.map +1 -0
- package/dist/src/ruvector/ast-analyzer.js +277 -0
- package/dist/src/ruvector/ast-analyzer.js.map +1 -0
- package/dist/src/ruvector/coverage-router.d.ts +160 -0
- package/dist/src/ruvector/coverage-router.d.ts.map +1 -0
- package/dist/src/ruvector/coverage-router.js +529 -0
- package/dist/src/ruvector/coverage-router.js.map +1 -0
- package/dist/src/ruvector/coverage-tools.d.ts +33 -0
- package/dist/src/ruvector/coverage-tools.d.ts.map +1 -0
- package/dist/src/ruvector/coverage-tools.js +157 -0
- package/dist/src/ruvector/coverage-tools.js.map +1 -0
- package/dist/src/ruvector/diff-classifier.d.ts +175 -0
- package/dist/src/ruvector/diff-classifier.d.ts.map +1 -0
- package/dist/src/ruvector/diff-classifier.js +698 -0
- package/dist/src/ruvector/diff-classifier.js.map +1 -0
- package/dist/src/ruvector/graph-analyzer.d.ts +187 -0
- package/dist/src/ruvector/graph-analyzer.d.ts.map +1 -0
- package/dist/src/ruvector/graph-analyzer.js +929 -0
- package/dist/src/ruvector/graph-analyzer.js.map +1 -0
- package/dist/src/ruvector/index.d.ts +27 -0
- package/dist/src/ruvector/index.d.ts.map +1 -0
- package/dist/src/ruvector/index.js +53 -0
- package/dist/src/ruvector/index.js.map +1 -0
- package/dist/src/ruvector/q-learning-router.d.ts +211 -0
- package/dist/src/ruvector/q-learning-router.d.ts.map +1 -0
- package/dist/src/ruvector/q-learning-router.js +681 -0
- package/dist/src/ruvector/q-learning-router.js.map +1 -0
- package/dist/src/ruvector/vector-db.d.ts +69 -0
- package/dist/src/ruvector/vector-db.d.ts.map +1 -0
- package/dist/src/ruvector/vector-db.js +243 -0
- package/dist/src/ruvector/vector-db.js.map +1 -0
- package/dist/src/services/claim-service.d.ts +204 -0
- package/dist/src/services/claim-service.d.ts.map +1 -0
- package/dist/src/services/claim-service.js +818 -0
- package/dist/src/services/claim-service.js.map +1 -0
- package/dist/src/services/container-worker-pool.d.ts +197 -0
- package/dist/src/services/container-worker-pool.d.ts.map +1 -0
- package/dist/src/services/container-worker-pool.js +581 -0
- package/dist/src/services/container-worker-pool.js.map +1 -0
- package/dist/src/services/headless-worker-executor.d.ts +304 -0
- package/dist/src/services/headless-worker-executor.d.ts.map +1 -0
- package/dist/src/services/headless-worker-executor.js +997 -0
- package/dist/src/services/headless-worker-executor.js.map +1 -0
- package/dist/src/services/index.d.ts +13 -0
- package/dist/src/services/index.d.ts.map +1 -0
- package/dist/src/services/index.js +11 -0
- package/dist/src/services/index.js.map +1 -0
- package/dist/src/services/worker-daemon.d.ts +203 -0
- package/dist/src/services/worker-daemon.d.ts.map +1 -0
- package/dist/src/services/worker-daemon.js +745 -0
- package/dist/src/services/worker-daemon.js.map +1 -0
- package/dist/src/services/worker-queue.d.ts +194 -0
- package/dist/src/services/worker-queue.d.ts.map +1 -0
- package/dist/src/services/worker-queue.js +511 -0
- package/dist/src/services/worker-queue.js.map +1 -0
- package/dist/src/suggest.d.ts +53 -0
- package/dist/src/suggest.d.ts.map +1 -0
- package/dist/src/suggest.js +200 -0
- package/dist/src/suggest.js.map +1 -0
- package/dist/src/transfer/anonymization/index.d.ts +25 -0
- package/dist/src/transfer/anonymization/index.d.ts.map +1 -0
- package/dist/src/transfer/anonymization/index.js +175 -0
- package/dist/src/transfer/anonymization/index.js.map +1 -0
- package/dist/src/transfer/deploy-seraphine.d.ts +13 -0
- package/dist/src/transfer/deploy-seraphine.d.ts.map +1 -0
- package/dist/src/transfer/deploy-seraphine.js +205 -0
- package/dist/src/transfer/deploy-seraphine.js.map +1 -0
- package/dist/src/transfer/export.d.ts +25 -0
- package/dist/src/transfer/export.d.ts.map +1 -0
- package/dist/src/transfer/export.js +113 -0
- package/dist/src/transfer/export.js.map +1 -0
- package/dist/src/transfer/index.d.ts +12 -0
- package/dist/src/transfer/index.d.ts.map +1 -0
- package/dist/src/transfer/index.js +31 -0
- package/dist/src/transfer/index.js.map +1 -0
- package/dist/src/transfer/ipfs/client.d.ts +31 -0
- package/dist/src/transfer/ipfs/client.d.ts.map +1 -0
- package/dist/src/transfer/ipfs/client.js +74 -0
- package/dist/src/transfer/ipfs/client.js.map +1 -0
- package/dist/src/transfer/ipfs/upload.d.ts +95 -0
- package/dist/src/transfer/ipfs/upload.d.ts.map +1 -0
- package/dist/src/transfer/ipfs/upload.js +410 -0
- package/dist/src/transfer/ipfs/upload.js.map +1 -0
- package/dist/src/transfer/models/seraphine.d.ts +72 -0
- package/dist/src/transfer/models/seraphine.d.ts.map +1 -0
- package/dist/src/transfer/models/seraphine.js +373 -0
- package/dist/src/transfer/models/seraphine.js.map +1 -0
- package/dist/src/transfer/serialization/cfp.d.ts +49 -0
- package/dist/src/transfer/serialization/cfp.d.ts.map +1 -0
- package/dist/src/transfer/serialization/cfp.js +180 -0
- package/dist/src/transfer/serialization/cfp.js.map +1 -0
- package/dist/src/transfer/store/discovery.d.ts +84 -0
- package/dist/src/transfer/store/discovery.d.ts.map +1 -0
- package/dist/src/transfer/store/discovery.js +275 -0
- package/dist/src/transfer/store/discovery.js.map +1 -0
- package/dist/src/transfer/store/download.d.ts +70 -0
- package/dist/src/transfer/store/download.d.ts.map +1 -0
- package/dist/src/transfer/store/download.js +295 -0
- package/dist/src/transfer/store/download.js.map +1 -0
- package/dist/src/transfer/store/index.d.ts +84 -0
- package/dist/src/transfer/store/index.d.ts.map +1 -0
- package/dist/src/transfer/store/index.js +153 -0
- package/dist/src/transfer/store/index.js.map +1 -0
- package/dist/src/transfer/store/publish.d.ts +76 -0
- package/dist/src/transfer/store/publish.d.ts.map +1 -0
- package/dist/src/transfer/store/publish.js +262 -0
- package/dist/src/transfer/store/publish.js.map +1 -0
- package/dist/src/transfer/store/registry.d.ts +58 -0
- package/dist/src/transfer/store/registry.d.ts.map +1 -0
- package/dist/src/transfer/store/registry.js +285 -0
- package/dist/src/transfer/store/registry.js.map +1 -0
- package/dist/src/transfer/store/search.d.ts +54 -0
- package/dist/src/transfer/store/search.d.ts.map +1 -0
- package/dist/src/transfer/store/search.js +232 -0
- package/dist/src/transfer/store/search.js.map +1 -0
- package/dist/src/transfer/store/tests/standalone-test.d.ts +12 -0
- package/dist/src/transfer/store/tests/standalone-test.d.ts.map +1 -0
- package/dist/src/transfer/store/tests/standalone-test.js +190 -0
- package/dist/src/transfer/store/tests/standalone-test.js.map +1 -0
- package/dist/src/transfer/store/types.d.ts +193 -0
- package/dist/src/transfer/store/types.d.ts.map +1 -0
- package/dist/src/transfer/store/types.js +6 -0
- package/dist/src/transfer/store/types.js.map +1 -0
- package/dist/src/transfer/test-seraphine.d.ts +6 -0
- package/dist/src/transfer/test-seraphine.d.ts.map +1 -0
- package/dist/src/transfer/test-seraphine.js +105 -0
- package/dist/src/transfer/test-seraphine.js.map +1 -0
- package/dist/src/transfer/tests/test-store.d.ts +7 -0
- package/dist/src/transfer/tests/test-store.d.ts.map +1 -0
- package/dist/src/transfer/tests/test-store.js +214 -0
- package/dist/src/transfer/tests/test-store.js.map +1 -0
- package/dist/src/transfer/types.d.ts +245 -0
- package/dist/src/transfer/types.d.ts.map +1 -0
- package/dist/src/transfer/types.js +6 -0
- package/dist/src/transfer/types.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +37 -9
- package/.agentic-flow/intelligence.json +0 -17
- package/.claude-flow/metrics/task-metrics.json +0 -10
- package/__tests__/README.md +0 -140
- package/__tests__/TEST_SUMMARY.md +0 -144
- package/__tests__/cli.test.ts +0 -558
- package/__tests__/commands.test.ts +0 -726
- package/__tests__/config-adapter.test.ts +0 -362
- package/__tests__/config-loading.test.ts +0 -106
- package/__tests__/coverage/.tmp/coverage-0.json +0 -1
- package/__tests__/coverage/.tmp/coverage-1.json +0 -1
- package/__tests__/coverage/.tmp/coverage-2.json +0 -1
- package/__tests__/coverage/.tmp/coverage-3.json +0 -1
- package/__tests__/coverage/.tmp/coverage-4.json +0 -1
- package/__tests__/coverage/.tmp/coverage-5.json +0 -1
- package/__tests__/mcp-client.test.ts +0 -480
- package/__tests__/p1-commands.test.ts +0 -1064
- package/agents/architect.yaml +0 -11
- package/agents/coder.yaml +0 -11
- package/agents/reviewer.yaml +0 -10
- package/agents/security-architect.yaml +0 -10
- package/agents/tester.yaml +0 -10
- package/docs/CONFIG_LOADING.md +0 -236
- package/docs/IMPLEMENTATION_COMPLETE.md +0 -421
- package/docs/MCP_CLIENT_GUIDE.md +0 -620
- package/docs/REFACTORING_SUMMARY.md +0 -247
- package/src/commands/agent.ts +0 -941
- package/src/commands/config.ts +0 -452
- package/src/commands/hive-mind.ts +0 -762
- package/src/commands/hooks.ts +0 -2603
- package/src/commands/index.ts +0 -115
- package/src/commands/init.ts +0 -597
- package/src/commands/mcp.ts +0 -753
- package/src/commands/memory.ts +0 -1161
- package/src/commands/migrate.ts +0 -447
- package/src/commands/process.ts +0 -695
- package/src/commands/session.ts +0 -891
- package/src/commands/start.ts +0 -457
- package/src/commands/status.ts +0 -736
- package/src/commands/swarm.ts +0 -648
- package/src/commands/task.ts +0 -792
- package/src/commands/workflow.ts +0 -742
- package/src/config-adapter.ts +0 -210
- package/src/index.ts +0 -400
- package/src/infrastructure/in-memory-repositories.ts +0 -310
- package/src/init/claudemd-generator.ts +0 -631
- package/src/init/executor.ts +0 -762
- package/src/init/helpers-generator.ts +0 -628
- package/src/init/index.ts +0 -60
- package/src/init/mcp-generator.ts +0 -83
- package/src/init/settings-generator.ts +0 -274
- package/src/init/statusline-generator.ts +0 -211
- package/src/init/types.ts +0 -447
- package/src/mcp-client.ts +0 -229
- package/src/mcp-server.ts +0 -577
- package/src/mcp-tools/agent-tools.ts +0 -92
- package/src/mcp-tools/config-tools.ts +0 -88
- package/src/mcp-tools/hooks-tools.ts +0 -1849
- package/src/mcp-tools/index.ts +0 -14
- package/src/mcp-tools/memory-tools.ts +0 -270
- package/src/mcp-tools/session-tools.ts +0 -102
- package/src/mcp-tools/swarm-tools.ts +0 -105
- package/src/mcp-tools/task-tools.ts +0 -102
- package/src/mcp-tools/types.ts +0 -33
- package/src/output.ts +0 -593
- package/src/parser.ts +0 -417
- package/src/prompt.ts +0 -619
- package/src/types.ts +0 -287
- package/tsconfig.json +0 -16
- package/tsconfig.tsbuildinfo +0 -1
- package/vitest.config.ts +0 -13
- /package/{tmp.json → .claude/agents/tmp.json} +0 -0
- /package/{.claude-flow → .claude/skills/skill-builder/.claude-flow}/metrics/agent-metrics.json +0 -0
|
@@ -0,0 +1,929 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graph Analyzer Module
|
|
3
|
+
*
|
|
4
|
+
* Provides code dependency graph analysis using ruvector's graph algorithms:
|
|
5
|
+
* - MinCut for code boundary detection (refactoring suggestions)
|
|
6
|
+
* - Louvain for module/community detection
|
|
7
|
+
* - Circular dependency detection
|
|
8
|
+
* - DOT format export for visualization
|
|
9
|
+
*
|
|
10
|
+
* Falls back to built-in implementations when @ruvector/wasm is not available.
|
|
11
|
+
*
|
|
12
|
+
* @module @claude-flow/cli/ruvector/graph-analyzer
|
|
13
|
+
*/
|
|
14
|
+
import { readFile, readdir, stat } from 'fs/promises';
|
|
15
|
+
import { join, relative, extname, dirname, basename } from 'path';
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// Caching for Performance
|
|
18
|
+
// ============================================================================
|
|
19
|
+
/**
|
|
20
|
+
* Cache for dependency graphs (5 minute TTL)
|
|
21
|
+
*/
|
|
22
|
+
const graphCache = new Map();
|
|
23
|
+
const GRAPH_CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes
|
|
24
|
+
/**
|
|
25
|
+
* Cache for analysis results (2 minute TTL)
|
|
26
|
+
*/
|
|
27
|
+
const analysisResultCache = new Map();
|
|
28
|
+
const ANALYSIS_CACHE_TTL_MS = 2 * 60 * 1000; // 2 minutes
|
|
29
|
+
/**
|
|
30
|
+
* Clear all graph caches
|
|
31
|
+
*/
|
|
32
|
+
export function clearGraphCaches() {
|
|
33
|
+
graphCache.clear();
|
|
34
|
+
analysisResultCache.clear();
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Get cache statistics
|
|
38
|
+
*/
|
|
39
|
+
export function getGraphCacheStats() {
|
|
40
|
+
return {
|
|
41
|
+
graphCacheSize: graphCache.size,
|
|
42
|
+
analysisCacheSize: analysisResultCache.size,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
let ruVectorGraph = null;
|
|
46
|
+
let ruVectorLoadAttempted = false;
|
|
47
|
+
/**
|
|
48
|
+
* Attempt to load ruvector graph algorithms
|
|
49
|
+
*/
|
|
50
|
+
async function loadRuVector() {
|
|
51
|
+
if (ruVectorLoadAttempted)
|
|
52
|
+
return ruVectorGraph;
|
|
53
|
+
ruVectorLoadAttempted = true;
|
|
54
|
+
// Use dynamic module names to bypass TypeScript static analysis
|
|
55
|
+
// These modules are optional and may not be installed
|
|
56
|
+
const ruvectorModule = 'ruvector';
|
|
57
|
+
const wasmModule = '@ruvector/wasm';
|
|
58
|
+
try {
|
|
59
|
+
// Try to load ruvector's graph module
|
|
60
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
61
|
+
const ruvector = await import(/* webpackIgnore: true */ ruvectorModule).catch(() => null);
|
|
62
|
+
if (ruvector && typeof ruvector.hooks_graph_mincut === 'function' && typeof ruvector.hooks_graph_cluster === 'function') {
|
|
63
|
+
ruVectorGraph = {
|
|
64
|
+
mincut: (nodes, edges) => ruvector.hooks_graph_mincut(nodes, edges),
|
|
65
|
+
louvain: (nodes, edges) => ruvector.hooks_graph_cluster(nodes, edges),
|
|
66
|
+
};
|
|
67
|
+
return ruVectorGraph;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// Try alternative import paths
|
|
72
|
+
try {
|
|
73
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
74
|
+
const wasm = await import(/* webpackIgnore: true */ wasmModule).catch(() => null);
|
|
75
|
+
if (wasm && wasm.GraphAnalyzer) {
|
|
76
|
+
const analyzer = new wasm.GraphAnalyzer();
|
|
77
|
+
ruVectorGraph = {
|
|
78
|
+
mincut: (nodes, edges) => analyzer.mincut(nodes, edges),
|
|
79
|
+
louvain: (nodes, edges) => analyzer.louvain(nodes, edges),
|
|
80
|
+
};
|
|
81
|
+
return ruVectorGraph;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// Fallback will be used
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
// ============================================================================
|
|
91
|
+
// Import/Require Parser
|
|
92
|
+
// ============================================================================
|
|
93
|
+
/**
|
|
94
|
+
* Extract imports from TypeScript/JavaScript file
|
|
95
|
+
*/
|
|
96
|
+
function extractImports(content, _filePath) {
|
|
97
|
+
const imports = [];
|
|
98
|
+
// ES6 import statements
|
|
99
|
+
const esImportRegex = /import\s+(?:(?:\{[^}]*\}|\*\s+as\s+\w+|\w+)\s*,?\s*)*\s*from\s*['"]([^'"]+)['"]/g;
|
|
100
|
+
let match;
|
|
101
|
+
while ((match = esImportRegex.exec(content)) !== null) {
|
|
102
|
+
imports.push({ path: match[1], type: 'import' });
|
|
103
|
+
}
|
|
104
|
+
// Side-effect imports: import 'module'
|
|
105
|
+
const sideEffectRegex = /import\s+['"]([^'"]+)['"]/g;
|
|
106
|
+
while ((match = sideEffectRegex.exec(content)) !== null) {
|
|
107
|
+
imports.push({ path: match[1], type: 'import' });
|
|
108
|
+
}
|
|
109
|
+
// CommonJS require
|
|
110
|
+
const requireRegex = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
111
|
+
while ((match = requireRegex.exec(content)) !== null) {
|
|
112
|
+
imports.push({ path: match[1], type: 'require' });
|
|
113
|
+
}
|
|
114
|
+
// Dynamic imports
|
|
115
|
+
const dynamicImportRegex = /import\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
116
|
+
while ((match = dynamicImportRegex.exec(content)) !== null) {
|
|
117
|
+
imports.push({ path: match[1], type: 'dynamic' });
|
|
118
|
+
}
|
|
119
|
+
// Re-exports: export * from 'module'
|
|
120
|
+
const reExportRegex = /export\s+(?:\*|\{[^}]*\})\s+from\s*['"]([^'"]+)['"]/g;
|
|
121
|
+
while ((match = reExportRegex.exec(content)) !== null) {
|
|
122
|
+
imports.push({ path: match[1], type: 're-export' });
|
|
123
|
+
}
|
|
124
|
+
return imports;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Extract exports from TypeScript/JavaScript file
|
|
128
|
+
*/
|
|
129
|
+
function extractExports(content) {
|
|
130
|
+
const exports = [];
|
|
131
|
+
// Named exports
|
|
132
|
+
const namedExportRegex = /export\s+(?:const|let|var|function|class|interface|type|enum)\s+(\w+)/g;
|
|
133
|
+
let match;
|
|
134
|
+
while ((match = namedExportRegex.exec(content)) !== null) {
|
|
135
|
+
exports.push(match[1]);
|
|
136
|
+
}
|
|
137
|
+
// Export list: export { a, b, c }
|
|
138
|
+
const exportListRegex = /export\s+\{([^}]+)\}/g;
|
|
139
|
+
while ((match = exportListRegex.exec(content)) !== null) {
|
|
140
|
+
const names = match[1].split(',').map(n => n.trim().split(/\s+as\s+/)[0].trim());
|
|
141
|
+
exports.push(...names.filter(n => n));
|
|
142
|
+
}
|
|
143
|
+
// Default export
|
|
144
|
+
if (/export\s+default/.test(content)) {
|
|
145
|
+
exports.push('default');
|
|
146
|
+
}
|
|
147
|
+
return exports;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Resolve import path to absolute file path
|
|
151
|
+
*/
|
|
152
|
+
function resolveImportPath(importPath, fromFile, rootDir) {
|
|
153
|
+
// Skip external packages
|
|
154
|
+
if (!importPath.startsWith('.') && !importPath.startsWith('/')) {
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
const fromDir = dirname(fromFile);
|
|
158
|
+
let resolved;
|
|
159
|
+
if (importPath.startsWith('/')) {
|
|
160
|
+
resolved = join(rootDir, importPath);
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
resolved = join(fromDir, importPath);
|
|
164
|
+
}
|
|
165
|
+
// Handle extension-less imports
|
|
166
|
+
const ext = extname(resolved);
|
|
167
|
+
if (!ext) {
|
|
168
|
+
// Try common extensions
|
|
169
|
+
const extensions = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'];
|
|
170
|
+
for (const tryExt of extensions) {
|
|
171
|
+
const tryPath = resolved + tryExt;
|
|
172
|
+
return tryPath; // Return normalized, existence check done later
|
|
173
|
+
}
|
|
174
|
+
// Could be index file
|
|
175
|
+
return join(resolved, 'index');
|
|
176
|
+
}
|
|
177
|
+
return resolved;
|
|
178
|
+
}
|
|
179
|
+
// ============================================================================
|
|
180
|
+
// Graph Builder
|
|
181
|
+
// ============================================================================
|
|
182
|
+
/**
|
|
183
|
+
* Build dependency graph from source directory (with caching)
|
|
184
|
+
*/
|
|
185
|
+
export async function buildDependencyGraph(rootDir, options = {}) {
|
|
186
|
+
// Check cache first
|
|
187
|
+
const cacheKey = `${rootDir}:${JSON.stringify(options)}`;
|
|
188
|
+
if (!options.skipCache) {
|
|
189
|
+
const cached = graphCache.get(cacheKey);
|
|
190
|
+
if (cached && Date.now() - cached.timestamp < GRAPH_CACHE_TTL_MS) {
|
|
191
|
+
return cached.graph;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
const startTime = Date.now();
|
|
195
|
+
const nodes = new Map();
|
|
196
|
+
const edges = [];
|
|
197
|
+
const include = options.include || ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'];
|
|
198
|
+
const exclude = options.exclude || ['node_modules', 'dist', 'build', '.git', '__tests__', '*.test.*', '*.spec.*'];
|
|
199
|
+
const maxDepth = options.maxDepth ?? 10;
|
|
200
|
+
/**
|
|
201
|
+
* Check if path should be excluded
|
|
202
|
+
*/
|
|
203
|
+
function shouldExclude(path) {
|
|
204
|
+
const name = basename(path);
|
|
205
|
+
return exclude.some(pattern => {
|
|
206
|
+
if (pattern.includes('*')) {
|
|
207
|
+
const regex = new RegExp('^' + pattern.replace(/\*/g, '.*') + '$');
|
|
208
|
+
return regex.test(name);
|
|
209
|
+
}
|
|
210
|
+
return name === pattern || path.includes(`/${pattern}/`);
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Recursively scan directory for source files
|
|
215
|
+
*/
|
|
216
|
+
async function scanDir(dir, depth) {
|
|
217
|
+
if (depth > maxDepth)
|
|
218
|
+
return;
|
|
219
|
+
try {
|
|
220
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
221
|
+
for (const entry of entries) {
|
|
222
|
+
const fullPath = join(dir, entry.name);
|
|
223
|
+
const relPath = relative(rootDir, fullPath);
|
|
224
|
+
if (shouldExclude(fullPath))
|
|
225
|
+
continue;
|
|
226
|
+
if (entry.isDirectory()) {
|
|
227
|
+
await scanDir(fullPath, depth + 1);
|
|
228
|
+
}
|
|
229
|
+
else if (entry.isFile()) {
|
|
230
|
+
const ext = extname(entry.name);
|
|
231
|
+
if (include.includes(ext)) {
|
|
232
|
+
await processFile(fullPath, relPath);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
// Directory not readable, skip
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Process a single source file
|
|
243
|
+
*/
|
|
244
|
+
async function processFile(fullPath, relPath) {
|
|
245
|
+
try {
|
|
246
|
+
const content = await readFile(fullPath, 'utf-8');
|
|
247
|
+
const fileStats = await stat(fullPath);
|
|
248
|
+
const imports = extractImports(content, fullPath);
|
|
249
|
+
const exportsList = extractExports(content);
|
|
250
|
+
// Create node
|
|
251
|
+
const node = {
|
|
252
|
+
id: relPath,
|
|
253
|
+
path: relPath,
|
|
254
|
+
name: basename(relPath, extname(relPath)),
|
|
255
|
+
type: 'file',
|
|
256
|
+
imports: imports.map(i => i.path),
|
|
257
|
+
exports: exportsList,
|
|
258
|
+
size: fileStats.size,
|
|
259
|
+
complexity: estimateComplexity(content),
|
|
260
|
+
};
|
|
261
|
+
nodes.set(relPath, node);
|
|
262
|
+
// Create edges for imports
|
|
263
|
+
for (const imp of imports) {
|
|
264
|
+
const resolved = resolveImportPath(imp.path, fullPath, rootDir);
|
|
265
|
+
if (resolved) {
|
|
266
|
+
const targetRel = relative(rootDir, resolved);
|
|
267
|
+
edges.push({
|
|
268
|
+
source: relPath,
|
|
269
|
+
target: targetRel,
|
|
270
|
+
type: imp.type,
|
|
271
|
+
weight: imp.type === 're-export' ? 2 : 1,
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
catch {
|
|
277
|
+
// File not readable, skip
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
// Build the graph
|
|
281
|
+
await scanDir(rootDir, 0);
|
|
282
|
+
// Normalize edges - ensure targets exist (with extension variations)
|
|
283
|
+
const normalizedEdges = [];
|
|
284
|
+
for (const edge of edges) {
|
|
285
|
+
// Try to find matching node
|
|
286
|
+
let targetKey = edge.target;
|
|
287
|
+
if (!nodes.has(targetKey)) {
|
|
288
|
+
// Try with different extensions
|
|
289
|
+
const extensions = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'];
|
|
290
|
+
const baseTarget = targetKey.replace(/\.[^.]+$/, '');
|
|
291
|
+
for (const ext of extensions) {
|
|
292
|
+
if (nodes.has(baseTarget + ext)) {
|
|
293
|
+
targetKey = baseTarget + ext;
|
|
294
|
+
break;
|
|
295
|
+
}
|
|
296
|
+
// Try index files
|
|
297
|
+
if (nodes.has(join(baseTarget, 'index' + ext))) {
|
|
298
|
+
targetKey = join(baseTarget, 'index' + ext);
|
|
299
|
+
break;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
if (nodes.has(targetKey)) {
|
|
304
|
+
normalizedEdges.push({ ...edge, target: targetKey });
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
const graph = {
|
|
308
|
+
nodes,
|
|
309
|
+
edges: normalizedEdges,
|
|
310
|
+
metadata: {
|
|
311
|
+
rootDir,
|
|
312
|
+
totalFiles: nodes.size,
|
|
313
|
+
totalEdges: normalizedEdges.length,
|
|
314
|
+
buildTime: Date.now() - startTime,
|
|
315
|
+
},
|
|
316
|
+
};
|
|
317
|
+
// Cache the result
|
|
318
|
+
graphCache.set(cacheKey, { graph, timestamp: Date.now() });
|
|
319
|
+
return graph;
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Estimate cyclomatic complexity from code
|
|
323
|
+
*/
|
|
324
|
+
function estimateComplexity(content) {
|
|
325
|
+
let complexity = 1;
|
|
326
|
+
// Count branching statements
|
|
327
|
+
const patterns = [
|
|
328
|
+
/\bif\s*\(/g,
|
|
329
|
+
/\belse\s+if\s*\(/g,
|
|
330
|
+
/\bfor\s*\(/g,
|
|
331
|
+
/\bwhile\s*\(/g,
|
|
332
|
+
/\bcase\s+/g,
|
|
333
|
+
/\bcatch\s*\(/g,
|
|
334
|
+
/\?\s*[^:]+:/g, // Ternary operator
|
|
335
|
+
/&&/g,
|
|
336
|
+
/\|\|/g,
|
|
337
|
+
];
|
|
338
|
+
for (const pattern of patterns) {
|
|
339
|
+
const matches = content.match(pattern);
|
|
340
|
+
if (matches)
|
|
341
|
+
complexity += matches.length;
|
|
342
|
+
}
|
|
343
|
+
return complexity;
|
|
344
|
+
}
|
|
345
|
+
// ============================================================================
|
|
346
|
+
// MinCut Algorithm (Fallback Implementation)
|
|
347
|
+
// ============================================================================
|
|
348
|
+
/**
|
|
349
|
+
* Stoer-Wagner MinCut algorithm (fallback when ruvector not available)
|
|
350
|
+
* Finds minimum cut with deterministic result
|
|
351
|
+
*/
|
|
352
|
+
function fallbackMinCut(nodes, edges) {
|
|
353
|
+
if (nodes.length < 2) {
|
|
354
|
+
return {
|
|
355
|
+
cutValue: 0,
|
|
356
|
+
partition1: nodes,
|
|
357
|
+
partition2: [],
|
|
358
|
+
cutEdges: [],
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
// Build adjacency map with weights
|
|
362
|
+
const adj = new Map();
|
|
363
|
+
for (const node of nodes) {
|
|
364
|
+
adj.set(node, new Map());
|
|
365
|
+
}
|
|
366
|
+
for (const [u, v, w] of edges) {
|
|
367
|
+
if (adj.has(u) && adj.has(v)) {
|
|
368
|
+
adj.get(u).set(v, (adj.get(u).get(v) || 0) + w);
|
|
369
|
+
adj.get(v).set(u, (adj.get(v).get(u) || 0) + w);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
let bestCut = Infinity;
|
|
373
|
+
let bestPartition1 = [];
|
|
374
|
+
let bestPartition2 = [];
|
|
375
|
+
let bestCutEdges = [];
|
|
376
|
+
// Run multiple iterations for better results
|
|
377
|
+
const iterations = Math.min(nodes.length * 2, 20);
|
|
378
|
+
for (let iter = 0; iter < iterations; iter++) {
|
|
379
|
+
// Start from different nodes
|
|
380
|
+
const startNode = nodes[iter % nodes.length];
|
|
381
|
+
const inSet = new Set([startNode]);
|
|
382
|
+
const remaining = new Set(nodes.filter(n => n !== startNode));
|
|
383
|
+
while (remaining.size > 1) {
|
|
384
|
+
// Find node with maximum connectivity to current set
|
|
385
|
+
let maxNode = '';
|
|
386
|
+
let maxConn = -1;
|
|
387
|
+
for (const node of Array.from(remaining)) {
|
|
388
|
+
let conn = 0;
|
|
389
|
+
for (const inNode of Array.from(inSet)) {
|
|
390
|
+
conn += adj.get(node)?.get(inNode) || 0;
|
|
391
|
+
}
|
|
392
|
+
if (conn > maxConn) {
|
|
393
|
+
maxConn = conn;
|
|
394
|
+
maxNode = node;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
if (!maxNode)
|
|
398
|
+
break;
|
|
399
|
+
remaining.delete(maxNode);
|
|
400
|
+
inSet.add(maxNode);
|
|
401
|
+
}
|
|
402
|
+
if (remaining.size === 1) {
|
|
403
|
+
const lastNode = Array.from(remaining)[0];
|
|
404
|
+
let cutValue = 0;
|
|
405
|
+
const cutEdges = [];
|
|
406
|
+
for (const inNode of Array.from(inSet)) {
|
|
407
|
+
const weight = adj.get(lastNode)?.get(inNode) || 0;
|
|
408
|
+
if (weight > 0) {
|
|
409
|
+
cutValue += weight;
|
|
410
|
+
cutEdges.push([lastNode, inNode]);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
if (cutValue < bestCut) {
|
|
414
|
+
bestCut = cutValue;
|
|
415
|
+
bestPartition1 = Array.from(inSet);
|
|
416
|
+
bestPartition2 = [lastNode];
|
|
417
|
+
bestCutEdges = cutEdges;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
// If we didn't find a good cut, split roughly in half
|
|
422
|
+
if (bestCut === Infinity) {
|
|
423
|
+
const mid = Math.floor(nodes.length / 2);
|
|
424
|
+
bestPartition1 = nodes.slice(0, mid);
|
|
425
|
+
bestPartition2 = nodes.slice(mid);
|
|
426
|
+
bestCut = 0;
|
|
427
|
+
bestCutEdges = [];
|
|
428
|
+
for (const [u, v, w] of edges) {
|
|
429
|
+
const uIn1 = bestPartition1.includes(u);
|
|
430
|
+
const vIn1 = bestPartition1.includes(v);
|
|
431
|
+
if (uIn1 !== vIn1) {
|
|
432
|
+
bestCut += w;
|
|
433
|
+
bestCutEdges.push([u, v]);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
return {
|
|
438
|
+
cutValue: bestCut,
|
|
439
|
+
partition1: bestPartition1,
|
|
440
|
+
partition2: bestPartition2,
|
|
441
|
+
cutEdges: bestCutEdges,
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
// ============================================================================
|
|
445
|
+
// Louvain Algorithm (Fallback Implementation)
|
|
446
|
+
// ============================================================================
|
|
447
|
+
/**
|
|
448
|
+
* Louvain community detection algorithm (fallback when ruvector not available)
|
|
449
|
+
* Greedy modularity optimization
|
|
450
|
+
*/
|
|
451
|
+
function fallbackLouvain(nodes, edges) {
|
|
452
|
+
if (nodes.length === 0) {
|
|
453
|
+
return { communities: [], modularity: 0 };
|
|
454
|
+
}
|
|
455
|
+
// Build adjacency map
|
|
456
|
+
const adj = new Map();
|
|
457
|
+
for (const node of nodes) {
|
|
458
|
+
adj.set(node, new Map());
|
|
459
|
+
}
|
|
460
|
+
let totalWeight = 0;
|
|
461
|
+
for (const [u, v, w] of edges) {
|
|
462
|
+
if (adj.has(u) && adj.has(v)) {
|
|
463
|
+
adj.get(u).set(v, (adj.get(u).get(v) || 0) + w);
|
|
464
|
+
adj.get(v).set(u, (adj.get(v).get(u) || 0) + w);
|
|
465
|
+
totalWeight += w * 2;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
if (totalWeight === 0) {
|
|
469
|
+
// No edges, each node is its own community
|
|
470
|
+
return {
|
|
471
|
+
communities: nodes.map((n, i) => ({ id: i, members: [n] })),
|
|
472
|
+
modularity: 0,
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
// Initialize: each node in its own community
|
|
476
|
+
const community = new Map();
|
|
477
|
+
let nextCommunityId = 0;
|
|
478
|
+
for (const node of nodes) {
|
|
479
|
+
community.set(node, nextCommunityId++);
|
|
480
|
+
}
|
|
481
|
+
// Calculate node degree
|
|
482
|
+
const degree = new Map();
|
|
483
|
+
for (const node of nodes) {
|
|
484
|
+
let d = 0;
|
|
485
|
+
for (const [, w] of Array.from(adj.get(node).entries())) {
|
|
486
|
+
d += w;
|
|
487
|
+
}
|
|
488
|
+
degree.set(node, d);
|
|
489
|
+
}
|
|
490
|
+
// Louvain phase 1: local moving
|
|
491
|
+
let improved = true;
|
|
492
|
+
const maxIterations = 10;
|
|
493
|
+
let iteration = 0;
|
|
494
|
+
while (improved && iteration < maxIterations) {
|
|
495
|
+
improved = false;
|
|
496
|
+
iteration++;
|
|
497
|
+
for (const node of nodes) {
|
|
498
|
+
const currentCommunity = community.get(node);
|
|
499
|
+
const nodeAdj = adj.get(node);
|
|
500
|
+
const nodeDegree = degree.get(node);
|
|
501
|
+
// Calculate modularity gain for moving to each neighbor's community
|
|
502
|
+
const communityWeights = new Map();
|
|
503
|
+
for (const [neighbor, weight] of Array.from(nodeAdj.entries())) {
|
|
504
|
+
const neighborCommunity = community.get(neighbor);
|
|
505
|
+
communityWeights.set(neighborCommunity, (communityWeights.get(neighborCommunity) || 0) + weight);
|
|
506
|
+
}
|
|
507
|
+
// Calculate community totals
|
|
508
|
+
const communityTotal = new Map();
|
|
509
|
+
for (const [n, c] of Array.from(community.entries())) {
|
|
510
|
+
communityTotal.set(c, (communityTotal.get(c) || 0) + (degree.get(n) || 0));
|
|
511
|
+
}
|
|
512
|
+
let bestCommunity = currentCommunity;
|
|
513
|
+
let bestGain = 0;
|
|
514
|
+
for (const [targetCommunity, edgeWeight] of Array.from(communityWeights.entries())) {
|
|
515
|
+
if (targetCommunity === currentCommunity)
|
|
516
|
+
continue;
|
|
517
|
+
// Calculate modularity gain
|
|
518
|
+
const currentTotal = communityTotal.get(currentCommunity) || 0;
|
|
519
|
+
const targetTotal = communityTotal.get(targetCommunity) || 0;
|
|
520
|
+
const currentEdges = communityWeights.get(currentCommunity) || 0;
|
|
521
|
+
const gain = (edgeWeight - currentEdges) / totalWeight -
|
|
522
|
+
(nodeDegree * (targetTotal - currentTotal + nodeDegree)) / (totalWeight * totalWeight);
|
|
523
|
+
if (gain > bestGain) {
|
|
524
|
+
bestGain = gain;
|
|
525
|
+
bestCommunity = targetCommunity;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
if (bestCommunity !== currentCommunity) {
|
|
529
|
+
community.set(node, bestCommunity);
|
|
530
|
+
improved = true;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
// Collect communities
|
|
535
|
+
const communityMembers = new Map();
|
|
536
|
+
for (const [node, comm] of Array.from(community.entries())) {
|
|
537
|
+
if (!communityMembers.has(comm)) {
|
|
538
|
+
communityMembers.set(comm, []);
|
|
539
|
+
}
|
|
540
|
+
communityMembers.get(comm).push(node);
|
|
541
|
+
}
|
|
542
|
+
// Renumber communities
|
|
543
|
+
const communities = [];
|
|
544
|
+
let id = 0;
|
|
545
|
+
for (const members of Array.from(communityMembers.values())) {
|
|
546
|
+
communities.push({ id: id++, members });
|
|
547
|
+
}
|
|
548
|
+
// Calculate modularity
|
|
549
|
+
let modularity = 0;
|
|
550
|
+
for (const [u, v, w] of edges) {
|
|
551
|
+
const cu = community.get(u);
|
|
552
|
+
const cv = community.get(v);
|
|
553
|
+
if (cu === cv) {
|
|
554
|
+
const du = degree.get(u);
|
|
555
|
+
const dv = degree.get(v);
|
|
556
|
+
modularity += w - (du * dv) / totalWeight;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
modularity /= totalWeight;
|
|
560
|
+
return { communities, modularity };
|
|
561
|
+
}
|
|
562
|
+
// ============================================================================
|
|
563
|
+
// Circular Dependency Detection
|
|
564
|
+
// ============================================================================
|
|
565
|
+
/**
|
|
566
|
+
* Detect circular dependencies using DFS
|
|
567
|
+
*/
|
|
568
|
+
export function detectCircularDependencies(graph) {
|
|
569
|
+
const cycles = [];
|
|
570
|
+
const visited = new Set();
|
|
571
|
+
const recursionStack = new Set();
|
|
572
|
+
const path = [];
|
|
573
|
+
// Build adjacency list
|
|
574
|
+
const adjList = new Map();
|
|
575
|
+
for (const node of Array.from(graph.nodes.keys())) {
|
|
576
|
+
adjList.set(node, []);
|
|
577
|
+
}
|
|
578
|
+
for (const edge of graph.edges) {
|
|
579
|
+
const list = adjList.get(edge.source);
|
|
580
|
+
if (list) {
|
|
581
|
+
list.push(edge.target);
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
function dfs(node) {
|
|
585
|
+
visited.add(node);
|
|
586
|
+
recursionStack.add(node);
|
|
587
|
+
path.push(node);
|
|
588
|
+
const neighbors = adjList.get(node) || [];
|
|
589
|
+
for (const neighbor of neighbors) {
|
|
590
|
+
if (!visited.has(neighbor)) {
|
|
591
|
+
dfs(neighbor);
|
|
592
|
+
}
|
|
593
|
+
else if (recursionStack.has(neighbor)) {
|
|
594
|
+
// Found cycle
|
|
595
|
+
const cycleStart = path.indexOf(neighbor);
|
|
596
|
+
const cycle = path.slice(cycleStart);
|
|
597
|
+
cycle.push(neighbor); // Complete the cycle
|
|
598
|
+
const severity = getCycleSeverity(cycle, graph);
|
|
599
|
+
cycles.push({
|
|
600
|
+
cycle,
|
|
601
|
+
severity,
|
|
602
|
+
suggestion: getCycleSuggestion(cycle, graph),
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
recursionStack.delete(node);
|
|
607
|
+
path.pop();
|
|
608
|
+
}
|
|
609
|
+
for (const node of Array.from(graph.nodes.keys())) {
|
|
610
|
+
if (!visited.has(node)) {
|
|
611
|
+
dfs(node);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
return cycles;
|
|
615
|
+
}
|
|
616
|
+
function getCycleSeverity(cycle, _graph) {
|
|
617
|
+
// High severity if cycle involves many files or core modules
|
|
618
|
+
if (cycle.length > 5)
|
|
619
|
+
return 'high';
|
|
620
|
+
if (cycle.some(n => n.includes('index') || n.includes('core')))
|
|
621
|
+
return 'high';
|
|
622
|
+
if (cycle.length > 3)
|
|
623
|
+
return 'medium';
|
|
624
|
+
return 'low';
|
|
625
|
+
}
|
|
626
|
+
function getCycleSuggestion(cycle, graph) {
|
|
627
|
+
if (cycle.length === 2) {
|
|
628
|
+
return `Consider extracting shared code into a separate module to break the cycle between ${cycle[0]} and ${cycle[1]}`;
|
|
629
|
+
}
|
|
630
|
+
// Find the weakest link (least important edge)
|
|
631
|
+
let weakestEdge = '';
|
|
632
|
+
let minImports = Infinity;
|
|
633
|
+
for (let i = 0; i < cycle.length - 1; i++) {
|
|
634
|
+
const from = cycle[i];
|
|
635
|
+
const to = cycle[i + 1];
|
|
636
|
+
const fromNode = graph.nodes.get(from);
|
|
637
|
+
if (fromNode && fromNode.imports.length < minImports) {
|
|
638
|
+
minImports = fromNode.imports.length;
|
|
639
|
+
weakestEdge = `${from} -> ${to}`;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
return `Break the cycle by refactoring the dependency: ${weakestEdge}. Consider dependency injection or extracting interfaces.`;
|
|
643
|
+
}
|
|
644
|
+
// ============================================================================
|
|
645
|
+
// Main Analysis Functions
|
|
646
|
+
// ============================================================================
|
|
647
|
+
/**
|
|
648
|
+
* Analyze graph boundaries using MinCut algorithm
|
|
649
|
+
*/
|
|
650
|
+
export async function analyzeMinCutBoundaries(graph, numPartitions = 2) {
|
|
651
|
+
const nodes = Array.from(graph.nodes.keys());
|
|
652
|
+
const edges = graph.edges.map(e => [e.source, e.target, e.weight]);
|
|
653
|
+
const boundaries = [];
|
|
654
|
+
// Try to use ruvector, fallback to built-in
|
|
655
|
+
const ruVector = await loadRuVector();
|
|
656
|
+
// Get initial partition
|
|
657
|
+
let result;
|
|
658
|
+
if (ruVector) {
|
|
659
|
+
result = ruVector.mincut(nodes, edges);
|
|
660
|
+
}
|
|
661
|
+
else {
|
|
662
|
+
result = fallbackMinCut(nodes, edges);
|
|
663
|
+
}
|
|
664
|
+
boundaries.push({
|
|
665
|
+
cutValue: result.cutValue,
|
|
666
|
+
partition1: result.partition1,
|
|
667
|
+
partition2: result.partition2,
|
|
668
|
+
cutEdges: result.cutEdges.map(([s, t]) => {
|
|
669
|
+
const edge = graph.edges.find(e => e.source === s && e.target === t);
|
|
670
|
+
return edge || { source: s, target: t, type: 'import', weight: 1 };
|
|
671
|
+
}),
|
|
672
|
+
suggestion: generateBoundarySuggestion(result.partition1, result.partition2, graph),
|
|
673
|
+
});
|
|
674
|
+
// Recursively partition if needed
|
|
675
|
+
if (numPartitions > 2 && result.partition1.length > 2) {
|
|
676
|
+
const subEdges = edges.filter(([u, v]) => result.partition1.includes(u) && result.partition1.includes(v));
|
|
677
|
+
const subResult = ruVector
|
|
678
|
+
? ruVector.mincut(result.partition1, subEdges)
|
|
679
|
+
: fallbackMinCut(result.partition1, subEdges);
|
|
680
|
+
if (subResult.cutValue > 0) {
|
|
681
|
+
boundaries.push({
|
|
682
|
+
cutValue: subResult.cutValue,
|
|
683
|
+
partition1: subResult.partition1,
|
|
684
|
+
partition2: subResult.partition2,
|
|
685
|
+
cutEdges: subResult.cutEdges.map(([s, t]) => {
|
|
686
|
+
const edge = graph.edges.find(e => e.source === s && e.target === t);
|
|
687
|
+
return edge || { source: s, target: t, type: 'import', weight: 1 };
|
|
688
|
+
}),
|
|
689
|
+
suggestion: generateBoundarySuggestion(subResult.partition1, subResult.partition2, graph),
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
return boundaries;
|
|
694
|
+
}
|
|
695
|
+
function generateBoundarySuggestion(partition1, partition2, _graph) {
|
|
696
|
+
// Analyze the partitions to suggest organization
|
|
697
|
+
const p1Dirs = partition1.map(p => dirname(p)).filter(d => d !== '.');
|
|
698
|
+
const p2Dirs = partition2.map(p => dirname(p)).filter(d => d !== '.');
|
|
699
|
+
const p1DirsSet = new Set(p1Dirs);
|
|
700
|
+
const p2DirsSet = new Set(p2Dirs);
|
|
701
|
+
if (p1DirsSet.size === 1 && p2DirsSet.size === 1) {
|
|
702
|
+
const dir1 = p1Dirs[0];
|
|
703
|
+
const dir2 = p2Dirs[0];
|
|
704
|
+
return `Natural boundary detected between ${dir1}/ and ${dir2}/. These could be separate packages.`;
|
|
705
|
+
}
|
|
706
|
+
if (partition1.length > partition2.length * 3) {
|
|
707
|
+
return `Consider extracting ${partition2.length} files into a separate module. They have minimal coupling to the rest.`;
|
|
708
|
+
}
|
|
709
|
+
return `Found ${partition1.length} and ${partition2.length} file groups with minimal coupling. Consider organizing into separate modules.`;
|
|
710
|
+
}
|
|
711
|
+
/**
|
|
712
|
+
* Analyze module communities using Louvain algorithm
|
|
713
|
+
*/
|
|
714
|
+
export async function analyzeModuleCommunities(graph) {
|
|
715
|
+
const nodes = Array.from(graph.nodes.keys());
|
|
716
|
+
const edges = graph.edges.map(e => [e.source, e.target, e.weight]);
|
|
717
|
+
// Try to use ruvector, fallback to built-in
|
|
718
|
+
const ruVector = await loadRuVector();
|
|
719
|
+
const result = ruVector ? ruVector.louvain(nodes, edges) : fallbackLouvain(nodes, edges);
|
|
720
|
+
return result.communities.map(comm => {
|
|
721
|
+
// Find the most connected node as central
|
|
722
|
+
let maxConnections = 0;
|
|
723
|
+
let centralNode = comm.members[0];
|
|
724
|
+
for (const member of comm.members) {
|
|
725
|
+
const connections = graph.edges.filter(e => (e.source === member && comm.members.includes(e.target)) ||
|
|
726
|
+
(e.target === member && comm.members.includes(e.source))).length;
|
|
727
|
+
if (connections > maxConnections) {
|
|
728
|
+
maxConnections = connections;
|
|
729
|
+
centralNode = member;
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
// Calculate cohesion (internal edges / total possible edges)
|
|
733
|
+
const internalEdges = graph.edges.filter(e => comm.members.includes(e.source) && comm.members.includes(e.target)).length;
|
|
734
|
+
const possibleEdges = (comm.members.length * (comm.members.length - 1)) / 2;
|
|
735
|
+
const cohesion = possibleEdges > 0 ? internalEdges / possibleEdges : 1;
|
|
736
|
+
// Suggest name based on common directory
|
|
737
|
+
const dirs = comm.members.map(m => dirname(m));
|
|
738
|
+
const commonDir = findCommonPrefix(dirs);
|
|
739
|
+
const suggestedName = commonDir || basename(centralNode, extname(centralNode));
|
|
740
|
+
return {
|
|
741
|
+
id: comm.id,
|
|
742
|
+
members: comm.members,
|
|
743
|
+
cohesion,
|
|
744
|
+
centralNode,
|
|
745
|
+
suggestedName,
|
|
746
|
+
};
|
|
747
|
+
});
|
|
748
|
+
}
|
|
749
|
+
function findCommonPrefix(strings) {
|
|
750
|
+
if (strings.length === 0)
|
|
751
|
+
return '';
|
|
752
|
+
if (strings.length === 1)
|
|
753
|
+
return strings[0];
|
|
754
|
+
const sorted = [...strings].sort();
|
|
755
|
+
const first = sorted[0];
|
|
756
|
+
const last = sorted[sorted.length - 1];
|
|
757
|
+
let i = 0;
|
|
758
|
+
while (i < first.length && first[i] === last[i]) {
|
|
759
|
+
i++;
|
|
760
|
+
}
|
|
761
|
+
const prefix = first.slice(0, i);
|
|
762
|
+
// Return the last complete directory segment
|
|
763
|
+
const lastSlash = prefix.lastIndexOf('/');
|
|
764
|
+
return lastSlash > 0 ? prefix.slice(0, lastSlash) : '';
|
|
765
|
+
}
|
|
766
|
+
/**
|
|
767
|
+
* Full graph analysis (with caching)
|
|
768
|
+
*/
|
|
769
|
+
export async function analyzeGraph(rootDir, options = {}) {
|
|
770
|
+
// Check cache first
|
|
771
|
+
const cacheKey = `analysis:${rootDir}:${JSON.stringify(options)}`;
|
|
772
|
+
if (!options.skipCache) {
|
|
773
|
+
const cached = analysisResultCache.get(cacheKey);
|
|
774
|
+
if (cached && Date.now() - cached.timestamp < ANALYSIS_CACHE_TTL_MS) {
|
|
775
|
+
return cached.result;
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
const graph = await buildDependencyGraph(rootDir, { skipCache: options.skipCache });
|
|
779
|
+
// Calculate statistics
|
|
780
|
+
const nodeCount = graph.nodes.size;
|
|
781
|
+
const edgeCount = graph.edges.length;
|
|
782
|
+
const degrees = new Map();
|
|
783
|
+
for (const node of Array.from(graph.nodes.keys())) {
|
|
784
|
+
degrees.set(node, 0);
|
|
785
|
+
}
|
|
786
|
+
for (const edge of graph.edges) {
|
|
787
|
+
degrees.set(edge.source, (degrees.get(edge.source) || 0) + 1);
|
|
788
|
+
degrees.set(edge.target, (degrees.get(edge.target) || 0) + 1);
|
|
789
|
+
}
|
|
790
|
+
const degreeValues = Array.from(degrees.values());
|
|
791
|
+
const avgDegree = degreeValues.length > 0 ? degreeValues.reduce((a, b) => a + b, 0) / degreeValues.length : 0;
|
|
792
|
+
const maxDegree = degreeValues.length > 0 ? Math.max(...degreeValues) : 0;
|
|
793
|
+
const density = nodeCount > 1 ? (2 * edgeCount) / (nodeCount * (nodeCount - 1)) : 0;
|
|
794
|
+
// Count connected components
|
|
795
|
+
const visited = new Set();
|
|
796
|
+
let componentCount = 0;
|
|
797
|
+
function dfs(node) {
|
|
798
|
+
visited.add(node);
|
|
799
|
+
for (const edge of graph.edges) {
|
|
800
|
+
if (edge.source === node && !visited.has(edge.target)) {
|
|
801
|
+
dfs(edge.target);
|
|
802
|
+
}
|
|
803
|
+
if (edge.target === node && !visited.has(edge.source)) {
|
|
804
|
+
dfs(edge.source);
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
for (const node of Array.from(graph.nodes.keys())) {
|
|
809
|
+
if (!visited.has(node)) {
|
|
810
|
+
componentCount++;
|
|
811
|
+
dfs(node);
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
// Detect circular dependencies
|
|
815
|
+
const circularDependencies = detectCircularDependencies(graph);
|
|
816
|
+
// Analyze boundaries and communities if requested
|
|
817
|
+
let boundaries;
|
|
818
|
+
let communities;
|
|
819
|
+
if (options.includeBoundaries !== false) {
|
|
820
|
+
boundaries = await analyzeMinCutBoundaries(graph, options.numPartitions);
|
|
821
|
+
}
|
|
822
|
+
if (options.includeModules !== false) {
|
|
823
|
+
communities = await analyzeModuleCommunities(graph);
|
|
824
|
+
}
|
|
825
|
+
const result = {
|
|
826
|
+
graph,
|
|
827
|
+
boundaries,
|
|
828
|
+
communities,
|
|
829
|
+
circularDependencies,
|
|
830
|
+
statistics: {
|
|
831
|
+
nodeCount,
|
|
832
|
+
edgeCount,
|
|
833
|
+
avgDegree,
|
|
834
|
+
maxDegree,
|
|
835
|
+
density,
|
|
836
|
+
componentCount,
|
|
837
|
+
},
|
|
838
|
+
};
|
|
839
|
+
// Cache the result
|
|
840
|
+
analysisResultCache.set(cacheKey, { result, timestamp: Date.now() });
|
|
841
|
+
return result;
|
|
842
|
+
}
|
|
843
|
+
// ============================================================================
|
|
844
|
+
// DOT Format Export
|
|
845
|
+
// ============================================================================
|
|
846
|
+
/**
|
|
847
|
+
* Export graph to DOT format for visualization
|
|
848
|
+
*/
|
|
849
|
+
export function exportToDot(result, options = {}) {
|
|
850
|
+
const { graph, communities, circularDependencies } = result;
|
|
851
|
+
const lines = ['digraph DependencyGraph {'];
|
|
852
|
+
lines.push(' rankdir=LR;');
|
|
853
|
+
lines.push(' node [shape=box, style=rounded];');
|
|
854
|
+
lines.push('');
|
|
855
|
+
// Generate colors for communities
|
|
856
|
+
const communityColors = new Map();
|
|
857
|
+
if (options.colorByCommunity && communities) {
|
|
858
|
+
const colors = [
|
|
859
|
+
'#e6194b', '#3cb44b', '#ffe119', '#4363d8', '#f58231',
|
|
860
|
+
'#911eb4', '#42d4f4', '#f032e6', '#bfef45', '#fabed4',
|
|
861
|
+
];
|
|
862
|
+
for (const comm of communities) {
|
|
863
|
+
const color = colors[comm.id % colors.length];
|
|
864
|
+
for (const member of comm.members) {
|
|
865
|
+
communityColors.set(member, color);
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
// Find nodes in cycles
|
|
870
|
+
const nodesInCycles = new Set();
|
|
871
|
+
if (options.highlightCycles && circularDependencies) {
|
|
872
|
+
for (const cycle of circularDependencies) {
|
|
873
|
+
for (const node of cycle.cycle) {
|
|
874
|
+
nodesInCycles.add(node);
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
// Output nodes
|
|
879
|
+
lines.push(' // Nodes');
|
|
880
|
+
for (const [id, node] of Array.from(graph.nodes.entries())) {
|
|
881
|
+
const attrs = [];
|
|
882
|
+
if (options.includeLabels !== false) {
|
|
883
|
+
attrs.push(`label="${node.name}"`);
|
|
884
|
+
}
|
|
885
|
+
if (communityColors.has(id)) {
|
|
886
|
+
attrs.push(`fillcolor="${communityColors.get(id)}"`, 'style="filled,rounded"');
|
|
887
|
+
}
|
|
888
|
+
if (nodesInCycles.has(id)) {
|
|
889
|
+
attrs.push('color=red', 'penwidth=2');
|
|
890
|
+
}
|
|
891
|
+
const attrStr = attrs.length > 0 ? ` [${attrs.join(', ')}]` : '';
|
|
892
|
+
lines.push(` "${id}"${attrStr};`);
|
|
893
|
+
}
|
|
894
|
+
lines.push('');
|
|
895
|
+
// Output edges
|
|
896
|
+
lines.push(' // Edges');
|
|
897
|
+
for (const edge of graph.edges) {
|
|
898
|
+
const attrs = [];
|
|
899
|
+
if (edge.type === 'dynamic') {
|
|
900
|
+
attrs.push('style=dashed');
|
|
901
|
+
}
|
|
902
|
+
else if (edge.type === 're-export') {
|
|
903
|
+
attrs.push('style=bold');
|
|
904
|
+
}
|
|
905
|
+
// Check if edge is part of a cycle
|
|
906
|
+
if (options.highlightCycles) {
|
|
907
|
+
const isCycleEdge = circularDependencies.some(cd => {
|
|
908
|
+
for (let i = 0; i < cd.cycle.length - 1; i++) {
|
|
909
|
+
if (cd.cycle[i] === edge.source && cd.cycle[i + 1] === edge.target) {
|
|
910
|
+
return true;
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
return false;
|
|
914
|
+
});
|
|
915
|
+
if (isCycleEdge) {
|
|
916
|
+
attrs.push('color=red', 'penwidth=2');
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
const attrStr = attrs.length > 0 ? ` [${attrs.join(', ')}]` : '';
|
|
920
|
+
lines.push(` "${edge.source}" -> "${edge.target}"${attrStr};`);
|
|
921
|
+
}
|
|
922
|
+
lines.push('}');
|
|
923
|
+
return lines.join('\n');
|
|
924
|
+
}
|
|
925
|
+
// ============================================================================
|
|
926
|
+
// Exports
|
|
927
|
+
// ============================================================================
|
|
928
|
+
export { loadRuVector, fallbackMinCut, fallbackLouvain, };
|
|
929
|
+
//# sourceMappingURL=graph-analyzer.js.map
|