From 6b3a6f2698da37ca7edaa3009e35fb2a3fb5eac4 Mon Sep 17 00:00:00 2001 From: Emanuel Almeida Date: Thu, 12 Mar 2026 15:05:03 +0000 Subject: [PATCH] feat: refactor 30+ skills to Anthropic progressive disclosure pattern - All SKILL.md files now <500 lines (avg reduction 69%) - Detailed content extracted to references/ subdirectories - Frontmatter standardised: only name + description (Anthropic standard) - New skills: brand-guidelines, spec-coauthor, report-templates, skill-creator - Design skills: anti-slop guidelines, premium-proposals reference - Removed non-standard frontmatter fields (triggers, version, author, category) Plugins affected: infraestrutura, marketing, dev-tools, crm-ops, gestao, core-tools, negocio, perfex-dev, wordpress, design-media Co-Authored-By: Claude Opus 4.6 --- .claude-plugin/marketplace.json | 18 +- automacao/.claude-plugin/plugin.json | 4 +- automacao/agents/automation-lead.md | 24 +- automacao/agents/mcp-protocol-developer.md | 27 +- automacao/agents/n8n-automation-expert.md | 27 +- automacao/knowledge/datasets.json | 86 +- automacao/skills/moloni-api/SKILL.md | 6 +- automacao/skills/n8n-chatbot/SKILL.md | 22 + automacao/skills/n8n-health/SKILL.md | 22 + automacao/skills/n8n-notify/SKILL.md | 6 + automacao/skills/n8n-schedule/SKILL.md | 6 + automacao/skills/n8n-sync/SKILL.md | 6 + automacao/skills/n8n-webhook/SKILL.md | 5 + core-tools/skills/_core/SKILL.md | 9 +- .../skills/agent-context-injector/SKILL.md | 9 +- .../skills/component-generator/SKILL.md | 9 +- .../skills/db-maintenance-manager/SKILL.md | 9 +- .../skills/infrastructure-manager/SKILL.md | 8 +- core-tools/skills/metrics/SKILL.md | 550 +- .../references/dashboards-templates.md | 126 + .../skills/metrics/references/sql-queries.md | 77 + core-tools/skills/plugin-curator/SKILL.md | 8 +- core-tools/skills/plugin-manager/SKILL.md | 14 +- core-tools/skills/quality-validator/SKILL.md | 8 +- .../skills/relationship-manager/SKILL.md | 8 +- crm-ops/.claude-plugin/plugin.json | 2 +- crm-ops/agents/budget-proposal-specialist.md | 22 +- crm-ops/agents/lead-approach-strategist.md | 18 +- crm-ops/agents/lead-qualifier.md | 28 +- crm-ops/agents/sales-manager.md | 9 - crm-ops/knowledge/datasets.json | 30 +- crm-ops/skills/auto-expense/SKILL.md | 23 +- crm-ops/skills/billing-check/SKILL.md | 10 +- crm-ops/skills/crm-admin/SKILL.md | 10 +- crm-ops/skills/crm-ops/SKILL.md | 39 +- crm-ops/skills/crm/SKILL.md | 40 +- crm-ops/skills/desk/SKILL.md | 17 +- crm-ops/skills/expense/SKILL.md | 566 +-- .../expense/references/category-mapping.md | 187 + .../skills/expense/references/changelog.md | 56 + .../expense/references/ticket-processing.md | 75 + crm-ops/skills/invoice/SKILL.md | 14 +- crm-ops/skills/orcamento/SKILL.md | 720 +-- crm-ops/skills/proposal-deck/SKILL.md | 367 ++ crm-ops/skills/ticket-triage/SKILL.md | 22 +- crm-ops/skills/ticket/SKILL.md | 14 +- design-media/agents/ui-designer.md | 26 +- .../agents/video-production-specialist.md | 17 +- design-media/agents/web-designer.md | 28 +- design-media/knowledge/datasets.json | 46 +- design-media/skills/brand-guidelines/SKILL.md | 318 ++ .../references/color-palettes.md | 227 + .../references/descomplicar-theme.md | 188 + design-media/skills/design/SKILL.md | 49 +- .../design/references/premium-proposals.md | 289 ++ dev-tools/.claude-plugin/plugin.json | 2 +- .../agents/database-design-specialist.md | 25 +- dev-tools/agents/dev-helper.md | 29 +- dev-tools/agents/development-lead.md | 24 +- .../agents/javascript-fullstack-specialist.md | 26 +- dev-tools/agents/nextjs-specialist.md | 13 +- dev-tools/agents/php-fullstack-engineer.md | 9 - dev-tools/knowledge/datasets.json | 74 +- dev-tools/skills/chrome/SKILL.md | 6 +- dev-tools/skills/db-design/SKILL.md | 9 +- .../{security-check => dep-audit}/SKILL.md | 47 +- dev-tools/skills/docx/SKILL.md | 512 ++ dev-tools/skills/docx/scripts/__init__.py | 1 + .../skills/docx/scripts/accept_changes.py | 135 + dev-tools/skills/docx/scripts/comment.py | 318 ++ .../docx/scripts/office/helpers/__init__.py | 0 .../docx/scripts/office/helpers/merge_runs.py | 199 + .../office/helpers/simplify_redlines.py | 197 + dev-tools/skills/docx/scripts/office/pack.py | 159 + .../schemas/ISO-IEC29500-4_2016/dml-chart.xsd | 1499 ++++++ .../ISO-IEC29500-4_2016/dml-chartDrawing.xsd | 146 + .../ISO-IEC29500-4_2016/dml-diagram.xsd | 1085 ++++ .../ISO-IEC29500-4_2016/dml-lockedCanvas.xsd | 11 + .../schemas/ISO-IEC29500-4_2016/dml-main.xsd | 3081 ++++++++++++ .../ISO-IEC29500-4_2016/dml-picture.xsd | 23 + .../dml-spreadsheetDrawing.xsd | 185 + .../dml-wordprocessingDrawing.xsd | 287 ++ .../schemas/ISO-IEC29500-4_2016/pml.xsd | 1676 +++++++ .../shared-additionalCharacteristics.xsd | 28 + .../shared-bibliography.xsd | 144 + .../shared-commonSimpleTypes.xsd | 174 + .../shared-customXmlDataProperties.xsd | 25 + .../shared-customXmlSchemaProperties.xsd | 18 + .../shared-documentPropertiesCustom.xsd | 59 + .../shared-documentPropertiesExtended.xsd | 56 + .../shared-documentPropertiesVariantTypes.xsd | 195 + .../ISO-IEC29500-4_2016/shared-math.xsd | 582 +++ .../shared-relationshipReference.xsd | 25 + .../schemas/ISO-IEC29500-4_2016/sml.xsd | 4439 +++++++++++++++++ .../schemas/ISO-IEC29500-4_2016/vml-main.xsd | 570 +++ .../ISO-IEC29500-4_2016/vml-officeDrawing.xsd | 509 ++ .../vml-presentationDrawing.xsd | 12 + .../vml-spreadsheetDrawing.xsd | 108 + .../vml-wordprocessingDrawing.xsd | 96 + .../schemas/ISO-IEC29500-4_2016/wml.xsd | 3646 ++++++++++++++ .../schemas/ISO-IEC29500-4_2016/xml.xsd | 116 + .../ecma/fouth-edition/opc-contentTypes.xsd | 42 + .../ecma/fouth-edition/opc-coreProperties.xsd | 50 + .../schemas/ecma/fouth-edition/opc-digSig.xsd | 49 + .../ecma/fouth-edition/opc-relationships.xsd | 33 + .../docx/scripts/office/schemas/mce/mc.xsd | 75 + .../office/schemas/microsoft/wml-2010.xsd | 560 +++ .../office/schemas/microsoft/wml-2012.xsd | 67 + .../office/schemas/microsoft/wml-2018.xsd | 14 + .../office/schemas/microsoft/wml-cex-2018.xsd | 20 + .../office/schemas/microsoft/wml-cid-2016.xsd | 13 + .../microsoft/wml-sdtdatahash-2020.xsd | 4 + .../schemas/microsoft/wml-symex-2015.xsd | 8 + .../skills/docx/scripts/office/soffice.py | 183 + .../skills/docx/scripts/office/unpack.py | 132 + .../skills/docx/scripts/office/validate.py | 111 + .../scripts/office/validators/__init__.py | 15 + .../docx/scripts/office/validators/base.py | 847 ++++ .../docx/scripts/office/validators/docx.py | 446 ++ .../docx/scripts/office/validators/pptx.py | 275 + .../scripts/office/validators/redlining.py | 247 + .../docx/scripts/templates/comments.xml | 3 + .../scripts/templates/commentsExtended.xml | 3 + .../scripts/templates/commentsExtensible.xml | 3 + .../docx/scripts/templates/commentsIds.xml | 3 + .../skills/docx/scripts/templates/people.xml | 3 + dev-tools/skills/nextjs/SKILL.md | 661 +-- .../nextjs/references/performance-rules.md | 245 + dev-tools/skills/pdf/SKILL.md | 796 +++ .../pdf/scripts/check_bounding_boxes.py | 65 + .../pdf/scripts/check_fillable_fields.py | 11 + .../pdf/scripts/convert_pdf_to_images.py | 33 + .../pdf/scripts/create_validation_image.py | 37 + .../pdf/scripts/extract_form_field_info.py | 122 + .../pdf/scripts/extract_form_structure.py | 115 + .../pdf/scripts/fill_fillable_fields.py | 98 + .../scripts/fill_pdf_form_with_annotations.py | 107 + dev-tools/skills/php-dev/SKILL.md | 38 +- dev-tools/skills/react-patterns/SKILL.md | 557 +-- .../references/composition-patterns.md | 183 + .../react-patterns/references/custom-hooks.md | 66 + dev-tools/skills/skill-creator/SKILL.md | 188 + .../references/anthropic-patterns.md | 258 + .../references/descomplicar-standards.md | 318 ++ .../references/output-patterns.md | 184 + .../skill-creator/references/workflows.md | 181 + dev-tools/skills/webapp-testing/SKILL.md | 146 + .../examples/console_logging.py | 35 + .../examples/element_discovery.py | 40 + .../examples/static_html_automation.py | 33 + .../webapp-testing/scripts/with_server.py | 106 + dev-tools/skills/xlsx/SKILL.md | 374 ++ .../xlsx/scripts/office/helpers/__init__.py | 0 .../xlsx/scripts/office/helpers/merge_runs.py | 199 + .../office/helpers/simplify_redlines.py | 197 + dev-tools/skills/xlsx/scripts/office/pack.py | 159 + .../schemas/ISO-IEC29500-4_2016/dml-chart.xsd | 1499 ++++++ .../ISO-IEC29500-4_2016/dml-chartDrawing.xsd | 146 + .../ISO-IEC29500-4_2016/dml-diagram.xsd | 1085 ++++ .../ISO-IEC29500-4_2016/dml-lockedCanvas.xsd | 11 + .../schemas/ISO-IEC29500-4_2016/dml-main.xsd | 3081 ++++++++++++ .../ISO-IEC29500-4_2016/dml-picture.xsd | 23 + .../dml-spreadsheetDrawing.xsd | 185 + .../dml-wordprocessingDrawing.xsd | 287 ++ .../schemas/ISO-IEC29500-4_2016/pml.xsd | 1676 +++++++ .../shared-additionalCharacteristics.xsd | 28 + .../shared-bibliography.xsd | 144 + .../shared-commonSimpleTypes.xsd | 174 + .../shared-customXmlDataProperties.xsd | 25 + .../shared-customXmlSchemaProperties.xsd | 18 + .../shared-documentPropertiesCustom.xsd | 59 + .../shared-documentPropertiesExtended.xsd | 56 + .../shared-documentPropertiesVariantTypes.xsd | 195 + .../ISO-IEC29500-4_2016/shared-math.xsd | 582 +++ .../shared-relationshipReference.xsd | 25 + .../schemas/ISO-IEC29500-4_2016/sml.xsd | 4439 +++++++++++++++++ .../schemas/ISO-IEC29500-4_2016/vml-main.xsd | 570 +++ .../ISO-IEC29500-4_2016/vml-officeDrawing.xsd | 509 ++ .../vml-presentationDrawing.xsd | 12 + .../vml-spreadsheetDrawing.xsd | 108 + .../vml-wordprocessingDrawing.xsd | 96 + .../schemas/ISO-IEC29500-4_2016/wml.xsd | 3646 ++++++++++++++ .../schemas/ISO-IEC29500-4_2016/xml.xsd | 116 + .../ecma/fouth-edition/opc-contentTypes.xsd | 42 + .../ecma/fouth-edition/opc-coreProperties.xsd | 50 + .../schemas/ecma/fouth-edition/opc-digSig.xsd | 49 + .../ecma/fouth-edition/opc-relationships.xsd | 33 + .../xlsx/scripts/office/schemas/mce/mc.xsd | 75 + .../office/schemas/microsoft/wml-2010.xsd | 560 +++ .../office/schemas/microsoft/wml-2012.xsd | 67 + .../office/schemas/microsoft/wml-2018.xsd | 14 + .../office/schemas/microsoft/wml-cex-2018.xsd | 20 + .../office/schemas/microsoft/wml-cid-2016.xsd | 13 + .../microsoft/wml-sdtdatahash-2020.xsd | 4 + .../schemas/microsoft/wml-symex-2015.xsd | 8 + .../skills/xlsx/scripts/office/soffice.py | 183 + .../skills/xlsx/scripts/office/unpack.py | 132 + .../skills/xlsx/scripts/office/validate.py | 111 + .../scripts/office/validators/__init__.py | 15 + .../xlsx/scripts/office/validators/base.py | 847 ++++ .../xlsx/scripts/office/validators/docx.py | 446 ++ .../xlsx/scripts/office/validators/pptx.py | 275 + .../scripts/office/validators/redlining.py | 247 + dev-tools/skills/xlsx/scripts/recalc.py | 184 + gestao/.claude-plugin/plugin.json | 2 +- gestao/agents/analytics-insights-agent.md | 27 +- gestao/agents/project-manager.md | 23 +- gestao/agents/reflect-agent.md | 10 +- gestao/agents/software-project-planner.md | 21 +- gestao/agents/wiki-knowledge-agent.md | 11 - gestao/knowledge/datasets.json | 64 +- gestao/skills/aiktop-tasks/SKILL.md | 14 +- gestao/skills/archive/SKILL.md | 11 +- gestao/skills/calendar-manager/SKILL.md | 520 +- .../references/mcp-tools-referencia.md | 81 + .../references/workflows-detalhados.md | 181 + gestao/skills/cleanup-downloads/SKILL.md | 3 +- gestao/skills/daily-digest/SKILL.md | 20 +- gestao/skills/delegate/SKILL.md | 10 +- gestao/skills/doc-coauthoring/SKILL.md | 442 ++ gestao/skills/imap-triage/SKILL.md | 22 +- gestao/skills/index-update/SKILL.md | 3 +- gestao/skills/knowledge/SKILL.md | 692 +-- .../knowledge/references/routing-guide.md | 309 ++ gestao/skills/mindmap/SKILL.md | 16 +- gestao/skills/notebooklm/SKILL.md | 16 +- gestao/skills/proc-creator/SKILL.md | 3 +- gestao/skills/reflect/SKILL.md | 21 +- gestao/skills/report-templates/SKILL.md | 185 + .../references/client-update.md | 173 + .../references/incident-report.md | 235 + .../references/monthly-review.md | 297 ++ .../references/project-status.md | 210 + gestao/skills/report/SKILL.md | 14 +- gestao/skills/spec-coauthor/SKILL.md | 340 ++ .../spec-coauthor/references/templates.md | 484 ++ gestao/skills/tasks-overview/SKILL.md | 20 +- gestao/skills/time/SKILL.md | 15 +- gestao/skills/today/SKILL.md | 197 +- gestao/skills/today/prompts/execute.md | 5 - gestao/skills/today/templates/daily-report.md | 13 - gestao/skills/validate-component/SKILL.md | 2 +- gestao/skills/worklog/SKILL.md | 43 +- infraestrutura/.claude-plugin/plugin.json | 2 +- infraestrutura/agents/backup-specialist.md | 24 +- infraestrutura/agents/cwp-server-manager.md | 13 +- infraestrutura/agents/easypanel-specialist.md | 27 +- infraestrutura/agents/proxmox-specialist.md | 20 +- .../agents/security-compliance-specialist.md | 23 +- infraestrutura/knowledge/datasets.json | 44 +- infraestrutura/skills/authentik/SKILL.md | 8 +- .../skills/backup-strategies/SKILL.md | 758 +-- .../backup-strategies/references/scripts.md | 297 ++ infraestrutura/skills/cwp-accounts/SKILL.md | 8 +- infraestrutura/skills/cwp-backup/SKILL.md | 8 +- infraestrutura/skills/cwp-email/SKILL.md | 8 +- infraestrutura/skills/cwp-php/SKILL.md | 27 +- infraestrutura/skills/cwp-scripts/SKILL.md | 26 +- infraestrutura/skills/cwp-security/SKILL.md | 27 +- infraestrutura/skills/cwp-ssl/SKILL.md | 8 +- infraestrutura/skills/cwp-webserver/SKILL.md | 8 +- infraestrutura/skills/easypanel-api/SKILL.md | 598 +-- .../references/service-config-api.md | 178 + .../easypanel-api/references/services-api.md | 100 + .../skills/easypanel-deploy/SKILL.md | 11 +- infraestrutura/skills/easypanel-init/SKILL.md | 13 +- .../skills/easypanel-monitor/SKILL.md | 281 ++ .../skills/easypanel-rollback/SKILL.md | 13 +- .../skills/easypanel-troubleshoot/SKILL.md | 14 +- .../skills/easypanel-validate/SKILL.md | 12 +- infraestrutura/skills/gateway-check/SKILL.md | 220 + infraestrutura/skills/infra-check/SKILL.md | 20 +- infraestrutura/skills/mcp-dev/SKILL.md | 1267 +---- .../mcp-dev/references/best-practices.md | 287 ++ .../mcp-dev/references/evaluation-guide.md | 280 ++ .../skills/mcp-dev/references/templates.md | 341 ++ infraestrutura/skills/pbs-config/SKILL.md | 482 +- .../pbs-config/references/pbs-avancado.md | 125 + .../references/pbs-setup-completo.md | 235 + .../skills/proxmox-cluster/SKILL.md | 32 +- infraestrutura/skills/proxmox-ha/SKILL.md | 444 +- .../proxmox-ha/references/failover-testing.md | 185 + .../references/fencing-configuration.md | 60 + infraestrutura/skills/proxmox-setup/SKILL.md | 465 +- .../references/installimage-zfs.md | 112 + .../references/networking-nat.md | 120 + infraestrutura/skills/security-audit/SKILL.md | 822 +-- .../references/owasp-checklist.md | 275 + .../references/report-template.md | 237 + infraestrutura/skills/security-check/SKILL.md | 320 ++ infraestrutura/skills/server-health/SKILL.md | 666 +-- .../server-health/references/commands.md | 232 + infraestrutura/skills/vm-migration/SKILL.md | 544 +- .../references/fase1-easypanel.md | 118 + .../vm-migration/references/fase2-cwp.md | 112 + .../vm-migration/references/fase3-cluster.md | 63 + .../references/troubleshooting.md | 48 + marketing/.claude-plugin/plugin.json | 2 +- marketing/agents/content-manager.md | 29 +- marketing/agents/copywriter.md | 27 +- marketing/agents/marketing-planning-expert.md | 10 - marketing/agents/ppc-specialist.md | 18 +- marketing/agents/seo-specialist.md | 22 +- marketing/agents/social-media-manager.md | 18 +- .../agents/video-production-specialist.md | 17 +- marketing/agents/youtube-specialist.md | 18 +- marketing/knowledge/datasets.json | 206 +- marketing/skills/ads/SKILL.md | 29 +- .../skills/content-marketing-pt/SKILL.md | 614 +-- .../references/copywriting-patterns.md | 112 + .../references/templates-conteudo.md | 129 + .../references/vocabulario-br-pt.md | 22 + marketing/skills/lead-approach/SKILL.md | 77 +- marketing/skills/marketing-strategy/SKILL.md | 566 +-- .../references/frameworks-estrategicos.md | 156 + .../references/marketing-mix-orcamento.md | 191 + marketing/skills/seo-audit/SKILL.md | 537 +- .../seo-audit/references/ferramentas-api.md | 94 + .../template-relatorio-auditoria.md | 195 + .../skills/seo-content-optimization/SKILL.md | 678 +-- .../references/structured-data.md | 270 + marketing/skills/seo-report/SKILL.md | 597 +-- .../references/implementacao-tecnica.md | 144 + .../references/template-relatorio.md | 220 + marketing/skills/social-media/SKILL.md | 565 +-- .../references/estrategias-crescimento.md | 180 + .../references/plataformas-formatos.md | 62 + marketing/skills/video/SKILL.md | 711 +-- .../skills/video/references/components.md | 274 + marketing/skills/youtube/SKILL.md | 642 +-- .../youtube/references/strategy-guide.md | 215 + metabase/knowledge/datasets.json | 5 - metabase/skills/dashboard/SKILL.md | 10 +- metabase/skills/metabase/SKILL.md | 9 +- metabase/skills/query/SKILL.md | 9 +- negocio/.claude-plugin/plugin.json | 2 +- negocio/agents/ecommerce-architect.md | 18 +- negocio/agents/finance-manager.md | 27 +- negocio/agents/research-analyst.md | 8 - negocio/agents/saas-architect.md | 17 +- negocio/knowledge/datasets.json | 60 +- negocio/skills/ecommerce/SKILL.md | 39 +- negocio/skills/interview/SKILL.md | 28 +- negocio/skills/product/SKILL.md | 494 +- .../product/references/metricas-produto.md | 83 + .../references/prioritization-frameworks.md | 78 + .../references/roadmap-sprint-templates.md | 162 + negocio/skills/research/SKILL.md | 508 +- .../research/references/frameworks-analise.md | 223 + .../references/recolha-dados-templates.md | 148 + negocio/skills/saas/SKILL.md | 513 +- .../skills/saas/references/metricas-kpis.md | 63 + .../skills/saas/references/multi-tenancy.md | 59 + .../skills/saas/references/pricing-billing.md | 137 + perfex-dev/.claude-plugin/plugin.json | 2 +- .../agents/perfex-crm-module-developer.md | 27 +- perfex-dev/knowledge/datasets.json | 20 +- perfex-dev/skills/perfex-controllers/SKILL.md | 7 +- perfex-dev/skills/perfex-database/SKILL.md | 7 +- perfex-dev/skills/perfex-forms/SKILL.md | 395 +- .../references/elementos-formulario.md | 159 + .../references/formulario-completo-exemplo.md | 141 + perfex-dev/skills/perfex-hooks/SKILL.md | 7 +- perfex-dev/skills/perfex-menus/SKILL.md | 7 +- perfex-dev/skills/perfex-migrations/SKILL.md | 7 +- .../skills/perfex-module-basics/SKILL.md | 7 +- perfex-dev/skills/perfex-permissions/SKILL.md | 7 +- perfex-dev/skills/perfex-security/SKILL.md | 7 +- perfex-dev/skills/perfex-views/SKILL.md | 7 +- project-manager/knowledge/datasets.json | 90 +- project-manager/skills/brainstorm/SKILL.md | 15 +- project-manager/skills/discover/SKILL.md | 15 +- project-manager/skills/scope/SKILL.md | 17 +- project-manager/skills/spec/SKILL.md | 33 +- project-manager/skills/sprint/SKILL.md | 36 +- project-manager/skills/status/SKILL.md | 17 +- wordpress/.claude-plugin/plugin.json | 2 +- wordpress/agents/elementor-specialist.md | 18 +- wordpress/agents/woocommerce-specialist.md | 17 +- .../wordpress-performance-specialist.md | 29 +- .../agents/wordpress-plugin-developer.md | 10 - wordpress/knowledge/datasets.json | 55 +- wordpress/skills/branda-menu/SKILL.md | 449 +- .../references/mapeamento-slugs.md | 100 + .../branda-menu/references/script-template.md | 174 + wordpress/skills/crocoblock/SKILL.md | 18 +- wordpress/skills/elementor/SKILL.md | 37 +- wordpress/skills/jetengine/SKILL.md | 19 +- wordpress/skills/rank-math/SKILL.md | 36 +- wordpress/skills/woocommerce-cli/SKILL.md | 14 +- wordpress/skills/woocommerce/SKILL.md | 42 +- wordpress/skills/wp-cli/SKILL.md | 12 +- wordpress/skills/wp-dev/SKILL.md | 112 +- wordpress/skills/wp-hardening/SKILL.md | 356 ++ wordpress/skills/wp-performance/SKILL.md | 29 +- wordpress/skills/wp-translate/SKILL.md | 13 +- wordpress/skills/wp-update/SKILL.md | 10 +- 397 files changed, 67154 insertions(+), 17257 deletions(-) create mode 100644 core-tools/skills/metrics/references/dashboards-templates.md create mode 100644 core-tools/skills/metrics/references/sql-queries.md create mode 100644 crm-ops/skills/expense/references/category-mapping.md create mode 100644 crm-ops/skills/expense/references/changelog.md create mode 100644 crm-ops/skills/expense/references/ticket-processing.md create mode 100644 crm-ops/skills/proposal-deck/SKILL.md create mode 100644 design-media/skills/brand-guidelines/SKILL.md create mode 100644 design-media/skills/brand-guidelines/references/color-palettes.md create mode 100644 design-media/skills/brand-guidelines/references/descomplicar-theme.md create mode 100644 design-media/skills/design/references/premium-proposals.md rename dev-tools/skills/{security-check => dep-audit}/SKILL.md (85%) create mode 100644 dev-tools/skills/docx/SKILL.md create mode 100755 dev-tools/skills/docx/scripts/__init__.py create mode 100644 dev-tools/skills/docx/scripts/accept_changes.py create mode 100644 dev-tools/skills/docx/scripts/comment.py create mode 100644 dev-tools/skills/docx/scripts/office/helpers/__init__.py create mode 100644 dev-tools/skills/docx/scripts/office/helpers/merge_runs.py create mode 100644 dev-tools/skills/docx/scripts/office/helpers/simplify_redlines.py create mode 100755 dev-tools/skills/docx/scripts/office/pack.py create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/mce/mc.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/microsoft/wml-2010.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/microsoft/wml-2012.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/microsoft/wml-2018.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/microsoft/wml-cex-2018.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/microsoft/wml-cid-2016.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd create mode 100644 dev-tools/skills/docx/scripts/office/schemas/microsoft/wml-symex-2015.xsd create mode 100644 dev-tools/skills/docx/scripts/office/soffice.py create mode 100755 dev-tools/skills/docx/scripts/office/unpack.py create mode 100755 dev-tools/skills/docx/scripts/office/validate.py create mode 100644 dev-tools/skills/docx/scripts/office/validators/__init__.py create mode 100644 dev-tools/skills/docx/scripts/office/validators/base.py create mode 100644 dev-tools/skills/docx/scripts/office/validators/docx.py create mode 100644 dev-tools/skills/docx/scripts/office/validators/pptx.py create mode 100644 dev-tools/skills/docx/scripts/office/validators/redlining.py create mode 100644 dev-tools/skills/docx/scripts/templates/comments.xml create mode 100644 dev-tools/skills/docx/scripts/templates/commentsExtended.xml create mode 100644 dev-tools/skills/docx/scripts/templates/commentsExtensible.xml create mode 100644 dev-tools/skills/docx/scripts/templates/commentsIds.xml create mode 100644 dev-tools/skills/docx/scripts/templates/people.xml create mode 100644 dev-tools/skills/nextjs/references/performance-rules.md create mode 100644 dev-tools/skills/pdf/SKILL.md create mode 100644 dev-tools/skills/pdf/scripts/check_bounding_boxes.py create mode 100644 dev-tools/skills/pdf/scripts/check_fillable_fields.py create mode 100644 dev-tools/skills/pdf/scripts/convert_pdf_to_images.py create mode 100644 dev-tools/skills/pdf/scripts/create_validation_image.py create mode 100644 dev-tools/skills/pdf/scripts/extract_form_field_info.py create mode 100644 dev-tools/skills/pdf/scripts/extract_form_structure.py create mode 100644 dev-tools/skills/pdf/scripts/fill_fillable_fields.py create mode 100644 dev-tools/skills/pdf/scripts/fill_pdf_form_with_annotations.py create mode 100644 dev-tools/skills/react-patterns/references/composition-patterns.md create mode 100644 dev-tools/skills/react-patterns/references/custom-hooks.md create mode 100644 dev-tools/skills/skill-creator/SKILL.md create mode 100644 dev-tools/skills/skill-creator/references/anthropic-patterns.md create mode 100644 dev-tools/skills/skill-creator/references/descomplicar-standards.md create mode 100644 dev-tools/skills/skill-creator/references/output-patterns.md create mode 100644 dev-tools/skills/skill-creator/references/workflows.md create mode 100644 dev-tools/skills/webapp-testing/SKILL.md create mode 100644 dev-tools/skills/webapp-testing/examples/console_logging.py create mode 100644 dev-tools/skills/webapp-testing/examples/element_discovery.py create mode 100644 dev-tools/skills/webapp-testing/examples/static_html_automation.py create mode 100755 dev-tools/skills/webapp-testing/scripts/with_server.py create mode 100644 dev-tools/skills/xlsx/SKILL.md create mode 100644 dev-tools/skills/xlsx/scripts/office/helpers/__init__.py create mode 100644 dev-tools/skills/xlsx/scripts/office/helpers/merge_runs.py create mode 100644 dev-tools/skills/xlsx/scripts/office/helpers/simplify_redlines.py create mode 100755 dev-tools/skills/xlsx/scripts/office/pack.py create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/mce/mc.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/microsoft/wml-2010.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/microsoft/wml-2012.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/microsoft/wml-2018.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/microsoft/wml-cex-2018.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/microsoft/wml-cid-2016.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/schemas/microsoft/wml-symex-2015.xsd create mode 100644 dev-tools/skills/xlsx/scripts/office/soffice.py create mode 100755 dev-tools/skills/xlsx/scripts/office/unpack.py create mode 100755 dev-tools/skills/xlsx/scripts/office/validate.py create mode 100644 dev-tools/skills/xlsx/scripts/office/validators/__init__.py create mode 100644 dev-tools/skills/xlsx/scripts/office/validators/base.py create mode 100644 dev-tools/skills/xlsx/scripts/office/validators/docx.py create mode 100644 dev-tools/skills/xlsx/scripts/office/validators/pptx.py create mode 100644 dev-tools/skills/xlsx/scripts/office/validators/redlining.py create mode 100644 dev-tools/skills/xlsx/scripts/recalc.py create mode 100644 gestao/skills/calendar-manager/references/mcp-tools-referencia.md create mode 100644 gestao/skills/calendar-manager/references/workflows-detalhados.md create mode 100644 gestao/skills/doc-coauthoring/SKILL.md create mode 100644 gestao/skills/knowledge/references/routing-guide.md create mode 100644 gestao/skills/report-templates/SKILL.md create mode 100644 gestao/skills/report-templates/references/client-update.md create mode 100644 gestao/skills/report-templates/references/incident-report.md create mode 100644 gestao/skills/report-templates/references/monthly-review.md create mode 100644 gestao/skills/report-templates/references/project-status.md create mode 100644 gestao/skills/spec-coauthor/SKILL.md create mode 100644 gestao/skills/spec-coauthor/references/templates.md create mode 100644 infraestrutura/skills/backup-strategies/references/scripts.md create mode 100644 infraestrutura/skills/easypanel-api/references/service-config-api.md create mode 100644 infraestrutura/skills/easypanel-api/references/services-api.md create mode 100644 infraestrutura/skills/easypanel-monitor/SKILL.md create mode 100644 infraestrutura/skills/gateway-check/SKILL.md create mode 100644 infraestrutura/skills/mcp-dev/references/best-practices.md create mode 100644 infraestrutura/skills/mcp-dev/references/evaluation-guide.md create mode 100644 infraestrutura/skills/mcp-dev/references/templates.md create mode 100644 infraestrutura/skills/pbs-config/references/pbs-avancado.md create mode 100644 infraestrutura/skills/pbs-config/references/pbs-setup-completo.md create mode 100644 infraestrutura/skills/proxmox-ha/references/failover-testing.md create mode 100644 infraestrutura/skills/proxmox-ha/references/fencing-configuration.md create mode 100644 infraestrutura/skills/proxmox-setup/references/installimage-zfs.md create mode 100644 infraestrutura/skills/proxmox-setup/references/networking-nat.md create mode 100644 infraestrutura/skills/security-audit/references/owasp-checklist.md create mode 100644 infraestrutura/skills/security-audit/references/report-template.md create mode 100644 infraestrutura/skills/security-check/SKILL.md create mode 100644 infraestrutura/skills/server-health/references/commands.md create mode 100644 infraestrutura/skills/vm-migration/references/fase1-easypanel.md create mode 100644 infraestrutura/skills/vm-migration/references/fase2-cwp.md create mode 100644 infraestrutura/skills/vm-migration/references/fase3-cluster.md create mode 100644 infraestrutura/skills/vm-migration/references/troubleshooting.md create mode 100644 marketing/skills/content-marketing-pt/references/copywriting-patterns.md create mode 100644 marketing/skills/content-marketing-pt/references/templates-conteudo.md create mode 100644 marketing/skills/content-marketing-pt/references/vocabulario-br-pt.md create mode 100644 marketing/skills/marketing-strategy/references/frameworks-estrategicos.md create mode 100644 marketing/skills/marketing-strategy/references/marketing-mix-orcamento.md create mode 100644 marketing/skills/seo-audit/references/ferramentas-api.md create mode 100644 marketing/skills/seo-audit/references/template-relatorio-auditoria.md create mode 100644 marketing/skills/seo-content-optimization/references/structured-data.md create mode 100644 marketing/skills/seo-report/references/implementacao-tecnica.md create mode 100644 marketing/skills/seo-report/references/template-relatorio.md create mode 100644 marketing/skills/social-media/references/estrategias-crescimento.md create mode 100644 marketing/skills/social-media/references/plataformas-formatos.md create mode 100644 marketing/skills/video/references/components.md create mode 100644 marketing/skills/youtube/references/strategy-guide.md create mode 100644 negocio/skills/product/references/metricas-produto.md create mode 100644 negocio/skills/product/references/prioritization-frameworks.md create mode 100644 negocio/skills/product/references/roadmap-sprint-templates.md create mode 100644 negocio/skills/research/references/frameworks-analise.md create mode 100644 negocio/skills/research/references/recolha-dados-templates.md create mode 100644 negocio/skills/saas/references/metricas-kpis.md create mode 100644 negocio/skills/saas/references/multi-tenancy.md create mode 100644 negocio/skills/saas/references/pricing-billing.md create mode 100644 perfex-dev/skills/perfex-forms/references/elementos-formulario.md create mode 100644 perfex-dev/skills/perfex-forms/references/formulario-completo-exemplo.md create mode 100644 wordpress/skills/branda-menu/references/mapeamento-slugs.md create mode 100644 wordpress/skills/branda-menu/references/script-template.md create mode 100644 wordpress/skills/wp-hardening/SKILL.md diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 800d712..638bdcd 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -9,7 +9,7 @@ { "name": "automacao", "source": "./automacao", - "description": "Process automation with n8n workflows, Moloni integration, Dify, Flowise, Typebot, Chatwoot and AI tools. Backed by 9 Dify KB datasets.", + "description": "Process automation with n8n workflows, Moloni integration, Flowise, Typebot, Chatwoot and AI tools. Backed by NotebookLM notebooks.", "version": "1.0.0", "author": { "name": "Descomplicar - Crescimento Digital", @@ -19,7 +19,7 @@ { "name": "crm-ops", "source": "./crm-ops", - "description": "CRM operations, sales management, leads, customers, estimates, invoices, tickets and expense tracking with Desk CRM. Backed by 2 Dify KB datasets.", + "description": "CRM operations, sales management, leads, customers, estimates, invoices, tickets and expense tracking with Desk CRM. Backed by NotebookLM notebooks.", "version": "1.0.0", "author": { "name": "Descomplicar - Crescimento Digital", @@ -39,7 +39,7 @@ { "name": "dev-tools", "source": "./dev-tools", - "description": "PHP, React, Next.js development, database design and frontend patterns. Backed by 7 Dify KB datasets.", + "description": "PHP, React, Next.js development, database design and frontend patterns. Backed by NotebookLM notebooks.", "version": "1.0.0", "author": { "name": "Descomplicar - Crescimento Digital", @@ -49,7 +49,7 @@ { "name": "gestao", "source": "./gestao", - "description": "Project management, time tracking, daily checkups, worklogs, reflections, knowledge management and archiving. Backed by 6 Dify KB datasets.", + "description": "Project management, time tracking, daily checkups, worklogs, reflections, knowledge management and archiving. Backed by NotebookLM notebooks.", "version": "1.0.0", "author": { "name": "Descomplicar - Crescimento Digital", @@ -69,7 +69,7 @@ { "name": "infraestrutura", "source": "./infraestrutura", - "description": "Server management, Proxmox VE/PBS/Clustering, CWP administration, EasyPanel deployments, security audits, backups and MCP development. Backed by 4 Dify KB datasets + NotebookLM Proxmox (150+ sources).", + "description": "Server management, Proxmox VE/PBS/Clustering, CWP administration, EasyPanel deployments, security audits, backups and MCP development. Backed by NotebookLM notebooks (Proxmox 150+ sources).", "version": "1.1.0", "author": { "name": "Descomplicar - Crescimento Digital", @@ -79,7 +79,7 @@ { "name": "marketing", "source": "./marketing", - "description": "Digital marketing strategy, SEO, content marketing, social media, ads, copywriting, video and YouTube. Backed by 25 Dify KB datasets including 10 marketing mentors.", + "description": "Digital marketing strategy, SEO, content marketing, social media, ads, copywriting, video and YouTube. Backed by NotebookLM notebooks.", "version": "1.0.0", "author": { "name": "Descomplicar - Crescimento Digital", @@ -89,7 +89,7 @@ { "name": "negocio", "source": "./negocio", - "description": "E-commerce architecture, SaaS strategy, product management, competitive research and financial management. Backed by 5 Dify KB datasets.", + "description": "E-commerce architecture, SaaS strategy, product management, competitive research and financial management. Backed by NotebookLM notebooks.", "version": "1.0.0", "author": { "name": "Descomplicar - Crescimento Digital", @@ -99,7 +99,7 @@ { "name": "perfex-dev", "source": "./perfex-dev", - "description": "Perfex CRM module development - controllers, views, forms, hooks, menus, migrations, permissions, security and database. Backed by 1 Dify KB dataset.", + "description": "Perfex CRM module development - controllers, views, forms, hooks, menus, migrations, permissions, security and database. Backed by NotebookLM notebooks.", "version": "1.0.0", "author": { "name": "Descomplicar - Crescimento Digital", @@ -119,7 +119,7 @@ { "name": "wordpress", "source": "./wordpress", - "description": "WordPress development, maintenance and optimization - plugins, themes, WooCommerce, Elementor, Crocoblock. Backed by 6 Dify KB datasets.", + "description": "WordPress development, maintenance and optimization - plugins, themes, WooCommerce, Elementor, Crocoblock. Backed by NotebookLM notebooks.", "version": "1.0.0", "author": { "name": "Descomplicar - Crescimento Digital", diff --git a/automacao/.claude-plugin/plugin.json b/automacao/.claude-plugin/plugin.json index 2823ef9..24dd9d4 100644 --- a/automacao/.claude-plugin/plugin.json +++ b/automacao/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "automacao", - "description": "Process automation with n8n workflows, Moloni integration, Dify, Flowise, Typebot, Chatwoot and AI tools. Backed by 9 Dify KB datasets.", + "description": "Process automation with n8n workflows, Moloni integration, Flowise, Typebot, Chatwoot and AI tools. Backed by NotebookLM notebooks.", "version": "1.0.0", "author": { "name": "Descomplicar - Crescimento Digital", @@ -8,5 +8,5 @@ }, "homepage": "https://git.descomplicar.pt/ealmeida/descomplicar-plugins", "license": "MIT", - "keywords": ["automacao", "n8n", "moloni", "dify", "workflows", "integracao"] + "keywords": ["automacao", "n8n", "moloni", "workflows", "integracao"] } diff --git a/automacao/agents/automation-lead.md b/automacao/agents/automation-lead.md index 4add6e6..743c0bb 100644 --- a/automacao/agents/automation-lead.md +++ b/automacao/agents/automation-lead.md @@ -159,15 +159,6 @@ mcp__notebooklm__notebook_query notebook_id:"ab876d0d-12a8-43d9-bc62-59c1c8e9d0f mcp__notebooklm__notebook_query notebook_id:"929ef67b-c131-4f01-abd0-8b078491a6b7" query:"LLM workflows deployment" ``` -### Dify KB (Secundario - se NotebookLM insuficiente) - -``` -mcp__dify-kb__dify_kb_retrieve_segments dataset:"n8n" query:"workflows automacao integracao" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Ferramentas de Automacao e IA" query:"AI agents orchestration" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Dify" query:"LLM workflows deployment" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Flowise" query:"chatbots automation" -``` - ## Your Available MCPs ### Recommended for automation @@ -177,16 +168,14 @@ mcp__dify-kb__dify_kb_retrieve_segments dataset:"Flowise" query:"chatbots automa - **gitea** - Repositórios Git, issues, PRs - **puppeteer** - Browser automation - **memory-supabase** - Memória longo prazo -- **dify-kb** - Knowledge base AI +- **** - Knowledge base AI - **filesystem** - Ficheiros locais -### All Available (33 total) +### All Available (32 total) moloni, context7, cwp, google-analytics, google-workspace, imap, outline-api, youtube-research, youtube-uploader, wikijs, gsc, lighthouse, mcp-time, mcp-mermaid, mcp-echarts, powerpoint, penpot, pixabay, pexels, tavily, elevenlabs, magic, vimeo, design-systems, replicate **Discovery:** Use ToolSearch to find specific tools. **Example:** `ToolSearch("ssh upload")` finds SSH upload tools. - - ## Your Available Skills ### Primary Skills (Your Domain) @@ -208,20 +197,16 @@ moloni, context7, cwp, google-analytics, google-workspace, imap, outline-api, yo - **/knowledge** - Gestão unificada de conhecimento - pesquisa inteligente com - **/desk** - Integração com Desk CRM via ficheiro .desk-project. Auto-det -### All Available (54 total) +### All Available (53 total) /billing-check, /crm-ops, /ecommerce, /lead-approach, /orcamento, /saas, /content-marketing-pt, /remotion-video, /seo-content-optimization, /social-media, /video, /ui-ux-pro-max-repo, /brand-voice-generator, /frontend-design, /pptx-generator, /ui-ux-pro-max, /crm-admin, /db-design, /elementor, /mcp-dev, /nextjs, /php-dev, /react-patterns, /woocommerce, /wp-dev, /backup-strategies, /security-audit, /server-health, /wp-performance, /wp-update, /second-brain-repo, /ads, /marketing-strategy, /product, /skill-creator, /sop-creator, /calendar-manager, /interview, /today, /research, /youtube, /seo-audit, /seo-report, /metrics **Discovery:** Use the Skill tool to invoke skills. **Example:** `Skill("skill-name")` invokes the skill. - - ## Colaboração - **Reports to**: CTO - **Colabora com**: N8N Automation Expert, MCP Protocol Developer, Development Lead, All department heads - **Escalar para**: CTO (decisões estratégicas), Security Compliance Specialist (segurança workflows) - - ## Your Team & Responsibilities You are part of **2 SDKs** (TaskForce teams): @@ -231,9 +216,6 @@ You are part of **2 SDKs** (TaskForce teams): **Purpose:** NULL **Your responsibilities in this TaskForce:** - -- **Sistema de agentes especializados para delegacao de tarefas via Task tool com consulta automatica de datasets Dify.**: NULL - ### TaskForce Claude Workflow **Purpose:** NULL diff --git a/automacao/agents/mcp-protocol-developer.md b/automacao/agents/mcp-protocol-developer.md index a1c1ef6..501b4ca 100644 --- a/automacao/agents/mcp-protocol-developer.md +++ b/automacao/agents/mcp-protocol-developer.md @@ -39,8 +39,6 @@ created: '2025-01-13' updated: '2026-02-04' author: Descomplicar® --- - - # MCP Protocol Developer Descomplicar Especialista em desenvolvimento, optimizacao e manutencao de servidores MCP e ferramentas customizadas que expandem o ecossistema Model Context Protocol. @@ -62,14 +60,6 @@ mcp__notebooklm__notebook_query notebook_id:"2876d1fe-5cea-4d98-8140-b0e1a81c6bc mcp__notebooklm__notebook_query notebook_id:"24947ffa-0019-448a-a340-2f4a275d2eb1" query:"typescript nodejs api development" ``` -### Dify KB (Secundario - se NotebookLM insuficiente) - -``` -mcp__dify-kb__dify_kb_retrieve_segments dataset:"MCP Servers" query:"protocol development tools integration" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Claude Code" query:"MCP server configuration" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Desenvolvimento de Software" query:"typescript nodejs api development" -``` - ## System Prompt ### Papel @@ -119,7 +109,7 @@ Especialista em desenvolvimento, optimizacao e manutencao de servidores MCP e fe ## MCPs Relevantes - `gitea`: Gestão de código MCP - `desk-crm-v3`: Tracking desenvolvimento (Proj #65, Milestone 256) -- `notebooklm`: KB primaria (Gemini 2.5 RAG) | `dify-kb`: KB MCP Servers, Claude Code, Desenvolvimento Software +- `notebooklm`: KB primaria (Gemini 2.5 RAG) | ``: KB MCP Servers, Claude Code, Desenvolvimento Software - `ssh-unified`: Deploy em servidores ## Colaboracao @@ -142,9 +132,9 @@ Especialista em desenvolvimento, optimizacao e manutencao de servidores MCP e fe - Usage: `mcp__ssh-unified__*` ✓ **notebooklm** (knowledge primaria) -✓ **dify-kb** (knowledge fallback) +✓ **** (knowledge fallback) - Knowledge base AI - - Usage: `mcp__dify-kb__*` + - Usage: `mcp____*` ### Recommended for dev - **context7** - Context documentation @@ -155,13 +145,11 @@ Especialista em desenvolvimento, optimizacao e manutencao de servidores MCP e fe - **cwp** - CentOS Web Panel - **puppeteer** - Browser automation -### All Available (33 total) +### All Available (32 total) moloni, google-analytics, google-workspace, imap, outline-api, youtube-research, youtube-uploader, wikijs, gsc, lighthouse, mcp-time, mcp-mermaid, mcp-echarts, powerpoint, penpot, pixabay, pexels, tavily, elevenlabs, vimeo, design-systems, replicate **Discovery:** Use ToolSearch to find specific tools. **Example:** `ToolSearch("ssh upload")` finds SSH upload tools. - - ## Your Available Skills ### Primary Skills (Your Domain) @@ -195,13 +183,11 @@ moloni, google-analytics, google-workspace, imap, outline-api, youtube-research, - **/knowledge** - Gestão unificada de conhecimento - pesquisa inteligente com - **/desk** - Integração com Desk CRM via ficheiro .desk-project. Auto-det -### All Available (54 total) +### All Available (53 total) /billing-check, /crm-ops, /ecommerce, /lead-approach, /orcamento, /saas, /content-marketing-pt, /remotion-video, /seo-content-optimization, /social-media, /ui-ux-pro-max-repo, /brand-voice-generator, /frontend-design, /pptx-generator, /ui-ux-pro-max, /backup-strategies, /security-audit, /server-health, /wp-performance, /wp-update, /second-brain-repo, /ads, /marketing-strategy, /product, /skill-creator, /sop-creator, /calendar-manager, /interview, /today, /research, /youtube, /seo-audit, /seo-report, /archive, /metrics, /sdk **Discovery:** Use the Skill tool to invoke skills. **Example:** `Skill("skill-name")` invokes the skill. - - ## Your Team & Responsibilities You are part of **2 SDKs** (TaskForce teams): @@ -211,9 +197,6 @@ You are part of **2 SDKs** (TaskForce teams): **Purpose:** NULL **Your responsibilities in this TaskForce:** - -- **Sistema de agentes especializados para delegacao de tarefas via Task tool com consulta automatica de datasets Dify.**: NULL - ### TaskForce MCP **Purpose:** NULL diff --git a/automacao/agents/n8n-automation-expert.md b/automacao/agents/n8n-automation-expert.md index cb3ad3d..ee87c62 100644 --- a/automacao/agents/n8n-automation-expert.md +++ b/automacao/agents/n8n-automation-expert.md @@ -38,8 +38,6 @@ created: '2025-01-13' updated: '2026-02-04' author: Descomplicar® --- - - # N8N Automation Expert Descomplicar Especialista em design, desenvolvimento e optimizacao de workflows automatizados usando N8N para automacao de processos e integracao seamless de sistemas. @@ -61,14 +59,6 @@ mcp__notebooklm__notebook_query notebook_id:"ab876d0d-12a8-43d9-bc62-59c1c8e9d0f mcp__notebooklm__notebook_query notebook_id:"929ef67b-c131-4f01-abd0-8b078491a6b7" query:"AI automation workflows" ``` -### Dify KB (Secundario - se NotebookLM insuficiente) - -``` -mcp__dify-kb__dify_kb_retrieve_segments dataset:"n8n" query:"workflow automation nodes triggers" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Ferramentas de Automacao e IA" query:"process automation integration" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Dify" query:"AI automation workflows" -``` - ## System Prompt ### Papel @@ -118,7 +108,7 @@ Especialista em design, desenvolvimento e optimizacao de workflows automatizados ## MCPs Relevantes - `desk-crm-v3`: Dados para automações (leads, tarefas) -- `notebooklm`: KB primaria (Gemini 2.5 RAG) | `dify-kb`: KB n8n, Ferramentas Automação, Dify +- `notebooklm`: KB primaria (Gemini 2.5 RAG) - `memory-supabase`: Histórico de workflows criados ## Colaboracao @@ -137,9 +127,9 @@ Especialista em design, desenvolvimento e optimizacao de workflows automatizados - Usage: `mcp__n8n__*` ✓ **notebooklm** (knowledge primaria) -✓ **dify-kb** (knowledge fallback) +✓ **** (knowledge fallback) - Knowledge base AI - - Usage: `mcp__dify-kb__*` + - Usage: `mcp____*` ✓ **memory-supabase** (system) - Memória longo prazo @@ -151,13 +141,11 @@ Especialista em design, desenvolvimento e optimizacao de workflows automatizados - **puppeteer** - Browser automation - **filesystem** - Ficheiros locais -### All Available (33 total) +### All Available (32 total) moloni, context7, cwp, google-analytics, google-workspace, imap, outline-api, youtube-research, youtube-uploader, wikijs, gsc, lighthouse, mcp-time, mcp-mermaid, mcp-echarts, powerpoint, penpot, pixabay, pexels, tavily, elevenlabs, magic, vimeo, design-systems, replicate **Discovery:** Use ToolSearch to find specific tools. **Example:** `ToolSearch("ssh upload")` finds SSH upload tools. - - ## Your Available Skills ### Primary Skills (Your Domain) @@ -179,13 +167,11 @@ moloni, context7, cwp, google-analytics, google-workspace, imap, outline-api, yo - **/knowledge** - Gestão unificada de conhecimento - pesquisa inteligente com - **/desk** - Integração com Desk CRM via ficheiro .desk-project. Auto-det -### All Available (54 total) +### All Available (53 total) /billing-check, /crm-ops, /ecommerce, /lead-approach, /orcamento, /saas, /content-marketing-pt, /remotion-video, /seo-content-optimization, /social-media, /video, /ui-ux-pro-max-repo, /brand-voice-generator, /frontend-design, /pptx-generator, /ui-ux-pro-max, /crm-admin, /db-design, /elementor, /mcp-dev, /nextjs, /php-dev, /react-patterns, /woocommerce, /wp-dev, /backup-strategies, /security-audit, /server-health, /wp-performance, /wp-update, /second-brain-repo, /ads, /marketing-strategy, /product, /skill-creator, /sop-creator, /calendar-manager, /interview, /today, /research, /youtube, /seo-audit, /seo-report, /metrics **Discovery:** Use the Skill tool to invoke skills. **Example:** `Skill("skill-name")` invokes the skill. - - ## Your Team & Responsibilities You are part of **2 SDKs** (TaskForce teams): @@ -195,9 +181,6 @@ You are part of **2 SDKs** (TaskForce teams): **Purpose:** NULL **Your responsibilities in this TaskForce:** - -- **Sistema de agentes especializados para delegacao de tarefas via Task tool com consulta automatica de datasets Dify.**: NULL - ### TaskForce Claude Workflow **Purpose:** NULL diff --git a/automacao/knowledge/datasets.json b/automacao/knowledge/datasets.json index 1a0da34..a81cae1 100644 --- a/automacao/knowledge/datasets.json +++ b/automacao/knowledge/datasets.json @@ -1,5 +1,5 @@ { - "description": "Knowledge sources (NotebookLM + Dify KB) for Automation domain", + "description": "Knowledge sources for Automation domain", "sources": { "notebooklm": { "description": "NotebookLM - conhecimento curado profundo via Gemini 2.5 RAG (PRIMARIO)", @@ -10,16 +10,13 @@ "title": "n8n", "topics": [ "n8n" - ], - "maps_from_dify": "n8n" + ] }, { "id": "929ef67b-c131-4f01-abd0-8b078491a6b7", "title": "AI Automation Stack", "topics": [ - "dify" - ], - "maps_from_dify": "Dify" + ] }, { "id": "be6f72ac-f8ba-4337-912d-abd5dd448519", @@ -27,8 +24,7 @@ "topics": [ "open", "webui" - ], - "maps_from_dify": "Open WebUI" + ] }, { "id": "ab876d0d-12a8-43d9-bc62-59c1c8e9d0f8", @@ -36,79 +32,9 @@ "topics": [ "ferramentas", "automacao" - ], - "maps_from_dify": "Ferramentas Automacao e IA" - } - ] - }, - "dify_kb": { - "description": "Dify KB - datasets tematicos (FALLBACK)", - "query_tool": "mcp__dify-kb__dify_kb_retrieve_segments", - "datasets": [ - { - "id": "f14521df-c44a-48f0-8703-b1d1cf77ca05", - "name": "n8n", - "priority": 1, - "document_count": 1, - "word_count": 206928 - }, - { - "id": "44d1517b-65b8-4d81-8253-5683ff0b8830", - "name": "Dify", - "priority": 1, - "document_count": 4, - "word_count": 1244175 - }, - { - "id": "b0a5e9e6-0d39-4e56-8c61-72c8e14ca41d", - "name": "Flowise", - "priority": 2, - "document_count": 3, - "word_count": 245565 - }, - { - "id": "b3e994c9-f642-4f23-a3db-8d9e344d489f", - "name": "Typebot", - "priority": 2, - "document_count": 1, - "word_count": 79608 - }, - { - "id": "728bed1f-79cb-4e56-aa8a-8dd961197354", - "name": "Chatwoot", - "priority": 2, - "document_count": 7, - "word_count": 149615 - }, - { - "id": "76f14ca9-7e11-4924-9ebc-ccd79876aa78", - "name": "Baserow", - "priority": 2, - "document_count": 1, - "word_count": 53665 - }, - { - "id": "ebf7e4aa-5d2c-49f0-bbb3-f73711a9e0b3", - "name": "Open WebUI", - "priority": 2, - "document_count": 3, - "word_count": 15266191 - }, - { - "id": "22f1d0cf-0661-4a5d-ad0e-b3c1cd2c234a", - "name": "Ferramentas Automacao e IA", - "priority": 1, - "document_count": 41, - "word_count": 805400 - }, - { - "id": "a8987108-2121-4e55-b055-67fe70f8aae0", - "name": "Moodle", - "priority": 3, - "document_count": 40, - "word_count": 764457 + ] } ] } } -} \ No newline at end of file +} diff --git a/automacao/skills/moloni-api/SKILL.md b/automacao/skills/moloni-api/SKILL.md index 2c4c251..0836fb3 100644 --- a/automacao/skills/moloni-api/SKILL.md +++ b/automacao/skills/moloni-api/SKILL.md @@ -1,10 +1,6 @@ --- name: moloni-api -description: >- - Moloni API v2 para facturacao portuguesa - autenticacao, documentos, clientes, produtos. - Usar quando trabalhar com Moloni API, criar/consultar facturas, recibos, notas de credito, - clientes, ou qualquer operacao de facturacao via Moloni. Triggers: moloni, factura, recibo, - nota de credito, billing, invoicing, facturacao portuguesa. +description: Referência da API Moloni v2 para facturação portuguesa — autenticação, documentos, clientes e produtos. --- # Moloni API v2 diff --git a/automacao/skills/n8n-chatbot/SKILL.md b/automacao/skills/n8n-chatbot/SKILL.md index 4fdca71..304ade8 100644 --- a/automacao/skills/n8n-chatbot/SKILL.md +++ b/automacao/skills/n8n-chatbot/SKILL.md @@ -1,7 +1,29 @@ +--- +name: n8n-chatbot +description: Criação de chatbots e workflows com inteligência artificial usando LangChain no n8n. +--- + # /n8n-chatbot - Chatbots e AI Agents n8n Criar chatbots e workflows com AI usando LangChain. +## Contexto NotebookLM + +ANTES de executar, consultar notebooks para contexto especializado: + +| Notebook | ID | Consultar quando | +|----------|-----|-----------------| +| n8n Deep Research | f2c809b8-1cb5-4dd0-aa7e-be2cfb6704d1 | Sempre | + +``` +mcp__notebooklm__notebook_query({ + notebook_id: "f2c809b8-1cb5-4dd0-aa7e-be2cfb6704d1", + query: "" +}) +``` + +Integrar insights do NotebookLM nas recomendações e decisões. + --- ## Uso diff --git a/automacao/skills/n8n-health/SKILL.md b/automacao/skills/n8n-health/SKILL.md index dffbf8f..7c41529 100644 --- a/automacao/skills/n8n-health/SKILL.md +++ b/automacao/skills/n8n-health/SKILL.md @@ -1,7 +1,29 @@ +--- +name: n8n-health +description: Diagnóstico de conectividade e estado da instância n8n. Verificação de saúde do sistema. +--- + # /n8n-health - Diagnóstico n8n Verificar conectividade e estado da instância n8n. +## Contexto NotebookLM + +ANTES de executar, consultar notebooks para contexto especializado: + +| Notebook | ID | Consultar quando | +|----------|-----|-----------------| +| n8n Deep Research | f2c809b8-1cb5-4dd0-aa7e-be2cfb6704d1 | Sempre | + +``` +mcp__notebooklm__notebook_query({ + notebook_id: "f2c809b8-1cb5-4dd0-aa7e-be2cfb6704d1", + query: "" +}) +``` + +Integrar insights do NotebookLM nas recomendações e decisões. + --- ## Uso diff --git a/automacao/skills/n8n-notify/SKILL.md b/automacao/skills/n8n-notify/SKILL.md index 1948307..59cfd04 100644 --- a/automacao/skills/n8n-notify/SKILL.md +++ b/automacao/skills/n8n-notify/SKILL.md @@ -1,3 +1,9 @@ +--- +name: n8n-notify +description: Criação de sistemas de notificações e alertas n8n via Slack, email e SMS. +disable-model-invocation: true +--- + # /n8n-notify - Notificações e Alertas n8n Criar sistemas de alertas via Slack, email, SMS. diff --git a/automacao/skills/n8n-schedule/SKILL.md b/automacao/skills/n8n-schedule/SKILL.md index c984957..cbba972 100644 --- a/automacao/skills/n8n-schedule/SKILL.md +++ b/automacao/skills/n8n-schedule/SKILL.md @@ -1,3 +1,9 @@ +--- +name: n8n-schedule +description: Criação de workflows n8n com execução agendada via cron para automações recorrentes. +disable-model-invocation: true +--- + # /n8n-schedule - Automações Agendadas n8n Criar workflows com execução agendada (cron). diff --git a/automacao/skills/n8n-sync/SKILL.md b/automacao/skills/n8n-sync/SKILL.md index 46b1d74..787efcd 100644 --- a/automacao/skills/n8n-sync/SKILL.md +++ b/automacao/skills/n8n-sync/SKILL.md @@ -1,3 +1,9 @@ +--- +name: n8n-sync +description: Sincronização de dados entre sistemas via workflows n8n. Mantém dados consistentes entre plataformas. +disable-model-invocation: true +--- + # /n8n-sync - Sincronização de Dados n8n Manter dados sincronizados entre sistemas. diff --git a/automacao/skills/n8n-webhook/SKILL.md b/automacao/skills/n8n-webhook/SKILL.md index 24373d1..f89db25 100644 --- a/automacao/skills/n8n-webhook/SKILL.md +++ b/automacao/skills/n8n-webhook/SKILL.md @@ -1,3 +1,8 @@ +--- +name: n8n-webhook +description: Criação e gestão de webhooks n8n para receber dados de sistemas externos. +--- + # /n8n-webhook - Webhooks n8n Criar e gerir webhooks para receber dados externos. diff --git a/core-tools/skills/_core/SKILL.md b/core-tools/skills/_core/SKILL.md index 4f3fe73..b45ddec 100644 --- a/core-tools/skills/_core/SKILL.md +++ b/core-tools/skills/_core/SKILL.md @@ -1,7 +1,7 @@ --- name: core-descomplicar -description: Padrões fundamentais Descomplicar® - Sacred Rules, Excellence Standards, MCP Protocol. Skill base para todos os agentes. -quality_score: 40 +description: Padrões fundamentais Descomplicar® — regras sagradas, standards de excelência e protocolo MCP. Skill base para todos os agentes. +user-invocable: false --- # Core Standards Descomplicar® @@ -42,6 +42,9 @@ Pedir esclarecimento quando incerto. ### 10. Crescimento contínuo Mentalidade de aprendizagem constante. +### 11. CWP: Zero Invenção (CLAUDE.md #38) +Sempre pesquisar wiki CWP e skills `/cwp-*` antes de qualquer operação CWP. Apenas scripts oficiais (`/scripts/*`). Nunca inventar comandos ou paths CWP sem verificação prévia. + --- ## 🎯 PADRÕES DE EXCELÊNCIA @@ -118,4 +121,4 @@ mcp__memory-supabase__save_memory { --- -*Core Standards v1.0 | 2026-01-27* +*Core Standards v1.1 | 2026-03-12* diff --git a/core-tools/skills/agent-context-injector/SKILL.md b/core-tools/skills/agent-context-injector/SKILL.md index 2c41908..5d3c655 100644 --- a/core-tools/skills/agent-context-injector/SKILL.md +++ b/core-tools/skills/agent-context-injector/SKILL.md @@ -1,12 +1,7 @@ --- name: agent-context-injector -description: > - Injecção dinâmica de contexto específico para cada agente. - Use when "contexto agente", "injectar", "SubagentStart", - "recursos agente", "mcps disponíveis", "skills relevantes". -author: Descomplicar® -version: 1.0.0 -desk_task: 1441 +description: Injecção dinâmica de contexto específico para cada agente — MCPs disponíveis, skills relevantes e datasets Dify. +user-invocable: false allowed-tools: Read, Glob, Grep, ToolSearch --- diff --git a/core-tools/skills/component-generator/SKILL.md b/core-tools/skills/component-generator/SKILL.md index 0e44b66..6f778e0 100644 --- a/core-tools/skills/component-generator/SKILL.md +++ b/core-tools/skills/component-generator/SKILL.md @@ -1,12 +1,7 @@ --- name: component-generator -description: > - Gera componentes Claude Code seguindo templates Descomplicar®. - Use when "criar skill", "criar agent", "novo componente", - "gerar template", "scaffolding", "criar command". -author: Descomplicar® -version: 1.0.0 -desk_task: 1441 +description: Gera componentes Claude Code (skills, agents, commands) seguindo templates Descomplicar® com ciclo criar, validar e registar. +disable-model-invocation: true allowed-tools: Read, Write, Edit, Glob, ToolSearch --- diff --git a/core-tools/skills/db-maintenance-manager/SKILL.md b/core-tools/skills/db-maintenance-manager/SKILL.md index d419e45..9411ef8 100644 --- a/core-tools/skills/db-maintenance-manager/SKILL.md +++ b/core-tools/skills/db-maintenance-manager/SKILL.md @@ -1,12 +1,7 @@ --- name: db-maintenance-manager -description: > - Manutenção automatizada das tabelas cr_* da infraestrutura Claude Code. - Use when "manutenção BD", "limpeza órfãos", "migração schema", - "backup tabelas", "archiving", "optimização BD", "database maintenance". -author: Descomplicar® -version: 1.0.0 -desk_task: 1441 +description: Manutenção automatizada das tabelas cr_* da infraestrutura Claude Code — limpeza de órfãos, migração de schema, backups e optimização. +disable-model-invocation: true allowed-tools: Read, Glob, Grep, ToolSearch --- diff --git a/core-tools/skills/infrastructure-manager/SKILL.md b/core-tools/skills/infrastructure-manager/SKILL.md index 4c356fe..b3a1659 100644 --- a/core-tools/skills/infrastructure-manager/SKILL.md +++ b/core-tools/skills/infrastructure-manager/SKILL.md @@ -1,12 +1,6 @@ --- name: infrastructure-manager -description: > - Gestão automatizada da infraestrutura Claude Code Descomplicar. - Use when "infraestrutura", "sistema", "componentes", "health", - "sincronização", "relacionamentos", "mcps", "skills", "agents". -author: Descomplicar® -version: 1.0.0 -desk_task: 1441 +description: Gestão automatizada da infraestrutura Claude Code Descomplicar — componentes, health, sincronização e relacionamentos entre MCPs, skills e agentes. allowed-tools: Read, Glob, Grep, ToolSearch --- diff --git a/core-tools/skills/metrics/SKILL.md b/core-tools/skills/metrics/SKILL.md index 0b6ad37..4ea9ab6 100644 --- a/core-tools/skills/metrics/SKILL.md +++ b/core-tools/skills/metrics/SKILL.md @@ -1,91 +1,68 @@ --- name: metrics -description: > - Performance metrics dashboard for skills and agents with quantitative telemetry. Automatic tracking, temporal trending, degradation alerts, Dify KB impact analysis and ROI calculation per client/project. - Use when analyzing performance, tracking improvements, validating PDCA cycles, calculating ROI, or when user mentions - "metrics", "performance", "dashboard", "analytics", "trending", "degradation", "baseline", "improvement", "roi calculation". -author: Descomplicar® Crescimento Digital -version: 1.3.0 -user_invocable: true -tags: [metrics, pdca, performance, dashboard, dify-kb, analytics, roi] -desk_project: 65 -desk_task: 1637 -allowed-tools: mcp__desk-crm-v3__get_skill_metrics, mcp__desk-crm-v3__log_skill_metric, Read -category: infra -quality_score: 85 -updated: "2026-02-04T18:00:00Z" +description: Dashboard de metricas de performance de skills e agentes com telemetria quantitativa, trending temporal, alertas de degradacao e calculo de ROI. --- # SKILL: Performance Metrics Dashboard -**Trigger:** `/metrics` +## Proposito ---- +Dashboard interactivo de performance de skills e agents com metricas quantitativas automaticas gravadas em Desk DB. -## Propósito - -Dashboard interactivo de performance de skills e agents com métricas quantitativas automáticas gravadas em Desk DB. - -**Complementa:** -- `/reflect` (qualitativo) com dados quantitativos -- `/worklog` com métricas objectivas -- PDCA com decisões data-driven +Complementa `/reflect` (qualitativo) com dados quantitativos, `/worklog` com metricas objectivas, e PDCA com decisoes data-driven. --- ## Quando Usar - Ver performance de skills/agents -- Identificar degradações de performance +- Identificar degradacoes de performance - Validar melhorias PDCA -- Análise ROI de optimizações -- Dashboard executivo de automação +- Analise ROI de optimizacoes +- Dashboard executivo de automacao --- -## Capabilities +## Comandos -### Tipos de Análise - -| Comando | Função | +| Comando | Funcao | |---------|--------| | `/metrics` | Overview geral (30 dias) | -| `/metrics ` | Detalhes de skill específica | -| `/metrics --project ` | Métricas por projecto | +| `/metrics ` | Detalhes de skill especifica | +| `/metrics --project ` | Metricas por projecto | | `/metrics --trend` | Trending temporal | -| `/metrics --compare` | Comparação vs baseline | -| `/metrics --kb` | **NOVO v1.2** Métricas Dify KB | -| `/metrics --roi` | **NOVO v1.2** ROI por cliente/projecto | -| `/metrics --export` | **NOVO v1.2** Exportar JSON/CSV | -| `/metrics --alerts` | **NOVO v1.2** Listar alertas activos | +| `/metrics --compare` | Comparacao vs baseline | +| `/metrics --kb` | Metricas Dify KB | +| `/metrics --roi` | ROI por cliente/projecto | +| `/metrics --export` | Exportar JSON/CSV | +| `/metrics --alerts` | Listar alertas activos | -### Agregações Disponíveis +### Agregacoes Disponiveis -1. **avg** - Médias de performance (padrão) +1. **avg** - Medias de performance (padrao) 2. **count** - Contagens por status -3. **trend** - Evolução temporal (semanal) -4. **compare** - Comparação com baseline +3. **trend** - Evolucao temporal (semanal) +4. **compare** - Comparacao com baseline 5. **detailed** - Listagem detalhada --- -## Execução +## Execucao -### 1. Verificar Tools MCP Disponíveis +### 1. Verificar Tools MCP ```javascript -// Tools necessários (MCP desk-crm-v3) +// Tools necessarios (MCP desk-crm-v3) const REQUIRED_TOOLS = [ 'mcp__desk-crm-v3__log_skill_metric', 'mcp__desk-crm-v3__get_skill_metrics' ]; - -// Se tools não disponíveis → query SQL directa como fallback +// Se tools nao disponiveis -> query SQL directa como fallback ``` -### 2. Query Métricas (Via MCP ou SQL) +### 2. Query Metricas -**Opção A: Via MCP (preferencial)** +**Via MCP (preferencial):** ```javascript const metrics = await mcp__desk_crm_v3__get_skill_metrics({ @@ -95,53 +72,22 @@ const metrics = await mcp__desk_crm_v3__get_skill_metrics({ }); ``` -**Opção B: Fallback SQL Directo** - -```sql --- Via MCP desk-crm-v3 SQL directo se tools metrics não disponíveis -SELECT - name, - type, - COUNT(*) as executions, - AVG(duration_ms) as avg_ms, - (SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) / COUNT(*) * 100) as error_rate -FROM tblskill_agent_metrics -WHERE created_at > DATE_SUB(NOW(), INTERVAL 30 DAY) -GROUP BY name, type -ORDER BY executions DESC -LIMIT 10; -``` +**Fallback SQL:** Ver [references/sql-queries.md](references/sql-queries.md) ### 3. Formatar Output -**Template Dashboard:** - ``` -📊 Performance Overview (últimos {days} dias) +Performance Overview (ultimos {days} dias) Top Skills/Agents: -┌─────────────────────┬────────┬──────────┬────────┬────────┐ -│ Nome │ Usos │ Avg Time │ Trend │ Status │ -├─────────────────────┼────────┼──────────┼────────┼────────┤ -│ /orcamento │ 45 │ 18min │ -12% ✓ │ ✅ │ -│ /lead-approach │ 38 │ 22min │ +5% ⚠ │ ⚠️ │ -│ wp-plugin-developer │ 32 │ 47min │ -8% ✓ │ ✅ │ -└─────────────────────┴────────┴──────────┴────────┴────────┘ - -⚠️ Alertas de Degradação: -{se houver degradação >15%} - -🎯 Dify KB Impact: -- Coverage: {skills_com_dify}/{total_skills} ({pct}%) -- Avg time reduction: {reducao_tempo}% -- Cache hit rate: {cache_hit_rate}% - -📈 Dashboard completo: https://plan-eal.descomplicar.pt/metrics +| Nome | Usos | Avg Time | Trend | Status | +|----------------|------|----------|-------|--------| +| /orcamento | 45 | 18min | -12% | OK | +| /lead-approach | 38 | 22min | +5% | Alerta | +| wp-plugin-dev | 32 | 47min | -8% | OK | ``` -### 4. Análise Específica - -Se utilizador pedir skill específica: +### 4. Analise Especifica ```javascript const details = await get_skill_metrics({ @@ -150,52 +96,21 @@ const details = await get_skill_metrics({ aggregate: 'detailed' }); -// Calcular estatísticas -const baseline = await query("SELECT baseline_duration_ms FROM tblskill_agent_baselines WHERE name = ?", [skill_name]); +const baseline = await query( + "SELECT baseline_duration_ms FROM tblskill_agent_baselines WHERE name = ?", + [skill_name] +); const improvement = ((baseline - current_avg) / baseline * 100); ``` -**Output Detalhado:** - -``` -📊 {skill_name} - Análise Detalhada - -Performance (30 dias): -- Execuções: {count} -- Tempo médio: {avg_ms}ms ({format_time}) -- Baseline: {baseline_ms}ms -- Melhoria: {improvement}% {icon} -- Error rate: {error_rate}% -- Success rate: {success_rate}% - -Dify KB: -- Consultas: {kb_consulted_count}/{total} ({pct}%) -- Com KB: {avg_with_kb}ms -- Sem KB: {avg_without_kb}ms -- Cache hit: {cache_hit_rate}% - -Trending (últimas 4 semanas): -Semana 1: {w1_avg}ms ({w1_count} usos) -Semana 2: {w2_avg}ms ({w2_count} usos) -Semana 3: {w3_avg}ms ({w3_count} usos) -Semana 4: {w4_avg}ms ({w4_count} usos) {trend_icon} - -Últimas 5 execuções: -1. {timestamp} - {duration}ms - {status} -2. ... -``` - --- -## Alertas Automáticos - -### Detectar Degradação +## Alertas Automaticos ```javascript -// Query comparação com baseline const degraded = await get_skill_metrics({ aggregate: 'compare', - days: 7 // última semana + days: 7 }); const alerts = degraded.results.filter(r => @@ -203,31 +118,11 @@ const alerts = degraded.results.filter(r => ); if (alerts.length > 0) { - // Output alertas - for (const alert of alerts) { - console.log(`⚠️ ${alert.name}: +${alert.degradation_pct}% vs baseline`); - } - - // Sugerir acção - console.log("\n💡 Sugestão: Executar /reflect para investigar causas"); + // Output alertas e sugerir /reflect para investigar } ``` ---- - -## Integração com Outros Sistemas - -### Link para Desk CRM - -``` -Ver métricas no Desk CRM: -https://desk.descomplicar.pt/admin/projects/view/65 - -Relatório personalizado: -Reports → Stack Performance -``` - -### Trigger Reflect se Degradação +### Trigger Reflect se Degradacao ```javascript if (degradation_pct > 15) { @@ -236,356 +131,47 @@ if (degradation_pct > 15) { subagent_type: 'reflect-agent', background: true, model: 'sonnet', - prompt: ` - PERFORMANCE DEGRADATION DETECTED - - Component: ${name} - Baseline: ${baseline}ms - Current: ${current}ms - Degradation: ${degradation_pct}% - - Analyze root cause and suggest fixes. - ` + prompt: `PERFORMANCE DEGRADATION: ${name} +${degradation_pct}%` }); } ``` --- -## Queries SQL Úteis (Fallback) - -### Top 10 Skills - -```sql -SELECT - name, - COUNT(*) as uses, - AVG(duration_ms)/60000 as avg_min, - (SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) / COUNT(*) * 100) as error_rate -FROM tblskill_agent_metrics -WHERE created_at > DATE_SUB(NOW(), INTERVAL 30 DAY) - AND type = 'skill' -GROUP BY name -ORDER BY uses DESC -LIMIT 10; -``` - -### ROI por Projecto - -```sql -WITH skill_savings AS ( - SELECT - m.project_id, - m.name, - COUNT(*) as uses, - (b.baseline_duration_ms - AVG(m.duration_ms))/60000 as saved_per_use_min - FROM tblskill_agent_metrics m - JOIN tblskill_agent_baselines b ON b.name = m.name - WHERE m.status = 'success' - GROUP BY m.project_id, m.name -) -SELECT - p.name as project, - c.company as client, - s.name as skill, - s.uses, - ROUND(s.uses * s.saved_per_use_min/60, 1) as hours_saved, - ROUND((s.uses * s.saved_per_use_min/60) * 50, 2) as value_eur -FROM skill_savings s -JOIN tblprojects p ON p.id = s.project_id -JOIN tblclients c ON c.userid = p.clientid -WHERE s.saved_per_use_min > 0 -ORDER BY hours_saved DESC; -``` - -### Trending Semanal - -```sql -SELECT - name, - DATE_FORMAT(created_at, '%Y-W%u') as week, - COUNT(*) as executions, - AVG(duration_ms) as avg_ms -FROM tblskill_agent_metrics -WHERE created_at > DATE_SUB(NOW(), INTERVAL 30 DAY) -GROUP BY name, week -ORDER BY name, week DESC; -``` - ---- - -## Exemplo de Uso - -```bash -# Dashboard geral -> /metrics - -📊 Performance Overview (últimos 30 dias) - -Top Skills: -┌─────────────────────┬────────┬──────────┬────────┐ -│ Skill │ Usos │ Avg Time │ Trend │ -├─────────────────────┼────────┼──────────┼────────┤ -│ /orcamento │ 45 │ 18min │ -12% ✓ │ -│ /lead-approach │ 38 │ 22min │ +5% ⚠ │ -│ /wp-dev │ 32 │ 47min │ -8% ✓ │ -└─────────────────────┴────────┴──────────┴────────┘ - -⚠️ 1 alerta detectado -🎯 Dify KB: 35/43 skills (81%) - -# Análise específica -> /metrics /orcamento - -📊 /orcamento - Análise Detalhada - -Performance: 18min avg (vs 30min baseline) → -40% ✓ -Execuções: 45 (última semana: 12) -Success: 96% | Errors: 4% - -Trending: ↓ Melhoria constante -``` - ---- - -## Notas Técnicas - -### Tools MCP Status - -**Estado:** Implementados em `/opt/desk-crm-v3/src/tools/core/metrics.ts` -**Compilados:** ✅ `/opt/desk-crm-v3/dist/tools/core/metrics.js` -**Serviço:** ✅ desk-crm.service reiniciado (249 tools) -**Disponibilidade:** Podem precisar de refresh Claude Code para serem descobertos - -### Fallback Strategy - -Se tools MCP não disponíveis: -1. Usar queries SQL directas via `sql_direct` tool -2. Funcionalidade completa mantém-se -3. Performance ligeiramente inferior mas aceitável - -### Tabelas DB - -- `tblskill_agent_metrics` - Telemetria -- `tblskill_agent_baselines` - Baselines -- `tblskill_agent_pdca_cycles` - PDCA histórico - ---- - ---- - -## NOVO v1.2.0: Métricas Dify KB - -### /metrics --kb - -Dashboard específico de performance Dify Knowledge Base. - -``` -┌──────────────────────────────────────────────────────────────┐ -│ DIFY KB PERFORMANCE DASHBOARD │ -│ 2026-02-03 │ -├──────────────────────────────────────────────────────────────┤ -│ │ -│ CACHE PERFORMANCE │ -│ ════════════════════════════════════════════════════════ │ -│ Hit Rate: ████░░░░░░░░░░░░░░░░ 6.3% (target: 40%+) │ -│ │ -│ Cache Breakdown: │ -│ ┌────────────────┬────────┬────────┬────────┐ │ -│ │ Skill │ Queries│ Hits │ Hit % │ │ -│ ├────────────────┼────────┼────────┼────────┤ │ -│ │ /orcamento │ 5 │ 1 │ 20% │ │ -│ │ /lead-approach │ 3 │ 0 │ 0% │ │ -│ │ /wp-dev │ 4 │ 0 │ 0% │ │ -│ │ /seo-content │ 2 │ 0 │ 0% │ │ -│ └────────────────┴────────┴────────┴────────┘ │ -│ │ -│ QUERY RELEVANCE (avg score) │ -│ ════════════════════════════════════════════════════════ │ -│ SEO: █████████████████░░░ 0.85 ⭐ │ -│ Perfex: ████████████████░░░░ 0.79 │ -│ Elementor: ██████████████░░░░░░ 0.70 │ -│ Marketing: █████████████░░░░░░░ 0.66 │ -│ Vendas: █████████░░░░░░░░░░░ 0.46 ⚠️ │ -│ │ -│ IMPACT ON PERFORMANCE │ -│ ════════════════════════════════════════════════════════ │ -│ Com Dify KB: 18 min avg │ -│ Sem Dify KB: 30 min avg (baseline) │ -│ Improvement: -40% ✓ │ -│ │ -│ GAPS DETECTED │ -│ ════════════════════════════════════════════════════════ │ -│ ⚠️ Vendas dataset: score 0.46 (queries mal formuladas) │ -│ ℹ️ Cache hit baixo: requer mais uso para acumular │ -│ │ -└──────────────────────────────────────────────────────────────┘ -``` - -### /metrics --roi - -ROI detalhado por cliente/projecto. - -``` -┌──────────────────────────────────────────────────────────────┐ -│ ROI POR CLIENTE/PROJECTO │ -│ Últimos 30 dias │ -├──────────────────────────────────────────────────────────────┤ -│ │ -│ TOP CLIENTES POR VALOR GERADO │ -│ ════════════════════════════════════════════════════════ │ -│ ┌────────────────────┬────────┬────────┬──────────────┐ │ -│ │ Cliente │ Horas │ Skills │ Valor (€) │ │ -│ ├────────────────────┼────────┼────────┼──────────────┤ │ -│ │ SFV-360 │ 24h │ 45 │ €1.200,00 │ │ -│ │ Descomplicar │ 18h │ 32 │ €900,00 │ │ -│ │ INTERNAL │ 12h │ 28 │ €600,00 │ │ -│ └────────────────────┴────────┴────────┴──────────────┘ │ -│ │ -│ TOTAL PERÍODO: 54 horas poupadas = €2.700,00 │ -│ Custo hora interno: €50,00 │ -│ │ -│ BREAKDOWN POR SKILL │ -│ ════════════════════════════════════════════════════════ │ -│ /orcamento: 12h poupadas (baseline 30min→18min) │ -│ /wp-dev: 8h poupadas (baseline 4h→2h) │ -│ /lead-approach: 6h poupadas (baseline 25min→12min) │ -│ │ -└──────────────────────────────────────────────────────────────┘ -``` - -### /metrics --export - -Exportar métricas para integração. - -``` -Formatos disponíveis: -1. JSON - ~/.claude/skills/_metrics-export-YYYYMMDD.json -2. CSV - ~/.claude/skills/_metrics-export-YYYYMMDD.csv -3. Markdown - Para colar em documentos - -Campos exportados: -- name, type, executions, avg_ms, baseline_ms -- improvement_pct, error_rate, kb_consulted -- cache_hit_rate, project_id, client_name -``` - -### /metrics --alerts - -Sistema de alertas inteligentes. - -``` -┌──────────────────────────────────────────────────────────────┐ -│ ALERTAS ACTIVOS │ -├──────────────────────────────────────────────────────────────┤ -│ │ -│ ⚠️ DEGRADAÇÃO (>15% vs baseline) │ -│ ─────────────────────────────────────────────────────── │ -│ /lead-approach: +22% (baseline 12min → actual 15min) │ -│ Última ocorrência: 2026-02-02 │ -│ Afecta: 3 projectos │ -│ Acção: Executar /reflect para investigar │ -│ │ -│ ℹ️ LOW CACHE HIT (<30%) │ -│ ─────────────────────────────────────────────────────── │ -│ Cache hit rate: 6.3% │ -│ Target: 40% │ -│ Causa: Sistema recente, acumular com uso │ -│ Acção: Continuar monitorização │ -│ │ -│ ✅ MELHORIAS DETECTADAS │ -│ ─────────────────────────────────────────────────────── │ -│ /orcamento: -40% (era 30min, agora 18min) │ -│ /wp-dev: -50% (era 4h, agora 2h) │ -│ │ -└──────────────────────────────────────────────────────────────┘ - -Configurar alertas: -- Degradação threshold: 15% (padrão) -- Cache hit minimum: 30% (padrão) -- Error rate maximum: 10% (padrão) -``` - ---- - -## ASCII Charts Library - -Templates reutilizáveis para visualização. - -### Progress Bar -```javascript -function progressBar(value, max, width=20) { - const filled = Math.round((value / max) * width); - const empty = width - filled; - return '█'.repeat(filled) + '░'.repeat(empty); -} - -// Exemplo: progressBar(40, 100, 20) → "████████░░░░░░░░░░░░" -``` - -### Trending Arrow -```javascript -function trendIcon(pct) { - if (pct < -10) return '↓↓ ✓'; // Grande melhoria - if (pct < 0) return '↓ ✓'; // Melhoria - if (pct === 0) return '→'; // Estável - if (pct < 10) return '↑ ⚠'; // Pequena degradação - return '↑↑ ⚠️'; // Grande degradação -} -``` - -### Mini Sparkline -```javascript -function sparkline(values) { - const chars = '▁▂▃▄▅▆▇█'; - const min = Math.min(...values); - const max = Math.max(...values); - const range = max - min || 1; - return values.map(v => chars[Math.floor((v - min) / range * 7)]).join(''); -} - -// Exemplo: sparkline([10, 15, 8, 20, 12]) → "▃▅▁█▄" -``` - ---- - -## Integração com /taskforce kb-health - -O comando `/metrics --kb` complementa `/taskforce kb-health`: +## Integracao com Outros Sistemas | Comando | Foco | Quando Usar | |---------|------|-------------| -| `/taskforce kb-health` | Saúde sistema KB (coverage, gaps) | Visão arquitectural | -| `/metrics --kb` | Performance queries KB | Análise operacional | -| `/metrics --roi` | Valor económico gerado | Justificação investimento | +| `/taskforce kb-health` | Saude sistema KB | Visao arquitectural | +| `/metrics --kb` | Performance queries KB | Analise operacional | +| `/metrics --roi` | Valor economico gerado | Justificacao investimento | **Workflow recomendado:** 1. `/taskforce kb-health` - Verificar gaps e coverage 2. `/metrics --kb` - Analisar performance queries 3. `/metrics --roi` - Calcular ROI para stakeholders ---- - -## Changelog - -### v1.2.0 (2026-02-03) -- **NOVO:** `/metrics --kb` - Dashboard Dify KB -- **NOVO:** `/metrics --roi` - ROI por cliente/projecto -- **NOVO:** `/metrics --export` - Export JSON/CSV -- **NOVO:** `/metrics --alerts` - Sistema alertas -- **NOVO:** ASCII Charts Library -- **MELHORIA:** Integração com `/taskforce kb-health` -- Frontmatter YAML standard - -### v1.0.0 (2026-02-03) -- Versão inicial -- Dashboard overview -- Análise por skill -- Trending temporal -- Comparação baseline +Link Desk CRM: `https://desk.descomplicar.pt/admin/projects/view/65` --- -**Skill:** /metrics v1.2.0 | **Autor:** Descomplicar® -**Parte de:** Sistema de Métricas Quantitativas -**Desk CRM:** Projecto #65 | Task #1637 +## Notas Tecnicas + +**Tabelas DB:** `tblskill_agent_metrics` (telemetria), `tblskill_agent_baselines` (baselines), `tblskill_agent_pdca_cycles` (PDCA historico) + +**Tools:** Implementados em `/opt/desk-crm-v3/src/tools/core/metrics.ts` + +**Fallback:** Se tools MCP nao disponiveis, usar queries SQL directas via `sql_direct`. + +--- + +## Conteudo Detalhado + +| Referencia | Conteudo | +|------------|----------| +| [references/sql-queries.md](references/sql-queries.md) | Queries SQL completas (top 10, ROI, trending) | +| [references/dashboards-templates.md](references/dashboards-templates.md) | Templates visuais KB, ROI, alertas, export, ASCII charts | + +--- + +**Desk CRM:** Projecto #65, Task #1637 diff --git a/core-tools/skills/metrics/references/dashboards-templates.md b/core-tools/skills/metrics/references/dashboards-templates.md new file mode 100644 index 0000000..9989f55 --- /dev/null +++ b/core-tools/skills/metrics/references/dashboards-templates.md @@ -0,0 +1,126 @@ +# Metrics - Templates de Dashboards + +## Dashboard KB Performance + +``` +DIFY KB PERFORMANCE DASHBOARD + +CACHE PERFORMANCE +Hit Rate: [barra progresso] X% (target: 40%+) + +Cache Breakdown: +| Skill | Queries | Hits | Hit % | +|----------------|---------|------|-------| +| /orcamento | 5 | 1 | 20% | +| /lead-approach | 3 | 0 | 0% | +| /wp-dev | 4 | 0 | 0% | + +QUERY RELEVANCE (avg score) +SEO: 0.85 +Perfex: 0.79 +Elementor: 0.70 +Marketing: 0.66 +Vendas: 0.46 (alerta) + +IMPACT ON PERFORMANCE +Com Dify KB: 18 min avg +Sem Dify KB: 30 min avg (baseline) +Improvement: -40% +``` + +## Dashboard ROI por Cliente/Projecto + +``` +ROI POR CLIENTE/PROJECTO (ultimos 30 dias) + +TOP CLIENTES POR VALOR GERADO +| Cliente | Horas | Skills | Valor (EUR) | +|--------------|-------|--------|-------------| +| SFV-360 | 24h | 45 | 1.200,00 | +| Descomplicar | 18h | 32 | 900,00 | +| INTERNAL | 12h | 28 | 600,00 | + +TOTAL PERIODO: 54 horas poupadas = 2.700,00 EUR +Custo hora interno: 50,00 EUR + +BREAKDOWN POR SKILL +/orcamento: 12h poupadas (baseline 30min->18min) +/wp-dev: 8h poupadas (baseline 4h->2h) +/lead-approach: 6h poupadas (baseline 25min->12min) +``` + +## Dashboard Alertas + +``` +ALERTAS ACTIVOS + +DEGRADACAO (>15% vs baseline) +/lead-approach: +22% (baseline 12min -> actual 15min) +Ultima ocorrencia: 2026-02-02 +Afecta: 3 projectos +Accao: Executar /reflect para investigar + +LOW CACHE HIT (<30%) +Cache hit rate: 6.3% +Target: 40% +Causa: Sistema recente, acumular com uso + +MELHORIAS DETECTADAS +/orcamento: -40% (era 30min, agora 18min) +/wp-dev: -50% (era 4h, agora 2h) + +Configurar alertas: +- Degradacao threshold: 15% (padrao) +- Cache hit minimum: 30% (padrao) +- Error rate maximum: 10% (padrao) +``` + +## Dashboard Export + +``` +Formatos disponiveis: +1. JSON - ~/.claude/skills/_metrics-export-YYYYMMDD.json +2. CSV - ~/.claude/skills/_metrics-export-YYYYMMDD.csv +3. Markdown - Para colar em documentos + +Campos exportados: +- name, type, executions, avg_ms, baseline_ms +- improvement_pct, error_rate, kb_consulted +- cache_hit_rate, project_id, client_name +``` + +## ASCII Charts Library + +### Progress Bar + +```javascript +function progressBar(value, max, width=20) { + const filled = Math.round((value / max) * width); + const empty = width - filled; + return '#'.repeat(filled) + '-'.repeat(empty); +} +``` + +### Trending Arrow + +```javascript +function trendIcon(pct) { + if (pct < -10) return 'melhoria significativa'; + if (pct < 0) return 'melhoria'; + if (pct === 0) return 'estavel'; + if (pct < 10) return 'degradacao ligeira'; + return 'degradacao significativa'; +} +``` + +### Mini Sparkline + +```javascript +function sparkline(values) { + const chars = '________'; + const min = Math.min(...values); + const max = Math.max(...values); + const range = max - min || 1; + return values.map(v => chars[Math.floor((v - min) / range * 7)]).join(''); +} +``` diff --git a/core-tools/skills/metrics/references/sql-queries.md b/core-tools/skills/metrics/references/sql-queries.md new file mode 100644 index 0000000..1def1d8 --- /dev/null +++ b/core-tools/skills/metrics/references/sql-queries.md @@ -0,0 +1,77 @@ +# Metrics - Queries SQL (Fallback) + +Queries para usar quando tools MCP nao estao disponiveis. + +## Top 10 Skills + +```sql +SELECT + name, + COUNT(*) as uses, + AVG(duration_ms)/60000 as avg_min, + (SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) / COUNT(*) * 100) as error_rate +FROM tblskill_agent_metrics +WHERE created_at > DATE_SUB(NOW(), INTERVAL 30 DAY) + AND type = 'skill' +GROUP BY name +ORDER BY uses DESC +LIMIT 10; +``` + +## ROI por Projecto + +```sql +WITH skill_savings AS ( + SELECT + m.project_id, + m.name, + COUNT(*) as uses, + (b.baseline_duration_ms - AVG(m.duration_ms))/60000 as saved_per_use_min + FROM tblskill_agent_metrics m + JOIN tblskill_agent_baselines b ON b.name = m.name + WHERE m.status = 'success' + GROUP BY m.project_id, m.name +) +SELECT + p.name as project, + c.company as client, + s.name as skill, + s.uses, + ROUND(s.uses * s.saved_per_use_min/60, 1) as hours_saved, + ROUND((s.uses * s.saved_per_use_min/60) * 50, 2) as value_eur +FROM skill_savings s +JOIN tblprojects p ON p.id = s.project_id +JOIN tblclients c ON c.userid = p.clientid +WHERE s.saved_per_use_min > 0 +ORDER BY hours_saved DESC; +``` + +## Trending Semanal + +```sql +SELECT + name, + DATE_FORMAT(created_at, '%Y-W%u') as week, + COUNT(*) as executions, + AVG(duration_ms) as avg_ms +FROM tblskill_agent_metrics +WHERE created_at > DATE_SUB(NOW(), INTERVAL 30 DAY) +GROUP BY name, week +ORDER BY name, week DESC; +``` + +## Query Basica via MCP + +```sql +SELECT + name, + type, + COUNT(*) as executions, + AVG(duration_ms) as avg_ms, + (SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) / COUNT(*) * 100) as error_rate +FROM tblskill_agent_metrics +WHERE created_at > DATE_SUB(NOW(), INTERVAL 30 DAY) +GROUP BY name, type +ORDER BY executions DESC +LIMIT 10; +``` diff --git a/core-tools/skills/plugin-curator/SKILL.md b/core-tools/skills/plugin-curator/SKILL.md index d278d17..d1258af 100644 --- a/core-tools/skills/plugin-curator/SKILL.md +++ b/core-tools/skills/plugin-curator/SKILL.md @@ -1,12 +1,6 @@ --- name: plugin-curator -description: > - Curadoria inteligente de plugins para o ecossistema Claude Code. - Use when "plugins", "marketplace", "instalar plugin", "descobrir", - "recomendações", "actualizar", "gaps funcionais", "extensões". -author: Descomplicar® -version: 1.0.0 -desk_task: 1441 +description: Curadoria inteligente de plugins para o ecossistema Claude Code — descoberta, recomendações, actualizações e identificação de gaps funcionais. allowed-tools: Read, Glob, Grep, WebFetch, WebSearch --- diff --git a/core-tools/skills/plugin-manager/SKILL.md b/core-tools/skills/plugin-manager/SKILL.md index 71a6184..ea48e7a 100644 --- a/core-tools/skills/plugin-manager/SKILL.md +++ b/core-tools/skills/plugin-manager/SKILL.md @@ -1,17 +1,7 @@ --- name: plugin-config -description: > - Gestao inteligente de plugins por contexto v3.0. Avalia regras aditivas — activa - cada plugin que fizer sentido para o contexto actual (directorio, ficheiros, conversa). - Sem profiles rigidos. Use when "plugins", "plugin-config", "activar plugin", - "desactivar plugin", "contexto plugins", "prompt too long". -author: Descomplicar -version: 3.1.0 -user_invocable: true -category: system -tags: [plugins, context, optimization, registry] -desk_project: 65 -desk_task: 1754 +description: Gestão inteligente de plugins por contexto. Avalia regras aditivas e activa cada plugin relevante para o contexto actual (directório, ficheiros, conversa). +user-invocable: false allowed-tools: Read, Bash, Glob --- diff --git a/core-tools/skills/quality-validator/SKILL.md b/core-tools/skills/quality-validator/SKILL.md index 6faba79..bc27c43 100644 --- a/core-tools/skills/quality-validator/SKILL.md +++ b/core-tools/skills/quality-validator/SKILL.md @@ -1,12 +1,6 @@ --- name: quality-validator -description: > - Valida componentes contra standards Descomplicar®. - Use when "validar", "score", "qualidade", "audit", - "verificar frontmatter", "checklist", "quality gate". -author: Descomplicar® -version: 1.0.0 -desk_task: 1441 +description: Validação de componentes contra os standards Descomplicar® — frontmatter, checklists e quality gates antes de activação ou release. allowed-tools: Read, Glob, Grep --- diff --git a/core-tools/skills/relationship-manager/SKILL.md b/core-tools/skills/relationship-manager/SKILL.md index 3f28a2a..e92f4fc 100644 --- a/core-tools/skills/relationship-manager/SKILL.md +++ b/core-tools/skills/relationship-manager/SKILL.md @@ -1,12 +1,6 @@ --- name: relationship-manager -description: > - Gestão inteligente de relacionamentos entre componentes do sistema. - Use when "relacionamentos", "mapeamento", "colaborações", "dependências", - "agent-mcp", "agent-skill", "sdk", "impacto", "inconsistências". -author: Descomplicar® -version: 1.0.0 -desk_task: 1441 +description: Gestão inteligente de relacionamentos entre componentes do sistema — mapeamento de dependências, colaborações agent-MCP/skill e análise de impacto. allowed-tools: Read, Glob, Grep, ToolSearch --- diff --git a/crm-ops/.claude-plugin/plugin.json b/crm-ops/.claude-plugin/plugin.json index ee6af5a..ddc1c2a 100644 --- a/crm-ops/.claude-plugin/plugin.json +++ b/crm-ops/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "crm-ops", - "description": "CRM operations, sales management, leads, customers, estimates, invoices, tickets and expense tracking with Desk CRM. Backed by 2 Dify KB datasets.", + "description": "CRM operations, sales management, leads, customers, estimates, invoices, tickets and expense tracking with Desk CRM. Backed by NotebookLM notebooks.", "version": "1.1.0", "author": { "name": "Descomplicar - Crescimento Digital", diff --git a/crm-ops/agents/budget-proposal-specialist.md b/crm-ops/agents/budget-proposal-specialist.md index d05a376..8d17e30 100644 --- a/crm-ops/agents/budget-proposal-specialist.md +++ b/crm-ops/agents/budget-proposal-specialist.md @@ -13,7 +13,6 @@ primary_mcps: recommended_mcps: - moloni - memory-supabase - - dify-kb skills: - _core - orcamento @@ -116,7 +115,7 @@ Você é um especialista comercial responsável por: | `desk-crm-v3` | Verificar cliente, criar estimate | | `google-workspace` | Criar orçamento em Google Docs | | `memory-supabase` | Consultar orçamentos similares | -| `dify-kb` | Best practices pricing | +| `` | Best practices pricing | ## Responsabilidades @@ -180,15 +179,6 @@ mcp__notebooklm__notebook_query notebook_id:"0c9c079c-a426-486c-99eb-1564d42d37a mcp__notebooklm__notebook_query notebook_id:"5be0d1a6-00f2-4cd9-b835-978cb7721601" query:"desenvolvimento custos" ``` -### Dify KB (Secundario - se NotebookLM insuficiente) - -``` -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Vendas" query:"orcamento proposta pricing" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Gestao" query:"projectos estimativa custos" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Marketing Digital" query:"servicos pacotes" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"WordPress" query:"desenvolvimento custos" -``` - ## Your Available MCPs ### Recommended for business @@ -197,16 +187,14 @@ mcp__dify-kb__dify_kb_retrieve_segments dataset:"WordPress" query:"desenvolvimen - **google-workspace** - Email, calendário, docs, drive - **imap** - Email IMAP - **memory-supabase** - Memória longo prazo -- **dify-kb** - Knowledge base AI +- **** - Knowledge base AI - **outline-api** - Outline documentation -### All Available (33 total) +### All Available (32 total) context7, gitea, n8n, cwp, filesystem, ssh-unified, google-analytics, youtube-research, youtube-uploader, wikijs, gsc, lighthouse, mcp-time, puppeteer, mcp-mermaid, mcp-echarts, powerpoint, penpot, pixabay, pexels, tavily, elevenlabs, magic, vimeo, design-systems, replicate **Discovery:** Use ToolSearch to find specific tools. **Example:** `ToolSearch("ssh upload")` finds SSH upload tools. - - ## Your Available Skills ### Primary Skills (Your Domain) @@ -235,13 +223,11 @@ context7, gitea, n8n, cwp, filesystem, ssh-unified, google-analytics, youtube-re - **/knowledge** - Gestão unificada de conhecimento - pesquisa inteligente com - **/desk** - Integração com Desk CRM via ficheiro .desk-project. Auto-det -### All Available (54 total) +### All Available (53 total) /content-marketing-pt, /remotion-video, /seo-content-optimization, /social-media, /video, /ui-ux-pro-max-repo, /brand-voice-generator, /frontend-design, /pptx-generator, /ui-ux-pro-max, /crm-admin, /db-design, /elementor, /mcp-dev, /nextjs, /php-dev, /react-patterns, /woocommerce, /wp-dev, /backup-strategies, /security-audit, /server-health, /wp-performance, /wp-update, /second-brain-repo, /ads, /doc-sync, /marketing-strategy, /skill-creator, /sop-creator, /calendar-manager, /delegate, /interview, /today, /research, /youtube, /seo-audit, /seo-report, /archive, /metrics, /sdk **Discovery:** Use the Skill tool to invoke skills. **Example:** `Skill("skill-name")` invokes the skill. - - ## Colaboração - **Reports to**: Sales Manager diff --git a/crm-ops/agents/lead-approach-strategist.md b/crm-ops/agents/lead-approach-strategist.md index 1955f98..89bfb7d 100644 --- a/crm-ops/agents/lead-approach-strategist.md +++ b/crm-ops/agents/lead-approach-strategist.md @@ -13,7 +13,6 @@ primary_mcps: - desk-crm-v3 - google-workspace recommended_mcps: - - dify-kb - memory-supabase - imap skills: @@ -38,8 +37,6 @@ created: '2025-01-13' updated: '2026-02-04' author: Descomplicar® --- - - # Lead Approach Strategist Descomplicar Especialista em estratégia de abordagem de leads - análise de perfil, definição de estratégia e criação de primeiro contacto personalizado. @@ -86,9 +83,6 @@ Especialista em estratégia de abordagem de leads - análise de perfil, definiç mcp__notebooklm__notebook_query notebook_id:"76647e0f-3ae2-4c00-a0a8-f457aebf5655" query:"" mcp__notebooklm__notebook_query notebook_id:"7b8fec17-d34f-4e3f-a8c6-8231e51f6323" query:"" ``` - -### Dify KB (Secundario) - - Vendas - Marketing Digital - Copywriting @@ -147,7 +141,7 @@ Estrategista comercial especializado em análise de leads e criação de abordag ## MCPs Relevantes - `desk-crm-v3`: Dados de leads e histórico -- `notebooklm`: KB primaria (Gemini 2.5 RAG) | `dify-kb`: KB Vendas, Marketing Digital, Copywriting +- `notebooklm`: KB primaria (Gemini 2.5 RAG) | ``: KB Vendas, Marketing Digital, Copywriting - `memory-supabase`: Padrões de abordagem bem-sucedidos ## Colaboracao @@ -166,9 +160,9 @@ Estrategista comercial especializado em análise de leads e criação de abordag - Gemini 2.5 RAG - Usage: `mcp__notebooklm__notebook_query` -✓ **dify-kb** (knowledge fallback) +✓ **** (knowledge fallback) - Knowledge base AI - - Usage: `mcp__dify-kb__*` + - Usage: `mcp____*` ✓ **memory-supabase** (system) - Memória longo prazo @@ -186,13 +180,11 @@ Estrategista comercial especializado em análise de leads e criação de abordag - **vimeo** - Video management - upload, metadata, transcripts, analytics - **replicate** - AI models - imagem, vídeo, áudio, LLMs -### All Available (33 total) +### All Available (32 total) moloni, context7, gitea, n8n, cwp, filesystem, ssh-unified, imap, outline-api, wikijs, gsc, lighthouse, mcp-time, puppeteer, mcp-mermaid, mcp-echarts, powerpoint, penpot, magic, design-systems **Discovery:** Use ToolSearch to find specific tools. **Example:** `ToolSearch("ssh upload")` finds SSH upload tools. - - ## Your Available Skills ### Primary Skills (Your Domain) @@ -219,7 +211,7 @@ moloni, context7, gitea, n8n, cwp, filesystem, ssh-unified, imap, outline-api, w - **/knowledge** - Gestão unificada de conhecimento - pesquisa inteligente com - **/desk** - Integração com Desk CRM via ficheiro .desk-project. Auto-det -### All Available (54 total) +### All Available (53 total) /billing-check, /crm-ops, /ecommerce, /orcamento, /saas, /remotion-video, /video, /ui-ux-pro-max-repo, /brand-voice-generator, /frontend-design, /pptx-generator, /ui-ux-pro-max, /crm-admin, /db-design, /elementor, /mcp-dev, /nextjs, /php-dev, /react-patterns, /woocommerce, /wp-dev, /backup-strategies, /security-audit, /server-health, /wp-performance, /wp-update, /second-brain-repo, /doc-sync, /product, /skill-creator, /sop-creator, /calendar-manager, /delegate, /interview, /time, /today, /seo-audit, /seo-report, /archive, /metrics, /sdk **Discovery:** Use the Skill tool to invoke skills. diff --git a/crm-ops/agents/lead-qualifier.md b/crm-ops/agents/lead-qualifier.md index f134943..8cbfbbc 100644 --- a/crm-ops/agents/lead-qualifier.md +++ b/crm-ops/agents/lead-qualifier.md @@ -12,7 +12,6 @@ tools: Read, Glob, Grep, ToolSearch primary_mcps: - desk-crm-v3 recommended_mcps: - - dify-kb - google-workspace - memory-supabase skills: @@ -37,8 +36,6 @@ created: '2025-01-13' updated: '2026-02-04' author: Descomplicar® --- - - # Lead Qualifier Descomplicar Avalia e prioriza leads inbound, garantindo que a equipa de vendas se foca em prospects de alta qualidade enquanto nutre os que ainda nao estao prontos para comprar. @@ -59,14 +56,6 @@ mcp__notebooklm__notebook_query notebook_id:"76647e0f-3ae2-4c00-a0a8-f457aebf565 mcp__notebooklm__notebook_query notebook_id:"df4688bb-c2c0-4aba-98c1-38c3b50a353c" query:"lead management pipeline" ``` -### Dify KB (Secundario - se NotebookLM insuficiente) - -``` -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Vendas" query:"lead qualification scoring criteria" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Marketing Digital" query:"lead generation conversion funnel" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"PerfexCRM" query:"lead management pipeline" -``` - ## System Prompt ### Papel @@ -120,7 +109,7 @@ Avalia e prioriza leads inbound, garantindo que a equipa de vendas se foca em pr ## MCPs Relevantes - `desk-crm-v3`: Gestão de leads e pipeline -- `notebooklm`: KB primaria (Gemini 2.5 RAG) | `dify-kb`: KB Vendas (qualification), Marketing Digital +- `notebooklm`: KB primaria (Gemini 2.5 RAG) | ``: KB Vendas (qualification), Marketing Digital - `memory-supabase`: Histórico de qualificações bem-sucedidas ## Colaboracao @@ -135,9 +124,9 @@ Avalia e prioriza leads inbound, garantindo que a equipa de vendas se foca em pr - Usage: `mcp__desk-crm-v3__*` ✓ **notebooklm** (knowledge primaria) -✓ **dify-kb** (knowledge fallback) +✓ **** (knowledge fallback) - Knowledge base AI - - Usage: `mcp__dify-kb__*` + - Usage: `mcp____*` ✓ **memory-supabase** (system) - Memória longo prazo @@ -149,13 +138,11 @@ Avalia e prioriza leads inbound, garantindo que a equipa de vendas se foca em pr - **imap** - Email IMAP - **outline-api** - Outline documentation -### All Available (33 total) +### All Available (32 total) context7, gitea, n8n, cwp, filesystem, ssh-unified, google-analytics, youtube-research, youtube-uploader, wikijs, gsc, lighthouse, mcp-time, puppeteer, mcp-mermaid, mcp-echarts, powerpoint, penpot, pixabay, pexels, tavily, elevenlabs, magic, vimeo, design-systems, replicate **Discovery:** Use ToolSearch to find specific tools. **Example:** `ToolSearch("ssh upload")` finds SSH upload tools. - - ## Your Available Skills ### Primary Skills (Your Domain) @@ -184,13 +171,11 @@ context7, gitea, n8n, cwp, filesystem, ssh-unified, google-analytics, youtube-re - **/knowledge** - Gestão unificada de conhecimento - pesquisa inteligente com - **/desk** - Integração com Desk CRM via ficheiro .desk-project. Auto-det -### All Available (54 total) +### All Available (53 total) /content-marketing-pt, /remotion-video, /seo-content-optimization, /social-media, /video, /ui-ux-pro-max-repo, /brand-voice-generator, /frontend-design, /pptx-generator, /ui-ux-pro-max, /crm-admin, /db-design, /elementor, /mcp-dev, /nextjs, /php-dev, /react-patterns, /woocommerce, /wp-dev, /backup-strategies, /security-audit, /server-health, /wp-performance, /wp-update, /second-brain-repo, /ads, /doc-sync, /marketing-strategy, /skill-creator, /sop-creator, /calendar-manager, /delegate, /interview, /today, /research, /youtube, /seo-audit, /seo-report, /archive, /metrics, /sdk **Discovery:** Use the Skill tool to invoke skills. **Example:** `Skill("skill-name")` invokes the skill. - - ## Your Team & Responsibilities You are part of **3 SDKs** (TaskForce teams): @@ -200,9 +185,6 @@ You are part of **3 SDKs** (TaskForce teams): **Purpose:** NULL **Your responsibilities in this TaskForce:** - -- **Sistema de agentes especializados para delegacao de tarefas via Task tool com consulta automatica de datasets Dify.**: NULL - ### TaskForce Marketing Estratégico **Purpose:** NULL diff --git a/crm-ops/agents/sales-manager.md b/crm-ops/agents/sales-manager.md index 11618d0..88e26f3 100644 --- a/crm-ops/agents/sales-manager.md +++ b/crm-ops/agents/sales-manager.md @@ -25,7 +25,6 @@ recommended_mcps: - moloni # Invoicing - imap # Email management - memory-supabase # Long-term memory - - dify-kb # Knowledge base - outline-api # Documentation primary_skills: @@ -91,14 +90,6 @@ mcp__notebooklm__notebook_query notebook_id:"76647e0f-3ae2-4c00-a0a8-f457aebf565 mcp__notebooklm__notebook_query notebook_id:"df4688bb-c2c0-4aba-98c1-38c3b50a353c" query:"CRM clientes pipeline" ``` -### Dify KB (Secundario - se NotebookLM insuficiente) - -``` -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Vendas" query:"estrategias comerciais leads conversao" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Marketing Digital" query:"funil vendas qualificacao" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"PerfexCRM" query:"CRM clientes pipeline" -``` - ## System Prompt ### Papel diff --git a/crm-ops/knowledge/datasets.json b/crm-ops/knowledge/datasets.json index ec0bbb5..9112660 100644 --- a/crm-ops/knowledge/datasets.json +++ b/crm-ops/knowledge/datasets.json @@ -1,5 +1,5 @@ { - "description": "Knowledge sources (NotebookLM + Dify KB) for CRM Operations domain", + "description": "Knowledge sources for CRM Operations domain", "sources": { "notebooklm": { "description": "NotebookLM - conhecimento curado profundo via Gemini 2.5 RAG (PRIMARIO)", @@ -10,8 +10,7 @@ "title": "Perfex CRM: Gestao de Clientes e Projetos", "topics": [ "perfexcrm" - ], - "maps_from_dify": "PerfexCRM" + ] }, { "id": "f29c8457-f16d-4fb3-979d-6e5901de1b20", @@ -19,30 +18,9 @@ "topics": [ "servicos", "descomplicar" - ], - "maps_from_dify": "Servicos Descomplicar" - } - ] - }, - "dify_kb": { - "description": "Dify KB - datasets tematicos (FALLBACK)", - "query_tool": "mcp__dify-kb__dify_kb_retrieve_segments", - "datasets": [ - { - "id": "43354eb6-f0b2-40cc-aa53-44e375ab347c", - "name": "PerfexCRM", - "priority": 1, - "document_count": 144, - "word_count": 1547186 - }, - { - "id": "bd65f36e-6004-4584-b478-129b2c21b4d2", - "name": "Servicos Descomplicar", - "priority": 1, - "document_count": 11, - "word_count": 1095103 + ] } ] } } -} \ No newline at end of file +} diff --git a/crm-ops/skills/auto-expense/SKILL.md b/crm-ops/skills/auto-expense/SKILL.md index 812f1b1..365f028 100644 --- a/crm-ops/skills/auto-expense/SKILL.md +++ b/crm-ops/skills/auto-expense/SKILL.md @@ -1,26 +1,7 @@ --- name: auto-expense -description: > - Criacao automatica de despesas a partir de facturas detectadas no IMAP e tickets. Le ficheiros JSON de /imap-triage e /ticket-triage, extrai dados das facturas, cria despesas no Desk CRM com PDF. Use when "auto despesa", "processar facturas", "auto-expense", "despesas automaticas". -author: Descomplicar® Crescimento Digital -version: 1.0.0 -quality_score: 85 -user_invocable: true -category: finance -tags: [expense, auto, invoices, imap, tickets, pdf, desk-crm] -desk_task: 1710 -desk_project: 65 -allowed-tools: Read, Write, mcp__desk-crm-v3, mcp__imap, mcp__ssh-unified -mcps: desk-crm-v3, imap, ssh-unified -dependencies: - mcps: [desk-crm-v3, imap, ssh-unified] - skills: [imap-triage, ticket-triage] - files: - - /media/ealmeida/Dados/Hub/06-Operacoes/Documentacao/fornecedores-recorrentes.md -triggers: - - "User asks to process invoices as expenses" - - "User mentions 'auto despesa', 'processar facturas'" - - "Invoked by /today orchestrator after /imap-triage and /ticket-triage" +description: Criação automática de despesas a partir de facturas detectadas no IMAP e tickets. Extrai dados, verifica duplicados e cria despesas no Desk CRM com PDF anexo. +disable-model-invocation: true --- # /auto-expense v1.0 diff --git a/crm-ops/skills/billing-check/SKILL.md b/crm-ops/skills/billing-check/SKILL.md index 439fbcd..c3a6ab6 100644 --- a/crm-ops/skills/billing-check/SKILL.md +++ b/crm-ops/skills/billing-check/SKILL.md @@ -1,14 +1,6 @@ --- name: billing-check -description: Billing verification and invoice validation. Checks billing accuracy, - matches invoices with contracts. Use when user mentions "billing check", "invoice - verification", "billing audit", "payment verification", "billing validation". -author: Descomplicar® Crescimento Digital -version: 2.0.0 -quality_score: 75 -user_invocable: true -desk_task: 1464 -allowed-tools: ToolSearch +description: Verificação de facturação e validação de facturas. Sincroniza facturas Moloni com horas Desk CRM para projectos 360, compara horas facturadas vs entregues e calcula saldos. --- # Billing Check - Desk vs Moloni (v2.0) diff --git a/crm-ops/skills/crm-admin/SKILL.md b/crm-ops/skills/crm-admin/SKILL.md index f08e6a9..a827a59 100644 --- a/crm-ops/skills/crm-admin/SKILL.md +++ b/crm-ops/skills/crm-admin/SKILL.md @@ -1,13 +1,7 @@ --- name: crm-admin -description: Desk CRM administration and maintenance. Manages users, permissions, - custom fields, and system configuration. Use when user mentions "crm admin", "desk - admin", "crm configuration", "user management", "crm permissions". -author: Descomplicar® Crescimento Digital -version: 1.0.0 -quality_score: 75 -user_invocable: true -desk_task: 1467 +description: Administração e manutenção do Desk CRM. Gestão de utilizadores, permissões, campos personalizados, configuração de sistema e módulos Perfex. +disable-model-invocation: true --- # CRM Admin Specialist diff --git a/crm-ops/skills/crm-ops/SKILL.md b/crm-ops/skills/crm-ops/SKILL.md index f82caa1..e026d64 100644 --- a/crm-ops/skills/crm-ops/SKILL.md +++ b/crm-ops/skills/crm-ops/SKILL.md @@ -1,42 +1,7 @@ --- name: crm-ops -description: > - Operações CRM seguras com verificações obrigatórias de duplicados e confirmações. Entende distinção crítica Lead vs Customer, Proposal vs Estimate. NUNCA cria entidade sem verificar existência. Use when creating leads, customers, proposals, estimates, or when user mentions "crm", "lead", "customer", "orçamento", "proposta", "estimate", "perfex". -author: Descomplicar® Crescimento Digital -version: 1.2.0 -quality_score: 80 -user_invocable: true -category: business -tags: [crm, leads, customers, proposals, estimates, perfex, validation, duplicates, sales-process] -desk_task: 1468 -desk_project: 65 -allowed-tools: Read, Bash, mcp__desk-crm-v3 -mcps: desk-crm-v3 -dependencies: - mcps: [desk-crm-v3] -triggers: - - "User wants to create lead, customer, proposal, estimate" - - "User mentions 'crm', 'lead', 'orçamento', 'proposta'" - - "Creating any CRM entity" - - "User says 'cliente', 'customer', 'estimate'" -anti_patterns: - critical: - - "NEVER create lead/customer without checking existence" - - "NEVER create customer automatically for estimate" - - "NEVER assume entity doesn't exist" - entities: - - "Creating customer when should be lead" - - "Using estimate for leads (use proposal)" - - "Using proposal for qualified customers (use estimate)" - technical: - - "Converting non-accepted estimate to invoice" - - "Accessing email directly in tblclients (JOIN tblcontacts)" - - "Using invented tables (verify schema first)" -performance: - baseline_duration_ms: 300000 - target_duration_ms: 180000 - last_run_duration_ms: null - success_rate: 0.92 +description: Operações CRM seguras com verificação obrigatória de duplicados e confirmações. Distinção Lead vs Customer, Proposal vs Estimate. Criação de entidades CRM. +disable-model-invocation: true --- # /crm-ops - Operações CRM Seguras diff --git a/crm-ops/skills/crm/SKILL.md b/crm-ops/skills/crm/SKILL.md index 372f6fc..5241da0 100644 --- a/crm-ops/skills/crm/SKILL.md +++ b/crm-ops/skills/crm/SKILL.md @@ -1,22 +1,6 @@ --- name: crm -description: > - Operações CRM unificadas v2.0. Consolida crm-ops + crm-admin. Leads, customers, proposals, estimates, visão 360. - Use when "crm", "lead", "cliente", "customer", "orçamento", "proposta", "estimate", "360". -author: Descomplicar® Crescimento Digital -version: 2.0.0 -quality_score: 85 -user_invocable: true -category: business -tags: [crm, leads, customers, proposals, estimates, 360, sales] -desk_task: 1468 -desk_project: 65 -allowed-tools: Read, mcp__desk-crm-v3 -mcps: desk-crm-v3 -anti_patterns: - - "NUNCA criar lead/customer sem verificar duplicados" - - "NUNCA criar customer automaticamente para estimate" - - "NUNCA fechar tarefa sem autorização" +description: Operações CRM unificadas. Leads, customers, proposals, estimates e visão 360 do cliente. Consolida crm-ops e crm-admin com verificação obrigatória de duplicados. --- # /crm v2.0 - Operações CRM Unificadas @@ -25,6 +9,28 @@ Consolida /crm-ops + /crm-admin numa única skill com subcomandos. --- +## Contexto NotebookLM + +ANTES de executar, consultar notebooks para contexto especializado: + +| Notebook | ID | Consultar quando | +|----------|-----|-----------------| +| Perfex CRM: Gestão de Clientes e Projectos | df4688bb | Sempre | + +``` +mcp__notebooklm__notebook_query({ + notebook_id: "df4688bb-c2c0-4aba-98c1-38c3b50a353c", + query: "" +}) +``` + +Integrar insights do NotebookLM nas recomendações e decisões. + +### Procedimentos Relacionados +- `PROC-CRM-Operacoes.md` — Operações CRM padrão + +--- + ## Comandos | Comando | Função | diff --git a/crm-ops/skills/desk/SKILL.md b/crm-ops/skills/desk/SKILL.md index af5ce64..8374816 100644 --- a/crm-ops/skills/desk/SKILL.md +++ b/crm-ops/skills/desk/SKILL.md @@ -1,21 +1,6 @@ --- name: desk -description: > - Contexto de projecto via .desk-project v3.0. Integração /time, status rápido. - Use when .desk-project exists, "desk", "projecto", "contexto", "desk-task". -author: Descomplicar® Crescimento Digital -version: 3.0.0 -quality_score: 90 -user_invocable: true -category: productivity -tags: [desk, crm, projecto, contexto, triangulo, integration] -desk_task: 1471 -desk_project: 65 -allowed-tools: Read, Write, Bash, mcp__desk-crm-v3, mcp__mcp-time -mcps: desk-crm-v3, mcp-time -auto_detection: - enabled: true - file: ".desk-project" +description: Contexto de projecto via .desk-project. Auto-detecção, integração com /time, status rápido, criação de tarefas e changelog. Sistema Triângulo Desk-GDrive-Local. --- # /desk v3.0 - Contexto de Projecto diff --git a/crm-ops/skills/expense/SKILL.md b/crm-ops/skills/expense/SKILL.md index 8f3d646..824dcbe 100644 --- a/crm-ops/skills/expense/SKILL.md +++ b/crm-ops/skills/expense/SKILL.md @@ -1,117 +1,49 @@ --- name: expense -description: > - Gestão de despesas Desk CRM v2.0. Documento PDF obrigatório para cada despesa. Registar, categorizar e analisar despesas com verificação de categorias e duplicados. Upload SFTP + arquivo mensal automatico. NUNCA cria sem PDF (excepto bypass explicito). Use when "despesa", "expense", "gasto", "custo", "categoria despesa", "registar despesa", "expense report", "processar tickets contabilidade", "recibo", "factura fornecedor". -author: Descomplicar® Crescimento Digital -version: 2.0.0 -quality_score: 90 -user_invocable: true -category: finance -tags: [expense, despesas, finance, categories, desk-crm, costs, reporting, tickets, receipts, pdf, sftp] -desk_task: 1710 -desk_project: 65 -allowed-tools: Read, mcp__desk-crm-v3, mcp__ssh-unified -mcps: desk-crm-v3, ssh-unified -dependencies: - mcps: [desk-crm-v3, ssh-unified] -triggers: - - "User wants to create expense" - - "User mentions 'despesa', 'expense', 'gasto', 'custo'" - - "User wants to categorize expenses" - - "User asks about expense categories" - - "User needs expense report or analysis" - - "User wants to process expenses from tickets" - - "User mentions 'tickets contabilidade', 'recibos', 'receipts'" -anti_patterns: - critical: - - "NEVER create category without checking if exists" - - "NEVER assume category doesn't exist" - - "ALWAYS list categories before creating new one" - categories: - - "Creating duplicate categories" - - "Using similar name instead of existing category" - - "Not checking existing categories first" - technical: - - "Creating expense without category_id" - - "Using category name instead of ID" -performance: - baseline_duration_ms: 60000 - target_duration_ms: 30000 - last_run_duration_ms: null - success_rate: 0.95 +description: Gestao de despesas Desk CRM com PDF obrigatorio. Registar, categorizar e analisar despesas com verificacao de duplicados, upload SFTP e arquivo mensal automatico. --- -# /expense - Gestão de Despesas +# /expense - Gestao de Despesas -Skill para gestão de despesas com verificação obrigatória de categorias existentes. - -## Metadata -- **Version**: 2.0.0 -- **Author**: Descomplicar -- **Date**: 2026-02-12 -- **Status**: Active - ---- +Skill para gestao de despesas com verificacao obrigatoria de categorias existentes. ## Quando Usar - Registar nova despesa - Criar/gerir categorias de despesas -- Consultar despesas por período/categoria +- Consultar despesas por periodo/categoria - Associar despesas a projectos/clientes -- Análise e relatórios de despesas -- **Processar despesas de tickets de contabilidade (departamento 3)** -- Importar recibos de serviços (Anthropic, Hetzner, etc.) +- Analise e relatorios de despesas +- Processar despesas de tickets de contabilidade (departamento 3) +- Importar recibos de servicos (Anthropic, Hetzner, etc.) -## Quando NÃO Usar +## Quando NAO Usar - Para facturas a clientes (usar /invoice) -- Para orçamentos (usar /orcamento) +- Para orcamentos (usar /orcamento) - Para pagamentos recebidos (usar /crm) --- -## REGRA CRÍTICA: CATEGORIAS +## REGRA CRITICA: CATEGORIAS -> **PROIBIDO criar categoria sem verificar se já existe.** - -Esta regra é INVIOLÁVEL. SEMPRE: +> **PROIBIDO criar categoria sem verificar se ja existe.** ``` 1. Listar categorias: get_expense_categories(with_stats=true) 2. Pesquisar por nome similar na lista -3. SE encontrar match ou similar: - - USAR a categoria existente - - NÃO criar duplicado -4. SE realmente não existe: - - PERGUNTAR: "Não encontrei categoria para X. Criar nova?" -5. SÓ CRIAR após confirmação explícita +3. SE encontrar match ou similar: USAR a categoria existente +4. SE realmente nao existe: PERGUNTAR "Nao encontrei categoria para X. Criar nova?" +5. SO CRIAR apos confirmacao explicita ``` -**Violação desta regra causa duplicados que prejudicam relatórios financeiros.** +**Violacao desta regra causa duplicados que prejudicam relatorios financeiros.** + +Para mapeamento completo de fornecedores, emails e padroes PDF para categorias: ver `references/category-mapping.md` --- -## Categorias Activas (top 8 - consolidacao 12-02-2026) - -| ID | Nome | Fornecedores tipicos | -|----|------|---------------------| -| 1 | Telecomunicacoes | MEO | -| 4 | Alojamento web (Hosting) | Hetzner, CWP | -| 6 | Servicos Externos | Make/Celonis, Gamma | -| 14 | Subscricoes e Servicos Digitais | YouTube Premium, BdThemes | -| 28 | Licencas Software | Canva, Cursor, Descript, GitHub, Softaculous | -| 30 | Servicos Cloud e Infraestrutura | Google One, Google Workspace, ElasticEmail | -| 37 | Dominios | PTisp, Namecheap | -| 38 | Servicos IA e APIs | Anthropic, OpenRouter, CapSolver, Replicate | - -**NOTA:** Existem ~30 categorias na BD mas apenas 8 sao usadas regularmente. SEMPRE usar `get_expense_categories()` para lista completa e actual. - ---- - -## Protocolo - -### 1. Registar Despesa +## Protocolo: Registar Despesa > **Gate PDF obrigatorio:** Sem documento, nao regista. Unica excepcao: bypass explicito do utilizador (AT/Salario sem recibo). @@ -122,407 +54,101 @@ Esta regra é INVIOLÁVEL. SEMPRE: - SE nao tem e pede bypass: PERGUNTAR "Confirmas despesa sem documento?" - Bypass valido apenas para: AT, Salarios, transferencias bancarias 2. LER O PDF: Extrair dados reais do documento - - NUNCA copiar valor de um PDF para outro, mesmo com nomes semelhantes - - Cada documento tem o seu valor proprio + - NUNCA copiar valor de um PDF para outro 3. OBRIGATORIO: get_expense_categories(with_stats=true) 4. Identificar categoria correcta na lista - - SE categoria nao existe: PERGUNTAR antes de criar 5. VERIFICAR DUPLICADOS: - get_expenses(search: "") - Mesmo fornecedor + valor + data = duplicado - Mesmo numero factura = duplicado 6. Recolher dados: - - category_id (obrigatorio) - - amount (obrigatorio - valor REAL extraido do documento) - - currency (obrigatorio - EUR=3, USD=2) - - date (obrigatorio, YYYY-MM-DD) - - note (obrigatorio, incluir numero factura) - - send_invoice_to_customer = 0 (obrigatorio na BD) - - client_id (opcional) - - project_id (opcional) - - billable (opcional, default false) - - tax (opcional) + - category_id, amount, currency (EUR=3, USD=2), date (YYYY-MM-DD) + - note (incluir numero factura), send_invoice_to_customer = 0 + - Opcionais: client_id, project_id, billable, tax 7. CONFIRMAR com utilizador (mostrar resumo) -8. create_expense (ou SQL directo se MCP indisponivel) +8. create_expense 9. UPLOAD PDF ao Desk via SFTP: a. mkdir -p no servidor: /home/ealmeida/desk.descomplicar.pt/uploads/expenses/ b. mcp__ssh-unified__sftp_upload(server:"desk", local_path, remote_path) c. chown -R ealmeida:ealmeida - d. INSERT INTO tblfiles (rel_id, rel_type='expense', file_name, filetype='application/pdf', - visible_to_customer=0, staffid=1, contact_id=0, dateadded=NOW()) -10. ARQUIVO MENSAL: Mover PDF para pasta correspondente a data da factura: - /media/ealmeida/Dados/GDrive/Cloud/ADM_Descomplicar/Financeiro/Contabilidade/YYYY/NN-NomeMes/ - (mkdir -p se pasta nao existir) + d. INSERT INTO tblfiles (rel_id, rel_type='expense', ...) +10. ARQUIVO MENSAL: Mover PDF para Contabilidade/YYYY/NN-NomeMes/ 11. Confirmar criacao ao utilizador ``` -### 2. Criar Categoria (APENAS se necessário) +## Protocolo: Criar Categoria ``` 1. get_expense_categories() - listar todas 2. Verificar se existe categoria similar -3. SE existe similar: USAR ESSA, não criar -4. SE não existe nenhuma similar: - - Perguntar confirmação ao utilizador - - Aguardar resposta explícita -5. SÓ APÓS confirmação: criar via SQL ou interface +3. SE existe similar: USAR ESSA, nao criar +4. SE nao existe: perguntar confirmacao ao utilizador +5. SO APOS confirmacao: criar ``` -### 3. Consultar Despesas +## Protocolo: Consultar Despesas ``` -1. get_expenses com filtros: - - category (ID da categoria) - - date_from / date_to (período) - - client_id (cliente específico) - - project_id (projecto específico) - - limit (número resultados) +1. get_expenses com filtros: category, date_from/date_to, client_id, project_id, limit 2. Apresentar resumo ao utilizador ``` -### 4. Análise de Despesas +## Protocolo: Analise de Despesas ``` -1. expense_analytics com parâmetros: - - period: "month", "quarter", "year" - - breakdown_by: "category", "client", "project" -2. Apresentar insights: - - Total por categoria - - Tendências - - Categorias mais usadas +1. expense_analytics: period ("month"/"quarter"/"year"), breakdown_by ("category"/"client"/"project") +2. Apresentar insights: total por categoria, tendencias, categorias mais usadas ``` -### 5. Processar Despesas de Tickets (Contabilidade) +## Processar Despesas de Tickets -> **REGRA 1:** Processar tickets UM A UM com confirmação do utilizador (ou em lote se solicitado). -> **REGRA 2:** Verificar SEMPRE se despesa já foi lançada (prevenir duplicados). -> **REGRA 3:** NÃO adicionar respostas aos tickets - apenas criar despesa e anexos. -> **REGRA 4:** Converter SEMPRE USD para EUR antes de criar despesa. -> **REGRA 5:** Saltar tickets que são apenas recibos de pagamento (não são facturas). +Para protocolo completo de processamento de tickets de contabilidade: ver `references/ticket-processing.md` -``` -1. Obter ticket: get_ticket(ticket_id) -2. Verificar anexos: SELECT * FROM tblticket_attachments WHERE ticketid = X -3. SE não tem PDFs: SALTAR ticket (apenas notificação) -4. VERIFICAR DUPLICADOS (OBRIGATÓRIO): - SELECT id, amount, date, note FROM tblexpenses - WHERE reference_no LIKE '%{receipt_number}%' OR note LIKE '%ticket #{ticket_id}%' - SE encontrar: PARAR e informar "Despesa já existe: #ID" -5. Extrair dados: - - Do HTML do ticket (valor, data, referência) - - OU usar script Python: python3 /home/ealmeida/scripts/extract_invoice_data.py {pdf_path} -6. APRESENTAR resumo ao utilizador e AGUARDAR confirmação -7. Apos confirmacao: - a. SQL: INSERT INTO tblexpenses (..., send_invoice_to_customer, ...) VALUES (..., 0, ...) - OU create_expense via MCP (se disponivel) - b. UPDATE tblexpenses SET expense_name = '{Fornecedor}' WHERE id = {id} - c. mcp__ssh-unified__ssh_execute: mkdir -p uploads/expenses/{expenseid} - d. mcp__ssh-unified__sftp_upload: PDF para uploads/expenses/{expenseid}/ - e. mcp__ssh-unified__ssh_execute: chown -R ealmeida:ealmeida uploads/expenses/{expenseid} - f. SQL: INSERT INTO tblfiles (rel_id, rel_type, file_name, filetype, - visible_to_customer, staffid, contact_id, dateadded) - VALUES ({id}, 'expense', '{file}', 'application/pdf', 0, 1, 0, NOW()) - g. Mover PDF para arquivo mensal: Contabilidade/YYYY/NN-NomeMes/ -8. Confirmar ao utilizador e passar ao proximo -``` - -#### Script Python para Extracção de PDFs - -Localização: `/home/ealmeida/scripts/extract_invoice_data.py` - -```bash -python3 /home/ealmeida/scripts/extract_invoice_data.py /path/to/invoice.pdf -``` - -Retorna JSON com: vendor, cat_id, total, date, invoice, currency, text - -#### Moedas e Valores - -> **Despesas em USD:** Manter valor original em USD com `currency = 2`. **Nao converter** manualmente. -> **Despesas em EUR:** Usar `currency = 3`. - -| Moeda | currency ID | Exemplo | -|-------|------------|---------| -| EUR | **3** | Anthropic 180.00 EUR | -| USD | **2** | Cursor 20.00 USD | - -> **CRITICO:** `currency = 1` nao existe e causa despesas invisiveis nos relatorios. SEMPRE usar 2 (USD) ou 3 (EUR). - -#### Tickets a Saltar - -| Tipo | Descrição | Acção | -|------|-----------|-------| -| Payment Receipt | Recibo de pagamento (não é fatura) | SALTAR - não criar despesa | -| Duplicado | Mesmo nº fatura já processado | SALTAR - informar utilizador | -| Sem anexo PDF | Apenas notificação por email | SALTAR - dados insuficientes | - -Exemplos de tickets a saltar: -- "Invoice Payment Confirmation" (é recibo, não fatura) -- Ticket com mesmo invoice_number de outro já processado - -#### Credenciais Base de Dados - -Localização: `/home/ealmeida/desk.descomplicar.pt/application/config/app-config.php` - -```bash -grep -E "APP_DB" /home/ealmeida/desk.descomplicar.pt/application/config/app-config.php -``` - -#### Processamento em Lote - -Se utilizador pedir "criar todas" ou "processar em lote": -1. Obter todos os tickets pendentes em paralelo -2. Identificar duplicados e tickets a saltar -3. Criar despesas em paralelo via `create_expense` -4. Actualizar `expense_name` e `reference_no` em batch via SQL -5. Copiar PDFs em batch -6. Registar ficheiros em batch via SQL INSERT múltiplo - -#### Mapeamento Fornecedor → Categoria (consolidado 12-02-2026) - -| Fornecedor | Categoria ID | Nome | -|-----------|-------------|------| -| Anthropic, OpenRouter, CapSolver, Replicate | 38 | Servicos IA e APIs | -| Canva, Cursor, Descript, GitHub, Softaculous, CWP | 28 | Licencas Software | -| Google One, Google Workspace, ElasticEmail | 30 | Servicos Cloud e Infraestrutura | -| Hetzner | 4 | Alojamento web (Hosting) | -| MEO | 1 | Telecomunicacoes | -| PTisp, Namecheap | 37 | Dominios | -| Make/Celonis, Gamma | 6 | Servicos Externos | -| YouTube Premium, BdThemes | 14 | Subscricoes e Servicos Digitais | - -#### Mapeamento Email → Categoria - -| Dominio Email | Categoria ID | Fornecedor | -|---------------|--------------|------------| -| anthropic.com | 38 | Anthropic | -| openrouter.ai | 38 | OpenRouter | -| payproglobal.com | 38 | CapSolver | -| replicate.com | 38 | Replicate | -| cursor.com, anysphere.dev | 28 | Cursor | -| canva.com | 28 | Canva | -| descript.com | 28 | Descript | -| github.com | 28 | GitHub | -| softaculous.com | 28 | Softaculous | -| centos-webpanel.com | 28 | CWP | -| elasticemail.com | 30 | ElasticEmail | -| google.com (One/Workspace) | 30 | Google Cloud | -| hetzner.com | 4 | Hetzner | -| meoempresas.pt | 1 | MEO | -| namecheap.com | 37 | Namecheap | -| ptisp.pt | 37 | PTisp | -| make.com, celonis.com | 6 | Make/Celonis | -| gamma.app | 6 | Gamma | - -> **NOTA:** `moloni.com` NAO incluido - e plataforma de facturacao, emails podem ser de qualquer fornecedor. - -#### Mapeamento Padrao PDF → Categoria - -Para documentos financeiros, identificar fornecedor pelo conteudo do PDF: - -| Padrao no PDF | Fornecedor | Categoria ID | Nome | -|---------------|-----------|--------------|------| -| `Gondooffice`, `Cubic Choices` | Gondooffice | 21 | Contabilidade | -| `Autoridade Tributaria`, `emiteDoc`, `AT -` | AT | 15 | Planos Prestacionais | -| `Staples`, `STP_ECOFACTURA` | Staples | 3 | Material de Escritorio | -| `MEO`, `meoempresas` | MEO | 1 | Telecomunicacoes | -| `TOConline`, `Recibo de Vencimento` | Salario | 22 | Salarios e Vencimentos | -| `Seguranca Social` | SS | 25 | Contribuicoes SS | -| `Cursor`, `Anysphere` | Cursor | 28 | Licencas Software | -| `Anthropic` | Anthropic | 38 | Servicos IA e APIs | -| `Hetzner` | Hetzner | 4 | Alojamento web (Hosting) | -| `ElasticEmail` | ElasticEmail | 30 | Servicos Cloud e Infraestrutura | - -#### Extracção de Dados de PDFs - -**Método 1: Script Python (recomendado)** -```bash -python3 /home/ealmeida/scripts/extract_invoice_data.py /path/to/invoice.pdf -``` - -**Método 2: pdfplumber directo** -```bash -python3 -c " -import pdfplumber -with pdfplumber.open('/path/to/file.pdf') as pdf: - for p in pdf.pages: - t = p.extract_text() - if t: print(t) -" | grep -iE "total|iva|€" -``` - -**Método 3: pdftotext (fallback)** -```bash -pdftotext /path/to/file.pdf - | head -80 -``` - -> **NOTA:** Se PDF não extrair texto (imagem), usar dados do HTML do ticket email. - -#### Comandos SQL - -```sql --- 1. VERIFICAR DUPLICADOS (EXECUTAR PRIMEIRO!) -SELECT id, amount, date, note, reference_no FROM tblexpenses -WHERE reference_no LIKE '%{receipt_number}%' - OR note LIKE '%ticket #{ticket_id}%' - --- 2. Verificar anexos do ticket -SELECT id, file_name, filetype FROM tblticket_attachments WHERE ticketid = {ID} - --- 3. Actualizar nome fornecedor -UPDATE tblexpenses SET expense_name = '{Fornecedor}' WHERE id = {expense_id} - --- 4. Registar anexo na despesa (contact_id obrigatorio!) -INSERT INTO tblfiles (rel_id, rel_type, file_name, filetype, visible_to_customer, staffid, contact_id, dateadded) -VALUES ({expense_id}, 'expense', '{filename}', 'application/pdf', 0, 1, 0, NOW()) -``` - -#### Campos para Rastreio de Duplicados - -| Campo | Conteúdo | Exemplo | -|-------|----------|---------| -| reference | Número do recibo | `2810-3712-9577` | -| note | Incluir ticket ID | `Anthropic Max (ticket #9648)` | - -#### Paths de Ficheiros - -- Anexos ticket: `/uploads/ticket_attachments/{ticketid}/` -- Anexos despesa: `/uploads/expenses/{expenseid}/` +**Resumo:** Obter ticket -> verificar anexos -> verificar duplicados -> extrair dados -> confirmar -> criar despesa -> upload PDF -> arquivo mensal. --- ## Comandos -| Comando | Descrição | +| Comando | Descricao | |---------|-----------| | `/expense create` | Registar nova despesa | | `/expense list` | Listar despesas recentes | -| `/expense categories` | Listar categorias disponíveis | -| `/expense report [período]` | Relatório de despesas | +| `/expense categories` | Listar categorias disponiveis | +| `/expense report [periodo]` | Relatorio de despesas | | `/expense search [termo]` | Pesquisar despesas | ---- - ## MCP Tools -### Despesas -- `get_expenses` - Listar despesas com filtros -- `create_expense` - Criar nova despesa -- `update_expense` - Actualizar despesa -- `delete_expense` - Eliminar despesa -- `bill_expense_to_customer` - Facturar ao cliente - -### Categorias -- `get_expense_categories` - Listar categorias (usar with_stats=true) - -### Análise -- `expense_analytics` - Métricas e análise - ---- - -## Campos create_expense - -| Campo | Tipo | Obrigatório | Descrição | -|-------|------|-------------|-----------| -| category_id | number | ✓ | ID da categoria | -| amount | number | ✓ | Valor da despesa | -| date | string | ✓ | Data (YYYY-MM-DD) | -| note | string | ✓ | Descrição (incluir ticket ID) | -| reference | string | ✓ | Número fatura/recibo (para duplicados) | -| tax | number | ✓ | **ID da taxa** (1 = IVA 23%) | -| client_id | number | - | Cliente associado | -| project_id | number | - | Projecto associado | -| billable | boolean | - | Facturável (default: false) | -| tax2 | number | - | Segunda taxa imposto | -| currency | number | ✓ | ID moeda (**EUR = 3**, USD = 2) | -| payment_mode | string | - | Metodo pagamento (default: 'online') | -| send_invoice_to_customer | number | ✓ | **Obrigatorio na BD** (sem default). Usar sempre **0** | - -### Campo expense_name (via SQL) - -> **IMPORTANTE:** Após criar despesa, actualizar `expense_name` com nome do fornecedor. - -```sql -UPDATE tblexpenses SET expense_name = '{Fornecedor}' WHERE id = {expense_id}; -``` - -### Taxas de Imposto (tbltaxes) - -| ID | Nome | Taxa | -|----|------|------| -| 1 | IVA Tx Normal | 23% | - -### Moedas (tblcurrencies) - -| ID | Nome | Símbolo | Default | -|----|------|---------|---------| -| 2 | USD | $ | Nao | -| 3 | EUR | € | Sim | - -> **CRITICO:** EUR = **3**, USD = **2**. Usar currency=1 causa despesas invisiveis nos relatorios. Para despesas em USD manter valor original com currency=2 (nao converter). +**Despesas:** `get_expenses`, `create_expense`, `update_expense`, `delete_expense`, `bill_expense_to_customer` +**Categorias:** `get_expense_categories` (usar with_stats=true) +**Analise:** `expense_analytics` --- ## Anti-Patterns (NUNCA fazer) -### Categorias -1. **NUNCA** criar categoria sem listar existentes primeiro -2. **NUNCA** assumir que categoria não existe -3. **NUNCA** criar categoria com nome similar a existente +**Categorias:** +1. Criar categoria sem listar existentes primeiro +2. Assumir que categoria nao existe +3. Criar categoria com nome similar a existente -### Despesas +**Despesas:** 4. Criar despesa sem category_id -5. Usar nome da categoria em vez do ID -6. Não validar data (formato YYYY-MM-DD) -7. Criar despesa sem note/descrição -8. **NUNCA** criar despesa sem verificar duplicados primeiro -9. **NUNCA** processar ticket sem verificar se já foi lançado +5. Nao validar data (formato YYYY-MM-DD) +6. Criar despesa sem verificar duplicados primeiro -### Valores de PDFs -10. **NUNCA** assumir que ficheiros com nomes semelhantes têm o mesmo valor -11. **SEMPRE** ler CADA PDF individualmente para extrair o valor real -12. Exemplo real: `emiteDoc.pdf` a `emiteDoc (12).pdf` tinham valores de 25,80€ a 100,53€ - todos diferentes +**Valores de PDFs:** +7. Assumir que ficheiros com nomes semelhantes tem o mesmo valor +8. SEMPRE ler CADA PDF individualmente para extrair o valor real -### Tickets -13. Processar ticket sem verificar anexos PDF -14. Assumir que ticket com recibo = despesa não lançada +**Tickets:** +9. Processar ticket sem verificar anexos PDF +10. Assumir que ticket com recibo = despesa nao lancada --- -## Exemplos - -### Exemplo 1: Registar despesa com categoria existente -``` -User: Registar despesa de 50€ de telecomunicações -→ get_expense_categories() -→ Encontra ID 1 = Telecomunicações -→ create_expense(category_id=1, amount=50, date="2026-02-05", note="Telecomunicações") -→ "Despesa #X criada: 50€ em Telecomunicações" -``` - -### Exemplo 2: Despesa com categoria a verificar -``` -User: Registar despesa de formação 200€ -→ get_expense_categories() -→ NÃO encontra "Formação" -→ "Não encontrei categoria 'Formação'. Usar 'Outras' (ID 17) ou criar nova categoria?" -→ User: Usar Outras -→ create_expense(category_id=17, amount=200, date="2026-02-05", note="Formação profissional") -``` - -### Exemplo 3: Despesa facturável a cliente -``` -User: Registar 150€ de domínio para cliente TechStart -→ get_expense_categories() → ID 13 = Registo de Domínios -→ search_customers("TechStart") → client_id=42 -→ create_expense(category_id=13, amount=150, date="2026-02-05", - note="Domínio techstart.pt", client_id=42, billable=true) -→ "Despesa facturável criada para TechStart" -``` - ---- - -## Checklist Pré-Operação +## Checklist Pre-Operacao - [ ] Listar categorias existentes - [ ] Validar categoria correcta @@ -532,80 +158,12 @@ User: Registar 150€ de domínio para cliente TechStart --- -## Base de Dados +## Referencias -- **Tabela categorias:** `tblexpenses_categories` -- **Tabela despesas:** `tblexpenses` -- **Campo categoria:** `category` (ID da categoria) +- `references/category-mapping.md` - Mapeamento fornecedores, emails, padroes PDF, campos, moedas, SQL +- `references/ticket-processing.md` - Protocolo completo de processamento de tickets +- `references/changelog.md` - Historico de alteracoes --- -## Changelog - -### v2.0.0 (2026-02-12) - Sistema Robusto 2026 -- **Gate PDF obrigatorio:** Despesa sem documento nao e registada (bypass explicito para AT/Salario) -- **Upload SFTP:** Substituido `cp` local por `mcp__ssh-unified__sftp_upload` (Regra #41) -- **Arquivo mensal:** PDF organizado em `Contabilidade/YYYY/NN-NomeMes/` automaticamente -- **Campo `send_invoice_to_customer`:** Documentado como obrigatorio na BD (valor 0) -- **Correccao currency:** EUR = **3** (nao 2), USD = **2**. Corrigido em toda a skill -- **Categorias alinhadas com consolidacao:** 8 categorias activas com mapeamento correcto - - Cursor/Canva/Descript/GitHub/Softaculous/CWP → 28 (Licencas Software) - - Hetzner → 4 (Alojamento web) - - ElasticEmail/Google → 30 (Servicos Cloud) - - PTisp/Namecheap → 37 (Dominios) - - YouTube/BdThemes → 14 (Subscricoes) - - Make/Gamma → 6 (Servicos Externos) -- **Verificacao duplicados reforçada:** Integrada no passo 5 do protocolo -- **MCP ssh-unified adicionado** a dependencias -- **Procedimento:** `06-Operacoes/Procedimentos/PROC-Skill-Expense.md` - -### v1.5.0 (2026-02-05) -- Adicionado mapeamento **Cursor (Anysphere)** → categoria 38 (Serviços IA e APIs) -- Email: `cursor.com` -- PDF patterns: `Cursor`, `Anysphere`, `cursor.com` - -### v1.4.0 (2026-02-05) -- **CORRECÇÃO CRÍTICA:** ID moeda EUR = **2** (não 1) -- Despesas com currency=1 não aparecem em relatórios -- Corrigidas 22 despesas existentes via `UPDATE tblexpenses SET currency = 2 WHERE currency = 1` -- Documentada tabela tblcurrencies com IDs correctos - -### v1.3.0 (2026-02-05) -- **Conversão USD → EUR obrigatória** (taxa ~0.92, $19.99 → €18.39) -- **Processamento em lote** quando utilizador pede "criar todas" -- Tickets a saltar documentados (payment receipts, duplicados, sem PDF) -- Localização credenciais BD: `app-config.php` -- Regras 4 e 5 adicionadas ao protocolo de tickets -- 9 despesas processadas em sessão de teste: €857.73 total - -### v1.2.0 (2026-02-05) -- Campo `expense_name` obrigatório com nome do fornecedor (via SQL UPDATE) -- Campo `tax` é ID da taxa de imposto (1 = IVA 23%), não percentagem -- Coluna BD é `reference_no`, não `reference` -- Script Python para extracção de PDFs: `/home/ealmeida/scripts/extract_invoice_data.py` -- 3 métodos de extracção PDF documentados (script, pdfplumber, pdftotext) -- Workflow actualizado: processar UM A UM com confirmação -- Removido: adicionar respostas aos tickets (apenas criar despesa + anexos) -- SQL commands actualizados com expense_name - -### v1.1.0 (2026-02-05) -- Processamento de despesas a partir de tickets de contabilidade -- Mapeamento automático email domain → categoria -- Workflow completo com verificação de anexos PDF -- Cópia automática de anexos ticket → despesa -- Registo de ficheiros em tblfiles - -### v1.0.0 (2026-02-05) -- Versão inicial -- Regra crítica de verificação de categorias -- Lista de categorias de referência -- Fluxos para criar/consultar despesas -- Integração com MCP desk-crm-v3 -- Anti-patterns documentados -- Criada após limpeza de 9 categorias duplicadas - ---- - -**Criado:** 2026-02-05 -**Actualizado:** 2026-02-12 -**Motivo:** Sistema robusto 2026 - PDF obrigatorio, SFTP, arquivo mensal, correccoes consolidacao +**Criado:** 2026-02-05 | **Actualizado:** 2026-02-12 diff --git a/crm-ops/skills/expense/references/category-mapping.md b/crm-ops/skills/expense/references/category-mapping.md new file mode 100644 index 0000000..af220ce --- /dev/null +++ b/crm-ops/skills/expense/references/category-mapping.md @@ -0,0 +1,187 @@ +# /expense - Mapeamento de Categorias e Dados Técnicos + +## Categorias Activas (consolidacao 12-02-2026) + +| ID | Nome | Fornecedores típicos | +|----|------|---------------------| +| 1 | Telecomunicacoes | MEO | +| 4 | Alojamento web (Hosting) | Hetzner, CWP | +| 6 | Servicos Externos | Make/Celonis, Gamma | +| 14 | Subscricoes e Servicos Digitais | YouTube Premium, BdThemes | +| 28 | Licencas Software | Canva, Cursor, Descript, GitHub, Softaculous | +| 30 | Servicos Cloud e Infraestrutura | Google One, Google Workspace, ElasticEmail | +| 37 | Dominios | PTisp, Namecheap | +| 38 | Servicos IA e APIs | Anthropic, OpenRouter, CapSolver, Replicate | + +Existem ~30 categorias na BD mas apenas 8 são usadas regularmente. SEMPRE usar `get_expense_categories()` para lista completa. + +--- + +## Mapeamento Fornecedor → Categoria + +| Fornecedor | Categoria ID | Nome | +|-----------|-------------|------| +| Anthropic, OpenRouter, CapSolver, Replicate | 38 | Servicos IA e APIs | +| Canva, Cursor, Descript, GitHub, Softaculous, CWP | 28 | Licencas Software | +| Google One, Google Workspace, ElasticEmail | 30 | Servicos Cloud e Infraestrutura | +| Hetzner | 4 | Alojamento web (Hosting) | +| MEO | 1 | Telecomunicacoes | +| PTisp, Namecheap | 37 | Dominios | +| Make/Celonis, Gamma | 6 | Servicos Externos | +| YouTube Premium, BdThemes | 14 | Subscricoes e Servicos Digitais | + +--- + +## Mapeamento Email → Categoria + +| Dominio Email | Categoria ID | Fornecedor | +|---------------|--------------|------------| +| anthropic.com | 38 | Anthropic | +| openrouter.ai | 38 | OpenRouter | +| payproglobal.com | 38 | CapSolver | +| replicate.com | 38 | Replicate | +| cursor.com, anysphere.dev | 28 | Cursor | +| canva.com | 28 | Canva | +| descript.com | 28 | Descript | +| github.com | 28 | GitHub | +| softaculous.com | 28 | Softaculous | +| centos-webpanel.com | 28 | CWP | +| elasticemail.com | 30 | ElasticEmail | +| google.com (One/Workspace) | 30 | Google Cloud | +| hetzner.com | 4 | Hetzner | +| meoempresas.pt | 1 | MEO | +| namecheap.com | 37 | Namecheap | +| ptisp.pt | 37 | PTisp | +| make.com, celonis.com | 6 | Make/Celonis | +| gamma.app | 6 | Gamma | + +> `moloni.com` NAO incluido - é plataforma de facturação. + +--- + +## Mapeamento Padrão PDF → Categoria + +| Padrão no PDF | Fornecedor | Categoria ID | +|---------------|-----------|--------------| +| `Gondooffice`, `Cubic Choices` | Gondooffice | 21 Contabilidade | +| `Autoridade Tributaria`, `emiteDoc`, `AT -` | AT | 15 Planos Prestacionais | +| `Staples`, `STP_ECOFACTURA` | Staples | 3 Material Escritorio | +| `MEO`, `meoempresas` | MEO | 1 Telecomunicacoes | +| `TOConline`, `Recibo de Vencimento` | Salario | 22 Salarios | +| `Seguranca Social` | SS | 25 Contribuicoes SS | +| `Cursor`, `Anysphere` | Cursor | 28 Licencas Software | +| `Anthropic` | Anthropic | 38 Servicos IA e APIs | +| `Hetzner` | Hetzner | 4 Alojamento web | +| `ElasticEmail` | ElasticEmail | 30 Servicos Cloud | + +--- + +## Campos create_expense + +| Campo | Tipo | Obrigatório | Descrição | +|-------|------|-------------|-----------| +| category_id | number | Sim | ID da categoria | +| amount | number | Sim | Valor da despesa | +| date | string | Sim | Data (YYYY-MM-DD) | +| note | string | Sim | Descrição (incluir ticket ID) | +| reference | string | Sim | Número fatura/recibo | +| tax | number | Sim | ID da taxa (1 = IVA 23%) | +| currency | number | Sim | EUR = **3**, USD = 2 | +| send_invoice_to_customer | number | Sim | Sempre **0** | +| client_id | number | Não | Cliente associado | +| project_id | number | Não | Projecto associado | +| billable | boolean | Não | Facturável (default: false) | + +--- + +## Moedas + +| ID | Nome | Símbolo | Default | +|----|------|---------|---------| +| 2 | USD | $ | Não | +| 3 | EUR | € | Sim | + +> **CRITICO:** EUR = **3**, USD = **2**. `currency = 1` não existe e causa despesas invisíveis nos relatórios. + +--- + +## Taxas de Imposto + +| ID | Nome | Taxa | +|----|------|------| +| 1 | IVA Tx Normal | 23% | + +--- + +## Comandos SQL + +```sql +-- 1. VERIFICAR DUPLICADOS (EXECUTAR PRIMEIRO) +SELECT id, amount, date, note, reference_no FROM tblexpenses +WHERE reference_no LIKE '%{receipt_number}%' + OR note LIKE '%ticket #{ticket_id}%' + +-- 2. Verificar anexos do ticket +SELECT id, file_name, filetype FROM tblticket_attachments WHERE ticketid = {ID} + +-- 3. Actualizar nome fornecedor (obrigatorio apos criar) +UPDATE tblexpenses SET expense_name = '{Fornecedor}' WHERE id = {expense_id} + +-- 4. Registar anexo na despesa +INSERT INTO tblfiles (rel_id, rel_type, file_name, filetype, visible_to_customer, staffid, contact_id, dateadded) +VALUES ({expense_id}, 'expense', '{filename}', 'application/pdf', 0, 1, 0, NOW()) +``` + +--- + +## Extracção de Dados de PDFs + +**Método 1: Script Python (recomendado)** +```bash +python3 /home/ealmeida/scripts/extract_invoice_data.py /path/to/invoice.pdf +``` +Retorna JSON com: vendor, cat_id, total, date, invoice, currency, text + +**Método 2: pdfplumber directo** +```bash +python3 -c " +import pdfplumber +with pdfplumber.open('/path/to/file.pdf') as pdf: + for p in pdf.pages: + t = p.extract_text() + if t: print(t) +" | grep -iE "total|iva|€" +``` + +**Método 3: pdftotext (fallback)** +```bash +pdftotext /path/to/file.pdf - | head -80 +``` + +--- + +## Paths de Ficheiros + +- Anexos ticket: `/uploads/ticket_attachments/{ticketid}/` +- Anexos despesa: `/uploads/expenses/{expenseid}/` +- Arquivo mensal: `/media/ealmeida/Dados/GDrive/Cloud/ADM_Descomplicar/Financeiro/Contabilidade/YYYY/NN-NomeMes/` +- Credenciais BD: `/home/ealmeida/desk.descomplicar.pt/application/config/app-config.php` + +--- + +## Tickets a Saltar + +| Tipo | Descrição | Acção | +|------|-----------|-------| +| Payment Receipt | Recibo de pagamento (não é fatura) | SALTAR | +| Duplicado | Mesmo nº fatura já processado | SALTAR | +| Sem anexo PDF | Apenas notificação por email | SALTAR | + +--- + +## Campos para Rastreio de Duplicados + +| Campo | Conteúdo | Exemplo | +|-------|----------|---------| +| reference | Número do recibo | `2810-3712-9577` | +| note | Incluir ticket ID | `Anthropic Max (ticket #9648)` | diff --git a/crm-ops/skills/expense/references/changelog.md b/crm-ops/skills/expense/references/changelog.md new file mode 100644 index 0000000..27fd9df --- /dev/null +++ b/crm-ops/skills/expense/references/changelog.md @@ -0,0 +1,56 @@ +# /expense - Changelog + +## v2.0.0 (2026-02-12) - Sistema Robusto 2026 + +- **Gate PDF obrigatorio:** Despesa sem documento nao e registada (bypass explicito para AT/Salario) +- **Upload SFTP:** Substituido `cp` local por `mcp__ssh-unified__sftp_upload` (Regra #41) +- **Arquivo mensal:** PDF organizado em `Contabilidade/YYYY/NN-NomeMes/` automaticamente +- **Campo `send_invoice_to_customer`:** Documentado como obrigatorio na BD (valor 0) +- **Correccao currency:** EUR = **3** (nao 2), USD = **2**. Corrigido em toda a skill +- **Categorias alinhadas com consolidacao:** 8 categorias activas com mapeamento correcto + - Cursor/Canva/Descript/GitHub/Softaculous/CWP -> 28 (Licencas Software) + - Hetzner -> 4 (Alojamento web) + - ElasticEmail/Google -> 30 (Servicos Cloud) + - PTisp/Namecheap -> 37 (Dominios) + - YouTube/BdThemes -> 14 (Subscricoes) + - Make/Gamma -> 6 (Servicos Externos) +- **Verificacao duplicados reforcada:** Integrada no passo 5 do protocolo +- **MCP ssh-unified adicionado** a dependencias +- **Procedimento:** `06-Operacoes/Procedimentos/PROC-Skill-Expense.md` + +## v1.5.0 (2026-02-05) + +- Adicionado mapeamento **Cursor (Anysphere)** -> categoria 38 (Servicos IA e APIs) + +## v1.4.0 (2026-02-05) + +- **CORRECCAO CRITICA:** ID moeda EUR = **2** (nao 1) +- Despesas com currency=1 nao aparecem em relatorios +- Corrigidas 22 despesas existentes via `UPDATE tblexpenses SET currency = 2 WHERE currency = 1` + +## v1.3.0 (2026-02-05) + +- **Conversao USD -> EUR obrigatoria** (taxa ~0.92, $19.99 -> 18.39 EUR) +- **Processamento em lote** quando utilizador pede "criar todas" +- Tickets a saltar documentados (payment receipts, duplicados, sem PDF) +- 9 despesas processadas em sessao de teste: 857.73 EUR total + +## v1.2.0 (2026-02-05) + +- Campo `expense_name` obrigatorio com nome do fornecedor (via SQL UPDATE) +- Campo `tax` e ID da taxa de imposto (1 = IVA 23%), nao percentagem +- Coluna BD e `reference_no`, nao `reference` +- Script Python para extraccao de PDFs +- 3 metodos de extraccao PDF documentados + +## v1.1.0 (2026-02-05) + +- Processamento de despesas a partir de tickets de contabilidade +- Mapeamento automatico email domain -> categoria +- Workflow completo com verificacao de anexos PDF + +## v1.0.0 (2026-02-05) + +- Versao inicial +- Regra critica de verificacao de categorias +- Criada apos limpeza de 9 categorias duplicadas diff --git a/crm-ops/skills/expense/references/ticket-processing.md b/crm-ops/skills/expense/references/ticket-processing.md new file mode 100644 index 0000000..22c24e3 --- /dev/null +++ b/crm-ops/skills/expense/references/ticket-processing.md @@ -0,0 +1,75 @@ +# /expense - Processamento de Despesas de Tickets + +## Regras + +1. Processar tickets UM A UM com confirmacao do utilizador (ou em lote se solicitado) +2. Verificar SEMPRE se despesa ja foi lancada (prevenir duplicados) +3. NAO adicionar respostas aos tickets - apenas criar despesa e anexos +4. Manter valor original na moeda do documento (EUR=3, USD=2) +5. Saltar tickets que sao apenas recibos de pagamento (nao sao facturas) + +--- + +## Protocolo Ticket a Ticket + +``` +1. Obter ticket: get_ticket(ticket_id) +2. Verificar anexos: SELECT * FROM tblticket_attachments WHERE ticketid = X +3. SE nao tem PDFs: SALTAR ticket (apenas notificacao) +4. VERIFICAR DUPLICADOS (OBRIGATORIO): + SELECT id, amount, date, note FROM tblexpenses + WHERE reference_no LIKE '%{receipt_number}%' OR note LIKE '%ticket #{ticket_id}%' + SE encontrar: PARAR e informar "Despesa ja existe: #ID" +5. Extrair dados: + - Do HTML do ticket (valor, data, referencia) + - OU usar script Python: python3 /home/ealmeida/scripts/extract_invoice_data.py {pdf_path} +6. APRESENTAR resumo ao utilizador e AGUARDAR confirmacao +7. Apos confirmacao: + a. SQL: INSERT INTO tblexpenses (..., send_invoice_to_customer, ...) VALUES (..., 0, ...) + OU create_expense via MCP (se disponivel) + b. UPDATE tblexpenses SET expense_name = '{Fornecedor}' WHERE id = {id} + c. mcp__ssh-unified__ssh_execute: mkdir -p uploads/expenses/{expenseid} + d. mcp__ssh-unified__sftp_upload: PDF para uploads/expenses/{expenseid}/ + e. mcp__ssh-unified__ssh_execute: chown -R ealmeida:ealmeida uploads/expenses/{expenseid} + f. SQL: INSERT INTO tblfiles (rel_id, rel_type, file_name, filetype, + visible_to_customer, staffid, contact_id, dateadded) + VALUES ({id}, 'expense', '{file}', 'application/pdf', 0, 1, 0, NOW()) + g. Mover PDF para arquivo mensal: Contabilidade/YYYY/NN-NomeMes/ +8. Confirmar ao utilizador e passar ao proximo +``` + +--- + +## Processamento em Lote + +Se utilizador pedir "criar todas" ou "processar em lote": +1. Obter todos os tickets pendentes em paralelo +2. Identificar duplicados e tickets a saltar +3. Criar despesas em paralelo via `create_expense` +4. Actualizar `expense_name` e `reference_no` em batch via SQL +5. Copiar PDFs em batch +6. Registar ficheiros em batch via SQL INSERT multiplo + +--- + +## Tickets a Saltar + +| Tipo | Descricao | Accao | +|------|-----------|-------| +| Payment Receipt | Recibo de pagamento (nao e fatura) | SALTAR | +| Duplicado | Mesmo numero fatura ja processado | SALTAR | +| Sem anexo PDF | Apenas notificacao por email | SALTAR | + +Exemplos: +- "Invoice Payment Confirmation" (e recibo, nao fatura) +- Ticket com mesmo invoice_number de outro ja processado + +--- + +## Credenciais Base de Dados + +Localizacao: `/home/ealmeida/desk.descomplicar.pt/application/config/app-config.php` + +```bash +grep -E "APP_DB" /home/ealmeida/desk.descomplicar.pt/application/config/app-config.php +``` diff --git a/crm-ops/skills/invoice/SKILL.md b/crm-ops/skills/invoice/SKILL.md index 6a4429a..2c2e59d 100644 --- a/crm-ops/skills/invoice/SKILL.md +++ b/crm-ops/skills/invoice/SKILL.md @@ -1,17 +1,7 @@ --- name: invoice -description: > - Gestão de facturação Desk CRM v1.0. Criar, enviar, pagamentos, vencidas, timesheets. - Use when "invoice", "factura", "fatura", "pagamento", "vencida", "facturar", "billing". -author: Descomplicar® Crescimento Digital -version: 1.0.0 -quality_score: 75 -user_invocable: true -category: business -tags: [invoice, factura, billing, payments, desk, crm] -desk_project: 65 -allowed-tools: Read, mcp__desk-crm-v3, mcp__mcp-time -mcps: desk-crm-v3, mcp-time +description: Gestão de facturação Desk CRM. Criar facturas, converter estimates, facturar timesheets, registar pagamentos e listar facturas vencidas. +disable-model-invocation: true --- # /invoice v1.0 - Gestão de Facturação diff --git a/crm-ops/skills/orcamento/SKILL.md b/crm-ops/skills/orcamento/SKILL.md index 1a1745e..376b4b2 100644 --- a/crm-ops/skills/orcamento/SKILL.md +++ b/crm-ops/skills/orcamento/SKILL.md @@ -1,183 +1,172 @@ --- name: orcamento -description: > - Criação sistemática de orçamentos Descomplicar® baseados em tabela oficial de preços (tabela-geral.csv). Integração directa CRM para proposals/estimates. Suporta StarterWP, CorporateWP, CareWP, eCommerceWP, Marketing 360, Manutenção. Consulta obrigatória datasets Dify (Serviços, Vendas). Use when user asks to create, generate or elaborate budget/proposal, or mentions "orçamento", "proposta", "estimate", "pricing", "website budget". -author: Descomplicar® Crescimento Digital -version: 3.1.0 -quality_score: 100 -user_invocable: true -category: business -tags: [orcamento, proposta, pricing, crm, proposals, estimates, vendas, packages] -desk_task: 1415 -desk_project: 65 -allowed-tools: Read, Bash, mcp__desk-crm-v3, mcp__dify-kb -mcps: desk-crm-v3, dify-kb -data_sources: - - path: /media/ealmeida/Dados/GDrive/Cloud/Docs/Produtos_Servicos/tabela-geral.csv - priority: 1 - usage: All products/services with pricing - - path: /media/ealmeida/Dados/GDrive/Cloud/Docs/Produtos_Servicos/items-subscricao.csv - priority: 2 - usage: Subscription services - - path: /media/ealmeida/Dados/GDrive/Cloud/Docs/Produtos_Servicos/chatbots-precos.csv - priority: 2 - usage: Chatbot pricing - - path: /media/ealmeida/Dados/GDrive/Cloud/Docs/Produtos_Servicos/items-faturacao-deskcrm.csv - priority: 2 - usage: Billing items -datasets: - - id: bd65f36e-6004-4584-b478-129b2c21b4d2 - name: Serviços Descomplicar - priority: 1 - usage: Packages, pricing justification - - id: a7ba6005-517c-41ab-ac5e-da1c1a1c62ef - name: Vendas - priority: 1 - usage: Proposal techniques, negotiation - - id: c1ec779f-4cb1-4ecf-ba11-6b39b93d4e24 - name: Marketing Digital - priority: 2 - usage: Value proposition, ROI - - id: c8489151-de94-42b2-8cee-c0b961cfac6d - name: Websites - priority: 2 - usage: Website features comparison -dependencies: - skills: [crm-ops, lead-approach] - mcps: [desk-crm-v3, dify-kb] -triggers: - - "User asks to create/generate/elaborate budget" - - "User mentions 'orçamento', 'proposta', 'pricing'" - - "User asks for 'estimate', 'quote', 'proposal'" - - "Creating pricing for leads or customers" -packages: - - code: starter - name: StarterWP - base_price: 700 - annual_fee: 250 - timeline: 3-5 weeks - - code: corporate - name: CorporateWP - base_price: 900 - annual_fee: 299 - timeline: 4-6 weeks - - code: care - name: CareWP - base_price: 1300 - annual_fee: 350 - timeline: 4-6 weeks - - code: ecom - name: eCommerceWP - base_price: 1100 - annual_fee: 349 - timeline: 7-9 weeks - - code: mkt - name: Marketing 360 - base_price: 459 - billing: monthly - commitment: 12 months - - code: man - name: Manutenção - base_price: 150 - billing: monthly - commitment: 12 months -performance: - baseline_duration_ms: 1800000 - target_duration_ms: 900000 - last_run_duration_ms: null - success_rate: 0.92 +description: Criação sistemática de orçamentos Descomplicar baseados nos itens oficiais do Desk CRM. Suporta StarterWP, CorporateWP, CareWP, eCommerceWP, Marketing 360, Manutenção, AcceleratorX, DeskCRM e Chatbots. Variantes -MEN (mensal) e -TRI (trimestral). +disable-model-invocation: true --- -# Skill /orcamento - Criação Sistemática de Orçamentos +# Skill /orcamento - Criacao Sistematica de Orcamentos -Skill para criar orçamentos profissionais baseados na tabela oficial de preços Descomplicar®, com integração directa ao CRM. +Skill para criar orcamentos profissionais baseados nos itens oficiais do Desk CRM, com integracao directa ao CRM. + +## Fonte de Verdade + +**IMPORTANTE**: A fonte de verdade para precos e servicos e o Desk CRM (`tblitems` + `tblitems_groups`). + +- **651 itens** em **14 grupos**: Websites, DeskCRM, Licencas, Tecnologia, Servicos, Chatbots, Marketing, Suporte, Comunicacao, Design, Estrategia, Mobile, IA, Alojamento +- Cada servico pode ter variantes de facturacao: Investimento, Anuidade, Trimestral, Mensalidade +- Os precos no CRM sao actualizados pela equipa e reflectem-se automaticamente nos orcamentos + +### Grupos de Itens (tblitems_groups) + +| ID | Grupo | Total Itens | Tipo Principal | +|----|-------|-------------|----------------| +| 1 | Websites | 183 | Pacotes WP + funcionalidades + anuidades | +| 14 | DeskCRM | 127 | Pacotes CRM + modulos | +| 8 | Licencas | 108 | Plugins WP + renovacoes | +| 3 | Tecnologia | 63 | AcceleratorX + WhatSMS | +| 2 | Servicos | 62 | Packs de horas | +| 13 | Chatbots | 46 | Chatbots + integracoes | +| 4 | Marketing | 34 | Packs SEO, Email, Ads | +| 9 | Suporte | 8 | Bancos de horas | +| 5 | Comunicacao | 5 | Packs copywriting | +| 6 | Design | 5 | Branding | +| 7 | Estrategia | 5 | Consultoria, coaching | +| 10 | Mobile | 3 | App React Native | +| 12 | IA | 2 | Agentes virtuais | +| 11 | Alojamento Web | — | Incluido nos websites | + +### Como Consultar Itens + +``` +# Listar itens por grupo +mcp__desk-crm-v3__price_management action="get_pricing_insights" params={"group": "Websites"} + +# Pesquisar item especifico via SQL (ssh server) +mysql -u root ealmeida_desk24 -e " + SELECT i.description, i.rate, i.unit, g.name as grupo + FROM tblitems i + JOIN tblitems_groups g ON i.group_id = g.id + WHERE i.description LIKE '%StarterWP%' + ORDER BY i.description;" + +# Listar todos os itens de um grupo (ex: grupo 1 = Websites) +mysql -u root ealmeida_desk24 -e " + SELECT i.description, i.rate, i.unit + FROM tblitems i + WHERE i.group_id = 1 + AND i.unit NOT IN ('mensalidade','trimestral','anuidade') + ORDER BY i.description;" +``` + +### Variantes de Facturacao + +Cada servico recorrente tem 4 variantes no CRM. Por defeito, o estimate usa o **item base**. Com os flags `-MEN` ou `-TRI`, os itens recorrentes sao incluidos directamente na variante pretendida. + +| Tipo | Sufixo no CRM | Flag | Quando usar | +|------|---------------|------|-------------| +| Investimento/Projeto | (sem sufixo) | (nenhum) | Projectos unicos | +| Anuidade | "Anuidade ..." | (nenhum) | Servicos com renovacao anual | +| Trimestral | "Trimestral ..." | `-TRI` | Cliente quer facturacao trimestral | +| Mensalidade | "Mensalidade ..." | `-MEN` | Cliente quer facturacao mensal | + +**Regra por defeito** (sem flag): No estimate, incluir o item base. Ao converter para invoice, seleccionar a variante de facturacao acordada. + +**Regra com flag `-MEN` ou `-TRI`**: Pesquisar itens recorrentes pela variante correspondente (prefixo "Mensalidade ..." ou "Trimestral ..."). Itens pontuais (setup, configuracao) mantêm-se inalterados. Apenas itens com unit "anuidade" sao substituidos pela variante equivalente. + +### Mapeamento de Variantes + +Ao usar `-MEN` ou `-TRI`, para cada item recorrente (unit = "anuidade"): + +1. Pesquisar no CRM o item equivalente com o prefixo da variante: + - `-MEN`: `WHERE description LIKE 'Mensalidade %' AND description LIKE '%[NOME_ITEM]%'` + - `-TRI`: `WHERE description LIKE 'Trimestral %' AND description LIKE '%[NOME_ITEM]%'` +2. Se encontrado, usar o preco e unit da variante +3. Se nao encontrado, manter item base e avisar o utilizador + +**Calculo de valores com variantes:** + +| Flag | Unit no estimate | Qty | Calculo | +|------|-----------------|-----|---------| +| (nenhum) | `ano` | 1 | Valor anual | +| `-TRI` | `trimestral` | 1 | Valor trimestral (tipicamente anuidade / 4 * 1.05-1.10) | +| `-MEN` | `mensalidade` | 1 | Valor mensal (tipicamente anuidade / 12 * 1.10-1.15) | + +**Nota**: Os precos das variantes sao definidos no CRM e podem incluir markup sobre o valor anual. Consultar SEMPRE o CRM, nunca calcular por divisao simples. ## Quando Usar -- Criar orçamento para cliente novo ou existente -- Gerar proposta comercial (proposal ou estimate) -- Consultar preços oficiais de produtos/serviços +- Criar orcamento para cliente novo ou existente +- Gerar proposta comercial (estimate) +- Consultar precos oficiais de produtos/servicos - Calcular valores com IVA e anuidades -- Integrar orçamento directamente no CRM +- Integrar orcamento directamente no CRM -## Quando NÃO Usar +## Quando NAO Usar -- Para análise estratégica de lead (usar /lead-approach) -- Para operações CRM genéricas (usar /crm-ops) -- Para simples consulta de preços (ler CSV directamente) +- Para analise estrategica de lead (usar /lead-approach) +- Para operacoes CRM genericas (usar /crm-ops) + +--- + +## Contexto NotebookLM + +ANTES de executar, consultar notebooks para contexto especializado: + +| Notebook | ID | Consultar quando | +|----------|-----|-----------------| +| Estratégia e Empreendedorismo | 79d43410 | Para enquadramento estratégico de preços | + +``` +mcp__notebooklm__notebook_query({ + notebook_id: "79d43410-0e29-4be1-881d-84db6bdc239a", + query: "" +}) +``` + +Integrar insights do NotebookLM nas recomendações e decisões. + +### Procedimentos Relacionados +- `PROC-Catalogo-Codificacao-Produtos.md` — Codificação e catálogo de produtos +- `PROC-CRM-Operacoes.md` — Operações CRM padrão --- ## Protocolo -### Fontes de Dados (OBRIGATÓRIO) - -**IMPORTANTE**: Antes de criar qualquer orçamento, ler SEMPRE os dados actualizados de: +### Sintaxe ``` -/media/ealmeida/Dados/GDrive/Cloud/Docs/Produtos_Servicos/ -├── tabela-geral.csv ← Todos os produtos/serviços com preços -├── items-subscricao.csv ← Serviços de subscrição -├── chatbots-precos.csv ← Preços de chatbots -└── items-faturacao-deskcrm.csv ← Items para facturação +/orcamento [cliente] [tipo] [-MEN|-TRI] ``` -### Estrutura do CSV Principal (tabela-geral.csv) +**Parametros:** +- `cliente` - Nome ou ID do cliente (opcional, sera solicitado se omitido) +- `tipo` - Tipo de orcamento (opcional, sera apresentado menu se omitido) +- `-MEN` - Variante mensal: usa itens com unit "mensalidade" e calcula valor/mes +- `-TRI` - Variante trimestral: usa itens com unit "trimestral" e calcula valor/trimestre +- (sem flag) - Comportamento actual: item base (Investimento/Projeto/Anual) -| Campo | Descrição | -|-------|-----------| -| Codigo | Código único (ex: WEB-WP-001) | -| Nome | Nome do produto/serviço | -| Familia | Categoria principal (Websites, Design, Tecnologia, etc.) | -| PrecoBase | Valor em euros | -| Unidade | Tipo (Projeto, Hora, Investimento, Mês) | -| DescricaoCurta | Para orçamento | -| TempoEstimado | Em dias/semanas | +**Tipos disponiveis:** +| Codigo | Tipo | Grupo CRM | +|--------|------|-----------| +| `starter` | StarterWP | Websites | +| `corporate` | CorporateWP | Websites | +| `care` | CareWP (Clinicas) | Websites | +| `ecom` | eCommerceWP | Websites | +| `mkt` | Marketing Digital 360 | Marketing | +| `man` | Manutencao | Suporte | +| `deskcrm` | DeskCRM | DeskCRM | +| `chatbot` | Chatbot | Chatbots | +| `acceleratorx` | AcceleratorX | Tecnologia | -### Como Usar os CSVs - -```python -# Exemplo de leitura -import csv -with open('/media/.../Produtos_Servicos/tabela-geral.csv') as f: - reader = csv.DictReader(f) - for row in reader: - if row['Codigo'] == 'WEB-WP-001': # StarterWP - preco = float(row['PrecoBase']) # 700 -``` - -**Regra**: Os CSVs são a fonte de verdade. O pricing-guide.md é referência rápida. - -## Sintaxe - -``` -/orcamento [cliente] [tipo] -``` - -**Parâmetros:** -- `cliente` - Nome ou ID do cliente (opcional, será solicitado se omitido) -- `tipo` - Tipo de orçamento (opcional, será apresentado menu se omitido) - -**Tipos disponíveis:** -| Código | Tipo | Template | Valor Base | -|--------|------|----------|------------| -| `starter` | StarterWP | `templates/website-corporativo.md` | 700€ | -| `corporate` | CorporateWP | `templates/website-corporativo.md` | 900€ | -| `care` | CareWP (Clínicas) | `templates/website-corporativo.md` | 1.300€ | -| `ecom` | eCommerceWP | `templates/e-commerce.md` | 1.100€ | -| `mkt` | Marketing Digital 360 | `templates/marketing-digital.md` | 459€/mês | -| `man` | Manutenção | `templates/manutencao.md` | 150€/mês | - -## Fluxo de Execução - -### Fase 1: Identificação do Cliente +### Fase 1: Identificacao do Cliente 1. Se cliente fornecido, pesquisar no CRM: ``` mcp__desk-crm-v3__search_customers query="[nome]" fields="company,vat" ``` -2. Se não encontrado ou não fornecido, solicitar dados: +2. Se nao encontrado ou nao fornecido, solicitar dados: - Nome da empresa - NIF (opcional) - Email contacto @@ -187,107 +176,161 @@ with open('/media/.../Produtos_Servicos/tabela-geral.csv') as f: mcp__desk-crm-v3__create_customer company="..." vat="..." ... ``` -### Fase 2: Selecção de Template +### Fase 2: Seleccao de Template 1. Se tipo fornecido, carregar template correspondente -2. Se não fornecido, apresentar menu interactivo via AskUserQuestion: - - StarterWP (700€ + 250€/ano) - - CorporateWP (900€ + 299€/ano) - - CareWP (1.300€ + 350€/ano) - - eCommerceWP (1.100€ + 349€/ano) - - Marketing 360 (459€/mês) - - Manutenção (150€/mês) +2. Se nao fornecido, apresentar menu interactivo: + - StarterWP | CorporateWP | CareWP | eCommerceWP + - Marketing 360 | Manutencao + - DeskCRM | Chatbot | AcceleratorX -### Fase 3: Personalização +### Fase 3: Consultar Precos no CRM -1. Ler template seleccionado de `templates/` -2. Apresentar questões de personalização específicas do tipo -3. Adicionar funcionalidades conforme requisitos -4. Calcular valores usando tabela de `references/pricing-guide.md` +**OBRIGATORIO**: Consultar precos actualizados no Desk CRM antes de calcular. -### Fase 4: Geração do Orçamento +#### Sem variante (comportamento actual) +```bash +# Buscar preco do pacote base +mysql -u root ealmeida_desk24 -e " + SELECT description, rate, unit FROM tblitems + WHERE group_id = [GROUP_ID] + AND description LIKE '%[PACOTE]%' + AND unit NOT IN ('mensalidade','trimestral','anuidade') + ORDER BY description;" +``` + +#### Com `-MEN` (variante mensal) +```bash +# Buscar itens base (setup/pontuais - mantêm-se iguais) +mysql -u root ealmeida_desk24 -e " + SELECT description, rate, unit FROM tblitems + WHERE group_id = [GROUP_ID] + AND description LIKE '%[PACOTE]%' + AND unit NOT IN ('mensalidade','trimestral','anuidade') + ORDER BY description;" + +# Buscar itens recorrentes na variante mensal +mysql -u root ealmeida_desk24 -e " + SELECT description, rate, unit FROM tblitems + WHERE group_id = [GROUP_ID] + AND description LIKE 'Mensalidade%[PACOTE]%' + ORDER BY description;" +``` + +#### Com `-TRI` (variante trimestral) +```bash +# Buscar itens base (setup/pontuais - mantêm-se iguais) +mysql -u root ealmeida_desk24 -e " + SELECT description, rate, unit FROM tblitems + WHERE group_id = [GROUP_ID] + AND description LIKE '%[PACOTE]%' + AND unit NOT IN ('mensalidade','trimestral','anuidade') + ORDER BY description;" + +# Buscar itens recorrentes na variante trimestral +mysql -u root ealmeida_desk24 -e " + SELECT description, rate, unit FROM tblitems + WHERE group_id = [GROUP_ID] + AND description LIKE 'Trimestral%[PACOTE]%' + ORDER BY description;" +``` + +Ou via MCP: +``` +mcp__desk-crm-v3__price_management action="get_pricing_insights" params={"group": "[GRUPO]", "search": "[PACOTE]"} +``` + +### Fase 4: Personalizacao + +1. Apresentar questoes de personalizacao especificas do tipo +2. Adicionar funcionalidades conforme requisitos +3. Para cada funcionalidade, buscar item correspondente no CRM + +### Fase 5: Geracao do Orcamento 1. Calcular valores finais: - - Subtotal por item + - Subtotal por item (precos do CRM) - IVA 23% - Total - - Anuidade (se aplicável) + - Recorrencia (anuidade, trimestral ou mensal conforme variante) -2. Criar estimate no CRM: +2. Ajustar items conforme variante: + - **Sem flag**: Itens base + anuidade separada + - **`-MEN`**: Itens setup + itens "Mensalidade ..." do CRM (unit: "mensalidade") + - **`-TRI`**: Itens setup + itens "Trimestral ..." do CRM (unit: "trimestral") + +3. Criar estimate no CRM: ``` mcp__desk-crm-v3__create_estimate client_id=[id] date=[hoje] expiry_date=[hoje + 30 dias] items=[items calculados] - terms="Condições de Pagamento: 50% na adjudicação + 50% na entrega" + terms="[termos ajustados a variante]" ``` -3. Apresentar resumo ao utilizador com link para CRM +4. Termos ajustados por variante: + - **Sem flag**: "Condicoes de Pagamento: 50% na adjudicacao + 50% na entrega" + - **`-MEN`**: "Condicoes de Pagamento: Setup - 50% na adjudicacao + 50% na entrega | Recorrencia - facturacao mensal antecipada" + - **`-TRI`**: "Condicoes de Pagamento: Setup - 50% na adjudicacao + 50% na entrega | Recorrencia - facturacao trimestral antecipada" -## Tabela de Preços Base +5. Apresentar resumo ao utilizador com link para CRM -Ver `references/pricing-guide.md` para tabela completa. +## Pacotes Principais (referencia rapida) + +**Nota**: Estes valores sao referencia. Consultar SEMPRE o CRM para precos actualizados. ### Websites - | Produto | Setup | Anuidade | Prazo | |---------|-------|----------|-------| -| StarterWP | 700€ | 250€ | 3-5 sem | -| CorporateWP | 900€ | 299€ | 4-6 sem | -| eCommerceWP | 1.100€ | 349€ | 7-9 sem | -| ChallengeWP | 700€ | 250€ | 8-10 sem | -| CareWP | 1.300€ | 350€ | 4-6 sem | +| StarterWP | 700 | 250 | 3-5 sem | +| CorporateWP | 900 | 299 | 4-6 sem | +| eCommerceWP | 1100 | 349 | 7-9 sem | +| ChallengeWP | 700 | 250 | 8-10 sem | +| CareWP | 1300 | 350 | 4-6 sem | -### Funcionalidades Frequentes +### DeskCRM +| Produto | Setup | Anuidade | +|---------|-------|----------| +| DeskCRM Starter | (ver CRM) | 400 | +| DeskCRM Profissional | (ver CRM) | 800 | +| DeskCRM Avancado | (ver CRM) | 1500 | +| DeskCRM Enterprise | (ver CRM) | 3000 | -| Funcionalidade | Valor | -|----------------|-------| -| EasyAppointment | 175€ (55+120) | -| Chat da Página | 50€ + 50€/ano | -| Forms Inteligentes | 150€ | -| CartRecovery | 190€ (90+100) + 90€/ano | -| Pixel + GTM | 50€ | -| ShopBuilder | 5€/produto | +### AcceleratorX +| Produto | Setup | +|---------|-------| +| WP ProCMS | 650 | +| e-Commerce | 750 | +| Membership | 450 | +| Booking | 450 | +| Care | 750 | +| Meet | 650 | +| School Manager | 850 | -### Serviços Recorrentes +### Chatbots +| Produto | Setup | +|---------|-------| +| Chatbot Basico | 350 | +| Chatbot Avancado | 850 | +| Chatbot Care | 850 | -| Serviço | Valor Mensal | Compromisso | -|---------|--------------|-------------| -| Marketing 360 | 459€ | 12 meses | -| Manutenção | 150€ | 12 meses | - -## Termos e Condições Padrão - -``` -CONDIÇÕES DE PAGAMENTO - -1. Projectos: 50% na adjudicação + 50% na entrega -2. Serviços recorrentes: facturação mensal antecipada - -VALIDADE - -Orçamento válido por 30 dias a partir da data de emissão. - -ANUIDADE - -A anuidade inclui: -- Alojamento Premium SSD NVMe -- Certificado SSL -- Actualizações de segurança -- Suporte técnico básico - -Descomplicar® Crescimento Digital -NIF: 514 623 168 | descomplicar.pt -``` +### Design/Branding +| Produto | Valor | +|---------|-------| +| Branding WOW Digital | 400 | +| Branding WOW Essencial | 850 | +| Branding Completo | 1100 | +| Pack Rebranding | 1500 | +| Pack Premium 360 | 5000 | ## Estrutura de Items para API -Cada item do orçamento segue o formato: +Cada item do orcamento segue o formato: ```json { - "description": "Descrição do serviço", + "description": "Descricao do servico", "qty": 1, "rate": 700, "unit": "un" @@ -295,172 +338,144 @@ Cada item do orçamento segue o formato: ``` **Unidades:** -- `un` - Unidade (projecto/item único) -- `mes` - Mês (serviço recorrente) -- `ano` - Ano (anuidade) +- `un` - Unidade (projecto/item unico) +- `mes` ou `mensalidade` - Mes (servico recorrente mensal, usado com `-MEN`) +- `trimestral` - Trimestre (servico recorrente trimestral, usado com `-TRI`) +- `ano` ou `anuidade` - Ano (anuidade, comportamento por defeito) -## Checklist de Execução +## Termos e Condicoes Padrao + +``` +CONDICOES DE PAGAMENTO + +1. Projectos: 50% na adjudicacao + 50% na entrega +2. Servicos recorrentes: facturacao mensal antecipada + +VALIDADE + +Orcamento valido por 30 dias a partir da data de emissao. + +ANUIDADE + +A anuidade inclui: +- Alojamento Premium SSD NVMe +- Certificado SSL +- Actualizacoes de seguranca +- Suporte tecnico basico + +Descomplicar Crescimento Digital +NIF: 514 623 168 | descomplicar.pt +``` + +## Checklist de Execucao - [ ] Cliente identificado/criado no CRM -- [ ] Tipo de orçamento seleccionado -- [ ] Template carregado +- [ ] Tipo de orcamento seleccionado +- [ ] Precos consultados no CRM (tblitems) - [ ] Funcionalidades adicionais identificadas - [ ] Valores calculados (subtotal + IVA) -- [ ] Anuidade calculada (se aplicável) -- [ ] Estimate criado no CRM +- [ ] Recorrencia calculada (anuidade/trimestral/mensal conforme variante) +- [ ] Estimate criado no CRM (status: Draft) - [ ] Resumo apresentado ao utilizador -## Exemplos de Uso - -### Exemplo 1: Website simples -``` -/orcamento "TechStartup Lda" starter -→ StarterWP: 700€ + IVA -→ Anuidade: 250€/ano -``` - -### Exemplo 2: E-commerce com funcionalidades -``` -/orcamento "Loja Online SA" ecom -→ Questiona: Nº produtos? Gateways? Transportadoras? -→ Calcula com funcionalidades -→ Gera orçamento detalhado -``` - -### Exemplo 3: Interactivo completo -``` -/orcamento -→ Solicita cliente -→ Apresenta menu de tipos -→ Questões de personalização -→ Gera orçamento no CRM -``` - ## MCPs Utilizados ``` mcp__desk-crm-v3__search_customers - Pesquisar cliente mcp__desk-crm-v3__get_customer - Obter detalhes cliente mcp__desk-crm-v3__create_customer - Criar cliente novo -mcp__desk-crm-v3__create_estimate - Criar orçamento -mcp__desk-crm-v3__get_estimates - Listar orçamentos existentes +mcp__desk-crm-v3__create_estimate - Criar orcamento +mcp__desk-crm-v3__get_estimates - Listar orcamentos existentes +mcp__desk-crm-v3__price_management - Consultar precos e itens ``` -## Códigos de Produtos (tabela-geral.csv) +## Formulas de Calculo -### Websites -| Código | Produto | Preço | -|--------|---------|-------| -| WEB-WP-001 | StarterWP | 700€ | -| WEB-WP-002 | CorporateWP | 900€ | -| WEB-WP-003 | eCommerceWP | 1.100€ | -| WEB-WP-004 | ChallengeWP | 700€ | -| WEB-WP-005 | CareWP | 1.300€ | +### Website Simples +``` +Total = Base + Funcionalidades + Conteudos +Anuidade = Anuidade_Base + Anuidades_Funcionalidades +``` -### Branding -| Código | Produto | Preço | -|--------|---------|-------| -| DES-BRA-001 | Branding WOW Essencial | 850€ | -| DES-BRA-002 | Branding Completo | 1.100€ | -| DES-BRA-003 | Branding WOW Digital | 400€ | +### Exemplo: Website Corporativo com Agendamento (sem variante) +``` +CorporateWP: 900 (item CRM: "CorporateWP") +EasyAppointment: 175 (item CRM: "EasyAppointment") +Chat da Pagina: 50 (item CRM: "Chat da Pagina") +Pixel + GTM: 50 (items CRM: "Configuracao Pixel Facebook" + "Configuracao GTM") +--------------------------------- +Subtotal: 1175 +IVA 23%: 270.25 +TOTAL: 1445.25 -### AcceleratorX -| Código | Produto | Preço | -|--------|---------|-------| -| TEC-WPC-001 | AcceleratorX WP ProCMS | 650€ | -| TEC-ECO-001 | AcceleratorX e-Commerce | 750€ | -| TEC-MEM-001 | AcceleratorX Membership | 450€ | -| TEC-BOO-001 | AcceleratorX Booking | 450€ | -| TEC-CAR-001 | AcceleratorX Care | 750€ | +Anuidade: 299 + 50 + 50 = 399 (items CRM com unit "anuidade") +``` -### Consultoria -| Código | Produto | Preço | -|--------|---------|-------| -| EST-CON-001 | Consultoria Estratégica | 90€/hora | -| EST-COA-001 | Coaching e Formação | 50€/hora | -| EST-BRA-001 | Estratégia de Marca | 900€ | +### Exemplo: Mesmo orcamento com `-MEN` +``` +SETUP (pagamento unico): +CorporateWP: 900 +EasyAppointment: 175 +Chat da Pagina: 50 +Pixel + GTM: 50 +--------------------------------- +Subtotal Setup: 1175 +IVA 23%: 270.25 +TOTAL Setup: 1445.25 -## Referências +RECORRENCIA MENSAL (items CRM com prefixo "Mensalidade"): +Mensalidade CorporateWP: 29.90 (item CRM: "Mensalidade CorporateWP") +Mensalidade EasyAppointment: 5.90 (item CRM: "Mensalidade EasyAppointment") +Mensalidade Chat da Pagina: 4.90 (item CRM: "Mensalidade Chat da Pagina") +--------------------------------- +Subtotal Mensal: 40.70 +IVA 23%: 9.36 +TOTAL Mensal: 50.06/mes -- `references/pricing-guide.md` - Tabela de preços rápida +Nota: precos mensais sao exemplificativos - consultar CRM para valores reais. +``` + +## Referencias + +- `references/pricing-guide.md` - Tabela de precos rapida (referencia, nao fonte de verdade) - `templates/website-corporativo.md` - Templates StarterWP, CorporateWP, CareWP - `templates/e-commerce.md` - Template eCommerceWP - `templates/marketing-digital.md` - Template Marketing 360 -- `templates/manutencao.md` - Template Manutenção - -## Fonte de Dados Principal - -``` -/media/ealmeida/Dados/GDrive/Cloud/Docs/Produtos_Servicos/tabela-geral.csv -``` +- `templates/manutencao.md` - Template Manutencao --- -## Datasets Dify (Consulta Obrigatória) - -Em caso de dúvidas ou para aprofundar conhecimento, consultar os seguintes datasets via MCP: +## Datasets Dify (Consulta Complementar) | Dataset | ID | Prioridade | |---------|----|-----------:| -| **Serviços Descomplicar** | `bd65f36e-6004-4584-b478-129b2c21b4d2` | 1 | +| **Servicos Descomplicar** | `bd65f36e-6004-4584-b478-129b2c21b4d2` | 1 | | **Vendas** | `a7ba6005-517c-41ab-ac5e-da1c1a1c62ef` | 1 | | **Marketing Digital** | `c1ec779f-4cb1-4ecf-ba11-6b39b93d4e24` | 2 | | **Desenvolvimento de WebSites** | `c8489151-de94-42b2-8cee-c0b961cfac6d` | 2 | -### Como Consultar - -```javascript -// Pesquisar serviços e preços -mcp__notebooklm__notebook_query, mcp__dify-kb__dify_kb_retrieve_segments({ - dataset_id: "bd65f36e-6004-4584-b478-129b2c21b4d2", - query: "pacote website ecommerce" -}) - -// Técnicas de proposta e negociação -mcp__dify-kb__dify_kb_retrieve_segments({ - dataset_id: "a7ba6005-517c-41ab-ac5e-da1c1a1c62ef", - query: "proposta comercial fechamento" -}) - -// Funcionalidades de websites -mcp__dify-kb__dify_kb_retrieve_segments({ - dataset_id: "c8489151-de94-42b2-8cee-c0b961cfac6d", - query: "funcionalidades website corporativo" -}) -``` - ### Quando Consultar -- Definir escopo de projecto -- Justificar preços ao cliente +- Justificar precos ao cliente - Comparar funcionalidades entre pacotes - Criar proposta de valor diferenciada +- Tecnicas de negociacao e fechamento --- -## Instrumentação Automática - -Esta skill grava métricas automaticamente para análise PDCA. +## Instrumentacao Automatica ### Baseline -| Métrica | Valor | +| Metrica | Valor | |---------|-------| | Tempo baseline | 30 min | | Tempo target | 15 min | | Melhoria esperada | -50% | -### Ao Executar Esta Skill - -1. **Início:** Registar `SKILL_START = Date.now()` -2. **Consultas KB:** Rastrear consultas Dify (KB_CONSULTED, KB_HITS) -3. **Tool calls:** Contar chamadas MCP -4. **Fim:** Gravar métrica - ### Query para Gravar (executar no final da skill) ```sql --- Executar via SSH ou MCP no final da skill INSERT INTO tblskill_agent_metrics ( type, name, duration_ms, status, staff_id, kb_consulted, kb_cache_hit, tool_calls, project_id @@ -470,29 +485,30 @@ INSERT INTO tblskill_agent_metrics ( ); ``` -### Exemplo Completo +--- -```sql --- Orçamento criado com sucesso em 20 minutos, consultou Dify, sem cache -INSERT INTO tblskill_agent_metrics ( - type, name, duration_ms, status, staff_id, - kb_consulted, kb_cache_hit, tool_calls, project_id -) VALUES ( - 'skill', '/orcamento', 1200000, 'success', 25, - 1, 0, 8, 65 -); -``` +## Changelog -### Ver Métricas +### v4.1.0 (2026-03-12) +- Suporte para variantes `-MEN` (mensal) e `-TRI` (trimestral) na sintaxe +- Fase 3 actualizada com queries especificas por variante +- Fase 5 actualizada com termos de pagamento ajustados por variante +- Mapeamento de variantes documentado (pesquisa por prefixo no CRM) +- Exemplo adicional com `-MEN` para demonstrar separacao setup/recorrencia +- Retrocompativel: sem flag = comportamento anterior (item base) -```bash -/metrics /orcamento -``` +### v4.0.0 (2026-03-05) +- **BREAKING**: Fonte de verdade migrada de CSVs para Desk CRM (tblitems + tblitems_groups) +- Removidas referencias a tabela-geral.csv, items-subscricao.csv, chatbots-precos.csv, items-faturacao-deskcrm.csv +- Adicionados grupos DeskCRM, Chatbots, AcceleratorX como tipos de orcamento +- Protocolo actualizado para consultar precos via MCP/SQL em vez de CSVs +- Tabela de referencia rapida mantida mas marcada como "nao fonte de verdade" +- Adicionada documentacao de variantes de facturacao (Investimento/Anuidade/Trimestral/Mensalidade) -### Protocolo - -Ver `~/.claude/skills/_core/instrumentation-protocol.md` +### v3.1.0 (2026-02-03) +- Instrumentacao automatica adicionada +- Datasets Dify integrados --- -**Versão**: 3.1.0 | **Data**: 2026-02-03 | **Instrumentação**: Activa +**Versao**: 4.1.0 | **Data**: 2026-03-12 | **Fonte de Verdade**: Desk CRM (tblitems) diff --git a/crm-ops/skills/proposal-deck/SKILL.md b/crm-ops/skills/proposal-deck/SKILL.md new file mode 100644 index 0000000..410914b --- /dev/null +++ b/crm-ops/skills/proposal-deck/SKILL.md @@ -0,0 +1,367 @@ +--- +name: proposal-deck +description: Geracao de apresentacoes PPTX de propostas comerciais profissionais com branding Descomplicar. Integra dados do CRM, tabela de precos e template curado de 16 layouts. +--- + +# Skill /proposal-deck - Apresentacoes de Propostas Comerciais + +Gera apresentacoes PPTX profissionais para propostas comerciais da Descomplicar, usando um template curado com 16 layouts e branding oficial. + +## Triggers + +- `/proposal-deck` +- "proposta", "apresentacao cliente", "deck proposta", "proposta comercial", "apresentacao proposta" + +## Quando Usar + +- Preparar apresentacao visual de proposta para reuniao com cliente +- Criar deck profissional para acompanhar orcamento/estimate +- Gerar proposta completa com branding para envio por email +- Complementar `/orcamento` com material visual + +## Quando NAO Usar + +- Para criar orcamento sem apresentacao (usar `/orcamento`) +- Para analise estrategica de lead (usar `/lead-approach`) +- Para operacoes CRM genericas (usar `/crm-ops`) +- Para apresentacoes sem contexto comercial (usar pptx-generator directamente) + +--- + +## Template + +**Localizacao:** `/media/ealmeida/Dados/Hub/90-Templates/Comercial/descomplicar-proposal-template.pptx` + +### Layouts Disponiveis (16) + +| # | Nome | Funcao | Quando usar | +|---|------|--------|-------------| +| 1 | capa | Titulo da proposta + subtitulo + ano | Sempre (obrigatorio) | +| 2 | divisor-seccao | Fundo escuro com titulo centrado | Entre seccoes principais | +| 3 | sobre-nos | Card texto + imagem lateral | Sempre (quem somos) | +| 4 | objectivos | Fundo escuro + objectivos + logo cliente | Sempre (o que vamos resolver) | +| 5 | processo-3-passos | 3 colunas douradas com texto | Explicar metodologia | +| 6 | fases-3-blocos | 3 blocos numerados verticais | Fases do projecto (3 items) | +| 7 | grid-4-cards | Grid 4 cards com icones | Valores, diferenciais, pilares (4 items) | +| 8 | beneficios-6 | 6 blocos com icones e setas | Beneficios (6 items) | +| 9 | pilares-engrenagens | 4 pilares em engrenagens | Solucao completa (4 pilares) | +| 10 | detalhe-servico | Titulo + features list + foto + CTA | Detalhe de um servico/pack | +| 11 | deliverables | 4 rows dourados com bullets | Lista deliverables/escopo | +| 12 | timeline-etapas | 5 etapas coloridas horizontais | Cronograma/fases com precos | +| 13 | pack-pricing | Checklist com preco e foto | Pack/avenca mensal | +| 14 | resumo-financeiro | Timeline com precos por fase | Resumo valores total | +| 15 | contacto | Foto gestor + dados | Sempre (obrigatorio) | +| 16 | encerramento | Lobo + branding nocturno | Sempre (obrigatorio) | + +### Slides Obrigatorios + +Toda proposta inclui **no minimo**: capa (1) + sobre-nos (3) + objectivos (4) + contacto (15) + encerramento (16). + +--- + +## Scripts PPTX + +**Base path:** `~/.claude/plugins/marketplaces/descomplicar-plugins/design-media/skills/pptx-generator/scripts/` + +| Script | Funcao | +|--------|--------| +| `office/unpack.py` | Descompactar PPTX em XML editavel | +| `office/pack.py` | Recompactar XML em PPTX valido | +| `clean.py` | Limpar XMLs (namespaces, refs orfas) | +| `add_slide.py` | Adicionar slides ao XML | +| `office/validate.py` | Validar estrutura do PPTX | + +--- + +## Protocolo + +### Sintaxe + +``` +/proposal-deck [cliente] [tipo] +``` + +**Parametros:** +- `cliente` - Nome ou ID do cliente (opcional, sera solicitado se omitido) +- `tipo` - Complexidade da proposta (opcional): `minima`, `standard`, `completa` + +### Fase 1: Recolha de Informacao + +1. **Identificar cliente no CRM:** + ``` + mcp__desk-crm-v3__search_customers query="[nome]" fields="company,vat" + mcp__desk-crm-v3__get_customer customer_id=[id] + ``` + +2. **Verificar orcamentos existentes:** + ``` + mcp__desk-crm-v3__get_estimates status="draft" client_id=[id] + ``` + +3. **Consultar tabela de precos** (complementar ao CRM): + - Ficheiro: `/media/ealmeida/Dados/GDrive/Cloud/Descomplicar/Servicos/tabela-geral.csv` + - CRM (fonte de verdade): `mcp__desk-crm-v3__price_management action="get_pricing_insights"` + +4. **Solicitar dados em falta** (se nao disponiveis no CRM): + +| Campo | Obrigatorio | Default | +|-------|:-----------:|---------| +| Nome do cliente | Sim | — | +| Sector/industria | Sim | — | +| Objectivos | Sim | — | +| Servicos a propor | Sim | — | +| Precos | Sim | CRM | +| Prazo estimado | Nao | "a definir" | +| Gestor de conta | Nao | Emanuel Almeida | + +### Fase 2: Seleccao de Layouts + +Seleccionar layouts com base na complexidade e servicos propostos. + +#### Proposta Minima (8 slides) +Para projectos simples, orcamentos rapidos. + +| Ordem | Layout | Conteudo | +|:-----:|--------|----------| +| 1 | capa | "Proposta [Servico]" + nome cliente + ano | +| 2 | sobre-nos | Apresentacao Descomplicar | +| 3 | objectivos | 3-5 objectivos do cliente | +| 4 | processo-3-passos | Metodologia de trabalho | +| 5 | deliverables | O que esta incluido | +| 6 | pack-pricing | Preco + o que inclui | +| 7 | contacto | Dados do gestor | +| 8 | encerramento | Branding Descomplicar | + +#### Proposta Standard (12 slides) +Para projectos de media complexidade (websites, marketing). + +| Ordem | Layout | Conteudo | +|:-----:|--------|----------| +| 1 | capa | Titulo + cliente + ano | +| 2 | sobre-nos | Apresentacao Descomplicar | +| 3 | divisor-seccao | "Desafio" | +| 4 | objectivos | Objectivos do cliente | +| 5 | processo-3-passos | Metodologia | +| 6 | fases-3-blocos | Fases do projecto | +| 7 | divisor-seccao | "Solucao" | +| 8 | beneficios-6 | Beneficios da solucao | +| 9 | deliverables | Escopo detalhado | +| 10 | timeline-etapas | Cronograma com precos | +| 11 | contacto | Dados do gestor | +| 12 | encerramento | Branding Descomplicar | + +#### Proposta Completa (16 slides) +Para projectos complexos, concursos, clientes enterprise. + +Usa todos os 16 layouts na ordem numerica original. + +### Fase 3: Geracao do PPTX + +**Directorio de trabalho:** `~/.claude-work/proposal-[cliente-slug]/` + +```bash +# 1. Criar directorio e copiar template +mkdir -p ~/.claude-work/proposal-[slug]/ +cp "/media/ealmeida/Dados/Hub/90-Templates/Comercial/descomplicar-proposal-template.pptx" \ + ~/.claude-work/proposal-[slug]/template.pptx + +# 2. Descompactar template +python3 ~/.claude/plugins/marketplaces/descomplicar-plugins/design-media/skills/pptx-generator/scripts/office/unpack.py \ + ~/.claude-work/proposal-[slug]/template.pptx \ + ~/.claude-work/proposal-[slug]/unpacked/ + +# 3. Editar slides XML (ver seccao "Edicao de Conteudo XML") + +# 4. Remover slides nao necessarios de presentation.xml +# (alterar rIdX refs e apagar ficheiros slideN.xml correspondentes) + +# 5. Limpar XMLs +python3 ~/.claude/plugins/marketplaces/descomplicar-plugins/design-media/skills/pptx-generator/scripts/clean.py \ + ~/.claude-work/proposal-[slug]/unpacked/ + +# 6. Recompactar +python3 ~/.claude/plugins/marketplaces/descomplicar-plugins/design-media/skills/pptx-generator/scripts/office/pack.py \ + ~/.claude-work/proposal-[slug]/unpacked/ \ + ~/.claude-work/proposal-[slug]/proposta-[slug].pptx \ + --original ~/.claude-work/proposal-[slug]/template.pptx +``` + +### Edicao de Conteudo XML + +Cada slide e um ficheiro `ppt/slides/slideN.xml`. Localizar placeholders pelo texto visivel e substituir: + +| Placeholder | Substituir por | Exemplo | +|-------------|----------------|---------| +| `[TITULO_PROPOSTA]` | Nome do servico proposto | "Website Corporativo" | +| `[SUBTITULO]` | Nome do cliente | "Para Empresa XYZ" | +| `[ANO]` | Ano corrente | "2026" | +| `[OBJECTIVO_N]` | Objectivo N do cliente | "Aumentar presenca online" | +| `[FASE_N_TITULO]` | Titulo da fase N | "Fase 1: Descoberta" | +| `[FASE_N_DESC]` | Descricao da fase N | "Analise de requisitos..." | +| `[DELIVERABLE_N]` | Item do escopo | "Website responsivo" | +| `[PRECO]` | Valor formatado | "1.200 EUR" | +| `[PRECO_TOTAL]` | Valor total | "2.500 EUR + IVA" | +| `[TIMELINE_N]` | Etapa do cronograma | "Semana 1-2" | +| `[GESTOR_NOME]` | Nome do gestor | "Emanuel Almeida" | +| `[GESTOR_EMAIL]` | Email do gestor | "emanuel@descomplicar.pt" | +| `[GESTOR_TEL]` | Telefone | "911 510 005" | + +**Tecnica XML:** Localizar `` tags dentro de `` runs. Substituir texto preservando formatacao: + +```python +# Exemplo: substituir texto num slide +import re + +def replace_placeholder(xml_content, placeholder, value): + """Substituir placeholder preservando formatacao XML.""" + # Placeholders podem estar fragmentados em multiplos tags + # Usar regex para localizar e substituir + return xml_content.replace(placeholder, value) +``` + +**Regra critica:** Nunca alterar atributos de formatacao (``, ``). Apenas substituir conteudo textual dentro de ``. + +### Fase 4: Entrega + +1. **Guardar PPTX final:** + ``` + Hub/03-Propostas/[cliente]/proposta-[servico]-[data].pptx + ``` + +2. **Upload para Google Drive** (opcional): + ``` + mcp__google-workspace__drive_upload_file + file_path="~/.claude-work/proposal-[slug]/proposta-[slug].pptx" + folder_id="[pasta-cliente-drive]" + ``` + +3. **Registar no CRM** (se nao existir estimate): + ``` + mcp__desk-crm-v3__create_estimate + client_id=[id] + date=[hoje] + expiry_date=[hoje + 30 dias] + items=[items] + ``` + +4. **Limpar temporarios:** + ```bash + rm -rf ~/.claude-work/proposal-[slug]/ + ``` + +--- + +## Exemplos de Propostas Tipicas + +### Website Corporativo (CorporateWP) + +**Tipo:** Standard (12 slides) +**Servico:** CorporateWP +**Slides seleccionados:** capa, sobre-nos, divisor, objectivos, processo-3-passos, fases-3-blocos, divisor, beneficios-6, deliverables, timeline-etapas, contacto, encerramento + +**Conteudo tipico:** +- **Objectivos:** Presenca profissional online, geracao de leads, credibilidade digital +- **3 Passos:** Descoberta -> Desenvolvimento -> Lancamento +- **3 Fases:** Analise e Conteudo (S1-2) -> Design e Desenvolvimento (S3-5) -> Testes e Lancamento (S6) +- **6 Beneficios:** Design responsivo, SEO optimizado, painel intuitivo, SSL incluido, suporte dedicado, performance rapida +- **Deliverables:** Website responsivo, 5-8 paginas, formularios, integracao redes sociais, Google Analytics, formacao +- **Timeline:** 4-6 semanas, 900 EUR + IVA, anuidade 299 EUR + +### Marketing 360 + +**Tipo:** Completa (16 slides) +**Servico:** Marketing Digital 360 +**Slides seleccionados:** todos os 16 + +**Conteudo tipico:** +- **Objectivos:** Aumentar visibilidade, gerar leads qualificados, ROI mensuravel, posicionamento digital +- **4 Pilares (engrenagens):** SEO, Redes Sociais, Publicidade Online, Email Marketing +- **Processo:** Auditoria -> Estrategia -> Execucao +- **6 Beneficios:** Mais trafego, leads qualificados, brand awareness, ROI mensuravel, relatorios mensais, equipa dedicada +- **Deliverables:** Auditoria inicial, plano estrategico, gestao redes sociais, campanhas Ads, relatorios mensais, reunioes quinzenais +- **Timeline:** Ongoing, setup 500-1500 EUR, mensalidade 300-800 EUR + +### SEO / Optimizacao + +**Tipo:** Standard (12 slides) +**Servico:** Pack SEO +**Slides seleccionados:** capa, sobre-nos, divisor, objectivos, processo-3-passos, grid-4-cards, divisor, detalhe-servico, deliverables, pack-pricing, contacto, encerramento + +**Conteudo tipico:** +- **Objectivos:** Melhorar posicionamento Google, aumentar trafego organico, ultrapassar concorrencia +- **3 Passos:** Auditoria Tecnica -> Optimizacao On-Page -> Link Building +- **4 Cards:** Pesquisa Keywords, SEO Tecnico, Conteudo Optimizado, Relatorios Mensais +- **Deliverables:** Auditoria inicial, optimizacao 10-20 paginas, blog mensal, relatorio posicoes, Google Search Console +- **Pricing:** Mensalidade 300-600 EUR conforme pack + +--- + +## MCPs Utilizados + +``` +mcp__desk-crm-v3__search_customers - Pesquisar cliente +mcp__desk-crm-v3__get_customer - Obter detalhes cliente +mcp__desk-crm-v3__get_estimates - Verificar orcamentos existentes +mcp__desk-crm-v3__create_estimate - Registar estimate no CRM +mcp__desk-crm-v3__price_management - Consultar precos oficiais +mcp__google-workspace__drive_upload_file - Upload para Google Drive +mcp__mcp-time__current_time - Data/hora actual +``` + +--- + +## Checklist de Execucao + +- [ ] Cliente identificado no CRM +- [ ] Dados recolhidos (objectivos, servicos, precos) +- [ ] Tipo de proposta seleccionado (minima/standard/completa) +- [ ] Layouts seleccionados e conteudo definido +- [ ] Template copiado para ~/.claude-work/ +- [ ] PPTX descompactado +- [ ] Slides editados com dados do cliente +- [ ] Slides desnecessarios removidos +- [ ] XMLs limpos (clean.py) +- [ ] PPTX recompactado e validado +- [ ] Ficheiro guardado em Hub/03-Propostas/[cliente]/ +- [ ] Temporarios limpos +- [ ] Estimate registado no CRM (se aplicavel) + +--- + +## Anti-Patterns + +| Fazer | NAO Fazer | +|-------|-----------| +| Personalizar cada slide com dados reais do cliente | Usar placeholders genericos ou "Lorem ipsum" | +| Consultar CRM para precos actualizados | Inventar precos de memoria | +| Seleccionar layouts relevantes para o servico | Incluir todos os 16 slides quando 8 bastam | +| Manter branding Descomplicar (cores, fontes, logo) | Alterar formatacao XML (cores, tamanhos, posicoes) | +| Guardar em Hub/03-Propostas/ com nome descritivo | Deixar ficheiros em ~/.claude-work/ | +| Usar slug sem espacos no nome do ficheiro | Espacos ou caracteres especiais no nome | +| Verificar PPTX abre correctamente apos geracao | Entregar sem validar | +| Adaptar objectivos ao sector do cliente | Copiar objectivos genericos entre propostas | +| Incluir dados de contacto do gestor real | Dados de contacto ficticios | + +--- + +## Procedimentos Relacionados + +- `PROC-Catalogo-Codificacao-Produtos.md` - Codificacao e catalogo de produtos +- `PROC-CRM-Operacoes.md` - Operacoes CRM padrao + +--- + +## Changelog + +### v1.0.0 (2026-03-06) +- Versao inicial da skill /proposal-deck +- 16 layouts mapeados do template PPTX curado +- 3 niveis de complexidade: minima (8), standard (12), completa (16) +- Integracao CRM (cliente, estimates, precos) +- Workflow completo: recolha -> seleccao -> geracao -> entrega +- Exemplos para website, marketing 360, SEO +- Anti-patterns documentados + +--- + +**Versao**: 1.0.0 | **Data**: 2026-03-06 | **Template**: descomplicar-proposal-template.pptx diff --git a/crm-ops/skills/ticket-triage/SKILL.md b/crm-ops/skills/ticket-triage/SKILL.md index b755bbc..3cf55a5 100644 --- a/crm-ops/skills/ticket-triage/SKILL.md +++ b/crm-ops/skills/ticket-triage/SKILL.md @@ -1,25 +1,7 @@ --- name: ticket-triage -description: > - Auto-processamento de tickets abertos no Desk CRM. Fecha SPAM, identifica facturas para /auto-expense, protege notificacoes de sistema. Use when "tickets", "triagem tickets", "limpar tickets", "ticket triage", "processar tickets". -author: Descomplicar® Crescimento Digital -version: 1.0.0 -quality_score: 85 -user_invocable: true -category: crm -tags: [tickets, triage, spam, invoices, notifications, desk-crm] -desk_task: 1710 -desk_project: 65 -allowed-tools: Read, Write, mcp__desk-crm-v3 -mcps: desk-crm-v3 -dependencies: - mcps: [desk-crm-v3] - files: - - /media/ealmeida/Dados/Hub/06-Operacoes/Documentacao/fornecedores-recorrentes.md -triggers: - - "User asks to process tickets" - - "User mentions 'tickets', 'triagem', 'limpar tickets'" - - "Invoked by /today orchestrator" +description: Auto-processamento de tickets abertos no Desk CRM. Fecha SPAM, identifica facturas para /auto-expense e protege notificações de sistema. +disable-model-invocation: true --- # /ticket-triage v1.0 diff --git a/crm-ops/skills/ticket/SKILL.md b/crm-ops/skills/ticket/SKILL.md index 4f36e1f..fb6d6b3 100644 --- a/crm-ops/skills/ticket/SKILL.md +++ b/crm-ops/skills/ticket/SKILL.md @@ -1,17 +1,7 @@ --- name: ticket -description: > - Gestão de tickets de suporte Desk CRM v1.0. Ver, responder, fechar, escalar. - Use when "ticket", "suporte", "support", "incidente", "helpdesk". -author: Descomplicar® Crescimento Digital -version: 1.0.0 -quality_score: 75 -user_invocable: true -category: business -tags: [ticket, support, suporte, helpdesk, desk, crm] -desk_project: 65 -allowed-tools: Read, mcp__desk-crm-v3, mcp__mcp-time -mcps: desk-crm-v3, mcp-time +description: Gestão de tickets de suporte Desk CRM. Ver, responder, fechar e escalar tickets. Inclui templates de resposta e integração com /today. +disable-model-invocation: true --- # /ticket v1.0 - Gestão de Suporte diff --git a/design-media/agents/ui-designer.md b/design-media/agents/ui-designer.md index 9fa0de4..116b19d 100644 --- a/design-media/agents/ui-designer.md +++ b/design-media/agents/ui-designer.md @@ -49,14 +49,6 @@ mcp__notebooklm__notebook_query notebook_id:"5be0d1a6-00f2-4cd9-b835-978cb772160 mcp__notebooklm__notebook_query notebook_id:"9053d0e8-dd39-460b-b5ea-e67af3e9a675" query:"visual design tipografia cores" ``` -### Dify KB (Secundario - se NotebookLM insuficiente) - -``` -mcp__dify-kb__dify_kb_retrieve_segments dataset:"UX e Usabilidade" query:"interface design sistemas componentes" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Desenvolvimento de WebSites" query:"design responsivo layouts" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Canva" query:"visual design tipografia cores" -``` - ## System Prompt ### Papel @@ -114,11 +106,6 @@ Designer de interfaces responsavel por criar designs visuais apelativos, manter - **Consistency**: Mesmos patterns = menos cognitive load - **Feedback**: Sistema responde a accoes (loaders, confirmacoes) - **Simplicity**: Remover tudo que nao adiciona valor - -## Datasets Dify (Consultar SEMPRE) -``` -mcp__dify-kb__dify_kb_retrieve_segments dataset:"UX e Usabilidade" query:"interface design componentes acessibilidade" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Canva" query:"design visual tipografia cores" ``` ## Colaboracao @@ -144,13 +131,11 @@ mcp__dify-kb__dify_kb_retrieve_segments dataset:"Canva" query:"design visual tip - **elevenlabs** - Text-to-speech, voice cloning, audio transcription - **vimeo** - Video management - upload, metadata, transcripts, analytics -### All Available (33 total) -desk-crm-v3, moloni, context7, gitea, n8n, cwp, filesystem, ssh-unified, google-analytics, imap, outline-api, youtube-research, youtube-uploader, dify-kb, wikijs, gsc, lighthouse, mcp-time, memory-supabase, puppeteer, tavily, replicate +### All Available (32 total) +desk-crm-v3, moloni, context7, gitea, n8n, cwp, filesystem, ssh-unified, google-analytics, imap, outline-api, youtube-research, youtube-uploader, wikijs, gsc, lighthouse, mcp-time, memory-supabase, puppeteer, tavily, replicate **Discovery:** Use ToolSearch to find specific tools. **Example:** `ToolSearch("ssh upload")` finds SSH upload tools. - - ## Your Available Skills ### Primary Skills (Your Domain) @@ -175,13 +160,11 @@ desk-crm-v3, moloni, context7, gitea, n8n, cwp, filesystem, ssh-unified, google- - **/knowledge** - Gestão unificada de conhecimento - pesquisa inteligente com - **/desk** - Integração com Desk CRM via ficheiro .desk-project. Auto-det -### All Available (54 total) +### All Available (53 total) /billing-check, /crm-ops, /ecommerce, /lead-approach, /orcamento, /saas, /content-marketing-pt, /seo-content-optimization, /social-media, /ui-ux-pro-max-repo, /crm-admin, /db-design, /elementor, /mcp-dev, /nextjs, /php-dev, /react-patterns, /woocommerce, /wp-dev, /backup-strategies, /security-audit, /server-health, /wp-performance, /wp-update, /second-brain-repo, /ads, /doc-sync, /marketing-strategy, /product, /skill-creator, /sop-creator, /calendar-manager, /delegate, /interview, /time, /today, /research, /youtube, /seo-audit, /seo-report, /archive, /metrics, /sdk **Discovery:** Use the Skill tool to invoke skills. **Example:** `Skill("skill-name")` invokes the skill. - - ## Your Team & Responsibilities You are part of **11 SDKs** (TaskForce teams): @@ -195,9 +178,6 @@ You are part of **11 SDKs** (TaskForce teams): **Purpose:** NULL **Your responsibilities in this TaskForce:** - -- **Sistema de agentes especializados para delegacao de tarefas via Task tool com consulta automatica de datasets Dify.**: NULL - ### TaskForce E-commerce **Purpose:** NULL diff --git a/design-media/agents/video-production-specialist.md b/design-media/agents/video-production-specialist.md index fd094b0..a9492a6 100644 --- a/design-media/agents/video-production-specialist.md +++ b/design-media/agents/video-production-specialist.md @@ -32,8 +32,6 @@ created: '2025-01-13' updated: '2026-02-04' author: Descomplicar® --- - - # Video Production Specialist Descomplicar Especialista em criacao de videos programaticos usando Remotion e React para produzir intros, promos, social media content e tutoriais animados escaláveis. @@ -110,13 +108,6 @@ mcp__notebooklm__notebook_query notebook_id:"76647e0f-3ae2-4c00-a0a8-f457aebf565 mcp__notebooklm__notebook_query notebook_id:"081ca512-8279-4850-b2b9-dff090267482" query:"animacao storytelling" ``` -### Dify KB (Secundario - se NotebookLM insuficiente) - -``` -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Marketing Digital" query:"video conteudo visual" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Criatividade" query:"animacao storytelling" -``` - ## Colaboracao - Reports to: Creative Director - Colabora com: Social Media Manager, Motion Designer, Copywriter @@ -136,13 +127,11 @@ mcp__dify-kb__dify_kb_retrieve_segments dataset:"Criatividade" query:"animacao s - **outline-api** - Outline documentation - **replicate** - AI models - imagem, vídeo, áudio, LLMs -### All Available (33 total) -desk-crm-v3, moloni, context7, gitea, n8n, cwp, filesystem, ssh-unified, google-analytics, imap, dify-kb, wikijs, gsc, lighthouse, mcp-time, memory-supabase, puppeteer, mcp-mermaid, mcp-echarts, powerpoint, penpot, pixabay, pexels, tavily, magic, design-systems +### All Available (32 total) +desk-crm-v3, moloni, context7, gitea, n8n, cwp, filesystem, ssh-unified, google-analytics, imap, wikijs, gsc, lighthouse, mcp-time, memory-supabase, puppeteer, mcp-mermaid, mcp-echarts, powerpoint, penpot, pixabay, pexels, tavily, magic, design-systems **Discovery:** Use ToolSearch to find specific tools. **Example:** `ToolSearch("ssh upload")` finds SSH upload tools. - - ## Your Available Skills ### Primary Skills (Your Domain) @@ -168,7 +157,7 @@ desk-crm-v3, moloni, context7, gitea, n8n, cwp, filesystem, ssh-unified, google- - **/knowledge** - Gestão unificada de conhecimento - pesquisa inteligente com - **/desk** - Integração com Desk CRM via ficheiro .desk-project. Auto-det -### All Available (54 total) +### All Available (53 total) /billing-check, /crm-ops, /ecommerce, /lead-approach, /orcamento, /saas, /ui-ux-pro-max-repo, /brand-voice-generator, /frontend-design, /pptx-generator, /ui-ux-pro-max, /crm-admin, /db-design, /elementor, /mcp-dev, /nextjs, /php-dev, /react-patterns, /woocommerce, /wp-dev, /backup-strategies, /security-audit, /server-health, /wp-performance, /wp-update, /second-brain-repo, /ads, /doc-sync, /marketing-strategy, /product, /skill-creator, /sop-creator, /calendar-manager, /delegate, /interview, /time, /today, /seo-audit, /seo-report, /archive, /metrics, /sdk **Discovery:** Use the Skill tool to invoke skills. diff --git a/design-media/agents/web-designer.md b/design-media/agents/web-designer.md index 54958e3..89f59ea 100644 --- a/design-media/agents/web-designer.md +++ b/design-media/agents/web-designer.md @@ -48,15 +48,6 @@ mcp__notebooklm__notebook_query notebook_id:"5be0d1a6-00f2-4cd9-b835-978cb772160 mcp__notebooklm__notebook_query notebook_id:"081ca512-8279-4850-b2b9-dff090267482" query:"conversao usabilidade navegacao" ``` -### Dify KB (Secundario - se NotebookLM insuficiente) - -``` -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Desenvolvimento de WebSites" query:"layouts design web responsivo" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"WordPress" query:"themes templates design" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Elementor" query:"page builder design visual" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"UX e Usabilidade" query:"conversao usabilidade navegacao" -``` - ## System Prompt ### Papel @@ -117,12 +108,6 @@ Designer web responsavel por criar layouts visualmente impactantes e funcionais, - **White space**: Dar espaco para respirar, nao sobrecarregar - **Hierarchy**: Tamanhos, cores, contraste para guiar olho - **Responsiveness**: Breakpoints logicos (mobile, tablet, desktop) - -## Datasets Dify (Consultar SEMPRE) -``` -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Desenvolvimento de WebSites" query:"layouts design responsivo conversao" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"WordPress" query:"temas templates design" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"UX e Usabilidade" query:"navegacao usabilidade heuristicas" ``` ## Colaboracao @@ -148,13 +133,11 @@ mcp__dify-kb__dify_kb_retrieve_segments dataset:"UX e Usabilidade" query:"navega - **elevenlabs** - Text-to-speech, voice cloning, audio transcription - **vimeo** - Video management - upload, metadata, transcripts, analytics -### All Available (33 total) -desk-crm-v3, moloni, context7, gitea, n8n, cwp, filesystem, ssh-unified, google-analytics, imap, outline-api, youtube-research, youtube-uploader, dify-kb, wikijs, gsc, lighthouse, mcp-time, memory-supabase, puppeteer, tavily, replicate +### All Available (32 total) +desk-crm-v3, moloni, context7, gitea, n8n, cwp, filesystem, ssh-unified, google-analytics, imap, outline-api, youtube-research, youtube-uploader, wikijs, gsc, lighthouse, mcp-time, memory-supabase, puppeteer, tavily, replicate **Discovery:** Use ToolSearch to find specific tools. **Example:** `ToolSearch("ssh upload")` finds SSH upload tools. - - ## Your Available Skills ### Primary Skills (Your Domain) @@ -179,13 +162,11 @@ desk-crm-v3, moloni, context7, gitea, n8n, cwp, filesystem, ssh-unified, google- - **/knowledge** - Gestão unificada de conhecimento - pesquisa inteligente com - **/desk** - Integração com Desk CRM via ficheiro .desk-project. Auto-det -### All Available (54 total) +### All Available (53 total) /billing-check, /crm-ops, /ecommerce, /lead-approach, /orcamento, /saas, /content-marketing-pt, /seo-content-optimization, /social-media, /ui-ux-pro-max-repo, /crm-admin, /db-design, /elementor, /mcp-dev, /nextjs, /php-dev, /react-patterns, /woocommerce, /wp-dev, /backup-strategies, /security-audit, /server-health, /wp-performance, /wp-update, /second-brain-repo, /ads, /doc-sync, /marketing-strategy, /product, /skill-creator, /sop-creator, /calendar-manager, /delegate, /interview, /time, /today, /research, /youtube, /seo-audit, /seo-report, /archive, /metrics, /sdk **Discovery:** Use the Skill tool to invoke skills. **Example:** `Skill("skill-name")` invokes the skill. - - ## Your Team & Responsibilities You are part of **7 SDKs** (TaskForce teams): @@ -195,9 +176,6 @@ You are part of **7 SDKs** (TaskForce teams): **Purpose:** NULL **Your responsibilities in this TaskForce:** - -- **Sistema de agentes especializados para delegacao de tarefas via Task tool com consulta automatica de datasets Dify.**: NULL - ### TaskForce E-commerce **Purpose:** NULL diff --git a/design-media/knowledge/datasets.json b/design-media/knowledge/datasets.json index cee1dac..d9f6931 100644 --- a/design-media/knowledge/datasets.json +++ b/design-media/knowledge/datasets.json @@ -1,5 +1,5 @@ { - "description": "Knowledge sources (NotebookLM + Dify KB) for Design and Media domain", + "description": "Knowledge sources for Design and Media domain", "sources": { "notebooklm": { "description": "NotebookLM - conhecimento curado profundo via Gemini 2.5 RAG (PRIMARIO)", @@ -10,16 +10,14 @@ "title": "Social Media e Branding", "topics": [ "canva" - ], - "maps_from_dify": "Canva" + ] }, { "id": "081ca512-8279-4850-b2b9-dff090267482", "title": "UI/UX Design", "topics": [ "usabilidade" - ], - "maps_from_dify": "UX e Usabilidade" + ] } ], "pending": [ @@ -35,33 +33,6 @@ } ] }, - "dify_kb": { - "description": "Dify KB - datasets tematicos (FALLBACK)", - "query_tool": "mcp__dify-kb__dify_kb_retrieve_segments", - "datasets": [ - { - "id": "7efc5db4-05b1-408a-9e41-b612188ee877", - "name": "Canva", - "priority": 1, - "document_count": 24, - "word_count": 148976 - }, - { - "id": "e14ab89e-8910-43b6-becf-d57c78afd62d", - "name": "UX e Usabilidade", - "priority": 1, - "document_count": 4, - "word_count": 413593 - }, - { - "id": "39818f77-8c70-4729-9b5c-6f92d3a2b418", - "name": "Criatividade", - "priority": 2, - "document_count": 9, - "word_count": 262795 - } - ] - }, "brand_packs": { "description": "Brand packs JSON para identidade visual por cliente", "path": "/media/ealmeida/Dados/Hub/04-Recursos/Design/brands/", @@ -69,8 +40,15 @@ { "slug": "descomplicar", "name": "Descomplicar - Consultoria e Desenvolvimento", - "colors": {"primary": "#dd7500", "secondary": "#cc8d00", "accent": "#f2d9a2"}, - "fonts": {"heading": "Nexa", "body": "Roboto"} + "colors": { + "primary": "#dd7500", + "secondary": "#cc8d00", + "accent": "#f2d9a2" + }, + "fonts": { + "heading": "Nexa", + "body": "Roboto" + } } ] } diff --git a/design-media/skills/brand-guidelines/SKILL.md b/design-media/skills/brand-guidelines/SKILL.md new file mode 100644 index 0000000..42d5940 --- /dev/null +++ b/design-media/skills/brand-guidelines/SKILL.md @@ -0,0 +1,318 @@ +--- +name: brand-guidelines +description: Guia de identidade visual Descomplicar® — cores, tipografia, logotipo, tom de comunicacao e aplicacao por contexto (slides, docs, web, emails). Usar quando "brand descomplicar", "marca descomplicar", "cores descomplicar", "identidade visual", "branding", "paleta de cores", "guia de marca", ou qualquer material que necessite conformidade visual com a marca. +--- + +# /brand-guidelines - Identidade Visual Descomplicar® + +Referencia normativa da marca Descomplicar®. Aplicar em todos os materiais de comunicacao, +design e desenvolvimento. + +--- + +## Identidade da Marca + +**Nome oficial:** Descomplicar® +**Slogan:** Crescimento Digital +**Website:** descomplicar.pt +**Tom:** Profissional mas acessivel, tecnologico sem ser frio +**Valores:** Simplicidade, transparencia, resultados mensuraveis + +> A marca registada (®) e obrigatoria na primeira ocorrencia em qualquer documento ou comunicacao. +> Nas ocorrencias seguintes, pode usar-se apenas "Descomplicar". + +--- + +## Paleta de Cores Principal + +| Nome | Hex | RGB | Uso | +|------|-----|-----|-----| +| Azul Escuro | `#1a365d` | 26, 54, 93 | Texto principal, fundos escuros, cabecalhos | +| Azul Medio | `#2b6cb0` | 43, 108, 176 | Links, acentos, botoes secundarios | +| Laranja | `#dd6b20` | 221, 107, 32 | CTA, destaques, elementos de accao | +| Branco | `#ffffff` | 255, 255, 255 | Fundos claros, texto sobre escuro | +| Cinza Claro | `#f7fafc` | 247, 250, 252 | Fundos secundarios, secoes alternadas | +| Cinza Texto | `#4a5568` | 74, 85, 104 | Texto de corpo, descricoes | + +Paleta completa com variacoes de contexto: `references/color-palettes.md` + +--- + +## CSS Variables (Web) + +```css +:root { + /* Cores principais */ + --color-primary: #1a365d; + --color-secondary: #2b6cb0; + --color-accent: #dd6b20; + + /* Neutros */ + --color-white: #ffffff; + --color-bg-light: #f7fafc; + --color-text-body: #4a5568; + --color-text-heading: #1a365d; + + /* Estados */ + --color-primary-hover: #2a4a7f; + --color-secondary-hover: #2c5282; + --color-accent-hover: #c05621; + + /* Bordas e divisores */ + --color-border: #e2e8f0; + --color-border-light: #edf2f7; +} +``` + +--- + +## Tipografia + +### Hierarquia + +| Elemento | Familia | Peso | Tamanho base | +|----------|---------|------|--------------| +| H1 / Titulo principal | Montserrat | Extra Bold (800) | 48px / 3rem | +| H2 / Titulo secao | Montserrat | Bold (700) | 36px / 2.25rem | +| H3 / Subtitulo | Montserrat | Semi Bold (600) | 24px / 1.5rem | +| H4 / Label | Montserrat | Semi Bold (600) | 18px / 1.125rem | +| Corpo / Paragrafo | Open Sans | Regular (400) | 16px / 1rem | +| Destaque / Lead | Open Sans | Semi Bold (600) | 18px / 1.125rem | +| Legenda / Caption | Open Sans | Regular (400) | 14px / 0.875rem | +| Codigo | JetBrains Mono | Regular (400) | 14px / 0.875rem | + +### CSS Tipografia + +```css +:root { + --font-heading: 'Montserrat', 'Arial Black', sans-serif; + --font-body: 'Open Sans', 'Helvetica Neue', Arial, sans-serif; + --font-code: 'JetBrains Mono', 'Fira Code', 'Courier New', monospace; + + --line-height-heading: 1.2; + --line-height-body: 1.6; + --letter-spacing-heading: -0.025em; +} +``` + +### Fallbacks de Sistema + +- **Montserrat** indisponivel: `'Arial Black', 'Impact', sans-serif` +- **Open Sans** indisponivel: `'Helvetica Neue', Arial, sans-serif` +- **JetBrains Mono** indisponivel: `'Fira Code', 'Courier New', monospace` + +--- + +## Logótipo + +### Regras de Uso + +| Regra | Descricao | +|-------|-----------| +| Espaco minimo | Margem de pelo menos 2x a altura da letra "D" em todos os lados | +| Tamanho minimo | 120px de largura em digital; 30mm em impressao | +| Fundo permitido | Branco `#ffffff`, Azul Escuro `#1a365d`, Cinza Claro `#f7fafc` | +| Fundo proibido | Qualquer fundo com baixo contraste, fotografias sem overlay | +| Distorcao | Nunca esticar, rodar ou alterar proporcoes | +| Cores proibidas | Nunca alterar as cores do logótipo original | +| Texto junto | Nunca sobrepor texto ao logótipo | + +### Variantes Disponiveis + +| Variante | Quando usar | +|----------|-------------| +| Principal (horizontal) | Uso geral, cabecalhos, documentos | +| Compacta (icone + nome vertical) | Espacos reduzidos, avatares | +| Monocromatica escura | Documentos a preto e branco, impressao simples | +| Monocromatica clara | Sobre fundos escuros, rodapes | +| Icone isolado | Favicon, app icon, redes sociais (foto de perfil) | + +### Ficheiros Logótipo + +``` +Hub/04-Recursos/Design/brands/descomplicar/ + logo-principal.svg + logo-compacto.svg + logo-mono-escuro.svg + logo-mono-claro.svg + favicon.png + favicon.svg +``` + +--- + +## Aplicacao por Contexto + +### Apresentacoes e Slides + +``` +Fundo slides: #1a365d (escuro) ou #ffffff (claro) +Titulo slide: Montserrat Extra Bold, #ffffff (sobre escuro) / #1a365d (sobre claro) +Corpo texto: Open Sans Regular, #ffffff ou #4a5568 +Destaques/CTA: #dd6b20 +Divisores: #2b6cb0 +Slide titulo (capa): fundo #1a365d, logótipo variante clara +``` + +Modelo: `/design presentation --brand descomplicar` + +### Documentos e Propostas + +``` +Cabecalho: fundo #1a365d, logótipo clara, texto branco +Corpo: fundo #ffffff, texto #4a5568 +Titulos secao: Montserrat Bold, #1a365d +Destaques/callouts: fundo #f7fafc, borda esquerda #dd6b20 +Links: #2b6cb0, sublinhado no hover +Rodape: fundo #f7fafc, texto #4a5568, borda topo #e2e8f0 +``` + +### Web e Landing Pages + +``` +Hero section: fundo #1a365d ou gradiente #1a365d -> #2b6cb0 +Botao primario (CTA): fundo #dd6b20, texto #ffffff, hover #c05621 +Botao secundario: borda #2b6cb0, texto #2b6cb0, hover fundo #2b6cb0 branco +Seccao alternada: fundo #f7fafc +Cards: fundo #ffffff, sombra suave, borda-topo #2b6cb0 (destaque) +Cards destaque: borda-topo ou borda-esquerda #dd6b20 +``` + +### Emails e Newsletter + +``` +Pre-header: fundo #1a365d, texto #ffffff +Corpo email: fundo #ffffff, texto #4a5568 +Cabecalhos: Montserrat Bold, #1a365d +CTA button: fundo #dd6b20, texto #ffffff, border-radius 4px +Rodape email: fundo #f7fafc, texto #4a5568 (tamanho reduzido) +Links: #2b6cb0 +``` + +### Redes Sociais + +``` +Fundo posts: #1a365d (principal) ou #ffffff +Texto sobre escuro: #ffffff (titulo), #f7fafc (corpo) +Texto sobre claro: #1a365d (titulo), #4a5568 (corpo) +Elemento de marca (cantos, bandas): #dd6b20 ou #2b6cb0 +Hashtags/links: #2b6cb0 +``` + +--- + +## Tom de Comunicacao + +### Principios + +| Principio | Descricao | +|-----------|-----------| +| Claro e directo | Frases curtas, vocabulario acessivel, sem jargao desnecessario | +| Confiante mas humilde | Mostramos resultados, nao promessas vazias | +| Tecnico sem ser frio | Tecnologia ao servico das pessoas, nao o contrario | +| Orientado a resultados | Sempre ligar accoes a beneficios mensuravelis | +| Em portugues correcto | PT-PT sempre, sem brasileirismos, sem calao | + +### Vocabulario da Marca + +| Usar | Evitar | +|------|--------| +| crescimento digital | growth hacking | +| resultados mensuraveis | metricas (sem contexto) | +| simplicidade | user-friendly (em textos publicos) | +| parceiros / clientes | users / leads (em comunicacao externa) | +| solucoes | produtos (quando sao servicos) | +| equipa | time (brasileirismo) | + +### Voz por Canal + +- **Website / Propostas:** Formal-acessivel. Nos apresentamos, o cliente decide. +- **Redes Sociais:** Mais conversacional, com pergunta ou convite a interaccao. +- **Emails:** Directo e pessoal, nome do destinatario sempre que possivel. +- **Documentacao tecnica:** Preciso e estruturado, sem ambiguidade. + +--- + +## Iconografia e Imagens + +### Icones + +- **Estilo:** Linear, peso medio (1.5-2px), cantos ligeiramente arredondados +- **Bibliotecas recomendadas:** Lucide Icons, Heroicons, Phosphor Icons +- **Tamanhos:** 16px, 20px, 24px, 32px (escala 4px) +- **Cor:** Herdar da cor de texto do contexto ou usar cor de acento + +### Fotografia + +- **Estilo:** Profissional, luminosa, pessoas reais em contexto de trabalho +- **Tratamento:** Sem filtros excessivos; overlay azul escuro (#1a365d, 20-40% opacidade) para texto +- **Evitar:** Stock photos genericas, imagens de baixa qualidade, estilos vintage/retro + +### Ilustracoes e Graficos + +- **Estilo:** Flat design com linhas limpas, paleta restrita as cores da marca +- **Graficos de dados:** Usar sempre cores da paleta principal, legenda clara +- **Infograficos:** Fundo branco ou cinza claro, acentos em laranja para destaques + +--- + +## Espacamento e Grid + +```css +:root { + /* Espacamento base: multiplos de 4px */ + --space-1: 4px; + --space-2: 8px; + --space-3: 12px; + --space-4: 16px; + --space-6: 24px; + --space-8: 32px; + --space-12: 48px; + --space-16: 64px; + --space-24: 96px; + + /* Border radius */ + --radius-sm: 4px; + --radius-md: 8px; + --radius-lg: 16px; + + /* Sombras */ + --shadow-sm: 0 1px 3px rgba(26, 54, 93, 0.1); + --shadow-md: 0 4px 12px rgba(26, 54, 93, 0.15); + --shadow-lg: 0 8px 24px rgba(26, 54, 93, 0.2); +} +``` + +--- + +## Acessibilidade + +| Par de cores | Racio contraste | Nivel WCAG | +|-------------|-----------------|------------| +| Branco sobre Azul Escuro | 12.6:1 | AAA | +| Branco sobre Azul Medio | 5.1:1 | AA | +| Branco sobre Laranja | 3.1:1 | AA (texto grande) | +| Cinza Texto sobre Branco | 7.0:1 | AAA | +| Azul Escuro sobre Cinza Claro | 11.9:1 | AAA | + +> Texto de corpo (abaixo de 18px normal ou 14px bold) requer minimo AA (4.5:1). +> Nunca usar Laranja como fundo de texto de corpo. + +--- + +## Checklist Conformidade de Marca + +- [ ] Logótipo com espaco de respiro correcto +- [ ] Apenas cores da paleta oficial +- [ ] Tipografia Montserrat (headings) e Open Sans (corpo) +- [ ] Tom de comunicacao adequado ao canal +- [ ] Marca registada (®) na primeira ocorrencia +- [ ] Contraste WCAG AA minimo em texto +- [ ] Slogan "Crescimento Digital" presente (quando relevante) +- [ ] Sem brasileirismos no texto +- [ ] Espacamento em multiplos de 4px + +--- + +**Versao**: 1.0.0 | **Data**: 2026-03-10 | **Autor**: Descomplicar® +*Paletas detalhadas por contexto: `references/color-palettes.md`* diff --git a/design-media/skills/brand-guidelines/references/color-palettes.md b/design-media/skills/brand-guidelines/references/color-palettes.md new file mode 100644 index 0000000..0623d54 --- /dev/null +++ b/design-media/skills/brand-guidelines/references/color-palettes.md @@ -0,0 +1,227 @@ +# Paletas de Cores Descomplicar® — Referencia Detalhada + +Extensao de `brand-guidelines/SKILL.md`. Paletas completas com variacoes de contexto, +estados de interaccao e combinacoes aprovadas. + +--- + +## Paleta Principal + +| Token | Hex | RGB | HSL | +|-------|-----|-----|-----| +| `--color-primary` | `#1a365d` | 26, 54, 93 | 213°, 56%, 23% | +| `--color-secondary` | `#2b6cb0` | 43, 108, 176 | 211°, 61%, 43% | +| `--color-accent` | `#dd6b20` | 221, 107, 32 | 27°, 74%, 50% | +| `--color-white` | `#ffffff` | 255, 255, 255 | — | +| `--color-bg-light` | `#f7fafc` | 247, 250, 252 | 204°, 33%, 98% | +| `--color-text-body` | `#4a5568` | 74, 85, 104 | 220°, 17%, 35% | + +--- + +## Escala Azul Escuro (Primary) + +| Variacao | Hex | Uso | +|----------|-----|-----| +| 50 (mais claro) | `#ebf4ff` | Fundos hover muito suaves | +| 100 | `#dbeafe` | Fundos informativos | +| 200 | `#bfdbfe` | Bordas suaves | +| 300 | `#93c5fd` | Icones em fundo claro | +| 400 | `#60a5fa` | Interaccao hover em elementos claros | +| 500 | `#2b6cb0` | Azul medio (secondary) | +| 600 | `#1d4ed8` | Links hover | +| 700 | `#1e40af` | Botoes primarios hover | +| 800 | `#1e3a8a` | Variacao escura | +| **900 (base)** | `#1a365d` | **Cor primaria — uso principal** | + +--- + +## Escala Laranja (Accent) + +| Variacao | Hex | Uso | +|----------|-----|-----| +| 50 | `#fff7ed` | Fundo callout de atencao | +| 100 | `#ffedd5` | Destaque suave | +| 200 | `#fed7aa` | Borda callout | +| 300 | `#fdba74` | Icones de alerta em fundo claro | +| 400 | `#fb923c` | Hover em elementos de acento | +| **500 (base)** | `#dd6b20` | **Cor de acento — CTA principal** | +| 600 | `#c05621` | Hover botao CTA | +| 700 | `#9c4221` | Pressed state / active | +| 800 | `#7c2d12` | Texto sobre fundo laranja claro | + +--- + +## Escala de Neutros + +| Token | Hex | Uso | +|-------|-----|-----| +| Branco | `#ffffff` | Fundos principais, texto sobre escuro | +| Gray 50 | `#f7fafc` | Fundos secundarios, seccoes alternadas | +| Gray 100 | `#edf2f7` | Hover em items de lista | +| Gray 200 | `#e2e8f0` | Bordas, divisores | +| Gray 300 | `#cbd5e0` | Bordas de formularios desactivados | +| Gray 400 | `#a0aec0` | Placeholder text, icones inactivos | +| Gray 500 | `#718096` | Texto auxiliar, labels | +| **Gray 600** | `#4a5568` | **Texto de corpo principal** | +| Gray 700 | `#2d3748` | Texto secundario escuro | +| Gray 800 | `#1a202c` | Texto titulo alternativo | +| Gray 900 | `#171923` | Fundo ultra-escuro (raro) | + +--- + +## Combinacoes de Cor Aprovadas + +### Combinacoes de Alta Prioridade (CTA e Heroi) + +| Fundo | Texto / Elemento | Racio | Nota | +|-------|-----------------|-------|------| +| `#1a365d` | `#ffffff` | 12.6:1 | Preferencial — hero, capa, footer | +| `#2b6cb0` | `#ffffff` | 5.1:1 | Botoes, badges, chips | +| `#dd6b20` | `#ffffff` | 3.1:1 | CTA (apenas texto grande >=18px ou bold >=14px) | +| `#ffffff` | `#1a365d` | 12.6:1 | Documentos, corpo pagina | +| `#f7fafc` | `#1a365d` | 11.9:1 | Cards, seccoes alternadas | + +### Combinacoes de Texto (Corpo) + +| Fundo | Texto | Racio | Nivel WCAG | +|-------|-------|-------|-----------| +| `#ffffff` | `#4a5568` | 7.0:1 | AAA | +| `#f7fafc` | `#4a5568` | 6.6:1 | AAA | +| `#ffffff` | `#2d3748` | 10.7:1 | AAA | +| `#1a365d` | `#f7fafc` | 12.0:1 | AAA | + +### Combinacoes Proibidas + +| Fundo | Texto | Motivo | +|-------|-------|--------| +| `#dd6b20` | `#ffffff` | Contraste insuficiente para texto pequeno (3.1:1) | +| `#2b6cb0` | `#1a365d` | Contraste insuficiente entre tons de azul (2.2:1) | +| `#4a5568` | `#2b6cb0` | Baixo contraste em textos de corpo (2.8:1) | +| Qualquer cor | `#a0aec0` | Gray 400 nunca como texto (max 2.9:1 sobre branco) | + +--- + +## Paleta por Contexto de Produto + +### Dashboard / Aplicacao Web + +``` +Sidebar: fundo #1a365d, icones #f7fafc (inactivo), #dd6b20 (activo) +Top bar: fundo #ffffff, borda inferior #e2e8f0 +Conteudo: fundo #f7fafc +Cards: fundo #ffffff, sombra --shadow-sm +Tabelas: linhas alternas #f7fafc / #ffffff +Botao primario: #dd6b20 (fundo), #ffffff (texto) +Botao secundario: #2b6cb0 (borda e texto), transparente (fundo) +Botao ghost: #4a5568 (texto), hover #f7fafc (fundo) +Links inline: #2b6cb0, hover #1a365d +``` + +### Apresentacoes (Slides) + +``` +Slide escuro (capa, divider): fundo #1a365d + - Titulo: Montserrat 800, #ffffff + - Subtitulo: Montserrat 600, #f7fafc + - Acento barra: #dd6b20 + - Logótipo: variante clara + +Slide claro (conteudo): fundo #ffffff + - Titulo: Montserrat 700, #1a365d + - Corpo: Open Sans 400, #4a5568 + - Highlight box: fundo #f7fafc, borda esquerda #dd6b20 4px + - Numero/stat: Montserrat 800, #dd6b20 ou #2b6cb0 + +Slide citacao: fundo #f7fafc + - Aspas: #dd6b20 + - Texto citacao: Montserrat 600, #1a365d + - Atribuicao: Open Sans 400, #4a5568 +``` + +### Email Marketing + +``` +Wrapper: fundo #f7fafc +Container: fundo #ffffff, max-width 600px +Pre-header (top bar): fundo #1a365d, altura 4px ou bloco com logótipo +Header: fundo #1a365d, logótipo clara, padding 32px + Titulo: Montserrat 700, #ffffff, 28px +Body: fundo #ffffff, padding 32px + H2: Montserrat 600, #1a365d, 22px + Paragrafo: Open Sans 400, #4a5568, 16px, line-height 1.6 + Link inline: #2b6cb0 +CTA block: centrado, botao #dd6b20, texto #ffffff, border-radius 4px, padding 14px 28px +Divisor: border-top 1px solid #e2e8f0 +Footer: fundo #f7fafc, texto #718096, 13px, links #4a5568 +``` + +### Social Media + +``` +Post Instagram (1080x1080): + Opcao A (escuro): fundo #1a365d, titulo #ffffff, acento #dd6b20 + Opcao B (claro): fundo #ffffff, titulo #1a365d, detalhe #dd6b20 + Borda/frame: strip #dd6b20 (8-12px) em baixo ou em cima + Logo: canto inferior direito, variante adequada ao fundo + +Story Instagram (1080x1920): + Gradiente vertical: #1a365d (topo) -> #2b6cb0 (base) + Texto: #ffffff + CTA button area: #dd6b20 + +LinkedIn Banner (1584x396): + Fundo: #1a365d ou fotografia com overlay #1a365d 60% + Texto: #ffffff (titulo), #f7fafc (sub) + Acento: strip ou elemento #dd6b20 +``` + +### Documentos PDF / Propostas + +``` +Capa: fundo #1a365d + Logo: variante clara, centrado no topo + Titulo: Montserrat 800, #ffffff, 36px + Subtitulo: Montserrat 400, #f7fafc, 18px + Data/ref: Open Sans 400, #a0aec0, 14px, em baixo + +Paginas internas: + Cabecalho: altura 48px, fundo #1a365d, logótipo pequena (variante clara), numero de pagina + Titulo capitulo: Montserrat 700, #1a365d, 22px, fundo #f7fafc, padding 12px, borda esquerda #dd6b20 4px + Corpo: Open Sans 400, #4a5568, 11pt, line-height 1.6 + Callout/destaque: fundo #f7fafc, borda #dd6b20, icone #dd6b20 + Tabelas: header fundo #1a365d texto #ffffff; linhas alternas #f7fafc / #ffffff + Rodape: borda topo #e2e8f0, texto #718096, 9pt +``` + +--- + +## Gradientes Aprovados + +| Nome | Valor CSS | Uso | +|------|-----------|-----| +| Hero primario | `linear-gradient(135deg, #1a365d 0%, #2b6cb0 100%)` | Heroi web, fundo apresentacao | +| Acento | `linear-gradient(135deg, #dd6b20 0%, #f6ad55 100%)` | Banners promocionais | +| Escuro suave | `linear-gradient(180deg, #1a365d 0%, #2d3748 100%)` | Sidebars, overlays | +| Claro | `linear-gradient(180deg, #ffffff 0%, #f7fafc 100%)` | Seccoes de transicao | + +> Nunca usar gradientes em texto (excecto como elemento decorativo com contraste garantido). +> Maximo 2 gradientes por composicao visual. + +--- + +## Cores de Estado e Feedback + +| Estado | Cor | Hex | Uso | +|--------|-----|-----|-----| +| Sucesso | Verde | `#38a169` | Confirmacoes, checkmarks, alertas positivos | +| Aviso | Amarelo | `#d69e2e` | Alertas de atencao, pendentes | +| Erro | Vermelho | `#e53e3e` | Erros, validacoes negativas | +| Informacao | Azul Medio | `#2b6cb0` | Mensagens informativas, tooltips | + +> Cores de estado nao fazem parte da identidade visual principal. +> Usar apenas para feedback de interface, nunca como cor de marca. + +--- + +*Referencia de paletas v1.0.0 | 2026-03-10 | Descomplicar®* +*Fonte principal: `brand-guidelines/SKILL.md`* diff --git a/design-media/skills/brand-guidelines/references/descomplicar-theme.md b/design-media/skills/brand-guidelines/references/descomplicar-theme.md new file mode 100644 index 0000000..3038ece --- /dev/null +++ b/design-media/skills/brand-guidelines/references/descomplicar-theme.md @@ -0,0 +1,188 @@ +--- +name: "Descomplicar Digital" +description: "Professional technology consulting theme with warm accents" +version: "1.0.0" +updated: "2026-03-10" +--- + +# Tema Descomplicar Digital + +Tema oficial Descomplicar® para uso em apresentações, relatórios, designs e qualquer material de comunicação. + +--- + +## Paleta de Cores + +```yaml +colors: + primary: "#1a365d" # Azul escuro — headers, fundos principais + secondary: "#2b6cb0" # Azul médio — links, sub-headers + accent: "#dd6b20" # Laranja — CTAs, destaques, números + background: "#ffffff" # Branco — fundo principal + surface: "#f7fafc" # Cinza muito claro — secções alternadas + text_primary: "#2d3748" # Cinza escuro — texto corpo + text_secondary: "#4a5568" # Cinza médio — subtítulos, legendas + border: "#e2e8f0" # Cinza claro — bordas, separadores + success: "#38a169" # Verde — confirmações + warning: "#d69e2e" # Amarelo — avisos + error: "#e53e3e" # Vermelho — erros +``` + +### Referência Visual + +| Token | Hex | Uso | +|-------|-----|-----| +| `primary` | `#1a365d` | Headers H1/H2, fundos de navegação, capa de apresentação | +| `secondary` | `#2b6cb0` | Links, H3/H4, badges, ícones activos | +| `accent` | `#dd6b20` | Botões CTA, números em destaque, linhas de separação principais | +| `background` | `#ffffff` | Fundo padrão de slides e páginas | +| `surface` | `#f7fafc` | Slides alternados, tabelas linha par, painéis laterais | +| `text_primary` | `#2d3748` | Corpo de texto, parágrafos, listas | +| `text_secondary` | `#4a5568` | Subtítulos, legendas, texto auxiliar | +| `border` | `#e2e8f0` | Bordas de tabela, separadores horizontais, cards | +| `success` | `#38a169` | Confirmações, métricas positivas, status "concluído" | +| `warning` | `#d69e2e` | Avisos, métricas de atenção, status "em risco" | +| `error` | `#e53e3e` | Erros, métricas negativas, status "crítico" | + +--- + +## Tipografia + +```yaml +fonts: + heading: "Montserrat" + heading_weight: "700, 800" + heading_fallback: "Arial, sans-serif" + body: "Open Sans" + body_weight: "400, 600" + body_fallback: "Helvetica, sans-serif" + code: "JetBrains Mono" + code_fallback: "Consolas, monospace" +``` + +### Hierarquia Tipográfica + +| Nível | Fonte | Peso | Tamanho (slides) | Tamanho (docs) | +|-------|-------|------|-----------------|----------------| +| H1 — Título principal | Montserrat | 800 | 40-48px | 32px | +| H2 — Título secção | Montserrat | 700 | 28-36px | 24px | +| H3 — Subtítulo | Montserrat | 700 | 22-26px | 20px | +| H4 — Label | Open Sans | 600 | 18-20px | 16px | +| Corpo | Open Sans | 400 | 16-18px | 14-16px | +| Caption | Open Sans | 400 | 12-14px | 12px | +| Código | JetBrains Mono | 400 | 14-16px | 13px | + +### Google Fonts — Import + +```css +@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@700;800&family=Open+Sans:wght@400;600&family=JetBrains+Mono&display=swap'); +``` + +--- + +## Regras de Uso + +```yaml +usage_notes: + - Usar laranja com moderação (apenas CTAs e destaques-chave) + - Azul escuro para headers e elementos de navegação + - Fundos alternados branco/cinza para secções longas + - Nunca usar mais de 3 cores numa slide + - Manter contraste WCAG AA em todos os textos +``` + +### Regras Expandidas + +**Cores** +- O laranja (`accent`) é reservado para no máximo 1-2 elementos por slide/página +- Nunca usar `primary` e `accent` em simultâneo em texto — garante legibilidade +- Fundo `surface` em slides alternados cria ritmo visual sem poluição +- Combinação permitida em texto: `primary` fundo + `background` texto, ou `background` fundo + `primary` texto + +**Tipografia** +- Nunca misturar Montserrat com outra fonte de títulos no mesmo documento +- Open Sans é a única fonte de corpo permitida +- Código inline e blocos de código: sempre JetBrains Mono +- Não usar itálico em títulos — usar peso (bold) para ênfase + +**Contraste WCAG AA** +- `text_primary` (#2d3748) sobre `background` (#ffffff): rácio 12.6:1 — aprovado +- `text_secondary` (#4a5568) sobre `background` (#ffffff): rácio 7.4:1 — aprovado +- `accent` (#dd6b20) sobre `background` (#ffffff): rácio 3.8:1 — aprovado para texto grande (>18px bold) +- `background` (#ffffff) sobre `primary` (#1a365d): rácio 12.6:1 — aprovado + +--- + +## Aplicação em Slides + +### Layout Tipo Capa + +``` +[Fundo: primary #1a365d] +[Logo Descomplicar — branco, topo esquerdo] +[H1: Montserrat 800, branco] +[H2: Montserrat 700, accent #dd6b20] +[Rodapé: Open Sans 400, text_secondary, separador border] +``` + +### Layout Tipo Conteúdo + +``` +[Fundo: background #ffffff] +[Header barra: primary #1a365d, 8px altura] +[H2: primary #1a365d, Montserrat 700] +[Corpo: text_primary #2d3748, Open Sans 400] +[Sidebar ou destaque: surface #f7fafc] +[CTA ou número chave: accent #dd6b20, Montserrat 800] +``` + +### Layout Tipo Dados / Métricas + +``` +[Fundo alternado: surface #f7fafc] +[Número grande: accent #dd6b20, Montserrat 800, 60-80px] +[Label: text_secondary #4a5568, Open Sans 600, 14px] +[Ícone: secondary #2b6cb0] +``` + +--- + +## Aplicação em HTML (Desk CRM / Relatórios) + +```css +:root { + --color-primary: #1a365d; + --color-secondary: #2b6cb0; + --color-accent: #dd6b20; + --color-background: #ffffff; + --color-surface: #f7fafc; + --color-text-primary: #2d3748; + --color-text-secondary: #4a5568; + --color-border: #e2e8f0; + --color-success: #38a169; + --color-warning: #d69e2e; + --color-error: #e53e3e; + --font-heading: 'Montserrat', Arial, sans-serif; + --font-body: 'Open Sans', Helvetica, sans-serif; + --font-code: 'JetBrains Mono', Consolas, monospace; +} + +h1, h2 { font-family: var(--font-heading); font-weight: 800; color: var(--color-primary); } +h3, h4 { font-family: var(--font-heading); font-weight: 700; color: var(--color-secondary); } +p, li { font-family: var(--font-body); color: var(--color-text-primary); } +code { font-family: var(--font-code); } +.accent { color: var(--color-accent); } +.surface { background: var(--color-surface); } +``` + +--- + +## Compatibilidade com /design + +Este tema é carregado automaticamente quando se usa `--brand descomplicar` no skill `/design`. + +**Pack JSON:** `/media/ealmeida/Dados/Hub/04-Recursos/Design/brands/descomplicar.json` + +--- + +*Tema v1.0.0 | 2026-03-10 | Descomplicar®* diff --git a/design-media/skills/design/SKILL.md b/design-media/skills/design/SKILL.md index 9b689d5..05a1e9a 100644 --- a/design-media/skills/design/SKILL.md +++ b/design-media/skills/design/SKILL.md @@ -1,28 +1,43 @@ --- name: design -description: > - Motor de design profissional multi-marca. Gera apresentacoes, infograficos, logos, social media, web pages e identidade visual para qualquer empresa. - Use when user mentions "design", "criar design", "fazer apresentacao", "infografico", "logo", "social media post", "landing page", "identidade visual", - "brand", "marca", "--brand", "proposta visual". -triggers: - - /design - - design - - criar design - - apresentacao - - infografico - - social media post - - logo - - landing page - - identidade visual -version: 2.0.0 -author: Descomplicar Crescimento Digital -category: design +description: Motor de design profissional multi-marca. Gera apresentações, infográficos, logos, social media, web pages e identidade visual. --- # /design - Motor de Design Profissional Ponto de entrada unificado para o sistema de design multi-marca. Routing automatico para o motor adequado. +## Contexto NotebookLM + +ANTES de executar, consultar notebooks para contexto especializado: + +| Notebook | ID | Consultar quando | +|----------|-----|-----------------| +| Tipografia e Cor para Web | f97a0d2b | Sempre | +| UI/UX Design | 081ca512 | Para decisões de interface | +| Design Profissional AItomatizado | b568b13b-0eed-48c9-b513-5c5b7ec0b102 | Sempre | + +``` +mcp__notebooklm__notebook_query({ + notebook_id: "f97a0d2b-a5b3-4640-b941-3cbb184b1b81", + query: "" +}) + +mcp__notebooklm__notebook_query({ + notebook_id: "081ca512-8279-4850-b2b9-dff090267482", + query: "" +}) + +mcp__notebooklm__notebook_query({ + notebook_id: "b568b13b-0eed-48c9-b513-5c5b7ec0b102", + query: "" +}) +``` + +Integrar insights do NotebookLM nas recomendações e decisões. + +--- + ## Comandos | Comando | Output | Motor | diff --git a/design-media/skills/design/references/premium-proposals.md b/design-media/skills/design/references/premium-proposals.md new file mode 100644 index 0000000..8f3a6fc --- /dev/null +++ b/design-media/skills/design/references/premium-proposals.md @@ -0,0 +1,289 @@ +# Referência: Propostas Premium — Design de Capas e Páginas Visuais + +Guia prático para criar páginas visuais de impacto em propostas comerciais Descomplicar. +Baseado na filosofia canvas-design: design-forward, cada página comunica antes de ser lida. + +--- + +## Filosofia de Design + +**Princípio central:** o cliente forma opinião sobre a proposta nos primeiros 3 segundos. +Cada página deve funcionar como imagem antes de funcionar como texto. + +| Princípio | Aplicação | +|-----------|-----------| +| Visual-first | Imagem/composição comunica o tema antes do texto | +| Texto mínimo | Menos palavras, mais impacto por palavra | +| Espaço negativo | Respiração generosa — o vazio é parte do design | +| Tipografia como design | O tipo de letra é um elemento visual, não só legível | +| Paleta disciplinada | Máximo 3 cores por página (+ neutros) | + +--- + +## Paleta Descomplicar + +```python +# Cores base da marca — aplicar consistentemente +PALETA = { + "dourado": "#C9A84C", # acento principal + "dourado_lt": "#E8D5A3", # acento suave / fundo dourado + "preto": "#0D0D0D", # fundo principal dark + "cinza_esc": "#1A1A1A", # fundo secundário + "cinza_med": "#3D3D3D", # separadores + "cinza_lt": "#F5F5F5", # fundo light / texto em dark + "branco": "#FFFFFF", # texto em dark, fundo clean +} + +# Tipografia (Nexa é a fonte da marca) +FONTES = { + "heading": "Nexa Bold", + "subheading":"Nexa Light", + "corpo": "Source Sans 3", + "detalhe": "IBM Plex Mono", # para números, códigos +} +``` + +--- + +## Workflow: do conceito à página + +``` +1. BRIEFING — que secção é esta? qual a mensagem principal? +2. COMPOSIÇÃO — escolher layout base (ver tipos abaixo) +3. HIERARQUIA — definir 3 níveis: âncora visual / título / detalhe +4. COR — aplicar paleta com dominante + acento +5. TIPOGRAFIA — tamanhos com contraste forte (ex: 72pt / 14pt) +6. REFINAMENTO — remover tudo o que não é necessário +7. EXPORTAÇÃO — PDF vector (300dpi para imprimir, 72dpi para digital) +``` + +--- + +## Tipos de Página por Secção + +### Capa de Proposta (primeira página) + +**Objectivo:** impressionar, identificar o cliente, criar antecipação. + +```python +# Composição com python-reportlab +from reportlab.lib.pagesizes import A4 +from reportlab.pdfgen import canvas +from reportlab.lib.colors import HexColor + +W, H = A4 # 595 x 842 pontos + +def criar_capa(c: canvas.Canvas, nome_cliente: str, titulo: str): + # Fundo preto total + c.setFillColor(HexColor("#0D0D0D")) + c.rect(0, 0, W, H, fill=1, stroke=0) + + # Barra dourada lateral esquerda (elemento âncora) + c.setFillColor(HexColor("#C9A84C")) + c.rect(0, 0, 8, H, fill=1, stroke=0) + + # Logo Descomplicar (topo direito) + c.drawImage("assets/logo-white.png", W - 130, H - 60, 110, 40, mask="auto") + + # Título em grande — dois terços da página + c.setFillColor(HexColor("#FFFFFF")) + c.setFont("Nexa-Bold", 52) + # Quebra em 2 linhas se necessário + linhas = quebrar_texto(titulo, max_chars=24) + y = H * 0.55 + for linha in linhas: + c.drawString(48, y, linha) + y -= 64 + + # Nome do cliente — acento dourado + c.setFillColor(HexColor("#C9A84C")) + c.setFont("Nexa-Light", 18) + c.drawString(48, H * 0.35, f"Preparado para {nome_cliente}") + + # Data — rodapé discreto + c.setFillColor(HexColor("#3D3D3D")) + c.setFont("SourceSans3-Regular", 10) + c.drawString(48, 32, f"Descomplicar® · descomplicar.pt · Março 2026") +``` + +**Composição alternativa (versão light):** +- Fundo branco com mancha fotográfica no lado direito (60% da largura) +- Título sobreposto à foto com overlay escuro +- Logo em preto, barra dourada mantida + +### Separador de Secção + +**Objectivo:** pausar o ritmo, anunciar o tema seguinte. + +```python +def criar_separador(c: canvas.Canvas, numero: str, titulo_seccao: str): + # Fundo dourado total — inversão de cor + c.setFillColor(HexColor("#C9A84C")) + c.rect(0, 0, W, H, fill=1, stroke=0) + + # Número enorme em background (marca de água visual) + c.setFillColor(HexColor("#E8D5A3")) # dourado claro + c.setFont("Nexa-Bold", 280) + c.drawString(-20, H * 0.1, numero) # pode sair do bounds — intencional + + # Título da secção — preto sobre dourado + c.setFillColor(HexColor("#0D0D0D")) + c.setFont("Nexa-Bold", 42) + c.drawString(48, H * 0.45, titulo_seccao) + + # Linha divisória fina + c.setStrokeColor(HexColor("#0D0D0D")) + c.setLineWidth(1) + c.line(48, H * 0.42, W - 48, H * 0.42) +``` + +### Infográfico de Dados + +**Objectivo:** tornar números abstractos em narrativa visual. + +```python +def criar_infografico_metricas(c: canvas.Canvas, metricas: list[dict]): + """ + metricas = [ + {"valor": "3x", "label": "Aumento de tráfego", "icone": "trend"}, + {"valor": "47%", "label": "Redução de custo por lead", "icone": "savings"}, + {"valor": "12", "label": "Palavras-chave no Top 3", "icone": "star"}, + ] + """ + # Fundo neutro quente + c.setFillColor(HexColor("#F5F5F5")) + c.rect(0, 0, W, H, fill=1, stroke=0) + + # Título da página + c.setFillColor(HexColor("#0D0D0D")) + c.setFont("Nexa-Bold", 32) + c.drawString(48, H - 80, "Resultados Projectados") + + # Grid de métricas (3 colunas) + col_w = (W - 96) / len(metricas) + for i, m in enumerate(metricas): + x = 48 + i * col_w + y_center = H * 0.5 + + # Caixa de métrica + c.setFillColor(HexColor("#FFFFFF")) + c.roundRect(x + 8, y_center - 80, col_w - 16, 160, 12, fill=1, stroke=0) + + # Valor principal — grande e dourado + c.setFillColor(HexColor("#C9A84C")) + c.setFont("Nexa-Bold", 56) + c.drawCentredString(x + col_w / 2, y_center + 20, m["valor"]) + + # Label — preto, pequeno + c.setFillColor(HexColor("#3D3D3D")) + c.setFont("SourceSans3-Regular", 11) + c.drawCentredString(x + col_w / 2, y_center - 20, m["label"]) +``` + +### Página de Pricing Visual + +**Objectivo:** apresentar preços sem que pareçam uma tabela de custos. + +```python +def criar_pricing(c: canvas.Canvas, planos: list[dict]): + """ + planos = [ + {"nome": "Essencial", "preco": 450, "destaque": False, + "items": ["SEO On-page", "Relatório mensal", "2 artigos/mês"]}, + {"nome": "Crescimento", "preco": 850, "destaque": True, + "items": ["SEO completo", "Google Ads", "4 artigos/mês", "Dashboard BI"]}, + ] + """ + # Fundo escuro para pricing + c.setFillColor(HexColor("#0D0D0D")) + c.rect(0, 0, W, H, fill=1, stroke=0) + + card_w = (W - 96 - 16 * (len(planos) - 1)) / len(planos) + + for i, p in enumerate(planos): + x = 48 + i * (card_w + 16) + y_top = H * 0.75 + + if p["destaque"]: + # Card dourado para o plano recomendado + c.setFillColor(HexColor("#C9A84C")) + c.roundRect(x - 4, y_top - 4, card_w + 8, H * 0.5 + 8, 16, fill=1, stroke=0) + texto_cor = HexColor("#0D0D0D") + else: + c.setFillColor(HexColor("#1A1A1A")) + c.roundRect(x, y_top, card_w, H * 0.5, 12, fill=1, stroke=0) + texto_cor = HexColor("#FFFFFF") + + # Nome do plano + c.setFillColor(texto_cor) + c.setFont("Nexa-Bold", 20) + c.drawString(x + 20, y_top + H * 0.5 - 44, p["nome"]) + + # Preço + c.setFont("Nexa-Bold", 48) + c.drawString(x + 20, y_top + H * 0.5 - 100, f"{p['preco']}€") + c.setFont("SourceSans3-Regular", 11) + c.drawString(x + 20, y_top + H * 0.5 - 118, "/ mês + IVA") + + # Items incluídos + c.setFont("SourceSans3-Regular", 12) + y_item = y_top + H * 0.5 - 150 + for item in p["items"]: + c.drawString(x + 28, y_item, f"— {item}") + y_item -= 22 +``` + +--- + +## Ferramentas: python-reportlab vs pptxgenjs + +| Critério | python-reportlab | pptxgenjs (Node) | +|----------|-----------------|------------------| +| Output | PDF nativo | PPTX (editável) | +| Controlo | Pixel-perfect | Aproximado | +| Fontes custom | Suporte completo | Limitado | +| Melhor para | Proposta final PDF | Template editável pelo cliente | +| Ambiente | Servidor dev (`/root/Dev`) | Servidor dev ou local | + +**Recomendação:** usar reportlab para proposta final; pptxgenjs se o cliente precisar de editar. + +```bash +# Instalar no servidor dev +pip install reportlab Pillow + +# Registar fontes Nexa +from reportlab.pdfbase import pdfmetrics +from reportlab.pdfbase.ttfonts import TTFont +pdfmetrics.registerFont(TTFont("Nexa-Bold", "/root/Dev/assets/fonts/Nexa-Bold.ttf")) +pdfmetrics.registerFont(TTFont("Nexa-Light", "/root/Dev/assets/fonts/Nexa-Light.ttf")) +``` + +--- + +## Regras de Composição (resumo operacional) + +1. **Uma mensagem por página** — se precisas de duas frases para explicar, remove uma +2. **Âncora visual primeiro** — o olho precisa de um ponto de entrada (número grande, foto, cor) +3. **Contraste de escala** — combinar elemento 280pt com texto 12pt (não 24pt com 18pt) +4. **Margens generosas** — margem mínima de 48pt em A4; prefere 64pt +5. **Rodapé discreto** — página + marca em 9pt, nunca competir com conteúdo +6. **Máximo 3 fontes** — Nexa Bold + Nexa Light + Source Sans 3 (IBM Plex Mono opcional para dados) +7. **Alinhamento consistente** — escolher esquerda ou centrado para o documento inteiro + +--- + +## Checklist de Qualidade + +- [ ] Capa com nome do cliente e data correctos +- [ ] Logo Descomplicar presente em todas as páginas (rodapé ou canto) +- [ ] Paleta restrita a 3 cores por página +- [ ] Nenhuma fonte genérica (Arial, Calibri, Times) +- [ ] Espaço negativo generoso — sem páginas "cheias" +- [ ] Preços em EUR sem decimais desnecessários (850EUR, não 850,00EUR) +- [ ] PDF exportado em vector (não rasterizado) +- [ ] Tamanho final < 10MB para envio por email +- [ ] Testar visualização em modo claro e escuro (PDF viewer) + +--- + +*Referência: premium-proposals v1.0 | 2026-03-10 | Descomplicar®* diff --git a/dev-tools/.claude-plugin/plugin.json b/dev-tools/.claude-plugin/plugin.json index b363ed2..df37d71 100644 --- a/dev-tools/.claude-plugin/plugin.json +++ b/dev-tools/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "dev-tools", - "description": "PHP, React, Next.js development, database design and frontend patterns. Backed by 7 Dify KB datasets.", + "description": "PHP, React, Next.js development, database design and frontend patterns. Backed by NotebookLM notebooks.", "version": "1.0.0", "author": { "name": "Descomplicar - Crescimento Digital", diff --git a/dev-tools/agents/database-design-specialist.md b/dev-tools/agents/database-design-specialist.md index 3eca2b1..40588e3 100644 --- a/dev-tools/agents/database-design-specialist.md +++ b/dev-tools/agents/database-design-specialist.md @@ -67,14 +67,6 @@ mcp__notebooklm__notebook_query notebook_id:"f9a79b5a-649f-4443-afaf-7ff562b6c2e mcp__notebooklm__notebook_query notebook_id:"24947ffa-0019-448a-a340-2f4a275d2eb1" query:"arquitectura dados" ``` -### Dify KB (Secundario - se NotebookLM insuficiente) - -``` -mcp__dify-kb__dify_kb_retrieve_segments dataset:"TI" query:"database SQL optimizacao" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Desenvolvimento de Software" query:"arquitectura dados" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"AWS" query:"RDS cloud database" -``` - ## System Prompt ### Papel @@ -124,7 +116,7 @@ Especialista em arquitectura de bases de dados, entregando solucoes eficientes, ## MCPs Relevantes - `desk-crm-v3`: Acesso directo à BD Perfex para análise - `ssh-unified`: Acesso MySQL em servidores -- `notebooklm`: KB primaria (Gemini 2.5 RAG) | `dify-kb`: KB TI (SQL, optimização), AWS (RDS) +- `notebooklm`: KB primaria (Gemini 2.5 RAG) | ``: KB TI (SQL, optimização), AWS (RDS) ## Colaboracao @@ -142,9 +134,9 @@ Especialista em arquitectura de bases de dados, entregando solucoes eficientes, - SSH, SFTP, servidor management - Usage: `mcp__ssh-unified__*` -✓ **dify-kb** (knowledge) +✓ **** (knowledge) - Knowledge base AI - - Usage: `mcp__dify-kb__*` + - Usage: `mcp____*` ### Recommended for dev - **gitea** - Repositórios Git, issues, PRs @@ -156,13 +148,11 @@ Especialista em arquitectura de bases de dados, entregando solucoes eficientes, - **cwp** - CentOS Web Panel - **puppeteer** - Browser automation -### All Available (33 total) +### All Available (32 total) moloni, google-analytics, google-workspace, imap, outline-api, youtube-research, youtube-uploader, wikijs, gsc, lighthouse, mcp-time, mcp-mermaid, mcp-echarts, powerpoint, penpot, pixabay, pexels, tavily, elevenlabs, vimeo, design-systems, replicate **Discovery:** Use ToolSearch to find specific tools. **Example:** `ToolSearch("ssh upload")` finds SSH upload tools. - - ## Your Available Skills ### Primary Skills (Your Domain) @@ -196,13 +186,11 @@ moloni, google-analytics, google-workspace, imap, outline-api, youtube-research, - **/knowledge** - Gestão unificada de conhecimento - pesquisa inteligente com - **/desk** - Integração com Desk CRM via ficheiro .desk-project. Auto-det -### All Available (54 total) +### All Available (53 total) /billing-check, /crm-ops, /ecommerce, /lead-approach, /orcamento, /saas, /content-marketing-pt, /remotion-video, /seo-content-optimization, /social-media, /ui-ux-pro-max-repo, /brand-voice-generator, /frontend-design, /pptx-generator, /ui-ux-pro-max, /backup-strategies, /security-audit, /server-health, /wp-performance, /wp-update, /second-brain-repo, /ads, /marketing-strategy, /product, /skill-creator, /sop-creator, /calendar-manager, /interview, /today, /research, /youtube, /seo-audit, /seo-report, /archive, /metrics, /sdk **Discovery:** Use the Skill tool to invoke skills. **Example:** `Skill("skill-name")` invokes the skill. - - ## Your Team & Responsibilities You are part of **5 SDKs** (TaskForce teams): @@ -216,9 +204,6 @@ You are part of **5 SDKs** (TaskForce teams): **Purpose:** NULL **Your responsibilities in this TaskForce:** - -- **Sistema de agentes especializados para delegacao de tarefas via Task tool com consulta automatica de datasets Dify.**: NULL - ### TaskForce DeskDev **Purpose:** NULL diff --git a/dev-tools/agents/dev-helper.md b/dev-tools/agents/dev-helper.md index 4e05b32..d49b6b0 100644 --- a/dev-tools/agents/dev-helper.md +++ b/dev-tools/agents/dev-helper.md @@ -73,7 +73,6 @@ Você é um desenvolvedor experiente generalista responsável por: - [ ] **Manutenibilidade**: Código legível > código "clever" - [ ] **Testar**: Validar sugestões quando possível - [ ] **Documentar**: Explicar "porquê", não só "como" -- [ ] **Consultar Dify KB**: Verificar padrões estabelecidos ### Output Format Esperado @@ -109,7 +108,7 @@ Você é um desenvolvedor experiente generalista responsável por: | MCP | Quando Usar | |-----|-------------| -| `dify-kb` | Best practices, padrões arquitectura | +| `` | Best practices, padrões arquitectura | | `memory-supabase` | Soluções anteriores similares | | `gitea` | Consultar histórico código | @@ -185,7 +184,7 @@ OBRIGATÓRIO antes de git commit: 5. Decisão - 0 vulnerabilidades → ✅ Commit safe - Vulnerabilidades transitivas → Usar pnpm.overrides - - Vulnerabilidades críticas → Corrigir ou invocar /security-check + - Vulnerabilidades críticas → Corrigir ou invocar /dep-audit 6. Documentar - Se há vulnerabilidades conhecidas → Mencionar no commit message @@ -224,15 +223,6 @@ mcp__notebooklm__notebook_query notebook_id:"f9a79b5a-649f-4443-afaf-7ff562b6c2e mcp__notebooklm__notebook_query notebook_id:"2876d1fe-5cea-4d98-8140-b0e1a81c6bc4" query:"desenvolvimento assistente workflow" ``` -### Dify KB (Secundario - se NotebookLM insuficiente) - -``` -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Desenvolvimento de Software" query:"boas praticas SOLID clean code" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"TI" query:"debugging arquitectura troubleshooting" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Claude Code" query:"desenvolvimento assistente workflow" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Seguranca" query:"vulnerabilidades code security" -``` - ## Your Available MCPs ### Recommended for dev @@ -242,18 +232,16 @@ mcp__dify-kb__dify_kb_retrieve_segments dataset:"Seguranca" query:"vulnerabilida - **n8n** - Workflows automation - **filesystem** - Ficheiros locais - **magic** - AI-powered UI component generation (tipo v0.dev) -- **dify-kb** - Knowledge base AI +- **** - Knowledge base AI - **memory-supabase** - Memória longo prazo - **cwp** - CentOS Web Panel - **puppeteer** - Browser automation -### All Available (33 total) +### All Available (32 total) desk-crm-v3, moloni, google-analytics, google-workspace, imap, outline-api, youtube-research, youtube-uploader, wikijs, gsc, lighthouse, mcp-time, mcp-mermaid, mcp-echarts, powerpoint, penpot, pixabay, pexels, tavily, elevenlabs, vimeo, design-systems, replicate **Discovery:** Use ToolSearch to find specific tools. **Example:** `ToolSearch("ssh upload")` finds SSH upload tools. - - ## Your Available Skills ### Primary Skills (Your Domain) @@ -287,20 +275,16 @@ desk-crm-v3, moloni, google-analytics, google-workspace, imap, outline-api, yout - **/knowledge** - Gestão unificada de conhecimento - pesquisa inteligente com - **/desk** - Integração com Desk CRM via ficheiro .desk-project. Auto-det -### All Available (54 total) +### All Available (53 total) /billing-check, /crm-ops, /ecommerce, /lead-approach, /orcamento, /saas, /content-marketing-pt, /remotion-video, /seo-content-optimization, /social-media, /ui-ux-pro-max-repo, /brand-voice-generator, /frontend-design, /pptx-generator, /ui-ux-pro-max, /backup-strategies, /security-audit, /server-health, /wp-performance, /wp-update, /second-brain-repo, /ads, /marketing-strategy, /product, /skill-creator, /sop-creator, /calendar-manager, /interview, /today, /research, /youtube, /seo-audit, /seo-report, /archive, /metrics, /sdk **Discovery:** Use the Skill tool to invoke skills. **Example:** `Skill("skill-name")` invokes the skill. - - ## Colaboração - **Reports to**: Development Lead - **Colabora com**: Todos os development specialists, System Architects, Database Design Specialist, Security Compliance Specialist - **Escalar para**: Development Lead (decisões arquitectura complexas), Security Compliance Specialist (vulnerabilidades críticas) - - ## Your Team & Responsibilities You are part of **1 TaskForce** (TaskForce teams): @@ -310,9 +294,6 @@ You are part of **1 TaskForce** (TaskForce teams): **Purpose:** NULL **Your responsibilities in this TaskForce:** - -- **Sistema de agentes especializados para delegacao de tarefas via Task tool com consulta automatica de datasets Dify.**: NULL - **Collaboration:** - Work with other agents in your TaskForce teams - Share knowledge and context across team members diff --git a/dev-tools/agents/development-lead.md b/dev-tools/agents/development-lead.md index 7a409aa..b0916b4 100644 --- a/dev-tools/agents/development-lead.md +++ b/dev-tools/agents/development-lead.md @@ -69,14 +69,6 @@ mcp__notebooklm__notebook_query notebook_id:"0c9c079c-a426-486c-99eb-1564d42d37a mcp__notebooklm__notebook_query notebook_id:"79d43410-0e29-4be1-881d-84db6bdc239a" query:"arquitectura solucoes" ``` -### Dify KB (Secundario - se NotebookLM insuficiente) - -``` -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Desenvolvimento de Software" query:"lideranca tecnica" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Gestao de Projetos" query:"coordenacao equipas" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Estrategia" query:"arquitectura solucoes" -``` - ## System Prompt ### Papel @@ -109,7 +101,7 @@ Lider de desenvolvimento responsavel por liderar equipas, garantir qualidade de ### Workflow 2: Decisão Arquitectural 1. Entender problema e contexto -2. Pesquisar soluções existentes (memory, dify-kb) +2. Pesquisar soluções existentes (memory) 3. Propor 2-3 opções com tradeoffs 4. Discussão com stakeholders 5. Documentar decisão (ADR - Architecture Decision Record) @@ -127,7 +119,7 @@ Lider de desenvolvimento responsavel por liderar equipas, garantir qualidade de - `desk-crm-v3`: Gestão de tarefas e projectos - `gitea`: Gestão de repositórios e PRs - `memory-supabase`: Histórico de decisões técnicas -- `notebooklm`: KB primaria (Gemini 2.5 RAG) | `dify-kb`: KB Desenvolvimento, Gestão Projectos +- `notebooklm`: KB primaria (Gemini 2.5 RAG) | ``: KB Desenvolvimento, Gestão Projectos ## Colaboracao @@ -145,9 +137,9 @@ Lider de desenvolvimento responsavel por liderar equipas, garantir qualidade de - Repositórios Git, issues, PRs - Usage: `mcp__gitea__*` -✓ **dify-kb** (knowledge) +✓ **** (knowledge) - Knowledge base AI - - Usage: `mcp__dify-kb__*` + - Usage: `mcp____*` ✓ **memory-supabase** (system) - Memória longo prazo @@ -162,13 +154,11 @@ Lider de desenvolvimento responsavel por liderar equipas, garantir qualidade de - **cwp** - CentOS Web Panel - **puppeteer** - Browser automation -### All Available (33 total) +### All Available (32 total) moloni, google-analytics, google-workspace, imap, outline-api, youtube-research, youtube-uploader, wikijs, gsc, lighthouse, mcp-time, mcp-mermaid, mcp-echarts, powerpoint, penpot, pixabay, pexels, tavily, elevenlabs, vimeo, design-systems, replicate **Discovery:** Use ToolSearch to find specific tools. **Example:** `ToolSearch("ssh upload")` finds SSH upload tools. - - ## Your Available Skills ### Primary Skills (Your Domain) @@ -202,13 +192,11 @@ moloni, google-analytics, google-workspace, imap, outline-api, youtube-research, - **/knowledge** - Gestão unificada de conhecimento - pesquisa inteligente com - **/desk** - Integração com Desk CRM via ficheiro .desk-project. Auto-det -### All Available (54 total) +### All Available (53 total) /billing-check, /crm-ops, /ecommerce, /lead-approach, /orcamento, /saas, /content-marketing-pt, /remotion-video, /seo-content-optimization, /social-media, /ui-ux-pro-max-repo, /brand-voice-generator, /frontend-design, /pptx-generator, /ui-ux-pro-max, /backup-strategies, /security-audit, /server-health, /wp-performance, /wp-update, /second-brain-repo, /ads, /marketing-strategy, /product, /skill-creator, /sop-creator, /calendar-manager, /interview, /today, /research, /youtube, /seo-audit, /seo-report, /archive, /metrics, /sdk **Discovery:** Use the Skill tool to invoke skills. **Example:** `Skill("skill-name")` invokes the skill. - - ## Your Team & Responsibilities You are part of **2 SDKs** (TaskForce teams): diff --git a/dev-tools/agents/javascript-fullstack-specialist.md b/dev-tools/agents/javascript-fullstack-specialist.md index 034e971..da464b2 100644 --- a/dev-tools/agents/javascript-fullstack-specialist.md +++ b/dev-tools/agents/javascript-fullstack-specialist.md @@ -39,8 +39,6 @@ created: '2025-01-13' updated: '2026-02-04' author: Descomplicar® --- - - # JavaScript Fullstack Specialist Descomplicar Especialista em desenvolvimento JavaScript fullstack, coordenando frontend e backend para entregar aplicacoes web modernas, escalaveis e performantes. @@ -61,13 +59,6 @@ mcp__notebooklm__notebook_query notebook_id:"24947ffa-0019-448a-a340-2f4a275d2eb mcp__notebooklm__notebook_query notebook_id:"f9a79b5a-649f-4443-afaf-7ff562b6c2e7" query:"fullstack web development modern frameworks" ``` -### Dify KB (Secundario - se NotebookLM insuficiente) - -``` -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Desenvolvimento de Software" query:"javascript typescript react node" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"TI" query:"fullstack web development modern frameworks" -``` - ## System Prompt ### Papel @@ -117,7 +108,7 @@ Especialista em desenvolvimento JavaScript fullstack, coordenando frontend e bac ## MCPs Relevantes - `gitea`: Gestão de repositórios e PRs - `desk-crm-v3`: Tracking de tarefas -- `notebooklm`: KB primaria (Gemini 2.5 RAG) | `dify-kb`: KB Desenvolvimento Software, TI +- `notebooklm`: KB primaria (Gemini 2.5 RAG) | ``: KB Desenvolvimento Software, TI - `memory-supabase`: Padrões e decisões técnicas ## Colaboracao @@ -136,9 +127,9 @@ Especialista em desenvolvimento JavaScript fullstack, coordenando frontend e bac - Usage: `mcp__gitea__*` ✓ **notebooklm** (knowledge primaria) -✓ **dify-kb** (knowledge fallback) +✓ **** (knowledge fallback) - Knowledge base AI - - Usage: `mcp__dify-kb__*` + - Usage: `mcp____*` ✓ **memory-supabase** (system) - Memória longo prazo @@ -153,13 +144,11 @@ Especialista em desenvolvimento JavaScript fullstack, coordenando frontend e bac - **cwp** - CentOS Web Panel - **puppeteer** - Browser automation -### All Available (33 total) +### All Available (32 total) moloni, google-analytics, google-workspace, imap, outline-api, youtube-research, youtube-uploader, wikijs, gsc, lighthouse, mcp-time, mcp-mermaid, mcp-echarts, powerpoint, penpot, pixabay, pexels, tavily, elevenlabs, vimeo, design-systems, replicate **Discovery:** Use ToolSearch to find specific tools. **Example:** `ToolSearch("ssh upload")` finds SSH upload tools. - - ## Your Available Skills ### Primary Skills (Your Domain) @@ -193,13 +182,11 @@ moloni, google-analytics, google-workspace, imap, outline-api, youtube-research, - **/knowledge** - Gestão unificada de conhecimento - pesquisa inteligente com - **/desk** - Integração com Desk CRM via ficheiro .desk-project. Auto-det -### All Available (54 total) +### All Available (53 total) /billing-check, /crm-ops, /ecommerce, /lead-approach, /orcamento, /saas, /content-marketing-pt, /remotion-video, /seo-content-optimization, /social-media, /ui-ux-pro-max-repo, /brand-voice-generator, /frontend-design, /pptx-generator, /ui-ux-pro-max, /backup-strategies, /security-audit, /server-health, /wp-performance, /wp-update, /second-brain-repo, /ads, /marketing-strategy, /product, /skill-creator, /sop-creator, /calendar-manager, /interview, /today, /research, /youtube, /seo-audit, /seo-report, /archive, /metrics, /sdk **Discovery:** Use the Skill tool to invoke skills. **Example:** `Skill("skill-name")` invokes the skill. - - ## Your Team & Responsibilities You are part of **6 SDKs** (TaskForce teams): @@ -213,9 +200,6 @@ You are part of **6 SDKs** (TaskForce teams): **Purpose:** NULL **Your responsibilities in this TaskForce:** - -- **Sistema de agentes especializados para delegacao de tarefas via Task tool com consulta automatica de datasets Dify.**: NULL - ### TaskForce Dashboard **Purpose:** NULL diff --git a/dev-tools/agents/nextjs-specialist.md b/dev-tools/agents/nextjs-specialist.md index fde55eb..a5f686a 100644 --- a/dev-tools/agents/nextjs-specialist.md +++ b/dev-tools/agents/nextjs-specialist.md @@ -97,9 +97,6 @@ Especialista em desenvolvimento Next.js - App Router, Server Components, e arqui ``` mcp__notebooklm__notebook_query notebook_id:"f9a79b5a-649f-4443-afaf-7ff562b6c2e7" query:"" ``` - -### Dify KB (Secundario) - - Desenvolvimento Software - TI - React @@ -166,7 +163,7 @@ Especialista em desenvolvimento Next.js moderno com App Router, React Server Com ## MCPs Relevantes - `gitea`: Gestão de repositórios Next.js - `desk-crm-v3`: Tracking de desenvolvimento -- `notebooklm`: KB primaria (Gemini 2.5 RAG) | `dify-kb`: KB Desenvolvimento Software, React, TI +- `notebooklm`: KB primaria (Gemini 2.5 RAG) | ``: KB Desenvolvimento Software, React, TI - `ssh-unified`: Deploy (Docker ou Node.js) ## Colaboracao @@ -183,18 +180,16 @@ Especialista em desenvolvimento Next.js moderno com App Router, React Server Com - **n8n** - Workflows automation - **filesystem** - Ficheiros locais - **magic** - AI-powered UI component generation (tipo v0.dev) -- **dify-kb** - Knowledge base AI +- **** - Knowledge base AI - **memory-supabase** - Memória longo prazo - **cwp** - CentOS Web Panel - **puppeteer** - Browser automation -### All Available (33 total) +### All Available (32 total) desk-crm-v3, moloni, google-analytics, google-workspace, imap, outline-api, youtube-research, youtube-uploader, wikijs, gsc, lighthouse, mcp-time, mcp-mermaid, mcp-echarts, powerpoint, penpot, pixabay, pexels, tavily, elevenlabs, vimeo, design-systems, replicate **Discovery:** Use ToolSearch to find specific tools. **Example:** `ToolSearch("ssh upload")` finds SSH upload tools. - - ## Your Available Skills ### Primary Skills (Your Domain) @@ -228,7 +223,7 @@ desk-crm-v3, moloni, google-analytics, google-workspace, imap, outline-api, yout - **/knowledge** - Gestão unificada de conhecimento - pesquisa inteligente com - **/desk** - Integração com Desk CRM via ficheiro .desk-project. Auto-det -### All Available (54 total) +### All Available (53 total) /billing-check, /crm-ops, /ecommerce, /lead-approach, /orcamento, /saas, /content-marketing-pt, /remotion-video, /seo-content-optimization, /social-media, /ui-ux-pro-max-repo, /brand-voice-generator, /frontend-design, /pptx-generator, /ui-ux-pro-max, /backup-strategies, /security-audit, /server-health, /wp-performance, /wp-update, /second-brain-repo, /ads, /marketing-strategy, /product, /skill-creator, /sop-creator, /calendar-manager, /interview, /today, /research, /youtube, /seo-audit, /seo-report, /archive, /metrics, /sdk **Discovery:** Use the Skill tool to invoke skills. diff --git a/dev-tools/agents/php-fullstack-engineer.md b/dev-tools/agents/php-fullstack-engineer.md index 57f11f6..e82cc7a 100644 --- a/dev-tools/agents/php-fullstack-engineer.md +++ b/dev-tools/agents/php-fullstack-engineer.md @@ -22,7 +22,6 @@ primary_mcps: - desk-crm-v3 # Business operations - gitea # Version control - ssh-unified # Server deployment - - dify-kb # Knowledge base recommended_mcps: - context7 # Technical documentation - n8n # Workflow automation @@ -105,14 +104,6 @@ mcp__notebooklm__notebook_query notebook_id:"5be0d1a6-00f2-4cd9-b835-978cb772160 mcp__notebooklm__notebook_query notebook_id:"f9a79b5a-649f-4443-afaf-7ff562b6c2e7" query:"backend MySQL PostgreSQL arquitectura" ``` -### Dify KB (Secundario - se NotebookLM insuficiente) - -``` -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Desenvolvimento de Software" query:"PHP Laravel Symfony APIs" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"WordPress" query:"PHP WordPress WooCommerce" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"TI" query:"backend MySQL PostgreSQL arquitectura" -``` - ## System Prompt ### Papel diff --git a/dev-tools/knowledge/datasets.json b/dev-tools/knowledge/datasets.json index 28ac737..d6edfb6 100644 --- a/dev-tools/knowledge/datasets.json +++ b/dev-tools/knowledge/datasets.json @@ -1,5 +1,5 @@ { - "description": "Knowledge sources (NotebookLM + Dify KB) for Development Tools domain", + "description": "Knowledge sources for Development Tools domain", "sources": { "notebooklm": { "description": "NotebookLM - conhecimento curado profundo via Gemini 2.5 RAG (PRIMARIO)", @@ -11,8 +11,7 @@ "topics": [ "claude", "code" - ], - "maps_from_dify": "Claude Code" + ] }, { "id": "73102308-70ef-403e-9be9-eae0cfc62d55", @@ -20,16 +19,14 @@ "topics": [ "mcp", "servers" - ], - "maps_from_dify": "MCP Servers" + ] }, { "id": "57d9c6c9-48ba-4d83-8f71-cc890f348a53", "title": "AI Code Editors", "topics": [ "code" - ], - "maps_from_dify": "VS Code" + ] }, { "id": "24947ffa-0019-448a-a340-2f4a275d2eb1", @@ -37,8 +34,7 @@ "topics": [ "desenvolvimento", "software" - ], - "maps_from_dify": "Desenvolvimento de Software" + ] }, { "id": "ebee9fe1-78fd-4f85-8938-f19f3ea32131", @@ -47,65 +43,9 @@ "obsidian", "claude", "code" - ], - "maps_from_dify": "Obsidian + Claude Code" - } - ] - }, - "dify_kb": { - "description": "Dify KB - datasets tematicos (FALLBACK)", - "query_tool": "mcp__dify-kb__dify_kb_retrieve_segments", - "datasets": [ - { - "id": "98e74ec7-4b4d-4876-8321-7f26ae66c3a6", - "name": "Claude Code", - "priority": 1, - "document_count": 53, - "word_count": 1241283 - }, - { - "id": "02ca690a-a901-4034-9165-5ef42830f91e", - "name": "MCP Servers", - "priority": 1, - "document_count": 22, - "word_count": 158091 - }, - { - "id": "eafd864e-5331-4a1d-a7e2-603ec263e2e1", - "name": "VS Code", - "priority": 2, - "document_count": 52, - "word_count": 10450973 - }, - { - "id": "66ce30ab-a630-402b-8ae8-c3f44312e228", - "name": "Windsurf", - "priority": 2, - "document_count": 5, - "word_count": 98903 - }, - { - "id": "2e68ac58-12cc-4c6f-b000-2bfff8fe6fcb", - "name": "Claude Computer Use", - "priority": 2, - "document_count": 4, - "word_count": 17078 - }, - { - "id": "e7c7decc-0ded-4351-ab14-b110b3c38ec9", - "name": "Desenvolvimento de Software", - "priority": 1, - "document_count": 2, - "word_count": 534153 - }, - { - "id": "e38a510f-ca93-4407-8b44-c4c66efe01f8", - "name": "Obsidian + Claude Code", - "priority": 2, - "document_count": 121, - "word_count": 2292847 + ] } ] } } -} \ No newline at end of file +} diff --git a/dev-tools/skills/chrome/SKILL.md b/dev-tools/skills/chrome/SKILL.md index fabdbe4..cf44496 100644 --- a/dev-tools/skills/chrome/SKILL.md +++ b/dev-tools/skills/chrome/SKILL.md @@ -1,10 +1,6 @@ --- name: chrome -description: Chrome browser integration for Claude Code. Navigate pages, fill forms, debug console, extract data, test web apps, automate tasks. Use when user mentions "chrome", "browser", "navegar site", "abrir pagina", "testar site", "preencher formulario", "extrair dados", "screenshot site", "google docs", "authenticated site", "gravar gif", "console errors". -author: Descomplicar® Crescimento Digital -version: 2.0.0 -quality_score: 80 -user_invocable: true +description: Integração com Chrome para automação browser — navegar páginas, preencher formulários, debug de consola, extracção de dados, testes e screenshots. allowed-tools: Bash, Read, Write, Glob --- diff --git a/dev-tools/skills/db-design/SKILL.md b/dev-tools/skills/db-design/SKILL.md index 8472400..d3d89b8 100644 --- a/dev-tools/skills/db-design/SKILL.md +++ b/dev-tools/skills/db-design/SKILL.md @@ -1,13 +1,6 @@ --- name: db-design -description: Database schema design and optimization. Creates normalized schemas, - indexes, and migration plans. Use when user mentions "database design", "schema", - "modelo dados", "database optimization", "sql design". -author: Descomplicar® Crescimento Digital -version: 1.0.0 -quality_score: 75 -user_invocable: true -desk_task: 1469 +description: Design e optimização de schemas de base de dados — normalização, índices, planos de migração e particionamento. --- # Database Design Specialist diff --git a/dev-tools/skills/security-check/SKILL.md b/dev-tools/skills/dep-audit/SKILL.md similarity index 85% rename from dev-tools/skills/security-check/SKILL.md rename to dev-tools/skills/dep-audit/SKILL.md index e350679..6c5644d 100644 --- a/dev-tools/skills/security-check/SKILL.md +++ b/dev-tools/skills/dep-audit/SKILL.md @@ -1,22 +1,37 @@ --- -name: security-check -description: Comprehensive security audit for Node.js/PHP projects - dependency vulnerabilities, outdated packages, environment safety, type checking. Use before git commits. -domain: Dev -model: sonnet -priority: high -tags: - - security - - audit - - vulnerabilities - - npm - - composer - - mandatory +name: dep-audit +description: Auditoria de dependencias para projectos Node.js e PHP — vulnerabilidades, pacotes desactualizados, seguranca de ambiente e verificacao de tipos. Obrigatoria antes de commits. +disable-model-invocation: true --- -# /security-check - Security Audit Pre-Commit +# /dep-audit - Dependency Security Audit Pre-Commit + +> **Renomeado de /security-check (12-03-2026).** `/security-check` e agora a skill de auditoria de infraestrutura (plugin infraestrutura). Auditoria de segurança completa para projectos Node.js e PHP. **Obrigatória antes de commits** (Regra CLAUDE.md #47). +## Contexto NotebookLM + +ANTES de executar, consultar notebooks para contexto especializado: + +| Notebook | ID | Consultar quando | +|----------|-----|-----------------| +| Programação | 24947ffa-0019-448a-a340-2f4a275d2eb1 | Para contexto de vulnerabilidades | + +``` +mcp__notebooklm__notebook_query({ + notebook_id: "24947ffa-0019-448a-a340-2f4a275d2eb1", + query: "" +}) +``` + +Integrar insights do NotebookLM nas recomendações e decisões. + +### Procedimentos relacionados + +- [PROC-DEV-SEC-001-Security-Audit.md](file:///media/ealmeida/Dados/Hub/06-Operacoes/Procedimentos/D7-Tecnologia/Seguranca/PROC-DEV-SEC-001-Security-Audit.md) +- [PROC-Security-Audit-API-Keys.md](file:///media/ealmeida/Dados/Hub/06-Operacoes/Procedimentos/D7-Tecnologia/Seguranca/PROC-Security-Audit-API-Keys.md) + --- ## Quando Usar @@ -407,7 +422,7 @@ Se não existe ou > 1h → **BLOQUEIA** commit # Workflow típico /time start 1446 # Tarefa Desk # ... fazer alterações ... -/security-check # Antes de commit +/dep-audit # Antes de commit git commit /time stop ``` @@ -428,7 +443,7 @@ git commit |----------|--------------| | Vulnerabilidades críticas não corrigíveis | Security Compliance Specialist | | Dúvidas sobre overrides | Development Lead | -| Múltiplas vulnerabilidades altas | /security-check + manual review | +| Múltiplas vulnerabilidades altas | /dep-audit + manual review | | Alternativas a packages | Research Analyst | --- @@ -444,5 +459,5 @@ git commit --- -**Skill v1.0** | 2026-02-14 | Descomplicar® +**Skill v1.1** | 12-03-2026 | Descomplicar® | Renomeado de /security-check para /dep-audit **Security First** - Zero vulnerabilities ou documentadas diff --git a/dev-tools/skills/docx/SKILL.md b/dev-tools/skills/docx/SKILL.md new file mode 100644 index 0000000..b000879 --- /dev/null +++ b/dev-tools/skills/docx/SKILL.md @@ -0,0 +1,512 @@ +--- +name: docx +description: "Criacao, edicao e analise de documentos Word (.docx). Usar quando o utilizador mencionar \"Word\", \".docx\", ou pedir documentos profissionais com formatacao (indices, cabecalhos, numeracao de paginas, letterheads). Inclui extracao de conteudo, insercao/substituicao de imagens, find-and-replace, tracked changes, comentarios, e conversao de conteudo para Word. Aplica-se a relatorios, memorandos, cartas, templates e propostas em formato .docx. NAO usar para PDFs, folhas de calculo, Google Docs, ou tarefas de codigo nao relacionadas." +--- + +# Criacao, edicao e analise de documentos DOCX + +## Visao geral + +Um ficheiro .docx e um arquivo ZIP contendo ficheiros XML. + +## Referencia rapida + +| Tarefa | Abordagem | +|--------|-----------| +| Ler/analisar conteudo | `pandoc` ou descompactar para XML bruto | +| Criar novo documento | Usar `docx-js` - ver seccao Criar Novos Documentos | +| Editar documento existente | Descompactar -> editar XML -> recompactar - ver seccao Editar Documentos Existentes | + +### Converter .doc para .docx + +Ficheiros legacy `.doc` devem ser convertidos antes de editar: + +```bash +python scripts/office/soffice.py --headless --convert-to docx document.doc +``` + +### Ler conteudo + +```bash +# Extracao de texto com tracked changes +pandoc --track-changes=all document.docx -o output.md + +# Acesso ao XML bruto +python scripts/office/unpack.py document.docx unpacked/ +``` + +### Converter para imagens + +```bash +python scripts/office/soffice.py --headless --convert-to pdf document.docx +pdftoppm -jpeg -r 150 document.pdf page +``` + +### Aceitar tracked changes + +Para produzir um documento limpo com todas as alteracoes aceites (requer LibreOffice): + +```bash +python scripts/accept_changes.py input.docx output.docx +``` + +--- + +## Criar novos documentos + +Gerar ficheiros .docx com JavaScript, depois validar. Instalacao: `npm install -g docx` + +### Setup +```javascript +const { Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell, ImageRun, + Header, Footer, AlignmentType, PageOrientation, LevelFormat, ExternalHyperlink, + TableOfContents, HeadingLevel, BorderStyle, WidthType, ShadingType, + VerticalAlign, PageNumber, PageBreak } = require('docx'); + +const doc = new Document({ sections: [{ children: [/* conteudo */] }] }); +Packer.toBuffer(doc).then(buffer => fs.writeFileSync("doc.docx", buffer)); +``` + +### Validacao +Apos criar o ficheiro, validar. Se a validacao falhar, descompactar, corrigir o XML e recompactar. +```bash +python scripts/office/validate.py doc.docx +``` + +### Tamanho da pagina + +```javascript +// CRITICO: docx-js assume A4 por defeito +// Definir sempre o tamanho da pagina explicitamente para resultados consistentes +// Para documentos PT/EU, A4 e o padrao correcto +sections: [{ + properties: { + page: { + size: { + width: 11906, // A4: 210mm em DXA + height: 16838 // A4: 297mm em DXA + }, + margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 } // 1 polegada de margens + } + }, + children: [/* conteudo */] +}] +``` + +**Tamanhos de pagina comuns (unidades DXA, 1440 DXA = 1 polegada):** + +| Papel | Largura | Altura | Largura conteudo (margens 1") | +|-------|---------|--------|-------------------------------| +| A4 (padrao PT/EU) | 11.906 | 16.838 | 9.026 | +| US Letter | 12.240 | 15.840 | 9.360 | + +**Orientacao paisagem:** docx-js troca largura/altura internamente, por isso passar dimensoes retrato e deixar a biblioteca tratar: +```javascript +size: { + width: 11906, // Passar lado CURTO como width + height: 16838, // Passar lado LONGO como height + orientation: PageOrientation.LANDSCAPE // docx-js troca no XML +}, +// Largura de conteudo = 16838 - margem esquerda - margem direita (usa o lado longo) +``` + +### Estilos (Override Built-in Headings) + +Usar Arial como fonte por defeito (suporte universal). Manter titulos a preto para legibilidade. + +```javascript +const doc = new Document({ + styles: { + default: { document: { run: { font: "Arial", size: 24 } } }, // 12pt por defeito + paragraphStyles: [ + // IMPORTANTE: Usar IDs exactos para override dos estilos built-in + { id: "Heading1", name: "Heading 1", basedOn: "Normal", next: "Normal", quickFormat: true, + run: { size: 32, bold: true, font: "Arial" }, + paragraph: { spacing: { before: 240, after: 240 }, outlineLevel: 0 } }, // outlineLevel necessario para TOC + { id: "Heading2", name: "Heading 2", basedOn: "Normal", next: "Normal", quickFormat: true, + run: { size: 28, bold: true, font: "Arial" }, + paragraph: { spacing: { before: 180, after: 180 }, outlineLevel: 1 } }, + ] + }, + sections: [{ + children: [ + new Paragraph({ heading: HeadingLevel.HEADING_1, children: [new TextRun("Titulo")] }), + ] + }] +}); +``` + +### Listas (NUNCA usar bullets unicode) + +```javascript +// ERRADO - nunca inserir caracteres de bullet manualmente +new Paragraph({ children: [new TextRun("* Item")] }) // MAU +new Paragraph({ children: [new TextRun("\u2022 Item")] }) // MAU + +// CORRECTO - usar config numbering com LevelFormat.BULLET +const doc = new Document({ + numbering: { + config: [ + { reference: "bullets", + levels: [{ level: 0, format: LevelFormat.BULLET, text: "\u2022", alignment: AlignmentType.LEFT, + style: { paragraph: { indent: { left: 720, hanging: 360 } } } }] }, + { reference: "numbers", + levels: [{ level: 0, format: LevelFormat.DECIMAL, text: "%1.", alignment: AlignmentType.LEFT, + style: { paragraph: { indent: { left: 720, hanging: 360 } } } }] }, + ] + }, + sections: [{ + children: [ + new Paragraph({ numbering: { reference: "bullets", level: 0 }, + children: [new TextRun("Item com bullet")] }), + new Paragraph({ numbering: { reference: "numbers", level: 0 }, + children: [new TextRun("Item numerado")] }), + ] + }] +}); + +// ATENCAO: Cada reference cria numeracao INDEPENDENTE +// Mesma reference = continua (1,2,3 depois 4,5,6) +// Reference diferente = reinicia (1,2,3 depois 1,2,3) +``` + +### Tabelas + +**CRITICO: Tabelas precisam de larguras duplas** - definir tanto `columnWidths` na tabela COMO `width` em cada celula. Sem ambos, tabelas renderizam incorrectamente em algumas plataformas. + +```javascript +// CRITICO: Definir sempre largura da tabela para renderizacao consistente +// CRITICO: Usar ShadingType.CLEAR (nao SOLID) para evitar fundos pretos +const border = { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" }; +const borders = { top: border, bottom: border, left: border, right: border }; + +new Table({ + width: { size: 9026, type: WidthType.DXA }, // Sempre usar DXA (percentagens quebram no Google Docs) + columnWidths: [4513, 4513], // Deve somar a largura da tabela (DXA: 1440 = 1 polegada) + rows: [ + new TableRow({ + children: [ + new TableCell({ + borders, + width: { size: 4513, type: WidthType.DXA }, // Tambem definir em cada celula + shading: { fill: "D5E8F0", type: ShadingType.CLEAR }, // CLEAR e nao SOLID + margins: { top: 80, bottom: 80, left: 120, right: 120 }, // Padding da celula (interno, nao adicionado a largura) + children: [new Paragraph({ children: [new TextRun("Celula")] })] + }) + ] + }) + ] +}) +``` + +**Calculo de largura da tabela:** + +Usar sempre `WidthType.DXA` — `WidthType.PERCENTAGE` quebra no Google Docs. + +```javascript +// Largura da tabela = soma de columnWidths = largura do conteudo +// A4 com margens de 1": 11906 - 2880 = 9026 DXA +width: { size: 9026, type: WidthType.DXA }, +columnWidths: [7000, 2026] // Deve somar a largura da tabela +``` + +**Regras de largura:** +- **Usar sempre `WidthType.DXA`** — nunca `WidthType.PERCENTAGE` (incompativel com Google Docs) +- Largura da tabela deve igualar a soma de `columnWidths` +- `width` da celula deve corresponder ao respectivo `columnWidth` +- `margins` da celula sao padding interno - reduzem a area de conteudo, nao adicionam a largura +- Para tabelas full-width: usar largura de conteudo (largura pagina menos margens esquerda e direita) + +### Imagens + +```javascript +// CRITICO: parametro type e OBRIGATORIO +new Paragraph({ + children: [new ImageRun({ + type: "png", // Obrigatorio: png, jpg, jpeg, gif, bmp, svg + data: fs.readFileSync("image.png"), + transformation: { width: 200, height: 150 }, + altText: { title: "Titulo", description: "Desc", name: "Nome" } // Os tres sao obrigatorios + })] +}) +``` + +### Quebras de pagina + +```javascript +// CRITICO: PageBreak deve estar dentro de um Paragraph +new Paragraph({ children: [new PageBreak()] }) + +// Ou usar pageBreakBefore +new Paragraph({ pageBreakBefore: true, children: [new TextRun("Nova pagina")] }) +``` + +### Indice (Table of Contents) + +```javascript +// CRITICO: Headings devem usar HeadingLevel APENAS - sem estilos custom +new TableOfContents("Indice", { hyperlink: true, headingStyleRange: "1-3" }) +``` + +### Cabecalhos/Rodapes + +```javascript +sections: [{ + properties: { + page: { margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 } } // 1440 = 1 polegada + }, + headers: { + default: new Header({ children: [new Paragraph({ children: [new TextRun("Cabecalho")] })] }) + }, + footers: { + default: new Footer({ children: [new Paragraph({ + children: [new TextRun("Pagina "), new TextRun({ children: [PageNumber.CURRENT] })] + })] }) + }, + children: [/* conteudo */] +}] +``` + +### Regras criticas para docx-js + +- **Definir tamanho de pagina explicitamente** - docx-js assume A4; para documentos PT/EU, A4 (11906 x 16838 DXA) e o padrao correcto +- **Paisagem: passar dimensoes retrato** - docx-js troca largura/altura internamente; passar lado curto como `width`, lado longo como `height`, e definir `orientation: PageOrientation.LANDSCAPE` +- **Nunca usar `\n`** - usar elementos Paragraph separados +- **Nunca usar bullets unicode** - usar `LevelFormat.BULLET` com config numbering +- **PageBreak deve estar em Paragraph** - standalone cria XML invalido +- **ImageRun requer `type`** - especificar sempre png/jpg/etc +- **Definir sempre `width` da tabela com DXA** - nunca usar `WidthType.PERCENTAGE` (quebra no Google Docs) +- **Tabelas precisam de larguras duplas** - array `columnWidths` E `width` da celula, ambos devem corresponder +- **Largura tabela = soma de columnWidths** - para DXA, garantir que somam exactamente +- **Adicionar sempre margins nas celulas** - usar `margins: { top: 80, bottom: 80, left: 120, right: 120 }` para padding legivel +- **Usar `ShadingType.CLEAR`** - nunca SOLID para shading de tabelas +- **TOC requer HeadingLevel apenas** - sem estilos custom nos paragrafos de heading +- **Override built-in styles** - usar IDs exactos: "Heading1", "Heading2", etc. +- **Incluir `outlineLevel`** - necessario para TOC (0 para H1, 1 para H2, etc.) + +--- + +## Editar documentos existentes + +**Seguir os 3 passos por ordem.** + +### Passo 1: Descompactar +```bash +python scripts/office/unpack.py document.docx unpacked/ +``` +Extrai XML, pretty-prints, funde runs adjacentes e converte smart quotes para entidades XML (`“` etc.) para sobreviverem a edicao. Usar `--merge-runs false` para saltar a fusao de runs. + +### Passo 2: Editar XML + +Editar ficheiros em `unpacked/word/`. Ver Referencia XML abaixo para padroes. + +**Usar "Claude" como autor** para tracked changes e comentarios, salvo se o utilizador pedir outro nome. + +**Usar a ferramenta Edit directamente para substituicao de strings. Nao escrever scripts Python.** Scripts introduzem complexidade desnecessaria. A ferramenta Edit mostra exactamente o que esta a ser substituido. + +**CRITICO: Usar smart quotes para novo conteudo.** Ao adicionar texto com apostrofos ou aspas, usar entidades XML para produzir smart quotes: +```xml + +Here’s a quote: “Hello” +``` +| Entidade | Caractere | +|----------|-----------| +| `‘` | ' (aspas simples esquerda) | +| `’` | ' (aspas simples direita / apostrofo) | +| `“` | " (aspas duplas esquerda) | +| `”` | " (aspas duplas direita) | + +**Adicionar comentarios:** Usar `comment.py` para tratar boilerplate em multiplos ficheiros XML (texto deve ser XML pre-escaped): +```bash +python scripts/comment.py unpacked/ 0 "Texto do comentario com & e ’" +python scripts/comment.py unpacked/ 1 "Texto de resposta" --parent 0 # resposta ao comentario 0 +python scripts/comment.py unpacked/ 0 "Texto" --author "Autor Custom" # nome de autor custom +``` +Depois adicionar marcadores ao document.xml (ver Comentarios na Referencia XML). + +### Passo 3: Recompactar +```bash +python scripts/office/pack.py unpacked/ output.docx --original document.docx +``` +Valida com auto-reparacao, condensa XML e cria DOCX. Usar `--validate false` para saltar. + +**Auto-reparacao corrige:** +- `durableId` >= 0x7FFFFFFF (regenera ID valido) +- `xml:space="preserve"` em falta em `` com whitespace + +**Auto-reparacao nao corrige:** +- XML malformado, nesting de elementos invalido, relacoes em falta, violacoes de schema + +### Erros comuns + +- **Substituir elementos `` inteiros**: Ao adicionar tracked changes, substituir o bloco `...` completo com `......` como siblings. Nao injectar tags de tracked change dentro de um run. +- **Preservar formatacao ``**: Copiar o bloco `` do run original para os runs de tracked change para manter bold, tamanho de fonte, etc. + +--- + +## Referencia XML + +### Conformidade com schema + +- **Ordem de elementos em ``**: ``, ``, ``, ``, ``, `` por ultimo +- **Whitespace**: Adicionar `xml:space="preserve"` a `` com espacos no inicio/fim +- **RSIDs**: Devem ser hex de 8 digitos (ex: `00AB1234`) + +### Tracked Changes + +**Insercao:** +```xml + + texto inserido + +``` + +**Eliminacao:** +```xml + + texto eliminado + +``` + +**Dentro de ``**: Usar `` em vez de ``, e `` em vez de ``. + +**Edicoes minimas** - marcar apenas o que muda: +```xml + +O prazo e de + + 30 + + + 60 + + dias. +``` + +**Eliminar paragrafos/itens de lista inteiros** - ao remover TODO o conteudo de um paragrafo, marcar tambem o paragraph mark como eliminado para fundir com o proximo paragrafo. Adicionar `` dentro de ``: +```xml + + + ... + + + + + + Conteudo inteiro do paragrafo a ser eliminado... + + +``` +Sem o `` em ``, aceitar alteracoes deixa um paragrafo/item de lista vazio. + +**Rejeitar insercao de outro autor** - aninhar eliminacao dentro da insercao: +```xml + + + texto inserido por ela + + +``` + +**Restaurar eliminacao de outro autor** - adicionar insercao depois (nao modificar a eliminacao): +```xml + + texto eliminado + + + texto eliminado + +``` + +### Comentarios + +Apos executar `comment.py` (ver Passo 2), adicionar marcadores ao document.xml. Para respostas, usar flag `--parent` e aninhar marcadores dentro dos do pai. + +**CRITICO: `` e `` sao siblings de ``, nunca dentro de ``.** + +```xml + + + + eliminado + + mais texto + + + + + + + texto + + + + +``` + +### Imagens + +1. Adicionar ficheiro de imagem a `word/media/` +2. Adicionar relacao a `word/_rels/document.xml.rels`: +```xml + +``` +3. Adicionar content type a `[Content_Types].xml`: +```xml + +``` +4. Referenciar no document.xml: +```xml + + + + + + + + + + + + +``` + +--- + +## Dependencias + +- **pandoc**: Extracao de texto +- **docx**: `npm install -g docx` (novos documentos) +- **LibreOffice**: Conversao PDF (auto-configurado para ambientes sandbox via `scripts/office/soffice.py`) +- **Poppler**: `pdftoppm` para imagens + +--- + +## Integracao Descomplicar + +### MCPs disponiveis + +| MCP | Uso | +|-----|-----| +| `mcp__filesystem__*` | Ler/escrever ficheiros .docx locais, listar directorios | +| `mcp__google-workspace__*` | Upload para Google Drive, conversao para Google Docs | +| `mcp__ssh-unified__*` | Operacoes em ficheiros .docx em servidores remotos | + +### Workflow tipico + +1. **Criar documento** com docx-js conforme instrucoes acima +2. **Validar** com `scripts/office/validate.py` +3. **Guardar** via `mcp__filesystem__write_file` ou directamente no path do projecto +4. **Upload** (opcional) via `mcp__google-workspace__drive_upload_file` para partilha com cliente + +### Convencoes Descomplicar + +- **Formato de data** em documentos: DD-MM-YYYY (ex: 06-03-2026) +- **Formato monetario**: 1.234,56 EUR (separador milhar ponto, decimal virgula) +- **Fonte padrao**: Arial 12pt +- **Tamanho pagina padrao**: A4 (11906 x 16838 DXA) +- **Autor para tracked changes**: "Claude" (salvo indicacao contraria) +- **Idioma do documento**: PT-PT salvo indicacao contraria + +--- +**Versao**: 1.0.0 | **Autor**: Descomplicar® diff --git a/dev-tools/skills/docx/scripts/__init__.py b/dev-tools/skills/docx/scripts/__init__.py new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/dev-tools/skills/docx/scripts/__init__.py @@ -0,0 +1 @@ + diff --git a/dev-tools/skills/docx/scripts/accept_changes.py b/dev-tools/skills/docx/scripts/accept_changes.py new file mode 100644 index 0000000..8e36316 --- /dev/null +++ b/dev-tools/skills/docx/scripts/accept_changes.py @@ -0,0 +1,135 @@ +"""Accept all tracked changes in a DOCX file using LibreOffice. + +Requires LibreOffice (soffice) to be installed. +""" + +import argparse +import logging +import shutil +import subprocess +from pathlib import Path + +from office.soffice import get_soffice_env + +logger = logging.getLogger(__name__) + +LIBREOFFICE_PROFILE = "/tmp/libreoffice_docx_profile" +MACRO_DIR = f"{LIBREOFFICE_PROFILE}/user/basic/Standard" + +ACCEPT_CHANGES_MACRO = """ + + + Sub AcceptAllTrackedChanges() + Dim document As Object + Dim dispatcher As Object + + document = ThisComponent.CurrentController.Frame + dispatcher = createUnoService("com.sun.star.frame.DispatchHelper") + + dispatcher.executeDispatch(document, ".uno:AcceptAllTrackedChanges", "", 0, Array()) + ThisComponent.store() + ThisComponent.close(True) + End Sub +""" + + +def accept_changes( + input_file: str, + output_file: str, +) -> tuple[None, str]: + input_path = Path(input_file) + output_path = Path(output_file) + + if not input_path.exists(): + return None, f"Error: Input file not found: {input_file}" + + if not input_path.suffix.lower() == ".docx": + return None, f"Error: Input file is not a DOCX file: {input_file}" + + try: + output_path.parent.mkdir(parents=True, exist_ok=True) + shutil.copy2(input_path, output_path) + except Exception as e: + return None, f"Error: Failed to copy input file to output location: {e}" + + if not _setup_libreoffice_macro(): + return None, "Error: Failed to setup LibreOffice macro" + + cmd = [ + "soffice", + "--headless", + f"-env:UserInstallation=file://{LIBREOFFICE_PROFILE}", + "--norestore", + "vnd.sun.star.script:Standard.Module1.AcceptAllTrackedChanges?language=Basic&location=application", + str(output_path.absolute()), + ] + + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + timeout=30, + check=False, + env=get_soffice_env(), + ) + except subprocess.TimeoutExpired: + return ( + None, + f"Successfully accepted all tracked changes: {input_file} -> {output_file}", + ) + + if result.returncode != 0: + return None, f"Error: LibreOffice failed: {result.stderr}" + + return ( + None, + f"Successfully accepted all tracked changes: {input_file} -> {output_file}", + ) + + +def _setup_libreoffice_macro() -> bool: + macro_dir = Path(MACRO_DIR) + macro_file = macro_dir / "Module1.xba" + + if macro_file.exists() and "AcceptAllTrackedChanges" in macro_file.read_text(): + return True + + if not macro_dir.exists(): + subprocess.run( + [ + "soffice", + "--headless", + f"-env:UserInstallation=file://{LIBREOFFICE_PROFILE}", + "--terminate_after_init", + ], + capture_output=True, + timeout=10, + check=False, + env=get_soffice_env(), + ) + macro_dir.mkdir(parents=True, exist_ok=True) + + try: + macro_file.write_text(ACCEPT_CHANGES_MACRO) + return True + except Exception as e: + logger.warning(f"Failed to setup LibreOffice macro: {e}") + return False + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Accept all tracked changes in a DOCX file" + ) + parser.add_argument("input_file", help="Input DOCX file with tracked changes") + parser.add_argument( + "output_file", help="Output DOCX file (clean, no tracked changes)" + ) + args = parser.parse_args() + + _, message = accept_changes(args.input_file, args.output_file) + print(message) + + if "Error" in message: + raise SystemExit(1) diff --git a/dev-tools/skills/docx/scripts/comment.py b/dev-tools/skills/docx/scripts/comment.py new file mode 100644 index 0000000..36e1c93 --- /dev/null +++ b/dev-tools/skills/docx/scripts/comment.py @@ -0,0 +1,318 @@ +"""Add comments to DOCX documents. + +Usage: + python comment.py unpacked/ 0 "Comment text" + python comment.py unpacked/ 1 "Reply text" --parent 0 + +Text should be pre-escaped XML (e.g., & for &, ’ for smart quotes). + +After running, add markers to document.xml: + + ... commented content ... + + +""" + +import argparse +import random +import shutil +import sys +from datetime import datetime, timezone +from pathlib import Path + +import defusedxml.minidom + +TEMPLATE_DIR = Path(__file__).parent / "templates" +NS = { + "w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main", + "w14": "http://schemas.microsoft.com/office/word/2010/wordml", + "w15": "http://schemas.microsoft.com/office/word/2012/wordml", + "w16cid": "http://schemas.microsoft.com/office/word/2016/wordml/cid", + "w16cex": "http://schemas.microsoft.com/office/word/2018/wordml/cex", +} + +COMMENT_XML = """\ + + + + + + + + + + + + + {text} + + +""" + +COMMENT_MARKER_TEMPLATE = """ +Add to document.xml (markers must be direct children of w:p, never inside w:r): + + ... + + """ + +REPLY_MARKER_TEMPLATE = """ +Nest markers inside parent {pid}'s markers (markers must be direct children of w:p, never inside w:r): + + ... + + + """ + + +def _generate_hex_id() -> str: + return f"{random.randint(0, 0x7FFFFFFE):08X}" + + +SMART_QUOTE_ENTITIES = { + "\u201c": "“", + "\u201d": "”", + "\u2018": "‘", + "\u2019": "’", +} + + +def _encode_smart_quotes(text: str) -> str: + for char, entity in SMART_QUOTE_ENTITIES.items(): + text = text.replace(char, entity) + return text + + +def _append_xml(xml_path: Path, root_tag: str, content: str) -> None: + dom = defusedxml.minidom.parseString(xml_path.read_text(encoding="utf-8")) + root = dom.getElementsByTagName(root_tag)[0] + ns_attrs = " ".join(f'xmlns:{k}="{v}"' for k, v in NS.items()) + wrapper_dom = defusedxml.minidom.parseString(f"{content}") + for child in wrapper_dom.documentElement.childNodes: + if child.nodeType == child.ELEMENT_NODE: + root.appendChild(dom.importNode(child, True)) + output = _encode_smart_quotes(dom.toxml(encoding="UTF-8").decode("utf-8")) + xml_path.write_text(output, encoding="utf-8") + + +def _find_para_id(comments_path: Path, comment_id: int) -> str | None: + dom = defusedxml.minidom.parseString(comments_path.read_text(encoding="utf-8")) + for c in dom.getElementsByTagName("w:comment"): + if c.getAttribute("w:id") == str(comment_id): + for p in c.getElementsByTagName("w:p"): + if pid := p.getAttribute("w14:paraId"): + return pid + return None + + +def _get_next_rid(rels_path: Path) -> int: + dom = defusedxml.minidom.parseString(rels_path.read_text(encoding="utf-8")) + max_rid = 0 + for rel in dom.getElementsByTagName("Relationship"): + rid = rel.getAttribute("Id") + if rid and rid.startswith("rId"): + try: + max_rid = max(max_rid, int(rid[3:])) + except ValueError: + pass + return max_rid + 1 + + +def _has_relationship(rels_path: Path, target: str) -> bool: + dom = defusedxml.minidom.parseString(rels_path.read_text(encoding="utf-8")) + for rel in dom.getElementsByTagName("Relationship"): + if rel.getAttribute("Target") == target: + return True + return False + + +def _has_content_type(ct_path: Path, part_name: str) -> bool: + dom = defusedxml.minidom.parseString(ct_path.read_text(encoding="utf-8")) + for override in dom.getElementsByTagName("Override"): + if override.getAttribute("PartName") == part_name: + return True + return False + + +def _ensure_comment_relationships(unpacked_dir: Path) -> None: + rels_path = unpacked_dir / "word" / "_rels" / "document.xml.rels" + if not rels_path.exists(): + return + + if _has_relationship(rels_path, "comments.xml"): + return + + dom = defusedxml.minidom.parseString(rels_path.read_text(encoding="utf-8")) + root = dom.documentElement + next_rid = _get_next_rid(rels_path) + + rels = [ + ( + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments", + "comments.xml", + ), + ( + "http://schemas.microsoft.com/office/2011/relationships/commentsExtended", + "commentsExtended.xml", + ), + ( + "http://schemas.microsoft.com/office/2016/09/relationships/commentsIds", + "commentsIds.xml", + ), + ( + "http://schemas.microsoft.com/office/2018/08/relationships/commentsExtensible", + "commentsExtensible.xml", + ), + ] + + for rel_type, target in rels: + rel = dom.createElement("Relationship") + rel.setAttribute("Id", f"rId{next_rid}") + rel.setAttribute("Type", rel_type) + rel.setAttribute("Target", target) + root.appendChild(rel) + next_rid += 1 + + rels_path.write_bytes(dom.toxml(encoding="UTF-8")) + + +def _ensure_comment_content_types(unpacked_dir: Path) -> None: + ct_path = unpacked_dir / "[Content_Types].xml" + if not ct_path.exists(): + return + + if _has_content_type(ct_path, "/word/comments.xml"): + return + + dom = defusedxml.minidom.parseString(ct_path.read_text(encoding="utf-8")) + root = dom.documentElement + + overrides = [ + ( + "/word/comments.xml", + "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml", + ), + ( + "/word/commentsExtended.xml", + "application/vnd.openxmlformats-officedocument.wordprocessingml.commentsExtended+xml", + ), + ( + "/word/commentsIds.xml", + "application/vnd.openxmlformats-officedocument.wordprocessingml.commentsIds+xml", + ), + ( + "/word/commentsExtensible.xml", + "application/vnd.openxmlformats-officedocument.wordprocessingml.commentsExtensible+xml", + ), + ] + + for part_name, content_type in overrides: + override = dom.createElement("Override") + override.setAttribute("PartName", part_name) + override.setAttribute("ContentType", content_type) + root.appendChild(override) + + ct_path.write_bytes(dom.toxml(encoding="UTF-8")) + + +def add_comment( + unpacked_dir: str, + comment_id: int, + text: str, + author: str = "Claude", + initials: str = "C", + parent_id: int | None = None, +) -> tuple[str, str]: + word = Path(unpacked_dir) / "word" + if not word.exists(): + return "", f"Error: {word} not found" + + para_id, durable_id = _generate_hex_id(), _generate_hex_id() + ts = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") + + comments = word / "comments.xml" + first_comment = not comments.exists() + if first_comment: + shutil.copy(TEMPLATE_DIR / "comments.xml", comments) + _ensure_comment_relationships(Path(unpacked_dir)) + _ensure_comment_content_types(Path(unpacked_dir)) + _append_xml( + comments, + "w:comments", + COMMENT_XML.format( + id=comment_id, + author=author, + date=ts, + initials=initials, + para_id=para_id, + text=text, + ), + ) + + ext = word / "commentsExtended.xml" + if not ext.exists(): + shutil.copy(TEMPLATE_DIR / "commentsExtended.xml", ext) + if parent_id is not None: + parent_para = _find_para_id(comments, parent_id) + if not parent_para: + return "", f"Error: Parent comment {parent_id} not found" + _append_xml( + ext, + "w15:commentsEx", + f'', + ) + else: + _append_xml( + ext, + "w15:commentsEx", + f'', + ) + + ids = word / "commentsIds.xml" + if not ids.exists(): + shutil.copy(TEMPLATE_DIR / "commentsIds.xml", ids) + _append_xml( + ids, + "w16cid:commentsIds", + f'', + ) + + extensible = word / "commentsExtensible.xml" + if not extensible.exists(): + shutil.copy(TEMPLATE_DIR / "commentsExtensible.xml", extensible) + _append_xml( + extensible, + "w16cex:commentsExtensible", + f'', + ) + + action = "reply" if parent_id is not None else "comment" + return para_id, f"Added {action} {comment_id} (para_id={para_id})" + + +if __name__ == "__main__": + p = argparse.ArgumentParser(description="Add comments to DOCX documents") + p.add_argument("unpacked_dir", help="Unpacked DOCX directory") + p.add_argument("comment_id", type=int, help="Comment ID (must be unique)") + p.add_argument("text", help="Comment text") + p.add_argument("--author", default="Claude", help="Author name") + p.add_argument("--initials", default="C", help="Author initials") + p.add_argument("--parent", type=int, help="Parent comment ID (for replies)") + args = p.parse_args() + + para_id, msg = add_comment( + args.unpacked_dir, + args.comment_id, + args.text, + args.author, + args.initials, + args.parent, + ) + print(msg) + if "Error" in msg: + sys.exit(1) + cid = args.comment_id + if args.parent is not None: + print(REPLY_MARKER_TEMPLATE.format(pid=args.parent, cid=cid)) + else: + print(COMMENT_MARKER_TEMPLATE.format(cid=cid)) diff --git a/dev-tools/skills/docx/scripts/office/helpers/__init__.py b/dev-tools/skills/docx/scripts/office/helpers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dev-tools/skills/docx/scripts/office/helpers/merge_runs.py b/dev-tools/skills/docx/scripts/office/helpers/merge_runs.py new file mode 100644 index 0000000..ad7c25e --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/helpers/merge_runs.py @@ -0,0 +1,199 @@ +"""Merge adjacent runs with identical formatting in DOCX. + +Merges adjacent elements that have identical properties. +Works on runs in paragraphs and inside tracked changes (, ). + +Also: +- Removes rsid attributes from runs (revision metadata that doesn't affect rendering) +- Removes proofErr elements (spell/grammar markers that block merging) +""" + +from pathlib import Path + +import defusedxml.minidom + + +def merge_runs(input_dir: str) -> tuple[int, str]: + doc_xml = Path(input_dir) / "word" / "document.xml" + + if not doc_xml.exists(): + return 0, f"Error: {doc_xml} not found" + + try: + dom = defusedxml.minidom.parseString(doc_xml.read_text(encoding="utf-8")) + root = dom.documentElement + + _remove_elements(root, "proofErr") + _strip_run_rsid_attrs(root) + + containers = {run.parentNode for run in _find_elements(root, "r")} + + merge_count = 0 + for container in containers: + merge_count += _merge_runs_in(container) + + doc_xml.write_bytes(dom.toxml(encoding="UTF-8")) + return merge_count, f"Merged {merge_count} runs" + + except Exception as e: + return 0, f"Error: {e}" + + + + +def _find_elements(root, tag: str) -> list: + results = [] + + def traverse(node): + if node.nodeType == node.ELEMENT_NODE: + name = node.localName or node.tagName + if name == tag or name.endswith(f":{tag}"): + results.append(node) + for child in node.childNodes: + traverse(child) + + traverse(root) + return results + + +def _get_child(parent, tag: str): + for child in parent.childNodes: + if child.nodeType == child.ELEMENT_NODE: + name = child.localName or child.tagName + if name == tag or name.endswith(f":{tag}"): + return child + return None + + +def _get_children(parent, tag: str) -> list: + results = [] + for child in parent.childNodes: + if child.nodeType == child.ELEMENT_NODE: + name = child.localName or child.tagName + if name == tag or name.endswith(f":{tag}"): + results.append(child) + return results + + +def _is_adjacent(elem1, elem2) -> bool: + node = elem1.nextSibling + while node: + if node == elem2: + return True + if node.nodeType == node.ELEMENT_NODE: + return False + if node.nodeType == node.TEXT_NODE and node.data.strip(): + return False + node = node.nextSibling + return False + + + + +def _remove_elements(root, tag: str): + for elem in _find_elements(root, tag): + if elem.parentNode: + elem.parentNode.removeChild(elem) + + +def _strip_run_rsid_attrs(root): + for run in _find_elements(root, "r"): + for attr in list(run.attributes.values()): + if "rsid" in attr.name.lower(): + run.removeAttribute(attr.name) + + + + +def _merge_runs_in(container) -> int: + merge_count = 0 + run = _first_child_run(container) + + while run: + while True: + next_elem = _next_element_sibling(run) + if next_elem and _is_run(next_elem) and _can_merge(run, next_elem): + _merge_run_content(run, next_elem) + container.removeChild(next_elem) + merge_count += 1 + else: + break + + _consolidate_text(run) + run = _next_sibling_run(run) + + return merge_count + + +def _first_child_run(container): + for child in container.childNodes: + if child.nodeType == child.ELEMENT_NODE and _is_run(child): + return child + return None + + +def _next_element_sibling(node): + sibling = node.nextSibling + while sibling: + if sibling.nodeType == sibling.ELEMENT_NODE: + return sibling + sibling = sibling.nextSibling + return None + + +def _next_sibling_run(node): + sibling = node.nextSibling + while sibling: + if sibling.nodeType == sibling.ELEMENT_NODE: + if _is_run(sibling): + return sibling + sibling = sibling.nextSibling + return None + + +def _is_run(node) -> bool: + name = node.localName or node.tagName + return name == "r" or name.endswith(":r") + + +def _can_merge(run1, run2) -> bool: + rpr1 = _get_child(run1, "rPr") + rpr2 = _get_child(run2, "rPr") + + if (rpr1 is None) != (rpr2 is None): + return False + if rpr1 is None: + return True + return rpr1.toxml() == rpr2.toxml() + + +def _merge_run_content(target, source): + for child in list(source.childNodes): + if child.nodeType == child.ELEMENT_NODE: + name = child.localName or child.tagName + if name != "rPr" and not name.endswith(":rPr"): + target.appendChild(child) + + +def _consolidate_text(run): + t_elements = _get_children(run, "t") + + for i in range(len(t_elements) - 1, 0, -1): + curr, prev = t_elements[i], t_elements[i - 1] + + if _is_adjacent(prev, curr): + prev_text = prev.firstChild.data if prev.firstChild else "" + curr_text = curr.firstChild.data if curr.firstChild else "" + merged = prev_text + curr_text + + if prev.firstChild: + prev.firstChild.data = merged + else: + prev.appendChild(run.ownerDocument.createTextNode(merged)) + + if merged.startswith(" ") or merged.endswith(" "): + prev.setAttribute("xml:space", "preserve") + elif prev.hasAttribute("xml:space"): + prev.removeAttribute("xml:space") + + run.removeChild(curr) diff --git a/dev-tools/skills/docx/scripts/office/helpers/simplify_redlines.py b/dev-tools/skills/docx/scripts/office/helpers/simplify_redlines.py new file mode 100644 index 0000000..db963bb --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/helpers/simplify_redlines.py @@ -0,0 +1,197 @@ +"""Simplify tracked changes by merging adjacent w:ins or w:del elements. + +Merges adjacent elements from the same author into a single element. +Same for elements. This makes heavily-redlined documents easier to +work with by reducing the number of tracked change wrappers. + +Rules: +- Only merges w:ins with w:ins, w:del with w:del (same element type) +- Only merges if same author (ignores timestamp differences) +- Only merges if truly adjacent (only whitespace between them) +""" + +import xml.etree.ElementTree as ET +import zipfile +from pathlib import Path + +import defusedxml.minidom + +WORD_NS = "http://schemas.openxmlformats.org/wordprocessingml/2006/main" + + +def simplify_redlines(input_dir: str) -> tuple[int, str]: + doc_xml = Path(input_dir) / "word" / "document.xml" + + if not doc_xml.exists(): + return 0, f"Error: {doc_xml} not found" + + try: + dom = defusedxml.minidom.parseString(doc_xml.read_text(encoding="utf-8")) + root = dom.documentElement + + merge_count = 0 + + containers = _find_elements(root, "p") + _find_elements(root, "tc") + + for container in containers: + merge_count += _merge_tracked_changes_in(container, "ins") + merge_count += _merge_tracked_changes_in(container, "del") + + doc_xml.write_bytes(dom.toxml(encoding="UTF-8")) + return merge_count, f"Simplified {merge_count} tracked changes" + + except Exception as e: + return 0, f"Error: {e}" + + +def _merge_tracked_changes_in(container, tag: str) -> int: + merge_count = 0 + + tracked = [ + child + for child in container.childNodes + if child.nodeType == child.ELEMENT_NODE and _is_element(child, tag) + ] + + if len(tracked) < 2: + return 0 + + i = 0 + while i < len(tracked) - 1: + curr = tracked[i] + next_elem = tracked[i + 1] + + if _can_merge_tracked(curr, next_elem): + _merge_tracked_content(curr, next_elem) + container.removeChild(next_elem) + tracked.pop(i + 1) + merge_count += 1 + else: + i += 1 + + return merge_count + + +def _is_element(node, tag: str) -> bool: + name = node.localName or node.tagName + return name == tag or name.endswith(f":{tag}") + + +def _get_author(elem) -> str: + author = elem.getAttribute("w:author") + if not author: + for attr in elem.attributes.values(): + if attr.localName == "author" or attr.name.endswith(":author"): + return attr.value + return author + + +def _can_merge_tracked(elem1, elem2) -> bool: + if _get_author(elem1) != _get_author(elem2): + return False + + node = elem1.nextSibling + while node and node != elem2: + if node.nodeType == node.ELEMENT_NODE: + return False + if node.nodeType == node.TEXT_NODE and node.data.strip(): + return False + node = node.nextSibling + + return True + + +def _merge_tracked_content(target, source): + while source.firstChild: + child = source.firstChild + source.removeChild(child) + target.appendChild(child) + + +def _find_elements(root, tag: str) -> list: + results = [] + + def traverse(node): + if node.nodeType == node.ELEMENT_NODE: + name = node.localName or node.tagName + if name == tag or name.endswith(f":{tag}"): + results.append(node) + for child in node.childNodes: + traverse(child) + + traverse(root) + return results + + +def get_tracked_change_authors(doc_xml_path: Path) -> dict[str, int]: + if not doc_xml_path.exists(): + return {} + + try: + tree = ET.parse(doc_xml_path) + root = tree.getroot() + except ET.ParseError: + return {} + + namespaces = {"w": WORD_NS} + author_attr = f"{{{WORD_NS}}}author" + + authors: dict[str, int] = {} + for tag in ["ins", "del"]: + for elem in root.findall(f".//w:{tag}", namespaces): + author = elem.get(author_attr) + if author: + authors[author] = authors.get(author, 0) + 1 + + return authors + + +def _get_authors_from_docx(docx_path: Path) -> dict[str, int]: + try: + with zipfile.ZipFile(docx_path, "r") as zf: + if "word/document.xml" not in zf.namelist(): + return {} + with zf.open("word/document.xml") as f: + tree = ET.parse(f) + root = tree.getroot() + + namespaces = {"w": WORD_NS} + author_attr = f"{{{WORD_NS}}}author" + + authors: dict[str, int] = {} + for tag in ["ins", "del"]: + for elem in root.findall(f".//w:{tag}", namespaces): + author = elem.get(author_attr) + if author: + authors[author] = authors.get(author, 0) + 1 + return authors + except (zipfile.BadZipFile, ET.ParseError): + return {} + + +def infer_author(modified_dir: Path, original_docx: Path, default: str = "Claude") -> str: + modified_xml = modified_dir / "word" / "document.xml" + modified_authors = get_tracked_change_authors(modified_xml) + + if not modified_authors: + return default + + original_authors = _get_authors_from_docx(original_docx) + + new_changes: dict[str, int] = {} + for author, count in modified_authors.items(): + original_count = original_authors.get(author, 0) + diff = count - original_count + if diff > 0: + new_changes[author] = diff + + if not new_changes: + return default + + if len(new_changes) == 1: + return next(iter(new_changes)) + + raise ValueError( + f"Multiple authors added new changes: {new_changes}. " + "Cannot infer which author to validate." + ) diff --git a/dev-tools/skills/docx/scripts/office/pack.py b/dev-tools/skills/docx/scripts/office/pack.py new file mode 100755 index 0000000..db29ed8 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/pack.py @@ -0,0 +1,159 @@ +"""Pack a directory into a DOCX, PPTX, or XLSX file. + +Validates with auto-repair, condenses XML formatting, and creates the Office file. + +Usage: + python pack.py [--original ] [--validate true|false] + +Examples: + python pack.py unpacked/ output.docx --original input.docx + python pack.py unpacked/ output.pptx --validate false +""" + +import argparse +import sys +import shutil +import tempfile +import zipfile +from pathlib import Path + +import defusedxml.minidom + +from validators import DOCXSchemaValidator, PPTXSchemaValidator, RedliningValidator + +def pack( + input_directory: str, + output_file: str, + original_file: str | None = None, + validate: bool = True, + infer_author_func=None, +) -> tuple[None, str]: + input_dir = Path(input_directory) + output_path = Path(output_file) + suffix = output_path.suffix.lower() + + if not input_dir.is_dir(): + return None, f"Error: {input_dir} is not a directory" + + if suffix not in {".docx", ".pptx", ".xlsx"}: + return None, f"Error: {output_file} must be a .docx, .pptx, or .xlsx file" + + if validate and original_file: + original_path = Path(original_file) + if original_path.exists(): + success, output = _run_validation( + input_dir, original_path, suffix, infer_author_func + ) + if output: + print(output) + if not success: + return None, f"Error: Validation failed for {input_dir}" + + with tempfile.TemporaryDirectory() as temp_dir: + temp_content_dir = Path(temp_dir) / "content" + shutil.copytree(input_dir, temp_content_dir) + + for pattern in ["*.xml", "*.rels"]: + for xml_file in temp_content_dir.rglob(pattern): + _condense_xml(xml_file) + + output_path.parent.mkdir(parents=True, exist_ok=True) + with zipfile.ZipFile(output_path, "w", zipfile.ZIP_DEFLATED) as zf: + for f in temp_content_dir.rglob("*"): + if f.is_file(): + zf.write(f, f.relative_to(temp_content_dir)) + + return None, f"Successfully packed {input_dir} to {output_file}" + + +def _run_validation( + unpacked_dir: Path, + original_file: Path, + suffix: str, + infer_author_func=None, +) -> tuple[bool, str | None]: + output_lines = [] + validators = [] + + if suffix == ".docx": + author = "Claude" + if infer_author_func: + try: + author = infer_author_func(unpacked_dir, original_file) + except ValueError as e: + print(f"Warning: {e} Using default author 'Claude'.", file=sys.stderr) + + validators = [ + DOCXSchemaValidator(unpacked_dir, original_file), + RedliningValidator(unpacked_dir, original_file, author=author), + ] + elif suffix == ".pptx": + validators = [PPTXSchemaValidator(unpacked_dir, original_file)] + + if not validators: + return True, None + + total_repairs = sum(v.repair() for v in validators) + if total_repairs: + output_lines.append(f"Auto-repaired {total_repairs} issue(s)") + + success = all(v.validate() for v in validators) + + if success: + output_lines.append("All validations PASSED!") + + return success, "\n".join(output_lines) if output_lines else None + + +def _condense_xml(xml_file: Path) -> None: + try: + with open(xml_file, encoding="utf-8") as f: + dom = defusedxml.minidom.parse(f) + + for element in dom.getElementsByTagName("*"): + if element.tagName.endswith(":t"): + continue + + for child in list(element.childNodes): + if ( + child.nodeType == child.TEXT_NODE + and child.nodeValue + and child.nodeValue.strip() == "" + ) or child.nodeType == child.COMMENT_NODE: + element.removeChild(child) + + xml_file.write_bytes(dom.toxml(encoding="UTF-8")) + except Exception as e: + print(f"ERROR: Failed to parse {xml_file.name}: {e}", file=sys.stderr) + raise + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Pack a directory into a DOCX, PPTX, or XLSX file" + ) + parser.add_argument("input_directory", help="Unpacked Office document directory") + parser.add_argument("output_file", help="Output Office file (.docx/.pptx/.xlsx)") + parser.add_argument( + "--original", + help="Original file for validation comparison", + ) + parser.add_argument( + "--validate", + type=lambda x: x.lower() == "true", + default=True, + metavar="true|false", + help="Run validation with auto-repair (default: true)", + ) + args = parser.parse_args() + + _, message = pack( + args.input_directory, + args.output_file, + original_file=args.original, + validate=args.validate, + ) + print(message) + + if "Error" in message: + sys.exit(1) diff --git a/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd new file mode 100644 index 0000000..6454ef9 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd @@ -0,0 +1,1499 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd new file mode 100644 index 0000000..afa4f46 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd new file mode 100644 index 0000000..64e66b8 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd @@ -0,0 +1,1085 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd new file mode 100644 index 0000000..687eea8 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd @@ -0,0 +1,11 @@ + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd new file mode 100644 index 0000000..6ac81b0 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd @@ -0,0 +1,3081 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd new file mode 100644 index 0000000..1dbf051 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd new file mode 100644 index 0000000..f1af17d --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd new file mode 100644 index 0000000..0a185ab --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd @@ -0,0 +1,287 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd new file mode 100644 index 0000000..14ef488 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd @@ -0,0 +1,1676 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd new file mode 100644 index 0000000..c20f3bf --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd new file mode 100644 index 0000000..ac60252 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd new file mode 100644 index 0000000..424b8ba --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd new file mode 100644 index 0000000..2bddce2 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd new file mode 100644 index 0000000..8a8c18b --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd new file mode 100644 index 0000000..5c42706 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd new file mode 100644 index 0000000..853c341 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd new file mode 100644 index 0000000..da835ee --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd @@ -0,0 +1,195 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd new file mode 100644 index 0000000..87ad265 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd @@ -0,0 +1,582 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd new file mode 100644 index 0000000..9e86f1b --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd new file mode 100644 index 0000000..d0be42e --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd @@ -0,0 +1,4439 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd new file mode 100644 index 0000000..8821dd1 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd @@ -0,0 +1,570 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd new file mode 100644 index 0000000..ca2575c --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd @@ -0,0 +1,509 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd new file mode 100644 index 0000000..dd079e6 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd new file mode 100644 index 0000000..3dd6cf6 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd new file mode 100644 index 0000000..f1041e3 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd new file mode 100644 index 0000000..9c5b7a6 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd @@ -0,0 +1,3646 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd new file mode 100644 index 0000000..0f13678 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd @@ -0,0 +1,116 @@ + + + + + + See http://www.w3.org/XML/1998/namespace.html and + http://www.w3.org/TR/REC-xml for information about this namespace. + + This schema document describes the XML namespace, in a form + suitable for import by other schema documents. + + Note that local names in this namespace are intended to be defined + only by the World Wide Web Consortium or its subgroups. The + following names are currently defined in this namespace and should + not be used with conflicting semantics by any Working Group, + specification, or document instance: + + base (as an attribute name): denotes an attribute whose value + provides a URI to be used as the base for interpreting any + relative URIs in the scope of the element on which it + appears; its value is inherited. This name is reserved + by virtue of its definition in the XML Base specification. + + lang (as an attribute name): denotes an attribute whose value + is a language code for the natural language of the content of + any element; its value is inherited. This name is reserved + by virtue of its definition in the XML specification. + + space (as an attribute name): denotes an attribute whose + value is a keyword indicating what whitespace processing + discipline is intended for the content of the element; its + value is inherited. This name is reserved by virtue of its + definition in the XML specification. + + Father (in any context at all): denotes Jon Bosak, the chair of + the original XML Working Group. This name is reserved by + the following decision of the W3C XML Plenary and + XML Coordination groups: + + In appreciation for his vision, leadership and dedication + the W3C XML Plenary on this 10th day of February, 2000 + reserves for Jon Bosak in perpetuity the XML name + xml:Father + + + + + This schema defines attributes and an attribute group + suitable for use by + schemas wishing to allow xml:base, xml:lang or xml:space attributes + on elements they define. + + To enable this, such a schema must import this schema + for the XML namespace, e.g. as follows: + <schema . . .> + . . . + <import namespace="http://www.w3.org/XML/1998/namespace" + schemaLocation="http://www.w3.org/2001/03/xml.xsd"/> + + Subsequently, qualified reference to any of the attributes + or the group defined below will have the desired effect, e.g. + + <type . . .> + . . . + <attributeGroup ref="xml:specialAttrs"/> + + will define a type which will schema-validate an instance + element with any of those attributes + + + + In keeping with the XML Schema WG's standard versioning + policy, this schema document will persist at + http://www.w3.org/2001/03/xml.xsd. + At the date of issue it can also be found at + http://www.w3.org/2001/xml.xsd. + The schema document at that URI may however change in the future, + in order to remain compatible with the latest version of XML Schema + itself. In other words, if the XML Schema namespace changes, the version + of this document at + http://www.w3.org/2001/xml.xsd will change + accordingly; the version at + http://www.w3.org/2001/03/xml.xsd will not change. + + + + + + In due course, we should install the relevant ISO 2- and 3-letter + codes as the enumerated possible values . . . + + + + + + + + + + + + + + + See http://www.w3.org/TR/xmlbase/ for + information about this attribute. + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd b/dev-tools/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd new file mode 100644 index 0000000..a6de9d2 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd b/dev-tools/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd new file mode 100644 index 0000000..10e978b --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd b/dev-tools/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd new file mode 100644 index 0000000..4248bf7 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd b/dev-tools/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd new file mode 100644 index 0000000..5649746 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/mce/mc.xsd b/dev-tools/skills/docx/scripts/office/schemas/mce/mc.xsd new file mode 100644 index 0000000..ef72545 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/mce/mc.xsd @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/microsoft/wml-2010.xsd b/dev-tools/skills/docx/scripts/office/schemas/microsoft/wml-2010.xsd new file mode 100644 index 0000000..f65f777 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/microsoft/wml-2010.xsd @@ -0,0 +1,560 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/microsoft/wml-2012.xsd b/dev-tools/skills/docx/scripts/office/schemas/microsoft/wml-2012.xsd new file mode 100644 index 0000000..6b00755 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/microsoft/wml-2012.xsd @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/microsoft/wml-2018.xsd b/dev-tools/skills/docx/scripts/office/schemas/microsoft/wml-2018.xsd new file mode 100644 index 0000000..f321d33 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/microsoft/wml-2018.xsd @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/microsoft/wml-cex-2018.xsd b/dev-tools/skills/docx/scripts/office/schemas/microsoft/wml-cex-2018.xsd new file mode 100644 index 0000000..364c6a9 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/microsoft/wml-cex-2018.xsd @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/microsoft/wml-cid-2016.xsd b/dev-tools/skills/docx/scripts/office/schemas/microsoft/wml-cid-2016.xsd new file mode 100644 index 0000000..fed9d15 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/microsoft/wml-cid-2016.xsd @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd b/dev-tools/skills/docx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd new file mode 100644 index 0000000..680cf15 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd @@ -0,0 +1,4 @@ + + + + diff --git a/dev-tools/skills/docx/scripts/office/schemas/microsoft/wml-symex-2015.xsd b/dev-tools/skills/docx/scripts/office/schemas/microsoft/wml-symex-2015.xsd new file mode 100644 index 0000000..89ada90 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/schemas/microsoft/wml-symex-2015.xsd @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/dev-tools/skills/docx/scripts/office/soffice.py b/dev-tools/skills/docx/scripts/office/soffice.py new file mode 100644 index 0000000..c7f7e32 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/soffice.py @@ -0,0 +1,183 @@ +""" +Helper for running LibreOffice (soffice) in environments where AF_UNIX +sockets may be blocked (e.g., sandboxed VMs). Detects the restriction +at runtime and applies an LD_PRELOAD shim if needed. + +Usage: + from office.soffice import run_soffice, get_soffice_env + + # Option 1 – run soffice directly + result = run_soffice(["--headless", "--convert-to", "pdf", "input.docx"]) + + # Option 2 – get env dict for your own subprocess calls + env = get_soffice_env() + subprocess.run(["soffice", ...], env=env) +""" + +import os +import socket +import subprocess +import tempfile +from pathlib import Path + + +def get_soffice_env() -> dict: + env = os.environ.copy() + env["SAL_USE_VCLPLUGIN"] = "svp" + + if _needs_shim(): + shim = _ensure_shim() + env["LD_PRELOAD"] = str(shim) + + return env + + +def run_soffice(args: list[str], **kwargs) -> subprocess.CompletedProcess: + env = get_soffice_env() + return subprocess.run(["soffice"] + args, env=env, **kwargs) + + + +_SHIM_SO = Path(tempfile.gettempdir()) / "lo_socket_shim.so" + + +def _needs_shim() -> bool: + try: + s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + s.close() + return False + except OSError: + return True + + +def _ensure_shim() -> Path: + if _SHIM_SO.exists(): + return _SHIM_SO + + src = Path(tempfile.gettempdir()) / "lo_socket_shim.c" + src.write_text(_SHIM_SOURCE) + subprocess.run( + ["gcc", "-shared", "-fPIC", "-o", str(_SHIM_SO), str(src), "-ldl"], + check=True, + capture_output=True, + ) + src.unlink() + return _SHIM_SO + + + +_SHIM_SOURCE = r""" +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include + +static int (*real_socket)(int, int, int); +static int (*real_socketpair)(int, int, int, int[2]); +static int (*real_listen)(int, int); +static int (*real_accept)(int, struct sockaddr *, socklen_t *); +static int (*real_close)(int); +static int (*real_read)(int, void *, size_t); + +/* Per-FD bookkeeping (FDs >= 1024 are passed through unshimmed). */ +static int is_shimmed[1024]; +static int peer_of[1024]; +static int wake_r[1024]; /* accept() blocks reading this */ +static int wake_w[1024]; /* close() writes to this */ +static int listener_fd = -1; /* FD that received listen() */ + +__attribute__((constructor)) +static void init(void) { + real_socket = dlsym(RTLD_NEXT, "socket"); + real_socketpair = dlsym(RTLD_NEXT, "socketpair"); + real_listen = dlsym(RTLD_NEXT, "listen"); + real_accept = dlsym(RTLD_NEXT, "accept"); + real_close = dlsym(RTLD_NEXT, "close"); + real_read = dlsym(RTLD_NEXT, "read"); + for (int i = 0; i < 1024; i++) { + peer_of[i] = -1; + wake_r[i] = -1; + wake_w[i] = -1; + } +} + +/* ---- socket ---------------------------------------------------------- */ +int socket(int domain, int type, int protocol) { + if (domain == AF_UNIX) { + int fd = real_socket(domain, type, protocol); + if (fd >= 0) return fd; + /* socket(AF_UNIX) blocked – fall back to socketpair(). */ + int sv[2]; + if (real_socketpair(domain, type, protocol, sv) == 0) { + if (sv[0] >= 0 && sv[0] < 1024) { + is_shimmed[sv[0]] = 1; + peer_of[sv[0]] = sv[1]; + int wp[2]; + if (pipe(wp) == 0) { + wake_r[sv[0]] = wp[0]; + wake_w[sv[0]] = wp[1]; + } + } + return sv[0]; + } + errno = EPERM; + return -1; + } + return real_socket(domain, type, protocol); +} + +/* ---- listen ---------------------------------------------------------- */ +int listen(int sockfd, int backlog) { + if (sockfd >= 0 && sockfd < 1024 && is_shimmed[sockfd]) { + listener_fd = sockfd; + return 0; + } + return real_listen(sockfd, backlog); +} + +/* ---- accept ---------------------------------------------------------- */ +int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { + if (sockfd >= 0 && sockfd < 1024 && is_shimmed[sockfd]) { + /* Block until close() writes to the wake pipe. */ + if (wake_r[sockfd] >= 0) { + char buf; + real_read(wake_r[sockfd], &buf, 1); + } + errno = ECONNABORTED; + return -1; + } + return real_accept(sockfd, addr, addrlen); +} + +/* ---- close ----------------------------------------------------------- */ +int close(int fd) { + if (fd >= 0 && fd < 1024 && is_shimmed[fd]) { + int was_listener = (fd == listener_fd); + is_shimmed[fd] = 0; + + if (wake_w[fd] >= 0) { /* unblock accept() */ + char c = 0; + write(wake_w[fd], &c, 1); + real_close(wake_w[fd]); + wake_w[fd] = -1; + } + if (wake_r[fd] >= 0) { real_close(wake_r[fd]); wake_r[fd] = -1; } + if (peer_of[fd] >= 0) { real_close(peer_of[fd]); peer_of[fd] = -1; } + + if (was_listener) + _exit(0); /* conversion done – exit */ + } + return real_close(fd); +} +""" + + + +if __name__ == "__main__": + import sys + result = run_soffice(sys.argv[1:]) + sys.exit(result.returncode) diff --git a/dev-tools/skills/docx/scripts/office/unpack.py b/dev-tools/skills/docx/scripts/office/unpack.py new file mode 100755 index 0000000..0015253 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/unpack.py @@ -0,0 +1,132 @@ +"""Unpack Office files (DOCX, PPTX, XLSX) for editing. + +Extracts the ZIP archive, pretty-prints XML files, and optionally: +- Merges adjacent runs with identical formatting (DOCX only) +- Simplifies adjacent tracked changes from same author (DOCX only) + +Usage: + python unpack.py [options] + +Examples: + python unpack.py document.docx unpacked/ + python unpack.py presentation.pptx unpacked/ + python unpack.py document.docx unpacked/ --merge-runs false +""" + +import argparse +import sys +import zipfile +from pathlib import Path + +import defusedxml.minidom + +from helpers.merge_runs import merge_runs as do_merge_runs +from helpers.simplify_redlines import simplify_redlines as do_simplify_redlines + +SMART_QUOTE_REPLACEMENTS = { + "\u201c": "“", + "\u201d": "”", + "\u2018": "‘", + "\u2019": "’", +} + + +def unpack( + input_file: str, + output_directory: str, + merge_runs: bool = True, + simplify_redlines: bool = True, +) -> tuple[None, str]: + input_path = Path(input_file) + output_path = Path(output_directory) + suffix = input_path.suffix.lower() + + if not input_path.exists(): + return None, f"Error: {input_file} does not exist" + + if suffix not in {".docx", ".pptx", ".xlsx"}: + return None, f"Error: {input_file} must be a .docx, .pptx, or .xlsx file" + + try: + output_path.mkdir(parents=True, exist_ok=True) + + with zipfile.ZipFile(input_path, "r") as zf: + zf.extractall(output_path) + + xml_files = list(output_path.rglob("*.xml")) + list(output_path.rglob("*.rels")) + for xml_file in xml_files: + _pretty_print_xml(xml_file) + + message = f"Unpacked {input_file} ({len(xml_files)} XML files)" + + if suffix == ".docx": + if simplify_redlines: + simplify_count, _ = do_simplify_redlines(str(output_path)) + message += f", simplified {simplify_count} tracked changes" + + if merge_runs: + merge_count, _ = do_merge_runs(str(output_path)) + message += f", merged {merge_count} runs" + + for xml_file in xml_files: + _escape_smart_quotes(xml_file) + + return None, message + + except zipfile.BadZipFile: + return None, f"Error: {input_file} is not a valid Office file" + except Exception as e: + return None, f"Error unpacking: {e}" + + +def _pretty_print_xml(xml_file: Path) -> None: + try: + content = xml_file.read_text(encoding="utf-8") + dom = defusedxml.minidom.parseString(content) + xml_file.write_bytes(dom.toprettyxml(indent=" ", encoding="utf-8")) + except Exception: + pass + + +def _escape_smart_quotes(xml_file: Path) -> None: + try: + content = xml_file.read_text(encoding="utf-8") + for char, entity in SMART_QUOTE_REPLACEMENTS.items(): + content = content.replace(char, entity) + xml_file.write_text(content, encoding="utf-8") + except Exception: + pass + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Unpack an Office file (DOCX, PPTX, XLSX) for editing" + ) + parser.add_argument("input_file", help="Office file to unpack") + parser.add_argument("output_directory", help="Output directory") + parser.add_argument( + "--merge-runs", + type=lambda x: x.lower() == "true", + default=True, + metavar="true|false", + help="Merge adjacent runs with identical formatting (DOCX only, default: true)", + ) + parser.add_argument( + "--simplify-redlines", + type=lambda x: x.lower() == "true", + default=True, + metavar="true|false", + help="Merge adjacent tracked changes from same author (DOCX only, default: true)", + ) + args = parser.parse_args() + + _, message = unpack( + args.input_file, + args.output_directory, + merge_runs=args.merge_runs, + simplify_redlines=args.simplify_redlines, + ) + print(message) + + if "Error" in message: + sys.exit(1) diff --git a/dev-tools/skills/docx/scripts/office/validate.py b/dev-tools/skills/docx/scripts/office/validate.py new file mode 100755 index 0000000..03b01f6 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/validate.py @@ -0,0 +1,111 @@ +""" +Command line tool to validate Office document XML files against XSD schemas and tracked changes. + +Usage: + python validate.py [--original ] [--auto-repair] [--author NAME] + +The first argument can be either: +- An unpacked directory containing the Office document XML files +- A packed Office file (.docx/.pptx/.xlsx) which will be unpacked to a temp directory + +Auto-repair fixes: +- paraId/durableId values that exceed OOXML limits +- Missing xml:space="preserve" on w:t elements with whitespace +""" + +import argparse +import sys +import tempfile +import zipfile +from pathlib import Path + +from validators import DOCXSchemaValidator, PPTXSchemaValidator, RedliningValidator + + +def main(): + parser = argparse.ArgumentParser(description="Validate Office document XML files") + parser.add_argument( + "path", + help="Path to unpacked directory or packed Office file (.docx/.pptx/.xlsx)", + ) + parser.add_argument( + "--original", + required=False, + default=None, + help="Path to original file (.docx/.pptx/.xlsx). If omitted, all XSD errors are reported and redlining validation is skipped.", + ) + parser.add_argument( + "-v", + "--verbose", + action="store_true", + help="Enable verbose output", + ) + parser.add_argument( + "--auto-repair", + action="store_true", + help="Automatically repair common issues (hex IDs, whitespace preservation)", + ) + parser.add_argument( + "--author", + default="Claude", + help="Author name for redlining validation (default: Claude)", + ) + args = parser.parse_args() + + path = Path(args.path) + assert path.exists(), f"Error: {path} does not exist" + + original_file = None + if args.original: + original_file = Path(args.original) + assert original_file.is_file(), f"Error: {original_file} is not a file" + assert original_file.suffix.lower() in [".docx", ".pptx", ".xlsx"], ( + f"Error: {original_file} must be a .docx, .pptx, or .xlsx file" + ) + + file_extension = (original_file or path).suffix.lower() + assert file_extension in [".docx", ".pptx", ".xlsx"], ( + f"Error: Cannot determine file type from {path}. Use --original or provide a .docx/.pptx/.xlsx file." + ) + + if path.is_file() and path.suffix.lower() in [".docx", ".pptx", ".xlsx"]: + temp_dir = tempfile.mkdtemp() + with zipfile.ZipFile(path, "r") as zf: + zf.extractall(temp_dir) + unpacked_dir = Path(temp_dir) + else: + assert path.is_dir(), f"Error: {path} is not a directory or Office file" + unpacked_dir = path + + match file_extension: + case ".docx": + validators = [ + DOCXSchemaValidator(unpacked_dir, original_file, verbose=args.verbose), + ] + if original_file: + validators.append( + RedliningValidator(unpacked_dir, original_file, verbose=args.verbose, author=args.author) + ) + case ".pptx": + validators = [ + PPTXSchemaValidator(unpacked_dir, original_file, verbose=args.verbose), + ] + case _: + print(f"Error: Validation not supported for file type {file_extension}") + sys.exit(1) + + if args.auto_repair: + total_repairs = sum(v.repair() for v in validators) + if total_repairs: + print(f"Auto-repaired {total_repairs} issue(s)") + + success = all(v.validate() for v in validators) + + if success: + print("All validations PASSED!") + + sys.exit(0 if success else 1) + + +if __name__ == "__main__": + main() diff --git a/dev-tools/skills/docx/scripts/office/validators/__init__.py b/dev-tools/skills/docx/scripts/office/validators/__init__.py new file mode 100644 index 0000000..db092ec --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/validators/__init__.py @@ -0,0 +1,15 @@ +""" +Validation modules for Word document processing. +""" + +from .base import BaseSchemaValidator +from .docx import DOCXSchemaValidator +from .pptx import PPTXSchemaValidator +from .redlining import RedliningValidator + +__all__ = [ + "BaseSchemaValidator", + "DOCXSchemaValidator", + "PPTXSchemaValidator", + "RedliningValidator", +] diff --git a/dev-tools/skills/docx/scripts/office/validators/base.py b/dev-tools/skills/docx/scripts/office/validators/base.py new file mode 100644 index 0000000..db4a06a --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/validators/base.py @@ -0,0 +1,847 @@ +""" +Base validator with common validation logic for document files. +""" + +import re +from pathlib import Path + +import defusedxml.minidom +import lxml.etree + + +class BaseSchemaValidator: + + IGNORED_VALIDATION_ERRORS = [ + "hyphenationZone", + "purl.org/dc/terms", + ] + + UNIQUE_ID_REQUIREMENTS = { + "comment": ("id", "file"), + "commentrangestart": ("id", "file"), + "commentrangeend": ("id", "file"), + "bookmarkstart": ("id", "file"), + "bookmarkend": ("id", "file"), + "sldid": ("id", "file"), + "sldmasterid": ("id", "global"), + "sldlayoutid": ("id", "global"), + "cm": ("authorid", "file"), + "sheet": ("sheetid", "file"), + "definedname": ("id", "file"), + "cxnsp": ("id", "file"), + "sp": ("id", "file"), + "pic": ("id", "file"), + "grpsp": ("id", "file"), + } + + EXCLUDED_ID_CONTAINERS = { + "sectionlst", + } + + ELEMENT_RELATIONSHIP_TYPES = {} + + SCHEMA_MAPPINGS = { + "word": "ISO-IEC29500-4_2016/wml.xsd", + "ppt": "ISO-IEC29500-4_2016/pml.xsd", + "xl": "ISO-IEC29500-4_2016/sml.xsd", + "[Content_Types].xml": "ecma/fouth-edition/opc-contentTypes.xsd", + "app.xml": "ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd", + "core.xml": "ecma/fouth-edition/opc-coreProperties.xsd", + "custom.xml": "ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd", + ".rels": "ecma/fouth-edition/opc-relationships.xsd", + "people.xml": "microsoft/wml-2012.xsd", + "commentsIds.xml": "microsoft/wml-cid-2016.xsd", + "commentsExtensible.xml": "microsoft/wml-cex-2018.xsd", + "commentsExtended.xml": "microsoft/wml-2012.xsd", + "chart": "ISO-IEC29500-4_2016/dml-chart.xsd", + "theme": "ISO-IEC29500-4_2016/dml-main.xsd", + "drawing": "ISO-IEC29500-4_2016/dml-main.xsd", + } + + MC_NAMESPACE = "http://schemas.openxmlformats.org/markup-compatibility/2006" + XML_NAMESPACE = "http://www.w3.org/XML/1998/namespace" + + PACKAGE_RELATIONSHIPS_NAMESPACE = ( + "http://schemas.openxmlformats.org/package/2006/relationships" + ) + OFFICE_RELATIONSHIPS_NAMESPACE = ( + "http://schemas.openxmlformats.org/officeDocument/2006/relationships" + ) + CONTENT_TYPES_NAMESPACE = ( + "http://schemas.openxmlformats.org/package/2006/content-types" + ) + + MAIN_CONTENT_FOLDERS = {"word", "ppt", "xl"} + + OOXML_NAMESPACES = { + "http://schemas.openxmlformats.org/officeDocument/2006/math", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships", + "http://schemas.openxmlformats.org/schemaLibrary/2006/main", + "http://schemas.openxmlformats.org/drawingml/2006/main", + "http://schemas.openxmlformats.org/drawingml/2006/chart", + "http://schemas.openxmlformats.org/drawingml/2006/chartDrawing", + "http://schemas.openxmlformats.org/drawingml/2006/diagram", + "http://schemas.openxmlformats.org/drawingml/2006/picture", + "http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing", + "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing", + "http://schemas.openxmlformats.org/wordprocessingml/2006/main", + "http://schemas.openxmlformats.org/presentationml/2006/main", + "http://schemas.openxmlformats.org/spreadsheetml/2006/main", + "http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes", + "http://www.w3.org/XML/1998/namespace", + } + + def __init__(self, unpacked_dir, original_file=None, verbose=False): + self.unpacked_dir = Path(unpacked_dir).resolve() + self.original_file = Path(original_file) if original_file else None + self.verbose = verbose + + self.schemas_dir = Path(__file__).parent.parent / "schemas" + + patterns = ["*.xml", "*.rels"] + self.xml_files = [ + f for pattern in patterns for f in self.unpacked_dir.rglob(pattern) + ] + + if not self.xml_files: + print(f"Warning: No XML files found in {self.unpacked_dir}") + + def validate(self): + raise NotImplementedError("Subclasses must implement the validate method") + + def repair(self) -> int: + return self.repair_whitespace_preservation() + + def repair_whitespace_preservation(self) -> int: + repairs = 0 + + for xml_file in self.xml_files: + try: + content = xml_file.read_text(encoding="utf-8") + dom = defusedxml.minidom.parseString(content) + modified = False + + for elem in dom.getElementsByTagName("*"): + if elem.tagName.endswith(":t") and elem.firstChild: + text = elem.firstChild.nodeValue + if text and (text.startswith((' ', '\t')) or text.endswith((' ', '\t'))): + if elem.getAttribute("xml:space") != "preserve": + elem.setAttribute("xml:space", "preserve") + text_preview = repr(text[:30]) + "..." if len(text) > 30 else repr(text) + print(f" Repaired: {xml_file.name}: Added xml:space='preserve' to {elem.tagName}: {text_preview}") + repairs += 1 + modified = True + + if modified: + xml_file.write_bytes(dom.toxml(encoding="UTF-8")) + + except Exception: + pass + + return repairs + + def validate_xml(self): + errors = [] + + for xml_file in self.xml_files: + try: + lxml.etree.parse(str(xml_file)) + except lxml.etree.XMLSyntaxError as e: + errors.append( + f" {xml_file.relative_to(self.unpacked_dir)}: " + f"Line {e.lineno}: {e.msg}" + ) + except Exception as e: + errors.append( + f" {xml_file.relative_to(self.unpacked_dir)}: " + f"Unexpected error: {str(e)}" + ) + + if errors: + print(f"FAILED - Found {len(errors)} XML violations:") + for error in errors: + print(error) + return False + else: + if self.verbose: + print("PASSED - All XML files are well-formed") + return True + + def validate_namespaces(self): + errors = [] + + for xml_file in self.xml_files: + try: + root = lxml.etree.parse(str(xml_file)).getroot() + declared = set(root.nsmap.keys()) - {None} + + for attr_val in [ + v for k, v in root.attrib.items() if k.endswith("Ignorable") + ]: + undeclared = set(attr_val.split()) - declared + errors.extend( + f" {xml_file.relative_to(self.unpacked_dir)}: " + f"Namespace '{ns}' in Ignorable but not declared" + for ns in undeclared + ) + except lxml.etree.XMLSyntaxError: + continue + + if errors: + print(f"FAILED - {len(errors)} namespace issues:") + for error in errors: + print(error) + return False + if self.verbose: + print("PASSED - All namespace prefixes properly declared") + return True + + def validate_unique_ids(self): + errors = [] + global_ids = {} + + for xml_file in self.xml_files: + try: + root = lxml.etree.parse(str(xml_file)).getroot() + file_ids = {} + + mc_elements = root.xpath( + ".//mc:AlternateContent", namespaces={"mc": self.MC_NAMESPACE} + ) + for elem in mc_elements: + elem.getparent().remove(elem) + + for elem in root.iter(): + tag = ( + elem.tag.split("}")[-1].lower() + if "}" in elem.tag + else elem.tag.lower() + ) + + if tag in self.UNIQUE_ID_REQUIREMENTS: + in_excluded_container = any( + ancestor.tag.split("}")[-1].lower() in self.EXCLUDED_ID_CONTAINERS + for ancestor in elem.iterancestors() + ) + if in_excluded_container: + continue + + attr_name, scope = self.UNIQUE_ID_REQUIREMENTS[tag] + + id_value = None + for attr, value in elem.attrib.items(): + attr_local = ( + attr.split("}")[-1].lower() + if "}" in attr + else attr.lower() + ) + if attr_local == attr_name: + id_value = value + break + + if id_value is not None: + if scope == "global": + if id_value in global_ids: + prev_file, prev_line, prev_tag = global_ids[ + id_value + ] + errors.append( + f" {xml_file.relative_to(self.unpacked_dir)}: " + f"Line {elem.sourceline}: Global ID '{id_value}' in <{tag}> " + f"already used in {prev_file} at line {prev_line} in <{prev_tag}>" + ) + else: + global_ids[id_value] = ( + xml_file.relative_to(self.unpacked_dir), + elem.sourceline, + tag, + ) + elif scope == "file": + key = (tag, attr_name) + if key not in file_ids: + file_ids[key] = {} + + if id_value in file_ids[key]: + prev_line = file_ids[key][id_value] + errors.append( + f" {xml_file.relative_to(self.unpacked_dir)}: " + f"Line {elem.sourceline}: Duplicate {attr_name}='{id_value}' in <{tag}> " + f"(first occurrence at line {prev_line})" + ) + else: + file_ids[key][id_value] = elem.sourceline + + except (lxml.etree.XMLSyntaxError, Exception) as e: + errors.append( + f" {xml_file.relative_to(self.unpacked_dir)}: Error: {e}" + ) + + if errors: + print(f"FAILED - Found {len(errors)} ID uniqueness violations:") + for error in errors: + print(error) + return False + else: + if self.verbose: + print("PASSED - All required IDs are unique") + return True + + def validate_file_references(self): + errors = [] + + rels_files = list(self.unpacked_dir.rglob("*.rels")) + + if not rels_files: + if self.verbose: + print("PASSED - No .rels files found") + return True + + all_files = [] + for file_path in self.unpacked_dir.rglob("*"): + if ( + file_path.is_file() + and file_path.name != "[Content_Types].xml" + and not file_path.name.endswith(".rels") + ): + all_files.append(file_path.resolve()) + + all_referenced_files = set() + + if self.verbose: + print( + f"Found {len(rels_files)} .rels files and {len(all_files)} target files" + ) + + for rels_file in rels_files: + try: + rels_root = lxml.etree.parse(str(rels_file)).getroot() + + rels_dir = rels_file.parent + + referenced_files = set() + broken_refs = [] + + for rel in rels_root.findall( + ".//ns:Relationship", + namespaces={"ns": self.PACKAGE_RELATIONSHIPS_NAMESPACE}, + ): + target = rel.get("Target") + if target and not target.startswith( + ("http", "mailto:") + ): + if target.startswith("/"): + target_path = self.unpacked_dir / target.lstrip("/") + elif rels_file.name == ".rels": + target_path = self.unpacked_dir / target + else: + base_dir = rels_dir.parent + target_path = base_dir / target + + try: + target_path = target_path.resolve() + if target_path.exists() and target_path.is_file(): + referenced_files.add(target_path) + all_referenced_files.add(target_path) + else: + broken_refs.append((target, rel.sourceline)) + except (OSError, ValueError): + broken_refs.append((target, rel.sourceline)) + + if broken_refs: + rel_path = rels_file.relative_to(self.unpacked_dir) + for broken_ref, line_num in broken_refs: + errors.append( + f" {rel_path}: Line {line_num}: Broken reference to {broken_ref}" + ) + + except Exception as e: + rel_path = rels_file.relative_to(self.unpacked_dir) + errors.append(f" Error parsing {rel_path}: {e}") + + unreferenced_files = set(all_files) - all_referenced_files + + if unreferenced_files: + for unref_file in sorted(unreferenced_files): + unref_rel_path = unref_file.relative_to(self.unpacked_dir) + errors.append(f" Unreferenced file: {unref_rel_path}") + + if errors: + print(f"FAILED - Found {len(errors)} relationship validation errors:") + for error in errors: + print(error) + print( + "CRITICAL: These errors will cause the document to appear corrupt. " + + "Broken references MUST be fixed, " + + "and unreferenced files MUST be referenced or removed." + ) + return False + else: + if self.verbose: + print( + "PASSED - All references are valid and all files are properly referenced" + ) + return True + + def validate_all_relationship_ids(self): + import lxml.etree + + errors = [] + + for xml_file in self.xml_files: + if xml_file.suffix == ".rels": + continue + + rels_dir = xml_file.parent / "_rels" + rels_file = rels_dir / f"{xml_file.name}.rels" + + if not rels_file.exists(): + continue + + try: + rels_root = lxml.etree.parse(str(rels_file)).getroot() + rid_to_type = {} + + for rel in rels_root.findall( + f".//{{{self.PACKAGE_RELATIONSHIPS_NAMESPACE}}}Relationship" + ): + rid = rel.get("Id") + rel_type = rel.get("Type", "") + if rid: + if rid in rid_to_type: + rels_rel_path = rels_file.relative_to(self.unpacked_dir) + errors.append( + f" {rels_rel_path}: Line {rel.sourceline}: " + f"Duplicate relationship ID '{rid}' (IDs must be unique)" + ) + type_name = ( + rel_type.split("/")[-1] if "/" in rel_type else rel_type + ) + rid_to_type[rid] = type_name + + xml_root = lxml.etree.parse(str(xml_file)).getroot() + + r_ns = self.OFFICE_RELATIONSHIPS_NAMESPACE + rid_attrs_to_check = ["id", "embed", "link"] + for elem in xml_root.iter(): + for attr_name in rid_attrs_to_check: + rid_attr = elem.get(f"{{{r_ns}}}{attr_name}") + if not rid_attr: + continue + xml_rel_path = xml_file.relative_to(self.unpacked_dir) + elem_name = ( + elem.tag.split("}")[-1] if "}" in elem.tag else elem.tag + ) + + if rid_attr not in rid_to_type: + errors.append( + f" {xml_rel_path}: Line {elem.sourceline}: " + f"<{elem_name}> r:{attr_name} references non-existent relationship '{rid_attr}' " + f"(valid IDs: {', '.join(sorted(rid_to_type.keys())[:5])}{'...' if len(rid_to_type) > 5 else ''})" + ) + elif attr_name == "id" and self.ELEMENT_RELATIONSHIP_TYPES: + expected_type = self._get_expected_relationship_type( + elem_name + ) + if expected_type: + actual_type = rid_to_type[rid_attr] + if expected_type not in actual_type.lower(): + errors.append( + f" {xml_rel_path}: Line {elem.sourceline}: " + f"<{elem_name}> references '{rid_attr}' which points to '{actual_type}' " + f"but should point to a '{expected_type}' relationship" + ) + + except Exception as e: + xml_rel_path = xml_file.relative_to(self.unpacked_dir) + errors.append(f" Error processing {xml_rel_path}: {e}") + + if errors: + print(f"FAILED - Found {len(errors)} relationship ID reference errors:") + for error in errors: + print(error) + print("\nThese ID mismatches will cause the document to appear corrupt!") + return False + else: + if self.verbose: + print("PASSED - All relationship ID references are valid") + return True + + def _get_expected_relationship_type(self, element_name): + elem_lower = element_name.lower() + + if elem_lower in self.ELEMENT_RELATIONSHIP_TYPES: + return self.ELEMENT_RELATIONSHIP_TYPES[elem_lower] + + if elem_lower.endswith("id") and len(elem_lower) > 2: + prefix = elem_lower[:-2] + if prefix.endswith("master"): + return prefix.lower() + elif prefix.endswith("layout"): + return prefix.lower() + else: + if prefix == "sld": + return "slide" + return prefix.lower() + + if elem_lower.endswith("reference") and len(elem_lower) > 9: + prefix = elem_lower[:-9] + return prefix.lower() + + return None + + def validate_content_types(self): + errors = [] + + content_types_file = self.unpacked_dir / "[Content_Types].xml" + if not content_types_file.exists(): + print("FAILED - [Content_Types].xml file not found") + return False + + try: + root = lxml.etree.parse(str(content_types_file)).getroot() + declared_parts = set() + declared_extensions = set() + + for override in root.findall( + f".//{{{self.CONTENT_TYPES_NAMESPACE}}}Override" + ): + part_name = override.get("PartName") + if part_name is not None: + declared_parts.add(part_name.lstrip("/")) + + for default in root.findall( + f".//{{{self.CONTENT_TYPES_NAMESPACE}}}Default" + ): + extension = default.get("Extension") + if extension is not None: + declared_extensions.add(extension.lower()) + + declarable_roots = { + "sld", + "sldLayout", + "sldMaster", + "presentation", + "document", + "workbook", + "worksheet", + "theme", + } + + media_extensions = { + "png": "image/png", + "jpg": "image/jpeg", + "jpeg": "image/jpeg", + "gif": "image/gif", + "bmp": "image/bmp", + "tiff": "image/tiff", + "wmf": "image/x-wmf", + "emf": "image/x-emf", + } + + all_files = list(self.unpacked_dir.rglob("*")) + all_files = [f for f in all_files if f.is_file()] + + for xml_file in self.xml_files: + path_str = str(xml_file.relative_to(self.unpacked_dir)).replace( + "\\", "/" + ) + + if any( + skip in path_str + for skip in [".rels", "[Content_Types]", "docProps/", "_rels/"] + ): + continue + + try: + root_tag = lxml.etree.parse(str(xml_file)).getroot().tag + root_name = root_tag.split("}")[-1] if "}" in root_tag else root_tag + + if root_name in declarable_roots and path_str not in declared_parts: + errors.append( + f" {path_str}: File with <{root_name}> root not declared in [Content_Types].xml" + ) + + except Exception: + continue + + for file_path in all_files: + if file_path.suffix.lower() in {".xml", ".rels"}: + continue + if file_path.name == "[Content_Types].xml": + continue + if "_rels" in file_path.parts or "docProps" in file_path.parts: + continue + + extension = file_path.suffix.lstrip(".").lower() + if extension and extension not in declared_extensions: + if extension in media_extensions: + relative_path = file_path.relative_to(self.unpacked_dir) + errors.append( + f' {relative_path}: File with extension \'{extension}\' not declared in [Content_Types].xml - should add: ' + ) + + except Exception as e: + errors.append(f" Error parsing [Content_Types].xml: {e}") + + if errors: + print(f"FAILED - Found {len(errors)} content type declaration errors:") + for error in errors: + print(error) + return False + else: + if self.verbose: + print( + "PASSED - All content files are properly declared in [Content_Types].xml" + ) + return True + + def validate_file_against_xsd(self, xml_file, verbose=False): + xml_file = Path(xml_file).resolve() + unpacked_dir = self.unpacked_dir.resolve() + + is_valid, current_errors = self._validate_single_file_xsd( + xml_file, unpacked_dir + ) + + if is_valid is None: + return None, set() + elif is_valid: + return True, set() + + original_errors = self._get_original_file_errors(xml_file) + + assert current_errors is not None + new_errors = current_errors - original_errors + + new_errors = { + e for e in new_errors + if not any(pattern in e for pattern in self.IGNORED_VALIDATION_ERRORS) + } + + if new_errors: + if verbose: + relative_path = xml_file.relative_to(unpacked_dir) + print(f"FAILED - {relative_path}: {len(new_errors)} new error(s)") + for error in list(new_errors)[:3]: + truncated = error[:250] + "..." if len(error) > 250 else error + print(f" - {truncated}") + return False, new_errors + else: + if verbose: + print( + f"PASSED - No new errors (original had {len(current_errors)} errors)" + ) + return True, set() + + def validate_against_xsd(self): + new_errors = [] + original_error_count = 0 + valid_count = 0 + skipped_count = 0 + + for xml_file in self.xml_files: + relative_path = str(xml_file.relative_to(self.unpacked_dir)) + is_valid, new_file_errors = self.validate_file_against_xsd( + xml_file, verbose=False + ) + + if is_valid is None: + skipped_count += 1 + continue + elif is_valid and not new_file_errors: + valid_count += 1 + continue + elif is_valid: + original_error_count += 1 + valid_count += 1 + continue + + new_errors.append(f" {relative_path}: {len(new_file_errors)} new error(s)") + for error in list(new_file_errors)[:3]: + new_errors.append( + f" - {error[:250]}..." if len(error) > 250 else f" - {error}" + ) + + if self.verbose: + print(f"Validated {len(self.xml_files)} files:") + print(f" - Valid: {valid_count}") + print(f" - Skipped (no schema): {skipped_count}") + if original_error_count: + print(f" - With original errors (ignored): {original_error_count}") + print( + f" - With NEW errors: {len(new_errors) > 0 and len([e for e in new_errors if not e.startswith(' ')]) or 0}" + ) + + if new_errors: + print("\nFAILED - Found NEW validation errors:") + for error in new_errors: + print(error) + return False + else: + if self.verbose: + print("\nPASSED - No new XSD validation errors introduced") + return True + + def _get_schema_path(self, xml_file): + if xml_file.name in self.SCHEMA_MAPPINGS: + return self.schemas_dir / self.SCHEMA_MAPPINGS[xml_file.name] + + if xml_file.suffix == ".rels": + return self.schemas_dir / self.SCHEMA_MAPPINGS[".rels"] + + if "charts/" in str(xml_file) and xml_file.name.startswith("chart"): + return self.schemas_dir / self.SCHEMA_MAPPINGS["chart"] + + if "theme/" in str(xml_file) and xml_file.name.startswith("theme"): + return self.schemas_dir / self.SCHEMA_MAPPINGS["theme"] + + if xml_file.parent.name in self.MAIN_CONTENT_FOLDERS: + return self.schemas_dir / self.SCHEMA_MAPPINGS[xml_file.parent.name] + + return None + + def _clean_ignorable_namespaces(self, xml_doc): + xml_string = lxml.etree.tostring(xml_doc, encoding="unicode") + xml_copy = lxml.etree.fromstring(xml_string) + + for elem in xml_copy.iter(): + attrs_to_remove = [] + + for attr in elem.attrib: + if "{" in attr: + ns = attr.split("}")[0][1:] + if ns not in self.OOXML_NAMESPACES: + attrs_to_remove.append(attr) + + for attr in attrs_to_remove: + del elem.attrib[attr] + + self._remove_ignorable_elements(xml_copy) + + return lxml.etree.ElementTree(xml_copy) + + def _remove_ignorable_elements(self, root): + elements_to_remove = [] + + for elem in list(root): + if not hasattr(elem, "tag") or callable(elem.tag): + continue + + tag_str = str(elem.tag) + if tag_str.startswith("{"): + ns = tag_str.split("}")[0][1:] + if ns not in self.OOXML_NAMESPACES: + elements_to_remove.append(elem) + continue + + self._remove_ignorable_elements(elem) + + for elem in elements_to_remove: + root.remove(elem) + + def _preprocess_for_mc_ignorable(self, xml_doc): + root = xml_doc.getroot() + + if f"{{{self.MC_NAMESPACE}}}Ignorable" in root.attrib: + del root.attrib[f"{{{self.MC_NAMESPACE}}}Ignorable"] + + return xml_doc + + def _validate_single_file_xsd(self, xml_file, base_path): + schema_path = self._get_schema_path(xml_file) + if not schema_path: + return None, None + + try: + with open(schema_path, "rb") as xsd_file: + parser = lxml.etree.XMLParser() + xsd_doc = lxml.etree.parse( + xsd_file, parser=parser, base_url=str(schema_path) + ) + schema = lxml.etree.XMLSchema(xsd_doc) + + with open(xml_file, "r") as f: + xml_doc = lxml.etree.parse(f) + + xml_doc, _ = self._remove_template_tags_from_text_nodes(xml_doc) + xml_doc = self._preprocess_for_mc_ignorable(xml_doc) + + relative_path = xml_file.relative_to(base_path) + if ( + relative_path.parts + and relative_path.parts[0] in self.MAIN_CONTENT_FOLDERS + ): + xml_doc = self._clean_ignorable_namespaces(xml_doc) + + if schema.validate(xml_doc): + return True, set() + else: + errors = set() + for error in schema.error_log: + errors.add(error.message) + return False, errors + + except Exception as e: + return False, {str(e)} + + def _get_original_file_errors(self, xml_file): + if self.original_file is None: + return set() + + import tempfile + import zipfile + + xml_file = Path(xml_file).resolve() + unpacked_dir = self.unpacked_dir.resolve() + relative_path = xml_file.relative_to(unpacked_dir) + + with tempfile.TemporaryDirectory() as temp_dir: + temp_path = Path(temp_dir) + + with zipfile.ZipFile(self.original_file, "r") as zip_ref: + zip_ref.extractall(temp_path) + + original_xml_file = temp_path / relative_path + + if not original_xml_file.exists(): + return set() + + is_valid, errors = self._validate_single_file_xsd( + original_xml_file, temp_path + ) + return errors if errors else set() + + def _remove_template_tags_from_text_nodes(self, xml_doc): + warnings = [] + template_pattern = re.compile(r"\{\{[^}]*\}\}") + + xml_string = lxml.etree.tostring(xml_doc, encoding="unicode") + xml_copy = lxml.etree.fromstring(xml_string) + + def process_text_content(text, content_type): + if not text: + return text + matches = list(template_pattern.finditer(text)) + if matches: + for match in matches: + warnings.append( + f"Found template tag in {content_type}: {match.group()}" + ) + return template_pattern.sub("", text) + return text + + for elem in xml_copy.iter(): + if not hasattr(elem, "tag") or callable(elem.tag): + continue + tag_str = str(elem.tag) + if tag_str.endswith("}t") or tag_str == "t": + continue + + elem.text = process_text_content(elem.text, "text content") + elem.tail = process_text_content(elem.tail, "tail content") + + return lxml.etree.ElementTree(xml_copy), warnings + + +if __name__ == "__main__": + raise RuntimeError("This module should not be run directly.") diff --git a/dev-tools/skills/docx/scripts/office/validators/docx.py b/dev-tools/skills/docx/scripts/office/validators/docx.py new file mode 100644 index 0000000..fec405e --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/validators/docx.py @@ -0,0 +1,446 @@ +""" +Validator for Word document XML files against XSD schemas. +""" + +import random +import re +import tempfile +import zipfile + +import defusedxml.minidom +import lxml.etree + +from .base import BaseSchemaValidator + + +class DOCXSchemaValidator(BaseSchemaValidator): + + WORD_2006_NAMESPACE = "http://schemas.openxmlformats.org/wordprocessingml/2006/main" + W14_NAMESPACE = "http://schemas.microsoft.com/office/word/2010/wordml" + W16CID_NAMESPACE = "http://schemas.microsoft.com/office/word/2016/wordml/cid" + + ELEMENT_RELATIONSHIP_TYPES = {} + + def validate(self): + if not self.validate_xml(): + return False + + all_valid = True + if not self.validate_namespaces(): + all_valid = False + + if not self.validate_unique_ids(): + all_valid = False + + if not self.validate_file_references(): + all_valid = False + + if not self.validate_content_types(): + all_valid = False + + if not self.validate_against_xsd(): + all_valid = False + + if not self.validate_whitespace_preservation(): + all_valid = False + + if not self.validate_deletions(): + all_valid = False + + if not self.validate_insertions(): + all_valid = False + + if not self.validate_all_relationship_ids(): + all_valid = False + + if not self.validate_id_constraints(): + all_valid = False + + if not self.validate_comment_markers(): + all_valid = False + + self.compare_paragraph_counts() + + return all_valid + + def validate_whitespace_preservation(self): + errors = [] + + for xml_file in self.xml_files: + if xml_file.name != "document.xml": + continue + + try: + root = lxml.etree.parse(str(xml_file)).getroot() + + for elem in root.iter(f"{{{self.WORD_2006_NAMESPACE}}}t"): + if elem.text: + text = elem.text + if re.search(r"^[ \t\n\r]", text) or re.search( + r"[ \t\n\r]$", text + ): + xml_space_attr = f"{{{self.XML_NAMESPACE}}}space" + if ( + xml_space_attr not in elem.attrib + or elem.attrib[xml_space_attr] != "preserve" + ): + text_preview = ( + repr(text)[:50] + "..." + if len(repr(text)) > 50 + else repr(text) + ) + errors.append( + f" {xml_file.relative_to(self.unpacked_dir)}: " + f"Line {elem.sourceline}: w:t element with whitespace missing xml:space='preserve': {text_preview}" + ) + + except (lxml.etree.XMLSyntaxError, Exception) as e: + errors.append( + f" {xml_file.relative_to(self.unpacked_dir)}: Error: {e}" + ) + + if errors: + print(f"FAILED - Found {len(errors)} whitespace preservation violations:") + for error in errors: + print(error) + return False + else: + if self.verbose: + print("PASSED - All whitespace is properly preserved") + return True + + def validate_deletions(self): + errors = [] + + for xml_file in self.xml_files: + if xml_file.name != "document.xml": + continue + + try: + root = lxml.etree.parse(str(xml_file)).getroot() + namespaces = {"w": self.WORD_2006_NAMESPACE} + + for t_elem in root.xpath(".//w:del//w:t", namespaces=namespaces): + if t_elem.text: + text_preview = ( + repr(t_elem.text)[:50] + "..." + if len(repr(t_elem.text)) > 50 + else repr(t_elem.text) + ) + errors.append( + f" {xml_file.relative_to(self.unpacked_dir)}: " + f"Line {t_elem.sourceline}: found within : {text_preview}" + ) + + for instr_elem in root.xpath( + ".//w:del//w:instrText", namespaces=namespaces + ): + text_preview = ( + repr(instr_elem.text or "")[:50] + "..." + if len(repr(instr_elem.text or "")) > 50 + else repr(instr_elem.text or "") + ) + errors.append( + f" {xml_file.relative_to(self.unpacked_dir)}: " + f"Line {instr_elem.sourceline}: found within (use ): {text_preview}" + ) + + except (lxml.etree.XMLSyntaxError, Exception) as e: + errors.append( + f" {xml_file.relative_to(self.unpacked_dir)}: Error: {e}" + ) + + if errors: + print(f"FAILED - Found {len(errors)} deletion validation violations:") + for error in errors: + print(error) + return False + else: + if self.verbose: + print("PASSED - No w:t elements found within w:del elements") + return True + + def count_paragraphs_in_unpacked(self): + count = 0 + + for xml_file in self.xml_files: + if xml_file.name != "document.xml": + continue + + try: + root = lxml.etree.parse(str(xml_file)).getroot() + paragraphs = root.findall(f".//{{{self.WORD_2006_NAMESPACE}}}p") + count = len(paragraphs) + except Exception as e: + print(f"Error counting paragraphs in unpacked document: {e}") + + return count + + def count_paragraphs_in_original(self): + original = self.original_file + if original is None: + return 0 + + count = 0 + + try: + with tempfile.TemporaryDirectory() as temp_dir: + with zipfile.ZipFile(original, "r") as zip_ref: + zip_ref.extractall(temp_dir) + + doc_xml_path = temp_dir + "/word/document.xml" + root = lxml.etree.parse(doc_xml_path).getroot() + + paragraphs = root.findall(f".//{{{self.WORD_2006_NAMESPACE}}}p") + count = len(paragraphs) + + except Exception as e: + print(f"Error counting paragraphs in original document: {e}") + + return count + + def validate_insertions(self): + errors = [] + + for xml_file in self.xml_files: + if xml_file.name != "document.xml": + continue + + try: + root = lxml.etree.parse(str(xml_file)).getroot() + namespaces = {"w": self.WORD_2006_NAMESPACE} + + invalid_elements = root.xpath( + ".//w:ins//w:delText[not(ancestor::w:del)]", namespaces=namespaces + ) + + for elem in invalid_elements: + text_preview = ( + repr(elem.text or "")[:50] + "..." + if len(repr(elem.text or "")) > 50 + else repr(elem.text or "") + ) + errors.append( + f" {xml_file.relative_to(self.unpacked_dir)}: " + f"Line {elem.sourceline}: within : {text_preview}" + ) + + except (lxml.etree.XMLSyntaxError, Exception) as e: + errors.append( + f" {xml_file.relative_to(self.unpacked_dir)}: Error: {e}" + ) + + if errors: + print(f"FAILED - Found {len(errors)} insertion validation violations:") + for error in errors: + print(error) + return False + else: + if self.verbose: + print("PASSED - No w:delText elements within w:ins elements") + return True + + def compare_paragraph_counts(self): + original_count = self.count_paragraphs_in_original() + new_count = self.count_paragraphs_in_unpacked() + + diff = new_count - original_count + diff_str = f"+{diff}" if diff > 0 else str(diff) + print(f"\nParagraphs: {original_count} → {new_count} ({diff_str})") + + def _parse_id_value(self, val: str, base: int = 16) -> int: + return int(val, base) + + def validate_id_constraints(self): + errors = [] + para_id_attr = f"{{{self.W14_NAMESPACE}}}paraId" + durable_id_attr = f"{{{self.W16CID_NAMESPACE}}}durableId" + + for xml_file in self.xml_files: + try: + for elem in lxml.etree.parse(str(xml_file)).iter(): + if val := elem.get(para_id_attr): + if self._parse_id_value(val, base=16) >= 0x80000000: + errors.append( + f" {xml_file.name}:{elem.sourceline}: paraId={val} >= 0x80000000" + ) + + if val := elem.get(durable_id_attr): + if xml_file.name == "numbering.xml": + try: + if self._parse_id_value(val, base=10) >= 0x7FFFFFFF: + errors.append( + f" {xml_file.name}:{elem.sourceline}: " + f"durableId={val} >= 0x7FFFFFFF" + ) + except ValueError: + errors.append( + f" {xml_file.name}:{elem.sourceline}: " + f"durableId={val} must be decimal in numbering.xml" + ) + else: + if self._parse_id_value(val, base=16) >= 0x7FFFFFFF: + errors.append( + f" {xml_file.name}:{elem.sourceline}: " + f"durableId={val} >= 0x7FFFFFFF" + ) + except Exception: + pass + + if errors: + print(f"FAILED - {len(errors)} ID constraint violations:") + for e in errors: + print(e) + elif self.verbose: + print("PASSED - All paraId/durableId values within constraints") + return not errors + + def validate_comment_markers(self): + errors = [] + + document_xml = None + comments_xml = None + for xml_file in self.xml_files: + if xml_file.name == "document.xml" and "word" in str(xml_file): + document_xml = xml_file + elif xml_file.name == "comments.xml": + comments_xml = xml_file + + if not document_xml: + if self.verbose: + print("PASSED - No document.xml found (skipping comment validation)") + return True + + try: + doc_root = lxml.etree.parse(str(document_xml)).getroot() + namespaces = {"w": self.WORD_2006_NAMESPACE} + + range_starts = { + elem.get(f"{{{self.WORD_2006_NAMESPACE}}}id") + for elem in doc_root.xpath( + ".//w:commentRangeStart", namespaces=namespaces + ) + } + range_ends = { + elem.get(f"{{{self.WORD_2006_NAMESPACE}}}id") + for elem in doc_root.xpath( + ".//w:commentRangeEnd", namespaces=namespaces + ) + } + references = { + elem.get(f"{{{self.WORD_2006_NAMESPACE}}}id") + for elem in doc_root.xpath( + ".//w:commentReference", namespaces=namespaces + ) + } + + orphaned_ends = range_ends - range_starts + for comment_id in sorted( + orphaned_ends, key=lambda x: int(x) if x and x.isdigit() else 0 + ): + errors.append( + f' document.xml: commentRangeEnd id="{comment_id}" has no matching commentRangeStart' + ) + + orphaned_starts = range_starts - range_ends + for comment_id in sorted( + orphaned_starts, key=lambda x: int(x) if x and x.isdigit() else 0 + ): + errors.append( + f' document.xml: commentRangeStart id="{comment_id}" has no matching commentRangeEnd' + ) + + comment_ids = set() + if comments_xml and comments_xml.exists(): + comments_root = lxml.etree.parse(str(comments_xml)).getroot() + comment_ids = { + elem.get(f"{{{self.WORD_2006_NAMESPACE}}}id") + for elem in comments_root.xpath( + ".//w:comment", namespaces=namespaces + ) + } + + marker_ids = range_starts | range_ends | references + invalid_refs = marker_ids - comment_ids + for comment_id in sorted( + invalid_refs, key=lambda x: int(x) if x and x.isdigit() else 0 + ): + if comment_id: + errors.append( + f' document.xml: marker id="{comment_id}" references non-existent comment' + ) + + except (lxml.etree.XMLSyntaxError, Exception) as e: + errors.append(f" Error parsing XML: {e}") + + if errors: + print(f"FAILED - {len(errors)} comment marker violations:") + for error in errors: + print(error) + return False + else: + if self.verbose: + print("PASSED - All comment markers properly paired") + return True + + def repair(self) -> int: + repairs = super().repair() + repairs += self.repair_durableId() + return repairs + + def repair_durableId(self) -> int: + repairs = 0 + + for xml_file in self.xml_files: + try: + content = xml_file.read_text(encoding="utf-8") + dom = defusedxml.minidom.parseString(content) + modified = False + + for elem in dom.getElementsByTagName("*"): + if not elem.hasAttribute("w16cid:durableId"): + continue + + durable_id = elem.getAttribute("w16cid:durableId") + needs_repair = False + + if xml_file.name == "numbering.xml": + try: + needs_repair = ( + self._parse_id_value(durable_id, base=10) >= 0x7FFFFFFF + ) + except ValueError: + needs_repair = True + else: + try: + needs_repair = ( + self._parse_id_value(durable_id, base=16) >= 0x7FFFFFFF + ) + except ValueError: + needs_repair = True + + if needs_repair: + value = random.randint(1, 0x7FFFFFFE) + if xml_file.name == "numbering.xml": + new_id = str(value) + else: + new_id = f"{value:08X}" + + elem.setAttribute("w16cid:durableId", new_id) + print( + f" Repaired: {xml_file.name}: durableId {durable_id} → {new_id}" + ) + repairs += 1 + modified = True + + if modified: + xml_file.write_bytes(dom.toxml(encoding="UTF-8")) + + except Exception: + pass + + return repairs + + +if __name__ == "__main__": + raise RuntimeError("This module should not be run directly.") diff --git a/dev-tools/skills/docx/scripts/office/validators/pptx.py b/dev-tools/skills/docx/scripts/office/validators/pptx.py new file mode 100644 index 0000000..09842aa --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/validators/pptx.py @@ -0,0 +1,275 @@ +""" +Validator for PowerPoint presentation XML files against XSD schemas. +""" + +import re + +from .base import BaseSchemaValidator + + +class PPTXSchemaValidator(BaseSchemaValidator): + + PRESENTATIONML_NAMESPACE = ( + "http://schemas.openxmlformats.org/presentationml/2006/main" + ) + + ELEMENT_RELATIONSHIP_TYPES = { + "sldid": "slide", + "sldmasterid": "slidemaster", + "notesmasterid": "notesmaster", + "sldlayoutid": "slidelayout", + "themeid": "theme", + "tablestyleid": "tablestyles", + } + + def validate(self): + if not self.validate_xml(): + return False + + all_valid = True + if not self.validate_namespaces(): + all_valid = False + + if not self.validate_unique_ids(): + all_valid = False + + if not self.validate_uuid_ids(): + all_valid = False + + if not self.validate_file_references(): + all_valid = False + + if not self.validate_slide_layout_ids(): + all_valid = False + + if not self.validate_content_types(): + all_valid = False + + if not self.validate_against_xsd(): + all_valid = False + + if not self.validate_notes_slide_references(): + all_valid = False + + if not self.validate_all_relationship_ids(): + all_valid = False + + if not self.validate_no_duplicate_slide_layouts(): + all_valid = False + + return all_valid + + def validate_uuid_ids(self): + import lxml.etree + + errors = [] + uuid_pattern = re.compile( + r"^[\{\(]?[0-9A-Fa-f]{8}-?[0-9A-Fa-f]{4}-?[0-9A-Fa-f]{4}-?[0-9A-Fa-f]{4}-?[0-9A-Fa-f]{12}[\}\)]?$" + ) + + for xml_file in self.xml_files: + try: + root = lxml.etree.parse(str(xml_file)).getroot() + + for elem in root.iter(): + for attr, value in elem.attrib.items(): + attr_name = attr.split("}")[-1].lower() + if attr_name == "id" or attr_name.endswith("id"): + if self._looks_like_uuid(value): + if not uuid_pattern.match(value): + errors.append( + f" {xml_file.relative_to(self.unpacked_dir)}: " + f"Line {elem.sourceline}: ID '{value}' appears to be a UUID but contains invalid hex characters" + ) + + except (lxml.etree.XMLSyntaxError, Exception) as e: + errors.append( + f" {xml_file.relative_to(self.unpacked_dir)}: Error: {e}" + ) + + if errors: + print(f"FAILED - Found {len(errors)} UUID ID validation errors:") + for error in errors: + print(error) + return False + else: + if self.verbose: + print("PASSED - All UUID-like IDs contain valid hex values") + return True + + def _looks_like_uuid(self, value): + clean_value = value.strip("{}()").replace("-", "") + return len(clean_value) == 32 and all(c.isalnum() for c in clean_value) + + def validate_slide_layout_ids(self): + import lxml.etree + + errors = [] + + slide_masters = list(self.unpacked_dir.glob("ppt/slideMasters/*.xml")) + + if not slide_masters: + if self.verbose: + print("PASSED - No slide masters found") + return True + + for slide_master in slide_masters: + try: + root = lxml.etree.parse(str(slide_master)).getroot() + + rels_file = slide_master.parent / "_rels" / f"{slide_master.name}.rels" + + if not rels_file.exists(): + errors.append( + f" {slide_master.relative_to(self.unpacked_dir)}: " + f"Missing relationships file: {rels_file.relative_to(self.unpacked_dir)}" + ) + continue + + rels_root = lxml.etree.parse(str(rels_file)).getroot() + + valid_layout_rids = set() + for rel in rels_root.findall( + f".//{{{self.PACKAGE_RELATIONSHIPS_NAMESPACE}}}Relationship" + ): + rel_type = rel.get("Type", "") + if "slideLayout" in rel_type: + valid_layout_rids.add(rel.get("Id")) + + for sld_layout_id in root.findall( + f".//{{{self.PRESENTATIONML_NAMESPACE}}}sldLayoutId" + ): + r_id = sld_layout_id.get( + f"{{{self.OFFICE_RELATIONSHIPS_NAMESPACE}}}id" + ) + layout_id = sld_layout_id.get("id") + + if r_id and r_id not in valid_layout_rids: + errors.append( + f" {slide_master.relative_to(self.unpacked_dir)}: " + f"Line {sld_layout_id.sourceline}: sldLayoutId with id='{layout_id}' " + f"references r:id='{r_id}' which is not found in slide layout relationships" + ) + + except (lxml.etree.XMLSyntaxError, Exception) as e: + errors.append( + f" {slide_master.relative_to(self.unpacked_dir)}: Error: {e}" + ) + + if errors: + print(f"FAILED - Found {len(errors)} slide layout ID validation errors:") + for error in errors: + print(error) + print( + "Remove invalid references or add missing slide layouts to the relationships file." + ) + return False + else: + if self.verbose: + print("PASSED - All slide layout IDs reference valid slide layouts") + return True + + def validate_no_duplicate_slide_layouts(self): + import lxml.etree + + errors = [] + slide_rels_files = list(self.unpacked_dir.glob("ppt/slides/_rels/*.xml.rels")) + + for rels_file in slide_rels_files: + try: + root = lxml.etree.parse(str(rels_file)).getroot() + + layout_rels = [ + rel + for rel in root.findall( + f".//{{{self.PACKAGE_RELATIONSHIPS_NAMESPACE}}}Relationship" + ) + if "slideLayout" in rel.get("Type", "") + ] + + if len(layout_rels) > 1: + errors.append( + f" {rels_file.relative_to(self.unpacked_dir)}: has {len(layout_rels)} slideLayout references" + ) + + except Exception as e: + errors.append( + f" {rels_file.relative_to(self.unpacked_dir)}: Error: {e}" + ) + + if errors: + print("FAILED - Found slides with duplicate slideLayout references:") + for error in errors: + print(error) + return False + else: + if self.verbose: + print("PASSED - All slides have exactly one slideLayout reference") + return True + + def validate_notes_slide_references(self): + import lxml.etree + + errors = [] + notes_slide_references = {} + + slide_rels_files = list(self.unpacked_dir.glob("ppt/slides/_rels/*.xml.rels")) + + if not slide_rels_files: + if self.verbose: + print("PASSED - No slide relationship files found") + return True + + for rels_file in slide_rels_files: + try: + root = lxml.etree.parse(str(rels_file)).getroot() + + for rel in root.findall( + f".//{{{self.PACKAGE_RELATIONSHIPS_NAMESPACE}}}Relationship" + ): + rel_type = rel.get("Type", "") + if "notesSlide" in rel_type: + target = rel.get("Target", "") + if target: + normalized_target = target.replace("../", "") + + slide_name = rels_file.stem.replace( + ".xml", "" + ) + + if normalized_target not in notes_slide_references: + notes_slide_references[normalized_target] = [] + notes_slide_references[normalized_target].append( + (slide_name, rels_file) + ) + + except (lxml.etree.XMLSyntaxError, Exception) as e: + errors.append( + f" {rels_file.relative_to(self.unpacked_dir)}: Error: {e}" + ) + + for target, references in notes_slide_references.items(): + if len(references) > 1: + slide_names = [ref[0] for ref in references] + errors.append( + f" Notes slide '{target}' is referenced by multiple slides: {', '.join(slide_names)}" + ) + for slide_name, rels_file in references: + errors.append(f" - {rels_file.relative_to(self.unpacked_dir)}") + + if errors: + print( + f"FAILED - Found {len([e for e in errors if not e.startswith(' ')])} notes slide reference validation errors:" + ) + for error in errors: + print(error) + print("Each slide may optionally have its own slide file.") + return False + else: + if self.verbose: + print("PASSED - All notes slide references are unique") + return True + + +if __name__ == "__main__": + raise RuntimeError("This module should not be run directly.") diff --git a/dev-tools/skills/docx/scripts/office/validators/redlining.py b/dev-tools/skills/docx/scripts/office/validators/redlining.py new file mode 100644 index 0000000..71c81b6 --- /dev/null +++ b/dev-tools/skills/docx/scripts/office/validators/redlining.py @@ -0,0 +1,247 @@ +""" +Validator for tracked changes in Word documents. +""" + +import subprocess +import tempfile +import zipfile +from pathlib import Path + + +class RedliningValidator: + + def __init__(self, unpacked_dir, original_docx, verbose=False, author="Claude"): + self.unpacked_dir = Path(unpacked_dir) + self.original_docx = Path(original_docx) + self.verbose = verbose + self.author = author + self.namespaces = { + "w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main" + } + + def repair(self) -> int: + return 0 + + def validate(self): + modified_file = self.unpacked_dir / "word" / "document.xml" + if not modified_file.exists(): + print(f"FAILED - Modified document.xml not found at {modified_file}") + return False + + try: + import xml.etree.ElementTree as ET + + tree = ET.parse(modified_file) + root = tree.getroot() + + del_elements = root.findall(".//w:del", self.namespaces) + ins_elements = root.findall(".//w:ins", self.namespaces) + + author_del_elements = [ + elem + for elem in del_elements + if elem.get(f"{{{self.namespaces['w']}}}author") == self.author + ] + author_ins_elements = [ + elem + for elem in ins_elements + if elem.get(f"{{{self.namespaces['w']}}}author") == self.author + ] + + if not author_del_elements and not author_ins_elements: + if self.verbose: + print(f"PASSED - No tracked changes by {self.author} found.") + return True + + except Exception: + pass + + with tempfile.TemporaryDirectory() as temp_dir: + temp_path = Path(temp_dir) + + try: + with zipfile.ZipFile(self.original_docx, "r") as zip_ref: + zip_ref.extractall(temp_path) + except Exception as e: + print(f"FAILED - Error unpacking original docx: {e}") + return False + + original_file = temp_path / "word" / "document.xml" + if not original_file.exists(): + print( + f"FAILED - Original document.xml not found in {self.original_docx}" + ) + return False + + try: + import xml.etree.ElementTree as ET + + modified_tree = ET.parse(modified_file) + modified_root = modified_tree.getroot() + original_tree = ET.parse(original_file) + original_root = original_tree.getroot() + except ET.ParseError as e: + print(f"FAILED - Error parsing XML files: {e}") + return False + + self._remove_author_tracked_changes(original_root) + self._remove_author_tracked_changes(modified_root) + + modified_text = self._extract_text_content(modified_root) + original_text = self._extract_text_content(original_root) + + if modified_text != original_text: + error_message = self._generate_detailed_diff( + original_text, modified_text + ) + print(error_message) + return False + + if self.verbose: + print(f"PASSED - All changes by {self.author} are properly tracked") + return True + + def _generate_detailed_diff(self, original_text, modified_text): + error_parts = [ + f"FAILED - Document text doesn't match after removing {self.author}'s tracked changes", + "", + "Likely causes:", + " 1. Modified text inside another author's or tags", + " 2. Made edits without proper tracked changes", + " 3. Didn't nest inside when deleting another's insertion", + "", + "For pre-redlined documents, use correct patterns:", + " - To reject another's INSERTION: Nest inside their ", + " - To restore another's DELETION: Add new AFTER their ", + "", + ] + + git_diff = self._get_git_word_diff(original_text, modified_text) + if git_diff: + error_parts.extend(["Differences:", "============", git_diff]) + else: + error_parts.append("Unable to generate word diff (git not available)") + + return "\n".join(error_parts) + + def _get_git_word_diff(self, original_text, modified_text): + try: + with tempfile.TemporaryDirectory() as temp_dir: + temp_path = Path(temp_dir) + + original_file = temp_path / "original.txt" + modified_file = temp_path / "modified.txt" + + original_file.write_text(original_text, encoding="utf-8") + modified_file.write_text(modified_text, encoding="utf-8") + + result = subprocess.run( + [ + "git", + "diff", + "--word-diff=plain", + "--word-diff-regex=.", + "-U0", + "--no-index", + str(original_file), + str(modified_file), + ], + capture_output=True, + text=True, + ) + + if result.stdout.strip(): + lines = result.stdout.split("\n") + content_lines = [] + in_content = False + for line in lines: + if line.startswith("@@"): + in_content = True + continue + if in_content and line.strip(): + content_lines.append(line) + + if content_lines: + return "\n".join(content_lines) + + result = subprocess.run( + [ + "git", + "diff", + "--word-diff=plain", + "-U0", + "--no-index", + str(original_file), + str(modified_file), + ], + capture_output=True, + text=True, + ) + + if result.stdout.strip(): + lines = result.stdout.split("\n") + content_lines = [] + in_content = False + for line in lines: + if line.startswith("@@"): + in_content = True + continue + if in_content and line.strip(): + content_lines.append(line) + return "\n".join(content_lines) + + except (subprocess.CalledProcessError, FileNotFoundError, Exception): + pass + + return None + + def _remove_author_tracked_changes(self, root): + ins_tag = f"{{{self.namespaces['w']}}}ins" + del_tag = f"{{{self.namespaces['w']}}}del" + author_attr = f"{{{self.namespaces['w']}}}author" + + for parent in root.iter(): + to_remove = [] + for child in parent: + if child.tag == ins_tag and child.get(author_attr) == self.author: + to_remove.append(child) + for elem in to_remove: + parent.remove(elem) + + deltext_tag = f"{{{self.namespaces['w']}}}delText" + t_tag = f"{{{self.namespaces['w']}}}t" + + for parent in root.iter(): + to_process = [] + for child in parent: + if child.tag == del_tag and child.get(author_attr) == self.author: + to_process.append((child, list(parent).index(child))) + + for del_elem, del_index in reversed(to_process): + for elem in del_elem.iter(): + if elem.tag == deltext_tag: + elem.tag = t_tag + + for child in reversed(list(del_elem)): + parent.insert(del_index, child) + parent.remove(del_elem) + + def _extract_text_content(self, root): + p_tag = f"{{{self.namespaces['w']}}}p" + t_tag = f"{{{self.namespaces['w']}}}t" + + paragraphs = [] + for p_elem in root.findall(f".//{p_tag}"): + text_parts = [] + for t_elem in p_elem.findall(f".//{t_tag}"): + if t_elem.text: + text_parts.append(t_elem.text) + paragraph_text = "".join(text_parts) + if paragraph_text: + paragraphs.append(paragraph_text) + + return "\n".join(paragraphs) + + +if __name__ == "__main__": + raise RuntimeError("This module should not be run directly.") diff --git a/dev-tools/skills/docx/scripts/templates/comments.xml b/dev-tools/skills/docx/scripts/templates/comments.xml new file mode 100644 index 0000000..cd01a7d --- /dev/null +++ b/dev-tools/skills/docx/scripts/templates/comments.xml @@ -0,0 +1,3 @@ + + + diff --git a/dev-tools/skills/docx/scripts/templates/commentsExtended.xml b/dev-tools/skills/docx/scripts/templates/commentsExtended.xml new file mode 100644 index 0000000..411003c --- /dev/null +++ b/dev-tools/skills/docx/scripts/templates/commentsExtended.xml @@ -0,0 +1,3 @@ + + + diff --git a/dev-tools/skills/docx/scripts/templates/commentsExtensible.xml b/dev-tools/skills/docx/scripts/templates/commentsExtensible.xml new file mode 100644 index 0000000..f5572d7 --- /dev/null +++ b/dev-tools/skills/docx/scripts/templates/commentsExtensible.xml @@ -0,0 +1,3 @@ + + + diff --git a/dev-tools/skills/docx/scripts/templates/commentsIds.xml b/dev-tools/skills/docx/scripts/templates/commentsIds.xml new file mode 100644 index 0000000..32f1629 --- /dev/null +++ b/dev-tools/skills/docx/scripts/templates/commentsIds.xml @@ -0,0 +1,3 @@ + + + diff --git a/dev-tools/skills/docx/scripts/templates/people.xml b/dev-tools/skills/docx/scripts/templates/people.xml new file mode 100644 index 0000000..3803d2d --- /dev/null +++ b/dev-tools/skills/docx/scripts/templates/people.xml @@ -0,0 +1,3 @@ + + + diff --git a/dev-tools/skills/nextjs/SKILL.md b/dev-tools/skills/nextjs/SKILL.md index 2e60959..a754edb 100644 --- a/dev-tools/skills/nextjs/SKILL.md +++ b/dev-tools/skills/nextjs/SKILL.md @@ -1,20 +1,26 @@ --- name: nextjs -description: Next.js development best practices and patterns. App router, server components, - API routes, and deployment. Use when user mentions "nextjs", "next.js", "react server", - "app router", "next deployment". -author: Descomplicar® Crescimento Digital -version: 2.0.0 -quality_score: 75 -user_invocable: true -allowed-tools: Glob +description: Desenvolvimento Next.js moderno (13+) com App Router, Server Components, rotas API e deployment seguindo padroes Descomplicar. --- # /nextjs - Next.js Development Desenvolvimento Next.js moderno (13+) com App Router e Server Components. -## Regra #48 - Dev Container (OBRIGATORIO) +--- + +## Contexto NotebookLM + +``` +mcp__notebooklm__notebook_query({ + notebook_id: "24947ffa-0019-448a-a340-2f4a275d2eb1", + query: "" +}) +``` + +--- + +## Regra #48 - Dev Container (OBRIGATÓRIO) **TODOS os projectos Next.js devem ser desenvolvidos no container dev.** @@ -28,18 +34,12 @@ Sync: auto -> /media/ealmeida/Dados/Dev/ (Syncthing) 1. `mcp__ssh-unified__ssh_execute server:"dev" command:"mkdir -p /root/Dev/"` 2. Desenvolver e testar no container 3. `npm run build` no container antes de deploy -4. Deploy via EasyPanel a partir do container -5. Syncthing propaga automaticamente para PC local e colegas +4. Deploy via EasyPanel +5. Syncthing propaga automaticamente **NUNCA:** `npx create-next-app` directamente no PC local para projectos colaborativos. -## Quando Usar - -- Criar aplicações Next.js -- Migrar de Pages para App Router -- Implementar Server Components -- Configurar Server Actions -- Optimizar SEO e performance +--- ## App Router Structure @@ -50,253 +50,83 @@ app/ ├── loading.tsx # Loading UI (Suspense) ├── error.tsx # Error boundary ├── not-found.tsx # 404 page -├── globals.css # Global styles ├── (auth)/ # Route group (não afecta URL) │ ├── login/page.tsx │ └── register/page.tsx ├── dashboard/ -│ ├── layout.tsx # Nested layout +│ ├── layout.tsx │ ├── page.tsx -│ └── [id]/ -│ └── page.tsx # Dynamic route -└── api/ - └── route.ts # API route +│ └── [id]/page.tsx # Dynamic route +└── api/route.ts # API route ``` +--- + ## Server vs Client Components ### Server Component (default) ```tsx -// ✅ PADRÃO - Runs on server async function ProductsPage() { - // Pode fazer fetch directo const products = await db.product.findMany(); - - return ( -
- {products.map(p => ( - - ))} -
- ); + return
{products.map(p => )}
; } - -export default ProductsPage; ``` -**Vantagens:** -- Acesso directo a BD -- Menos JavaScript no cliente -- SEO melhor -- Dados sempre frescos - ### Client Component ```tsx 'use client'; - import { useState } from 'react'; -// ✅ Para interactividade function Counter() { const [count, setCount] = useState(0); - - return ( - - ); + return ; } ``` -**Quando usar:** -- useState, useEffect, useContext -- Event listeners (onClick, onChange) -- Browser APIs (localStorage, window) -- Custom hooks +--- ## Data Fetching Patterns -### 1. Static (SSG) - ```tsx -// Default behaviour - cache infinito -async function Page() { - const data = await fetch('https://api.example.com/data', { - cache: 'force-cache' // Explícito (mas é default) - }); +// Static (SSG) - default +const data = await fetch('https://api.example.com/data', { cache: 'force-cache' }); - return
{data.title}
; -} +// Dynamic (SSR) +const data = await fetch('https://api.example.com/data', { cache: 'no-store' }); + +// ISR - revalidação automática +const data = await fetch('https://api.example.com/data', { next: { revalidate: 60 } }); ``` -### 2. Dynamic (SSR) - -```tsx -// Sempre fetch fresco -async function Page() { - const data = await fetch('https://api.example.com/data', { - cache: 'no-store' // NUNCA cache - }); - - return
{data.title}
; -} -``` - -### 3. Revalidate (ISR) - -```tsx -// Cache com revalidação automática -async function Page() { - const data = await fetch('https://api.example.com/data', { - next: { revalidate: 60 } // Revalida a cada 60s - }); - - return
{data.title}
; -} -``` +--- ## Server Actions ```tsx // app/actions.ts 'use server'; - import { revalidatePath } from 'next/cache'; -import { db } from '@/lib/db'; export async function createPost(formData: FormData) { const title = formData.get('title') as string; - const content = formData.get('content') as string; - - await db.post.create({ - data: { title, content } - }); - + await db.post.create({ data: { title } }); revalidatePath('/posts'); } -// app/create-post/page.tsx -import { createPost } from '@/app/actions'; - -export default function CreatePost() { - return ( -
- - - -``` - -### Select - -```php -
- - -
-``` - -### Select com AJAX (Clientes) - -```php -
- - -
-``` - -### Checkbox - -```php -
- is_active == 1) ? 'checked' : ''; ?>> - -
-``` - -### Radio - -```php -
- -
- status == 'pending') ? 'checked' : ''; ?>> - -
-
- status == 'active') ? 'checked' : ''; ?>> - -
-
-``` - -### Date Picker - -```php -
- - -
-``` - -### Date Time Picker - -```php -
- - -
-``` - -### File Upload - -```php - - -
- - -
- - -``` - -### Hidden - -```php - -``` - --- -## Validação Client-Side +## Validacao Client-Side O Perfex usa jQuery Validation. Usar `appValidateForm()`: @@ -250,23 +102,23 @@ $(function(){ ``` -### Regras de Validação +### Regras de Validacao -| Regra | Descrição | +| Regra | Descricao | |-------|-----------| -| `required: true` | Campo obrigatório | -| `email: true` | Email válido | -| `number: true` | Número | -| `digits: true` | Apenas dígitos | -| `minlength: N` | Mínimo N caracteres | -| `maxlength: N` | Máximo N caracteres | -| `min: N` | Valor mínimo | -| `max: N` | Valor máximo | +| `required: true` | Campo obrigatorio | +| `email: true` | Email valido | +| `number: true` | Numero | +| `digits: true` | Apenas digitos | +| `minlength: N` | Minimo N caracteres | +| `maxlength: N` | Maximo N caracteres | +| `min: N` | Valor minimo | +| `max: N` | Valor maximo | | `equalTo: '#field'` | Igual a outro campo | --- -## Validação Server-Side +## Validacao Server-Side ```php public function save() @@ -275,7 +127,6 @@ public function save() redirect(admin_url('meu_modulo')); } - // Validação $this->load->library('form_validation'); $this->form_validation->set_rules('name', _l('name'), 'required|min_length[3]'); @@ -283,12 +134,10 @@ public function save() $this->form_validation->set_rules('amount', _l('amount'), 'required|numeric'); if ($this->form_validation->run() === false) { - // Erro de validação set_alert('danger', validation_errors()); redirect(admin_url('meu_modulo/create')); } - // Dados válidos, processar $data = [ 'name' => $this->input->post('name'), 'email' => $this->input->post('email'), @@ -319,28 +168,6 @@ $.post(admin_url + 'meu_modulo/ajax_save', { }); ``` -### Com $.ajax() - -```javascript -$.ajax({ - url: admin_url + 'meu_modulo/ajax_save', - type: 'POST', - data: $('#form-meu-modulo').serialize(), - dataType: 'json', - success: function(response) { - if (response.success) { - alert_float('success', response.message); - // Redirecionar ou actualizar UI - } else { - alert_float('danger', response.message); - } - }, - error: function() { - alert_float('danger', 'Erro de comunicação'); - } -}); -``` - ### Controller AJAX ```php @@ -378,9 +205,7 @@ Para endpoints que recebem callbacks externos: ```php // modules/meu_modulo/config/csrf_exclude_uris.php - - - -
-
-
-
-
-
- -

- - -

-
- - id) - : admin_url('meu_modulo/save'); - echo form_open($action, ['id' => 'form-meu-modulo']); - ?> - - -
- - -
- - -
- - -
- - -
- - -
- - -
- - -
- - -
- - -
- - -
- is_active == 1) ? 'checked' : ''; ?>> - -
- - -
- - - - -
- - - -
-
-
-
-
-
- - - - - -``` - ---- - ## Anti-Patterns (NUNCA FAZER) | Anti-Pattern | Risco | Alternativa | |--------------|-------|-------------| | `` HTML directo | CSRF bypass | `form_open()` | | Valores sem `html_escape()` | XSS | Escape sempre | -| Validação só client-side | Bypass | Validar server também | +| Validacao so client-side | Bypass | Validar server tambem | | AJAX sem verificar `is_ajax_request()` | Acesso directo | Verificar sempre | --- -## Checklist Formulários +## Checklist Formularios ``` -1. [ ] form_open() para todos os formulários +1. [ ] form_open() para todos os formularios 2. [ ] html_escape() em todos os values -3. [ ] Validação client-side (appValidateForm) -4. [ ] Validação server-side (form_validation) -5. [ ] Permissões verificadas no controller -6. [ ] CSRF excluído apenas para webhooks +3. [ ] Validacao client-side (appValidateForm) +4. [ ] Validacao server-side (form_validation) +5. [ ] Permissoes verificadas no controller +6. [ ] CSRF excluido apenas para webhooks 7. [ ] form_open_multipart() para uploads 8. [ ] is_ajax_request() em endpoints AJAX ``` --- -**Versão:** 1.0.0 | **Autor:** Descomplicar® +## References + +- `references/elementos-formulario.md` - Todos os elementos HTML/PHP com exemplos +- `references/formulario-completo-exemplo.md` - View completa com todos os elementos + +--- + **Fonte:** help.perfexcrm.com/working-with-forms diff --git a/perfex-dev/skills/perfex-forms/references/elementos-formulario.md b/perfex-dev/skills/perfex-forms/references/elementos-formulario.md new file mode 100644 index 0000000..1445aee --- /dev/null +++ b/perfex-dev/skills/perfex-forms/references/elementos-formulario.md @@ -0,0 +1,159 @@ +# Elementos de Formulario Perfex CRM + +Referencia completa de todos os elementos HTML/PHP para formularios em modulos Perfex. + +--- + +## Input Text + +```php +
+ + +
+``` + +## Textarea + +```php +
+ + +
+``` + +## Select + +```php +
+ + +
+``` + +## Select com AJAX (Clientes) + +```php +
+ + +
+``` + +## Checkbox + +```php +
+ is_active == 1) ? 'checked' : ''; ?>> + +
+``` + +## Radio + +```php +
+ +
+ status == 'pending') ? 'checked' : ''; ?>> + +
+
+ status == 'active') ? 'checked' : ''; ?>> + +
+
+``` + +## Date Picker + +```php +
+ + +
+``` + +## Date Time Picker + +```php +
+ + +
+``` + +## File Upload + +```php + + +
+ + +
+ + +``` + +## Hidden + +```php + +``` diff --git a/perfex-dev/skills/perfex-forms/references/formulario-completo-exemplo.md b/perfex-dev/skills/perfex-forms/references/formulario-completo-exemplo.md new file mode 100644 index 0000000..8e97d00 --- /dev/null +++ b/perfex-dev/skills/perfex-forms/references/formulario-completo-exemplo.md @@ -0,0 +1,141 @@ +# Formulario Completo Exemplo - Perfex CRM + +Exemplo completo de view com formulario, validacao client-side e todos os elementos tipicos. + +--- + +## View + +```php + + + +
+
+
+
+
+
+ +

+ + +

+
+ + id) + : admin_url('meu_modulo/save'); + echo form_open($action, ['id' => 'form-meu-modulo']); + ?> + + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ is_active == 1) ? 'checked' : ''; ?>> + +
+ + +
+ + + + +
+ + + +
+
+
+
+
+
+ + + + + +``` diff --git a/perfex-dev/skills/perfex-hooks/SKILL.md b/perfex-dev/skills/perfex-hooks/SKILL.md index 8445e3b..a0bcd57 100644 --- a/perfex-dev/skills/perfex-hooks/SKILL.md +++ b/perfex-dev/skills/perfex-hooks/SKILL.md @@ -1,11 +1,6 @@ --- name: perfex-hooks -description: Perfex CRM hooks system. Actions, filters, add_action, add_filter, do_action, apply_filters. Complete hook list by category. Based on official documentation only. Use when user mentions "perfex hooks", "action hook", "filter perfex", "extend perfex". -author: Descomplicar® Crescimento Digital -version: 1.0.0 -quality_score: 70 -user_invocable: true -desk_task: null +description: Sistema de hooks Perfex CRM — actions, filters, add_action, add_filter, do_action, apply_filters com lista completa por categoria. Baseado apenas na documentação oficial. --- # /perfex-hooks - Sistema de Hooks Perfex CRM diff --git a/perfex-dev/skills/perfex-menus/SKILL.md b/perfex-dev/skills/perfex-menus/SKILL.md index 0577ea7..e4e569b 100644 --- a/perfex-dev/skills/perfex-menus/SKILL.md +++ b/perfex-dev/skills/perfex-menus/SKILL.md @@ -1,11 +1,6 @@ --- name: perfex-menus -description: Perfex CRM menu creation. Sidebar menus, client menus, add_sidebar_menu_item(), positions, icons. Based on official documentation only. Use when user mentions "perfex menu", "sidebar perfex", "menu item", "navigation perfex". -author: Descomplicar® Crescimento Digital -version: 1.0.0 -quality_score: 70 -user_invocable: true -desk_task: null +description: Criação de menus para módulos Perfex CRM — sidebar, menus de cliente, add_sidebar_menu_item(), posições e ícones. Baseado apenas na documentação oficial. --- # /perfex-menus - Menus Perfex CRM diff --git a/perfex-dev/skills/perfex-migrations/SKILL.md b/perfex-dev/skills/perfex-migrations/SKILL.md index 3ccb7d0..9c60576 100644 --- a/perfex-dev/skills/perfex-migrations/SKILL.md +++ b/perfex-dev/skills/perfex-migrations/SKILL.md @@ -1,11 +1,6 @@ --- name: perfex-migrations -description: Perfex CRM module migrations and upgrades. Version management, migration files, database updates. Based on official documentation only. Use when user mentions "perfex migration", "module upgrade", "version perfex", "database migration". -author: Descomplicar® Crescimento Digital -version: 1.0.0 -quality_score: 70 -user_invocable: true -desk_task: null +description: Migrações e upgrades de módulos Perfex CRM — gestão de versões, ficheiros de migração e actualizações de base de dados. Baseado apenas na documentação oficial. --- # /perfex-migrations - Migrations Perfex CRM diff --git a/perfex-dev/skills/perfex-module-basics/SKILL.md b/perfex-dev/skills/perfex-module-basics/SKILL.md index a99557f..7ec837a 100644 --- a/perfex-dev/skills/perfex-module-basics/SKILL.md +++ b/perfex-dev/skills/perfex-module-basics/SKILL.md @@ -1,11 +1,6 @@ --- name: perfex-module-basics -description: Perfex CRM module development basics. Folder structure, init file, file headers, CodeIgniter integration. Based on official documentation only. Use when user mentions "perfex module", "criar modulo perfex", "init file perfex", "module structure". -author: Descomplicar® Crescimento Digital -version: 1.0.0 -quality_score: 70 -user_invocable: true -desk_task: null +description: Fundamentos de desenvolvimento de módulos Perfex CRM — estrutura de pastas, ficheiro init, headers e integração CodeIgniter. Baseado apenas na documentação oficial. --- # /perfex-module-basics - Estrutura Base Módulos Perfex CRM diff --git a/perfex-dev/skills/perfex-permissions/SKILL.md b/perfex-dev/skills/perfex-permissions/SKILL.md index 5d0d5e4..55e0c59 100644 --- a/perfex-dev/skills/perfex-permissions/SKILL.md +++ b/perfex-dev/skills/perfex-permissions/SKILL.md @@ -1,11 +1,6 @@ --- name: perfex-permissions -description: Perfex CRM permissions system. staff_can(), register_staff_capabilities(), access control. Based on official documentation only. Use when user mentions "perfex permissions", "staff_can", "access control", "capabilities perfex". -author: Descomplicar® Crescimento Digital -version: 1.0.0 -quality_score: 70 -user_invocable: true -desk_task: null +description: Sistema de permissões Perfex CRM — staff_can(), register_staff_capabilities(), controlo de acesso e roles. Baseado apenas na documentação oficial. --- # /perfex-permissions - Permissões Perfex CRM diff --git a/perfex-dev/skills/perfex-security/SKILL.md b/perfex-dev/skills/perfex-security/SKILL.md index 5bd6ca4..bb27a92 100644 --- a/perfex-dev/skills/perfex-security/SKILL.md +++ b/perfex-dev/skills/perfex-security/SKILL.md @@ -1,11 +1,6 @@ --- name: perfex-security -description: Perfex CRM module security. Input validation, CSRF, XSS prevention, directory traversal. Based on official documentation only. Use when user mentions "perfex security", "input validation", "csrf perfex", "xss protection". -author: Descomplicar® Crescimento Digital -version: 1.0.0 -quality_score: 70 -user_invocable: true -desk_task: null +description: Segurança para módulos Perfex CRM — validação de input, CSRF, prevenção XSS e protecção contra directory traversal. Baseado apenas na documentação oficial. --- # /perfex-security - Segurança Módulos Perfex CRM diff --git a/perfex-dev/skills/perfex-views/SKILL.md b/perfex-dev/skills/perfex-views/SKILL.md index 819b153..c8afb5b 100644 --- a/perfex-dev/skills/perfex-views/SKILL.md +++ b/perfex-dev/skills/perfex-views/SKILL.md @@ -1,11 +1,6 @@ --- name: perfex-views -description: Perfex CRM module views. Templates, init_head(), init_tail(), admin and client views, passing data. Based on official documentation only. Use when user mentions "perfex views", "template perfex", "init_head", "init_tail". -author: Descomplicar® Crescimento Digital -version: 1.0.0 -quality_score: 70 -user_invocable: true -desk_task: null +description: Views e templates para módulos Perfex CRM — init_head(), init_tail(), views admin e cliente, passagem de dados. Baseado apenas na documentação oficial. --- # /perfex-views - Views Perfex CRM diff --git a/project-manager/knowledge/datasets.json b/project-manager/knowledge/datasets.json index f8b05d8..6eee6af 100644 --- a/project-manager/knowledge/datasets.json +++ b/project-manager/knowledge/datasets.json @@ -3,25 +3,79 @@ "sources": { "notebooklm": { "description": "NotebookLM - conhecimento curado profundo via Gemini 2.5 RAG", - "tools": ["mcp__notebooklm__search_notebooks", "mcp__notebooklm__ask_question"], + "tools": [ + "mcp__notebooklm__search_notebooks", + "mcp__notebooklm__ask_question" + ], "notebooks": [ - {"id": "perfex-crm-knowledge-base", "topics": ["perfex", "crm", "modulos", "extensoes"]}, - {"id": "claude-code-advanced-knowledge", "topics": ["claude-code", "mcp", "skills", "plugins", "frameworks"]}, - {"id": "stack-tecnol-gica-ia-descompli", "topics": ["ia", "saas", "n8n", "crewai", "sifide", "automacao"]}, - {"id": "centos-web-panel-cwp-complete", "topics": ["cwp", "servidores", "hosting", "seguranca", "linux"]}, - {"id": "obsidian-knowledge-system", "topics": ["obsidian", "vault", "pkm", "bases", "plugins"]}, - {"id": "whatsms-zender-platform", "topics": ["whatsms", "zender", "whatsapp", "sms"]}, - {"id": "e-commerce-portugal-estrat-gia", "topics": ["ecommerce", "portugal", "pmes", "mercado"]} - ] - }, - "dify_kb": { - "description": "Dify KB - boas praticas gerais e datasets tematicos", - "tool": "mcp__dify-kb__dify_kb_retrieve_segments", - "datasets": [ - {"name": "Gestao de Projetos", "priority": 1}, - {"name": "Gestao de Processos", "priority": 1}, - {"name": "Estrategia", "priority": 2}, - {"name": "Produtividade", "priority": 2} + { + "id": "perfex-crm-knowledge-base", + "topics": [ + "perfex", + "crm", + "modulos", + "extensoes" + ] + }, + { + "id": "claude-code-advanced-knowledge", + "topics": [ + "claude-code", + "mcp", + "skills", + "plugins", + "frameworks" + ] + }, + { + "id": "stack-tecnol-gica-ia-descompli", + "topics": [ + "ia", + "saas", + "n8n", + "crewai", + "sifide", + "automacao" + ] + }, + { + "id": "centos-web-panel-cwp-complete", + "topics": [ + "cwp", + "servidores", + "hosting", + "seguranca", + "linux" + ] + }, + { + "id": "obsidian-knowledge-system", + "topics": [ + "obsidian", + "vault", + "pkm", + "bases", + "plugins" + ] + }, + { + "id": "whatsms-zender-platform", + "topics": [ + "whatsms", + "zender", + "whatsapp", + "sms" + ] + }, + { + "id": "e-commerce-portugal-estrat-gia", + "topics": [ + "ecommerce", + "portugal", + "pmes", + "mercado" + ] + } ] } } diff --git a/project-manager/skills/brainstorm/SKILL.md b/project-manager/skills/brainstorm/SKILL.md index a2bd045..506cc69 100644 --- a/project-manager/skills/brainstorm/SKILL.md +++ b/project-manager/skills/brainstorm/SKILL.md @@ -1,19 +1,6 @@ --- name: brainstorm -description: > - Brainstorming estruturado v1.1. Explora ideias de multiplos angulos antes de criar spec. - Consulta NotebookLM (Gemini 2.5 + conhecimento curado) e Dify KB para perspectivas de especialistas. - Use when "brainstorm", "ideia", "pensar", "explorar", "debater", - "o que achas", "como farias", "vale a pena", "pros e contras". -author: Descomplicar® Crescimento Digital -version: 1.1.0 -quality_score: 72 -user_invocable: true -category: productivity -tags: [brainstorm, ideacao, debate, explorar, dify, notebooklm, especialistas, decisao] -desk_project: 65 -allowed-tools: Read, Write, Glob, Grep, mcp__dify-kb, mcp__mcp-time, mcp__memory-supabase, mcp__notebooklm -mcps: dify-kb, mcp-time, memory-supabase, notebooklm +description: Brainstorming estruturado que explora ideias de múltiplos ângulos antes de criar spec. Consulta NotebookLM e Dify KB para perspectivas de especialistas. --- # /brainstorm v1.1 - Ideacao Estruturada diff --git a/project-manager/skills/discover/SKILL.md b/project-manager/skills/discover/SKILL.md index da0bbb0..90e1ac0 100644 --- a/project-manager/skills/discover/SKILL.md +++ b/project-manager/skills/discover/SKILL.md @@ -1,19 +1,6 @@ --- name: discover -description: > - Pesquisa e discovery v1.1. Investiga viabilidade, abordagens e estado da arte antes de brainstorm. - Pesquisa NotebookLM (Gemini 2.5 + conhecimento curado), Dify KB, web, codebase e Context7. - Use when "pesquisar", "investigar", "discover", "como funciona", "existe algo para", - "alternativas", "estado da arte", "viabilidade", "research", "antes de comecar". -author: Descomplicar® Crescimento Digital -version: 1.1.0 -quality_score: 72 -user_invocable: true -category: productivity -tags: [research, discovery, pesquisa, viabilidade, alternativas, estado-arte, notebooklm] -desk_project: 65 -allowed-tools: Read, Glob, Grep, WebSearch, WebFetch, mcp__dify-kb, mcp__mcp-time, mcp__memory-supabase, mcp__plugin_context7_context7, mcp__notebooklm -mcps: dify-kb, mcp-time, memory-supabase, context7, notebooklm +description: Pesquisa e discovery de viabilidade, abordagens e estado da arte. Pesquisa NotebookLM, Dify KB, web, codebase e Context7. --- # /discover v1.1 - Pesquisa e Discovery diff --git a/project-manager/skills/scope/SKILL.md b/project-manager/skills/scope/SKILL.md index 206c32e..fa99898 100644 --- a/project-manager/skills/scope/SKILL.md +++ b/project-manager/skills/scope/SKILL.md @@ -1,21 +1,6 @@ --- name: scope -description: > - Validacao de scope v1.0. Verifica rapidamente se o trabalho esta dentro do spec. - Detecta scope creep. Sugere criar novo spec para trabalho fora do scope. - Use when "scope", "scope creep", "estou dentro do spec", "am I on track", - "fora do scope", "alinhado", "derrapagem". -author: Descomplicar® Crescimento Digital -version: 1.0.0 -quality_score: 70 -user_invocable: true -category: productivity -tags: [scope, validation, spec, creep, alignment, check] -desk_project: 65 -allowed-tools: Read, Bash, Glob, Grep, mcp__mcp-time -mcps: mcp-time -dependencies: - skills: [spec] +description: Validação de scope que verifica se o trabalho está dentro do spec e detecta scope creep. --- # /scope v1.0 - Validacao de Scope diff --git a/project-manager/skills/spec/SKILL.md b/project-manager/skills/spec/SKILL.md index 568a4e2..73eb6a7 100644 --- a/project-manager/skills/spec/SKILL.md +++ b/project-manager/skills/spec/SKILL.md @@ -1,19 +1,7 @@ --- name: spec -description: > - Spec-driven development v1.0. Cria e gere SPEC.md como contrato entre utilizador e Claude. - Forca ambos a alinhar antes de codificar. Suporta 3 pesos (light/medium/heavy). - Use when "spec", "especificacao", "requisitos", "requirements", "define scope", - "approve spec", "check spec", "o que vamos fazer", "antes de comecar". -author: Descomplicar® Crescimento Digital -version: 1.0.0 -quality_score: 70 -user_invocable: true -category: productivity -tags: [spec, requirements, scope, planning, project, contract] -desk_project: 65 -allowed-tools: Read, Write, Edit, Bash, Glob, mcp__desk-crm-v3, mcp__mcp-time -mcps: desk-crm-v3, mcp-time +description: Spec-driven development — cria e gere SPEC.md como contrato entre utilizador e Claude. Suporta 3 pesos (light/medium/heavy). +disable-model-invocation: true --- # /spec v1.0 - Spec-Driven Development @@ -22,6 +10,23 @@ Contrato bilateral: forca o Emanuel a definir o que quer e forca o Claude a prov **Sem spec aprovado, sem codigo.** +## Contexto NotebookLM + +ANTES de executar, consultar notebooks para contexto especializado: + +| Notebook | ID | Consultar quando | +|----------|-----|-----------------| +| Gestão de Projectos e Agile | 0c9c079c-a426-486c-99eb-1564d42d37ad | Sempre | + +``` +mcp__notebooklm__notebook_query({ + notebook_id: "0c9c079c-a426-486c-99eb-1564d42d37ad", + query: "" +}) +``` + +Integrar insights do NotebookLM nas recomendações e decisões. + --- ## Comandos diff --git a/project-manager/skills/sprint/SKILL.md b/project-manager/skills/sprint/SKILL.md index 8151d28..d9065a8 100644 --- a/project-manager/skills/sprint/SKILL.md +++ b/project-manager/skills/sprint/SKILL.md @@ -1,28 +1,30 @@ --- name: sprint -description: > - Sprints flexiveis v1.0. Le tasks do Desk CRM, agrupa em sprints com checkpoints. - Duracao flexivel por projecto. Checkpoint a meio e review no final. - Use when "sprint", "planning", "planeamento", "sprint plan", "sprint review", - "check-in", "o que fazer a seguir", "prioridades". -author: Descomplicar® Crescimento Digital -version: 1.0.0 -quality_score: 70 -user_invocable: true -category: productivity -tags: [sprint, planning, agile, desk, tasks, checkpoint, review] -desk_project: 65 -allowed-tools: Read, Write, Edit, Bash, Glob, mcp__desk-crm-v3, mcp__mcp-time, mcp__memory-supabase -mcps: desk-crm-v3, mcp-time, memory-supabase -dependencies: - skills: [spec] - mcps: [desk-crm-v3, mcp-time] +description: Sprints flexíveis que lêem tasks do Desk CRM, agrupam em sprints com checkpoints e reviews. +disable-model-invocation: true --- # /sprint v1.0 - Sprints Flexiveis Sprints com duracao flexivel, Desk CRM como fonte de verdade, checkpoints obrigatorios. +## Contexto NotebookLM + +ANTES de executar, consultar notebooks para contexto especializado: + +| Notebook | ID | Consultar quando | +|----------|-----|-----------------| +| Gestão de Projectos e Agile | 0c9c079c-a426-486c-99eb-1564d42d37ad | Sempre | + +``` +mcp__notebooklm__notebook_query({ + notebook_id: "0c9c079c-a426-486c-99eb-1564d42d37ad", + query: "" +}) +``` + +Integrar insights do NotebookLM nas recomendações e decisões. + --- ## Comandos diff --git a/project-manager/skills/status/SKILL.md b/project-manager/skills/status/SKILL.md index 1ed1b76..6b4ff83 100644 --- a/project-manager/skills/status/SKILL.md +++ b/project-manager/skills/status/SKILL.md @@ -1,21 +1,6 @@ --- name: status -description: > - Dashboard de projecto v1.0. Agrega spec, sprint, desk, git e timer num unico view. - Use when "status", "project status", "estado do projecto", "como estamos", - "progress", "overview", "dashboard", "resumo projecto". -author: Descomplicar® Crescimento Digital -version: 1.0.0 -quality_score: 70 -user_invocable: true -category: productivity -tags: [status, dashboard, project, progress, overview, aggregator] -desk_project: 65 -allowed-tools: Read, Bash, Glob, mcp__desk-crm-v3, mcp__mcp-time -mcps: desk-crm-v3, mcp-time -dependencies: - skills: [spec, sprint, scope] - mcps: [desk-crm-v3, mcp-time] +description: Dashboard de projecto que agrega spec, sprint, desk, git e timer numa única vista. --- # /status v1.0 - Dashboard de Projecto diff --git a/wordpress/.claude-plugin/plugin.json b/wordpress/.claude-plugin/plugin.json index 03dee7b..2ec219d 100644 --- a/wordpress/.claude-plugin/plugin.json +++ b/wordpress/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "wordpress", - "description": "WordPress development, maintenance and optimization - plugins, themes, WooCommerce, Elementor, Crocoblock. Backed by 6 Dify KB datasets.", + "description": "WordPress development, maintenance and optimization - plugins, themes, WooCommerce, Elementor, Crocoblock. Backed by NotebookLM notebooks.", "version": "1.0.0", "author": { "name": "Descomplicar - Crescimento Digital", diff --git a/wordpress/agents/elementor-specialist.md b/wordpress/agents/elementor-specialist.md index 88058e2..5e7ad9d 100644 --- a/wordpress/agents/elementor-specialist.md +++ b/wordpress/agents/elementor-specialist.md @@ -16,7 +16,6 @@ primary_mcps: recommended_mcps: - context7 - filesystem - - dify-kb skills: - _core desk_task: null @@ -39,8 +38,6 @@ created: '2025-01-13' updated: '2026-02-04' author: Descomplicar® --- - - # Elementor Specialist Descomplicar Especialista em desenvolvimento com Elementor Pro e criação de websites visuais. @@ -82,9 +79,6 @@ Especialista em desenvolvimento com Elementor Pro e criação de websites visuai ``` mcp__notebooklm__notebook_query notebook_id:"5be0d1a6-00f2-4cd9-b835-978cb7721601" query:"" ``` - -### Dify KB (Secundario) - - Wordpress - Elementor - Crocoblock @@ -143,7 +137,7 @@ Especialista em page building com Elementor Pro, entregando websites visuais de ## MCPs Relevantes - `ssh-unified`: Deploy e actualização de sites WordPress - `desk-crm-v3`: Gestão de projectos clientes -- `notebooklm`: KB primaria (Gemini 2.5 RAG) | `dify-kb`: KB WordPress, Elementor, Crocoblock +- `notebooklm`: KB primaria (Gemini 2.5 RAG) | ``: KB WordPress, Elementor, Crocoblock ## Colaboracao @@ -165,9 +159,9 @@ Especialista em page building com Elementor Pro, entregando websites visuais de - Gemini 2.5 RAG - Usage: `mcp__notebooklm__notebook_query` -✓ **dify-kb** (knowledge fallback) +✓ **** (knowledge fallback) - Knowledge base AI - - Usage: `mcp__dify-kb__*` + - Usage: `mcp____*` ### Recommended for dev - **gitea** - Repositórios Git, issues, PRs @@ -179,13 +173,11 @@ Especialista em page building com Elementor Pro, entregando websites visuais de - **cwp** - CentOS Web Panel - **puppeteer** - Browser automation -### All Available (33 total) +### All Available (32 total) moloni, google-analytics, google-workspace, imap, outline-api, youtube-research, youtube-uploader, wikijs, gsc, lighthouse, mcp-time, mcp-mermaid, mcp-echarts, powerpoint, penpot, pixabay, pexels, tavily, elevenlabs, vimeo, design-systems, replicate **Discovery:** Use ToolSearch to find specific tools. **Example:** `ToolSearch("ssh upload")` finds SSH upload tools. - - ## Your Available Skills ### Primary Skills (Your Domain) @@ -219,7 +211,7 @@ moloni, google-analytics, google-workspace, imap, outline-api, youtube-research, - **/knowledge** - Gestão unificada de conhecimento - pesquisa inteligente com - **/desk** - Integração com Desk CRM via ficheiro .desk-project. Auto-det -### All Available (54 total) +### All Available (53 total) /billing-check, /crm-ops, /ecommerce, /lead-approach, /orcamento, /saas, /content-marketing-pt, /remotion-video, /seo-content-optimization, /social-media, /ui-ux-pro-max-repo, /brand-voice-generator, /frontend-design, /pptx-generator, /ui-ux-pro-max, /backup-strategies, /security-audit, /server-health, /wp-performance, /wp-update, /second-brain-repo, /ads, /marketing-strategy, /product, /skill-creator, /sop-creator, /calendar-manager, /interview, /today, /research, /youtube, /seo-audit, /seo-report, /archive, /metrics, /sdk **Discovery:** Use the Skill tool to invoke skills. diff --git a/wordpress/agents/woocommerce-specialist.md b/wordpress/agents/woocommerce-specialist.md index 168a725..7af131b 100644 --- a/wordpress/agents/woocommerce-specialist.md +++ b/wordpress/agents/woocommerce-specialist.md @@ -41,8 +41,6 @@ created: '2025-01-13' updated: '2026-02-04' author: Descomplicar® --- - - # WooCommerce Specialist Descomplicar Especialista em desenvolvimento e optimizacao de lojas WooCommerce, focado em gateways de pagamento PT, checkout optimizado e integracoes com sistemas de facturacao. @@ -122,13 +120,6 @@ mcp__notebooklm__notebook_query notebook_id:"5be0d1a6-00f2-4cd9-b835-978cb772160 mcp__notebooklm__notebook_query notebook_id:"226e384e-d4bc-48f4-bb82-7927360436cc" query:"checkout conversao pagamentos" ``` -### Dify KB (Secundario - se NotebookLM insuficiente) - -``` -mcp__dify-kb__dify_kb_retrieve_segments dataset:"WordPress" query:"WooCommerce e-commerce plugins" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"E-commerce" query:"checkout conversao pagamentos" -``` - ## Colaboracao - Reports to: E-commerce Strategist - Colabora com: WordPress Plugin Developer, Payment Integration Specialist @@ -150,18 +141,16 @@ mcp__dify-kb__dify_kb_retrieve_segments dataset:"E-commerce" query:"checkout con - **n8n** - Workflows automation - **filesystem** - Ficheiros locais - **magic** - AI-powered UI component generation (tipo v0.dev) -- **dify-kb** - Knowledge base AI +- **** - Knowledge base AI - **memory-supabase** - Memória longo prazo - **cwp** - CentOS Web Panel - **puppeteer** - Browser automation -### All Available (33 total) +### All Available (32 total) moloni, google-analytics, google-workspace, imap, outline-api, youtube-research, youtube-uploader, wikijs, gsc, lighthouse, mcp-time, mcp-mermaid, mcp-echarts, powerpoint, penpot, pixabay, pexels, tavily, elevenlabs, vimeo, design-systems, replicate **Discovery:** Use ToolSearch to find specific tools. **Example:** `ToolSearch("ssh upload")` finds SSH upload tools. - - ## Your Available Skills ### Primary Skills (Your Domain) @@ -195,7 +184,7 @@ moloni, google-analytics, google-workspace, imap, outline-api, youtube-research, - **/knowledge** - Gestão unificada de conhecimento - pesquisa inteligente com - **/desk** - Integração com Desk CRM via ficheiro .desk-project. Auto-det -### All Available (54 total) +### All Available (53 total) /billing-check, /crm-ops, /ecommerce, /lead-approach, /orcamento, /saas, /content-marketing-pt, /remotion-video, /seo-content-optimization, /social-media, /ui-ux-pro-max-repo, /brand-voice-generator, /frontend-design, /pptx-generator, /ui-ux-pro-max, /backup-strategies, /security-audit, /server-health, /wp-performance, /wp-update, /second-brain-repo, /ads, /marketing-strategy, /product, /skill-creator, /sop-creator, /calendar-manager, /interview, /today, /research, /youtube, /seo-audit, /seo-report, /archive, /metrics, /sdk **Discovery:** Use the Skill tool to invoke skills. diff --git a/wordpress/agents/wordpress-performance-specialist.md b/wordpress/agents/wordpress-performance-specialist.md index 63410a7..828fe37 100644 --- a/wordpress/agents/wordpress-performance-specialist.md +++ b/wordpress/agents/wordpress-performance-specialist.md @@ -40,8 +40,6 @@ created: '2025-01-13' updated: '2026-02-04' author: Descomplicar® --- - - # WordPress Performance Specialist Descomplicar Especialista em optimizacao de performance WordPress e WooCommerce, focado em maximizar velocidade, Core Web Vitals e experiencia do utilizador atraves de caching, optimizacao de base de dados e assets. @@ -62,15 +60,6 @@ mcp__notebooklm__notebook_query notebook_id:"5be0d1a6-00f2-4cd9-b835-978cb772160 mcp__notebooklm__notebook_query notebook_id:"f9a79b5a-649f-4443-afaf-7ff562b6c2e7" query:"servidor PHP OPcache Redis" ``` -### Dify KB (Secundario - se NotebookLM insuficiente) - -``` -mcp__dify-kb__dify_kb_retrieve_segments dataset:"WordPress" query:"performance caching optimizacao velocidade" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Elementor" query:"performance assets optimizacao" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Crocoblock" query:"performance JetEngine queries" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"TI" query:"servidor PHP OPcache Redis" -``` - ## System Prompt ### Papel @@ -147,11 +136,6 @@ Especialista em optimizacao de performance WordPress responsavel por maximizar v | CLS | <0.1 | <0.25 | | TTFB | <600ms | <1.8s | | PageSpeed Score | >90 | >50 | - -## Datasets Dify (Consultar SEMPRE) -``` -mcp__dify-kb__dify_kb_retrieve_segments dataset:"WordPress" query:"performance caching optimizacao" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"TI" query:"Redis PHP OPcache servidor" ``` ## Colaboracao @@ -176,13 +160,11 @@ mcp__dify-kb__dify_kb_retrieve_segments dataset:"TI" query:"Redis PHP OPcache se - **mcp-time** - Hora actual, conversão fusos horários - **puppeteer** - Browser automation -### All Available (33 total) -moloni, context7, gitea, n8n, google-analytics, google-workspace, imap, outline-api, youtube-research, youtube-uploader, dify-kb, wikijs, gsc, memory-supabase, mcp-mermaid, mcp-echarts, powerpoint, penpot, pixabay, pexels, tavily, elevenlabs, magic, vimeo, design-systems, replicate +### All Available (32 total) +moloni, context7, gitea, n8n, google-analytics, google-workspace, imap, outline-api, youtube-research, youtube-uploader, wikijs, gsc, memory-supabase, mcp-mermaid, mcp-echarts, powerpoint, penpot, pixabay, pexels, tavily, elevenlabs, magic, vimeo, design-systems, replicate **Discovery:** Use ToolSearch to find specific tools. **Example:** `ToolSearch("ssh upload")` finds SSH upload tools. - - ## Your Available Skills ### Primary Skills (Your Domain) @@ -208,13 +190,11 @@ moloni, context7, gitea, n8n, google-analytics, google-workspace, imap, outline- - **/knowledge** - Gestão unificada de conhecimento - pesquisa inteligente com - **/desk** - Integração com Desk CRM via ficheiro .desk-project. Auto-det -### All Available (54 total) +### All Available (53 total) /billing-check, /crm-ops, /ecommerce, /lead-approach, /orcamento, /saas, /content-marketing-pt, /remotion-video, /seo-content-optimization, /social-media, /video, /ui-ux-pro-max-repo, /brand-voice-generator, /frontend-design, /pptx-generator, /ui-ux-pro-max, /crm-admin, /db-design, /elementor, /mcp-dev, /nextjs, /php-dev, /react-patterns, /woocommerce, /wp-dev, /second-brain-repo, /ads, /doc-sync, /marketing-strategy, /product, /skill-creator, /sop-creator, /calendar-manager, /interview, /time, /today, /research, /youtube, /seo-audit, /seo-report, /metrics, /sdk **Discovery:** Use the Skill tool to invoke skills. **Example:** `Skill("skill-name")` invokes the skill. - - ## Your Team & Responsibilities You are part of **2 SDKs** (TaskForce teams): @@ -224,9 +204,6 @@ You are part of **2 SDKs** (TaskForce teams): **Purpose:** NULL **Your responsibilities in this TaskForce:** - -- **Sistema de agentes especializados para delegacao de tarefas via Task tool com consulta automatica de datasets Dify.**: NULL - ### TaskForce WordPress **Purpose:** NULL diff --git a/wordpress/agents/wordpress-plugin-developer.md b/wordpress/agents/wordpress-plugin-developer.md index 722ab13..ce43f9a 100644 --- a/wordpress/agents/wordpress-plugin-developer.md +++ b/wordpress/agents/wordpress-plugin-developer.md @@ -27,7 +27,6 @@ recommended_mcps: - n8n # Workflow automation - filesystem # Local file operations - magic # UI component generation - - dify-kb # Knowledge base - memory-supabase # Long-term memory - cwp # Server management - puppeteer # Browser automation @@ -103,15 +102,6 @@ mcp__notebooklm__notebook_query notebook_id:"5be0d1a6-00f2-4cd9-b835-978cb772160 mcp__notebooklm__notebook_query notebook_id:"24947ffa-0019-448a-a340-2f4a275d2eb1" query:"PHP arquitectura APIs" ``` -### Dify KB (Secundario - se NotebookLM insuficiente) - -``` -mcp__dify-kb__dify_kb_retrieve_segments dataset:"WordPress" query:"plugins hooks filters desenvolvimento" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Crocoblock" query:"JetEngine custom post types dynamic" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Elementor" query:"widgets templates custom" -mcp__dify-kb__dify_kb_retrieve_segments dataset:"Desenvolvimento de Software" query:"PHP arquitectura APIs" -``` - ## System Prompt ### Papel diff --git a/wordpress/knowledge/datasets.json b/wordpress/knowledge/datasets.json index 423db82..d4fbf11 100644 --- a/wordpress/knowledge/datasets.json +++ b/wordpress/knowledge/datasets.json @@ -1,5 +1,5 @@ { - "description": "Knowledge sources (NotebookLM + Dify KB) for WordPress domain", + "description": "Knowledge sources for WordPress domain", "sources": { "notebooklm": { "description": "NotebookLM - conhecimento curado profundo via Gemini 2.5 RAG (PRIMARIO)", @@ -10,58 +10,9 @@ "title": "WordPress e Elementor", "topics": [ "wordpress" - ], - "maps_from_dify": "WordPress" - } - ] - }, - "dify_kb": { - "description": "Dify KB - datasets tematicos (FALLBACK)", - "query_tool": "mcp__dify-kb__dify_kb_retrieve_segments", - "datasets": [ - { - "id": "9da0b2b9-5051-4b99-b9f6-20bf35067092", - "name": "WordPress", - "priority": 1, - "document_count": 13, - "word_count": 819944 - }, - { - "id": "9c77d3e2-4d88-4a43-abff-d4e681267cc7", - "name": "Elementor", - "priority": 1, - "document_count": 32, - "word_count": 622946 - }, - { - "id": "139cdf67-afce-46ec-9ccd-2a06040e5b9d", - "name": "Crocoblock", - "priority": 1, - "document_count": 403, - "word_count": 7566111 - }, - { - "id": "bdf85c26-1824-4021-92d1-be20501b35ac", - "name": "Crocoblock 2", - "priority": 2, - "document_count": 25, - "word_count": 1429775 - }, - { - "id": "2e9b7c48-c630-457a-83a0-db8e77f76eae", - "name": "Kivicare", - "priority": 2, - "document_count": 178, - "word_count": 1085806 - }, - { - "id": "c8489151-de94-42b2-8cee-c0b961cfac6d", - "name": "Desenvolvimento de WebSites", - "priority": 2, - "document_count": 31, - "word_count": 4366521 + ] } ] } } -} \ No newline at end of file +} diff --git a/wordpress/skills/branda-menu/SKILL.md b/wordpress/skills/branda-menu/SKILL.md index 1a4e82b..149bda6 100644 --- a/wordpress/skills/branda-menu/SKILL.md +++ b/wordpress/skills/branda-menu/SKILL.md @@ -1,23 +1,6 @@ --- name: branda-menu -description: > - Organiza o menu admin WordPress via Branda (branda-white-labeling) em seccoes Descomplicar standard. Computa Branda IDs a partir de slugs WP, constroi menu custom com itens nativos reordenados + section headers, e guarda programaticamente via WP-CLI. Use when "branda menu", "organizar menu admin", "menu wordpress", "admin sidebar", "reorganizar admin". -author: Descomplicar Crescimento Digital -version: 1.0.0 -quality_score: 85 -user_invocable: true -category: wordpress -tags: [branda, wordpress, admin-menu, white-labeling, wip] -desk_project: 69 -allowed-tools: Read, Write, Edit, Bash, mcp__ssh-unified, mcp__memory-supabase -mcps: ssh-unified, memory-supabase -dependencies: - mcps: [ssh-unified] - plugins: [branda-white-labeling] -triggers: - - "User mentions 'branda menu', 'organizar menu', 'admin sidebar'" - - "User asks to reorganize WordPress admin menu" - - "Setting up new WiP site admin customization" +description: Organizacao do menu admin WordPress via Branda (branda-white-labeling) em seccoes Descomplicar standard. Computa Branda IDs a partir de slugs WP, constroi menu custom e guarda programaticamente via WP-CLI. --- # /branda-menu - Organizar Menu Admin WordPress @@ -38,12 +21,10 @@ O Branda usa um modulo `admin/menu.php` que intercepta o render do menu admin Wo |--------|--------| | `ultimatebranding_activated_modules` | Modulos activos (precisa ter `admin/menu.php`) | | `ub_custom_admin_menu` | Configuracao do menu custom por role | -| `ub_saved_admin_menus` | Captura do menu nativo WP (so para UI Branda, nao para render) | +| `ub_saved_admin_menus` | Captura do menu nativo WP (so para UI Branda) | ### Algoritmo de ID (critico) -O Branda mapeia slugs WordPress para IDs internos usando: - ```php function branda_id($slug) { return "menu_item_" . substr(base_convert(md5($slug), 16, 32), 0, 12); @@ -52,63 +33,35 @@ function branda_id($slug) { **Exemplo:** `index.php` -> `menu_item_42ho017e7jo0` -Este algoritmo e determinista. O mesmo slug gera sempre o mesmo ID, independente do site. - ### Tipos de itens no menu | Tipo | Campos chave | Uso | |------|-------------|-----| | **Section header** | `link_type: "none"`, `css_classes: "menu-highlight"` | Separador visual com titulo | -| **Custom link** | `link_type: "custom"`, `custom_url: "..."` | Link manual (ex: Descomplicar) | -| **Native item** | `was_native: 1`, campos vazios | Item WP real, nome preenchido dinamicamente | -| **Hidden item** | `is_hidden: "1"`, `was_native: 1` | Item WP escondido do menu | +| **Custom link** | `link_type: "custom"`, `custom_url: "..."` | Link manual | +| **Native item** | `was_native: 1`, campos vazios | Item WP real | +| **Hidden item** | `is_hidden: "1"`, `was_native: 1` | Item WP escondido | ### Mecanismo de merge (parse_args_deep) -Na renderizacao, o Branda faz merge do menu configurado com o menu WP real: -- Itens nativos no config: aparecem na posicao configurada -- Itens nativos **nao** no config: inseridos na posicao default (aparecem misturados!) -- Itens custom: aparecem na posicao configurada -- Submenus vazios `[]`: auto-preenchidos com submenus reais do WP - -**Regra critica:** Incluir **todos** os itens nativos no config (visiveis na posicao desejada OU hidden). Se faltar algum, aparece na posicao default e quebra a organizacao. +Na renderizacao, o Branda faz merge do menu configurado com o menu WP real. **Regra critica:** Incluir **todos** os itens nativos no config (visiveis ou hidden). Se faltar algum, aparece na posicao default e quebra a organizacao. --- ## Seccoes Standard Descomplicar (9) -Todo site WiP deve ter o menu organizado nestas 9 seccoes, nesta ordem: - | # | Seccao | Dashicon | Conteudo tipico | |---|--------|----------|----------------| -| 1 | **Suporte** | dashicons-admin-tools | Link Descomplicar (desk.descomplicar.pt) | +| 1 | **Suporte** | dashicons-admin-tools | Link Descomplicar | | 2 | **Admin** | dashicons-admin-generic | Painel, Utilizadores, Opcoes, Plugins, Ferramentas | -| 3 | **Conteudo** | dashicons-admin-page | Paginas, CPTs do projecto, Artigos, Multimedia, ACF | +| 3 | **Conteudo** | dashicons-admin-page | Paginas, CPTs, Artigos, Multimedia, ACF | | 4 | **Design** | dashicons-admin-appearance | Elementor, Modelos, Jeg Kit, Apresentacao | -| 5 | **Marketing** | dashicons-megaphone | FluentCRM, Fluent Forms, Rank Math, WhatsApp, etc. | +| 5 | **Marketing** | dashicons-megaphone | FluentCRM, Fluent Forms, Rank Math, WhatsApp | | 6 | **Idiomas** | dashicons-translation | Polylang/WPML, Loco Translate (se multilingue) | | 7 | **Performance** | dashicons-performance | WP Fastest Cache, WebP Express | | 8 | **Seguranca** | dashicons-shield | Wordfence, Complianz | | 9 | **WebMaster** | dashicons-admin-settings | Branda, Code Snippets, Activity Log | -**Notas:** -- Seccao Idiomas so aparece se site for multilingue -- CPTs especificos do projecto (Tours, Servicos, etc.) vao em Conteudo -- Plugins sectoriais (KiviCare, WooCommerce, etc.) podem ter seccao propria entre Marketing e Idiomas - ---- - -## Itens tipicamente hidden - -Estes itens nativos devem ser incluidos no config com `is_hidden: "1"`: - -| Slug | Motivo | -|------|--------| -| `separator1`, `separator2`, `separator-last` | Separadores nativos substituidos por section headers | -| `edit-comments.php` | Comentarios raramente usados | -| `hello-elementor` | Pagina tema redundante com themes.php | -| `elementor` | Menu Elementor duplicado (ja existe elementor-home) | - --- ## Procedimento @@ -116,7 +69,6 @@ Estes itens nativos devem ser incluidos no config com `is_hidden: "1"`: ### Passo 1: Verificar pre-requisitos ```bash -# Via MCP SSH - verificar Branda activo e modulo menu activo mcp__ssh-unified__ssh_execute server:"server" command:"wp plugin is-active branda-white-labeling --allow-root --path=/home/USER/SITE && echo ACTIVE || echo INACTIVE" # Verificar modulo menu activo @@ -138,272 +90,25 @@ echo \"Activado\"; ### Passo 2: Extrair menu nativo -Obter lista de plugins activos e menu WP via WP-CLI. Como WP-CLI nao carrega todos os menus admin, usar este metodo combinado: +**Opcao A (preferida): mu-plugin temporario** - criar mu-plugin que captura menu no proximo page load, depois ler a captura via `wp eval`. -**Opcao A (preferida): mu-plugin temporario** - -```bash -# Criar mu-plugin que captura menu no proximo page load -mcp__ssh-unified__ssh_execute server:"server" command:"cat > /home/USER/SITE/wp-content/mu-plugins/capture-menu.php << 'PHPEOF' - \$menu, - 'submenu' => \$submenu, - 'captured_at' => time() - )); - update_option('_branda_menu_captured', true); - - // Self-destruct - @unlink(__FILE__); -}, 999999); -PHPEOF -echo 'mu-plugin criado' -" -``` - -Depois, gerar cookie de auth e disparar um page load admin: -```bash -# Gerar cookie auth via WP-CLI -mcp__ssh-unified__ssh_execute server:"server" command:"wp eval ' -\$expiration = time() + 300; -\$cookie = wp_generate_auth_cookie(1, \$expiration, \"logged_in\"); -echo \$cookie; -' --allow-root --path=/home/USER/SITE" - -# Disparar page load admin com curl (substituir COOKIE e HASH) -mcp__ssh-unified__ssh_execute server:"server" command:"curl -s -o /dev/null -w '%{http_code}' -b 'wordpress_logged_in_HASH=COOKIE' https://SITE/wp-admin/" -``` - -Depois ler a captura: -```bash -mcp__ssh-unified__ssh_execute server:"server" command:"wp eval ' -\$cap = get_option(\"_branda_menu_capture\"); -if (\$cap) { - foreach (\$cap[\"menu\"] as \$pos => \$item) { - if (count(\$item) >= 3) { - \$slug = \$item[2]; - \$title = strip_tags(\$item[0]); - echo \"\$pos. \$title => \$slug\n\"; - } - } -} -' --allow-root --path=/home/USER/SITE" -``` - -**Opcao B (alternativa): Chrome DevTools** - -Se tiver acesso ao browser, navegar ao wp-admin e executar JS: -```javascript -Array.from(document.querySelectorAll('#adminmenu > li')).forEach((li, i) => { - const a = li.querySelector('a'); - if (a) { - const name = a.querySelector('.wp-menu-name')?.textContent?.trim() || a.textContent?.trim(); - const href = a.getAttribute('href') || ''; - console.log(i + '. ' + name + ' => ' + href); - } -}); -``` +**Opcao B (alternativa): Chrome DevTools** - navegar ao wp-admin e executar JS para listar itens. ### Passo 3: Mapear itens para seccoes Com a lista de itens nativos, mapear cada um para a seccao correcta. -**Mapeamento standard por slug:** - -``` -# Admin -index.php -> Admin -users.php -> Admin -options-general.php -> Admin -plugins.php -> Admin -tools.php -> Admin - -# Conteudo -edit.php -> Conteudo (Artigos) -edit.php?post_type=page -> Conteudo (Paginas) -upload.php -> Conteudo (Multimedia) -edit.php?post_type=acf-field-group -> Conteudo (ACF) -edit.php?post_type=* -> Conteudo (CPTs) - -# Design -elementor-home -> Design (Elementor) -edit.php?post_type=elementor_library -> Design (Modelos) -jkit -> Design (Jeg Kit) -themes.php -> Design (Apresentacao) - -# Marketing -fluentcrm-admin -> Marketing -fluent_forms -> Marketing -rank-math -> Marketing -click-to-chat -> Marketing - -# Idiomas (se multilingue) -mlang -> Idiomas (Polylang) -loco -> Idiomas (Loco Translate) - -# Performance -wpfastestcacheoptions -> Performance - -# Seguranca -Wordfence -> Seguranca -complianz -> Seguranca - -# WebMaster -branding -> WebMaster (Branda) -wpcode -> WebMaster (Code Snippets) - -# Hidden -separator1, separator2, separator-last -> Hidden -edit-comments.php -> Hidden -hello-elementor -> Hidden -elementor -> Hidden (duplicado de elementor-home) -``` - -**Itens que nao encaixam no standard:** Perguntar ao utilizador em que seccao colocar. Exemplos: WooCommerce, KiviCare, FareHarbor. +Mapeamento completo de slugs e IDs em: `references/mapeamento-slugs.md` ### Passo 4: Construir e guardar o menu -Criar um PHP script no servidor e executar com `wp eval-file`: +Script PHP template completo em: `references/script-template.md` -```bash -mcp__ssh-unified__ssh_execute server:"server" command:"cat > /tmp/branda-menu-SITE.php << 'PHPEOF' - '', 'id_attribute' => '', 'css_classes' => '', - 'icon_svg' => '', 'icon_url' => '', 'icon_image_id' => '', - 'dashicon' => '', 'icon_type' => '', 'custom_url' => '', - 'link_type' => '', 'link_target' => '', 'is_invisible' => '', - 'is_hidden' => '', 'was_native' => 1, 'submenu' => \$subs - ); -} - -function hidden_item() { - \$item = native_item(); - \$item['is_hidden'] = '1'; - return \$item; -} - -function section_header(\$title, \$dashicon) { - return array( - 'icon_type' => 'dashicon', 'link_type' => 'none', - 'submenu' => array(), 'title' => \$title, - 'css_classes' => 'menu-highlight', 'dashicon' => \$dashicon - ); -} - -function custom_link(\$title, \$url, \$dashicon, \$target = '') { - return array( - 'icon_type' => 'dashicon', 'link_type' => 'custom', - 'submenu' => array(), 'title' => \$title, - 'dashicon' => \$dashicon, 'link_target' => \$target, - 'custom_url' => \$url - ); -} - -// === BUILD MENU === -\$menu = array(); - -// 1. SUPORTE -\$menu['menu_item_sec_suporte'] = section_header('Suporte', 'dashicons-admin-tools'); -\$menu['menu_item_desk_link'] = custom_link('Descomplicar', 'https://desk.descomplicar.pt/', 'dashicons-admin-comments', '_blank'); - -// 2. ADMIN -\$menu['menu_item_sec_admin'] = section_header('Admin', 'dashicons-admin-generic'); -\$menu[branda_id('index.php')] = native_item(); -\$menu[branda_id('users.php')] = native_item(); -\$menu[branda_id('options-general.php')] = native_item(); -\$menu[branda_id('plugins.php')] = native_item(); -\$menu[branda_id('tools.php')] = native_item(); - -// 3. CONTEUDO -\$menu['menu_item_sec_conteudo'] = section_header('Conteudo', 'dashicons-admin-page'); -\$menu[branda_id('edit.php?post_type=page')] = native_item(); -// [INSERIR CPTs DO PROJECTO AQUI] -\$menu[branda_id('edit.php')] = native_item(); -\$menu[branda_id('upload.php')] = native_item(); -\$menu[branda_id('edit.php?post_type=acf-field-group')] = native_item(); - -// 4. DESIGN -\$menu['menu_item_sec_design'] = section_header('Design', 'dashicons-admin-appearance'); -\$menu[branda_id('elementor-home')] = native_item(); -\$menu[branda_id('edit.php?post_type=elementor_library')] = native_item(); -// \$menu[branda_id('jkit')] = native_item(); // Se Jeg Kit activo -\$menu[branda_id('themes.php')] = native_item(); - -// 5. MARKETING -\$menu['menu_item_sec_marketing'] = section_header('Marketing', 'dashicons-megaphone'); -\$menu[branda_id('fluentcrm-admin')] = native_item(); -\$menu[branda_id('fluent_forms')] = native_item(); -\$menu[branda_id('rank-math')] = native_item(); -\$menu[branda_id('click-to-chat')] = native_item(); - -// 6. IDIOMAS (se multilingue) -// \$menu['menu_item_sec_idiomas'] = section_header('Idiomas', 'dashicons-translation'); -// \$menu[branda_id('mlang')] = native_item(); -// \$menu[branda_id('loco')] = native_item(); - -// 7. PERFORMANCE -\$menu['menu_item_sec_performance'] = section_header('Performance', 'dashicons-performance'); -\$menu[branda_id('wpfastestcacheoptions')] = native_item(); - -// 8. SEGURANCA -\$menu['menu_item_sec_seguranca'] = section_header('Seguranca', 'dashicons-shield'); -\$menu[branda_id('Wordfence')] = native_item(); -\$menu[branda_id('complianz')] = native_item(); - -// 9. WEBMASTER -\$menu['menu_item_sec_webmaster'] = section_header('WebMaster', 'dashicons-admin-settings'); -\$menu[branda_id('branding')] = native_item(); -\$menu[branda_id('wpcode')] = native_item(); - -// HIDDEN -\$menu[branda_id('separator1')] = hidden_item(); -\$menu[branda_id('separator2')] = hidden_item(); -\$menu[branda_id('separator-last')] = hidden_item(); -\$menu[branda_id('edit-comments.php')] = hidden_item(); -\$menu[branda_id('hello-elementor')] = hidden_item(); -\$menu[branda_id('elementor')] = hidden_item(); - -// SAVE -update_option('ub_custom_admin_menu', array('administrator' => \$menu)); -wp_cache_flush(); - -\$visible = count(array_filter(\$menu, function(\$i) { return empty(\$i['is_hidden']); })); -\$hidden = count(\$menu) - \$visible; -echo \"Menu guardado: \$visible visiveis + \$hidden hidden = \" . count(\$menu) . \" total\n\"; -PHPEOF -echo 'Script criado' -" - -# Executar -mcp__ssh-unified__ssh_execute server:"server" command:"wp eval-file /tmp/branda-menu-SITE.php --allow-root --path=/home/USER/SITE" -``` +Executar com `wp eval-file` via SSH MCP. ### Passo 5: Verificar ```bash -# Contar itens no config mcp__ssh-unified__ssh_execute server:"server" command:"wp eval ' \$m = get_option(\"ub_custom_admin_menu\"); \$items = \$m[\"administrator\"]; @@ -417,145 +122,40 @@ foreach (\$items as \$key => \$item) { ' --allow-root --path=/home/USER/SITE" ``` -Verificar visualmente no browser: navegar ao wp-admin e confirmar que o menu esta organizado nas 9 seccoes. +Verificar visualmente no browser. ### Passo 6: Limpar ```bash -# Remover script temporario mcp__ssh-unified__ssh_execute server:"server" command:"rm -f /tmp/branda-menu-SITE.php" -# Limpar captura temporaria (se usou mu-plugin) mcp__ssh-unified__ssh_execute server:"server" command:"wp eval ' delete_option(\"_branda_menu_capture\"); delete_option(\"_branda_menu_captured\"); echo \"Limpo\"; ' --allow-root --path=/home/USER/SITE" -# Garantir mu-plugin removido mcp__ssh-unified__ssh_execute server:"server" command:"rm -f /home/USER/SITE/wp-content/mu-plugins/capture-menu.php 2>/dev/null; echo ok" ``` --- -## Adaptar para sites especificos - -### Sites multilingue (Polylang/WPML) - -Descomentar seccao Idiomas no script. Adicionar: -```php -$menu['menu_item_sec_idiomas'] = section_header('Idiomas', 'dashicons-translation'); -$menu[branda_id('mlang')] = native_item(); // Polylang -$menu[branda_id('loco')] = native_item(); // Loco Translate -``` - -### Sites WooCommerce - -Adicionar seccao e-Commerce entre Marketing e Idiomas: -```php -$menu['menu_item_sec_ecommerce'] = section_header('e-Commerce', 'dashicons-cart'); -$menu[branda_id('woocommerce')] = native_item(); -// $menu[branda_id('wc-admin&path=/analytics/overview')] = native_item(); // Analytics WC -``` - -### Sites Care (KiviCare) - -Adicionar seccao Clinica entre Marketing e Idiomas: -```php -$menu['menu_item_sec_clinica'] = section_header('Clinica', 'dashicons-heart'); -$menu[branda_id('kivicare-...')] = native_item(); // Verificar slug exacto -``` - -### CPTs customizados - -Adicionar na seccao Conteudo, antes de Artigos: -```php -$menu[branda_id('edit.php?post_type=SLUG_CPT')] = native_item(); -``` - -### Itens desconhecidos - -Se o menu nativo tiver itens que nao encaixam no mapeamento standard: -1. Perguntar ao utilizador onde colocar -2. Se plugin temporario/teste: adicionar ao Hidden -3. Se plugin permanente: criar seccao propria ou adicionar a seccao existente - ---- - ## Troubleshooting -### Menu nao muda apos guardar +| Problema | Causa | Solucao | +|----------|-------|---------| +| Menu nao muda apos guardar | Cache ou modulo inactivo | `wp cache flush` + verificar `admin/menu.php` activo | +| Itens nativos fora das seccoes | Item nao incluido no config | Identificar slug, computar Branda ID, adicionar ao config | +| Separadores nativos aparecem | Slugs diferentes dos standard | Verificar slugs via captura, adicionar como hidden | +| Items custom em duplicado | Existe como custom e native | Remover custom link, manter native | -1. Limpar cache: `wp cache flush --allow-root` -2. Verificar modulo activo: `admin/menu.php` em `ultimatebranding_activated_modules` -3. Verificar role: config usa key `administrator` (nao `admin`) - -### Itens nativos aparecem fora das seccoes - -Causa: item nativo nao incluido no config (inserido na posicao default pelo parse_args_deep). -Fix: Identificar o slug do item, computar o Branda ID, adicionar ao config (visivel ou hidden). - -### Separadores nativos aparecem - -Causa: separadores com slugs diferentes dos standard (`separator1`, `separator2`, `separator-last`). -Fix: Verificar slugs via captura do menu nativo, adicionar como hidden. - -### Menu items custom aparecem em duplicado - -Causa: o mesmo item existe como custom link E como native item. -Fix: Remover o custom link, manter apenas o native item na posicao correcta. - -### CSS para esconder separadores em falta - -Adicionar ao CSS custom do Branda (ub_admin_css) como fallback: +**CSS fallback para separadores:** ```css #adminmenu li.wp-menu-separator { display: none !important; } ``` --- -## IDs de slugs comuns (referencia rapida) - -| Slug | Branda ID | -|------|-----------| -| `index.php` | `menu_item_42ho017e7jo0` | -| `edit.php` | `menu_item_6lk5pbiakha0` | -| `upload.php` | `menu_item_1jkdde99dfd0` | -| `edit.php?post_type=page` | `menu_item_774p5endtlu0` | -| `themes.php` | `menu_item_7jgmlsspgv60` | -| `plugins.php` | `menu_item_5g2kqk93qi30` | -| `users.php` | `menu_item_gajld83c8es0` | -| `tools.php` | `menu_item_3t0no8pv5bfg` | -| `options-general.php` | `menu_item_d1a8rsor9700` | -| `edit-comments.php` | `menu_item_252pn6seih20` | -| `separator1` | `menu_item_3u7nva84d1i0` | -| `separator2` | `menu_item_6lm7mo14a4r0` | -| `separator-last` | `menu_item_74g99t5jejn0` | -| `elementor-home` | `menu_item_2kehh8g6nop0` | -| `elementor` | `menu_item_27qkhd7iqao0` | -| `edit.php?post_type=elementor_library` | `menu_item_3rubghs8krfg` | -| `hello-elementor` | `menu_item_3q7v6ask7gpg` | -| `fluentcrm-admin` | `menu_item_4a7t8bi9mt30` | -| `fluent_forms` | `menu_item_ebai6etubd00` | -| `rank-math` | `menu_item_148bl1t91os0` | -| `click-to-chat` | `menu_item_1b65lubbpnd8` | -| `Wordfence` | `menu_item_1077vi8mf9b0` | -| `complianz` | `menu_item_5etmjgu9lnk0` | -| `wpfastestcacheoptions` | `menu_item_4hqsn1kbum10` | -| `branding` | `menu_item_7qde2b2f7670` | -| `wpcode` | `menu_item_69igp9fj4tl0` | -| `loco` | `menu_item_2c34vb7r1csg` | -| `mlang` | `menu_item_24um676vv08g` | -| `woocommerce` | Computar: `branda_id('woocommerce')` | -| `edit.php?post_type=acf-field-group` | `menu_item_70ga2p32mc70` | - -Para slugs nao listados, computar com: -```bash -wp eval 'echo "menu_item_" . substr(base_convert(md5("SLUG"), 16, 32), 0, 12);' --allow-root --path=/home/USER/SITE -``` - ---- - ## Checklist - [ ] Branda activo e modulo `admin/menu.php` activo @@ -569,4 +169,7 @@ wp eval 'echo "menu_item_" . substr(base_convert(md5("SLUG"), 16, 32), 0, 12);' --- -*Skill v1.0.0 | 26-02-2026 | Descomplicar* +## References + +- `references/mapeamento-slugs.md` - Mapeamento completo slug -> seccao e tabela de Branda IDs +- `references/script-template.md` - Script PHP template + adaptacoes por tipo de site diff --git a/wordpress/skills/branda-menu/references/mapeamento-slugs.md b/wordpress/skills/branda-menu/references/mapeamento-slugs.md new file mode 100644 index 0000000..c9d01b7 --- /dev/null +++ b/wordpress/skills/branda-menu/references/mapeamento-slugs.md @@ -0,0 +1,100 @@ +# Mapeamento de Slugs para Seccoes Branda + +Referencia completa de mapeamento slug -> seccao e tabela de Branda IDs. + +--- + +## Mapeamento Standard por Slug + +``` +# Admin +index.php -> Admin +users.php -> Admin +options-general.php -> Admin +plugins.php -> Admin +tools.php -> Admin + +# Conteudo +edit.php -> Conteudo (Artigos) +edit.php?post_type=page -> Conteudo (Paginas) +upload.php -> Conteudo (Multimedia) +edit.php?post_type=acf-field-group -> Conteudo (ACF) +edit.php?post_type=* -> Conteudo (CPTs) + +# Design +elementor-home -> Design (Elementor) +edit.php?post_type=elementor_library -> Design (Modelos) +jkit -> Design (Jeg Kit) +themes.php -> Design (Apresentacao) + +# Marketing +fluentcrm-admin -> Marketing +fluent_forms -> Marketing +rank-math -> Marketing +click-to-chat -> Marketing + +# Idiomas (se multilingue) +mlang -> Idiomas (Polylang) +loco -> Idiomas (Loco Translate) + +# Performance +wpfastestcacheoptions -> Performance + +# Seguranca +Wordfence -> Seguranca +complianz -> Seguranca + +# WebMaster +branding -> WebMaster (Branda) +wpcode -> WebMaster (Code Snippets) + +# Hidden +separator1, separator2, separator-last -> Hidden +edit-comments.php -> Hidden +hello-elementor -> Hidden +elementor -> Hidden (duplicado de elementor-home) +``` + +**Itens que nao encaixam no standard:** Perguntar ao utilizador em que seccao colocar. Exemplos: WooCommerce, KiviCare, FareHarbor. + +--- + +## IDs de Slugs Comuns (referencia rapida) + +| Slug | Branda ID | +|------|-----------| +| `index.php` | `menu_item_42ho017e7jo0` | +| `edit.php` | `menu_item_6lk5pbiakha0` | +| `upload.php` | `menu_item_1jkdde99dfd0` | +| `edit.php?post_type=page` | `menu_item_774p5endtlu0` | +| `themes.php` | `menu_item_7jgmlsspgv60` | +| `plugins.php` | `menu_item_5g2kqk93qi30` | +| `users.php` | `menu_item_gajld83c8es0` | +| `tools.php` | `menu_item_3t0no8pv5bfg` | +| `options-general.php` | `menu_item_d1a8rsor9700` | +| `edit-comments.php` | `menu_item_252pn6seih20` | +| `separator1` | `menu_item_3u7nva84d1i0` | +| `separator2` | `menu_item_6lm7mo14a4r0` | +| `separator-last` | `menu_item_74g99t5jejn0` | +| `elementor-home` | `menu_item_2kehh8g6nop0` | +| `elementor` | `menu_item_27qkhd7iqao0` | +| `edit.php?post_type=elementor_library` | `menu_item_3rubghs8krfg` | +| `hello-elementor` | `menu_item_3q7v6ask7gpg` | +| `fluentcrm-admin` | `menu_item_4a7t8bi9mt30` | +| `fluent_forms` | `menu_item_ebai6etubd00` | +| `rank-math` | `menu_item_148bl1t91os0` | +| `click-to-chat` | `menu_item_1b65lubbpnd8` | +| `Wordfence` | `menu_item_1077vi8mf9b0` | +| `complianz` | `menu_item_5etmjgu9lnk0` | +| `wpfastestcacheoptions` | `menu_item_4hqsn1kbum10` | +| `branding` | `menu_item_7qde2b2f7670` | +| `wpcode` | `menu_item_69igp9fj4tl0` | +| `loco` | `menu_item_2c34vb7r1csg` | +| `mlang` | `menu_item_24um676vv08g` | +| `woocommerce` | Computar: `branda_id('woocommerce')` | +| `edit.php?post_type=acf-field-group` | `menu_item_70ga2p32mc70` | + +Para slugs nao listados, computar com: +```bash +wp eval 'echo "menu_item_" . substr(base_convert(md5("SLUG"), 16, 32), 0, 12);' --allow-root --path=/home/USER/SITE +``` diff --git a/wordpress/skills/branda-menu/references/script-template.md b/wordpress/skills/branda-menu/references/script-template.md new file mode 100644 index 0000000..b734aae --- /dev/null +++ b/wordpress/skills/branda-menu/references/script-template.md @@ -0,0 +1,174 @@ +# Script Template Branda Menu Builder + +Script PHP completo para construir e guardar menu Branda via WP-CLI. + +--- + +## Template Base + +```bash +mcp__ssh-unified__ssh_execute server:"server" command:"cat > /tmp/branda-menu-SITE.php << 'PHPEOF' + '', 'id_attribute' => '', 'css_classes' => '', + 'icon_svg' => '', 'icon_url' => '', 'icon_image_id' => '', + 'dashicon' => '', 'icon_type' => '', 'custom_url' => '', + 'link_type' => '', 'link_target' => '', 'is_invisible' => '', + 'is_hidden' => '', 'was_native' => 1, 'submenu' => \$subs + ); +} + +function hidden_item() { + \$item = native_item(); + \$item['is_hidden'] = '1'; + return \$item; +} + +function section_header(\$title, \$dashicon) { + return array( + 'icon_type' => 'dashicon', 'link_type' => 'none', + 'submenu' => array(), 'title' => \$title, + 'css_classes' => 'menu-highlight', 'dashicon' => \$dashicon + ); +} + +function custom_link(\$title, \$url, \$dashicon, \$target = '') { + return array( + 'icon_type' => 'dashicon', 'link_type' => 'custom', + 'submenu' => array(), 'title' => \$title, + 'dashicon' => \$dashicon, 'link_target' => \$target, + 'custom_url' => \$url + ); +} + +// === BUILD MENU === +\$menu = array(); + +// 1. SUPORTE +\$menu['menu_item_sec_suporte'] = section_header('Suporte', 'dashicons-admin-tools'); +\$menu['menu_item_desk_link'] = custom_link('Descomplicar', 'https://desk.descomplicar.pt/', 'dashicons-admin-comments', '_blank'); + +// 2. ADMIN +\$menu['menu_item_sec_admin'] = section_header('Admin', 'dashicons-admin-generic'); +\$menu[branda_id('index.php')] = native_item(); +\$menu[branda_id('users.php')] = native_item(); +\$menu[branda_id('options-general.php')] = native_item(); +\$menu[branda_id('plugins.php')] = native_item(); +\$menu[branda_id('tools.php')] = native_item(); + +// 3. CONTEUDO +\$menu['menu_item_sec_conteudo'] = section_header('Conteudo', 'dashicons-admin-page'); +\$menu[branda_id('edit.php?post_type=page')] = native_item(); +// [INSERIR CPTs DO PROJECTO AQUI] +\$menu[branda_id('edit.php')] = native_item(); +\$menu[branda_id('upload.php')] = native_item(); +\$menu[branda_id('edit.php?post_type=acf-field-group')] = native_item(); + +// 4. DESIGN +\$menu['menu_item_sec_design'] = section_header('Design', 'dashicons-admin-appearance'); +\$menu[branda_id('elementor-home')] = native_item(); +\$menu[branda_id('edit.php?post_type=elementor_library')] = native_item(); +// \$menu[branda_id('jkit')] = native_item(); // Se Jeg Kit activo +\$menu[branda_id('themes.php')] = native_item(); + +// 5. MARKETING +\$menu['menu_item_sec_marketing'] = section_header('Marketing', 'dashicons-megaphone'); +\$menu[branda_id('fluentcrm-admin')] = native_item(); +\$menu[branda_id('fluent_forms')] = native_item(); +\$menu[branda_id('rank-math')] = native_item(); +\$menu[branda_id('click-to-chat')] = native_item(); + +// 6. IDIOMAS (se multilingue) +// \$menu['menu_item_sec_idiomas'] = section_header('Idiomas', 'dashicons-translation'); +// \$menu[branda_id('mlang')] = native_item(); +// \$menu[branda_id('loco')] = native_item(); + +// 7. PERFORMANCE +\$menu['menu_item_sec_performance'] = section_header('Performance', 'dashicons-performance'); +\$menu[branda_id('wpfastestcacheoptions')] = native_item(); + +// 8. SEGURANCA +\$menu['menu_item_sec_seguranca'] = section_header('Seguranca', 'dashicons-shield'); +\$menu[branda_id('Wordfence')] = native_item(); +\$menu[branda_id('complianz')] = native_item(); + +// 9. WEBMASTER +\$menu['menu_item_sec_webmaster'] = section_header('WebMaster', 'dashicons-admin-settings'); +\$menu[branda_id('branding')] = native_item(); +\$menu[branda_id('wpcode')] = native_item(); + +// HIDDEN +\$menu[branda_id('separator1')] = hidden_item(); +\$menu[branda_id('separator2')] = hidden_item(); +\$menu[branda_id('separator-last')] = hidden_item(); +\$menu[branda_id('edit-comments.php')] = hidden_item(); +\$menu[branda_id('hello-elementor')] = hidden_item(); +\$menu[branda_id('elementor')] = hidden_item(); + +// SAVE +update_option('ub_custom_admin_menu', array('administrator' => \$menu)); +wp_cache_flush(); + +\$visible = count(array_filter(\$menu, function(\$i) { return empty(\$i['is_hidden']); })); +\$hidden = count(\$menu) - \$visible; +echo "Menu guardado: \$visible visiveis + \$hidden hidden = " . count(\$menu) . " total\n"; +PHPEOF +echo 'Script criado' +" + +# Executar +mcp__ssh-unified__ssh_execute server:"server" command:"wp eval-file /tmp/branda-menu-SITE.php --allow-root --path=/home/USER/SITE" +``` + +--- + +## Adaptacoes por Tipo de Site + +### Sites multilingue (Polylang/WPML) + +Descomentar seccao Idiomas no script. Adicionar: +```php +$menu['menu_item_sec_idiomas'] = section_header('Idiomas', 'dashicons-translation'); +$menu[branda_id('mlang')] = native_item(); // Polylang +$menu[branda_id('loco')] = native_item(); // Loco Translate +``` + +### Sites WooCommerce + +Adicionar seccao e-Commerce entre Marketing e Idiomas: +```php +$menu['menu_item_sec_ecommerce'] = section_header('e-Commerce', 'dashicons-cart'); +$menu[branda_id('woocommerce')] = native_item(); +``` + +### Sites Care (KiviCare) + +Adicionar seccao Clinica entre Marketing e Idiomas: +```php +$menu['menu_item_sec_clinica'] = section_header('Clinica', 'dashicons-heart'); +$menu[branda_id('kivicare-...')] = native_item(); // Verificar slug exacto +``` + +### CPTs customizados + +Adicionar na seccao Conteudo, antes de Artigos: +```php +$menu[branda_id('edit.php?post_type=SLUG_CPT')] = native_item(); +``` + +### Itens desconhecidos + +Se o menu nativo tiver itens que nao encaixam no mapeamento standard: +1. Perguntar ao utilizador onde colocar +2. Se plugin temporario/teste: adicionar ao Hidden +3. Se plugin permanente: criar seccao propria ou adicionar a seccao existente diff --git a/wordpress/skills/crocoblock/SKILL.md b/wordpress/skills/crocoblock/SKILL.md index edebb1d..53aacd6 100644 --- a/wordpress/skills/crocoblock/SKILL.md +++ b/wordpress/skills/crocoblock/SKILL.md @@ -1,22 +1,6 @@ --- name: crocoblock -description: > - Crocoblock ecosystem development with all JetPlugins for Elementor. Covers plugin selection, licensing, installation, - configuration and integration between JetEngine, JetSmartFilters, JetWooBuilder, JetElements, JetPopup, JetFormBuilder, - JetTabs, JetBlocks, JetSearch, JetBooking, JetThemeCore, JetReviews, JetTricks, JetCompareWishlist. - This skill should be used when the user asks about "crocoblock", "jet plugins", "jetelements", "jetwoobuilder", - "jetpopup", "jetsmartfilters", "jettabs", "jetformbuilder", "jetblocks", "jetbooking", "jetreviews", - "jetthemecore", "crocoblock license", "instalar crocoblock", "activar jet plugins", "ecosystem crocoblock", - "crocoblock subscription", "jet plugin escolher", "qual jet plugin usar", "crocoblock vs", "filtros ajax elementor", - "listing woocommerce elementor", "popup elementor crocoblock", "booking elementor", "reviews elementor". -author: Descomplicar® Crescimento Digital -version: 1.0.0 -user_invocable: true -tags: [wordpress, elementor, crocoblock, jetengine, jetelements, jetsmartfilters, jetformbuilder] -allowed-tools: Read, Write, Edit, Bash, mcp__ssh-unified__ssh_execute, mcp__notebooklm__notebook_query, mcp__dify-kb__dify_kb_retrieve_segments -category: dev -quality_score: 80 -updated: "2026-02-18T00:00:00Z" +description: Desenvolvimento com o ecossistema Crocoblock e todos os JetPlugins para Elementor. Cobre selecção, licenciamento, instalação, configuração e integração entre JetEngine, JetSmartFilters, JetWooBuilder, JetElements, JetPopup, JetFormBuilder e mais. --- # /crocoblock — Ecossistema Crocoblock + JetPlugins diff --git a/wordpress/skills/elementor/SKILL.md b/wordpress/skills/elementor/SKILL.md index 24be5a8..3c83ce5 100644 --- a/wordpress/skills/elementor/SKILL.md +++ b/wordpress/skills/elementor/SKILL.md @@ -1,22 +1,6 @@ --- name: elementor -description: > - Advanced development with Elementor Pro and Crocoblock ecosystem. Creates custom widgets, configures Theme Builder, develops with JetEngine, JetWooBuilder, optimizes performance and troubleshoots issues. - Also covers programmatic automation: deploy pipelines, kit import, replace-urls, flush-css, MySQL manipulation of _elementor_data, REST API endpoints, Dynamic Tags, CSS cache invalidation. - Use when building Elementor sites, creating custom widgets, configuring theme templates, developing with Crocoblock, or when user mentions - "elementor", "custom widget", "theme builder", "jetengine", "crocoblock", "jetwoobuilder", "page builder", "elementor pro", - "deploy elementor", "pipeline elementor", "elementor kit import", "elementor replace-urls", "elementor flush-css", - "automação elementor", "elementor programático", "elementor mysql", "rebranding elementor", "elementor rest api", - "elementor dynamic tag", "elementor cache", "elementor agente ia", "elementor wp-cli". -author: Descomplicar® Crescimento Digital -version: 1.2.0 -user_invocable: true -tags: [wordpress, elementor, pagebuilder, crocoblock, jetengine, widgets, automation, wpcli] -desk_task: 1478 -allowed-tools: Read, Write, Edit, Bash, mcp__ssh-unified__ssh_execute, mcp__notebooklm__notebook_query, mcp__dify-kb__dify_kb_retrieve_segments -category: dev -quality_score: 80 -updated: "2026-02-18T00:00:00Z" +description: Desenvolvimento avançado com Elementor Pro e ecossistema Crocoblock. Cria widgets custom, configura Theme Builder, automatiza deploys, manipula _elementor_data via MySQL, REST API, Dynamic Tags e cache CSS. --- # /elementor - Elementor Development @@ -31,6 +15,25 @@ Desenvolvimento avançado com Elementor Pro e Crocoblock. - Optimizar performance Elementor - Troubleshooting Elementor +## Contexto NotebookLM + +ANTES de executar, consultar notebooks para contexto especializado: + +| Notebook | ID | Consultar quando | +|----------|-----|-----------------| +| WordPress e Elementor | 5be0d1a6 | Sempre | + +``` +mcp__notebooklm__notebook_query({ + notebook_id: "5be0d1a6-00f2-4cd9-b835-978cb7721601", + query: "" +}) +``` + +Integrar insights do NotebookLM nas recomendações e decisões. + +--- + ## Estrutura Custom Widget ```php diff --git a/wordpress/skills/jetengine/SKILL.md b/wordpress/skills/jetengine/SKILL.md index 4419fd3..96da571 100644 --- a/wordpress/skills/jetengine/SKILL.md +++ b/wordpress/skills/jetengine/SKILL.md @@ -1,23 +1,6 @@ --- name: jetengine -description: > - JetEngine development: Custom Post Types (CPT), Custom Content Types (CCT), Meta Boxes, Taxonomies, - Relations, Query Builder, Listing Grid, Listing Map, Dynamic Content, Dynamic Tags, Macros, Profile Builder, - REST API, and headless/programmatic automation for AI agents and n8n integration. - This skill should be used when the user asks about "jetengine", "jet engine", "custom post type jetengine", - "meta box jetengine", "relations jetengine", "query builder jetengine", "listing grid", "listing map", - "jetengine dynamic content", "jetengine macros", "profile builder jetengine", "cct jetengine", - "custom content type", "jetengine cct", "jetengine rest api", "jetengine n8n", "jetengine sql", - "jetengine automação", "jetengine headless", "wp_jet_rel_default", "wp_jet_cct", "jetengine relations", - "conteúdo dinâmico elementor jetengine", "jetengine filtros", "jetengine repeater". -author: Descomplicar® Crescimento Digital -version: 1.0.0 -user_invocable: true -tags: [wordpress, elementor, crocoblock, jetengine, cpt, cct, listings, dynamic-content] -allowed-tools: Read, Write, Edit, Bash, mcp__ssh-unified__ssh_execute, mcp__notebooklm__notebook_query, mcp__dify-kb__dify_kb_retrieve_segments -category: dev -quality_score: 85 -updated: "2026-02-18T00:00:00Z" +description: Desenvolvimento com JetEngine (Crocoblock). Cobre CPT, CCT, Meta Boxes, Taxonomias, Relations, Query Builder, Listing Grid/Map, Dynamic Content, Dynamic Tags, Macros, Profile Builder, REST API e automação headless. --- # /jetengine — JetEngine Development diff --git a/wordpress/skills/rank-math/SKILL.md b/wordpress/skills/rank-math/SKILL.md index 856ff47..cb6e576 100644 --- a/wordpress/skills/rank-math/SKILL.md +++ b/wordpress/skills/rank-math/SKILL.md @@ -1,15 +1,6 @@ --- name: rank-math -description: This skill should be used when the user asks to "optimizar SEO wordpress", - "rank math wp-cli", "configurar rank math", "audit rank math", "update meta SEO", - "schema markup wordpress", "redirects rank math", "sitemap wordpress", "bulk SEO update", - "rank math CWP", "titles meta descriptions wp-cli", "configurar sitemap wordpress", - "noindex wordpress", "rank math robots". Manages Rank Math SEO plugin via WP-CLI - on CWP servers. -author: Descomplicar® Crescimento Digital -version: 1.0.0 -quality_score: 80 -user_invocable: true +description: Gestão do plugin Rank Math SEO via WP-CLI em servidores CWP. Cobre auditoria SEO, configuração em massa de títulos e meta descriptions, schema markup, redirects e sitemaps. --- # /rank-math - Gestão Rank Math SEO via WP-CLI @@ -22,6 +13,31 @@ Operações de SEO WordPress via WP-CLI no servidor CWP (server.descomplicar.pt) --- +## Contexto NotebookLM + +ANTES de executar, consultar notebooks para contexto especializado: + +| Notebook | ID | Consultar quando | +|----------|-----|-----------------| +| WordPress e Elementor | 5be0d1a6 | Sempre | +| Marketing Digital PT | 4c595973 | Para contexto SEO | + +``` +mcp__notebooklm__notebook_query({ + notebook_id: "5be0d1a6-00f2-4cd9-b835-978cb7721601", + query: "" +}) + +mcp__notebooklm__notebook_query({ + notebook_id: "4c595973-ba10-420a-a3bf-e4389e424ad3", + query: "" +}) +``` + +Integrar insights do NotebookLM nas recomendações e decisões. + +--- + ## Uso ``` diff --git a/wordpress/skills/woocommerce-cli/SKILL.md b/wordpress/skills/woocommerce-cli/SKILL.md index bf3c159..35c798a 100644 --- a/wordpress/skills/woocommerce-cli/SKILL.md +++ b/wordpress/skills/woocommerce-cli/SKILL.md @@ -1,18 +1,6 @@ --- name: woocommerce-cli -description: This skill should be used when the user asks to "gerir woocommerce linha de - comandos", "woocommerce wp-cli", "criar produto woocommerce cli", "actualizar stock - woocommerce cli", "gerir encomendas woocommerce cli", "importar produtos woocommerce", - "exportar produtos woocommerce", "configurar shipping woocommerce cli", "payment gateway - woocommerce cli", "limpar cache woocommerce cli", "bulk update woocommerce", "woocommerce - cwp", "wc cli cwp", "wp wc product", "wp wc shop_order", "configurar woocommerce servidor", - "scripting woocommerce", "automacao woocommerce cli". WooCommerce management via WP-CLI - on CWP server (server.descomplicar.pt) covering products, orders, customers, shipping, - payments, and automation. -author: Descomplicar® Crescimento Digital -version: 1.0.0 -quality_score: 80 -user_invocable: true +description: Gestão WooCommerce via WP-CLI no servidor CWP. Cobre produtos, encomendas, clientes, shipping, gateways de pagamento, importação/exportação em massa e automação. --- # /woocommerce-cli — WooCommerce via WP-CLI no CWP diff --git a/wordpress/skills/woocommerce/SKILL.md b/wordpress/skills/woocommerce/SKILL.md index 3c14e9c..7e32649 100644 --- a/wordpress/skills/woocommerce/SKILL.md +++ b/wordpress/skills/woocommerce/SKILL.md @@ -1,18 +1,6 @@ --- name: woocommerce -description: > - WooCommerce store development and optimization. Customizes checkout, integrates Portuguese payment gateways (Multibanco, MB Way, IfthenPay), develops custom features and optimizes performance. - Use when developing WooCommerce stores, customizing checkout, integrating payments, optimizing ecommerce performance, or when user mentions - "woocommerce", "checkout", "payment gateway", "multibanco", "mb way", "ifthen pay", "ecommerce", "online store", "shop optimization". -author: Descomplicar® Crescimento Digital -version: 1.1.0 -user_invocable: true -tags: [wordpress, woocommerce, ecommerce, checkout, payments, multibanco] -desk_task: 1479 -allowed-tools: Read, Write, Edit, Bash, mcp__ssh-unified__ssh_execute, mcp__notebooklm__notebook_query, mcp__dify-kb__dify_kb_retrieve_segments -category: dev -quality_score: 75 -updated: "2026-02-04T18:00:00Z" +description: Desenvolvimento e optimização de lojas WooCommerce. Personalização de checkout, integração de gateways de pagamento portugueses (Multibanco, MB Way, IfthenPay), funcionalidades custom e performance. --- # /woocommerce - WooCommerce Development @@ -27,6 +15,34 @@ Desenvolvimento e optimização de lojas WooCommerce. - Desenvolver funcionalidades custom - Optimizar performance +## Contexto NotebookLM + +ANTES de executar, consultar notebooks para contexto especializado: + +| Notebook | ID | Consultar quando | +|----------|-----|-----------------| +| WordPress e Elementor | 5be0d1a6 | Sempre | +| E-commerce Prático | 226e384e | Para estratégia e-commerce | + +``` +mcp__notebooklm__notebook_query({ + notebook_id: "5be0d1a6-00f2-4cd9-b835-978cb7721601", + query: "" +}) + +mcp__notebooklm__notebook_query({ + notebook_id: "226e384e-d4bc-48f4-bb82-7927360436cc", + query: "" +}) +``` + +Integrar insights do NotebookLM nas recomendações e decisões. + +### Procedimentos Relacionados +- `PROC-WiP-Starter-Template.md` — Template inicial para lojas WooCommerce + +--- + ## Hooks WooCommerce Essenciais ### Actions diff --git a/wordpress/skills/wp-cli/SKILL.md b/wordpress/skills/wp-cli/SKILL.md index c5b164c..3696269 100644 --- a/wordpress/skills/wp-cli/SKILL.md +++ b/wordpress/skills/wp-cli/SKILL.md @@ -1,16 +1,6 @@ --- name: wp-cli -description: This skill should be used when the user asks to "wp-cli cwp", "gerir - wordpress linha de comandos", "actualizar plugins wp-cli", "backup wordpress cli", - "migrar site wordpress", "search replace wordpress", "criar utilizador wordpress cli", - "wp-cli no servidor", "wp-cli allow-root", "comandos wordpress server", - "actualizar wordpress servidor", "modo manutencao wordpress", "wp db export", - "wp plugin update server", "wp core update cwp". WP-CLI management on CWP server - (server.descomplicar.pt) with multi-PHP support. -author: Descomplicar® Crescimento Digital -version: 1.0.0 -quality_score: 80 -user_invocable: true +description: Gestão WordPress via WP-CLI no servidor CWP. Cobre core, plugins, temas, base de dados, utilizadores, migração, search-replace e automação com suporte multi-PHP. --- # /wp-cli - Gestão WordPress via WP-CLI no CWP diff --git a/wordpress/skills/wp-dev/SKILL.md b/wordpress/skills/wp-dev/SKILL.md index 4cabc91..c55aafa 100644 --- a/wordpress/skills/wp-dev/SKILL.md +++ b/wordpress/skills/wp-dev/SKILL.md @@ -1,57 +1,6 @@ --- name: wp-dev -description: > - Desenvolvimento WordPress especializado com Quality Gate 70+. Cria/modifica plugins seguindo WordPress Coding Standards, desenvolve temas child, integra WooCommerce, resolve problemas WordPress. Consulta obrigatória de datasets Dify (Wordpress, Elementor, Crocoblock). Use when developing WordPress plugins, creating themes, integrating WooCommerce, solving WordPress issues, or when user mentions "wordpress", "plugin", "woocommerce", "elementor", "crocoblock", "jetengine". -author: Descomplicar® Crescimento Digital -version: 1.1.0 -quality_score: 100 -user_invocable: true -category: dev -tags: [wordpress, plugins, temas, woocommerce, elementor, crocoblock, development, quality-gate, wpcs] -desk_task: 1488 -desk_project: 65 -allowed-tools: Read, Write, Edit, Bash, mcp__dify-kb, mcp__memory-supabase, mcp__wikijs -mcps: dify-kb, memory-supabase, wikijs -datasets: - - id: 9da0b2b9-5051-4b99-b9f6-20bf35067092 - name: Wordpress - priority: 1 - - id: 9c77d3e2-4d88-4a43-abff-d4e681267cc7 - name: Elementor - priority: 1 - - id: 139cdf67-afce-46ec-9ccd-2a06040e5b9d - name: Crocooblock - priority: 1 - - id: bdf85c26-1824-4021-92d1-be20501b35ac - name: Crocoblock - priority: 1 - - id: 2e9b7c48-c630-457a-83a0-db8e77f76eae - name: Kivicare - priority: 2 - - id: c8489151-de94-42b2-8cee-c0b961cfac6d - name: Desenvolvimento de WebSites - priority: 2 -dependencies: - mcps: [dify-kb, memory-supabase] -triggers: - - "User mentions 'wordpress', 'plugin', 'wp'" - - "User asks to create/modify WordPress plugin" - - "User mentions 'woocommerce', 'elementor', 'jetengine'" - - "Developing WordPress themes or child themes" -quality_gate: - enabled: true - minimum_score: 70 - checks: - - WordPress Coding Standards (WPCS) - - PHPDoc documentation - - Hooks and filters structure - - No PHP warnings/notices - - Security: nonces, sanitization, escaping -performance: - baseline_duration_ms: 14400000 - target_duration_ms: 7200000 - last_run_duration_ms: null - success_rate: 0.90 +description: Desenvolvimento WordPress especializado com Quality Gate 70+. Cria e modifica plugins seguindo WordPress Coding Standards, desenvolve temas child, integra WooCommerce e resolve problemas WordPress. --- # WordPress Plugin Developer @@ -72,6 +21,34 @@ Skill para desenvolvimento WordPress profissional seguindo padrões Descomplicar - Para operações servidor/SSH genéricas (usar agente especializado) - Para manutenção rotineira WP (usar /today às segundas) +## Contexto NotebookLM + +ANTES de executar, consultar notebooks para contexto especializado: + +| Notebook | ID | Consultar quando | +|----------|-----|-----------------| +| WordPress e Elementor | 5be0d1a6 | Sempre | +| WordPress Config CLI | fb2f26bd-8cb0-4d4c-bafc-4f1ebb51c51d | Para WP-CLI e configuração | + +``` +mcp__notebooklm__notebook_query({ + notebook_id: "5be0d1a6-00f2-4cd9-b835-978cb7721601", + query: "" +}) + +mcp__notebooklm__notebook_query({ + notebook_id: "fb2f26bd-8cb0-4d4c-bafc-4f1ebb51c51d", + query: "" +}) +``` + +Integrar insights do NotebookLM nas recomendações e decisões. + +### Procedimentos Relacionados +- `PROC-WiP-Definicao.md` — Definição de projectos WordPress in a Package +- `PROC-WiP-Instalacao.md` — Instalação e configuração WiP +- `PROC-WiP-Gestao.md` — Gestão e manutenção WiP + --- ## Protocolo Obrigatório @@ -286,6 +263,35 @@ find /path -type f -exec chmod 644 {} \; chmod 600 wp-config.php ``` +### 5. Páginas com shortcodes React/Vite + +Páginas que usam shortcodes para renderizar componentes React (ex: `[react-app]`, `[vite-app]`, `[app-root]`) **nunca devem ser editadas via editor wp-admin** (Gutenberg ou Classic). O editor pode: +- Adicionar `

` e `
` indesejados à volta do shortcode +- Remover atributos ou alterar aspas +- Quebrar a montagem do componente React no DOM + +**Procedimento correcto:** + +```bash +# Ver conteúdo actual da página +wp post get --field=content --ssh= + +# Editar conteúdo via WP-CLI +wp post update --post_content='[react-app id="main"]' --ssh= + +# Ou via SQL directo (quando WP-CLI não é suficiente) +UPDATE wp_posts SET post_content = '[react-app id="main"]' WHERE ID = ; +``` + +**Identificar páginas afectadas:** + +```bash +# Listar páginas com shortcodes React/Vite +wp post list --post_type=page --fields=ID,post_title,post_content --format=csv --ssh= | grep -iE '\[(react|vite|app)' +``` + +**Regra:** Ao criar ou manter plugins que registam shortcodes para aplicações React/Vite, documentar no `readme.txt` do plugin que as páginas associadas devem ser editadas exclusivamente via WP-CLI ou BD. + ## Datasets Dify (Consulta Obrigatória) Em caso de dúvidas ou para aprofundar conhecimento, consultar os seguintes datasets via MCP: @@ -401,4 +407,4 @@ INSERT INTO tblskill_agent_metrics ( --- -**Versão**: 1.1.0 | **Data**: 2026-02-03 | **Instrumentação**: Activa +**Versão**: 1.2.0 | **Data**: 2026-03-12 | **Instrumentação**: Activa diff --git a/wordpress/skills/wp-hardening/SKILL.md b/wordpress/skills/wp-hardening/SKILL.md new file mode 100644 index 0000000..a1fcdd6 --- /dev/null +++ b/wordpress/skills/wp-hardening/SKILL.md @@ -0,0 +1,356 @@ +--- +name: wp-hardening +description: Aplicar hardening de seguranca standard a sites WordPress via SSH. Desactiva XML-RPC, file editing, directory listing, esconde versao WP, verifica permissoes e security headers. +--- + +# /wp-hardening - Hardening WordPress + +Aplica medidas de hardening standard a sites WordPress no servidor CWP (176.9.3.158). + +> **Nota:** Esta skill APLICA alteracoes. Para auditar sem alterar, usar `/security-check`. + +## Contexto NotebookLM + +ANTES de executar, consultar notebook para contexto: + +| Notebook | ID | Consultar quando | +|----------|-----|-----------------| +| WordPress e Elementor | 5be0d1a6 | Sempre | + +``` +mcp__notebooklm__notebook_query({ + notebook_id: "5be0d1a6-00f2-4cd9-b835-978cb7721601", + query: "wordpress security hardening best practices" +}) +``` + +--- + +## Uso + +``` +/wp-hardening descomplicar.pt +/wp-hardening all # todos os 16 sites +/wp-hardening descomplicar.pt --dry # apenas verificar, sem aplicar +``` + +**Argumento:** dominio do site (ver tabela de sites em /wp-update) ou `all`. +**Flag `--dry`:** apenas verifica estado actual sem aplicar alteracoes. + +--- + +## Sites WordPress no servidor + +| Conta | Site | Path | +|-------|------|------| +| carstuff | carstuff.pt | /home/carstuff/public_html | +| ealmeida | descomplicar.pt | /home/ealmeida/public_html | +| ealmeida | emanuelalmeida.pt | /home/ealmeida/emanuelalmeida.pt | +| ealmeida | ecommerce.descomplicar.pt | /home/ealmeida/ecommerce.descomplicar.pt | +| ealmeida | ecommerce-demo.descomplicar.pt | /home/ealmeida/ecommerce-demo.descomplicar.pt | +| ealmeida | starter.descomplicar.pt | /home/ealmeida/starter.descomplicar.pt | +| ealmeida | care.descomplicar.pt | /home/ealmeida/care.descomplicar.pt | +| ealmeida | e-commerce.descomplicar.pt | /home/ealmeida/e-commerce.descomplicar.pt | +| espiral | espiralsenior.pt | /home/espiral/public_html | +| espiral | dev.espiralsenior.pt | /home/espiral/dev.espiralsenior.pt | +| familycl | familyclinic.pt | /home/familycl/public_html | +| ignition | ignitionvortex.pt | /home/ignition/public_html | +| karate | karateclubedegaia.com | /home/karate/karateclubedegaia.com | +| sintri | sintricare.com.pt | /home/sintri/public_html | +| solarfv | solarfvengenharia.com | /home/solarfv/public_html | +| wtc | watercontrol.pt | /home/wtc/public_html | + +--- + +## Execucao + +### Passo 0: Identificar site e path + +Mapear o dominio fornecido para o path e conta do servidor usando a tabela acima. + +```bash +SITE="dominio.pt" +WP_PATH="/home/USER/public_html" +WP_USER="user" +``` + +### Passo 1: Verificar estado actual (antes) + +Executar via `mcp__ssh-unified__ssh_execute` no servidor `cwp`: + +```bash +# 1. XML-RPC activo? +curl -s -o /dev/null -w "%{http_code}" -X POST "${SITE}/xmlrpc.php" -d 'system.listMethods' + +# 2. DISALLOW_FILE_EDIT definido? +grep -c "DISALLOW_FILE_EDIT" ${WP_PATH}/wp-config.php + +# 3. Permissoes directórios (esperado: 755) +find ${WP_PATH} -type d -not -perm 755 | head -10 + +# 4. Permissoes ficheiros (esperado: 644) +find ${WP_PATH} -type f -not -perm 644 -not -name "wp-config.php" | head -10 + +# 5. Versao WP exposta no HTML? +curl -s ${SITE} | grep -o 'content="WordPress [0-9.]*"' | head -1 + +# 6. Versao WP exposta no feed? +curl -s ${SITE}/feed/ | grep -o '.*' | head -1 + +# 7. Directory listing activo? +curl -s -o /dev/null -w "%{http_code}" ${SITE}/wp-content/uploads/ + +# 8. wp-config.php permissoes (esperado: 400 ou 440) +stat -c "%a" ${WP_PATH}/wp-config.php + +# 9. .htaccess security headers? +grep -c "X-Frame-Options\|X-Content-Type-Options\|X-XSS-Protection\|Referrer-Policy\|Content-Security-Policy\|Strict-Transport-Security" ${WP_PATH}/.htaccess 2>/dev/null + +# 10. debug.log exposto? +test -f ${WP_PATH}/wp-content/debug.log && echo "EXPOSTO" || echo "OK" +``` + +Registar cada resultado como ANTES. + +### Passo 2: Aplicar hardening (se nao --dry) + +> **Regra:** Fazer backup de cada ficheiro ANTES de alterar. + +#### 2.1 Desactivar XML-RPC + +```bash +# Backup .htaccess +cp ${WP_PATH}/.htaccess ${WP_PATH}/.htaccess.bak.$(date +%Y%m%d) + +# Adicionar bloqueio XML-RPC ao .htaccess (antes de # BEGIN WordPress) +sed -i '/# BEGIN WordPress/i \ +# BEGIN Block XML-RPC\ +\ + Require all denied\ +\ +# END Block XML-RPC\ +' ${WP_PATH}/.htaccess +``` + +**Excepcao:** Se o site usa JetPack ou aplicacao mobile WP, NAO desactivar XML-RPC. Verificar primeiro: +```bash +sudo -u ${WP_USER} wp plugin list --status=active --path=${WP_PATH} | grep -i "jetpack" +``` + +#### 2.2 Desactivar file editing (DISALLOW_FILE_EDIT) + +```bash +# Backup wp-config.php +cp ${WP_PATH}/wp-config.php ${WP_PATH}/wp-config.php.bak.$(date +%Y%m%d) + +# Adicionar se nao existir +grep -q "DISALLOW_FILE_EDIT" ${WP_PATH}/wp-config.php || \ + sed -i "/\/\* That's all, stop editing/i define('DISALLOW_FILE_EDIT', true);" ${WP_PATH}/wp-config.php +``` + +#### 2.3 Corrigir permissoes + +```bash +# Directorios: 755 +find ${WP_PATH} -type d -exec chmod 755 {} \; + +# Ficheiros: 644 +find ${WP_PATH} -type f -exec chmod 644 {} \; + +# wp-config.php: 440 (leitura apenas para owner e grupo) +chmod 440 ${WP_PATH}/wp-config.php + +# Corrigir ownership +chown -R ${WP_USER}:${WP_USER} ${WP_PATH} +``` + +#### 2.4 Esconder versao WordPress + +```bash +# Adicionar ao functions.php do tema activo (via wp-cli) +THEME_PATH=$(sudo -u ${WP_USER} wp theme path --path=${WP_PATH})/$(sudo -u ${WP_USER} wp theme list --status=active --field=name --path=${WP_PATH}) + +# Verificar se ja tem o filtro +grep -q "remove_action.*wp_head.*wp_generator" ${THEME_PATH}/functions.php 2>/dev/null +if [ $? -ne 0 ]; then + # Alternativa robusta: usar mu-plugin (nao se perde em updates de tema) + mkdir -p ${WP_PATH}/wp-content/mu-plugins + cat > ${WP_PATH}/wp-content/mu-plugins/dsc-hardening.php << 'MUEOF' +> ${WP_PATH}/.htaccess << 'HTEOF' + +# BEGIN Security Headers + + Header always set X-Frame-Options "SAMEORIGIN" + Header always set X-Content-Type-Options "nosniff" + Header always set X-XSS-Protection "1; mode=block" + Header always set Referrer-Policy "strict-origin-when-cross-origin" + Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()" + Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" + +# END Security Headers +HTEOF +fi +``` + +#### 2.7 Proteger debug.log + +```bash +# Se debug.log existe, bloquear acesso +if [ -f "${WP_PATH}/wp-content/debug.log" ]; then + cat >> ${WP_PATH}/wp-content/.htaccess << 'DLEOF' + + Require all denied + +DLEOF +fi + +# Desactivar WP_DEBUG se estiver activo em producao +grep -q "define.*WP_DEBUG.*true" ${WP_PATH}/wp-config.php && \ + sed -i "s/define.*'WP_DEBUG'.*true.*/define('WP_DEBUG', false);/" ${WP_PATH}/wp-config.php +``` + +### Passo 3: Verificar estado (depois) + +Re-executar todos os testes do Passo 1 e registar como DEPOIS. + +### Passo 4: Verificar site funcional + +```bash +# Verificar que o site responde correctamente +HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" https://${SITE}) +echo "HTTP: ${HTTP_CODE}" + +# Verificar conteudo por erros criticos +curl -s https://${SITE} | grep -i "critical error\|fatal error\|error establishing" | head -3 +``` + +**Se o site reportar erro apos hardening:** reverter imediatamente usando os backups (.bak). + +### Passo 5: Corrigir ownership final + +```bash +chown -R ${WP_USER}:${WP_USER} ${WP_PATH} +``` + +--- + +## Output Template + +```markdown +# WP Hardening Report - [site.pt] + +**Data:** YYYY-MM-DD +**Modo:** Aplicado / Dry Run + +--- + +## Checklist Hardening + +| # | Item | Antes | Depois | Accao | +|---|------|-------|--------|-------| +| 1 | XML-RPC desactivado | / | / | .htaccess + mu-plugin | +| 2 | File editing desactivado | / | / | wp-config.php | +| 3 | Permissoes dirs (755) | / | / | chmod recursivo | +| 4 | Permissoes ficheiros (644) | / | / | chmod recursivo | +| 5 | Versao WP escondida | / | / | mu-plugin | +| 6 | Directory listing desactivado | / | / | .htaccess | +| 7 | Security headers | / | / | .htaccess | +| 8 | wp-config.php (440) | / | / | chmod | +| 9 | debug.log protegido | / | / | .htaccess | +| 10 | WP_DEBUG desactivado | / | / | wp-config.php | + +--- + +## Ficheiros alterados + +- `wp-config.php` (DISALLOW_FILE_EDIT, WP_DEBUG) +- `.htaccess` (XML-RPC, directory listing, security headers) +- `wp-content/mu-plugins/dsc-hardening.php` (criado) + +## Backups criados + +- `.htaccess.bak.YYYYMMDD` +- `wp-config.php.bak.YYYYMMDD` + +## Verificacao pos-hardening + +- HTTP: [200/301/etc] +- Erros criticos: [Nenhum / Lista] + +--- + +*Gerado via /wp-hardening v1.0.0 - YYYY-MM-DD* +``` + +--- + +## Notas importantes + +1. **Backups obrigatorios** antes de qualquer alteracao +2. **mu-plugin** preferido sobre functions.php (sobrevive a updates de tema) +3. **JetPack** requer XML-RPC — verificar SEMPRE antes de desactivar +4. **Content-Security-Policy** nao incluido como header standard porque varia por site. Adicionar manualmente se necessario +5. **Reverter:** os backups `.bak.YYYYMMDD` permitem rollback rapido +6. **Ownership:** SEMPRE `chown -R USER:USER` no final (regra #11) + +--- + +## Changelog + +### v1.0.0 (2026-03-12) +- Versao inicial +- 10 verificacoes de hardening +- Modo dry run (--dry) +- mu-plugin dsc-hardening.php para medidas PHP +- Security headers standard no .htaccess +- Backup automatico antes de alteracoes +- Verificacao pos-hardening com rollback +- Tarefa Desk CRM #443 (Projecto #65, Discussao #33) diff --git a/wordpress/skills/wp-performance/SKILL.md b/wordpress/skills/wp-performance/SKILL.md index 99e0a9c..037eb5e 100644 --- a/wordpress/skills/wp-performance/SKILL.md +++ b/wordpress/skills/wp-performance/SKILL.md @@ -1,19 +1,32 @@ --- name: wp-performance -description: WordPress performance optimization. Analyzes and improves site speed, - caching, database, and assets. Use when user mentions "wordpress performance", "wp - speed", "optimize wordpress", "wordpress slow", "site performance". -author: Descomplicar® Crescimento Digital -version: 1.0.0 -quality_score: 75 -user_invocable: true -desk_task: 1489 +description: Auditoria e optimização de performance WordPress. Analisa velocidade, caching, base de dados e assets. Usa Lighthouse, métricas Core Web Vitals e checklist sistemático. --- # /wp-performance - Auditoria Performance WordPress Checklist sistemático para auditar e optimizar performance de sites WordPress. +## Contexto NotebookLM + +ANTES de executar, consultar notebooks para contexto especializado: + +| Notebook | ID | Consultar quando | +|----------|-----|-----------------| +| WordPress e Elementor | 5be0d1a6 | Sempre | + +``` +mcp__notebooklm__notebook_query({ + notebook_id: "5be0d1a6-00f2-4cd9-b835-978cb7721601", + query: "" +}) +``` + +Integrar insights do NotebookLM nas recomendações e decisões. + +### Procedimentos Relacionados +- `PROC-WordPress-Performance-Standard.md` — Standards de performance WP + --- ## Uso diff --git a/wordpress/skills/wp-translate/SKILL.md b/wordpress/skills/wp-translate/SKILL.md index 4c1d818..ae111a6 100644 --- a/wordpress/skills/wp-translate/SKILL.md +++ b/wordpress/skills/wp-translate/SKILL.md @@ -1,17 +1,6 @@ --- name: wp-translate -description: > - Tradução WordPress PT-PT com DeepL Pro, glossário e scripts próprios. Use when translating WordPress plugins to PT-PT, fixing PT-BR translations, handling .po/.mo/.json files, working with Loco Translate, deploying translations to starter.descomplicar.pt, or when user mentions "tradução", "translate", "pt-pt", "pt-br", ".po", ".mo", "loco", "deepl wordpress". -author: Descomplicar® Crescimento Digital -version: 1.0.0 -quality_score: 100 -user_invocable: true -category: wordpress -tags: [wordpress, traducao, pt-pt, deepl, po, mo, gettext, loco-translate, i18n] -desk_task: 1580 -desk_project: 65 -allowed-tools: Read, Write, Edit, Bash, mcp__ssh-unified, mcp__deepl, mcp__memory-supabase -mcps: ssh-unified, deepl, memory-supabase +description: Tradução de plugins WordPress para PT-PT com DeepL Pro, glossário próprio e scripts de automação. Gere ficheiros .po/.mo/.json, corrige traduções PT-BR e faz deploy para starter.descomplicar.pt. --- # /wp-translate — Traduções WordPress PT-PT diff --git a/wordpress/skills/wp-update/SKILL.md b/wordpress/skills/wp-update/SKILL.md index b92b646..161ed36 100644 --- a/wordpress/skills/wp-update/SKILL.md +++ b/wordpress/skills/wp-update/SKILL.md @@ -1,13 +1,7 @@ --- name: wp-update -description: WordPress core, plugins, and themes update management. Safely updates - WordPress components with backups. Use when user mentions "wordpress update", "wp - update", "update plugins", "update themes", "wordpress maintenance". -author: Descomplicar® Crescimento Digital -version: 1.2.0 -quality_score: 75 -user_invocable: true -desk_task: 1553 +description: Actualização segura de WordPress core, plugins e temas em todos os sites CWP. Inclui backups pré-actualização, verificação pós-actualização e relatório de estado. +disable-model-invocation: true --- # /wp-update - Actualização WordPress