moai-adk 0.8.0__py3-none-any.whl → 0.34.0__py3-none-any.whl
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.
- moai_adk/__init__.py +2 -6
- moai_adk/__main__.py +136 -21
- moai_adk/cli/__init__.py +6 -2
- moai_adk/cli/commands/__init__.py +1 -4
- moai_adk/cli/commands/analyze.py +116 -0
- moai_adk/cli/commands/doctor.py +17 -5
- moai_adk/cli/commands/init.py +118 -48
- moai_adk/cli/commands/language.py +248 -0
- moai_adk/cli/commands/status.py +8 -13
- moai_adk/cli/commands/update.py +1978 -149
- moai_adk/cli/main.py +3 -2
- moai_adk/cli/prompts/init_prompts.py +144 -91
- moai_adk/cli/spec_status.py +263 -0
- moai_adk/cli/ui/__init__.py +44 -0
- moai_adk/cli/ui/progress.py +422 -0
- moai_adk/cli/ui/prompts.py +389 -0
- moai_adk/cli/ui/theme.py +129 -0
- moai_adk/cli/worktree/__init__.py +27 -0
- moai_adk/cli/worktree/__main__.py +31 -0
- moai_adk/cli/worktree/cli.py +683 -0
- moai_adk/cli/worktree/exceptions.py +89 -0
- moai_adk/cli/worktree/manager.py +493 -0
- moai_adk/cli/worktree/models.py +65 -0
- moai_adk/cli/worktree/registry.py +422 -0
- moai_adk/core/PHASE2_OPTIMIZATIONS.md +467 -0
- moai_adk/core/__init__.py +0 -1
- moai_adk/core/analysis/__init__.py +9 -0
- moai_adk/core/analysis/session_analyzer.py +400 -0
- moai_adk/core/claude_integration.py +393 -0
- moai_adk/core/command_helpers.py +270 -0
- moai_adk/core/comprehensive_monitoring_system.py +1183 -0
- moai_adk/core/config/__init__.py +6 -0
- moai_adk/core/config/auto_spec_config.py +340 -0
- moai_adk/core/config/migration.py +148 -17
- moai_adk/core/config/unified.py +436 -0
- moai_adk/core/context_manager.py +273 -0
- moai_adk/core/diagnostics/slash_commands.py +0 -1
- moai_adk/core/enterprise_features.py +1404 -0
- moai_adk/core/error_recovery_system.py +1902 -0
- moai_adk/core/event_driven_hook_system.py +1371 -0
- moai_adk/core/git/__init__.py +8 -1
- moai_adk/core/git/branch.py +0 -1
- moai_adk/core/git/branch_manager.py +2 -10
- moai_adk/core/git/checkpoint.py +1 -7
- moai_adk/core/git/commit.py +0 -1
- moai_adk/core/git/conflict_detector.py +413 -0
- moai_adk/core/git/event_detector.py +3 -5
- moai_adk/core/git/manager.py +91 -2
- moai_adk/core/hooks/post_tool_auto_spec_completion.py +901 -0
- moai_adk/core/input_validation_middleware.py +1006 -0
- moai_adk/core/integration/__init__.py +22 -0
- moai_adk/core/integration/engine.py +157 -0
- moai_adk/core/integration/integration_tester.py +226 -0
- moai_adk/core/integration/models.py +88 -0
- moai_adk/core/integration/utils.py +211 -0
- moai_adk/core/issue_creator.py +305 -0
- moai_adk/core/jit_context_loader.py +956 -0
- moai_adk/core/jit_enhanced_hook_manager.py +1987 -0
- moai_adk/core/language_config.py +202 -0
- moai_adk/core/language_config_resolver.py +572 -0
- moai_adk/core/language_validator.py +543 -0
- moai_adk/core/mcp/setup.py +116 -0
- moai_adk/core/merge/__init__.py +9 -0
- moai_adk/core/merge/analyzer.py +481 -0
- moai_adk/core/migration/__init__.py +18 -0
- moai_adk/core/migration/alfred_to_moai_migrator.py +383 -0
- moai_adk/core/migration/backup_manager.py +277 -0
- moai_adk/core/migration/custom_element_scanner.py +358 -0
- moai_adk/core/migration/file_migrator.py +209 -0
- moai_adk/core/migration/interactive_checkbox_ui.py +488 -0
- moai_adk/core/migration/selective_restorer.py +470 -0
- moai_adk/core/migration/template_utils.py +74 -0
- moai_adk/core/migration/user_selection_ui.py +338 -0
- moai_adk/core/migration/version_detector.py +139 -0
- moai_adk/core/migration/version_migrator.py +228 -0
- moai_adk/core/performance/__init__.py +6 -0
- moai_adk/core/performance/cache_system.py +316 -0
- moai_adk/core/performance/parallel_processor.py +116 -0
- moai_adk/core/phase_optimized_hook_scheduler.py +879 -0
- moai_adk/core/project/__init__.py +0 -1
- moai_adk/core/project/backup_utils.py +2 -7
- moai_adk/core/project/checker.py +2 -4
- moai_adk/core/project/detector.py +189 -22
- moai_adk/core/project/initializer.py +218 -27
- moai_adk/core/project/phase_executor.py +416 -44
- moai_adk/core/project/validator.py +7 -32
- moai_adk/core/quality/__init__.py +1 -1
- moai_adk/core/quality/trust_checker.py +37 -101
- moai_adk/core/quality/validators/__init__.py +1 -1
- moai_adk/core/quality/validators/base_validator.py +1 -1
- moai_adk/core/realtime_monitoring_dashboard.py +1724 -0
- moai_adk/core/robust_json_parser.py +611 -0
- moai_adk/core/rollback_manager.py +918 -0
- moai_adk/core/session_manager.py +651 -0
- moai_adk/core/skill_loading_system.py +579 -0
- moai_adk/core/spec/confidence_scoring.py +680 -0
- moai_adk/core/spec/ears_template_engine.py +1247 -0
- moai_adk/core/spec/quality_validator.py +687 -0
- moai_adk/core/spec_status_manager.py +478 -0
- moai_adk/core/template/__init__.py +0 -1
- moai_adk/core/template/backup.py +82 -17
- moai_adk/core/template/config.py +112 -40
- moai_adk/core/template/languages.py +0 -1
- moai_adk/core/template/merger.py +75 -26
- moai_adk/core/template/processor.py +750 -72
- moai_adk/core/template_engine.py +310 -0
- moai_adk/core/template_variable_synchronizer.py +417 -0
- moai_adk/core/unified_permission_manager.py +745 -0
- moai_adk/core/user_behavior_analytics.py +851 -0
- moai_adk/core/version_sync.py +429 -0
- moai_adk/foundation/__init__.py +56 -0
- moai_adk/foundation/backend.py +1027 -0
- moai_adk/foundation/database.py +1115 -0
- moai_adk/foundation/devops.py +1585 -0
- moai_adk/foundation/ears.py +431 -0
- moai_adk/foundation/frontend.py +870 -0
- moai_adk/foundation/git/commit_templates.py +557 -0
- moai_adk/foundation/git.py +376 -0
- moai_adk/foundation/langs.py +484 -0
- moai_adk/foundation/ml_ops.py +1162 -0
- moai_adk/foundation/testing.py +1524 -0
- moai_adk/foundation/trust/trust_principles.py +676 -0
- moai_adk/foundation/trust/validation_checklist.py +1573 -0
- moai_adk/project/__init__.py +0 -0
- moai_adk/project/configuration.py +1084 -0
- moai_adk/project/documentation.py +566 -0
- moai_adk/project/schema.py +447 -0
- moai_adk/statusline/__init__.py +38 -0
- moai_adk/statusline/alfred_detector.py +105 -0
- moai_adk/statusline/config.py +376 -0
- moai_adk/statusline/enhanced_output_style_detector.py +372 -0
- moai_adk/statusline/git_collector.py +190 -0
- moai_adk/statusline/main.py +322 -0
- moai_adk/statusline/metrics_tracker.py +78 -0
- moai_adk/statusline/renderer.py +343 -0
- moai_adk/statusline/update_checker.py +129 -0
- moai_adk/statusline/version_reader.py +741 -0
- moai_adk/templates/.claude/agents/moai/ai-nano-banana.md +670 -0
- moai_adk/templates/.claude/agents/moai/builder-agent.md +474 -0
- moai_adk/templates/.claude/agents/moai/builder-command.md +1172 -0
- moai_adk/templates/.claude/agents/moai/builder-skill.md +666 -0
- moai_adk/templates/.claude/agents/moai/expert-backend.md +899 -0
- moai_adk/templates/.claude/agents/moai/expert-database.md +777 -0
- moai_adk/templates/.claude/agents/moai/expert-debug.md +401 -0
- moai_adk/templates/.claude/agents/moai/expert-devops.md +720 -0
- moai_adk/templates/.claude/agents/moai/expert-frontend.md +734 -0
- moai_adk/templates/.claude/agents/moai/expert-performance.md +657 -0
- moai_adk/templates/.claude/agents/moai/expert-security.md +509 -0
- moai_adk/templates/.claude/agents/moai/expert-testing.md +733 -0
- moai_adk/templates/.claude/agents/moai/expert-uiux.md +1041 -0
- moai_adk/templates/.claude/agents/moai/manager-claude-code.md +432 -0
- moai_adk/templates/.claude/agents/moai/manager-docs.md +573 -0
- moai_adk/templates/.claude/agents/moai/manager-git.md +1020 -0
- moai_adk/templates/.claude/agents/moai/manager-project.md +891 -0
- moai_adk/templates/.claude/agents/moai/manager-quality.md +624 -0
- moai_adk/templates/.claude/agents/moai/manager-spec.md +809 -0
- moai_adk/templates/.claude/agents/moai/manager-strategy.md +780 -0
- moai_adk/templates/.claude/agents/moai/manager-tdd.md +784 -0
- moai_adk/templates/.claude/agents/moai/mcp-context7.md +458 -0
- moai_adk/templates/.claude/agents/moai/mcp-figma.md +1607 -0
- moai_adk/templates/.claude/agents/moai/mcp-notion.md +789 -0
- moai_adk/templates/.claude/agents/moai/mcp-playwright.md +469 -0
- moai_adk/templates/.claude/agents/moai/mcp-sequential-thinking.md +1032 -0
- moai_adk/templates/.claude/commands/moai/0-project.md +1384 -0
- moai_adk/templates/.claude/commands/moai/1-plan.md +1427 -0
- moai_adk/templates/.claude/commands/moai/2-run.md +943 -0
- moai_adk/templates/.claude/commands/moai/3-sync.md +1324 -0
- moai_adk/templates/.claude/commands/moai/9-feedback.md +314 -0
- moai_adk/templates/.claude/hooks/__init__.py +8 -0
- moai_adk/templates/.claude/hooks/moai/__init__.py +8 -0
- moai_adk/templates/.claude/hooks/moai/lib/__init__.py +85 -0
- moai_adk/templates/.claude/hooks/{alfred/core → moai/lib}/checkpoint.py +10 -37
- moai_adk/templates/.claude/hooks/moai/lib/common.py +131 -0
- moai_adk/templates/.claude/hooks/moai/lib/config_manager.py +446 -0
- moai_adk/templates/.claude/hooks/moai/lib/config_validator.py +639 -0
- moai_adk/templates/.claude/hooks/moai/lib/example_config.json +104 -0
- moai_adk/templates/.claude/hooks/moai/lib/git_operations_manager.py +590 -0
- moai_adk/templates/.claude/hooks/moai/lib/language_validator.py +317 -0
- moai_adk/templates/.claude/hooks/moai/lib/models.py +102 -0
- moai_adk/templates/.claude/hooks/moai/lib/path_utils.py +28 -0
- moai_adk/templates/.claude/hooks/moai/lib/project.py +768 -0
- moai_adk/templates/.claude/hooks/moai/lib/test_hooks_improvements.py +443 -0
- moai_adk/templates/.claude/hooks/moai/lib/timeout.py +160 -0
- moai_adk/templates/.claude/hooks/moai/lib/unified_timeout_manager.py +530 -0
- moai_adk/templates/.claude/hooks/moai/session_end__auto_cleanup.py +862 -0
- moai_adk/templates/.claude/hooks/moai/session_start__show_project_info.py +1075 -0
- moai_adk/templates/.claude/output-styles/moai/r2d2.md +560 -0
- moai_adk/templates/.claude/output-styles/moai/yoda.md +359 -0
- moai_adk/templates/.claude/settings.json +78 -50
- moai_adk/templates/.claude/skills/moai-ai-nano-banana/SKILL.md +438 -0
- moai_adk/templates/.claude/skills/moai-ai-nano-banana/examples.md +431 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/SKILL.md +249 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/examples.md +406 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/modules/README.md +44 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/modules/api-documentation.md +130 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/modules/code-documentation.md +152 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/modules/multi-format-output.md +178 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/modules/user-guides.md +147 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/reference.md +328 -0
- moai_adk/templates/.claude/skills/moai-domain-backend/SKILL.md +313 -283
- moai_adk/templates/.claude/skills/moai-domain-backend/examples.md +610 -1525
- moai_adk/templates/.claude/skills/moai-domain-backend/reference.md +423 -619
- moai_adk/templates/.claude/skills/moai-domain-database/SKILL.md +295 -95
- moai_adk/templates/.claude/skills/moai-domain-database/examples.md +817 -16
- moai_adk/templates/.claude/skills/moai-domain-database/modules/README.md +53 -0
- moai_adk/templates/.claude/skills/moai-domain-database/modules/mongodb.md +231 -0
- moai_adk/templates/.claude/skills/moai-domain-database/modules/postgresql.md +169 -0
- moai_adk/templates/.claude/skills/moai-domain-database/modules/redis.md +262 -0
- moai_adk/templates/.claude/skills/moai-domain-database/reference.md +532 -17
- moai_adk/templates/.claude/skills/moai-domain-frontend/SKILL.md +470 -97
- moai_adk/templates/.claude/skills/moai-domain-frontend/examples.md +955 -16
- moai_adk/templates/.claude/skills/moai-domain-frontend/reference.md +651 -18
- moai_adk/templates/.claude/skills/moai-domain-uiux/SKILL.md +455 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/examples.md +560 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/modules/accessibility-wcag.md +260 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/modules/component-architecture.md +228 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/modules/design-system-tokens.md +405 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/modules/icon-libraries.md +401 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/modules/theming-system.md +373 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/reference.md +243 -0
- moai_adk/templates/.claude/skills/moai-formats-data/SKILL.md +492 -0
- moai_adk/templates/.claude/skills/moai-formats-data/examples.md +804 -0
- moai_adk/templates/.claude/skills/moai-formats-data/modules/README.md +98 -0
- moai_adk/templates/.claude/skills/moai-formats-data/modules/SKILL-MODULARIZATION-TEMPLATE.md +278 -0
- moai_adk/templates/.claude/skills/moai-formats-data/modules/caching-performance.md +459 -0
- moai_adk/templates/.claude/skills/moai-formats-data/modules/data-validation.md +485 -0
- moai_adk/templates/.claude/skills/moai-formats-data/modules/json-optimization.md +374 -0
- moai_adk/templates/.claude/skills/moai-formats-data/modules/toon-encoding.md +308 -0
- moai_adk/templates/.claude/skills/moai-formats-data/reference.md +585 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/SKILL.md +202 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/examples.md +732 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/best-practices-checklist.md +616 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-custom-slash-commands-official.md +729 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-hooks-official.md +560 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-iam-official.md +635 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-memory-official.md +543 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-settings-official.md +663 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-skills-official.md +113 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-sub-agents-official.md +238 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/complete-configuration-guide.md +175 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/skill-examples.md +1674 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/skill-formatting-guide.md +729 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-examples.md +1513 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-formatting-guide.md +1086 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-integration-patterns.md +1100 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference.md +209 -0
- moai_adk/templates/.claude/skills/moai-foundation-context/SKILL.md +441 -0
- moai_adk/templates/.claude/skills/moai-foundation-context/examples.md +1048 -0
- moai_adk/templates/.claude/skills/moai-foundation-context/reference.md +246 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/SKILL.md +420 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/examples.md +358 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/README.md +296 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/agents-reference.md +359 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/commands-reference.md +432 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/delegation-patterns.md +757 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/execution-rules.md +687 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/modular-system.md +665 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/progressive-disclosure.md +649 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/spec-first-tdd.md +864 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/token-optimization.md +708 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/trust-5-framework.md +981 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/reference.md +478 -0
- moai_adk/templates/.claude/skills/moai-foundation-philosopher/SKILL.md +315 -0
- moai_adk/templates/.claude/skills/moai-foundation-philosopher/examples.md +228 -0
- moai_adk/templates/.claude/skills/moai-foundation-philosopher/modules/assumption-matrix.md +80 -0
- moai_adk/templates/.claude/skills/moai-foundation-philosopher/modules/cognitive-bias.md +199 -0
- moai_adk/templates/.claude/skills/moai-foundation-philosopher/modules/first-principles.md +140 -0
- moai_adk/templates/.claude/skills/moai-foundation-philosopher/modules/trade-off-analysis.md +154 -0
- moai_adk/templates/.claude/skills/moai-foundation-philosopher/reference.md +157 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/SKILL.md +364 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/examples.md +1232 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/modules/best-practices.md +261 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/modules/integration-patterns.md +194 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/modules/proactive-analysis.md +229 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/modules/trust5-validation.md +169 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/reference.md +1266 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/scripts/quality-gate.sh +668 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/templates/github-actions-quality.yml +481 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/templates/quality-config.yaml +519 -0
- moai_adk/templates/.claude/skills/moai-lang-cpp/SKILL.md +618 -93
- moai_adk/templates/.claude/skills/moai-lang-csharp/SKILL.md +446 -91
- moai_adk/templates/.claude/skills/moai-lang-elixir/SKILL.md +612 -0
- moai_adk/templates/.claude/skills/moai-lang-flutter/SKILL.md +477 -0
- moai_adk/templates/.claude/skills/moai-lang-flutter/examples.md +1090 -0
- moai_adk/templates/.claude/skills/moai-lang-flutter/reference.md +686 -0
- moai_adk/templates/.claude/skills/moai-lang-go/SKILL.md +346 -94
- moai_adk/templates/.claude/skills/moai-lang-go/examples.md +906 -16
- moai_adk/templates/.claude/skills/moai-lang-go/reference.md +721 -15
- moai_adk/templates/.claude/skills/moai-lang-java/SKILL.md +352 -91
- moai_adk/templates/.claude/skills/moai-lang-java/examples.md +851 -16
- moai_adk/templates/.claude/skills/moai-lang-java/reference.md +278 -18
- moai_adk/templates/.claude/skills/moai-lang-kotlin/SKILL.md +344 -86
- moai_adk/templates/.claude/skills/moai-lang-kotlin/examples.md +993 -16
- moai_adk/templates/.claude/skills/moai-lang-kotlin/reference.md +549 -18
- moai_adk/templates/.claude/skills/moai-lang-php/SKILL.md +617 -96
- moai_adk/templates/.claude/skills/moai-lang-python/SKILL.md +364 -314
- moai_adk/templates/.claude/skills/moai-lang-python/examples.md +849 -496
- moai_adk/templates/.claude/skills/moai-lang-python/reference.md +731 -243
- moai_adk/templates/.claude/skills/moai-lang-r/SKILL.md +545 -89
- moai_adk/templates/.claude/skills/moai-lang-ruby/SKILL.md +650 -87
- moai_adk/templates/.claude/skills/moai-lang-rust/SKILL.md +341 -93
- moai_adk/templates/.claude/skills/moai-lang-rust/examples.md +646 -16
- moai_adk/templates/.claude/skills/moai-lang-rust/reference.md +491 -18
- moai_adk/templates/.claude/skills/moai-lang-scala/SKILL.md +463 -89
- moai_adk/templates/.claude/skills/moai-lang-scala/examples.md +620 -16
- moai_adk/templates/.claude/skills/moai-lang-scala/reference.md +410 -17
- moai_adk/templates/.claude/skills/moai-lang-swift/SKILL.md +486 -112
- moai_adk/templates/.claude/skills/moai-lang-swift/examples.md +905 -16
- moai_adk/templates/.claude/skills/moai-lang-swift/reference.md +659 -17
- moai_adk/templates/.claude/skills/moai-lang-typescript/SKILL.md +333 -92
- moai_adk/templates/.claude/skills/moai-lang-typescript/examples.md +1076 -16
- moai_adk/templates/.claude/skills/moai-lang-typescript/reference.md +718 -21
- moai_adk/templates/.claude/skills/moai-library-mermaid/SKILL.md +300 -0
- moai_adk/templates/.claude/skills/moai-library-mermaid/advanced-patterns.md +465 -0
- moai_adk/templates/.claude/skills/moai-library-mermaid/examples.md +270 -0
- moai_adk/templates/.claude/skills/moai-library-mermaid/optimization.md +440 -0
- moai_adk/templates/.claude/skills/moai-library-mermaid/reference.md +228 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/SKILL.md +319 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/advanced-patterns.md +336 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/examples.md +592 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/advanced-deployment-patterns.md +182 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/advanced-patterns.md +17 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/configuration.md +57 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/content-architecture-optimization.md +162 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/deployment.md +52 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/framework-core-configuration.md +186 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/i18n-setup.md +55 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/mdx-components.md +52 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/optimization.md +303 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/reference.md +379 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/SKILL.md +372 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/examples.md +575 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/modules/advanced-patterns.md +394 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/modules/optimization.md +278 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/modules/shadcn-components.md +457 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/modules/shadcn-theming.md +373 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/reference.md +74 -0
- moai_adk/templates/.claude/skills/moai-mcp-figma/SKILL.md +402 -0
- moai_adk/templates/.claude/skills/moai-mcp-figma/advanced-patterns.md +607 -0
- moai_adk/templates/.claude/skills/moai-mcp-notion/SKILL.md +300 -0
- moai_adk/templates/.claude/skills/moai-mcp-notion/advanced-patterns.md +537 -0
- moai_adk/templates/.claude/skills/moai-platform-auth0/SKILL.md +290 -0
- moai_adk/templates/.claude/skills/moai-platform-clerk/SKILL.md +390 -0
- moai_adk/templates/.claude/skills/moai-platform-convex/SKILL.md +398 -0
- moai_adk/templates/.claude/skills/moai-platform-firebase-auth/SKILL.md +379 -0
- moai_adk/templates/.claude/skills/moai-platform-firestore/SKILL.md +358 -0
- moai_adk/templates/.claude/skills/moai-platform-neon/SKILL.md +467 -0
- moai_adk/templates/.claude/skills/moai-platform-railway/SKILL.md +377 -0
- moai_adk/templates/.claude/skills/moai-platform-supabase/SKILL.md +466 -0
- moai_adk/templates/.claude/skills/moai-platform-vercel/SKILL.md +482 -0
- moai_adk/templates/.claude/skills/moai-workflow-jit-docs/SKILL.md +449 -0
- moai_adk/templates/.claude/skills/moai-workflow-jit-docs/advanced-patterns.md +379 -0
- moai_adk/templates/.claude/skills/moai-workflow-jit-docs/examples.md +544 -0
- moai_adk/templates/.claude/skills/moai-workflow-jit-docs/optimization.md +286 -0
- moai_adk/templates/.claude/skills/moai-workflow-jit-docs/reference.md +307 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/README.md +190 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/SKILL.md +390 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/__init__.py +520 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/complete_workflow_demo_fixed.py +574 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples/complete_project_setup.py +317 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples/complete_workflow_demo.py +663 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples/config-migration-example.json +190 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples/question-examples.json +175 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples/quick_start.py +196 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples.md +547 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/__init__.py +17 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/advanced-patterns.md +158 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/ask_user_integration.py +340 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/batch_questions.py +713 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/config_manager.py +538 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/documentation_manager.py +1336 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/language_initializer.py +730 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/migration_manager.py +608 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/template_optimizer.py +1005 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/reference.md +275 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/schemas/config-schema.json +316 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/schemas/tab_schema.json +1462 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/config-template.json +71 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/product-template.md +44 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/structure-template.md +48 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/tech-template.md +92 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/config-manager-setup.json +109 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/language-initializer.json +228 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/menu-project-config.json +130 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/project-batch-questions.json +97 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/spec-workflow-setup.json +150 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/test_integration_simple.py +436 -0
- moai_adk/templates/.claude/skills/moai-workflow-spec/SKILL.md +534 -0
- moai_adk/templates/.claude/skills/moai-workflow-spec/examples.md +900 -0
- moai_adk/templates/.claude/skills/moai-workflow-spec/reference.md +704 -0
- moai_adk/templates/.claude/skills/moai-workflow-templates/SKILL.md +377 -0
- moai_adk/templates/.claude/skills/moai-workflow-templates/examples.md +552 -0
- moai_adk/templates/.claude/skills/moai-workflow-templates/modules/code-templates.md +124 -0
- moai_adk/templates/.claude/skills/moai-workflow-templates/modules/feedback-templates.md +100 -0
- moai_adk/templates/.claude/skills/moai-workflow-templates/modules/template-optimizer.md +138 -0
- moai_adk/templates/.claude/skills/moai-workflow-templates/reference.md +346 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/LICENSE.txt +202 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/SKILL.md +456 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/advanced-patterns.md +576 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/examples/ai-powered-testing.py +294 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/examples/console_logging.py +35 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/examples/element_discovery.py +40 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/examples/static_html_automation.py +34 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/examples.md +672 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/modules/README.md +220 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/modules/ai-debugging.md +845 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/modules/automated-code-review.md +1416 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/modules/performance-optimization.md +1234 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/modules/smart-refactoring.md +1243 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/modules/tdd-context7.md +1260 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/optimization.md +505 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/reference/playwright-best-practices.md +57 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/reference.md +440 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/scripts/with_server.py +218 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/templates/alfred-integration.md +376 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/workflows/enterprise-testing-workflow.py +571 -0
- moai_adk/templates/.claude/skills/moai-worktree/SKILL.md +411 -0
- moai_adk/templates/.claude/skills/moai-worktree/examples.md +606 -0
- moai_adk/templates/.claude/skills/moai-worktree/modules/integration-patterns.md +982 -0
- moai_adk/templates/.claude/skills/moai-worktree/modules/parallel-development.md +778 -0
- moai_adk/templates/.claude/skills/moai-worktree/modules/worktree-commands.md +646 -0
- moai_adk/templates/.claude/skills/moai-worktree/modules/worktree-management.md +782 -0
- moai_adk/templates/.claude/skills/moai-worktree/reference.md +357 -0
- moai_adk/templates/.git-hooks/pre-commit +128 -0
- moai_adk/templates/.git-hooks/pre-push +365 -0
- moai_adk/templates/.github/workflows/ci-universal.yml +513 -0
- moai_adk/templates/.github/workflows/security-secrets-check.yml +179 -0
- moai_adk/templates/.github/workflows/spec-issue-sync.yml +206 -36
- moai_adk/templates/.gitignore +194 -13
- moai_adk/templates/.mcp.json +31 -0
- moai_adk/templates/.moai/config/config.yaml +58 -0
- moai_adk/templates/.moai/config/questions/_schema.yaml +151 -0
- moai_adk/templates/.moai/config/questions/tab0-init.yaml +251 -0
- moai_adk/templates/.moai/config/questions/tab1-user.yaml +108 -0
- moai_adk/templates/.moai/config/questions/tab2-project.yaml +81 -0
- moai_adk/templates/.moai/config/questions/tab3-git.yaml +634 -0
- moai_adk/templates/.moai/config/questions/tab4-quality.yaml +170 -0
- moai_adk/templates/.moai/config/questions/tab5-system.yaml +87 -0
- moai_adk/templates/.moai/config/sections/git-strategy.yaml +116 -0
- moai_adk/templates/.moai/config/sections/language.yaml +11 -0
- moai_adk/templates/.moai/config/sections/project.yaml +13 -0
- moai_adk/templates/.moai/config/sections/quality.yaml +17 -0
- moai_adk/templates/.moai/config/sections/system.yaml +14 -0
- moai_adk/templates/.moai/config/sections/user.yaml +5 -0
- moai_adk/templates/.moai/config/statusline-config.yaml +92 -0
- moai_adk/templates/.moai/scripts/setup-glm.py +136 -0
- moai_adk/templates/CLAUDE.md +571 -244
- moai_adk/utils/__init__.py +24 -2
- moai_adk/utils/banner.py +9 -13
- moai_adk/utils/common.py +294 -0
- moai_adk/utils/link_validator.py +241 -0
- moai_adk/utils/logger.py +4 -9
- moai_adk/utils/safe_file_reader.py +206 -0
- moai_adk/utils/timeout.py +160 -0
- moai_adk/utils/toon_utils.py +256 -0
- moai_adk/version.py +22 -0
- moai_adk-0.34.0.dist-info/METADATA +2999 -0
- moai_adk-0.34.0.dist-info/RECORD +463 -0
- {moai_adk-0.8.0.dist-info → moai_adk-0.34.0.dist-info}/WHEEL +1 -1
- {moai_adk-0.8.0.dist-info → moai_adk-0.34.0.dist-info}/entry_points.txt +1 -0
- moai_adk/cli/commands/backup.py +0 -80
- moai_adk/templates/.claude/agents/alfred/cc-manager.md +0 -293
- moai_adk/templates/.claude/agents/alfred/debug-helper.md +0 -196
- moai_adk/templates/.claude/agents/alfred/doc-syncer.md +0 -207
- moai_adk/templates/.claude/agents/alfred/git-manager.md +0 -375
- moai_adk/templates/.claude/agents/alfred/implementation-planner.md +0 -343
- moai_adk/templates/.claude/agents/alfred/project-manager.md +0 -246
- moai_adk/templates/.claude/agents/alfred/quality-gate.md +0 -320
- moai_adk/templates/.claude/agents/alfred/skill-factory.md +0 -837
- moai_adk/templates/.claude/agents/alfred/spec-builder.md +0 -272
- moai_adk/templates/.claude/agents/alfred/tag-agent.md +0 -265
- moai_adk/templates/.claude/agents/alfred/tdd-implementer.md +0 -311
- moai_adk/templates/.claude/agents/alfred/trust-checker.md +0 -352
- moai_adk/templates/.claude/commands/alfred/0-project.md +0 -1184
- moai_adk/templates/.claude/commands/alfred/1-plan.md +0 -665
- moai_adk/templates/.claude/commands/alfred/2-run.md +0 -488
- moai_adk/templates/.claude/commands/alfred/3-sync.md +0 -623
- moai_adk/templates/.claude/hooks/alfred/HOOK_SCHEMA_VALIDATION.md +0 -313
- moai_adk/templates/.claude/hooks/alfred/README.md +0 -230
- moai_adk/templates/.claude/hooks/alfred/alfred_hooks.py +0 -174
- moai_adk/templates/.claude/hooks/alfred/core/__init__.py +0 -170
- moai_adk/templates/.claude/hooks/alfred/core/context.py +0 -67
- moai_adk/templates/.claude/hooks/alfred/core/project.py +0 -416
- moai_adk/templates/.claude/hooks/alfred/core/tags.py +0 -198
- moai_adk/templates/.claude/hooks/alfred/handlers/__init__.py +0 -21
- moai_adk/templates/.claude/hooks/alfred/handlers/notification.py +0 -25
- moai_adk/templates/.claude/hooks/alfred/handlers/session.py +0 -161
- moai_adk/templates/.claude/hooks/alfred/handlers/tool.py +0 -90
- moai_adk/templates/.claude/hooks/alfred/handlers/user.py +0 -42
- moai_adk/templates/.claude/hooks/alfred/test_hook_output.py +0 -175
- moai_adk/templates/.claude/output-styles/alfred/agentic-coding.md +0 -640
- moai_adk/templates/.claude/output-styles/alfred/moai-adk-learning.md +0 -696
- moai_adk/templates/.claude/output-styles/alfred/study-with-alfred.md +0 -474
- moai_adk/templates/.claude/skills/moai-alfred-ears-authoring/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-alfred-ears-authoring/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-alfred-ears-authoring/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-alfred-git-workflow/SKILL.md +0 -122
- moai_adk/templates/.claude/skills/moai-alfred-git-workflow/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-alfred-git-workflow/reference.md +0 -29
- moai_adk/templates/.claude/skills/moai-alfred-interactive-questions/SKILL.md +0 -237
- moai_adk/templates/.claude/skills/moai-alfred-interactive-questions/examples.md +0 -615
- moai_adk/templates/.claude/skills/moai-alfred-interactive-questions/reference.md +0 -653
- moai_adk/templates/.claude/skills/moai-alfred-language-detection/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-alfred-language-detection/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-alfred-language-detection/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-validation/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-validation/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-validation/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-alfred-tag-scanning/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-alfred-tag-scanning/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-alfred-tag-scanning/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-alfred-trust-validation/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-alfred-trust-validation/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-alfred-trust-validation/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-cc-agents/SKILL.md +0 -269
- moai_adk/templates/.claude/skills/moai-cc-agents/templates/agent-template.md +0 -32
- moai_adk/templates/.claude/skills/moai-cc-claude-md/SKILL.md +0 -298
- moai_adk/templates/.claude/skills/moai-cc-claude-md/templates/CLAUDE-template.md +0 -26
- moai_adk/templates/.claude/skills/moai-cc-commands/SKILL.md +0 -307
- moai_adk/templates/.claude/skills/moai-cc-commands/templates/command-template.md +0 -21
- moai_adk/templates/.claude/skills/moai-cc-hooks/SKILL.md +0 -252
- moai_adk/templates/.claude/skills/moai-cc-hooks/scripts/pre-bash-check.sh +0 -19
- moai_adk/templates/.claude/skills/moai-cc-hooks/scripts/preserve-permissions.sh +0 -19
- moai_adk/templates/.claude/skills/moai-cc-hooks/scripts/validate-bash-command.py +0 -24
- moai_adk/templates/.claude/skills/moai-cc-mcp-plugins/SKILL.md +0 -199
- moai_adk/templates/.claude/skills/moai-cc-mcp-plugins/templates/settings-mcp-template.json +0 -39
- moai_adk/templates/.claude/skills/moai-cc-memory/SKILL.md +0 -316
- moai_adk/templates/.claude/skills/moai-cc-memory/templates/session-summary-template.md +0 -18
- moai_adk/templates/.claude/skills/moai-cc-settings/SKILL.md +0 -263
- moai_adk/templates/.claude/skills/moai-cc-settings/templates/settings-complete-template.json +0 -30
- moai_adk/templates/.claude/skills/moai-cc-skills/SKILL.md +0 -291
- moai_adk/templates/.claude/skills/moai-cc-skills/templates/SKILL-template.md +0 -15
- moai_adk/templates/.claude/skills/moai-domain-cli-tool/SKILL.md +0 -123
- moai_adk/templates/.claude/skills/moai-domain-cli-tool/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-domain-cli-tool/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-domain-data-science/SKILL.md +0 -123
- moai_adk/templates/.claude/skills/moai-domain-data-science/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-domain-data-science/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-domain-devops/SKILL.md +0 -124
- moai_adk/templates/.claude/skills/moai-domain-devops/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-domain-devops/reference.md +0 -31
- moai_adk/templates/.claude/skills/moai-domain-ml/SKILL.md +0 -123
- moai_adk/templates/.claude/skills/moai-domain-ml/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-domain-ml/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-domain-mobile-app/SKILL.md +0 -123
- moai_adk/templates/.claude/skills/moai-domain-mobile-app/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-domain-mobile-app/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-domain-security/SKILL.md +0 -123
- moai_adk/templates/.claude/skills/moai-domain-security/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-domain-security/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-domain-web-api/SKILL.md +0 -123
- moai_adk/templates/.claude/skills/moai-domain-web-api/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-domain-web-api/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-essentials-debug/SKILL.md +0 -303
- moai_adk/templates/.claude/skills/moai-essentials-debug/examples.md +0 -1064
- moai_adk/templates/.claude/skills/moai-essentials-debug/reference.md +0 -1047
- moai_adk/templates/.claude/skills/moai-essentials-perf/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-essentials-perf/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-essentials-perf/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-essentials-refactor/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-essentials-refactor/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-essentials-refactor/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-essentials-review/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-essentials-review/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-essentials-review/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-foundation-ears/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-foundation-ears/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-foundation-ears/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-foundation-git/SKILL.md +0 -122
- moai_adk/templates/.claude/skills/moai-foundation-git/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-foundation-git/reference.md +0 -29
- moai_adk/templates/.claude/skills/moai-foundation-langs/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-foundation-langs/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-foundation-langs/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-foundation-specs/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-foundation-specs/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-foundation-specs/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-foundation-tags/SKILL.md +0 -113
- moai_adk/templates/.claude/skills/moai-foundation-tags/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-foundation-tags/reference.md +0 -28
- moai_adk/templates/.claude/skills/moai-foundation-trust/SKILL.md +0 -307
- moai_adk/templates/.claude/skills/moai-foundation-trust/examples.md +0 -0
- moai_adk/templates/.claude/skills/moai-foundation-trust/reference.md +0 -1099
- moai_adk/templates/.claude/skills/moai-lang-c/SKILL.md +0 -124
- moai_adk/templates/.claude/skills/moai-lang-c/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-c/reference.md +0 -31
- moai_adk/templates/.claude/skills/moai-lang-cpp/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-cpp/reference.md +0 -31
- moai_adk/templates/.claude/skills/moai-lang-csharp/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-csharp/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-lang-dart/SKILL.md +0 -123
- moai_adk/templates/.claude/skills/moai-lang-dart/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-dart/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-lang-javascript/SKILL.md +0 -125
- moai_adk/templates/.claude/skills/moai-lang-javascript/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-javascript/reference.md +0 -32
- moai_adk/templates/.claude/skills/moai-lang-php/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-php/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-lang-r/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-r/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-lang-ruby/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-ruby/reference.md +0 -31
- moai_adk/templates/.claude/skills/moai-lang-shell/SKILL.md +0 -123
- moai_adk/templates/.claude/skills/moai-lang-shell/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-shell/reference.md +0 -30
- moai_adk/templates/.claude/skills/moai-lang-sql/SKILL.md +0 -124
- moai_adk/templates/.claude/skills/moai-lang-sql/examples.md +0 -29
- moai_adk/templates/.claude/skills/moai-lang-sql/reference.md +0 -31
- moai_adk/templates/.claude/skills/moai-skill-factory/CHECKLIST.md +0 -482
- moai_adk/templates/.claude/skills/moai-skill-factory/EXAMPLES.md +0 -278
- moai_adk/templates/.claude/skills/moai-skill-factory/INTERACTIVE-DISCOVERY.md +0 -524
- moai_adk/templates/.claude/skills/moai-skill-factory/METADATA.md +0 -477
- moai_adk/templates/.claude/skills/moai-skill-factory/PARALLEL-ANALYSIS-REPORT.md +0 -429
- moai_adk/templates/.claude/skills/moai-skill-factory/PYTHON-VERSION-MATRIX.md +0 -391
- moai_adk/templates/.claude/skills/moai-skill-factory/SKILL-FACTORY-WORKFLOW.md +0 -431
- moai_adk/templates/.claude/skills/moai-skill-factory/SKILL-UPDATE-ADVISOR.md +0 -577
- moai_adk/templates/.claude/skills/moai-skill-factory/SKILL.md +0 -271
- moai_adk/templates/.claude/skills/moai-skill-factory/STEP-BY-STEP-GUIDE.md +0 -466
- moai_adk/templates/.claude/skills/moai-skill-factory/STRUCTURE.md +0 -583
- moai_adk/templates/.claude/skills/moai-skill-factory/WEB-RESEARCH.md +0 -526
- moai_adk/templates/.claude/skills/moai-skill-factory/reference.md +0 -465
- moai_adk/templates/.claude/skills/moai-skill-factory/scripts/generate-structure.sh +0 -328
- moai_adk/templates/.claude/skills/moai-skill-factory/scripts/validate-skill.sh +0 -312
- moai_adk/templates/.claude/skills/moai-skill-factory/templates/SKILL_TEMPLATE.md +0 -245
- moai_adk/templates/.claude/skills/moai-skill-factory/templates/examples-template.md +0 -285
- moai_adk/templates/.claude/skills/moai-skill-factory/templates/reference-template.md +0 -278
- moai_adk/templates/.claude/skills/moai-skill-factory/templates/scripts-template.sh +0 -303
- moai_adk/templates/.claude/skills/moai-spec-authoring/README.md +0 -137
- moai_adk/templates/.claude/skills/moai-spec-authoring/SKILL.md +0 -218
- moai_adk/templates/.claude/skills/moai-spec-authoring/examples/validate-spec.sh +0 -161
- moai_adk/templates/.claude/skills/moai-spec-authoring/examples.md +0 -541
- moai_adk/templates/.claude/skills/moai-spec-authoring/reference.md +0 -622
- moai_adk/templates/.github/ISSUE_TEMPLATE/spec.yml +0 -176
- moai_adk/templates/.github/PULL_REQUEST_TEMPLATE.md +0 -69
- moai_adk/templates/.github/workflows/moai-gitflow.yml +0 -256
- moai_adk/templates/.moai/config.json +0 -96
- moai_adk/templates/.moai/memory/CLAUDE-AGENTS-GUIDE.md +0 -208
- moai_adk/templates/.moai/memory/CLAUDE-PRACTICES.md +0 -369
- moai_adk/templates/.moai/memory/CLAUDE-RULES.md +0 -539
- moai_adk/templates/.moai/memory/CONFIG-SCHEMA.md +0 -444
- moai_adk/templates/.moai/memory/DEVELOPMENT-GUIDE.md +0 -344
- moai_adk/templates/.moai/memory/GITFLOW-PROTECTION-POLICY.md +0 -220
- moai_adk/templates/.moai/memory/SKILLS-DESCRIPTION-POLICY.md +0 -218
- moai_adk/templates/.moai/memory/SPEC-METADATA.md +0 -356
- moai_adk/templates/.moai/memory/config-schema.md +0 -444
- moai_adk/templates/.moai/memory/gitflow-protection-policy.md +0 -220
- moai_adk/templates/.moai/memory/spec-metadata.md +0 -356
- moai_adk/templates/.moai/project/product.md +0 -161
- moai_adk/templates/.moai/project/structure.md +0 -156
- moai_adk/templates/.moai/project/tech.md +0 -227
- moai_adk/templates/__init__.py +0 -2
- moai_adk-0.8.0.dist-info/METADATA +0 -1722
- moai_adk-0.8.0.dist-info/RECORD +0 -282
- {moai_adk-0.8.0.dist-info → moai_adk-0.34.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,1416 @@
|
|
|
1
|
+
# Automated Code Review with TRUST 5 Validation
|
|
2
|
+
|
|
3
|
+
> Module: AI-powered automated code review with TRUST 5 validation framework and comprehensive quality analysis
|
|
4
|
+
> Complexity: Advanced
|
|
5
|
+
> Time: 35+ minutes
|
|
6
|
+
> Dependencies: Python 3.8+, Context7 MCP, ast, pylint, flake8, bandit, mypy
|
|
7
|
+
|
|
8
|
+
## Core Implementation
|
|
9
|
+
|
|
10
|
+
### AutomatedCodeReviewer Class
|
|
11
|
+
|
|
12
|
+
```python
|
|
13
|
+
import ast
|
|
14
|
+
import subprocess
|
|
15
|
+
import json
|
|
16
|
+
import asyncio
|
|
17
|
+
from typing import Dict, List, Optional, Any, Union, Callable, Set
|
|
18
|
+
from dataclasses import dataclass, field
|
|
19
|
+
from enum import Enum
|
|
20
|
+
import re
|
|
21
|
+
import os
|
|
22
|
+
import sys
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
import tempfile
|
|
25
|
+
import difflib
|
|
26
|
+
|
|
27
|
+
class TrustCategory(Enum):
|
|
28
|
+
"""TRUST 5 framework categories."""
|
|
29
|
+
TRUTHFULNESS = "truthfulness" # Code correctness and logic accuracy
|
|
30
|
+
RELEVANCE = "relevance" # Code meets requirements and purpose
|
|
31
|
+
USABILITY = "usability" # Code is maintainable and understandable
|
|
32
|
+
SAFETY = "safety" # Code is secure and handles errors properly
|
|
33
|
+
TIMELINESS = "timeliness" # Code meets performance and delivery standards
|
|
34
|
+
|
|
35
|
+
class Severity(Enum):
|
|
36
|
+
"""Issue severity levels."""
|
|
37
|
+
CRITICAL = "critical"
|
|
38
|
+
HIGH = "high"
|
|
39
|
+
MEDIUM = "medium"
|
|
40
|
+
LOW = "low"
|
|
41
|
+
INFO = "info"
|
|
42
|
+
|
|
43
|
+
class IssueType(Enum):
|
|
44
|
+
"""Types of code issues."""
|
|
45
|
+
SYNTAX_ERROR = "syntax_error"
|
|
46
|
+
LOGIC_ERROR = "logic_error"
|
|
47
|
+
SECURITY_VULNERABILITY = "security_vulnerability"
|
|
48
|
+
PERFORMANCE_ISSUE = "performance_issue"
|
|
49
|
+
CODE_SMELL = "code_smell"
|
|
50
|
+
STYLE_VIOLATION = "style_violation"
|
|
51
|
+
DOCUMENTATION_ISSUE = "documentation_issue"
|
|
52
|
+
TESTING_ISSUE = "testing_issue"
|
|
53
|
+
TYPE_ERROR = "type_error"
|
|
54
|
+
IMPORT_ISSUE = "import_issue"
|
|
55
|
+
|
|
56
|
+
@dataclass
|
|
57
|
+
class CodeIssue:
|
|
58
|
+
"""Individual code issue found during review."""
|
|
59
|
+
id: str
|
|
60
|
+
category: TrustCategory
|
|
61
|
+
severity: Severity
|
|
62
|
+
issue_type: IssueType
|
|
63
|
+
title: str
|
|
64
|
+
description: str
|
|
65
|
+
file_path: str
|
|
66
|
+
line_number: int
|
|
67
|
+
column_number: int
|
|
68
|
+
code_snippet: str
|
|
69
|
+
suggested_fix: str
|
|
70
|
+
confidence: float # 0.0 to 1.0
|
|
71
|
+
rule_violated: Optional[str] = None
|
|
72
|
+
external_reference: Optional[str] = None
|
|
73
|
+
auto_fixable: bool = False
|
|
74
|
+
fix_diff: Optional[str] = None
|
|
75
|
+
|
|
76
|
+
@dataclass
|
|
77
|
+
class FileReviewResult:
|
|
78
|
+
"""Review results for a single file."""
|
|
79
|
+
file_path: str
|
|
80
|
+
issues: List[CodeIssue]
|
|
81
|
+
metrics: Dict[str, Any]
|
|
82
|
+
trust_score: float # 0.0 to 1.0
|
|
83
|
+
category_scores: Dict[TrustCategory, float]
|
|
84
|
+
lines_of_code: int
|
|
85
|
+
complexity_metrics: Dict[str, float]
|
|
86
|
+
review_timestamp: float
|
|
87
|
+
|
|
88
|
+
@dataclass
|
|
89
|
+
class CodeReviewReport:
|
|
90
|
+
"""Comprehensive code review report."""
|
|
91
|
+
project_path: str
|
|
92
|
+
files_reviewed: List[FileReviewResult]
|
|
93
|
+
overall_trust_score: float
|
|
94
|
+
overall_category_scores: Dict[TrustCategory, float]
|
|
95
|
+
summary_metrics: Dict[str, Any]
|
|
96
|
+
recommendations: List[str]
|
|
97
|
+
critical_issues: List[CodeIssue]
|
|
98
|
+
review_duration: float
|
|
99
|
+
context7_patterns_used: List[str]
|
|
100
|
+
|
|
101
|
+
class Context7CodeAnalyzer:
|
|
102
|
+
"""Integration with Context7 for code analysis patterns."""
|
|
103
|
+
|
|
104
|
+
def __init__(self, context7_client=None):
|
|
105
|
+
self.context7 = context7_client
|
|
106
|
+
self.analysis_patterns = {}
|
|
107
|
+
self.security_patterns = {}
|
|
108
|
+
self.performance_patterns = {}
|
|
109
|
+
|
|
110
|
+
async def load_analysis_patterns(self, language: str = "python") -> Dict[str, Any]:
|
|
111
|
+
"""Load code analysis patterns from Context7."""
|
|
112
|
+
|
|
113
|
+
if not self.context7:
|
|
114
|
+
return self._get_default_analysis_patterns()
|
|
115
|
+
|
|
116
|
+
try:
|
|
117
|
+
# Load security analysis patterns
|
|
118
|
+
security_patterns = await self.context7.get_library_docs(
|
|
119
|
+
context7_library_id="/security/semgrep",
|
|
120
|
+
topic="security vulnerability detection patterns 2025",
|
|
121
|
+
tokens=4000
|
|
122
|
+
)
|
|
123
|
+
self.security_patterns = security_patterns
|
|
124
|
+
|
|
125
|
+
# Load performance analysis patterns
|
|
126
|
+
performance_patterns = await self.context7.get_library_docs(
|
|
127
|
+
context7_library_id="/performance/python-profiling",
|
|
128
|
+
topic="performance anti-patterns code analysis 2025",
|
|
129
|
+
tokens=3000
|
|
130
|
+
)
|
|
131
|
+
self.performance_patterns = performance_patterns
|
|
132
|
+
|
|
133
|
+
# Load code quality patterns
|
|
134
|
+
quality_patterns = await self.context7.get_library_docs(
|
|
135
|
+
context7_library_id="/code-quality/sonarqube",
|
|
136
|
+
topic="code quality best practices smells detection 2025",
|
|
137
|
+
tokens=4000
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
# Load TRUST 5 validation patterns
|
|
141
|
+
trust_patterns = await self.context7.get_library_docs(
|
|
142
|
+
context7_library_id="/code-review/trust-framework",
|
|
143
|
+
topic="TRUST 5 code validation framework patterns 2025",
|
|
144
|
+
tokens=3000
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
'security': security_patterns,
|
|
149
|
+
'performance': performance_patterns,
|
|
150
|
+
'quality': quality_patterns,
|
|
151
|
+
'trust': trust_patterns
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
except Exception as e:
|
|
155
|
+
print(f"Failed to load Context7 patterns: {e}")
|
|
156
|
+
return self._get_default_analysis_patterns()
|
|
157
|
+
|
|
158
|
+
def _get_default_analysis_patterns(self) -> Dict[str, Any]:
|
|
159
|
+
"""Get default analysis patterns when Context7 is unavailable."""
|
|
160
|
+
return {
|
|
161
|
+
'security': {
|
|
162
|
+
'sql_injection': [
|
|
163
|
+
r"execute\([^)]*\+[^)]*\)",
|
|
164
|
+
r"format\s*\(",
|
|
165
|
+
r"%\s*[^,]*s"
|
|
166
|
+
],
|
|
167
|
+
'command_injection': [
|
|
168
|
+
r"os\.system\(",
|
|
169
|
+
r"subprocess\.call\(",
|
|
170
|
+
r"eval\("
|
|
171
|
+
],
|
|
172
|
+
'path_traversal': [
|
|
173
|
+
r"open\([^)]*\+[^)]*\)",
|
|
174
|
+
r"\.\.\/"
|
|
175
|
+
]
|
|
176
|
+
},
|
|
177
|
+
'performance': {
|
|
178
|
+
'inefficient_loops': [
|
|
179
|
+
r"for.*in.*range\(len\(",
|
|
180
|
+
r"while.*len\("
|
|
181
|
+
],
|
|
182
|
+
'memory_leaks': [
|
|
183
|
+
r"global\s+",
|
|
184
|
+
r"\.append\(.*\)\s*\.append\("
|
|
185
|
+
]
|
|
186
|
+
},
|
|
187
|
+
'quality': {
|
|
188
|
+
'long_functions': {'max_lines': 50},
|
|
189
|
+
'complex_conditionals': {'max_complexity': 10},
|
|
190
|
+
'deep_nesting': {'max_depth': 4}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
class StaticAnalysisTools:
|
|
195
|
+
"""Wrapper for various static analysis tools."""
|
|
196
|
+
|
|
197
|
+
def __init__(self):
|
|
198
|
+
self.tools = {
|
|
199
|
+
'pylint': self._run_pylint,
|
|
200
|
+
'flake8': self._run_flake8,
|
|
201
|
+
'bandit': self._run_bandit,
|
|
202
|
+
'mypy': self._run_mypy
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
async def run_all_analyses(self, file_path: str) -> Dict[str, Any]:
|
|
206
|
+
"""Run all available static analysis tools."""
|
|
207
|
+
|
|
208
|
+
results = {}
|
|
209
|
+
|
|
210
|
+
for tool_name, tool_func in self.tools.items():
|
|
211
|
+
try:
|
|
212
|
+
result = await tool_func(file_path)
|
|
213
|
+
results[tool_name] = result
|
|
214
|
+
except Exception as e:
|
|
215
|
+
print(f"Error running {tool_name}: {e}")
|
|
216
|
+
results[tool_name] = {'error': str(e)}
|
|
217
|
+
|
|
218
|
+
return results
|
|
219
|
+
|
|
220
|
+
async def _run_pylint(self, file_path: str) -> Dict[str, Any]:
|
|
221
|
+
"""Run pylint analysis."""
|
|
222
|
+
try:
|
|
223
|
+
result = subprocess.run(
|
|
224
|
+
['pylint', file_path, '--output-format=json'],
|
|
225
|
+
capture_output=True,
|
|
226
|
+
text=True
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
if result.returncode == 0:
|
|
230
|
+
return {'issues': []}
|
|
231
|
+
|
|
232
|
+
try:
|
|
233
|
+
issues = json.loads(result.stdout)
|
|
234
|
+
return {'issues': issues, 'summary': self._parse_pylint_summary(result.stderr)}
|
|
235
|
+
except json.JSONDecodeError:
|
|
236
|
+
return {'raw_output': result.stdout, 'raw_errors': result.stderr}
|
|
237
|
+
|
|
238
|
+
except FileNotFoundError:
|
|
239
|
+
return {'error': 'pylint not installed'}
|
|
240
|
+
|
|
241
|
+
async def _run_flake8(self, file_path: str) -> Dict[str, Any]:
|
|
242
|
+
"""Run flake8 analysis."""
|
|
243
|
+
try:
|
|
244
|
+
result = subprocess.run(
|
|
245
|
+
['flake8', file_path, '--format=json'],
|
|
246
|
+
capture_output=True,
|
|
247
|
+
text=True
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
if result.returncode == 0:
|
|
251
|
+
return {'issues': []}
|
|
252
|
+
|
|
253
|
+
# Parse flake8 output
|
|
254
|
+
issues = []
|
|
255
|
+
for line in result.stdout.split('\n'):
|
|
256
|
+
if line.strip():
|
|
257
|
+
parts = line.split(':')
|
|
258
|
+
if len(parts) >= 4:
|
|
259
|
+
issues.append({
|
|
260
|
+
'path': parts[0],
|
|
261
|
+
'line': int(parts[1]),
|
|
262
|
+
'column': int(parts[2]),
|
|
263
|
+
'code': parts[3].strip(),
|
|
264
|
+
'message': ':'.join(parts[4:]).strip()
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
return {'issues': issues}
|
|
268
|
+
|
|
269
|
+
except FileNotFoundError:
|
|
270
|
+
return {'error': 'flake8 not installed'}
|
|
271
|
+
|
|
272
|
+
async def _run_bandit(self, file_path: str) -> Dict[str, Any]:
|
|
273
|
+
"""Run bandit security analysis."""
|
|
274
|
+
try:
|
|
275
|
+
result = subprocess.run(
|
|
276
|
+
['bandit', '-f', 'json', file_path],
|
|
277
|
+
capture_output=True,
|
|
278
|
+
text=True
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
try:
|
|
282
|
+
bandit_results = json.loads(result.stdout)
|
|
283
|
+
return bandit_results
|
|
284
|
+
except json.JSONDecodeError:
|
|
285
|
+
return {'raw_output': result.stdout}
|
|
286
|
+
|
|
287
|
+
except FileNotFoundError:
|
|
288
|
+
return {'error': 'bandit not installed'}
|
|
289
|
+
|
|
290
|
+
async def _run_mypy(self, file_path: str) -> Dict[str, Any]:
|
|
291
|
+
"""Run mypy type analysis."""
|
|
292
|
+
try:
|
|
293
|
+
result = subprocess.run(
|
|
294
|
+
['mypy', file_path, '--show-error-codes'],
|
|
295
|
+
capture_output=True,
|
|
296
|
+
text=True
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
# Parse mypy output
|
|
300
|
+
issues = []
|
|
301
|
+
for line in result.stdout.split('\n'):
|
|
302
|
+
if ':' in line and 'error:' in line:
|
|
303
|
+
parts = line.split(':', 3)
|
|
304
|
+
if len(parts) >= 4:
|
|
305
|
+
issues.append({
|
|
306
|
+
'path': parts[0],
|
|
307
|
+
'line': int(parts[1]),
|
|
308
|
+
'message': parts[3].strip()
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
return {'issues': issues}
|
|
312
|
+
|
|
313
|
+
except FileNotFoundError:
|
|
314
|
+
return {'error': 'mypy not installed'}
|
|
315
|
+
|
|
316
|
+
def _parse_pylint_summary(self, stderr: str) -> Dict[str, Any]:
|
|
317
|
+
"""Parse pylint summary from stderr."""
|
|
318
|
+
summary = {}
|
|
319
|
+
for line in stderr.split('\n'):
|
|
320
|
+
if 'rated at' in line:
|
|
321
|
+
# Extract rating
|
|
322
|
+
match = re.search(r'rated at ([\d.]+)/10', line)
|
|
323
|
+
if match:
|
|
324
|
+
summary['rating'] = float(match.group(1))
|
|
325
|
+
|
|
326
|
+
elif any(keyword in line for keyword in ['statements', 'lines', 'functions', 'classes']):
|
|
327
|
+
parts = line.split()
|
|
328
|
+
if len(parts) >= 2:
|
|
329
|
+
summary[parts[0]] = parts[1]
|
|
330
|
+
|
|
331
|
+
return summary
|
|
332
|
+
|
|
333
|
+
class AutomatedCodeReviewer:
|
|
334
|
+
"""Main automated code reviewer with TRUST 5 validation."""
|
|
335
|
+
|
|
336
|
+
def __init__(self, context7_client=None):
|
|
337
|
+
self.context7 = context7_client
|
|
338
|
+
self.context7_analyzer = Context7CodeAnalyzer(context7_client)
|
|
339
|
+
self.static_analyzer = StaticAnalysisTools()
|
|
340
|
+
self.analysis_patterns = {}
|
|
341
|
+
self.review_history = []
|
|
342
|
+
|
|
343
|
+
async def review_codebase(
|
|
344
|
+
self, project_path: str,
|
|
345
|
+
include_patterns: List[str] = None,
|
|
346
|
+
exclude_patterns: List[str] = None
|
|
347
|
+
) -> CodeReviewReport:
|
|
348
|
+
"""Perform comprehensive code review of entire codebase."""
|
|
349
|
+
|
|
350
|
+
start_time = time.time()
|
|
351
|
+
|
|
352
|
+
# Load analysis patterns
|
|
353
|
+
self.analysis_patterns = await self.context7_analyzer.load_analysis_patterns()
|
|
354
|
+
|
|
355
|
+
# Find files to review
|
|
356
|
+
files_to_review = self._find_files_to_review(
|
|
357
|
+
project_path, include_patterns, exclude_patterns
|
|
358
|
+
)
|
|
359
|
+
|
|
360
|
+
print(f"Found {len(files_to_review)} files to review")
|
|
361
|
+
|
|
362
|
+
# Review each file
|
|
363
|
+
file_results = []
|
|
364
|
+
for file_path in files_to_review:
|
|
365
|
+
print(f"Reviewing {file_path}...")
|
|
366
|
+
file_result = await self.review_single_file(file_path)
|
|
367
|
+
file_results.append(file_result)
|
|
368
|
+
|
|
369
|
+
# Generate comprehensive report
|
|
370
|
+
end_time = time.time()
|
|
371
|
+
report = self._generate_comprehensive_report(
|
|
372
|
+
project_path, file_results, end_time - start_time
|
|
373
|
+
)
|
|
374
|
+
|
|
375
|
+
return report
|
|
376
|
+
|
|
377
|
+
async def review_single_file(self, file_path: str) -> FileReviewResult:
|
|
378
|
+
"""Review a single Python file."""
|
|
379
|
+
|
|
380
|
+
# Read file content
|
|
381
|
+
try:
|
|
382
|
+
with open(file_path, 'r', encoding='utf-8') as f:
|
|
383
|
+
content = f.read()
|
|
384
|
+
except Exception as e:
|
|
385
|
+
print(f"Error reading {file_path}: {e}")
|
|
386
|
+
return self._create_error_result(file_path, str(e))
|
|
387
|
+
|
|
388
|
+
# Parse AST
|
|
389
|
+
try:
|
|
390
|
+
tree = ast.parse(content)
|
|
391
|
+
except SyntaxError as e:
|
|
392
|
+
return self._create_syntax_error_result(file_path, content, e)
|
|
393
|
+
|
|
394
|
+
# Run static analyses
|
|
395
|
+
static_results = await self.static_analyzer.run_all_analyses(file_path)
|
|
396
|
+
|
|
397
|
+
# Perform Context7-enhanced analysis
|
|
398
|
+
context7_issues = await self._perform_context7_analysis(file_path, content, tree)
|
|
399
|
+
|
|
400
|
+
# Perform custom analysis
|
|
401
|
+
custom_issues = await self._perform_custom_analysis(file_path, content, tree)
|
|
402
|
+
|
|
403
|
+
# Combine all issues
|
|
404
|
+
all_issues = []
|
|
405
|
+
all_issues.extend(self._convert_static_issues(static_results, file_path))
|
|
406
|
+
all_issues.extend(context7_issues)
|
|
407
|
+
all_issues.extend(custom_issues)
|
|
408
|
+
|
|
409
|
+
# Calculate metrics and scores
|
|
410
|
+
metrics = self._calculate_file_metrics(content, tree)
|
|
411
|
+
trust_scores = self._calculate_trust_scores(all_issues, metrics)
|
|
412
|
+
|
|
413
|
+
return FileReviewResult(
|
|
414
|
+
file_path=file_path,
|
|
415
|
+
issues=all_issues,
|
|
416
|
+
metrics=metrics,
|
|
417
|
+
trust_score=trust_scores['overall'],
|
|
418
|
+
category_scores=trust_scores['categories'],
|
|
419
|
+
lines_of_code=len(content.split('\n')),
|
|
420
|
+
complexity_metrics=self._calculate_complexity_metrics(content, tree),
|
|
421
|
+
review_timestamp=time.time()
|
|
422
|
+
)
|
|
423
|
+
|
|
424
|
+
def _find_files_to_review(
|
|
425
|
+
self, project_path: str,
|
|
426
|
+
include_patterns: List[str] = None,
|
|
427
|
+
exclude_patterns: List[str] = None
|
|
428
|
+
) -> List[str]:
|
|
429
|
+
"""Find Python files to review."""
|
|
430
|
+
|
|
431
|
+
if include_patterns is None:
|
|
432
|
+
include_patterns = ['/*.py']
|
|
433
|
+
|
|
434
|
+
if exclude_patterns is None:
|
|
435
|
+
exclude_patterns = [
|
|
436
|
+
'/__pycache__/',
|
|
437
|
+
'/venv/',
|
|
438
|
+
'/env/',
|
|
439
|
+
'/node_modules/',
|
|
440
|
+
'/.git/',
|
|
441
|
+
'/migrations/',
|
|
442
|
+
'/tests/'
|
|
443
|
+
]
|
|
444
|
+
|
|
445
|
+
import fnmatch
|
|
446
|
+
from pathlib import Path
|
|
447
|
+
|
|
448
|
+
project_root = Path(project_path)
|
|
449
|
+
files = []
|
|
450
|
+
|
|
451
|
+
for pattern in include_patterns:
|
|
452
|
+
for file_path in project_root.glob(pattern):
|
|
453
|
+
if file_path.is_file():
|
|
454
|
+
# Check exclude patterns
|
|
455
|
+
excluded = False
|
|
456
|
+
for exclude_pattern in exclude_patterns:
|
|
457
|
+
if fnmatch.fnmatch(str(file_path.relative_to(project_root)), exclude_pattern):
|
|
458
|
+
excluded = True
|
|
459
|
+
break
|
|
460
|
+
|
|
461
|
+
if not excluded:
|
|
462
|
+
files.append(str(file_path))
|
|
463
|
+
|
|
464
|
+
return sorted(files)
|
|
465
|
+
|
|
466
|
+
async def _perform_context7_analysis(
|
|
467
|
+
self, file_path: str, content: str, tree: ast.AST
|
|
468
|
+
) -> List[CodeIssue]:
|
|
469
|
+
"""Perform Context7-enhanced code analysis."""
|
|
470
|
+
|
|
471
|
+
issues = []
|
|
472
|
+
|
|
473
|
+
# Security analysis
|
|
474
|
+
security_issues = await self._analyze_security_patterns(file_path, content)
|
|
475
|
+
issues.extend(security_issues)
|
|
476
|
+
|
|
477
|
+
# Performance analysis
|
|
478
|
+
performance_issues = await self._analyze_performance_patterns(file_path, content)
|
|
479
|
+
issues.extend(performance_issues)
|
|
480
|
+
|
|
481
|
+
# Code quality analysis
|
|
482
|
+
quality_issues = await self._analyze_quality_patterns(file_path, tree)
|
|
483
|
+
issues.extend(quality_issues)
|
|
484
|
+
|
|
485
|
+
# TRUST 5 analysis
|
|
486
|
+
trust_issues = await self._analyze_trust_patterns(file_path, content, tree)
|
|
487
|
+
issues.extend(trust_issues)
|
|
488
|
+
|
|
489
|
+
return issues
|
|
490
|
+
|
|
491
|
+
async def _analyze_security_patterns(self, file_path: str, content: str) -> List[CodeIssue]:
|
|
492
|
+
"""Analyze security patterns using Context7."""
|
|
493
|
+
|
|
494
|
+
issues = []
|
|
495
|
+
security_patterns = self.analysis_patterns.get('security', {})
|
|
496
|
+
lines = content.split('\n')
|
|
497
|
+
|
|
498
|
+
for category, patterns in security_patterns.items():
|
|
499
|
+
if isinstance(patterns, list):
|
|
500
|
+
for pattern in patterns:
|
|
501
|
+
try:
|
|
502
|
+
regex = re.compile(pattern, re.IGNORECASE)
|
|
503
|
+
for line_num, line in enumerate(lines, 1):
|
|
504
|
+
if regex.search(line):
|
|
505
|
+
issue = CodeIssue(
|
|
506
|
+
id=f"security_{category}_{line_num}_{len(issues)}",
|
|
507
|
+
category=TrustCategory.SAFETY,
|
|
508
|
+
severity=Severity.HIGH,
|
|
509
|
+
issue_type=IssueType.SECURITY_VULNERABILITY,
|
|
510
|
+
title=f"Security Issue: {category.replace('_', ' ').title()}",
|
|
511
|
+
description=f"Potential {category} vulnerability detected",
|
|
512
|
+
file_path=file_path,
|
|
513
|
+
line_number=line_num,
|
|
514
|
+
column_number=1,
|
|
515
|
+
code_snippet=line.strip(),
|
|
516
|
+
suggested_fix=self._get_security_fix_suggestion(category, line),
|
|
517
|
+
confidence=0.7,
|
|
518
|
+
rule_violated=f"SECURITY_{category.upper()}",
|
|
519
|
+
external_reference=self._get_security_reference(category)
|
|
520
|
+
)
|
|
521
|
+
issues.append(issue)
|
|
522
|
+
except re.error as e:
|
|
523
|
+
print(f"Invalid security pattern {pattern}: {e}")
|
|
524
|
+
|
|
525
|
+
return issues
|
|
526
|
+
|
|
527
|
+
async def _analyze_performance_patterns(self, file_path: str, content: str) -> List[CodeIssue]:
|
|
528
|
+
"""Analyze performance patterns using Context7."""
|
|
529
|
+
|
|
530
|
+
issues = []
|
|
531
|
+
performance_patterns = self.analysis_patterns.get('performance', {})
|
|
532
|
+
lines = content.split('\n')
|
|
533
|
+
|
|
534
|
+
for category, patterns in performance_patterns.items():
|
|
535
|
+
if isinstance(patterns, list):
|
|
536
|
+
for pattern in patterns:
|
|
537
|
+
try:
|
|
538
|
+
regex = re.compile(pattern)
|
|
539
|
+
for line_num, line in enumerate(lines, 1):
|
|
540
|
+
if regex.search(line):
|
|
541
|
+
issue = CodeIssue(
|
|
542
|
+
id=f"perf_{category}_{line_num}_{len(issues)}",
|
|
543
|
+
category=TrustCategory.TIMELINESS,
|
|
544
|
+
severity=Severity.MEDIUM,
|
|
545
|
+
issue_type=IssueType.PERFORMANCE_ISSUE,
|
|
546
|
+
title=f"Performance Issue: {category.replace('_', ' ').title()}",
|
|
547
|
+
description=f"Performance anti-pattern detected: {category}",
|
|
548
|
+
file_path=file_path,
|
|
549
|
+
line_number=line_num,
|
|
550
|
+
column_number=1,
|
|
551
|
+
code_snippet=line.strip(),
|
|
552
|
+
suggested_fix=self._get_performance_fix_suggestion(category, line),
|
|
553
|
+
confidence=0.6,
|
|
554
|
+
rule_violated=f"PERF_{category.upper()}"
|
|
555
|
+
)
|
|
556
|
+
issues.append(issue)
|
|
557
|
+
except re.error as e:
|
|
558
|
+
print(f"Invalid performance pattern {pattern}: {e}")
|
|
559
|
+
|
|
560
|
+
return issues
|
|
561
|
+
|
|
562
|
+
async def _analyze_quality_patterns(self, file_path: str, tree: ast.AST) -> List[CodeIssue]:
|
|
563
|
+
"""Analyze code quality patterns."""
|
|
564
|
+
|
|
565
|
+
issues = []
|
|
566
|
+
quality_patterns = self.analysis_patterns.get('quality', {})
|
|
567
|
+
|
|
568
|
+
# Analyze function length
|
|
569
|
+
if 'long_functions' in quality_patterns:
|
|
570
|
+
max_lines = quality_patterns['long_functions'].get('max_lines', 50)
|
|
571
|
+
function_issues = self._analyze_function_length(file_path, tree, max_lines)
|
|
572
|
+
issues.extend(function_issues)
|
|
573
|
+
|
|
574
|
+
# Analyze complexity
|
|
575
|
+
if 'complex_conditionals' in quality_patterns:
|
|
576
|
+
max_complexity = quality_patterns['complex_conditionals'].get('max_complexity', 10)
|
|
577
|
+
complexity_issues = self._analyze_complexity(file_path, tree, max_complexity)
|
|
578
|
+
issues.extend(complexity_issues)
|
|
579
|
+
|
|
580
|
+
# Analyze nesting depth
|
|
581
|
+
if 'deep_nesting' in quality_patterns:
|
|
582
|
+
max_depth = quality_patterns['deep_nesting'].get('max_depth', 4)
|
|
583
|
+
nesting_issues = self._analyze_nesting_depth(file_path, tree, max_depth)
|
|
584
|
+
issues.extend(nesting_issues)
|
|
585
|
+
|
|
586
|
+
return issues
|
|
587
|
+
|
|
588
|
+
async def _analyze_trust_patterns(
|
|
589
|
+
self, file_path: str, content: str, tree: ast.AST
|
|
590
|
+
) -> List[CodeIssue]:
|
|
591
|
+
"""Analyze TRUST 5 patterns."""
|
|
592
|
+
|
|
593
|
+
issues = []
|
|
594
|
+
|
|
595
|
+
# Truthfulness: Logic correctness
|
|
596
|
+
truthfulness_issues = self._analyze_truthfulness(file_path, tree)
|
|
597
|
+
issues.extend(truthfulness_issues)
|
|
598
|
+
|
|
599
|
+
# Relevance: Requirements fulfillment
|
|
600
|
+
relevance_issues = self._analyze_relevance(file_path, content)
|
|
601
|
+
issues.extend(relevance_issues)
|
|
602
|
+
|
|
603
|
+
# Usability: Maintainability
|
|
604
|
+
usability_issues = self._analyze_usability(file_path, content, tree)
|
|
605
|
+
issues.extend(usability_issues)
|
|
606
|
+
|
|
607
|
+
# Safety: Error handling
|
|
608
|
+
safety_issues = self._analyze_safety(file_path, tree)
|
|
609
|
+
issues.extend(safety_issues)
|
|
610
|
+
|
|
611
|
+
# Timeliness: Performance and standards
|
|
612
|
+
timeliness_issues = self._analyze_timeliness(file_path, content)
|
|
613
|
+
issues.extend(timeliness_issues)
|
|
614
|
+
|
|
615
|
+
return issues
|
|
616
|
+
|
|
617
|
+
def _analyze_function_length(
|
|
618
|
+
self, file_path: str, tree: ast.AST, max_lines: int
|
|
619
|
+
) -> List[CodeIssue]:
|
|
620
|
+
"""Analyze function length violations."""
|
|
621
|
+
|
|
622
|
+
issues = []
|
|
623
|
+
lines = None
|
|
624
|
+
|
|
625
|
+
for node in ast.walk(tree):
|
|
626
|
+
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
627
|
+
if lines is None:
|
|
628
|
+
with open(file_path, 'r') as f:
|
|
629
|
+
lines = f.readlines()
|
|
630
|
+
|
|
631
|
+
# Calculate function length (excluding docstring)
|
|
632
|
+
start_line = node.lineno - 1
|
|
633
|
+
end_line = node.end_lineno - 1 if node.end_lineno else start_line
|
|
634
|
+
func_lines = lines[start_line:end_line + 1]
|
|
635
|
+
|
|
636
|
+
# Remove docstring and blank lines
|
|
637
|
+
code_lines = []
|
|
638
|
+
in_docstring = False
|
|
639
|
+
for line in func_lines:
|
|
640
|
+
stripped = line.strip()
|
|
641
|
+
if not in_docstring and ('"""' in line or "'''" in line):
|
|
642
|
+
in_docstring = True
|
|
643
|
+
continue
|
|
644
|
+
if in_docstring and ('"""' in line or "'''" in line):
|
|
645
|
+
in_docstring = False
|
|
646
|
+
continue
|
|
647
|
+
if not in_docstring and stripped and not stripped.startswith('#'):
|
|
648
|
+
code_lines.append(line)
|
|
649
|
+
|
|
650
|
+
if len(code_lines) > max_lines:
|
|
651
|
+
issue = CodeIssue(
|
|
652
|
+
id=f"func_length_{node.lineno}",
|
|
653
|
+
category=TrustCategory.USABILITY,
|
|
654
|
+
severity=Severity.MEDIUM,
|
|
655
|
+
issue_type=IssueType.CODE_SMELL,
|
|
656
|
+
title="Long Function",
|
|
657
|
+
description=f"Function '{node.name}' is {len(code_lines)} lines long (max: {max_lines})",
|
|
658
|
+
file_path=file_path,
|
|
659
|
+
line_number=node.lineno,
|
|
660
|
+
column_number=1,
|
|
661
|
+
code_snippet=f"def {node.name}(...): # {len(code_lines)} lines",
|
|
662
|
+
suggested_fix=f"Consider breaking '{node.name}' into smaller functions",
|
|
663
|
+
confidence=0.8,
|
|
664
|
+
rule_violated="FUNC_LENGTH"
|
|
665
|
+
)
|
|
666
|
+
issues.append(issue)
|
|
667
|
+
|
|
668
|
+
return issues
|
|
669
|
+
|
|
670
|
+
def _analyze_complexity(
|
|
671
|
+
self, file_path: str, tree: ast.AST, max_complexity: int
|
|
672
|
+
) -> List[CodeIssue]:
|
|
673
|
+
"""Analyze cyclomatic complexity."""
|
|
674
|
+
|
|
675
|
+
issues = []
|
|
676
|
+
|
|
677
|
+
for node in ast.walk(tree):
|
|
678
|
+
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
679
|
+
complexity = self._calculate_cyclomatic_complexity(node)
|
|
680
|
+
|
|
681
|
+
if complexity > max_complexity:
|
|
682
|
+
issue = CodeIssue(
|
|
683
|
+
id=f"complexity_{node.lineno}",
|
|
684
|
+
category=TrustCategory.USABILITY,
|
|
685
|
+
severity=Severity.HIGH if complexity > max_complexity * 1.5 else Severity.MEDIUM,
|
|
686
|
+
issue_type=IssueType.CODE_SMELL,
|
|
687
|
+
title="High Complexity",
|
|
688
|
+
description=f"Function '{node.name}' has cyclomatic complexity {complexity} (max: {max_complexity})",
|
|
689
|
+
file_path=file_path,
|
|
690
|
+
line_number=node.lineno,
|
|
691
|
+
column_number=1,
|
|
692
|
+
code_snippet=f"def {node.name}(...): # complexity: {complexity}",
|
|
693
|
+
suggested_fix=f"Consider refactoring '{node.name}' to reduce complexity",
|
|
694
|
+
confidence=0.9,
|
|
695
|
+
rule_violated="COMPLEXITY"
|
|
696
|
+
)
|
|
697
|
+
issues.append(issue)
|
|
698
|
+
|
|
699
|
+
return issues
|
|
700
|
+
|
|
701
|
+
def _calculate_cyclomatic_complexity(self, node: ast.AST) -> int:
|
|
702
|
+
"""Calculate cyclomatic complexity for an AST node."""
|
|
703
|
+
|
|
704
|
+
complexity = 1 # Base complexity
|
|
705
|
+
|
|
706
|
+
for child in ast.walk(node):
|
|
707
|
+
if isinstance(child, (ast.If, ast.While, ast.For, ast.AsyncFor,
|
|
708
|
+
ast.ExceptHandler, ast.With, ast.AsyncWith)):
|
|
709
|
+
complexity += 1
|
|
710
|
+
elif isinstance(child, ast.BoolOp):
|
|
711
|
+
complexity += len(child.values) - 1
|
|
712
|
+
|
|
713
|
+
return complexity
|
|
714
|
+
|
|
715
|
+
def _analyze_nesting_depth(
|
|
716
|
+
self, file_path: str, tree: ast.AST, max_depth: int
|
|
717
|
+
) -> List[CodeIssue]:
|
|
718
|
+
"""Analyze nesting depth."""
|
|
719
|
+
|
|
720
|
+
issues = []
|
|
721
|
+
|
|
722
|
+
for node in ast.walk(tree):
|
|
723
|
+
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
724
|
+
max_func_depth = self._calculate_nesting_depth(node)
|
|
725
|
+
|
|
726
|
+
if max_func_depth > max_depth:
|
|
727
|
+
issue = CodeIssue(
|
|
728
|
+
id=f"nesting_{node.lineno}",
|
|
729
|
+
category=TrustCategory.USABILITY,
|
|
730
|
+
severity=Severity.MEDIUM,
|
|
731
|
+
issue_type=IssueType.CODE_SMELL,
|
|
732
|
+
title="Deep Nesting",
|
|
733
|
+
description=f"Function '{node.name}' has nesting depth {max_func_depth} (max: {max_depth})",
|
|
734
|
+
file_path=file_path,
|
|
735
|
+
line_number=node.lineno,
|
|
736
|
+
column_number=1,
|
|
737
|
+
code_snippet=f"def {node.name}(...): # nesting depth: {max_func_depth}",
|
|
738
|
+
suggested_fix=f"Consider using early returns or extracting functions in '{node.name}'",
|
|
739
|
+
confidence=0.8,
|
|
740
|
+
rule_violated="NESTING_DEPTH"
|
|
741
|
+
)
|
|
742
|
+
issues.append(issue)
|
|
743
|
+
|
|
744
|
+
return issues
|
|
745
|
+
|
|
746
|
+
def _calculate_nesting_depth(self, node: ast.AST, current_depth: int = 0) -> int:
|
|
747
|
+
"""Calculate maximum nesting depth for an AST node."""
|
|
748
|
+
|
|
749
|
+
max_depth = current_depth
|
|
750
|
+
|
|
751
|
+
for child in ast.walk(node):
|
|
752
|
+
if isinstance(child, (ast.If, ast.While, ast.For, ast.AsyncFor,
|
|
753
|
+
ast.With, ast.AsyncWith, ast.Try)):
|
|
754
|
+
if hasattr(child, 'lineno') and hasattr(node, 'lineno') and child.lineno > node.lineno:
|
|
755
|
+
child_depth = self._calculate_nesting_depth(child, current_depth + 1)
|
|
756
|
+
max_depth = max(max_depth, child_depth)
|
|
757
|
+
|
|
758
|
+
return max_depth
|
|
759
|
+
|
|
760
|
+
def _analyze_truthfulness(self, file_path: str, tree: ast.AST) -> List[CodeIssue]:
|
|
761
|
+
"""Analyze code for correctness and logic issues."""
|
|
762
|
+
|
|
763
|
+
issues = []
|
|
764
|
+
|
|
765
|
+
# Check for unreachable code
|
|
766
|
+
for node in ast.walk(tree):
|
|
767
|
+
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
768
|
+
unreachable_issues = self._check_unreachable_code(file_path, node)
|
|
769
|
+
issues.extend(unreachable_issues)
|
|
770
|
+
|
|
771
|
+
# Check for logic issues
|
|
772
|
+
logic_issues = self._check_logic_issues(file_path, tree)
|
|
773
|
+
issues.extend(logic_issues)
|
|
774
|
+
|
|
775
|
+
return issues
|
|
776
|
+
|
|
777
|
+
def _check_unreachable_code(self, file_path: str, func_node: ast.AST) -> List[CodeIssue]:
|
|
778
|
+
"""Check for unreachable code after return statements."""
|
|
779
|
+
|
|
780
|
+
issues = []
|
|
781
|
+
|
|
782
|
+
class UnreachableCodeVisitor(ast.NodeVisitor):
|
|
783
|
+
def __init__(self):
|
|
784
|
+
self.found_return = False
|
|
785
|
+
self.issues = []
|
|
786
|
+
|
|
787
|
+
def visit_Return(self, node):
|
|
788
|
+
self.found_return = True
|
|
789
|
+
self.generic_visit(node)
|
|
790
|
+
|
|
791
|
+
def generic_visit(self, node):
|
|
792
|
+
if self.found_return and hasattr(node, 'lineno'):
|
|
793
|
+
if isinstance(node, (ast.Expr, ast.Assign, ast.AugAssign)):
|
|
794
|
+
issue = CodeIssue(
|
|
795
|
+
id=f"unreachable_{node.lineno}",
|
|
796
|
+
category=TrustCategory.TRUTHFULNESS,
|
|
797
|
+
severity=Severity.LOW,
|
|
798
|
+
issue_type=IssueType.CODE_SMELL,
|
|
799
|
+
title="Unreachable Code",
|
|
800
|
+
description="Code after return statement is never executed",
|
|
801
|
+
file_path=file_path,
|
|
802
|
+
line_number=node.lineno,
|
|
803
|
+
column_number=1,
|
|
804
|
+
code_snippet=f"# Unreachable code at line {node.lineno}",
|
|
805
|
+
suggested_fix="Remove unreachable code or move before return statement",
|
|
806
|
+
confidence=0.7,
|
|
807
|
+
rule_violated="UNREACHABLE_CODE"
|
|
808
|
+
)
|
|
809
|
+
self.issues.append(issue)
|
|
810
|
+
|
|
811
|
+
super().generic_visit(node)
|
|
812
|
+
|
|
813
|
+
visitor = UnreachableCodeVisitor()
|
|
814
|
+
visitor.visit(func_node)
|
|
815
|
+
|
|
816
|
+
return visitor.issues
|
|
817
|
+
|
|
818
|
+
def _check_logic_issues(self, file_path: str, tree: ast.AST) -> List[CodeIssue]:
|
|
819
|
+
"""Check for common logic issues."""
|
|
820
|
+
|
|
821
|
+
issues = []
|
|
822
|
+
|
|
823
|
+
# Check for comparison issues
|
|
824
|
+
for node in ast.walk(tree):
|
|
825
|
+
if isinstance(node, ast.Compare):
|
|
826
|
+
comparison_issues = self._check_comparison_issues(file_path, node)
|
|
827
|
+
issues.extend(comparison_issues)
|
|
828
|
+
|
|
829
|
+
return issues
|
|
830
|
+
|
|
831
|
+
def _check_comparison_issues(self, file_path: str, compare_node: ast.Compare) -> List[CodeIssue]:
|
|
832
|
+
"""Check for comparison logic issues."""
|
|
833
|
+
|
|
834
|
+
issues = []
|
|
835
|
+
|
|
836
|
+
# Check for None comparison
|
|
837
|
+
for op in compare_node.ops:
|
|
838
|
+
if isinstance(op, ast.Eq) or isinstance(op, ast.NotEq):
|
|
839
|
+
for comparator in compare_node.comparators:
|
|
840
|
+
if isinstance(comparator, ast.Constant) and comparator.value is None:
|
|
841
|
+
issue = CodeIssue(
|
|
842
|
+
id=f"none_comparison_{compare_node.lineno}",
|
|
843
|
+
category=TrustCategory.TRUTHFULNESS,
|
|
844
|
+
severity=Severity.LOW,
|
|
845
|
+
issue_type=IssueType.CODE_SMELL,
|
|
846
|
+
title="None Comparison",
|
|
847
|
+
description="Use 'is' or 'is not' for None comparison",
|
|
848
|
+
file_path=file_path,
|
|
849
|
+
line_number=compare_node.lineno,
|
|
850
|
+
column_number=1,
|
|
851
|
+
code_snippet="# Use 'is None' instead of '== None'",
|
|
852
|
+
suggested_fix="Replace '== None' with 'is None' and '!= None' with 'is not None'",
|
|
853
|
+
confidence=0.8,
|
|
854
|
+
rule_violated="NONE_COMPARISON",
|
|
855
|
+
auto_fixable=True
|
|
856
|
+
)
|
|
857
|
+
issues.append(issue)
|
|
858
|
+
|
|
859
|
+
return issues
|
|
860
|
+
|
|
861
|
+
def _analyze_relevance(self, file_path: str, content: str) -> List[CodeIssue]:
|
|
862
|
+
"""Analyze code for relevance and requirements fulfillment."""
|
|
863
|
+
|
|
864
|
+
issues = []
|
|
865
|
+
|
|
866
|
+
# Check for TODO/FIXME comments
|
|
867
|
+
lines = content.split('\n')
|
|
868
|
+
for line_num, line in enumerate(lines, 1):
|
|
869
|
+
if 'TODO:' in line or 'FIXME:' in line:
|
|
870
|
+
issue = CodeIssue(
|
|
871
|
+
id=f"todo_{line_num}",
|
|
872
|
+
category=TrustCategory.RELEVANCE,
|
|
873
|
+
severity=Severity.LOW,
|
|
874
|
+
issue_type=IssueType.DOCUMENTATION_ISSUE,
|
|
875
|
+
title="Unresolved TODO",
|
|
876
|
+
description=f"TODO/FIXME comment found: {line.strip()}",
|
|
877
|
+
file_path=file_path,
|
|
878
|
+
line_number=line_num,
|
|
879
|
+
column_number=line.find('TODO') if 'TODO' in line else line.find('FIXME'),
|
|
880
|
+
code_snippet=line.strip(),
|
|
881
|
+
suggested_fix="Address the TODO/FIXME item or remove the comment",
|
|
882
|
+
confidence=0.6,
|
|
883
|
+
rule_violated="UNRESOLVED_TODO"
|
|
884
|
+
)
|
|
885
|
+
issues.append(issue)
|
|
886
|
+
|
|
887
|
+
return issues
|
|
888
|
+
|
|
889
|
+
def _analyze_usability(self, file_path: str, content: str, tree: ast.AST) -> List[CodeIssue]:
|
|
890
|
+
"""Analyze code for usability and maintainability."""
|
|
891
|
+
|
|
892
|
+
issues = []
|
|
893
|
+
|
|
894
|
+
# Check for docstring presence
|
|
895
|
+
for node in ast.walk(tree):
|
|
896
|
+
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
897
|
+
if not ast.get_docstring(node):
|
|
898
|
+
issue = CodeIssue(
|
|
899
|
+
id=f"no_docstring_{node.lineno}",
|
|
900
|
+
category=TrustCategory.USABILITY,
|
|
901
|
+
severity=Severity.LOW,
|
|
902
|
+
issue_type=IssueType.DOCUMENTATION_ISSUE,
|
|
903
|
+
title="Missing Docstring",
|
|
904
|
+
description=f"Function '{node.name}' is missing a docstring",
|
|
905
|
+
file_path=file_path,
|
|
906
|
+
line_number=node.lineno,
|
|
907
|
+
column_number=1,
|
|
908
|
+
code_snippet=f"def {node.name}(...):",
|
|
909
|
+
suggested_fix=f"Add a docstring to '{node.name}' explaining its purpose, parameters, and return value",
|
|
910
|
+
confidence=0.7,
|
|
911
|
+
rule_violated="MISSING_DOCSTRING"
|
|
912
|
+
)
|
|
913
|
+
issues.append(issue)
|
|
914
|
+
|
|
915
|
+
return issues
|
|
916
|
+
|
|
917
|
+
def _analyze_safety(self, file_path: str, tree: ast.AST) -> List[CodeIssue]:
|
|
918
|
+
"""Analyze code for safety and error handling."""
|
|
919
|
+
|
|
920
|
+
issues = []
|
|
921
|
+
|
|
922
|
+
# Check for bare except clauses
|
|
923
|
+
for node in ast.walk(tree):
|
|
924
|
+
if isinstance(node, ast.ExceptHandler):
|
|
925
|
+
if node.type is None:
|
|
926
|
+
issue = CodeIssue(
|
|
927
|
+
id=f"bare_except_{node.lineno}",
|
|
928
|
+
category=TrustCategory.SAFETY,
|
|
929
|
+
severity=Severity.MEDIUM,
|
|
930
|
+
issue_type=IssueType.CODE_SMELL,
|
|
931
|
+
title="Bare Except Clause",
|
|
932
|
+
description="Bare except clause can hide unexpected errors",
|
|
933
|
+
file_path=file_path,
|
|
934
|
+
line_number=node.lineno,
|
|
935
|
+
column_number=1,
|
|
936
|
+
code_snippet="except:",
|
|
937
|
+
suggested_fix="Specify exception types or use 'except Exception:' with logging",
|
|
938
|
+
confidence=0.8,
|
|
939
|
+
rule_violated="BARE_EXCEPT"
|
|
940
|
+
)
|
|
941
|
+
issues.append(issue)
|
|
942
|
+
|
|
943
|
+
return issues
|
|
944
|
+
|
|
945
|
+
def _analyze_timeliness(self, file_path: str, content: str) -> List[CodeIssue]:
|
|
946
|
+
"""Analyze code for timeliness and performance."""
|
|
947
|
+
|
|
948
|
+
issues = []
|
|
949
|
+
|
|
950
|
+
# Check for deprecated imports
|
|
951
|
+
deprecated_imports = {
|
|
952
|
+
'StringIO': 'io.StringIO',
|
|
953
|
+
'cStringIO': 'io.StringIO'
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
lines = content.split('\n')
|
|
957
|
+
for line_num, line in enumerate(lines, 1):
|
|
958
|
+
for old_import, new_import in deprecated_imports.items():
|
|
959
|
+
if f"import {old_import}" in line or f"from {old_import}" in line:
|
|
960
|
+
issue = CodeIssue(
|
|
961
|
+
id=f"deprecated_import_{line_num}",
|
|
962
|
+
category=TrustCategory.TIMELINESS,
|
|
963
|
+
severity=Severity.LOW,
|
|
964
|
+
issue_type=IssueType.IMPORT_ISSUE,
|
|
965
|
+
title="Deprecated Import",
|
|
966
|
+
description=f"Using deprecated import '{old_import}', should use '{new_import}'",
|
|
967
|
+
file_path=file_path,
|
|
968
|
+
line_number=line_num,
|
|
969
|
+
column_number=line.find(old_import),
|
|
970
|
+
code_snippet=line.strip(),
|
|
971
|
+
suggested_fix=f"Replace '{old_import}' with '{new_import}'",
|
|
972
|
+
confidence=0.9,
|
|
973
|
+
rule_violated="DEPRECATED_IMPORT",
|
|
974
|
+
auto_fixable=True
|
|
975
|
+
)
|
|
976
|
+
issues.append(issue)
|
|
977
|
+
|
|
978
|
+
return issues
|
|
979
|
+
|
|
980
|
+
def _convert_static_issues(
|
|
981
|
+
self, static_results: Dict[str, Any], file_path: str
|
|
982
|
+
) -> List[CodeIssue]:
|
|
983
|
+
"""Convert static analysis results to CodeIssue objects."""
|
|
984
|
+
|
|
985
|
+
issues = []
|
|
986
|
+
|
|
987
|
+
for tool_name, results in static_results.items():
|
|
988
|
+
if 'error' in results:
|
|
989
|
+
continue
|
|
990
|
+
|
|
991
|
+
tool_issues = results.get('issues', [])
|
|
992
|
+
for issue_data in tool_issues:
|
|
993
|
+
# Map tool to TRUST category
|
|
994
|
+
category = self._map_tool_to_trust_category(tool_name, issue_data)
|
|
995
|
+
|
|
996
|
+
issue = CodeIssue(
|
|
997
|
+
id=f"{tool_name}_{len(issues)}",
|
|
998
|
+
category=category,
|
|
999
|
+
severity=self._map_severity(issue_data.get('severity', 'medium')),
|
|
1000
|
+
issue_type=self._map_issue_type(tool_name, issue_data),
|
|
1001
|
+
title=f"{tool_name.title()}: {issue_data.get('message', 'Unknown issue')}",
|
|
1002
|
+
description=issue_data.get('message', 'Static analysis issue'),
|
|
1003
|
+
file_path=file_path,
|
|
1004
|
+
line_number=issue_data.get('line', 0),
|
|
1005
|
+
column_number=issue_data.get('column', 0),
|
|
1006
|
+
code_snippet=issue_data.get('code_snippet', ''),
|
|
1007
|
+
suggested_fix=self._get_suggested_fix(tool_name, issue_data),
|
|
1008
|
+
confidence=0.8,
|
|
1009
|
+
rule_violated=issue_data.get('code', ''),
|
|
1010
|
+
external_reference=f"{tool_name} documentation"
|
|
1011
|
+
)
|
|
1012
|
+
issues.append(issue)
|
|
1013
|
+
|
|
1014
|
+
return issues
|
|
1015
|
+
|
|
1016
|
+
def _map_tool_to_trust_category(self, tool_name: str, issue_data: Dict) -> TrustCategory:
|
|
1017
|
+
"""Map static analysis tool to TRUST category."""
|
|
1018
|
+
|
|
1019
|
+
if tool_name == 'bandit':
|
|
1020
|
+
return TrustCategory.SAFETY
|
|
1021
|
+
elif tool_name == 'mypy':
|
|
1022
|
+
return TrustCategory.TRUTHFULNESS
|
|
1023
|
+
elif tool_name == 'pylint':
|
|
1024
|
+
message = issue_data.get('message', '').lower()
|
|
1025
|
+
if any(keyword in message for keyword in ['security', 'injection', 'unsafe']):
|
|
1026
|
+
return TrustCategory.SAFETY
|
|
1027
|
+
elif any(keyword in message for keyword in ['performance', 'inefficient']):
|
|
1028
|
+
return TrustCategory.TIMELINESS
|
|
1029
|
+
else:
|
|
1030
|
+
return TrustCategory.USABILITY
|
|
1031
|
+
else:
|
|
1032
|
+
return TrustCategory.USABILITY
|
|
1033
|
+
|
|
1034
|
+
def _map_severity(self, severity: str) -> Severity:
|
|
1035
|
+
"""Map severity string to Severity enum."""
|
|
1036
|
+
|
|
1037
|
+
severity_map = {
|
|
1038
|
+
'critical': Severity.CRITICAL,
|
|
1039
|
+
'high': Severity.HIGH,
|
|
1040
|
+
'medium': Severity.MEDIUM,
|
|
1041
|
+
'low': Severity.LOW,
|
|
1042
|
+
'info': Severity.INFO
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
return severity_map.get(severity.lower(), Severity.MEDIUM)
|
|
1046
|
+
|
|
1047
|
+
def _map_issue_type(self, tool_name: str, issue_data: Dict) -> IssueType:
|
|
1048
|
+
"""Map tool issue to IssueType enum."""
|
|
1049
|
+
|
|
1050
|
+
if tool_name == 'bandit':
|
|
1051
|
+
return IssueType.SECURITY_VULNERABILITY
|
|
1052
|
+
elif tool_name == 'mypy':
|
|
1053
|
+
return IssueType.TYPE_ERROR
|
|
1054
|
+
else:
|
|
1055
|
+
message = issue_data.get('message', '').lower()
|
|
1056
|
+
if 'security' in message:
|
|
1057
|
+
return IssueType.SECURITY_VULNERABILITY
|
|
1058
|
+
elif 'performance' in message:
|
|
1059
|
+
return IssueType.PERFORMANCE_ISSUE
|
|
1060
|
+
elif 'syntax' in message:
|
|
1061
|
+
return IssueType.SYNTAX_ERROR
|
|
1062
|
+
else:
|
|
1063
|
+
return IssueType.CODE_SMELL
|
|
1064
|
+
|
|
1065
|
+
def _get_suggested_fix(self, tool_name: str, issue_data: Dict) -> str:
|
|
1066
|
+
"""Get suggested fix for tool issue."""
|
|
1067
|
+
|
|
1068
|
+
message = issue_data.get('message', '')
|
|
1069
|
+
|
|
1070
|
+
if 'unused' in message.lower():
|
|
1071
|
+
return "Remove unused variable or import"
|
|
1072
|
+
elif 'missing docstring' in message.lower():
|
|
1073
|
+
return "Add docstring explaining function purpose"
|
|
1074
|
+
elif 'too many arguments' in message.lower():
|
|
1075
|
+
return "Consider reducing function arguments or using data classes"
|
|
1076
|
+
elif else:
|
|
1077
|
+
return "Address the linting issue by following best practices"
|
|
1078
|
+
|
|
1079
|
+
def _get_security_fix_suggestion(self, category: str, line: str) -> str:
|
|
1080
|
+
"""Get security fix suggestion."""
|
|
1081
|
+
|
|
1082
|
+
suggestions = {
|
|
1083
|
+
'sql_injection': "Use parameterized queries or ORM to prevent SQL injection",
|
|
1084
|
+
'command_injection': "Use subprocess.run with proper argument lists or validate input",
|
|
1085
|
+
'path_traversal': "Validate and sanitize file paths, use absolute paths"
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
return suggestions.get(category, "Review and fix security vulnerability")
|
|
1089
|
+
|
|
1090
|
+
def _get_performance_fix_suggestion(self, category: str, line: str) -> str:
|
|
1091
|
+
"""Get performance fix suggestion."""
|
|
1092
|
+
|
|
1093
|
+
suggestions = {
|
|
1094
|
+
'inefficient_loops': "Use list comprehensions or generator expressions",
|
|
1095
|
+
'memory_leaks': "Review memory usage and ensure proper cleanup"
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
return suggestions.get(category, "Optimize code for better performance")
|
|
1099
|
+
|
|
1100
|
+
def _get_security_reference(self, category: str) -> str:
|
|
1101
|
+
"""Get external security reference."""
|
|
1102
|
+
|
|
1103
|
+
references = {
|
|
1104
|
+
'sql_injection': "OWASP SQL Injection Prevention Cheat Sheet",
|
|
1105
|
+
'command_injection': "OWASP Command Injection Prevention Cheat Sheet",
|
|
1106
|
+
'path_traversal': "OWASP Path Traversal Prevention Cheat Sheet"
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
return references.get(category, "OWASP Top 10 Security Risks")
|
|
1110
|
+
|
|
1111
|
+
def _calculate_file_metrics(self, content: str, tree: ast.AST) -> Dict[str, Any]:
|
|
1112
|
+
"""Calculate comprehensive file metrics."""
|
|
1113
|
+
|
|
1114
|
+
lines = content.split('\n')
|
|
1115
|
+
code_lines = [line for line in lines if line.strip() and not line.strip().startswith('#')]
|
|
1116
|
+
|
|
1117
|
+
functions = [node for node in ast.walk(tree) if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef))]
|
|
1118
|
+
classes = [node for node in ast.walk(tree) if isinstance(node, ast.ClassDef)]
|
|
1119
|
+
|
|
1120
|
+
return {
|
|
1121
|
+
'total_lines': len(lines),
|
|
1122
|
+
'code_lines': len(code_lines),
|
|
1123
|
+
'comment_lines': len(lines) - len(code_lines),
|
|
1124
|
+
'functions': len(functions),
|
|
1125
|
+
'classes': len(classes),
|
|
1126
|
+
'imports': len([node for node in ast.walk(tree) if isinstance(node, (ast.Import, ast.ImportFrom))])
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
def _calculate_trust_scores(
|
|
1130
|
+
self, issues: List[CodeIssue], metrics: Dict[str, Any]
|
|
1131
|
+
) -> Dict[str, Any]:
|
|
1132
|
+
"""Calculate TRUST 5 scores."""
|
|
1133
|
+
|
|
1134
|
+
category_scores = {}
|
|
1135
|
+
category_weights = {
|
|
1136
|
+
TrustCategory.TRUTHFULNESS: 0.25,
|
|
1137
|
+
TrustCategory.RELEVANCE: 0.20,
|
|
1138
|
+
TrustCategory.USABILITY: 0.25,
|
|
1139
|
+
TrustCategory.SAFETY: 0.20,
|
|
1140
|
+
TrustCategory.TIMELINESS: 0.10
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
# Group issues by category
|
|
1144
|
+
issues_by_category = {category: [] for category in TrustCategory}
|
|
1145
|
+
for issue in issues:
|
|
1146
|
+
issues_by_category[issue.category].append(issue)
|
|
1147
|
+
|
|
1148
|
+
# Calculate scores for each category
|
|
1149
|
+
for category in TrustCategory:
|
|
1150
|
+
category_issues = issues_by_category[category]
|
|
1151
|
+
|
|
1152
|
+
# Calculate penalty based on severity and number of issues
|
|
1153
|
+
penalty = 0.0
|
|
1154
|
+
for issue in category_issues:
|
|
1155
|
+
severity_penalty = {
|
|
1156
|
+
Severity.CRITICAL: 0.5,
|
|
1157
|
+
Severity.HIGH: 0.3,
|
|
1158
|
+
Severity.MEDIUM: 0.1,
|
|
1159
|
+
Severity.LOW: 0.05,
|
|
1160
|
+
Severity.INFO: 0.01
|
|
1161
|
+
}
|
|
1162
|
+
penalty += severity_penalty.get(issue.severity, 0.1) * issue.confidence
|
|
1163
|
+
|
|
1164
|
+
# Apply penalties (max penalty of 1.0)
|
|
1165
|
+
score = max(0.0, 1.0 - min(penalty, 1.0))
|
|
1166
|
+
category_scores[category] = score
|
|
1167
|
+
|
|
1168
|
+
# Calculate overall score
|
|
1169
|
+
overall_score = sum(
|
|
1170
|
+
category_scores[cat] * category_weights[cat]
|
|
1171
|
+
for cat in TrustCategory
|
|
1172
|
+
)
|
|
1173
|
+
|
|
1174
|
+
return {
|
|
1175
|
+
'overall': overall_score,
|
|
1176
|
+
'categories': category_scores
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
def _calculate_complexity_metrics(self, content: str, tree: ast.AST) -> Dict[str, float]:
|
|
1180
|
+
"""Calculate complexity metrics."""
|
|
1181
|
+
|
|
1182
|
+
total_complexity = 0
|
|
1183
|
+
max_function_complexity = 0
|
|
1184
|
+
function_count = 0
|
|
1185
|
+
|
|
1186
|
+
for node in ast.walk(tree):
|
|
1187
|
+
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
1188
|
+
complexity = self._calculate_cyclomatic_complexity(node)
|
|
1189
|
+
total_complexity += complexity
|
|
1190
|
+
max_function_complexity = max(max_function_complexity, complexity)
|
|
1191
|
+
function_count += 1
|
|
1192
|
+
|
|
1193
|
+
avg_complexity = total_complexity / max(function_count, 1)
|
|
1194
|
+
|
|
1195
|
+
return {
|
|
1196
|
+
'total_complexity': total_complexity,
|
|
1197
|
+
'max_function_complexity': max_function_complexity,
|
|
1198
|
+
'average_complexity': avg_complexity,
|
|
1199
|
+
'function_count': function_count
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
def _generate_comprehensive_report(
|
|
1203
|
+
self, project_path: str, file_results: List[FileReviewResult], duration: float
|
|
1204
|
+
) -> CodeReviewReport:
|
|
1205
|
+
"""Generate comprehensive code review report."""
|
|
1206
|
+
|
|
1207
|
+
# Collect all issues
|
|
1208
|
+
all_issues = []
|
|
1209
|
+
for result in file_results:
|
|
1210
|
+
all_issues.extend(result.issues)
|
|
1211
|
+
|
|
1212
|
+
# Calculate overall scores
|
|
1213
|
+
overall_category_scores = {}
|
|
1214
|
+
for category in TrustCategory:
|
|
1215
|
+
scores = [result.category_scores.get(category, 0.0) for result in file_results]
|
|
1216
|
+
overall_category_scores[category] = sum(scores) / len(scores) if scores else 0.0
|
|
1217
|
+
|
|
1218
|
+
overall_trust_score = sum(overall_category_scores.values()) / len(overall_category_scores)
|
|
1219
|
+
|
|
1220
|
+
# Get critical issues
|
|
1221
|
+
critical_issues = [issue for issue in all_issues if issue.severity == Severity.CRITICAL]
|
|
1222
|
+
|
|
1223
|
+
# Generate recommendations
|
|
1224
|
+
recommendations = self._generate_recommendations(overall_category_scores, all_issues)
|
|
1225
|
+
|
|
1226
|
+
# Calculate summary metrics
|
|
1227
|
+
summary_metrics = {
|
|
1228
|
+
'files_reviewed': len(file_results),
|
|
1229
|
+
'total_issues': len(all_issues),
|
|
1230
|
+
'critical_issues': len(critical_issues),
|
|
1231
|
+
'issues_by_severity': {
|
|
1232
|
+
severity.value: len([i for i in all_issues if i.severity == severity])
|
|
1233
|
+
for severity in Severity
|
|
1234
|
+
},
|
|
1235
|
+
'issues_by_category': {
|
|
1236
|
+
category.value: len([i for i in all_issues if i.category == category])
|
|
1237
|
+
for category in TrustCategory
|
|
1238
|
+
},
|
|
1239
|
+
'total_lines_of_code': sum(result.lines_of_code for result in file_results),
|
|
1240
|
+
'average_trust_score': overall_trust_score,
|
|
1241
|
+
'context7_patterns_used': list(self.analysis_patterns.keys())
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
return CodeReviewReport(
|
|
1245
|
+
project_path=project_path,
|
|
1246
|
+
files_reviewed=file_results,
|
|
1247
|
+
overall_trust_score=overall_trust_score,
|
|
1248
|
+
overall_category_scores=overall_category_scores,
|
|
1249
|
+
summary_metrics=summary_metrics,
|
|
1250
|
+
recommendations=recommendations,
|
|
1251
|
+
critical_issues=critical_issues,
|
|
1252
|
+
review_duration=duration,
|
|
1253
|
+
context7_patterns_used=list(self.analysis_patterns.keys())
|
|
1254
|
+
)
|
|
1255
|
+
|
|
1256
|
+
def _generate_recommendations(
|
|
1257
|
+
self, category_scores: Dict[TrustCategory, float], issues: List[CodeIssue]
|
|
1258
|
+
) -> List[str]:
|
|
1259
|
+
"""Generate actionable recommendations."""
|
|
1260
|
+
|
|
1261
|
+
recommendations = []
|
|
1262
|
+
|
|
1263
|
+
# Category-specific recommendations
|
|
1264
|
+
for category, score in category_scores.items():
|
|
1265
|
+
if score < 0.7:
|
|
1266
|
+
if category == TrustCategory.SAFETY:
|
|
1267
|
+
recommendations.append("Address security vulnerabilities immediately - critical safety issues detected")
|
|
1268
|
+
elif category == TrustCategory.TRUTHFULNESS:
|
|
1269
|
+
recommendations.append("Review code logic and fix correctness issues")
|
|
1270
|
+
elif category == TrustCategory.USABILITY:
|
|
1271
|
+
recommendations.append("Improve code maintainability by refactoring complex functions")
|
|
1272
|
+
elif category == TrustCategory.RELEVANCE:
|
|
1273
|
+
recommendations.append("Remove TODO items and improve documentation")
|
|
1274
|
+
elif category == TrustCategory.TIMELINESS:
|
|
1275
|
+
recommendations.append("Optimize performance issues and update deprecated code")
|
|
1276
|
+
|
|
1277
|
+
# General recommendations
|
|
1278
|
+
high_severity_count = len([i for i in issues if i.severity in [Severity.CRITICAL, Severity.HIGH]])
|
|
1279
|
+
if high_severity_count > 0:
|
|
1280
|
+
recommendations.append(f"Address {high_severity_count} high-priority issues before release")
|
|
1281
|
+
|
|
1282
|
+
auto_fixable_count = len([i for i in issues if i.auto_fixable])
|
|
1283
|
+
if auto_fixable_count > 0:
|
|
1284
|
+
recommendations.append(f"Use automated fixes for {auto_fixable_count} auto-fixable issues")
|
|
1285
|
+
|
|
1286
|
+
return recommendations
|
|
1287
|
+
|
|
1288
|
+
def _create_error_result(self, file_path: str, error_message: str) -> FileReviewResult:
|
|
1289
|
+
"""Create error result for file that couldn't be processed."""
|
|
1290
|
+
|
|
1291
|
+
return FileReviewResult(
|
|
1292
|
+
file_path=file_path,
|
|
1293
|
+
issues=[],
|
|
1294
|
+
metrics={'error': error_message},
|
|
1295
|
+
trust_score=0.0,
|
|
1296
|
+
category_scores={cat: 0.0 for cat in TrustCategory},
|
|
1297
|
+
lines_of_code=0,
|
|
1298
|
+
complexity_metrics={},
|
|
1299
|
+
review_timestamp=time.time()
|
|
1300
|
+
)
|
|
1301
|
+
|
|
1302
|
+
def _create_syntax_error_result(
|
|
1303
|
+
self, file_path: str, content: str, syntax_error: SyntaxError
|
|
1304
|
+
) -> FileReviewResult:
|
|
1305
|
+
"""Create result for file with syntax errors."""
|
|
1306
|
+
|
|
1307
|
+
issue = CodeIssue(
|
|
1308
|
+
id=f"syntax_error_{syntax_error.lineno}",
|
|
1309
|
+
category=TrustCategory.TRUTHFULNESS,
|
|
1310
|
+
severity=Severity.CRITICAL,
|
|
1311
|
+
issue_type=IssueType.SYNTAX_ERROR,
|
|
1312
|
+
title="Syntax Error",
|
|
1313
|
+
description=f"Syntax error: {syntax_error.msg}",
|
|
1314
|
+
file_path=file_path,
|
|
1315
|
+
line_number=syntax_error.lineno,
|
|
1316
|
+
column_number=syntax_error.offset or 0,
|
|
1317
|
+
code_snippet=content.split('\n')[syntax_error.lineno - 1] if syntax_error.lineno <= len(content.split('\n')) else "",
|
|
1318
|
+
suggested_fix="Fix the syntax error",
|
|
1319
|
+
confidence=1.0
|
|
1320
|
+
)
|
|
1321
|
+
|
|
1322
|
+
return FileReviewResult(
|
|
1323
|
+
file_path=file_path,
|
|
1324
|
+
issues=[issue],
|
|
1325
|
+
metrics={'syntax_error': True},
|
|
1326
|
+
trust_score=0.0,
|
|
1327
|
+
category_scores={cat: 0.0 for cat in TrustCategory},
|
|
1328
|
+
lines_of_code=len(content.split('\n')),
|
|
1329
|
+
complexity_metrics={},
|
|
1330
|
+
review_timestamp=time.time()
|
|
1331
|
+
)
|
|
1332
|
+
|
|
1333
|
+
# Usage Examples
|
|
1334
|
+
"""
|
|
1335
|
+
# Initialize automated code reviewer
|
|
1336
|
+
reviewer = AutomatedCodeReviewer(context7_client=context7)
|
|
1337
|
+
|
|
1338
|
+
# Review entire codebase
|
|
1339
|
+
report = await reviewer.review_codebase(
|
|
1340
|
+
project_path="/path/to/project",
|
|
1341
|
+
include_patterns=["/*.py"],
|
|
1342
|
+
exclude_patterns=["/tests/", "/__pycache__/"]
|
|
1343
|
+
)
|
|
1344
|
+
|
|
1345
|
+
print(f"Code Review Results:")
|
|
1346
|
+
print(f" Overall TRUST Score: {report.overall_trust_score:.2f}")
|
|
1347
|
+
print(f" Files Reviewed: {report.summary_metrics['files_reviewed']}")
|
|
1348
|
+
print(f" Total Issues: {report.summary_metrics['total_issues']}")
|
|
1349
|
+
print(f" Critical Issues: {report.summary_metrics['critical_issues']}")
|
|
1350
|
+
|
|
1351
|
+
print(f"\nTRUST 5 Category Scores:")
|
|
1352
|
+
for category, score in report.overall_category_scores.items():
|
|
1353
|
+
print(f" {category.value}: {score:.2f}")
|
|
1354
|
+
|
|
1355
|
+
print(f"\nTop Recommendations:")
|
|
1356
|
+
for i, rec in enumerate(report.recommendations[:5], 1):
|
|
1357
|
+
print(f" {i}. {rec}")
|
|
1358
|
+
|
|
1359
|
+
print(f"\nCritical Issues:")
|
|
1360
|
+
for issue in report.critical_issues[:3]:
|
|
1361
|
+
print(f" - {issue.title} in {issue.file_path}:{issue.line_number}")
|
|
1362
|
+
print(f" {issue.description}")
|
|
1363
|
+
|
|
1364
|
+
# Review single file
|
|
1365
|
+
file_result = await reviewer.review_single_file("/path/to/file.py")
|
|
1366
|
+
print(f"\nFile Trust Score: {file_result.trust_score:.2f}")
|
|
1367
|
+
print(f"Issues found: {len(file_result.issues)}")
|
|
1368
|
+
"""
|
|
1369
|
+
```
|
|
1370
|
+
|
|
1371
|
+
## Advanced Features
|
|
1372
|
+
|
|
1373
|
+
### Context7-Enhanced Security Analysis
|
|
1374
|
+
|
|
1375
|
+
Advanced Security Pattern Detection:
|
|
1376
|
+
```python
|
|
1377
|
+
class EnhancedSecurityAnalyzer:
|
|
1378
|
+
"""Enhanced security analyzer with Context7 integration."""
|
|
1379
|
+
|
|
1380
|
+
async def analyze_advanced_security_patterns(
|
|
1381
|
+
self, file_path: str, content: str
|
|
1382
|
+
) -> List[CodeIssue]:
|
|
1383
|
+
"""Analyze advanced security patterns using Context7."""
|
|
1384
|
+
|
|
1385
|
+
issues = []
|
|
1386
|
+
|
|
1387
|
+
# Get latest security patterns from Context7
|
|
1388
|
+
security_patterns = await self.context7.get_library_docs(
|
|
1389
|
+
context7_library_id="/security/owasp",
|
|
1390
|
+
topic="advanced security vulnerability patterns 2025",
|
|
1391
|
+
tokens=5000
|
|
1392
|
+
)
|
|
1393
|
+
|
|
1394
|
+
# Analyze for OWASP Top 10 vulnerabilities
|
|
1395
|
+
owasp_issues = await self._analyze_owasp_patterns(file_path, content, security_patterns)
|
|
1396
|
+
issues.extend(owasp_issues)
|
|
1397
|
+
|
|
1398
|
+
# Analyze for business logic vulnerabilities
|
|
1399
|
+
logic_issues = await self._analyze_business_logic_security(file_path, content)
|
|
1400
|
+
issues.extend(logic_issues)
|
|
1401
|
+
|
|
1402
|
+
return issues
|
|
1403
|
+
```
|
|
1404
|
+
|
|
1405
|
+
## Best Practices
|
|
1406
|
+
|
|
1407
|
+
1. Comprehensive Coverage: Analyze code across all TRUST 5 dimensions
|
|
1408
|
+
2. Context Integration: Leverage Context7 for up-to-date security and quality patterns
|
|
1409
|
+
3. Actionable Feedback: Provide specific, implementable suggestions
|
|
1410
|
+
4. Severity Prioritization: Focus on critical and high-severity issues first
|
|
1411
|
+
5. Continuous Integration: Integrate into CI/CD pipeline for automated reviews
|
|
1412
|
+
|
|
1413
|
+
---
|
|
1414
|
+
|
|
1415
|
+
Module: `modules/automated-code-review.md`
|
|
1416
|
+
Related: [Smart Refactoring](./smart-refactoring.md) | [Performance Optimization](./performance-optimization.md)
|