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,134 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Analyzer cross-skill.
|
|
3
|
+
|
|
4
|
+
Identifica padroes compartilhados entre skills que poderiam ser
|
|
5
|
+
extraidos em modulos comuns, reducindo duplicacao.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import re
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Any, Dict, List, Tuple
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def analyze_cross_skill(all_skills: List[Dict[str, Any]]) -> Tuple[float, List[Dict[str, Any]]]:
|
|
15
|
+
"""
|
|
16
|
+
Analisa padroes cross-skill. Diferente dos outros analyzers,
|
|
17
|
+
recebe TODAS as skills e retorna findings globais.
|
|
18
|
+
Retorna (score_medio, findings).
|
|
19
|
+
"""
|
|
20
|
+
findings: List[Dict[str, Any]] = []
|
|
21
|
+
|
|
22
|
+
if len(all_skills) < 2:
|
|
23
|
+
return 100.0, findings
|
|
24
|
+
|
|
25
|
+
# -- 1. Detectar modulos duplicados (mesmo nome de arquivo em multiplas skills) ---
|
|
26
|
+
module_presence: Dict[str, List[str]] = {}
|
|
27
|
+
for skill in all_skills:
|
|
28
|
+
for rel_path in skill.get("python_files", []):
|
|
29
|
+
filename = Path(rel_path).name
|
|
30
|
+
module_presence.setdefault(filename, []).append(skill["name"])
|
|
31
|
+
|
|
32
|
+
shared_modules = {k: v for k, v in module_presence.items() if len(v) > 1}
|
|
33
|
+
|
|
34
|
+
if shared_modules:
|
|
35
|
+
for module, skills in shared_modules.items():
|
|
36
|
+
if module in ("__init__.py", "requirements.txt"):
|
|
37
|
+
continue
|
|
38
|
+
findings.append({
|
|
39
|
+
"skill_name": "cross-skill",
|
|
40
|
+
"dimension": "cross_skill",
|
|
41
|
+
"severity": "medium",
|
|
42
|
+
"category": "duplicated_module",
|
|
43
|
+
"title": f"Modulo '{module}' presente em {len(skills)} skills",
|
|
44
|
+
"description": f"Skills: {', '.join(skills)}. "
|
|
45
|
+
"Potencial para extrair em modulo compartilhado.",
|
|
46
|
+
"recommendation": f"Avaliar se {module} pode ser extraido para uma lib compartilhada "
|
|
47
|
+
f"(ex: shared-core/scripts/{module})",
|
|
48
|
+
"effort": "medium",
|
|
49
|
+
"impact": "high",
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
# -- 2. Padroes de Database (mesmo pattern _connect) --------------------------
|
|
53
|
+
db_skills = [s for s in all_skills if s.get("has_db")]
|
|
54
|
+
if len(db_skills) > 1:
|
|
55
|
+
findings.append({
|
|
56
|
+
"skill_name": "cross-skill",
|
|
57
|
+
"dimension": "cross_skill",
|
|
58
|
+
"severity": "low",
|
|
59
|
+
"category": "shared_db_pattern",
|
|
60
|
+
"title": f"{len(db_skills)} skills com modulo db.py independente",
|
|
61
|
+
"description": f"Skills: {', '.join(s['name'] for s in db_skills)}. "
|
|
62
|
+
"Padrao Database._connect() com WAL mode eh repetido.",
|
|
63
|
+
"recommendation": "Criar classe BaseDatabase em shared-core com _connect(), "
|
|
64
|
+
"e cada skill herdar e definir apenas suas tabelas.",
|
|
65
|
+
"effort": "medium",
|
|
66
|
+
"impact": "medium",
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
# -- 3. Padroes de Config (mesmo pattern ROOT_DIR) ----------------------------
|
|
70
|
+
config_skills = [s for s in all_skills if s.get("has_config")]
|
|
71
|
+
if len(config_skills) > 1:
|
|
72
|
+
findings.append({
|
|
73
|
+
"skill_name": "cross-skill",
|
|
74
|
+
"dimension": "cross_skill",
|
|
75
|
+
"severity": "info",
|
|
76
|
+
"category": "shared_config_pattern",
|
|
77
|
+
"title": f"{len(config_skills)} skills com config.py similar",
|
|
78
|
+
"description": "Padrao de paths (ROOT_DIR, DATA_DIR, etc) repetido.",
|
|
79
|
+
"recommendation": "Considerar base_config.py compartilhado com paths padrao",
|
|
80
|
+
"effort": "low",
|
|
81
|
+
"impact": "low",
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
# -- 4. Skills sem governanca vs com governanca --------------------------------
|
|
85
|
+
gov_skills = [s for s in all_skills if s.get("has_governance")]
|
|
86
|
+
no_gov_skills = [s for s in all_skills if not s.get("has_governance")]
|
|
87
|
+
|
|
88
|
+
if gov_skills and no_gov_skills:
|
|
89
|
+
findings.append({
|
|
90
|
+
"skill_name": "cross-skill",
|
|
91
|
+
"dimension": "cross_skill",
|
|
92
|
+
"severity": "medium",
|
|
93
|
+
"category": "inconsistent_governance",
|
|
94
|
+
"title": "Governanca inconsistente entre skills",
|
|
95
|
+
"description": f"Com governanca: {', '.join(s['name'] for s in gov_skills)}. "
|
|
96
|
+
f"Sem governanca: {', '.join(s['name'] for s in no_gov_skills)}.",
|
|
97
|
+
"recommendation": "Padronizar governanca em todas as skills. "
|
|
98
|
+
"Extrair GovernanceManager para modulo compartilhado.",
|
|
99
|
+
"effort": "medium",
|
|
100
|
+
"impact": "high",
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
# -- 5. Padroes de export (json/csv/parquet) -----------------------------------
|
|
104
|
+
export_skills = []
|
|
105
|
+
for skill in all_skills:
|
|
106
|
+
for rel_path in skill.get("python_files", []):
|
|
107
|
+
if "export" in rel_path.lower():
|
|
108
|
+
export_skills.append(skill["name"])
|
|
109
|
+
break
|
|
110
|
+
|
|
111
|
+
if len(export_skills) > 1:
|
|
112
|
+
findings.append({
|
|
113
|
+
"skill_name": "cross-skill",
|
|
114
|
+
"dimension": "cross_skill",
|
|
115
|
+
"severity": "low",
|
|
116
|
+
"category": "shared_export_pattern",
|
|
117
|
+
"title": f"{len(export_skills)} skills com modulo de export",
|
|
118
|
+
"description": f"Skills: {', '.join(export_skills)}",
|
|
119
|
+
"recommendation": "Considerar export utils compartilhados (json/csv/parquet)",
|
|
120
|
+
"effort": "low",
|
|
121
|
+
"impact": "low",
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
# Score baseado na quantidade de duplicacao encontrada
|
|
125
|
+
score = 100.0
|
|
126
|
+
for f in findings:
|
|
127
|
+
if f["severity"] == "medium":
|
|
128
|
+
score -= 8
|
|
129
|
+
elif f["severity"] == "low":
|
|
130
|
+
score -= 3
|
|
131
|
+
elif f["severity"] == "info":
|
|
132
|
+
score -= 1
|
|
133
|
+
|
|
134
|
+
return max(0.0, min(100.0, score)), findings
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Analyzer de dependencias.
|
|
3
|
+
|
|
4
|
+
Verifica: requirements.txt existe, versoes pinadas, dependencias nao usadas,
|
|
5
|
+
dependencias importadas mas nao listadas.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import re
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Any, Dict, List, Set, Tuple
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _extract_imports(source: str) -> Set[str]:
|
|
15
|
+
"""Extrai nomes de pacotes importados de um arquivo Python."""
|
|
16
|
+
imports = set()
|
|
17
|
+
for match in re.finditer(r'^(?:import|from)\s+(\w+)', source, re.MULTILINE):
|
|
18
|
+
pkg = match.group(1)
|
|
19
|
+
# Ignorar stdlib e imports relativos
|
|
20
|
+
if pkg not in {
|
|
21
|
+
"os", "sys", "re", "json", "ast", "pathlib", "datetime", "typing",
|
|
22
|
+
"uuid", "hashlib", "sqlite3", "argparse", "collections", "functools",
|
|
23
|
+
"time", "math", "io", "csv", "logging", "traceback", "textwrap",
|
|
24
|
+
"urllib", "http", "shutil", "subprocess", "tempfile", "threading",
|
|
25
|
+
"concurrent", "asyncio", "dataclasses", "enum", "abc", "copy",
|
|
26
|
+
"config", "db", "governance", "scanner", "analyzers", # modulos internos
|
|
27
|
+
}:
|
|
28
|
+
imports.add(pkg)
|
|
29
|
+
return imports
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _normalize_pkg_name(name: str) -> str:
|
|
33
|
+
"""Normaliza nome de pacote para comparacao (- e _ sao equivalentes)."""
|
|
34
|
+
return name.lower().replace("-", "_")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def analyze(skill_data: Dict[str, Any]) -> Tuple[float, List[Dict[str, Any]]]:
|
|
38
|
+
"""Analisa dependencias de uma skill. Retorna (score, findings)."""
|
|
39
|
+
score = 100.0
|
|
40
|
+
findings: List[Dict[str, Any]] = []
|
|
41
|
+
skill_name = skill_data["name"]
|
|
42
|
+
skill_path = Path(skill_data["path"])
|
|
43
|
+
|
|
44
|
+
requirements = skill_data.get("requirements", [])
|
|
45
|
+
reqs_path = skill_path / "scripts" / "requirements.txt"
|
|
46
|
+
|
|
47
|
+
# Sem requirements.txt
|
|
48
|
+
if not reqs_path.exists():
|
|
49
|
+
# Se nao tem Python files, nao precisa
|
|
50
|
+
if skill_data.get("file_count", 0) > 0:
|
|
51
|
+
findings.append({
|
|
52
|
+
"skill_name": skill_name,
|
|
53
|
+
"dimension": "dependencies",
|
|
54
|
+
"severity": "medium",
|
|
55
|
+
"category": "missing_requirements",
|
|
56
|
+
"title": "requirements.txt nao encontrado",
|
|
57
|
+
"recommendation": "Criar scripts/requirements.txt com todas as dependencias",
|
|
58
|
+
"effort": "low",
|
|
59
|
+
"impact": "medium",
|
|
60
|
+
})
|
|
61
|
+
score -= 15
|
|
62
|
+
return max(0.0, score), findings
|
|
63
|
+
|
|
64
|
+
# Verificar versoes pinadas
|
|
65
|
+
unpinned = [r for r in requirements if not r.get("pinned")]
|
|
66
|
+
if unpinned and len(requirements) > 1:
|
|
67
|
+
names = ", ".join(r["name"] for r in unpinned[:5])
|
|
68
|
+
findings.append({
|
|
69
|
+
"skill_name": skill_name,
|
|
70
|
+
"dimension": "dependencies",
|
|
71
|
+
"severity": "low",
|
|
72
|
+
"category": "unpinned_versions",
|
|
73
|
+
"title": f"{len(unpinned)} dependencia(s) sem versao pinada",
|
|
74
|
+
"description": f"Pacotes sem ==: {names}",
|
|
75
|
+
"recommendation": "Pinar versoes com == para reproducibilidade (ex: requests==2.31.0)",
|
|
76
|
+
"effort": "low",
|
|
77
|
+
"impact": "medium",
|
|
78
|
+
})
|
|
79
|
+
score -= min(10, len(unpinned) * 2)
|
|
80
|
+
|
|
81
|
+
# Verificar deps importadas vs listadas
|
|
82
|
+
all_imports: Set[str] = set()
|
|
83
|
+
for rel_path in skill_data.get("python_files", []):
|
|
84
|
+
filepath = skill_path / rel_path
|
|
85
|
+
if not filepath.exists():
|
|
86
|
+
continue
|
|
87
|
+
try:
|
|
88
|
+
source = filepath.read_text(encoding="utf-8", errors="replace")
|
|
89
|
+
except OSError:
|
|
90
|
+
continue
|
|
91
|
+
all_imports.update(_extract_imports(source))
|
|
92
|
+
|
|
93
|
+
listed_names = {_normalize_pkg_name(r["name"]) for r in requirements}
|
|
94
|
+
|
|
95
|
+
# Importadas mas nao listadas (possivel dep faltando)
|
|
96
|
+
# Mapear nomes de import para nomes de pacote (alguns diferem)
|
|
97
|
+
import_to_pkg = {
|
|
98
|
+
"PIL": "pillow",
|
|
99
|
+
"cv2": "opencv_python",
|
|
100
|
+
"bs4": "beautifulsoup4",
|
|
101
|
+
"yaml": "pyyaml",
|
|
102
|
+
"dotenv": "python_dotenv",
|
|
103
|
+
"playwright": "playwright",
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
for imp in all_imports:
|
|
107
|
+
pkg_name = _normalize_pkg_name(import_to_pkg.get(imp, imp))
|
|
108
|
+
if pkg_name not in listed_names:
|
|
109
|
+
findings.append({
|
|
110
|
+
"skill_name": skill_name,
|
|
111
|
+
"dimension": "dependencies",
|
|
112
|
+
"severity": "low",
|
|
113
|
+
"category": "unlisted_dependency",
|
|
114
|
+
"title": f"Pacote '{imp}' importado mas nao em requirements.txt",
|
|
115
|
+
"recommendation": f"Adicionar {imp} ao requirements.txt",
|
|
116
|
+
"effort": "low",
|
|
117
|
+
"impact": "low",
|
|
118
|
+
})
|
|
119
|
+
score -= 2
|
|
120
|
+
|
|
121
|
+
return max(0.0, min(100.0, score)), findings
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Analyzer de documentacao.
|
|
3
|
+
|
|
4
|
+
Verifica completude do SKILL.md, secoes obrigatorias, frontmatter,
|
|
5
|
+
triggers, exemplos e cobertura de reference files.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import re
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Any, Dict, List, Tuple
|
|
12
|
+
|
|
13
|
+
from config import SKILL_MD_RECOMMENDED_SECTIONS, SKILL_MD_REQUIRED_SECTIONS
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _check_frontmatter(content: str) -> Dict[str, bool]:
|
|
17
|
+
"""Verifica presenca de campos no frontmatter YAML."""
|
|
18
|
+
has = {}
|
|
19
|
+
if content.startswith("---"):
|
|
20
|
+
end = content.find("---", 3)
|
|
21
|
+
if end > 0:
|
|
22
|
+
fm = content[3:end].lower()
|
|
23
|
+
has["name"] = "name:" in fm
|
|
24
|
+
has["description"] = "description:" in fm or "description:" in fm
|
|
25
|
+
has["version"] = "version:" in fm
|
|
26
|
+
return has
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _check_sections(content: str) -> Dict[str, bool]:
|
|
30
|
+
"""Verifica presenca de secoes recomendadas no corpo."""
|
|
31
|
+
lower = content.lower()
|
|
32
|
+
sections = {}
|
|
33
|
+
section_keywords = {
|
|
34
|
+
"instalacao": ["instalacao", "installation", "instalação", "setup", "pip install"],
|
|
35
|
+
"comandos": ["comandos", "commands", "uso", "usage", "cli", "como usar"],
|
|
36
|
+
"governanca": ["governanca", "governance", "governança", "rate limit", "audit"],
|
|
37
|
+
"referencias": ["referencias", "references", "referências", "reference"],
|
|
38
|
+
}
|
|
39
|
+
for key, keywords in section_keywords.items():
|
|
40
|
+
sections[key] = any(kw in lower for kw in keywords)
|
|
41
|
+
return sections
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _check_triggers(description: str) -> Dict[str, Any]:
|
|
45
|
+
"""Verifica se description tem triggers adequados."""
|
|
46
|
+
if not description:
|
|
47
|
+
return {"has_triggers": False, "trigger_count": 0}
|
|
48
|
+
# Contar palavras-chave de trigger
|
|
49
|
+
words = re.findall(r'\b\w+\b', description.lower())
|
|
50
|
+
return {
|
|
51
|
+
"has_triggers": len(words) > 10,
|
|
52
|
+
"trigger_count": len(words),
|
|
53
|
+
"has_bilingual": any(w in description.lower() for w in ["use when", "use esta", "triggers on"]),
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def analyze(skill_data: Dict[str, Any]) -> Tuple[float, List[Dict[str, Any]]]:
|
|
58
|
+
"""Analisa documentacao de uma skill. Retorna (score, findings)."""
|
|
59
|
+
score = 100.0
|
|
60
|
+
findings: List[Dict[str, Any]] = []
|
|
61
|
+
skill_name = skill_data["name"]
|
|
62
|
+
skill_path = Path(skill_data["path"])
|
|
63
|
+
|
|
64
|
+
skill_md = skill_path / "SKILL.md"
|
|
65
|
+
if not skill_md.exists():
|
|
66
|
+
findings.append({
|
|
67
|
+
"skill_name": skill_name,
|
|
68
|
+
"dimension": "documentation",
|
|
69
|
+
"severity": "critical",
|
|
70
|
+
"category": "missing_skill_md",
|
|
71
|
+
"title": "SKILL.md nao encontrado",
|
|
72
|
+
"recommendation": "Criar SKILL.md com frontmatter YAML e documentacao completa",
|
|
73
|
+
"effort": "medium",
|
|
74
|
+
"impact": "high",
|
|
75
|
+
})
|
|
76
|
+
return 0.0, findings
|
|
77
|
+
|
|
78
|
+
try:
|
|
79
|
+
content = skill_md.read_text(encoding="utf-8", errors="replace")
|
|
80
|
+
except OSError:
|
|
81
|
+
return 0.0, findings
|
|
82
|
+
|
|
83
|
+
lines = len(content.splitlines())
|
|
84
|
+
|
|
85
|
+
# Frontmatter
|
|
86
|
+
fm = _check_frontmatter(content)
|
|
87
|
+
if not fm.get("name"):
|
|
88
|
+
findings.append({
|
|
89
|
+
"skill_name": skill_name,
|
|
90
|
+
"dimension": "documentation",
|
|
91
|
+
"severity": "high",
|
|
92
|
+
"category": "missing_frontmatter_name",
|
|
93
|
+
"title": "Frontmatter sem campo 'name'",
|
|
94
|
+
"recommendation": "Adicionar 'name: skill-name' no frontmatter YAML",
|
|
95
|
+
"effort": "low",
|
|
96
|
+
"impact": "high",
|
|
97
|
+
})
|
|
98
|
+
score -= 20
|
|
99
|
+
|
|
100
|
+
if not fm.get("description"):
|
|
101
|
+
findings.append({
|
|
102
|
+
"skill_name": skill_name,
|
|
103
|
+
"dimension": "documentation",
|
|
104
|
+
"severity": "high",
|
|
105
|
+
"category": "missing_frontmatter_description",
|
|
106
|
+
"title": "Frontmatter sem campo 'description'",
|
|
107
|
+
"recommendation": "Adicionar 'description:' com trigger keywords no frontmatter YAML",
|
|
108
|
+
"effort": "medium",
|
|
109
|
+
"impact": "high",
|
|
110
|
+
})
|
|
111
|
+
score -= 20
|
|
112
|
+
|
|
113
|
+
if not fm.get("version"):
|
|
114
|
+
findings.append({
|
|
115
|
+
"skill_name": skill_name,
|
|
116
|
+
"dimension": "documentation",
|
|
117
|
+
"severity": "low",
|
|
118
|
+
"category": "missing_version",
|
|
119
|
+
"title": "Sem versao no frontmatter",
|
|
120
|
+
"recommendation": "Adicionar 'version: 1.0.0' no frontmatter YAML",
|
|
121
|
+
"effort": "low",
|
|
122
|
+
"impact": "low",
|
|
123
|
+
})
|
|
124
|
+
score -= 3
|
|
125
|
+
|
|
126
|
+
# Triggers
|
|
127
|
+
desc = skill_data.get("description", "")
|
|
128
|
+
trigger_info = _check_triggers(desc)
|
|
129
|
+
if not trigger_info["has_triggers"]:
|
|
130
|
+
findings.append({
|
|
131
|
+
"skill_name": skill_name,
|
|
132
|
+
"dimension": "documentation",
|
|
133
|
+
"severity": "medium",
|
|
134
|
+
"category": "weak_triggers",
|
|
135
|
+
"title": "Description com poucas palavras-chave de trigger",
|
|
136
|
+
"description": f"Apenas {trigger_info['trigger_count']} palavras. "
|
|
137
|
+
"Mais keywords = mais chance de ativacao correta pelo Claude.",
|
|
138
|
+
"recommendation": "Expandir description com mais trigger keywords em PT-BR e EN",
|
|
139
|
+
"effort": "low",
|
|
140
|
+
"impact": "high",
|
|
141
|
+
})
|
|
142
|
+
score -= 10
|
|
143
|
+
|
|
144
|
+
# Secoes do corpo
|
|
145
|
+
sections = _check_sections(content)
|
|
146
|
+
for section_key in ["instalacao", "comandos", "governanca", "referencias"]:
|
|
147
|
+
if not sections.get(section_key):
|
|
148
|
+
findings.append({
|
|
149
|
+
"skill_name": skill_name,
|
|
150
|
+
"dimension": "documentation",
|
|
151
|
+
"severity": "low",
|
|
152
|
+
"category": f"missing_section_{section_key}",
|
|
153
|
+
"title": f"Secao '{section_key}' nao encontrada no SKILL.md",
|
|
154
|
+
"recommendation": f"Adicionar secao de {section_key} no SKILL.md",
|
|
155
|
+
"effort": "low",
|
|
156
|
+
"impact": "low",
|
|
157
|
+
})
|
|
158
|
+
score -= 3
|
|
159
|
+
|
|
160
|
+
# Reference files
|
|
161
|
+
ref_files = skill_data.get("reference_files", [])
|
|
162
|
+
if not ref_files and skill_data.get("has_references_dir"):
|
|
163
|
+
findings.append({
|
|
164
|
+
"skill_name": skill_name,
|
|
165
|
+
"dimension": "documentation",
|
|
166
|
+
"severity": "low",
|
|
167
|
+
"category": "empty_references",
|
|
168
|
+
"title": "Diretorio references/ vazio",
|
|
169
|
+
"recommendation": "Adicionar documentacao de referencia em references/",
|
|
170
|
+
"effort": "medium",
|
|
171
|
+
"impact": "low",
|
|
172
|
+
})
|
|
173
|
+
score -= 5
|
|
174
|
+
|
|
175
|
+
# SKILL.md tamanho: muito curto eh ruim
|
|
176
|
+
if lines < 20:
|
|
177
|
+
findings.append({
|
|
178
|
+
"skill_name": skill_name,
|
|
179
|
+
"dimension": "documentation",
|
|
180
|
+
"severity": "medium",
|
|
181
|
+
"category": "short_skill_md",
|
|
182
|
+
"title": f"SKILL.md muito curto ({lines} linhas)",
|
|
183
|
+
"recommendation": "Expandir SKILL.md com exemplos, workflows e detalhes de uso",
|
|
184
|
+
"effort": "medium",
|
|
185
|
+
"impact": "medium",
|
|
186
|
+
})
|
|
187
|
+
score -= 10
|
|
188
|
+
|
|
189
|
+
return max(0.0, min(100.0, score)), findings
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Analyzer de governanca.
|
|
3
|
+
|
|
4
|
+
Avalia maturidade de governanca: logging, rate limits, confirmacoes,
|
|
5
|
+
audit trail, alertas. Baseado no padrao de referencia do instagram/scripts/governance.py.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import re
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Any, Dict, List, Tuple
|
|
12
|
+
|
|
13
|
+
from config import GOVERNANCE_LEVELS
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _detect_governance_level(skill_data: Dict[str, Any], skill_path: Path) -> int:
|
|
17
|
+
"""Detecta nivel de maturidade de governanca."""
|
|
18
|
+
has_action_log = False
|
|
19
|
+
has_rate_limit = False
|
|
20
|
+
has_confirmation = False
|
|
21
|
+
has_warnings = False
|
|
22
|
+
|
|
23
|
+
for rel_path in skill_data.get("python_files", []):
|
|
24
|
+
filepath = skill_path / rel_path
|
|
25
|
+
if not filepath.exists():
|
|
26
|
+
continue
|
|
27
|
+
try:
|
|
28
|
+
source = filepath.read_text(encoding="utf-8", errors="replace")
|
|
29
|
+
except OSError:
|
|
30
|
+
continue
|
|
31
|
+
|
|
32
|
+
if re.search(r'(?:action_log|log_action|audit_log)', source, re.I):
|
|
33
|
+
has_action_log = True
|
|
34
|
+
if re.search(r'(?:rate_limit|check_rate|RateLimitExceeded)', source, re.I):
|
|
35
|
+
has_rate_limit = True
|
|
36
|
+
if re.search(r'(?:requires_confirmation|confirmation_request|--confirm)', source, re.I):
|
|
37
|
+
has_confirmation = True
|
|
38
|
+
if re.search(r'(?:warning_threshold|RATE_LIMIT_WARNING|warnings?\s*\.append)', source, re.I):
|
|
39
|
+
has_warnings = True
|
|
40
|
+
|
|
41
|
+
if has_action_log and has_rate_limit and has_confirmation and has_warnings:
|
|
42
|
+
return 4
|
|
43
|
+
elif has_action_log and has_rate_limit and has_confirmation:
|
|
44
|
+
return 3
|
|
45
|
+
elif has_action_log and has_rate_limit:
|
|
46
|
+
return 2
|
|
47
|
+
elif has_action_log:
|
|
48
|
+
return 1
|
|
49
|
+
return 0
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def analyze(skill_data: Dict[str, Any]) -> Tuple[float, List[Dict[str, Any]]]:
|
|
53
|
+
"""Analisa governanca de uma skill. Retorna (score, findings)."""
|
|
54
|
+
findings: List[Dict[str, Any]] = []
|
|
55
|
+
skill_name = skill_data["name"]
|
|
56
|
+
skill_path = Path(skill_data["path"])
|
|
57
|
+
|
|
58
|
+
level = _detect_governance_level(skill_data, skill_path)
|
|
59
|
+
score = level * 25.0 # 0=0, 1=25, 2=50, 3=75, 4=100
|
|
60
|
+
|
|
61
|
+
# Findings baseados no nivel
|
|
62
|
+
if level == 0:
|
|
63
|
+
findings.append({
|
|
64
|
+
"skill_name": skill_name,
|
|
65
|
+
"dimension": "governance",
|
|
66
|
+
"severity": "high",
|
|
67
|
+
"category": "no_governance",
|
|
68
|
+
"title": "Sem modulo de governanca",
|
|
69
|
+
"description": "A skill nao tem nenhum mecanismo de governanca. "
|
|
70
|
+
"Isso significa que acoes nao sao rastreadas e nao ha controle de taxa.",
|
|
71
|
+
"recommendation": "Criar governance.py com GovernanceManager (action log + rate limiting). "
|
|
72
|
+
"Referenciar instagram/scripts/governance.py como modelo.",
|
|
73
|
+
"effort": "medium",
|
|
74
|
+
"impact": "high",
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
if level < 2:
|
|
78
|
+
findings.append({
|
|
79
|
+
"skill_name": skill_name,
|
|
80
|
+
"dimension": "governance",
|
|
81
|
+
"severity": "medium",
|
|
82
|
+
"category": "no_rate_limiting",
|
|
83
|
+
"title": "Sem rate limiting",
|
|
84
|
+
"description": "Chamadas API nao tem controle de taxa, risco de bloqueio por excesso de uso.",
|
|
85
|
+
"recommendation": "Implementar check_rate_limit() antes de chamadas a APIs externas",
|
|
86
|
+
"effort": "medium",
|
|
87
|
+
"impact": "high",
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
if level < 3:
|
|
91
|
+
has_destructive = False
|
|
92
|
+
for rel_path in skill_data.get("python_files", []):
|
|
93
|
+
filepath = skill_path / rel_path
|
|
94
|
+
if not filepath.exists():
|
|
95
|
+
continue
|
|
96
|
+
try:
|
|
97
|
+
source = filepath.read_text(encoding="utf-8", errors="replace")
|
|
98
|
+
except OSError:
|
|
99
|
+
continue
|
|
100
|
+
if re.search(r'(?:delete|publish|send|post|remove)', source, re.I):
|
|
101
|
+
has_destructive = True
|
|
102
|
+
break
|
|
103
|
+
|
|
104
|
+
if has_destructive:
|
|
105
|
+
findings.append({
|
|
106
|
+
"skill_name": skill_name,
|
|
107
|
+
"dimension": "governance",
|
|
108
|
+
"severity": "medium",
|
|
109
|
+
"category": "no_confirmation",
|
|
110
|
+
"title": "Acoes destrutivas sem confirmacao",
|
|
111
|
+
"description": "Skill tem acoes que modificam dados externos mas sem 2-step confirmation",
|
|
112
|
+
"recommendation": "Implementar padrao de confirmacao: requires_confirmation() + create_confirmation_request()",
|
|
113
|
+
"effort": "medium",
|
|
114
|
+
"impact": "high",
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
if level >= 3:
|
|
118
|
+
# Bonus: verificar se o audit log tem consulta
|
|
119
|
+
has_cli = False
|
|
120
|
+
for rel_path in skill_data.get("python_files", []):
|
|
121
|
+
filepath = skill_path / rel_path
|
|
122
|
+
if not filepath.exists():
|
|
123
|
+
continue
|
|
124
|
+
try:
|
|
125
|
+
source = filepath.read_text(encoding="utf-8", errors="replace")
|
|
126
|
+
except OSError:
|
|
127
|
+
continue
|
|
128
|
+
if "get_recent_actions" in source or "__main__" in source:
|
|
129
|
+
has_cli = True
|
|
130
|
+
|
|
131
|
+
if not has_cli:
|
|
132
|
+
findings.append({
|
|
133
|
+
"skill_name": skill_name,
|
|
134
|
+
"dimension": "governance",
|
|
135
|
+
"severity": "info",
|
|
136
|
+
"category": "no_audit_cli",
|
|
137
|
+
"title": "Audit log sem CLI de consulta",
|
|
138
|
+
"recommendation": "Adicionar modo CLI para consultar acoes recentes: python governance.py",
|
|
139
|
+
"effort": "low",
|
|
140
|
+
"impact": "low",
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
# Registrar nivel como info
|
|
144
|
+
findings.append({
|
|
145
|
+
"skill_name": skill_name,
|
|
146
|
+
"dimension": "governance",
|
|
147
|
+
"severity": "info",
|
|
148
|
+
"category": "governance_level",
|
|
149
|
+
"title": f"Nivel de governanca: {level} - {GOVERNANCE_LEVELS.get(level, '?')}",
|
|
150
|
+
"description": f"Maturidade de governanca detectada: nivel {level}/4",
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
return max(0.0, min(100.0, score)), findings
|