bps-kit 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/templates/.agents/agents/backend-specialist.md +263 -0
- package/templates/.agents/agents/code-archaeologist.md +106 -0
- package/templates/.agents/agents/database-architect.md +226 -0
- package/templates/.agents/agents/debugger.md +225 -0
- package/templates/.agents/agents/devops-engineer.md +242 -0
- package/templates/.agents/agents/documentation-writer.md +104 -0
- package/templates/.agents/agents/explorer-agent.md +73 -0
- package/templates/.agents/agents/frontend-specialist.md +593 -0
- package/templates/.agents/agents/game-developer.md +162 -0
- package/templates/.agents/agents/mobile-developer.md +377 -0
- package/templates/.agents/agents/orchestrator.md +416 -0
- package/templates/.agents/agents/penetration-tester.md +188 -0
- package/templates/.agents/agents/performance-optimizer.md +187 -0
- package/templates/.agents/agents/product-manager.md +112 -0
- package/templates/.agents/agents/product-owner.md +95 -0
- package/templates/.agents/agents/project-planner.md +406 -0
- package/templates/.agents/agents/qa-automation-engineer.md +103 -0
- package/templates/.agents/agents/security-auditor.md +170 -0
- package/templates/.agents/agents/seo-specialist.md +111 -0
- package/templates/.agents/agents/test-engineer.md +158 -0
- package/templates/.agents/rules/GEMINI.md +219 -0
- package/templates/.agents/scripts/auto_preview.py +148 -0
- package/templates/.agents/scripts/checklist.py +217 -0
- package/templates/.agents/scripts/session_manager.py +120 -0
- package/templates/.agents/scripts/verify_all.py +327 -0
- package/templates/.agents/workflows/brainstorm.md +113 -0
- package/templates/.agents/workflows/create.md +59 -0
- package/templates/.agents/workflows/debug.md +103 -0
- package/templates/.agents/workflows/deploy.md +176 -0
- package/templates/.agents/workflows/enhance.md +63 -0
- package/templates/.agents/workflows/orchestrate.md +237 -0
- package/templates/.agents/workflows/plan.md +89 -0
- package/templates/.agents/workflows/preview.md +81 -0
- package/templates/.agents/workflows/setup-brain.md +39 -0
- package/templates/.agents/workflows/status.md +86 -0
- package/templates/.agents/workflows/test.md +144 -0
- package/templates/.agents/workflows/ui-ux-pro-max.md +296 -0
- package/templates/skills_normal/api-patterns/scripts/api_validator.py +211 -0
- package/templates/skills_normal/database-design/scripts/schema_validator.py +172 -0
- package/templates/skills_normal/frontend-design/scripts/accessibility_checker.py +183 -0
- package/templates/skills_normal/frontend-design/scripts/ux_audit.py +722 -0
- package/templates/skills_normal/git-pushing/scripts/smart_commit.sh +19 -0
- package/templates/skills_normal/lint-and-validate/scripts/lint_runner.py +184 -0
- package/templates/skills_normal/lint-and-validate/scripts/type_coverage.py +173 -0
- package/templates/skills_normal/performance-profiling/scripts/lighthouse_audit.py +76 -0
- package/templates/skills_normal/senior-fullstack/scripts/code_quality_analyzer.py +114 -0
- package/templates/skills_normal/senior-fullstack/scripts/fullstack_scaffolder.py +114 -0
- package/templates/skills_normal/senior-fullstack/scripts/project_scaffolder.py +114 -0
- package/templates/skills_normal/seo-fundamentals/scripts/seo_checker.py +219 -0
- package/templates/skills_normal/testing-patterns/scripts/test_runner.py +219 -0
- package/templates/skills_normal/vulnerability-scanner/scripts/security_scan.py +458 -0
- package/templates/vault/007/scripts/config.py +472 -0
- package/templates/vault/007/scripts/full_audit.py +1306 -0
- package/templates/vault/007/scripts/quick_scan.py +481 -0
- package/templates/vault/007/scripts/requirements.txt +26 -0
- package/templates/vault/007/scripts/scanners/__init__.py +0 -0
- package/templates/vault/007/scripts/scanners/dependency_scanner.py +1305 -0
- package/templates/vault/007/scripts/scanners/injection_scanner.py +1104 -0
- package/templates/vault/007/scripts/scanners/secrets_scanner.py +1008 -0
- package/templates/vault/007/scripts/score_calculator.py +693 -0
- package/templates/vault/agent-orchestrator/scripts/match_skills.py +329 -0
- package/templates/vault/agent-orchestrator/scripts/orchestrate.py +304 -0
- package/templates/vault/agent-orchestrator/scripts/requirements.txt +1 -0
- package/templates/vault/agent-orchestrator/scripts/scan_registry.py +508 -0
- package/templates/vault/ai-studio-image/scripts/config.py +613 -0
- package/templates/vault/ai-studio-image/scripts/generate.py +630 -0
- package/templates/vault/ai-studio-image/scripts/prompt_engine.py +424 -0
- package/templates/vault/ai-studio-image/scripts/requirements.txt +4 -0
- package/templates/vault/ai-studio-image/scripts/templates.py +349 -0
- package/templates/vault/android_ui_verification/scripts/verify_ui.sh +32 -0
- package/templates/vault/apify-audience-analysis/reference/scripts/run_actor.js +363 -0
- package/templates/vault/apify-brand-reputation-monitoring/reference/scripts/run_actor.js +363 -0
- package/templates/vault/apify-competitor-intelligence/reference/scripts/run_actor.js +363 -0
- package/templates/vault/apify-content-analytics/reference/scripts/run_actor.js +363 -0
- package/templates/vault/apify-ecommerce/reference/scripts/package.json +3 -0
- package/templates/vault/apify-ecommerce/reference/scripts/run_actor.js +369 -0
- package/templates/vault/apify-influencer-discovery/reference/scripts/run_actor.js +363 -0
- package/templates/vault/apify-lead-generation/reference/scripts/run_actor.js +363 -0
- package/templates/vault/apify-market-research/reference/scripts/run_actor.js +363 -0
- package/templates/vault/apify-trend-analysis/reference/scripts/run_actor.js +363 -0
- package/templates/vault/apify-ultimate-scraper/reference/scripts/run_actor.js +363 -0
- package/templates/vault/audio-transcriber/scripts/install-requirements.sh +190 -0
- package/templates/vault/audio-transcriber/scripts/transcribe.py +486 -0
- package/templates/vault/claude-monitor/scripts/api_bench.py +240 -0
- package/templates/vault/claude-monitor/scripts/config.py +69 -0
- package/templates/vault/claude-monitor/scripts/health_check.py +362 -0
- package/templates/vault/claude-monitor/scripts/monitor.py +296 -0
- package/templates/vault/content-creator/scripts/brand_voice_analyzer.py +185 -0
- package/templates/vault/content-creator/scripts/seo_optimizer.py +419 -0
- package/templates/vault/context-agent/scripts/active_context.py +227 -0
- package/templates/vault/context-agent/scripts/compressor.py +149 -0
- package/templates/vault/context-agent/scripts/config.py +69 -0
- package/templates/vault/context-agent/scripts/context_loader.py +155 -0
- package/templates/vault/context-agent/scripts/context_manager.py +302 -0
- package/templates/vault/context-agent/scripts/models.py +103 -0
- package/templates/vault/context-agent/scripts/project_registry.py +132 -0
- package/templates/vault/context-agent/scripts/requirements.txt +6 -0
- package/templates/vault/context-agent/scripts/search.py +115 -0
- package/templates/vault/context-agent/scripts/session_parser.py +206 -0
- package/templates/vault/context-agent/scripts/session_summary.py +319 -0
- package/templates/vault/context-guardian/scripts/context_snapshot.py +229 -0
- package/templates/vault/docx/ooxml/scripts/pack.py +159 -0
- package/templates/vault/docx/ooxml/scripts/unpack.py +29 -0
- package/templates/vault/docx/ooxml/scripts/validate.py +69 -0
- package/templates/vault/docx/ooxml/scripts/validation/__init__.py +15 -0
- package/templates/vault/docx/ooxml/scripts/validation/base.py +951 -0
- package/templates/vault/docx/ooxml/scripts/validation/docx.py +274 -0
- package/templates/vault/docx/ooxml/scripts/validation/pptx.py +315 -0
- package/templates/vault/docx/ooxml/scripts/validation/redlining.py +279 -0
- package/templates/vault/docx/scripts/__init__.py +1 -0
- package/templates/vault/docx/scripts/document.py +1276 -0
- package/templates/vault/docx/scripts/templates/comments.xml +3 -0
- package/templates/vault/docx/scripts/templates/commentsExtended.xml +3 -0
- package/templates/vault/docx/scripts/templates/commentsExtensible.xml +3 -0
- package/templates/vault/docx/scripts/templates/commentsIds.xml +3 -0
- package/templates/vault/docx/scripts/templates/people.xml +3 -0
- package/templates/vault/docx/scripts/utilities.py +374 -0
- package/templates/vault/docx-official/ooxml/scripts/pack.py +159 -0
- package/templates/vault/docx-official/ooxml/scripts/unpack.py +29 -0
- package/templates/vault/docx-official/ooxml/scripts/validate.py +69 -0
- package/templates/vault/docx-official/ooxml/scripts/validation/__init__.py +15 -0
- package/templates/vault/docx-official/ooxml/scripts/validation/base.py +951 -0
- package/templates/vault/docx-official/ooxml/scripts/validation/docx.py +274 -0
- package/templates/vault/docx-official/ooxml/scripts/validation/pptx.py +315 -0
- package/templates/vault/docx-official/ooxml/scripts/validation/redlining.py +279 -0
- package/templates/vault/docx-official/scripts/__init__.py +1 -0
- package/templates/vault/docx-official/scripts/document.py +1276 -0
- package/templates/vault/docx-official/scripts/templates/comments.xml +3 -0
- package/templates/vault/docx-official/scripts/templates/commentsExtended.xml +3 -0
- package/templates/vault/docx-official/scripts/templates/commentsExtensible.xml +3 -0
- package/templates/vault/docx-official/scripts/templates/commentsIds.xml +3 -0
- package/templates/vault/docx-official/scripts/templates/people.xml +3 -0
- package/templates/vault/docx-official/scripts/utilities.py +374 -0
- package/templates/vault/geo-fundamentals/scripts/geo_checker.py +289 -0
- package/templates/vault/helm-chart-scaffolding/scripts/validate-chart.sh +244 -0
- package/templates/vault/i18n-localization/scripts/i18n_checker.py +241 -0
- package/templates/vault/instagram/scripts/account_setup.py +233 -0
- package/templates/vault/instagram/scripts/analyze.py +221 -0
- package/templates/vault/instagram/scripts/api_client.py +444 -0
- package/templates/vault/instagram/scripts/auth.py +411 -0
- package/templates/vault/instagram/scripts/comments.py +160 -0
- package/templates/vault/instagram/scripts/config.py +111 -0
- package/templates/vault/instagram/scripts/db.py +467 -0
- package/templates/vault/instagram/scripts/export.py +138 -0
- package/templates/vault/instagram/scripts/governance.py +233 -0
- package/templates/vault/instagram/scripts/hashtags.py +114 -0
- package/templates/vault/instagram/scripts/insights.py +170 -0
- package/templates/vault/instagram/scripts/media.py +65 -0
- package/templates/vault/instagram/scripts/messages.py +103 -0
- package/templates/vault/instagram/scripts/profile.py +58 -0
- package/templates/vault/instagram/scripts/publish.py +449 -0
- package/templates/vault/instagram/scripts/requirements.txt +5 -0
- package/templates/vault/instagram/scripts/run_all.py +189 -0
- package/templates/vault/instagram/scripts/schedule.py +189 -0
- package/templates/vault/instagram/scripts/serve_api.py +234 -0
- package/templates/vault/instagram/scripts/templates.py +155 -0
- package/templates/vault/junta-leiloeiros/scripts/db.py +216 -0
- package/templates/vault/junta-leiloeiros/scripts/export.py +137 -0
- package/templates/vault/junta-leiloeiros/scripts/requirements.txt +15 -0
- package/templates/vault/junta-leiloeiros/scripts/run_all.py +190 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/__init__.py +4 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/base_scraper.py +209 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/generic_scraper.py +110 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucap.py +110 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/juceac.py +72 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/juceal.py +72 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/juceb.py +68 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucec.py +63 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucema.py +211 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucemg.py +218 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucep.py +70 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucepa.py +74 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucepar.py +80 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucepe.py +78 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucepi.py +69 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucer.py +256 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucerja.py +170 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucern.py +71 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucesc.py +89 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucesp.py +233 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucetins.py +134 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucis_df.py +63 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucisrs.py +299 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/states.py +99 -0
- package/templates/vault/junta-leiloeiros/scripts/serve_api.py +164 -0
- package/templates/vault/junta-leiloeiros/scripts/web_scraper_fallback.py +233 -0
- package/templates/vault/last30days/scripts/last30days.py +521 -0
- package/templates/vault/last30days/scripts/lib/__init__.py +1 -0
- package/templates/vault/last30days/scripts/lib/cache.py +152 -0
- package/templates/vault/last30days/scripts/lib/dates.py +124 -0
- package/templates/vault/last30days/scripts/lib/dedupe.py +120 -0
- package/templates/vault/last30days/scripts/lib/env.py +149 -0
- package/templates/vault/last30days/scripts/lib/http.py +152 -0
- package/templates/vault/last30days/scripts/lib/models.py +175 -0
- package/templates/vault/last30days/scripts/lib/normalize.py +160 -0
- package/templates/vault/last30days/scripts/lib/openai_reddit.py +230 -0
- package/templates/vault/last30days/scripts/lib/reddit_enrich.py +232 -0
- package/templates/vault/last30days/scripts/lib/render.py +383 -0
- package/templates/vault/last30days/scripts/lib/schema.py +336 -0
- package/templates/vault/last30days/scripts/lib/score.py +311 -0
- package/templates/vault/last30days/scripts/lib/ui.py +324 -0
- package/templates/vault/last30days/scripts/lib/websearch.py +401 -0
- package/templates/vault/last30days/scripts/lib/xai_x.py +217 -0
- package/templates/vault/leiloeiro-avaliacao/scripts/governance.py +106 -0
- package/templates/vault/leiloeiro-avaliacao/scripts/requirements.txt +1 -0
- package/templates/vault/leiloeiro-edital/scripts/governance.py +106 -0
- package/templates/vault/leiloeiro-edital/scripts/requirements.txt +1 -0
- package/templates/vault/leiloeiro-ia/scripts/governance.py +106 -0
- package/templates/vault/leiloeiro-ia/scripts/requirements.txt +1 -0
- package/templates/vault/leiloeiro-juridico/scripts/governance.py +106 -0
- package/templates/vault/leiloeiro-juridico/scripts/requirements.txt +1 -0
- package/templates/vault/leiloeiro-mercado/scripts/governance.py +106 -0
- package/templates/vault/leiloeiro-mercado/scripts/requirements.txt +1 -0
- package/templates/vault/leiloeiro-risco/scripts/governance.py +106 -0
- package/templates/vault/leiloeiro-risco/scripts/requirements.txt +1 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/db/database.ts +24 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/db/db.ts +35 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/db/index.ts +2 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/db/migrations.ts +31 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/db/schema.sql +8 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/index.ts +44 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/routes/todos.ts +155 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/types/index.ts +35 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/App.css +384 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/App.tsx +81 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/api/todos.ts +57 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/components/ConfirmDialog.tsx +26 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/components/EmptyState.tsx +8 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/components/TodoForm.tsx +43 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/components/TodoItem.tsx +36 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/components/TodoList.tsx +27 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/hooks/useTodos.ts +81 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/index.css +48 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/main.tsx +10 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/vite-env.d.ts +1 -0
- package/templates/vault/loki-mode/scripts/export-to-vibe-kanban.sh +178 -0
- package/templates/vault/loki-mode/scripts/loki-wrapper.sh +281 -0
- package/templates/vault/loki-mode/scripts/take-screenshots.js +55 -0
- package/templates/vault/matematico-tao/scripts/complexity_analyzer.py +544 -0
- package/templates/vault/matematico-tao/scripts/dependency_graph.py +538 -0
- package/templates/vault/mcp-builder/scripts/connections.py +151 -0
- package/templates/vault/mcp-builder/scripts/evaluation.py +373 -0
- package/templates/vault/mcp-builder/scripts/example_evaluation.xml +22 -0
- package/templates/vault/mcp-builder/scripts/requirements.txt +2 -0
- package/templates/vault/mobile-design/scripts/mobile_audit.py +670 -0
- package/templates/vault/notebooklm/scripts/__init__.py +81 -0
- package/templates/vault/notebooklm/scripts/ask_question.py +256 -0
- package/templates/vault/notebooklm/scripts/auth_manager.py +358 -0
- package/templates/vault/notebooklm/scripts/browser_session.py +255 -0
- package/templates/vault/notebooklm/scripts/browser_utils.py +107 -0
- package/templates/vault/notebooklm/scripts/cleanup_manager.py +302 -0
- package/templates/vault/notebooklm/scripts/config.py +44 -0
- package/templates/vault/notebooklm/scripts/notebook_manager.py +410 -0
- package/templates/vault/notebooklm/scripts/run.py +102 -0
- package/templates/vault/notebooklm/scripts/setup_environment.py +204 -0
- package/templates/vault/pdf/scripts/check_bounding_boxes.py +70 -0
- package/templates/vault/pdf/scripts/check_bounding_boxes_test.py +226 -0
- package/templates/vault/pdf/scripts/check_fillable_fields.py +12 -0
- package/templates/vault/pdf/scripts/convert_pdf_to_images.py +35 -0
- package/templates/vault/pdf/scripts/create_validation_image.py +41 -0
- package/templates/vault/pdf/scripts/extract_form_field_info.py +152 -0
- package/templates/vault/pdf/scripts/fill_fillable_fields.py +114 -0
- package/templates/vault/pdf/scripts/fill_pdf_form_with_annotations.py +108 -0
- package/templates/vault/pdf-official/scripts/check_bounding_boxes.py +70 -0
- package/templates/vault/pdf-official/scripts/check_bounding_boxes_test.py +226 -0
- package/templates/vault/pdf-official/scripts/check_fillable_fields.py +12 -0
- package/templates/vault/pdf-official/scripts/convert_pdf_to_images.py +35 -0
- package/templates/vault/pdf-official/scripts/create_validation_image.py +41 -0
- package/templates/vault/pdf-official/scripts/extract_form_field_info.py +152 -0
- package/templates/vault/pdf-official/scripts/fill_fillable_fields.py +114 -0
- package/templates/vault/pdf-official/scripts/fill_pdf_form_with_annotations.py +108 -0
- package/templates/vault/planning-with-files/scripts/check-complete.sh +44 -0
- package/templates/vault/planning-with-files/scripts/init-session.sh +120 -0
- package/templates/vault/pptx/ooxml/scripts/pack.py +159 -0
- package/templates/vault/pptx/ooxml/scripts/unpack.py +29 -0
- package/templates/vault/pptx/ooxml/scripts/validate.py +69 -0
- package/templates/vault/pptx/ooxml/scripts/validation/__init__.py +15 -0
- package/templates/vault/pptx/ooxml/scripts/validation/base.py +951 -0
- package/templates/vault/pptx/ooxml/scripts/validation/docx.py +274 -0
- package/templates/vault/pptx/ooxml/scripts/validation/pptx.py +315 -0
- package/templates/vault/pptx/ooxml/scripts/validation/redlining.py +279 -0
- package/templates/vault/pptx/scripts/html2pptx.js +979 -0
- package/templates/vault/pptx/scripts/inventory.py +1020 -0
- package/templates/vault/pptx/scripts/rearrange.py +231 -0
- package/templates/vault/pptx/scripts/replace.py +385 -0
- package/templates/vault/pptx/scripts/thumbnail.py +450 -0
- package/templates/vault/pptx-official/ooxml/scripts/pack.py +159 -0
- package/templates/vault/pptx-official/ooxml/scripts/unpack.py +29 -0
- package/templates/vault/pptx-official/ooxml/scripts/validate.py +69 -0
- package/templates/vault/pptx-official/ooxml/scripts/validation/__init__.py +15 -0
- package/templates/vault/pptx-official/ooxml/scripts/validation/base.py +951 -0
- package/templates/vault/pptx-official/ooxml/scripts/validation/docx.py +274 -0
- package/templates/vault/pptx-official/ooxml/scripts/validation/pptx.py +315 -0
- package/templates/vault/pptx-official/ooxml/scripts/validation/redlining.py +279 -0
- package/templates/vault/pptx-official/scripts/html2pptx.js +979 -0
- package/templates/vault/pptx-official/scripts/inventory.py +1020 -0
- package/templates/vault/pptx-official/scripts/rearrange.py +231 -0
- package/templates/vault/pptx-official/scripts/replace.py +385 -0
- package/templates/vault/pptx-official/scripts/thumbnail.py +450 -0
- package/templates/vault/product-manager-toolkit/scripts/customer_interview_analyzer.py +441 -0
- package/templates/vault/product-manager-toolkit/scripts/rice_prioritizer.py +296 -0
- package/templates/vault/prompt-engineering-patterns/scripts/optimize-prompt.py +279 -0
- package/templates/vault/scripts/.skill_cache.json +7538 -0
- package/templates/vault/scripts/skill_search.py +228 -0
- package/templates/vault/senior-architect/scripts/architecture_diagram_generator.py +114 -0
- package/templates/vault/senior-architect/scripts/dependency_analyzer.py +114 -0
- package/templates/vault/senior-architect/scripts/project_architect.py +114 -0
- package/templates/vault/shopify-development/scripts/requirements.txt +19 -0
- package/templates/vault/shopify-development/scripts/shopify_graphql.py +428 -0
- package/templates/vault/shopify-development/scripts/shopify_init.py +441 -0
- package/templates/vault/shopify-development/scripts/tests/test_shopify_init.py +379 -0
- package/templates/vault/skill-creator/scripts/init_skill.py +303 -0
- package/templates/vault/skill-creator/scripts/package_skill.py +110 -0
- package/templates/vault/skill-creator/scripts/quick_validate.py +95 -0
- package/templates/vault/skill-installer/scripts/detect_skills.py +318 -0
- package/templates/vault/skill-installer/scripts/install_skill.py +1708 -0
- package/templates/vault/skill-installer/scripts/package_skill.py +417 -0
- package/templates/vault/skill-installer/scripts/requirements.txt +1 -0
- package/templates/vault/skill-installer/scripts/validate_skill.py +430 -0
- package/templates/vault/skill-sentinel/scripts/analyzers/__init__.py +13 -0
- package/templates/vault/skill-sentinel/scripts/analyzers/code_quality.py +247 -0
- package/templates/vault/skill-sentinel/scripts/analyzers/cross_skill.py +134 -0
- package/templates/vault/skill-sentinel/scripts/analyzers/dependencies.py +121 -0
- package/templates/vault/skill-sentinel/scripts/analyzers/documentation.py +189 -0
- package/templates/vault/skill-sentinel/scripts/analyzers/governance_audit.py +153 -0
- package/templates/vault/skill-sentinel/scripts/analyzers/performance.py +164 -0
- package/templates/vault/skill-sentinel/scripts/analyzers/security.py +189 -0
- package/templates/vault/skill-sentinel/scripts/config.py +158 -0
- package/templates/vault/skill-sentinel/scripts/cost_optimizer.py +146 -0
- package/templates/vault/skill-sentinel/scripts/db.py +354 -0
- package/templates/vault/skill-sentinel/scripts/governance.py +58 -0
- package/templates/vault/skill-sentinel/scripts/recommender.py +228 -0
- package/templates/vault/skill-sentinel/scripts/report_generator.py +224 -0
- package/templates/vault/skill-sentinel/scripts/requirements.txt +1 -0
- package/templates/vault/skill-sentinel/scripts/run_audit.py +290 -0
- package/templates/vault/skill-sentinel/scripts/scanner.py +271 -0
- package/templates/vault/stability-ai/scripts/config.py +266 -0
- package/templates/vault/stability-ai/scripts/generate.py +687 -0
- package/templates/vault/stability-ai/scripts/requirements.txt +4 -0
- package/templates/vault/stability-ai/scripts/styles.py +174 -0
- package/templates/vault/telegram/assets/boilerplate/nodejs/src/bot-client.ts +86 -0
- package/templates/vault/telegram/assets/boilerplate/nodejs/src/handlers.ts +79 -0
- package/templates/vault/telegram/assets/boilerplate/nodejs/src/index.ts +32 -0
- package/templates/vault/telegram/scripts/send_message.py +143 -0
- package/templates/vault/telegram/scripts/setup_project.py +103 -0
- package/templates/vault/telegram/scripts/test_bot.py +144 -0
- package/templates/vault/typescript-expert/scripts/ts_diagnostic.py +203 -0
- package/templates/vault/ui-ux-pro-max/scripts/__pycache__/core.cpython-314.pyc +0 -0
- package/templates/vault/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-314.pyc +0 -0
- package/templates/vault/ui-ux-pro-max/scripts/core.py +257 -0
- package/templates/vault/ui-ux-pro-max/scripts/design_system.py +487 -0
- package/templates/vault/ui-ux-pro-max/scripts/search.py +76 -0
- package/templates/vault/videodb/scripts/ws_listener.py +204 -0
- package/templates/vault/web-artifacts-builder/scripts/bundle-artifact.sh +54 -0
- package/templates/vault/web-artifacts-builder/scripts/init-artifact.sh +322 -0
- package/templates/vault/web-artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
- package/templates/vault/webapp-testing/scripts/with_server.py +106 -0
- package/templates/vault/whatsapp-cloud-api/assets/boilerplate/nodejs/src/index.ts +125 -0
- package/templates/vault/whatsapp-cloud-api/assets/boilerplate/nodejs/src/template-manager.ts +67 -0
- package/templates/vault/whatsapp-cloud-api/assets/boilerplate/nodejs/src/types.ts +216 -0
- package/templates/vault/whatsapp-cloud-api/assets/boilerplate/nodejs/src/webhook-handler.ts +173 -0
- package/templates/vault/whatsapp-cloud-api/assets/boilerplate/nodejs/src/whatsapp-client.ts +193 -0
- package/templates/vault/whatsapp-cloud-api/scripts/send_test_message.py +137 -0
- package/templates/vault/whatsapp-cloud-api/scripts/setup_project.py +118 -0
- package/templates/vault/whatsapp-cloud-api/scripts/validate_config.py +190 -0
- package/templates/vault/youtube-summarizer/scripts/extract-transcript.py +65 -0
- package/templates/vault/youtube-summarizer/scripts/install-dependencies.sh +28 -0
|
@@ -0,0 +1,544 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
Prof. Euler — Complexity Analyzer
|
|
5
|
+
Análise automática de complexidade ciclomática, cognitiva e acoplamento
|
|
6
|
+
para projetos Kotlin/Android.
|
|
7
|
+
|
|
8
|
+
Uso:
|
|
9
|
+
python complexity_analyzer.py [path] [--module MODULE] [--threshold N]
|
|
10
|
+
python complexity_analyzer.py C:/Users/renat/earbudllm
|
|
11
|
+
python complexity_analyzer.py C:/Users/renat/earbudllm --module llm --threshold 10
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import os
|
|
15
|
+
import re
|
|
16
|
+
import sys
|
|
17
|
+
import json
|
|
18
|
+
import argparse
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
# Fix Unicode output on Windows (cp1252 terminal)
|
|
22
|
+
if sys.platform == 'win32':
|
|
23
|
+
try:
|
|
24
|
+
sys.stdout.reconfigure(encoding='utf-8', errors='replace')
|
|
25
|
+
sys.stderr.reconfigure(encoding='utf-8', errors='replace')
|
|
26
|
+
except AttributeError:
|
|
27
|
+
pass # Python < 3.7 fallback
|
|
28
|
+
from dataclasses import dataclass, field
|
|
29
|
+
from typing import List, Dict, Optional, Tuple
|
|
30
|
+
from collections import defaultdict
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass
|
|
34
|
+
class FunctionMetrics:
|
|
35
|
+
name: str
|
|
36
|
+
file: str
|
|
37
|
+
line: int
|
|
38
|
+
cyclomatic: int
|
|
39
|
+
cognitive: int
|
|
40
|
+
lines: int
|
|
41
|
+
parameters: int
|
|
42
|
+
nullable_params: int
|
|
43
|
+
has_try_catch: bool
|
|
44
|
+
coroutine: bool # is suspend fun
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass
|
|
48
|
+
class FileMetrics:
|
|
49
|
+
path: str
|
|
50
|
+
module: str
|
|
51
|
+
functions: List[FunctionMetrics] = field(default_factory=list)
|
|
52
|
+
imports: List[str] = field(default_factory=list)
|
|
53
|
+
total_lines: int = 0
|
|
54
|
+
blank_lines: int = 0
|
|
55
|
+
comment_lines: int = 0
|
|
56
|
+
|
|
57
|
+
@property
|
|
58
|
+
def code_lines(self):
|
|
59
|
+
return self.total_lines - self.blank_lines - self.comment_lines
|
|
60
|
+
|
|
61
|
+
@property
|
|
62
|
+
def max_cyclomatic(self):
|
|
63
|
+
return max((f.cyclomatic for f in self.functions), default=0)
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def avg_cyclomatic(self):
|
|
67
|
+
if not self.functions:
|
|
68
|
+
return 0.0
|
|
69
|
+
return sum(f.cyclomatic for f in self.functions) / len(self.functions)
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def max_cognitive(self):
|
|
73
|
+
return max((f.cognitive for f in self.functions), default=0)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@dataclass
|
|
77
|
+
class ModuleCoupling:
|
|
78
|
+
module: str
|
|
79
|
+
efferent: List[str] = field(default_factory=list) # Ce: modules this depends on
|
|
80
|
+
afferent: List[str] = field(default_factory=list) # Ca: modules that depend on this
|
|
81
|
+
|
|
82
|
+
@property
|
|
83
|
+
def instability(self) -> float:
|
|
84
|
+
ca = len(self.afferent)
|
|
85
|
+
ce = len(self.efferent)
|
|
86
|
+
if ca + ce == 0:
|
|
87
|
+
return 0.0
|
|
88
|
+
return ce / (ca + ce)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class KotlinComplexityAnalyzer:
|
|
92
|
+
"""Analisa complexidade de código Kotlin com rigor matemático."""
|
|
93
|
+
|
|
94
|
+
# Tokens que incrementam complexidade ciclomática
|
|
95
|
+
CYCLOMATIC_TOKENS = [
|
|
96
|
+
r'\bif\b', r'\belse if\b', r'\bwhen\b', r'\bfor\b', r'\bwhile\b',
|
|
97
|
+
r'\bdo\b', r'\btry\b', r'\bcatch\b', r'\band\b', r'\bor\b',
|
|
98
|
+
r'\?\?', r'\?\.', # Elvis operator e safe call
|
|
99
|
+
r'&&', r'\|\|',
|
|
100
|
+
]
|
|
101
|
+
|
|
102
|
+
# Tokens de quebra de fluxo (aumentam complexidade cognitiva mais que cicl.)
|
|
103
|
+
COGNITIVE_BREAK_TOKENS = [
|
|
104
|
+
r'\bbreak\b', r'\bcontinue\b', r'\breturn\b(?!\s+\w+\s*$)', # return no meio
|
|
105
|
+
r'\bthrow\b',
|
|
106
|
+
]
|
|
107
|
+
|
|
108
|
+
def __init__(self, project_root: str, threshold: int = 10):
|
|
109
|
+
self.project_root = Path(project_root)
|
|
110
|
+
self.threshold = threshold
|
|
111
|
+
self.metrics: List[FileMetrics] = []
|
|
112
|
+
|
|
113
|
+
def analyze(self, module_filter: Optional[str] = None) -> None:
|
|
114
|
+
"""Analisa todos os arquivos Kotlin no projeto."""
|
|
115
|
+
pattern = "**/*.kt"
|
|
116
|
+
kt_files = list(self.project_root.glob(pattern))
|
|
117
|
+
|
|
118
|
+
for kt_file in kt_files:
|
|
119
|
+
# Filtra arquivos de teste se não especificado
|
|
120
|
+
if 'test' in kt_file.parts and module_filter is None:
|
|
121
|
+
continue
|
|
122
|
+
|
|
123
|
+
# Filtro de módulo
|
|
124
|
+
module = self._detect_module(kt_file)
|
|
125
|
+
if module_filter and module != module_filter:
|
|
126
|
+
continue
|
|
127
|
+
|
|
128
|
+
metrics = self._analyze_file(kt_file, module)
|
|
129
|
+
self.metrics.append(metrics)
|
|
130
|
+
|
|
131
|
+
def _detect_module(self, file_path: Path) -> str:
|
|
132
|
+
"""Detecta qual módulo um arquivo pertence."""
|
|
133
|
+
parts = file_path.parts
|
|
134
|
+
known_modules = ['app', 'bluetooth', 'audio', 'voice', 'llm',
|
|
135
|
+
'integrations', 'core-logging']
|
|
136
|
+
for part in parts:
|
|
137
|
+
if part in known_modules:
|
|
138
|
+
return part
|
|
139
|
+
return 'unknown'
|
|
140
|
+
|
|
141
|
+
def _analyze_file(self, file_path: Path, module: str) -> FileMetrics:
|
|
142
|
+
"""Analisa um arquivo Kotlin."""
|
|
143
|
+
try:
|
|
144
|
+
content = file_path.read_text(encoding='utf-8', errors='ignore')
|
|
145
|
+
except Exception:
|
|
146
|
+
return FileMetrics(str(file_path), module)
|
|
147
|
+
|
|
148
|
+
lines = content.split('\n')
|
|
149
|
+
metrics = FileMetrics(
|
|
150
|
+
path=str(file_path.relative_to(self.project_root)),
|
|
151
|
+
module=module,
|
|
152
|
+
total_lines=len(lines)
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
# Contar linhas
|
|
156
|
+
for line in lines:
|
|
157
|
+
stripped = line.strip()
|
|
158
|
+
if not stripped:
|
|
159
|
+
metrics.blank_lines += 1
|
|
160
|
+
elif stripped.startswith('//') or stripped.startswith('*') or stripped.startswith('/*'):
|
|
161
|
+
metrics.comment_lines += 1
|
|
162
|
+
|
|
163
|
+
# Extrair imports
|
|
164
|
+
metrics.imports = re.findall(r'^import\s+(.+)$', content, re.MULTILINE)
|
|
165
|
+
|
|
166
|
+
# Analisar funções
|
|
167
|
+
metrics.functions = self._extract_functions(content, str(file_path))
|
|
168
|
+
|
|
169
|
+
return metrics
|
|
170
|
+
|
|
171
|
+
def _extract_functions(self, content: str, filepath: str) -> List[FunctionMetrics]:
|
|
172
|
+
"""Extrai e analisa todas as funções do arquivo."""
|
|
173
|
+
functions = []
|
|
174
|
+
lines = content.split('\n')
|
|
175
|
+
|
|
176
|
+
# Pattern para declarações de função Kotlin
|
|
177
|
+
fun_pattern = re.compile(
|
|
178
|
+
r'^(\s*)((?:suspend\s+)?(?:private\s+|protected\s+|internal\s+|public\s+)?'
|
|
179
|
+
r'(?:override\s+)?(?:suspend\s+)?fun\s+(\w+)\s*\(([^)]*)\))',
|
|
180
|
+
re.MULTILINE
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
for match in fun_pattern.finditer(content):
|
|
184
|
+
fun_name = match.group(3)
|
|
185
|
+
params_str = match.group(4)
|
|
186
|
+
is_suspend = 'suspend' in match.group(2)
|
|
187
|
+
line_num = content[:match.start()].count('\n') + 1
|
|
188
|
+
|
|
189
|
+
# Extrair corpo da função
|
|
190
|
+
body = self._extract_function_body(content, match.end())
|
|
191
|
+
if not body:
|
|
192
|
+
continue
|
|
193
|
+
|
|
194
|
+
# Calcular métricas
|
|
195
|
+
cc = self._cyclomatic_complexity(body)
|
|
196
|
+
cog = self._cognitive_complexity(body)
|
|
197
|
+
params = self._count_parameters(params_str)
|
|
198
|
+
nullable = self._count_nullable_params(params_str)
|
|
199
|
+
has_try = bool(re.search(r'\btry\b', body))
|
|
200
|
+
|
|
201
|
+
functions.append(FunctionMetrics(
|
|
202
|
+
name=fun_name,
|
|
203
|
+
file=filepath,
|
|
204
|
+
line=line_num,
|
|
205
|
+
cyclomatic=cc,
|
|
206
|
+
cognitive=cog,
|
|
207
|
+
lines=body.count('\n'),
|
|
208
|
+
parameters=params,
|
|
209
|
+
nullable_params=nullable,
|
|
210
|
+
has_try_catch=has_try,
|
|
211
|
+
coroutine=is_suspend
|
|
212
|
+
))
|
|
213
|
+
|
|
214
|
+
return functions
|
|
215
|
+
|
|
216
|
+
def _extract_function_body(self, content: str, start: int) -> str:
|
|
217
|
+
"""Extrai o corpo de uma função por contagem de chaves."""
|
|
218
|
+
i = start
|
|
219
|
+
depth = 0
|
|
220
|
+
started = False
|
|
221
|
+
|
|
222
|
+
while i < len(content):
|
|
223
|
+
c = content[i]
|
|
224
|
+
if c == '{':
|
|
225
|
+
depth += 1
|
|
226
|
+
started = True
|
|
227
|
+
elif c == '}':
|
|
228
|
+
depth -= 1
|
|
229
|
+
if started and depth == 0:
|
|
230
|
+
return content[start:i+1]
|
|
231
|
+
i += 1
|
|
232
|
+
|
|
233
|
+
return content[start:min(start + 500, len(content))]
|
|
234
|
+
|
|
235
|
+
def _cyclomatic_complexity(self, code: str) -> int:
|
|
236
|
+
"""Calcula CC de McCabe."""
|
|
237
|
+
cc = 1 # Base
|
|
238
|
+
for pattern in self.CYCLOMATIC_TOKENS:
|
|
239
|
+
matches = re.findall(pattern, code)
|
|
240
|
+
cc += len(matches)
|
|
241
|
+
return cc
|
|
242
|
+
|
|
243
|
+
def _cognitive_complexity(self, code: str) -> int:
|
|
244
|
+
"""Calcula complexidade cognitiva (aproximação)."""
|
|
245
|
+
cog = 0
|
|
246
|
+
nesting = 0
|
|
247
|
+
lines = code.split('\n')
|
|
248
|
+
|
|
249
|
+
for line in lines:
|
|
250
|
+
stripped = line.strip()
|
|
251
|
+
|
|
252
|
+
# Aumenta nesting
|
|
253
|
+
if re.search(r'\b(if|when|for|while|try)\b', stripped):
|
|
254
|
+
cog += (1 + nesting)
|
|
255
|
+
nesting += 1
|
|
256
|
+
|
|
257
|
+
# Fecha nesting
|
|
258
|
+
elif stripped == '}':
|
|
259
|
+
nesting = max(0, nesting - 1)
|
|
260
|
+
|
|
261
|
+
# Breaks de fluxo
|
|
262
|
+
for pattern in self.COGNITIVE_BREAK_TOKENS:
|
|
263
|
+
if re.search(pattern, stripped):
|
|
264
|
+
cog += 1
|
|
265
|
+
|
|
266
|
+
return cog
|
|
267
|
+
|
|
268
|
+
def _count_parameters(self, params_str: str) -> int:
|
|
269
|
+
"""Conta parâmetros de uma função."""
|
|
270
|
+
if not params_str.strip():
|
|
271
|
+
return 0
|
|
272
|
+
return len([p for p in params_str.split(',') if p.strip()])
|
|
273
|
+
|
|
274
|
+
def _count_nullable_params(self, params_str: str) -> int:
|
|
275
|
+
"""Conta parâmetros nullable (tipo?)."""
|
|
276
|
+
return len(re.findall(r'\w+\?', params_str))
|
|
277
|
+
|
|
278
|
+
def analyze_coupling(self) -> Dict[str, ModuleCoupling]:
|
|
279
|
+
"""Analisa acoplamento entre módulos."""
|
|
280
|
+
module_imports: Dict[str, set] = defaultdict(set)
|
|
281
|
+
|
|
282
|
+
for file_metrics in self.metrics:
|
|
283
|
+
for imp in file_metrics.imports:
|
|
284
|
+
# Detecta qual módulo está sendo importado
|
|
285
|
+
for mod in ['bluetooth', 'audio', 'voice', 'llm', 'integrations', 'core.logging']:
|
|
286
|
+
if mod in imp:
|
|
287
|
+
module_imports[file_metrics.module].add(mod.replace('.', '-'))
|
|
288
|
+
|
|
289
|
+
coupling = {}
|
|
290
|
+
all_modules = set(m.module for m in self.metrics)
|
|
291
|
+
|
|
292
|
+
for mod in all_modules:
|
|
293
|
+
c = ModuleCoupling(module=mod)
|
|
294
|
+
c.efferent = list(module_imports.get(mod, set()))
|
|
295
|
+
for other_mod, deps in module_imports.items():
|
|
296
|
+
if mod.replace('-', '.') in deps or mod in deps:
|
|
297
|
+
c.afferent.append(other_mod)
|
|
298
|
+
coupling[mod] = c
|
|
299
|
+
|
|
300
|
+
return coupling
|
|
301
|
+
|
|
302
|
+
def generate_report(self) -> Dict:
|
|
303
|
+
"""Gera relatório completo com análise matemática."""
|
|
304
|
+
# Funções problemáticas
|
|
305
|
+
high_cc = []
|
|
306
|
+
high_cognitive = []
|
|
307
|
+
too_long = []
|
|
308
|
+
too_many_params = []
|
|
309
|
+
unsafe_nullable = []
|
|
310
|
+
coroutine_issues = []
|
|
311
|
+
|
|
312
|
+
for file_m in self.metrics:
|
|
313
|
+
for func in file_m.functions:
|
|
314
|
+
if func.cyclomatic > self.threshold:
|
|
315
|
+
high_cc.append({
|
|
316
|
+
'function': func.name,
|
|
317
|
+
'file': file_m.path,
|
|
318
|
+
'line': func.line,
|
|
319
|
+
'cc': func.cyclomatic,
|
|
320
|
+
'risk': self._cc_risk_label(func.cyclomatic)
|
|
321
|
+
})
|
|
322
|
+
|
|
323
|
+
if func.cognitive > self.threshold * 1.5:
|
|
324
|
+
high_cognitive.append({
|
|
325
|
+
'function': func.name,
|
|
326
|
+
'file': file_m.path,
|
|
327
|
+
'line': func.line,
|
|
328
|
+
'cognitive': func.cognitive
|
|
329
|
+
})
|
|
330
|
+
|
|
331
|
+
if func.lines > 50:
|
|
332
|
+
too_long.append({
|
|
333
|
+
'function': func.name,
|
|
334
|
+
'file': file_m.path,
|
|
335
|
+
'line': func.line,
|
|
336
|
+
'lines': func.lines
|
|
337
|
+
})
|
|
338
|
+
|
|
339
|
+
if func.parameters > 5:
|
|
340
|
+
too_many_params.append({
|
|
341
|
+
'function': func.name,
|
|
342
|
+
'file': file_m.path,
|
|
343
|
+
'params': func.parameters
|
|
344
|
+
})
|
|
345
|
+
|
|
346
|
+
if func.nullable_params > 2:
|
|
347
|
+
unsafe_nullable.append({
|
|
348
|
+
'function': func.name,
|
|
349
|
+
'file': file_m.path,
|
|
350
|
+
'nullable_params': func.nullable_params
|
|
351
|
+
})
|
|
352
|
+
|
|
353
|
+
if func.coroutine and func.has_try_catch:
|
|
354
|
+
coroutine_issues.append({
|
|
355
|
+
'function': func.name,
|
|
356
|
+
'file': file_m.path,
|
|
357
|
+
'note': 'suspend fun with try-catch: verify structured concurrency'
|
|
358
|
+
})
|
|
359
|
+
|
|
360
|
+
# Ordenar por severidade
|
|
361
|
+
high_cc.sort(key=lambda x: x['cc'], reverse=True)
|
|
362
|
+
|
|
363
|
+
# Módulos com maior complexidade
|
|
364
|
+
module_stats = defaultdict(lambda: {'total_cc': 0, 'max_cc': 0, 'functions': 0, 'files': 0})
|
|
365
|
+
for file_m in self.metrics:
|
|
366
|
+
mod = file_m.module
|
|
367
|
+
module_stats[mod]['files'] += 1
|
|
368
|
+
module_stats[mod]['functions'] += len(file_m.functions)
|
|
369
|
+
for f in file_m.functions:
|
|
370
|
+
module_stats[mod]['total_cc'] += f.cyclomatic
|
|
371
|
+
module_stats[mod]['max_cc'] = max(module_stats[mod]['max_cc'], f.cyclomatic)
|
|
372
|
+
|
|
373
|
+
# Calcular média CC por módulo
|
|
374
|
+
for mod, stats in module_stats.items():
|
|
375
|
+
if stats['functions'] > 0:
|
|
376
|
+
stats['avg_cc'] = round(stats['total_cc'] / stats['functions'], 2)
|
|
377
|
+
else:
|
|
378
|
+
stats['avg_cc'] = 0
|
|
379
|
+
|
|
380
|
+
coupling = self.analyze_coupling()
|
|
381
|
+
coupling_data = {}
|
|
382
|
+
for mod, c in coupling.items():
|
|
383
|
+
coupling_data[mod] = {
|
|
384
|
+
'Ca': len(c.afferent),
|
|
385
|
+
'Ce': len(c.efferent),
|
|
386
|
+
'instability': round(c.instability, 3),
|
|
387
|
+
'depends_on': c.efferent,
|
|
388
|
+
'depended_by': c.afferent
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
return {
|
|
392
|
+
'summary': {
|
|
393
|
+
'total_files': len(self.metrics),
|
|
394
|
+
'total_functions': sum(len(f.functions) for f in self.metrics),
|
|
395
|
+
'total_code_lines': sum(f.code_lines for f in self.metrics),
|
|
396
|
+
'high_cc_functions': len(high_cc),
|
|
397
|
+
'high_cognitive_functions': len(high_cognitive),
|
|
398
|
+
},
|
|
399
|
+
'high_cyclomatic_complexity': high_cc[:20], # top 20
|
|
400
|
+
'high_cognitive_complexity': high_cognitive[:10],
|
|
401
|
+
'overly_long_functions': too_long[:10],
|
|
402
|
+
'too_many_parameters': too_many_params[:10],
|
|
403
|
+
'nullable_risks': unsafe_nullable[:10],
|
|
404
|
+
'coroutine_issues': coroutine_issues[:10],
|
|
405
|
+
'module_statistics': dict(module_stats),
|
|
406
|
+
'module_coupling': coupling_data,
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
def _cc_risk_label(self, cc: int) -> str:
|
|
410
|
+
if cc <= 5:
|
|
411
|
+
return "LOW"
|
|
412
|
+
elif cc <= 10:
|
|
413
|
+
return "MODERATE"
|
|
414
|
+
elif cc <= 20:
|
|
415
|
+
return "HIGH — refactor recommended"
|
|
416
|
+
else:
|
|
417
|
+
return "CRITICAL — must refactor"
|
|
418
|
+
|
|
419
|
+
def print_report(self, report: Dict) -> None:
|
|
420
|
+
"""Imprime relatório formatado."""
|
|
421
|
+
print("\n" + "="*70)
|
|
422
|
+
print(" PROF. EULER — ANÁLISE DE COMPLEXIDADE MATEMÁTICA")
|
|
423
|
+
print("="*70)
|
|
424
|
+
|
|
425
|
+
s = report['summary']
|
|
426
|
+
print(f"\n📊 RESUMO:")
|
|
427
|
+
print(f" Arquivos analisados: {s['total_files']}")
|
|
428
|
+
print(f" Funções analisadas: {s['total_functions']}")
|
|
429
|
+
print(f" Linhas de código: {s['total_code_lines']}")
|
|
430
|
+
print(f" Funções alta CC: {s['high_cc_functions']} (threshold={self.threshold})")
|
|
431
|
+
print(f" Funções alta cognitiva: {s['high_cognitive_functions']}")
|
|
432
|
+
|
|
433
|
+
if report['high_cyclomatic_complexity']:
|
|
434
|
+
print(f"\n⚠️ TOP FUNÇÕES POR COMPLEXIDADE CICLOMÁTICA:")
|
|
435
|
+
print(f" {'Função':<35} {'CC':>5} {'Arquivo':<40} Risco")
|
|
436
|
+
print(f" {'-'*35} {'-'*5} {'-'*40} {'-'*25}")
|
|
437
|
+
for item in report['high_cyclomatic_complexity'][:10]:
|
|
438
|
+
fname = item['function'][:34]
|
|
439
|
+
ffile = item['file'][:39]
|
|
440
|
+
print(f" {fname:<35} {item['cc']:>5} {ffile:<40} {item['risk']}")
|
|
441
|
+
|
|
442
|
+
if report['module_statistics']:
|
|
443
|
+
print(f"\n📦 ESTATÍSTICAS POR MÓDULO:")
|
|
444
|
+
print(f" {'Módulo':<20} {'Arquivos':>8} {'Funções':>8} {'CC Médio':>10} {'CC Máximo':>10} {'Instabilidade':>14}")
|
|
445
|
+
print(f" {'-'*20} {'-'*8} {'-'*8} {'-'*10} {'-'*10} {'-'*14}")
|
|
446
|
+
coupling = report['module_coupling']
|
|
447
|
+
for mod, stats in sorted(report['module_statistics'].items()):
|
|
448
|
+
inst = coupling.get(mod, {}).get('instability', 'N/A')
|
|
449
|
+
inst_str = f"{inst:.3f}" if isinstance(inst, float) else inst
|
|
450
|
+
print(f" {mod:<20} {stats['files']:>8} {stats['functions']:>8} "
|
|
451
|
+
f"{stats['avg_cc']:>10.2f} {stats['max_cc']:>10} {inst_str:>14}")
|
|
452
|
+
|
|
453
|
+
if report['coroutine_issues']:
|
|
454
|
+
print(f"\n🔄 PROBLEMAS POTENCIAIS EM COROUTINES:")
|
|
455
|
+
for item in report['coroutine_issues'][:5]:
|
|
456
|
+
print(f" ⚠️ {item['function']} ({item['file']})")
|
|
457
|
+
print(f" → {item['note']}")
|
|
458
|
+
|
|
459
|
+
if report['nullable_risks']:
|
|
460
|
+
print(f"\n❓ NULLABLE RISKS (muitos parâmetros nullable):")
|
|
461
|
+
for item in report['nullable_risks'][:5]:
|
|
462
|
+
print(f" {item['function']}: {item['nullable_params']} nullable params ({item['file']})")
|
|
463
|
+
|
|
464
|
+
print("\n" + "="*70)
|
|
465
|
+
print(" Análise matemática completa. Consulte Prof. Euler para interpretação.")
|
|
466
|
+
print("="*70 + "\n")
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
def main():
|
|
470
|
+
parser = argparse.ArgumentParser(
|
|
471
|
+
description='Prof. Euler — Análise de Complexidade Matemática para Kotlin/Android'
|
|
472
|
+
)
|
|
473
|
+
parser.add_argument('path', nargs='?',
|
|
474
|
+
default=r'C:\Users\renat\earbudllm',
|
|
475
|
+
help='Caminho raiz do projeto')
|
|
476
|
+
parser.add_argument('--module', '-m', help='Analisar apenas este módulo')
|
|
477
|
+
parser.add_argument('--threshold', '-t', type=int, default=10,
|
|
478
|
+
help='Threshold de complexidade ciclomática (default: 10)')
|
|
479
|
+
parser.add_argument('--json', '-j', action='store_true',
|
|
480
|
+
help='Saída em formato JSON')
|
|
481
|
+
parser.add_argument('--output', '-o', help='Salvar relatório em arquivo')
|
|
482
|
+
|
|
483
|
+
args = parser.parse_args()
|
|
484
|
+
|
|
485
|
+
print(f"🔬 Prof. Euler analisando: {args.path}")
|
|
486
|
+
if args.module:
|
|
487
|
+
print(f" Módulo: {args.module}")
|
|
488
|
+
|
|
489
|
+
analyzer = KotlinComplexityAnalyzer(args.path, threshold=args.threshold)
|
|
490
|
+
analyzer.analyze(module_filter=args.module)
|
|
491
|
+
|
|
492
|
+
report = analyzer.generate_report()
|
|
493
|
+
|
|
494
|
+
if args.json:
|
|
495
|
+
output = json.dumps(report, indent=2, ensure_ascii=False)
|
|
496
|
+
print(output)
|
|
497
|
+
else:
|
|
498
|
+
analyzer.print_report(report)
|
|
499
|
+
|
|
500
|
+
if args.output:
|
|
501
|
+
output_path = Path(args.output)
|
|
502
|
+
if args.json:
|
|
503
|
+
output_path.write_text(json.dumps(report, indent=2, ensure_ascii=False))
|
|
504
|
+
else:
|
|
505
|
+
# Salvar como markdown
|
|
506
|
+
save_as_markdown(report, output_path, args.threshold)
|
|
507
|
+
print(f"✅ Relatório salvo em: {args.output}")
|
|
508
|
+
|
|
509
|
+
return report
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
def save_as_markdown(report: Dict, path: Path, threshold: int) -> None:
|
|
513
|
+
"""Salva relatório em formato Markdown."""
|
|
514
|
+
lines = [
|
|
515
|
+
"# Prof. Euler — Relatório de Complexidade Matemática\n",
|
|
516
|
+
f"Threshold CC: {threshold}\n\n",
|
|
517
|
+
"## Resumo\n",
|
|
518
|
+
f"- **Arquivos**: {report['summary']['total_files']}\n",
|
|
519
|
+
f"- **Funções**: {report['summary']['total_functions']}\n",
|
|
520
|
+
f"- **Linhas de código**: {report['summary']['total_code_lines']}\n",
|
|
521
|
+
f"- **Alta CC**: {report['summary']['high_cc_functions']}\n\n",
|
|
522
|
+
"## Funções de Alta Complexidade Ciclomática\n",
|
|
523
|
+
"| Função | CC | Arquivo | Risco |\n",
|
|
524
|
+
"|--------|-----|---------|-------|\n",
|
|
525
|
+
]
|
|
526
|
+
for item in report['high_cyclomatic_complexity'][:15]:
|
|
527
|
+
lines.append(
|
|
528
|
+
f"| `{item['function']}` | {item['cc']} | `{item['file']}` | {item['risk']} |\n"
|
|
529
|
+
)
|
|
530
|
+
|
|
531
|
+
lines.append("\n## Acoplamento de Módulos\n")
|
|
532
|
+
lines.append("| Módulo | Ca | Ce | Instabilidade | Depende de |\n")
|
|
533
|
+
lines.append("|--------|----|----|--------------|------------|\n")
|
|
534
|
+
for mod, data in sorted(report['module_coupling'].items()):
|
|
535
|
+
deps = ', '.join(data['depends_on']) or 'nenhum'
|
|
536
|
+
lines.append(
|
|
537
|
+
f"| {mod} | {data['Ca']} | {data['Ce']} | {data['instability']:.3f} | {deps} |\n"
|
|
538
|
+
)
|
|
539
|
+
|
|
540
|
+
path.write_text(''.join(lines), encoding='utf-8')
|
|
541
|
+
|
|
542
|
+
|
|
543
|
+
if __name__ == '__main__':
|
|
544
|
+
main()
|