Compare commits
21 Commits
6b3a6f2698
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| d3f9c950cd | |||
| b6690a75fd | |||
| b3cb108ca7 | |||
| dada9ef7db | |||
| 82063391dd | |||
| 940c3903aa | |||
| c534051774 | |||
| 1d0b2b5441 | |||
| 3115ff24a5 | |||
| a33c5e1b05 | |||
| 37f62eb733 | |||
| 2ec16674c2 | |||
| faef9b47dc | |||
| 6285be6c2e | |||
| 2252e1c29c | |||
| 19f89e0d69 | |||
| 19da1bed48 | |||
| 8bf46bcaf0 | |||
| b1d31ef152 | |||
| e2b086acbf | |||
| 24b0b68ed0 |
@@ -0,0 +1 @@
|
|||||||
|
design-media/skills/*/references/__pycache__/
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# Plugin: acidaos
|
||||||
|
|
||||||
|
Skills especializadas para desenvolvimento do **AcidaOS** — o sistema operativo de negócio para PMEs da Descomplicar®.
|
||||||
|
|
||||||
|
## Arquitectura
|
||||||
|
|
||||||
|
O AcidaOS usa uma arquitectura Hub-and-Spoke:
|
||||||
|
- **Core (Hub):** Rust + Axum — motor de orquestração de agentes, API gRPC/REST interna
|
||||||
|
- **Spokes:** Next.js/TypeScript — dashboards, UI, aplicações de negócio
|
||||||
|
|
||||||
|
## Skills disponíveis
|
||||||
|
|
||||||
|
| Skill | Trigger | Descrição |
|
||||||
|
|-------|---------|-----------|
|
||||||
|
| `acidaos:rust-dev` | `/rust-dev`, desenvolvimento Core | Desenvolvimento do Core em Rust (Axum, Tokio) |
|
||||||
|
| `acidaos:spoke-dev` | `/spoke-dev`, desenvolvimento Spokes | Aplicações Next.js e componentes React |
|
||||||
|
| `acidaos:devops` | `/acidaos-pipeline`, CI/CD | Pipelines Gitea Actions para o AcidaOS |
|
||||||
|
| `acidaos:docs` | `/acidaos-docs`, documentação técnica | Gerar documentação a partir do código |
|
||||||
|
|
||||||
|
## Referências
|
||||||
|
|
||||||
|
- Arquitectura: `Hub/01-Planeamento/AcidaOS/Relatorio_Arquitetura_Core.md`
|
||||||
|
- SPECs: `Hub/01-Planeamento/AcidaOS/acidaos-core/SPECs.md`
|
||||||
|
- Visão estratégica: `Hub/01-Planeamento/AcidaOS/AcidaOS_Visao-Estrategica.md`
|
||||||
|
- Repositório: Gitea `acidaos-core`, `acidaos-dashboard`
|
||||||
|
|
||||||
|
---
|
||||||
|
**Versão**: 1.0.0 | **Autor**: Descomplicar® | **Data**: 2026-03-12
|
||||||
@@ -0,0 +1,328 @@
|
|||||||
|
---
|
||||||
|
name: devops
|
||||||
|
description: CI/CD pipelines para o AcidaOS via Gitea Actions — build, test, deploy para acidaos-core (Rust) e acidaos-dashboard (Next.js). Usar quando "pipeline acidaos", "gitea actions acidaos", "ci cd acidaos", "deploy acidaos", "workflow acidaos".
|
||||||
|
allowed-tools: Read, Write, Edit, Bash, mcp__gitea__list_repo_action_workflows, mcp__gitea__get_repo_action_workflow, mcp__gitea__create_file, mcp__gitea__update_file, mcp__memory-supabase__search_memories
|
||||||
|
---
|
||||||
|
|
||||||
|
# AcidaOS DevOps — Gitea Actions
|
||||||
|
|
||||||
|
Skill para criar e gerir pipelines CI/CD do AcidaOS via **Gitea Actions**.
|
||||||
|
|
||||||
|
> **Atenção:** O AcidaOS usa **Gitea Actions**, não GitHub Actions. A sintaxe é compatível mas o runner é self-hosted em `gateway.descomplicar.pt`.
|
||||||
|
|
||||||
|
## Contexto
|
||||||
|
|
||||||
|
```
|
||||||
|
Repositórios Gitea:
|
||||||
|
acidaos-core → Rust Core
|
||||||
|
acidaos-dashboard → Next.js Dashboard
|
||||||
|
|
||||||
|
Runners:
|
||||||
|
self-hosted @ gateway.descomplicar.pt
|
||||||
|
Labels: [self-hosted, linux, rust, node]
|
||||||
|
|
||||||
|
Deploy target:
|
||||||
|
EasyPanel (projectName: "descomplicar")
|
||||||
|
acidaos-core → serviceName: "acidaos-core"
|
||||||
|
acidaos-dashboard → serviceName: "acidaos-dashboard"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Protocolo Inicial
|
||||||
|
|
||||||
|
```
|
||||||
|
mcp__memory-supabase__search_memories "acidaos devops pipeline"
|
||||||
|
mcp__gitea__list_repo_action_workflows <repo> # ver workflows existentes
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Pipelines Disponíveis
|
||||||
|
|
||||||
|
### 1. Core Rust — CI Pipeline
|
||||||
|
|
||||||
|
**Ficheiro:** `.gitea/workflows/ci.yml`
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: AcidaOS Core CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main, develop]
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check:
|
||||||
|
name: Verificar código
|
||||||
|
runs-on: [self-hosted, linux, rust]
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Cache Cargo
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cargo/registry
|
||||||
|
~/.cargo/git
|
||||||
|
target/
|
||||||
|
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||||
|
|
||||||
|
- name: Cargo check
|
||||||
|
run: cargo check --all-features
|
||||||
|
|
||||||
|
- name: Clippy
|
||||||
|
run: cargo clippy --all-features -- -D warnings
|
||||||
|
|
||||||
|
- name: Formatação
|
||||||
|
run: cargo fmt --all -- --check
|
||||||
|
|
||||||
|
test:
|
||||||
|
name: Testes
|
||||||
|
needs: check
|
||||||
|
runs-on: [self-hosted, linux, rust]
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Cache Cargo
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cargo/registry
|
||||||
|
~/.cargo/git
|
||||||
|
target/
|
||||||
|
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||||
|
|
||||||
|
- name: Testes unitários
|
||||||
|
run: cargo test --all-features
|
||||||
|
|
||||||
|
- name: Testes de integração
|
||||||
|
run: cargo test --test '*' --all-features
|
||||||
|
env:
|
||||||
|
ACIDAOS_ENV: test
|
||||||
|
DATABASE_URL: ${{ secrets.TEST_DATABASE_URL }}
|
||||||
|
|
||||||
|
security:
|
||||||
|
name: Auditoria de segurança
|
||||||
|
runs-on: [self-hosted, linux, rust]
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: cargo-audit
|
||||||
|
run: |
|
||||||
|
cargo install cargo-audit --quiet
|
||||||
|
cargo audit
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. Core Rust — Deploy Pipeline
|
||||||
|
|
||||||
|
**Ficheiro:** `.gitea/workflows/deploy.yml`
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: AcidaOS Core Deploy
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
tags: ['v*']
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
name: Deploy para EasyPanel
|
||||||
|
runs-on: [self-hosted, linux, rust]
|
||||||
|
environment: production
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Build release
|
||||||
|
run: cargo build --release
|
||||||
|
|
||||||
|
- name: Build Docker image
|
||||||
|
run: |
|
||||||
|
docker build \
|
||||||
|
-t acidaos-core:${{ gitea.sha }} \
|
||||||
|
-t acidaos-core:latest \
|
||||||
|
.
|
||||||
|
|
||||||
|
- name: Push para registry
|
||||||
|
run: |
|
||||||
|
docker tag acidaos-core:latest \
|
||||||
|
registry.descomplicar.pt/acidaos/core:latest
|
||||||
|
docker push registry.descomplicar.pt/acidaos/core:latest
|
||||||
|
env:
|
||||||
|
DOCKER_REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
|
|
||||||
|
- name: Deploy via EasyPanel API
|
||||||
|
run: |
|
||||||
|
curl -X POST \
|
||||||
|
"https://easypanel.descomplicar.pt/api/deploy" \
|
||||||
|
-H "Authorization: Bearer ${{ secrets.EASYPANEL_TOKEN }}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"projectName": "descomplicar",
|
||||||
|
"serviceName": "acidaos-core",
|
||||||
|
"image": "registry.descomplicar.pt/acidaos/core:latest"
|
||||||
|
}'
|
||||||
|
|
||||||
|
- name: Verificar health
|
||||||
|
run: |
|
||||||
|
sleep 10
|
||||||
|
curl -f http://acidaos-core.descomplicar.pt/health || exit 1
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3. Dashboard Next.js — CI Pipeline
|
||||||
|
|
||||||
|
**Ficheiro:** `.gitea/workflows/ci.yml` (no repo acidaos-dashboard)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: AcidaOS Dashboard CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main, develop]
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint-typecheck:
|
||||||
|
name: Lint e TypeCheck
|
||||||
|
runs-on: [self-hosted, linux, node]
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '20'
|
||||||
|
cache: 'pnpm'
|
||||||
|
|
||||||
|
- name: Instalar dependências
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
- name: TypeScript check
|
||||||
|
run: pnpm tsc --noEmit
|
||||||
|
|
||||||
|
- name: ESLint
|
||||||
|
run: pnpm lint
|
||||||
|
|
||||||
|
test:
|
||||||
|
name: Testes
|
||||||
|
needs: lint-typecheck
|
||||||
|
runs-on: [self-hosted, linux, node]
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '20'
|
||||||
|
cache: 'pnpm'
|
||||||
|
|
||||||
|
- name: Instalar dependências
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Testes unitários
|
||||||
|
run: pnpm test
|
||||||
|
|
||||||
|
- name: Build de verificação
|
||||||
|
run: pnpm build
|
||||||
|
env:
|
||||||
|
ACIDAOS_CORE_URL: http://localhost:3001
|
||||||
|
|
||||||
|
e2e:
|
||||||
|
name: Testes E2E
|
||||||
|
needs: test
|
||||||
|
runs-on: [self-hosted, linux, node]
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '20'
|
||||||
|
cache: 'pnpm'
|
||||||
|
|
||||||
|
- name: Instalar dependências
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Instalar Playwright
|
||||||
|
run: pnpm exec playwright install --with-deps chromium
|
||||||
|
|
||||||
|
- name: Testes E2E
|
||||||
|
run: pnpm test:e2e
|
||||||
|
env:
|
||||||
|
BASE_URL: http://localhost:3000
|
||||||
|
ACIDAOS_CORE_URL: http://localhost:3001
|
||||||
|
|
||||||
|
- name: Upload relatório E2E
|
||||||
|
if: failure()
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: playwright-report
|
||||||
|
path: playwright-report/
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Gestão via MCP Gitea
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Listar workflows de um repo
|
||||||
|
mcp__gitea__list_repo_action_workflows({ owner: "descomplicar", repo: "acidaos-core" })
|
||||||
|
|
||||||
|
// Ver runs recentes
|
||||||
|
mcp__gitea__list_repo_action_runs({ owner: "descomplicar", repo: "acidaos-core" })
|
||||||
|
|
||||||
|
// Desencadear workflow manualmente
|
||||||
|
mcp__gitea__dispatch_repo_action_workflow({
|
||||||
|
owner: "descomplicar",
|
||||||
|
repo: "acidaos-core",
|
||||||
|
workflow_id: "deploy.yml",
|
||||||
|
ref: "main"
|
||||||
|
})
|
||||||
|
|
||||||
|
// Ver logs de uma job
|
||||||
|
mcp__gitea__get_repo_action_job_log_preview({ owner: "descomplicar", repo: "acidaos-core", job_id: <id> })
|
||||||
|
```
|
||||||
|
|
||||||
|
## Segredos necessários (Gitea Secrets)
|
||||||
|
|
||||||
|
| Segredo | Usado em | Descrição |
|
||||||
|
|---------|----------|-----------|
|
||||||
|
| `TEST_DATABASE_URL` | Core CI | PostgreSQL de teste |
|
||||||
|
| `REGISTRY_TOKEN` | Core Deploy | Token registry Docker |
|
||||||
|
| `EASYPANEL_TOKEN` | Core/Dashboard Deploy | Token API EasyPanel |
|
||||||
|
|
||||||
|
## Checklist Pipeline Nova
|
||||||
|
|
||||||
|
- [ ] Workflow criado em `.gitea/workflows/`
|
||||||
|
- [ ] Runner labels correctas (`self-hosted, linux, rust` ou `node`)
|
||||||
|
- [ ] Cache Cargo/pnpm configurado
|
||||||
|
- [ ] Segredos referenciados (não hardcoded)
|
||||||
|
- [ ] Health check no deploy
|
||||||
|
- [ ] Tested com `mcp__gitea__dispatch_repo_action_workflow`
|
||||||
|
|
||||||
|
---
|
||||||
|
**Versão**: 1.0.0 | **Autor**: Descomplicar® | **Plugin**: acidaos
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
@@ -0,0 +1,203 @@
|
|||||||
|
---
|
||||||
|
name: docs
|
||||||
|
description: Gerar documentação técnica do AcidaOS a partir do código — Rust (rustdoc), TypeScript (TypeDoc), e publicar no Outline. Usar quando "documentação acidaos", "gerar docs", "rustdoc", "typedoc", "acidaos-docs", documentar código do projecto.
|
||||||
|
allowed-tools: Read, Write, Bash, mcp__gitea__get_file_content, mcp__gitea__get_dir_content, mcp__outline-api__create_document, mcp__outline-api__update_document, mcp__outline-api__search_documents, mcp__memory-supabase__search_memories
|
||||||
|
---
|
||||||
|
|
||||||
|
# AcidaOS Docs
|
||||||
|
|
||||||
|
Skill para gerar e publicar documentação técnica do AcidaOS.
|
||||||
|
|
||||||
|
## Estratégia de Documentação
|
||||||
|
|
||||||
|
| Camada | Ferramenta | Destino |
|
||||||
|
|--------|-----------|---------|
|
||||||
|
| API interna Rust | `rustdoc` + comentários `///` | `/docs` no repo |
|
||||||
|
| Componentes React | TypeDoc + Storybook | Storybook deployed |
|
||||||
|
| Arquitectura | Mermaid.js diagramas | Outline (Wiki) |
|
||||||
|
| Endpoints API | OpenAPI/Swagger | Outline (Wiki) |
|
||||||
|
| Decisões técnicas | ADRs em Markdown | Outline (Wiki) |
|
||||||
|
|
||||||
|
## Protocolo
|
||||||
|
|
||||||
|
```
|
||||||
|
mcp__memory-supabase__search_memories "acidaos documentação"
|
||||||
|
mcp__outline-api__search_documents "acidaos" # ver docs existentes
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Operações
|
||||||
|
|
||||||
|
### 1. Gerar documentação Rust (`rustdoc`)
|
||||||
|
|
||||||
|
**Verificar comentários existentes:**
|
||||||
|
```
|
||||||
|
mcp__gitea__get_dir_content acidaos-core/src/
|
||||||
|
```
|
||||||
|
|
||||||
|
**Gerar localmente (no container dev):**
|
||||||
|
```bash
|
||||||
|
cd /root/Dev/acidaos-core
|
||||||
|
cargo doc --all-features --no-deps --open
|
||||||
|
```
|
||||||
|
|
||||||
|
**Verificar cobertura de documentação:**
|
||||||
|
```bash
|
||||||
|
cargo doc --all-features 2>&1 | grep "warning: missing documentation"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Template comentários Rust:**
|
||||||
|
```rust
|
||||||
|
/// # ComponenteX
|
||||||
|
///
|
||||||
|
/// Breve descrição em uma linha.
|
||||||
|
///
|
||||||
|
/// ## Descrição detalhada
|
||||||
|
///
|
||||||
|
/// Explicação mais longa do comportamento e propósito.
|
||||||
|
///
|
||||||
|
/// ## Exemplos
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use acidaos_core::ComponenteX;
|
||||||
|
///
|
||||||
|
/// let c = ComponenteX::new("id");
|
||||||
|
/// assert!(c.is_valid());
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ## Erros
|
||||||
|
///
|
||||||
|
/// Retorna [`Error::Init`] se a inicialização falhar.
|
||||||
|
pub struct ComponenteX { ... }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. Gerar documentação TypeScript (TypeDoc)
|
||||||
|
|
||||||
|
**Verificar configuração:**
|
||||||
|
```
|
||||||
|
mcp__gitea__get_file_content acidaos-dashboard/typedoc.json
|
||||||
|
```
|
||||||
|
|
||||||
|
**Gerar (no container dev):**
|
||||||
|
```bash
|
||||||
|
cd /root/Dev/acidaos-dashboard
|
||||||
|
pnpm typedoc --out docs/api src/
|
||||||
|
```
|
||||||
|
|
||||||
|
**Template JSDoc para componentes:**
|
||||||
|
```typescript
|
||||||
|
/**
|
||||||
|
* AgentStatusCard — Mostra o estado de um agente AcidaOS
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```tsx
|
||||||
|
* <AgentStatusCard
|
||||||
|
* agentId="agent-123"
|
||||||
|
* onRefresh={() => refetch()}
|
||||||
|
* />
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export interface AgentStatusCardProps {
|
||||||
|
/** ID único do agente no Core */
|
||||||
|
agentId: string;
|
||||||
|
/** Callback chamado ao clicar em refrescar */
|
||||||
|
onRefresh?: () => void;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3. Publicar arquitectura no Outline
|
||||||
|
|
||||||
|
**Criar/actualizar diagrama de arquitectura:**
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
mcp__outline-api__create_document({
|
||||||
|
title: "AcidaOS — Arquitectura Core",
|
||||||
|
text: `
|
||||||
|
# Arquitectura AcidaOS Core
|
||||||
|
|
||||||
|
## Hub-and-Spoke
|
||||||
|
|
||||||
|
\`\`\`mermaid
|
||||||
|
graph TD
|
||||||
|
A[acidaos-dashboard] -->|API REST| B[AcidaOS Core]
|
||||||
|
B --> C[Agent Kernel]
|
||||||
|
B --> D[Security & Sandboxing]
|
||||||
|
B --> E[Memory Engine]
|
||||||
|
B --> F[Observability]
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Componentes
|
||||||
|
|
||||||
|
| Componente | Linguagem | Responsabilidade |
|
||||||
|
|-----------|-----------|-----------------|
|
||||||
|
| Core | Rust | Orquestração de agentes |
|
||||||
|
| Dashboard | Next.js | Interface de utilizador |
|
||||||
|
`,
|
||||||
|
collectionId: "<acidaos-collection-id>"
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4. Criar ADR (Architecture Decision Record)
|
||||||
|
|
||||||
|
**Template ADR:**
|
||||||
|
```markdown
|
||||||
|
# ADR-<NNN>: <Título da Decisão>
|
||||||
|
|
||||||
|
**Data:** YYYY-MM-DD
|
||||||
|
**Estado:** [Proposto | Aceite | Depreciado | Substituído por ADR-NNN]
|
||||||
|
|
||||||
|
## Contexto
|
||||||
|
|
||||||
|
[Situação que levou à necessidade de tomar esta decisão]
|
||||||
|
|
||||||
|
## Opções Consideradas
|
||||||
|
|
||||||
|
1. **Opção A** — descrição breve
|
||||||
|
2. **Opção B** — descrição breve
|
||||||
|
|
||||||
|
## Decisão
|
||||||
|
|
||||||
|
[Opção escolhida e porquê]
|
||||||
|
|
||||||
|
## Consequências
|
||||||
|
|
||||||
|
**Positivas:**
|
||||||
|
- [Consequência positiva]
|
||||||
|
|
||||||
|
**Negativas / Trade-offs:**
|
||||||
|
- [Limitação ou custo]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quality Gate de Documentação
|
||||||
|
|
||||||
|
Antes de marcar tarefa como concluída:
|
||||||
|
|
||||||
|
- [ ] Rust: zero `missing documentation` warnings em `cargo doc`
|
||||||
|
- [ ] TypeScript: TypeDoc gera sem erros
|
||||||
|
- [ ] Novos módulos têm exemplos de uso nos comentários
|
||||||
|
- [ ] Diagramas Mermaid actualizado se arquitectura mudou
|
||||||
|
- [ ] ADR criado para decisões técnicas significativas
|
||||||
|
|
||||||
|
---
|
||||||
|
**Versão**: 1.0.0 | **Autor**: Descomplicar® | **Plugin**: acidaos
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
@@ -0,0 +1,244 @@
|
|||||||
|
---
|
||||||
|
name: rust-dev
|
||||||
|
description: Desenvolvimento do AcidaOS Core em Rust — criar crates, definir endpoints Axum, debugar erros do compilador. Usar quando "rust", "axum", "cargo", "crate", "core", "acidaos core", "rust error", "borrow checker", desenvolvimento do motor central do AcidaOS.
|
||||||
|
allowed-tools: Read, Write, Edit, Bash, mcp__memory-supabase__search_memories, mcp__gitea__get_file_content, mcp__gitea__create_file, mcp__gitea__update_file
|
||||||
|
---
|
||||||
|
|
||||||
|
# AcidaOS Rust Dev
|
||||||
|
|
||||||
|
Skill para desenvolvimento do **Core do AcidaOS** em Rust.
|
||||||
|
|
||||||
|
## Contexto do Projecto
|
||||||
|
|
||||||
|
```
|
||||||
|
acidaos-core (Rust)
|
||||||
|
├── src/
|
||||||
|
│ ├── api/ ← endpoints Axum (REST/gRPC)
|
||||||
|
│ ├── kernel/ ← Agent Kernel & Scheduler
|
||||||
|
│ ├── security/ ← Sandboxing, isolamento WASM
|
||||||
|
│ ├── memory/ ← Context & Memory Engine
|
||||||
|
│ ├── registry/ ← Parsers de skills/plugins
|
||||||
|
│ ├── observability/← Logging, tracing
|
||||||
|
│ └── ethics/ ← Constitution Engine
|
||||||
|
├── crates/ ← bibliotecas internas
|
||||||
|
└── Cargo.toml
|
||||||
|
```
|
||||||
|
|
||||||
|
**Stack:** Rust stable | Axum | Tokio | Serde | Tracing | SQLx | wasmtime
|
||||||
|
|
||||||
|
## Protocolo Inicial
|
||||||
|
|
||||||
|
```
|
||||||
|
mcp__memory-supabase__search_memories "acidaos core [componente]"
|
||||||
|
mcp__gitea__get_file_content acidaos-core/Cargo.toml # verificar dependências actuais
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Operações
|
||||||
|
|
||||||
|
### 1. Criar novo crate (`/rust-create-crate`)
|
||||||
|
|
||||||
|
**Input:** Nome do crate e propósito
|
||||||
|
|
||||||
|
**Passos:**
|
||||||
|
1. Criar directório `crates/<nome>/`
|
||||||
|
2. Gerar `Cargo.toml` com dependências mínimas
|
||||||
|
3. Criar `src/lib.rs` com estrutura base
|
||||||
|
4. Adicionar ao workspace `Cargo.toml`
|
||||||
|
5. Criar `src/error.rs` com tipo de erro custom usando `thiserror`
|
||||||
|
|
||||||
|
**Template `Cargo.toml`:**
|
||||||
|
```toml
|
||||||
|
[package]
|
||||||
|
name = "acidaos-<nome>"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
description = "<descrição>"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
tracing = "0.1"
|
||||||
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
thiserror = "1"
|
||||||
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
```
|
||||||
|
|
||||||
|
**Template `src/lib.rs`:**
|
||||||
|
```rust
|
||||||
|
//! # acidaos-<nome>
|
||||||
|
//!
|
||||||
|
//! <Descrição do módulo>
|
||||||
|
//!
|
||||||
|
//! ## Exemplo
|
||||||
|
//! ```rust
|
||||||
|
//! use acidaos_<nome>::<TipoPrincipal>;
|
||||||
|
//! ```
|
||||||
|
|
||||||
|
mod error;
|
||||||
|
pub use error::Error;
|
||||||
|
|
||||||
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
```
|
||||||
|
|
||||||
|
**Template `src/error.rs`:**
|
||||||
|
```rust
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum Error {
|
||||||
|
#[error("Erro de inicialização: {0}")]
|
||||||
|
Init(String),
|
||||||
|
|
||||||
|
#[error("Operação não suportada: {0}")]
|
||||||
|
Unsupported(String),
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. Definir endpoint Axum (`/rust-define-api-endpoint`)
|
||||||
|
|
||||||
|
**Input:** Definição do endpoint (método, path, request/response types) de uma SPEC.md
|
||||||
|
|
||||||
|
**Template de endpoint:**
|
||||||
|
```rust
|
||||||
|
use axum::{
|
||||||
|
extract::{Path, State},
|
||||||
|
http::StatusCode,
|
||||||
|
response::Json,
|
||||||
|
routing::{get, post},
|
||||||
|
Router,
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use tracing::instrument;
|
||||||
|
|
||||||
|
// --- Tipos ---
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct <NomeRequest> {
|
||||||
|
// campos do request
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
pub struct <NomeResponse> {
|
||||||
|
// campos do response
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Handler ---
|
||||||
|
|
||||||
|
#[instrument(skip(state))]
|
||||||
|
pub async fn <nome_handler>(
|
||||||
|
State(state): State<AppState>,
|
||||||
|
Json(req): Json<<NomeRequest>>,
|
||||||
|
) -> Result<Json<<NomeResponse>>, StatusCode> {
|
||||||
|
tracing::info!("Processando <nome>");
|
||||||
|
|
||||||
|
// lógica do handler
|
||||||
|
|
||||||
|
Ok(Json(<NomeResponse> {
|
||||||
|
// preencher response
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Router ---
|
||||||
|
|
||||||
|
pub fn <nome>_router() -> Router<AppState> {
|
||||||
|
Router::new()
|
||||||
|
.route("/<path>", post(<nome_handler>))
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Princípios obrigatórios:**
|
||||||
|
- `#[instrument]` em todos os handlers (observabilidade)
|
||||||
|
- Erros retornam `StatusCode` ou tipo de erro custom (nunca `.unwrap()`)
|
||||||
|
- Estado partilhado via `State<AppState>` (não globals)
|
||||||
|
- Validação de input antes de processamento
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3. Debugar erro do compilador (`/rust-debug-compiler-error`)
|
||||||
|
|
||||||
|
**Input:** Output completo de `cargo build` ou `cargo check`
|
||||||
|
|
||||||
|
**Protocolo de análise:**
|
||||||
|
|
||||||
|
1. **Identificar categoria do erro:**
|
||||||
|
| Código | Categoria | Solução típica |
|
||||||
|
|--------|-----------|----------------|
|
||||||
|
| E0382 | Move após uso | Usar `clone()` ou referências `&` |
|
||||||
|
| E0502 | Borrow conflict | Reordenar operações, usar `Arc<Mutex<>>` |
|
||||||
|
| E0308 | Type mismatch | Verificar tipos, usar `.into()` ou cast explícito |
|
||||||
|
| E0277 | Trait not impl | Implementar trait ou usar tipo diferente |
|
||||||
|
| E0499 | Multiple mut borrows | Usar `RefCell` ou reestruturar lógica |
|
||||||
|
|
||||||
|
2. **Analisar mensagem de erro completa** (incluindo `help:` e `note:`)
|
||||||
|
|
||||||
|
3. **Gerar código corrigido** com explicação da causa raiz
|
||||||
|
|
||||||
|
4. **Verificar:** `cargo check` passa antes de `cargo build`
|
||||||
|
|
||||||
|
**Padrões comuns no AcidaOS Core:**
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// ❌ Move não intencional
|
||||||
|
let data = fetch_data();
|
||||||
|
process(data);
|
||||||
|
log(data); // ERRO: data foi moved
|
||||||
|
|
||||||
|
// ✅ Correcto
|
||||||
|
let data = fetch_data();
|
||||||
|
process(&data); // ou process(data.clone())
|
||||||
|
log(&data);
|
||||||
|
|
||||||
|
// ❌ Async + lifetime
|
||||||
|
async fn handler(req: &Request) -> Response { ... } // lifetime issue
|
||||||
|
|
||||||
|
// ✅ Correcto — owned ou Arc
|
||||||
|
async fn handler(req: Arc<Request>) -> Response { ... }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quality Gate
|
||||||
|
|
||||||
|
Antes de fazer commit:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo check # zero erros
|
||||||
|
cargo clippy # zero warnings
|
||||||
|
cargo test # todos os testes passam
|
||||||
|
cargo fmt --check # formatação correcta
|
||||||
|
```
|
||||||
|
|
||||||
|
**Standards:**
|
||||||
|
- Zero `unwrap()` em código de produção — usar `?` ou `expect("mensagem descritiva")`
|
||||||
|
- Funções async < 50 linhas
|
||||||
|
- `tracing::instrument` em todas as funções públicas async
|
||||||
|
- Documentação `///` em todos os tipos e funções públicas
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Checklist Entrega
|
||||||
|
|
||||||
|
- [ ] `cargo check` sem erros
|
||||||
|
- [ ] `cargo clippy -- -D warnings` limpo
|
||||||
|
- [ ] `cargo test` 100% pass
|
||||||
|
- [ ] Documentação `///` completa
|
||||||
|
- [ ] Observabilidade: `#[instrument]` nos handlers
|
||||||
|
- [ ] Sem `.unwrap()` em paths críticos
|
||||||
|
- [ ] CHANGELOG.md actualizado
|
||||||
|
|
||||||
|
---
|
||||||
|
**Versão**: 1.0.0 | **Autor**: Descomplicar® | **Plugin**: acidaos
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
@@ -0,0 +1,251 @@
|
|||||||
|
---
|
||||||
|
name: spoke-dev
|
||||||
|
description: Desenvolvimento de Spokes do AcidaOS em Next.js/TypeScript — criar aplicações Spoke, componentes React com testes e Storybook. Usar quando "spoke", "dashboard acidaos", "next.js acidaos", "componente react acidaos", "ts-create-spoke", "acidaos ui", "acidaos frontend".
|
||||||
|
allowed-tools: Read, Write, Edit, Bash, mcp__memory-supabase__search_memories, mcp__gitea__get_file_content, mcp__gitea__create_file, mcp__gitea__update_file
|
||||||
|
---
|
||||||
|
|
||||||
|
# AcidaOS Spoke Dev
|
||||||
|
|
||||||
|
Skill para desenvolvimento dos **Spokes do AcidaOS** em Next.js/TypeScript.
|
||||||
|
|
||||||
|
## Contexto do Projecto
|
||||||
|
|
||||||
|
Os Spokes são as aplicações de interface que comunicam com o Core via API interna:
|
||||||
|
|
||||||
|
```
|
||||||
|
acidaos-dashboard (Next.js 15 + App Router)
|
||||||
|
├── src/
|
||||||
|
│ ├── app/ ← App Router pages
|
||||||
|
│ ├── components/ ← Componentes React
|
||||||
|
│ │ ├── ui/ ← Componentes base (shadcn/ui)
|
||||||
|
│ │ └── features/ ← Componentes de funcionalidade
|
||||||
|
│ ├── lib/
|
||||||
|
│ │ ├── api/ ← Client para AcidaOS Core API
|
||||||
|
│ │ └── hooks/ ← React hooks custom
|
||||||
|
│ └── types/ ← TypeScript types partilhados
|
||||||
|
├── __tests__/ ← Jest + Testing Library
|
||||||
|
└── .storybook/ ← Storybook
|
||||||
|
```
|
||||||
|
|
||||||
|
**Stack:** Next.js 15 | TypeScript 5 | React 19 | Tailwind CSS | shadcn/ui | Vercel AI SDK | Vitest | Playwright
|
||||||
|
|
||||||
|
## Protocolo Inicial
|
||||||
|
|
||||||
|
```
|
||||||
|
mcp__memory-supabase__search_memories "acidaos spoke dashboard [componente]"
|
||||||
|
mcp__gitea__get_file_content acidaos-dashboard/package.json
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Operações
|
||||||
|
|
||||||
|
### 1. Criar nova aplicação Spoke (`/ts-create-spoke-app`)
|
||||||
|
|
||||||
|
**Input:** Nome do Spoke e propósito
|
||||||
|
|
||||||
|
**Estrutura a criar:**
|
||||||
|
```bash
|
||||||
|
# No container dev (Regra #48)
|
||||||
|
cd /root/Dev
|
||||||
|
npx create-next-app@latest acidaos-<nome> \
|
||||||
|
--typescript \
|
||||||
|
--tailwind \
|
||||||
|
--app \
|
||||||
|
--src-dir \
|
||||||
|
--import-alias "@/*" \
|
||||||
|
--no-git
|
||||||
|
```
|
||||||
|
|
||||||
|
**Ficheiros obrigatórios após scaffold:**
|
||||||
|
|
||||||
|
`src/lib/api/core-client.ts` — cliente para o Core:
|
||||||
|
```typescript
|
||||||
|
/**
|
||||||
|
* AcidaOS Core API Client
|
||||||
|
*
|
||||||
|
* @author Descomplicar® Crescimento Digital
|
||||||
|
* @link https://descomplicar.pt
|
||||||
|
*/
|
||||||
|
|
||||||
|
const CORE_API_URL = process.env.ACIDAOS_CORE_URL ?? 'http://localhost:3001';
|
||||||
|
|
||||||
|
export async function coreRequest<T>(
|
||||||
|
endpoint: string,
|
||||||
|
options?: RequestInit
|
||||||
|
): Promise<T> {
|
||||||
|
const res = await fetch(`${CORE_API_URL}${endpoint}`, {
|
||||||
|
...options,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-AcidaOS-Version': '1',
|
||||||
|
...options?.headers,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
throw new Error(`Core API error: ${res.status} ${res.statusText}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.json() as Promise<T>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`src/types/index.ts` — tipos base:
|
||||||
|
```typescript
|
||||||
|
export interface AgentTask {
|
||||||
|
id: string;
|
||||||
|
status: 'pending' | 'running' | 'completed' | 'failed';
|
||||||
|
createdAt: string;
|
||||||
|
completedAt?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CoreHealth {
|
||||||
|
status: 'healthy' | 'degraded' | 'down';
|
||||||
|
version: string;
|
||||||
|
uptime: number;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. Criar componente React (`/ts-create-react-component`)
|
||||||
|
|
||||||
|
**Input:** Descrição do componente (nome, props, comportamento)
|
||||||
|
|
||||||
|
**Template base — componente:**
|
||||||
|
|
||||||
|
`src/components/features/<Nome>/<Nome>.tsx`:
|
||||||
|
```typescript
|
||||||
|
/**
|
||||||
|
* <Nome> — <Descrição curta>
|
||||||
|
*
|
||||||
|
* @author Descomplicar® Crescimento Digital
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { type FC } from 'react';
|
||||||
|
import { cn } from '@/lib/utils';
|
||||||
|
|
||||||
|
interface <Nome>Props {
|
||||||
|
// props do componente
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const <Nome>: FC<<Nome>Props> = ({ className }) => {
|
||||||
|
return (
|
||||||
|
<div className={cn('', className)}>
|
||||||
|
{/* conteúdo */}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
<Nome>.displayName = '<Nome>';
|
||||||
|
```
|
||||||
|
|
||||||
|
**Template — teste (Vitest + Testing Library):**
|
||||||
|
|
||||||
|
`src/components/features/<Nome>/<Nome>.test.tsx`:
|
||||||
|
```typescript
|
||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import { describe, it, expect } from 'vitest';
|
||||||
|
import { <Nome> } from './<Nome>';
|
||||||
|
|
||||||
|
describe('<Nome>', () => {
|
||||||
|
it('renderiza sem erros', () => {
|
||||||
|
render(<<Nome> />);
|
||||||
|
// asserção específica ao componente
|
||||||
|
});
|
||||||
|
|
||||||
|
it('aceita className personalizada', () => {
|
||||||
|
const { container } = render(<<Nome> className="test-class" />);
|
||||||
|
expect(container.firstChild).toHaveClass('test-class');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
**Template — Storybook:**
|
||||||
|
|
||||||
|
`src/components/features/<Nome>/<Nome>.stories.tsx`:
|
||||||
|
```typescript
|
||||||
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
|
import { <Nome> } from './<Nome>';
|
||||||
|
|
||||||
|
const meta: Meta<typeof <Nome>> = {
|
||||||
|
title: 'Features/<Nome>',
|
||||||
|
component: <Nome>,
|
||||||
|
parameters: {
|
||||||
|
layout: 'centered',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
type Story = StoryObj<typeof <Nome>>;
|
||||||
|
|
||||||
|
export const Default: Story = {
|
||||||
|
args: {},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
**Criar index de exportação:**
|
||||||
|
|
||||||
|
`src/components/features/<Nome>/index.ts`:
|
||||||
|
```typescript
|
||||||
|
export { <Nome> } from './<Nome>';
|
||||||
|
export type { <Nome>Props } from './<Nome>';
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Padrões Obrigatórios
|
||||||
|
|
||||||
|
### TypeScript
|
||||||
|
- `strict: true` em `tsconfig.json` — sem `any` implícito
|
||||||
|
- Props sempre tipadas com interface exportada
|
||||||
|
- Hooks custom em `src/lib/hooks/use<Nome>.ts`
|
||||||
|
- Server Components por defeito; `'use client'` apenas quando necessário
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
- `next/image` para todas as imagens
|
||||||
|
- `loading="lazy"` em componentes pesados
|
||||||
|
- `Suspense` boundaries em torno de data-fetching
|
||||||
|
- Cache de API calls com `unstable_cache` ou React cache
|
||||||
|
|
||||||
|
### Segurança
|
||||||
|
- Nunca expor `ACIDAOS_CORE_URL` no cliente (apenas server-side)
|
||||||
|
- Sanitizar input do utilizador antes de enviar ao Core
|
||||||
|
- Usar Next.js Server Actions para mutações
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quality Gate
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm build # zero erros TypeScript
|
||||||
|
pnpm test # todos os testes passam
|
||||||
|
pnpm lint # zero erros ESLint
|
||||||
|
```
|
||||||
|
|
||||||
|
## Checklist Entrega
|
||||||
|
|
||||||
|
- [ ] Tipos TypeScript sem `any`
|
||||||
|
- [ ] Testes criados (>80% cobertura)
|
||||||
|
- [ ] Story Storybook criada
|
||||||
|
- [ ] `displayName` definido no componente
|
||||||
|
- [ ] `pnpm build` sem erros
|
||||||
|
- [ ] Client/Server components correctamente marcados
|
||||||
|
- [ ] CHANGELOG.md actualizado
|
||||||
|
|
||||||
|
---
|
||||||
|
**Versão**: 1.0.0 | **Autor**: Descomplicar® | **Plugin**: acidaos
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
@@ -104,3 +104,15 @@ A sandbox fornece um ambiente isolado com dados fictícios para desenvolvimento
|
|||||||
- **[references/endpoints.md](references/endpoints.md)** - Catálogo completo de endpoints
|
- **[references/endpoints.md](references/endpoints.md)** - Catálogo completo de endpoints
|
||||||
- **Docs oficiais:** https://www.moloni.pt/dev/endpoints/
|
- **Docs oficiais:** https://www.moloni.pt/dev/endpoints/
|
||||||
- **Sandbox:** https://www.moloni.pt/dev/sandbox/
|
- **Sandbox:** https://www.moloni.pt/dev/sandbox/
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -1,301 +0,0 @@
|
|||||||
---
|
|
||||||
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: "<adaptar ao contexto do pedido do utilizador>"
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
Integrar insights do NotebookLM nas recomendações e decisões.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Uso
|
|
||||||
|
|
||||||
```
|
|
||||||
/n8n-chatbot create <descrição> # Criar chatbot
|
|
||||||
/n8n-chatbot agent <tipo> # Criar AI agent
|
|
||||||
/n8n-chatbot rag <knowledge_base> # Criar sistema RAG
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Workflow Obrigatório
|
|
||||||
|
|
||||||
```
|
|
||||||
1. Health check → mcp__n8n__n8n_health_check()
|
|
||||||
2. Pesquisar template → mcp__n8n__search_templates({ task: "ai_automation" })
|
|
||||||
3. Se template OK → mcp__n8n__n8n_deploy_template()
|
|
||||||
4. Se criar do zero → Seguir fluxo abaixo
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Nodes LangChain
|
|
||||||
|
|
||||||
### Core
|
|
||||||
|
|
||||||
| Node | Uso |
|
|
||||||
|------|-----|
|
|
||||||
| `@n8n/n8n-nodes-langchain.agent` | AI Agent principal |
|
|
||||||
| `@n8n/n8n-nodes-langchain.chainLlm` | Chain LLM simples |
|
|
||||||
| `@n8n/n8n-nodes-langchain.chainRetrievalQa` | RAG Q&A |
|
|
||||||
|
|
||||||
### Modelos
|
|
||||||
|
|
||||||
| Node | Provider |
|
|
||||||
|------|----------|
|
|
||||||
| `@n8n/n8n-nodes-langchain.lmChatOpenAi` | OpenAI GPT |
|
|
||||||
| `@n8n/n8n-nodes-langchain.lmChatAnthropic` | Claude |
|
|
||||||
| `@n8n/n8n-nodes-langchain.lmChatOllama` | Ollama local |
|
|
||||||
|
|
||||||
### Memória
|
|
||||||
|
|
||||||
| Node | Tipo |
|
|
||||||
|------|------|
|
|
||||||
| `@n8n/n8n-nodes-langchain.memoryBufferWindow` | Últimas N mensagens |
|
|
||||||
| `@n8n/n8n-nodes-langchain.memoryPostgresChat` | PostgreSQL |
|
|
||||||
| `@n8n/n8n-nodes-langchain.memoryRedisChat` | Redis |
|
|
||||||
|
|
||||||
### Tools
|
|
||||||
|
|
||||||
| Node | Função |
|
|
||||||
|------|--------|
|
|
||||||
| `@n8n/n8n-nodes-langchain.toolCalculator` | Cálculos |
|
|
||||||
| `@n8n/n8n-nodes-langchain.toolCode` | Executar código |
|
|
||||||
| `@n8n/n8n-nodes-langchain.toolHttpRequest` | Chamar APIs |
|
|
||||||
| `@n8n/n8n-nodes-langchain.toolWorkflow` | Chamar workflows |
|
|
||||||
|
|
||||||
### Vector Stores (RAG)
|
|
||||||
|
|
||||||
| Node | Sistema |
|
|
||||||
|------|---------|
|
|
||||||
| `@n8n/n8n-nodes-langchain.vectorStoreSupabase` | Supabase |
|
|
||||||
| `@n8n/n8n-nodes-langchain.vectorStorePinecone` | Pinecone |
|
|
||||||
| `@n8n/n8n-nodes-langchain.vectorStorePgVector` | PostgreSQL |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Chatbot Básico
|
|
||||||
|
|
||||||
### Estrutura
|
|
||||||
|
|
||||||
```
|
|
||||||
Webhook/Trigger
|
|
||||||
↓
|
|
||||||
LLM Chat Model (OpenAI/Claude)
|
|
||||||
↓
|
|
||||||
Memory (Buffer)
|
|
||||||
↓
|
|
||||||
Agent
|
|
||||||
↓
|
|
||||||
Resposta
|
|
||||||
```
|
|
||||||
|
|
||||||
### Implementação
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
// 1. Modelo LLM
|
|
||||||
mcp__n8n__get_node({
|
|
||||||
nodeType: "@n8n/n8n-nodes-langchain.lmChatOpenAi",
|
|
||||||
detail: "standard"
|
|
||||||
})
|
|
||||||
|
|
||||||
// 2. Memória
|
|
||||||
mcp__n8n__get_node({
|
|
||||||
nodeType: "@n8n/n8n-nodes-langchain.memoryBufferWindow",
|
|
||||||
detail: "standard"
|
|
||||||
})
|
|
||||||
|
|
||||||
// 3. Agent
|
|
||||||
mcp__n8n__get_node({
|
|
||||||
nodeType: "@n8n/n8n-nodes-langchain.agent",
|
|
||||||
detail: "standard"
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## RAG (Retrieval Augmented Generation)
|
|
||||||
|
|
||||||
### Estrutura
|
|
||||||
|
|
||||||
```
|
|
||||||
Documentos
|
|
||||||
↓
|
|
||||||
Embeddings
|
|
||||||
↓
|
|
||||||
Vector Store
|
|
||||||
↓
|
|
||||||
Query (pergunta)
|
|
||||||
↓
|
|
||||||
Retriever
|
|
||||||
↓
|
|
||||||
LLM (resposta contextualizada)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Configuração Vector Store
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
mcp__n8n__validate_node({
|
|
||||||
nodeType: "@n8n/n8n-nodes-langchain.vectorStoreSupabase",
|
|
||||||
config: {
|
|
||||||
mode: "insert", // ou "retrieve"
|
|
||||||
tableName: "documents",
|
|
||||||
queryName: "match_documents"
|
|
||||||
},
|
|
||||||
mode: "minimal"
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## AI Agent com Tools
|
|
||||||
|
|
||||||
### Estrutura
|
|
||||||
|
|
||||||
```
|
|
||||||
Input
|
|
||||||
↓
|
|
||||||
Agent
|
|
||||||
├── Tool: Calculator
|
|
||||||
├── Tool: HTTP Request
|
|
||||||
├── Tool: Code
|
|
||||||
└── Tool: Workflow
|
|
||||||
↓
|
|
||||||
Output
|
|
||||||
```
|
|
||||||
|
|
||||||
### Configuração Agent
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
mcp__n8n__validate_node({
|
|
||||||
nodeType: "@n8n/n8n-nodes-langchain.agent",
|
|
||||||
config: {
|
|
||||||
agentType: "conversationalAgent",
|
|
||||||
systemMessage: "Tu és um assistente prestável...",
|
|
||||||
options: {
|
|
||||||
returnIntermediateSteps: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mode: "minimal"
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Exemplos Práticos
|
|
||||||
|
|
||||||
### Chatbot de Suporte
|
|
||||||
|
|
||||||
```
|
|
||||||
Webhook (mensagem cliente)
|
|
||||||
↓
|
|
||||||
Memory PostgreSQL (histórico)
|
|
||||||
↓
|
|
||||||
Vector Store (docs suporte)
|
|
||||||
↓
|
|
||||||
Chain Retrieval QA
|
|
||||||
↓
|
|
||||||
Webhook Response
|
|
||||||
```
|
|
||||||
|
|
||||||
### Agent CRM
|
|
||||||
|
|
||||||
```
|
|
||||||
Webhook (comando)
|
|
||||||
↓
|
|
||||||
Agent
|
|
||||||
├── Tool: Pesquisar clientes
|
|
||||||
├── Tool: Criar lead
|
|
||||||
└── Tool: Actualizar tarefa
|
|
||||||
↓
|
|
||||||
Slack (resultado)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Resumo de Documentos
|
|
||||||
|
|
||||||
```
|
|
||||||
Webhook (upload PDF)
|
|
||||||
↓
|
|
||||||
PDF Extract
|
|
||||||
↓
|
|
||||||
Text Splitter
|
|
||||||
↓
|
|
||||||
LLM Chain (resumo)
|
|
||||||
↓
|
|
||||||
Email (enviar resumo)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Templates Recomendados
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
// AI templates
|
|
||||||
mcp__n8n__search_templates({
|
|
||||||
searchMode: "by_task",
|
|
||||||
task: "ai_automation"
|
|
||||||
})
|
|
||||||
|
|
||||||
// Por keyword
|
|
||||||
mcp__n8n__search_templates({
|
|
||||||
searchMode: "keyword",
|
|
||||||
query: "chatbot langchain openai"
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Credenciais Necessárias
|
|
||||||
|
|
||||||
| Provider | Credencial | Node |
|
|
||||||
|----------|------------|------|
|
|
||||||
| OpenAI | API Key | lmChatOpenAi |
|
|
||||||
| Anthropic | API Key | lmChatAnthropic |
|
|
||||||
| Supabase | URL + Key | vectorStoreSupabase |
|
|
||||||
| Pinecone | API Key | vectorStorePinecone |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Boas Práticas
|
|
||||||
|
|
||||||
| Prática | Razão |
|
|
||||||
|---------|-------|
|
|
||||||
| System prompt claro | Define comportamento |
|
|
||||||
| Temperatura baixa (0.1-0.3) | Respostas consistentes |
|
|
||||||
| Memória limitada | Performance |
|
|
||||||
| Retry on error | Resiliência |
|
|
||||||
| Logs de conversas | Debug e melhoria |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
| Problema | Solução |
|
|
||||||
|----------|---------|
|
|
||||||
| Respostas inconsistentes | Baixar temperatura |
|
|
||||||
| Contexto perdido | Verificar memória |
|
|
||||||
| RAG não encontra | Verificar embeddings |
|
|
||||||
| Timeout | Aumentar limite |
|
|
||||||
| Token limit | Resumir contexto |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*Skill v1.0 | Descomplicar®*
|
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
---
|
|
||||||
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: "<adaptar ao contexto do pedido do utilizador>"
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
Integrar insights do NotebookLM nas recomendações e decisões.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Uso
|
|
||||||
|
|
||||||
```
|
|
||||||
/n8n-health # Status rápido
|
|
||||||
/n8n-health verbose # Diagnóstico completo
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Instância
|
|
||||||
|
|
||||||
| Aspecto | Valor |
|
|
||||||
|---------|-------|
|
|
||||||
| URL | `https://automator.descomplicar.pt` |
|
|
||||||
| MCP | `mcp__n8n__*` |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Execução
|
|
||||||
|
|
||||||
### Status Rápido (default)
|
|
||||||
|
|
||||||
```
|
|
||||||
1. mcp__n8n__n8n_health_check({ mode: "status" })
|
|
||||||
2. Reportar: status, URL, versão, response time
|
|
||||||
```
|
|
||||||
|
|
||||||
### Diagnóstico Completo (verbose)
|
|
||||||
|
|
||||||
```
|
|
||||||
1. mcp__n8n__n8n_health_check({ mode: "diagnostic", verbose: true })
|
|
||||||
2. Reportar: env vars, tool status, cache, erros
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Output Esperado
|
|
||||||
|
|
||||||
```
|
|
||||||
n8n Health Check
|
|
||||||
----------------
|
|
||||||
Status: OK | ERRO
|
|
||||||
URL: https://automator.descomplicar.pt
|
|
||||||
MCP: 2.33.x
|
|
||||||
Response: XXXms
|
|
||||||
Workflows: XX activos
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Se Falhar
|
|
||||||
|
|
||||||
| Erro | Causa | Solução |
|
|
||||||
|------|-------|---------|
|
|
||||||
| Connection refused | n8n offline | Verificar servidor |
|
|
||||||
| 401 Unauthorized | API key inválida | Regenerar no n8n |
|
|
||||||
| Timeout | Rede lenta | Verificar latência |
|
|
||||||
|
|
||||||
### Diagnóstico Manual
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Verificar se n8n responde
|
|
||||||
curl -I https://automator.descomplicar.pt
|
|
||||||
|
|
||||||
# Verificar API
|
|
||||||
curl -H "X-N8N-API-KEY: $KEY" https://automator.descomplicar.pt/api/v1/workflows
|
|
||||||
|
|
||||||
# Logs MCP
|
|
||||||
~/.claude/logs/mcp-n8n.log
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Skills Relacionadas
|
|
||||||
|
|
||||||
| Skill | Quando Usar |
|
|
||||||
|-------|-------------|
|
|
||||||
| `/n8n-webhook` | Criar webhooks |
|
|
||||||
| `/n8n-schedule` | Automações cron |
|
|
||||||
| `/n8n-sync` | Sincronização dados |
|
|
||||||
| `/n8n-notify` | Alertas |
|
|
||||||
| `/n8n-chatbot` | AI/Chatbots |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*Skill v1.0 | Descomplicar®*
|
|
||||||
@@ -1,234 +0,0 @@
|
|||||||
---
|
|
||||||
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.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Uso
|
|
||||||
|
|
||||||
```
|
|
||||||
/n8n-notify create <descrição> # Criar sistema de alertas
|
|
||||||
/n8n-notify slack <mensagem> # Quick Slack notification
|
|
||||||
/n8n-notify email <para> <assunto> # Quick email
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Workflow Obrigatório
|
|
||||||
|
|
||||||
```
|
|
||||||
1. Health check → mcp__n8n__n8n_health_check()
|
|
||||||
2. Pesquisar template → mcp__n8n__search_templates({ query: "notification" })
|
|
||||||
3. Se template OK → mcp__n8n__n8n_deploy_template()
|
|
||||||
4. Se criar do zero → Seguir fluxo abaixo
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Canais Disponíveis
|
|
||||||
|
|
||||||
| Canal | Node | Uso |
|
|
||||||
|-------|------|-----|
|
|
||||||
| Slack | `nodes-base.slack` | Notificações equipa |
|
|
||||||
| Email | `nodes-base.emailSend` | Alertas formais |
|
|
||||||
| Telegram | `nodes-base.telegram` | Alertas mobile |
|
|
||||||
| Discord | `nodes-base.discord` | Comunidades |
|
|
||||||
| SMS | `nodes-base.twilio` | Alertas críticos |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slack
|
|
||||||
|
|
||||||
### Documentação
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
mcp__n8n__get_node({
|
|
||||||
nodeType: "nodes-base.slack",
|
|
||||||
detail: "standard",
|
|
||||||
includeExamples: true
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
### Configuração
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
mcp__n8n__validate_node({
|
|
||||||
nodeType: "nodes-base.slack",
|
|
||||||
config: {
|
|
||||||
resource: "message",
|
|
||||||
operation: "post",
|
|
||||||
channel: "#alertas",
|
|
||||||
text: "Mensagem de alerta"
|
|
||||||
},
|
|
||||||
mode: "minimal"
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
### Mensagem Formatada (Blocks)
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
{
|
|
||||||
blocksUi: {
|
|
||||||
blocksValues: [
|
|
||||||
{
|
|
||||||
type: "header",
|
|
||||||
text: { type: "plain_text", text: "Alerta" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "section",
|
|
||||||
text: { type: "mrkdwn", text: "*Detalhes:*\n{{ $json.message }}" }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Email
|
|
||||||
|
|
||||||
### Configuração
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
mcp__n8n__validate_node({
|
|
||||||
nodeType: "nodes-base.emailSend",
|
|
||||||
config: {
|
|
||||||
fromEmail: "alertas@descomplicar.pt",
|
|
||||||
toEmail: "emanuel@descomplicar.pt",
|
|
||||||
subject: "Alerta: {{ $json.title }}",
|
|
||||||
text: "{{ $json.message }}"
|
|
||||||
},
|
|
||||||
mode: "minimal"
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Padrões Comuns
|
|
||||||
|
|
||||||
### Webhook → Slack
|
|
||||||
|
|
||||||
```
|
|
||||||
Webhook (evento externo)
|
|
||||||
↓
|
|
||||||
Set (formatar)
|
|
||||||
↓
|
|
||||||
Slack (enviar)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Monitor → Multi-canal
|
|
||||||
|
|
||||||
```
|
|
||||||
Schedule (cada 5min)
|
|
||||||
↓
|
|
||||||
HTTP Request (check health)
|
|
||||||
↓
|
|
||||||
IF (erro?)
|
|
||||||
↓ TRUE
|
|
||||||
Slack + Email (alertar)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Error Handler
|
|
||||||
|
|
||||||
```
|
|
||||||
Qualquer workflow
|
|
||||||
↓ (erro)
|
|
||||||
Error Trigger
|
|
||||||
↓
|
|
||||||
Slack (alertar erro)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Níveis de Alerta
|
|
||||||
|
|
||||||
| Nível | Canal | Quando |
|
|
||||||
|-------|-------|--------|
|
|
||||||
| Info | Slack | Eventos normais |
|
|
||||||
| Warning | Slack + Email | Atenção necessária |
|
|
||||||
| Critical | Todos + SMS | Acção imediata |
|
|
||||||
|
|
||||||
### Implementação
|
|
||||||
|
|
||||||
```
|
|
||||||
IF (severity = "critical")
|
|
||||||
↓ TRUE
|
|
||||||
Slack + Email + SMS
|
|
||||||
↓ FALSE
|
|
||||||
IF (severity = "warning")
|
|
||||||
↓ TRUE
|
|
||||||
Slack + Email
|
|
||||||
↓ FALSE
|
|
||||||
Slack
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Exemplos
|
|
||||||
|
|
||||||
### Alerta de Servidor Down
|
|
||||||
|
|
||||||
```
|
|
||||||
Schedule (5min)
|
|
||||||
↓
|
|
||||||
HTTP Request (ping servidor)
|
|
||||||
↓
|
|
||||||
IF (falhou?)
|
|
||||||
↓ TRUE
|
|
||||||
Slack (#infra)
|
|
||||||
Email (admin)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Novo Lead
|
|
||||||
|
|
||||||
```
|
|
||||||
Webhook (lead criado)
|
|
||||||
↓
|
|
||||||
Set (formatar)
|
|
||||||
↓
|
|
||||||
Slack (#vendas)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Factura Vencida
|
|
||||||
|
|
||||||
```
|
|
||||||
Schedule (diário 9h)
|
|
||||||
↓
|
|
||||||
HTTP Request (facturas vencidas)
|
|
||||||
↓
|
|
||||||
Loop (cada factura)
|
|
||||||
↓
|
|
||||||
Email (cliente)
|
|
||||||
Slack (#contabilidade)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Templates
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
mcp__n8n__search_templates({
|
|
||||||
searchMode: "keyword",
|
|
||||||
query: "slack notification alert"
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
| Problema | Solução |
|
|
||||||
|----------|---------|
|
|
||||||
| Slack não envia | Verificar token e canal |
|
|
||||||
| Email em spam | Configurar SPF/DKIM |
|
|
||||||
| Rate limited | Agrupar notificações |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*Skill v1.0 | Descomplicar®*
|
|
||||||
@@ -1,169 +0,0 @@
|
|||||||
---
|
|
||||||
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).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Uso
|
|
||||||
|
|
||||||
```
|
|
||||||
/n8n-schedule create <descrição> # Criar automação agendada
|
|
||||||
/n8n-schedule list # Listar agendamentos
|
|
||||||
/n8n-schedule disable <id> # Desactivar
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Workflow Obrigatório
|
|
||||||
|
|
||||||
```
|
|
||||||
1. Health check → mcp__n8n__n8n_health_check()
|
|
||||||
2. Pesquisar template → mcp__n8n__search_templates({ task: "scheduling" })
|
|
||||||
3. Se template OK → mcp__n8n__n8n_deploy_template()
|
|
||||||
4. Se criar do zero → Seguir fluxo abaixo
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Expressões Cron Comuns
|
|
||||||
|
|
||||||
| Expressão | Descrição |
|
|
||||||
|-----------|-----------|
|
|
||||||
| `0 9 * * *` | Diário às 9h |
|
|
||||||
| `0 9 * * 1-5` | Seg-Sex às 9h |
|
|
||||||
| `0 */2 * * *` | A cada 2 horas |
|
|
||||||
| `*/15 * * * *` | A cada 15 minutos |
|
|
||||||
| `0 0 1 * *` | Dia 1 de cada mês |
|
|
||||||
| `0 3 * * 0` | Domingos às 3h |
|
|
||||||
|
|
||||||
### Formato
|
|
||||||
|
|
||||||
```
|
|
||||||
┌───────── minuto (0-59)
|
|
||||||
│ ┌─────── hora (0-23)
|
|
||||||
│ │ ┌───── dia mês (1-31)
|
|
||||||
│ │ │ ┌─── mês (1-12)
|
|
||||||
│ │ │ │ ┌─ dia semana (0-6)
|
|
||||||
* * * * *
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Configuração Schedule Trigger
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
mcp__n8n__validate_node({
|
|
||||||
nodeType: "nodes-base.scheduleTrigger",
|
|
||||||
config: {
|
|
||||||
rule: {
|
|
||||||
interval: [{
|
|
||||||
field: "cronExpression",
|
|
||||||
expression: "0 9 * * 1-5"
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mode: "minimal"
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Timezone
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
{
|
|
||||||
options: {
|
|
||||||
timezone: "Europe/Lisbon"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Exemplos
|
|
||||||
|
|
||||||
### Relatório Diário
|
|
||||||
|
|
||||||
```
|
|
||||||
Schedule (0 9 * * 1-5)
|
|
||||||
↓
|
|
||||||
PostgreSQL (query)
|
|
||||||
↓
|
|
||||||
Set (formatar)
|
|
||||||
↓
|
|
||||||
Email (enviar)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Backup Semanal
|
|
||||||
|
|
||||||
```
|
|
||||||
Schedule (0 3 * * 0)
|
|
||||||
↓
|
|
||||||
SSH (backup)
|
|
||||||
↓
|
|
||||||
IF (sucesso?)
|
|
||||||
↓
|
|
||||||
Slack (confirmar/alertar)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Limpeza de Logs
|
|
||||||
|
|
||||||
```
|
|
||||||
Schedule (0 2 * * *)
|
|
||||||
↓
|
|
||||||
SSH (limpar)
|
|
||||||
↓
|
|
||||||
Slack (reportar)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Gestão
|
|
||||||
|
|
||||||
### Desactivar
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
mcp__n8n__n8n_update_partial_workflow({
|
|
||||||
id: "wf-xxx",
|
|
||||||
operations: [{ type: "deactivateWorkflow" }]
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
### Reactivar
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
mcp__n8n__n8n_update_partial_workflow({
|
|
||||||
id: "wf-xxx",
|
|
||||||
operations: [{ type: "activateWorkflow" }]
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
### Ver Execuções
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
mcp__n8n__n8n_executions({
|
|
||||||
workflowId: "wf-xxx",
|
|
||||||
limit: 10,
|
|
||||||
status: "all"
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
| Problema | Solução |
|
|
||||||
|----------|---------|
|
|
||||||
| Não executa | Verificar workflow activo |
|
|
||||||
| Hora errada | Verificar timezone |
|
|
||||||
| Duplicado | Verificar múltiplos triggers |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*Skill v1.0 | Descomplicar®*
|
|
||||||
@@ -1,168 +0,0 @@
|
|||||||
---
|
|
||||||
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.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Uso
|
|
||||||
|
|
||||||
```
|
|
||||||
/n8n-sync create <origem> <destino> # Criar sync
|
|
||||||
/n8n-sync list # Listar syncs
|
|
||||||
/n8n-sync status <workflow_id> # Ver estado
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Workflow Obrigatório
|
|
||||||
|
|
||||||
```
|
|
||||||
1. Health check → mcp__n8n__n8n_health_check()
|
|
||||||
2. Pesquisar template → mcp__n8n__search_templates({ task: "data_sync" })
|
|
||||||
3. Se template OK → mcp__n8n__n8n_deploy_template()
|
|
||||||
4. Se criar do zero → Seguir fluxo abaixo
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Padrões de Sync
|
|
||||||
|
|
||||||
### One-Way (Unidireccional)
|
|
||||||
|
|
||||||
```
|
|
||||||
Origem → Transform → Destino
|
|
||||||
```
|
|
||||||
|
|
||||||
### Two-Way (Bidireccional)
|
|
||||||
|
|
||||||
```
|
|
||||||
A ←→ B (com resolução de conflitos)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Hub-and-Spoke
|
|
||||||
|
|
||||||
```
|
|
||||||
A ↔ HUB ↔ B
|
|
||||||
↕
|
|
||||||
C
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Nodes por Sistema
|
|
||||||
|
|
||||||
### APIs/CRM
|
|
||||||
|
|
||||||
| Node | Sistema |
|
|
||||||
|------|---------|
|
|
||||||
| `nodes-base.httpRequest` | APIs genéricas |
|
|
||||||
| `nodes-base.webhook` | Receber dados |
|
|
||||||
|
|
||||||
### Bases de Dados
|
|
||||||
|
|
||||||
| Node | Sistema |
|
|
||||||
|------|---------|
|
|
||||||
| `nodes-base.postgres` | PostgreSQL |
|
|
||||||
| `nodes-base.mySql` | MySQL |
|
|
||||||
| `nodes-base.mongoDb` | MongoDB |
|
|
||||||
|
|
||||||
### Ficheiros
|
|
||||||
|
|
||||||
| Node | Sistema |
|
|
||||||
|------|---------|
|
|
||||||
| `nodes-base.googleSheets` | Google Sheets |
|
|
||||||
| `nodes-base.spreadsheetFile` | Excel/CSV |
|
|
||||||
| `nodes-base.ftp` | FTP/SFTP |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Exemplo: CRM → Sheets
|
|
||||||
|
|
||||||
```
|
|
||||||
Schedule (horário)
|
|
||||||
↓
|
|
||||||
HTTP Request (GET leads)
|
|
||||||
↓
|
|
||||||
IF (há dados?)
|
|
||||||
↓
|
|
||||||
Set (mapear campos)
|
|
||||||
↓
|
|
||||||
Google Sheets (append)
|
|
||||||
↓
|
|
||||||
Slack (confirmar)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Estratégias
|
|
||||||
|
|
||||||
| Estratégia | Uso |
|
|
||||||
|------------|-----|
|
|
||||||
| Full Sync | Apagar tudo + inserir tudo |
|
|
||||||
| Incremental | Apenas modificados (updated_at) |
|
|
||||||
| Delta | Comparar hashes |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Upsert Pattern
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
{
|
|
||||||
nodeType: "nodes-base.postgres",
|
|
||||||
config: {
|
|
||||||
operation: "upsert",
|
|
||||||
table: "clientes",
|
|
||||||
columns: "email,nome,empresa",
|
|
||||||
conflictColumns: "email"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Gestão de Erros
|
|
||||||
|
|
||||||
### Retry
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
{
|
|
||||||
options: {
|
|
||||||
retry: {
|
|
||||||
maxRetries: 3,
|
|
||||||
retryInterval: 1000
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Dead Letter Queue
|
|
||||||
|
|
||||||
```
|
|
||||||
Operação
|
|
||||||
↓ (erro)
|
|
||||||
Error Trigger
|
|
||||||
↓
|
|
||||||
BD (guardar erro)
|
|
||||||
↓
|
|
||||||
Slack (alertar)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
| Problema | Solução |
|
|
||||||
|----------|---------|
|
|
||||||
| Duplicados | Usar upsert |
|
|
||||||
| Timeout | Batches menores |
|
|
||||||
| Rate limit | Adicionar delays |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*Skill v1.0 | Descomplicar®*
|
|
||||||
@@ -1,160 +0,0 @@
|
|||||||
---
|
|
||||||
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.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Uso
|
|
||||||
|
|
||||||
```
|
|
||||||
/n8n-webhook create <descrição> # Criar novo webhook
|
|
||||||
/n8n-webhook list # Listar webhooks existentes
|
|
||||||
/n8n-webhook test <workflow_id> # Testar webhook
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Workflow Obrigatório
|
|
||||||
|
|
||||||
```
|
|
||||||
1. Health check → mcp__n8n__n8n_health_check()
|
|
||||||
2. Pesquisar template → mcp__n8n__search_templates({ query: "webhook" })
|
|
||||||
3. Se template OK → mcp__n8n__n8n_deploy_template()
|
|
||||||
4. Se criar do zero → Seguir fluxo abaixo
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Criar Webhook do Zero
|
|
||||||
|
|
||||||
### Passo 1: Documentação do Node
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
mcp__n8n__get_node({
|
|
||||||
nodeType: "nodes-base.webhook",
|
|
||||||
detail: "standard",
|
|
||||||
includeExamples: true
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
### Passo 2: Validar Configuração
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
mcp__n8n__validate_node({
|
|
||||||
nodeType: "nodes-base.webhook",
|
|
||||||
config: {
|
|
||||||
httpMethod: "POST",
|
|
||||||
path: "meu-webhook",
|
|
||||||
responseMode: "onReceived"
|
|
||||||
},
|
|
||||||
mode: "minimal"
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
### Passo 3: Nodes de Processamento
|
|
||||||
|
|
||||||
| Node | Uso |
|
|
||||||
|------|-----|
|
|
||||||
| `nodes-base.set` | Transformar dados |
|
|
||||||
| `nodes-base.if` | Condicionais |
|
|
||||||
| `nodes-base.code` | JavaScript custom |
|
|
||||||
| `nodes-base.httpRequest` | Chamar APIs |
|
|
||||||
|
|
||||||
### Passo 4: Deploy
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
mcp__n8n__n8n_create_workflow({
|
|
||||||
name: "Webhook - Descrição",
|
|
||||||
nodes: [...],
|
|
||||||
connections: {...},
|
|
||||||
active: true
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Configurações Webhook
|
|
||||||
|
|
||||||
| Parâmetro | Opções | Default |
|
|
||||||
|-----------|--------|---------|
|
|
||||||
| `httpMethod` | GET, POST, PUT, DELETE | POST |
|
|
||||||
| `path` | String única | (obrigatório) |
|
|
||||||
| `authentication` | none, basicAuth, headerAuth | none |
|
|
||||||
| `responseMode` | onReceived, lastNode | onReceived |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## URL do Webhook
|
|
||||||
|
|
||||||
Após deploy:
|
|
||||||
```
|
|
||||||
https://automator.descomplicar.pt/webhook/<path>
|
|
||||||
```
|
|
||||||
|
|
||||||
Modo teste (workflow inactivo):
|
|
||||||
```
|
|
||||||
https://automator.descomplicar.pt/webhook-test/<path>
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Exemplos
|
|
||||||
|
|
||||||
### Webhook → Slack
|
|
||||||
|
|
||||||
```
|
|
||||||
Webhook (POST /notify)
|
|
||||||
↓
|
|
||||||
Set (formatar)
|
|
||||||
↓
|
|
||||||
Slack (enviar)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Webhook → CRM
|
|
||||||
|
|
||||||
```
|
|
||||||
Webhook (POST /lead)
|
|
||||||
↓
|
|
||||||
HTTP Request (criar no Desk)
|
|
||||||
↓
|
|
||||||
Email (notificar)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Testar
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
mcp__n8n__n8n_test_workflow({
|
|
||||||
workflowId: "wf-xxx",
|
|
||||||
inputData: {
|
|
||||||
body: { "test": "data" },
|
|
||||||
headers: { "Content-Type": "application/json" }
|
|
||||||
}
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl -X POST https://automator.descomplicar.pt/webhook/meu-webhook \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{"test": "data"}'
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
| Problema | Solução |
|
|
||||||
|----------|---------|
|
|
||||||
| 404 Not Found | Workflow não está activo |
|
|
||||||
| 401 Unauthorized | Verificar autenticação |
|
|
||||||
| Dados não chegam | Verificar responseMode |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*Skill v1.0 | Descomplicar®*
|
|
||||||
@@ -0,0 +1,270 @@
|
|||||||
|
---
|
||||||
|
name: n8n
|
||||||
|
description: Meta-skill n8n para criação e gestão de workflows na instância automator.descomplicar.pt. Cobre health check, webhooks, schedule (cron), sync de dados, notify (Slack/email/SMS) e chatbots/AI agents (LangChain/RAG). Triggers — n8n, workflow, automação, webhook, schedule, cron, sync, notify, alerta, slack, chatbot, ai agent, langchain, rag, automator, health check n8n.
|
||||||
|
---
|
||||||
|
|
||||||
|
# /n8n - Meta-skill n8n
|
||||||
|
|
||||||
|
Skill unificada para a instância n8n Descomplicar (`https://automator.descomplicar.pt`, MCP `mcp__n8n__*`). Substitui as antigas n8n-chatbot, n8n-health, n8n-notify, n8n-schedule, n8n-sync, n8n-webhook.
|
||||||
|
|
||||||
|
## Contexto NotebookLM (sempre antes de executar)
|
||||||
|
|
||||||
|
| Notebook | ID |
|
||||||
|
|----------|-----|
|
||||||
|
| n8n Deep Research | `f2c809b8-1cb5-4dd0-aa7e-be2cfb6704d1` |
|
||||||
|
|
||||||
|
```
|
||||||
|
mcp__notebooklm__notebook_query({ notebook_id: "f2c809b8-1cb5-4dd0-aa7e-be2cfb6704d1", query: "<adaptar ao pedido>" })
|
||||||
|
```
|
||||||
|
|
||||||
|
## Workflow obrigatório (qualquer criação)
|
||||||
|
|
||||||
|
```
|
||||||
|
1. mcp__n8n__n8n_health_check()
|
||||||
|
2. mcp__n8n__search_templates({ task: "<webhook|scheduling|data_sync|notification|ai_automation>" })
|
||||||
|
3. Se template adequado -> mcp__n8n__n8n_deploy_template()
|
||||||
|
4. Caso contrário, criar do zero seguindo a secção apropriada abaixo
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Health (diagnóstico)
|
||||||
|
|
||||||
|
```
|
||||||
|
/n8n health # status rápido
|
||||||
|
/n8n health verbose # diagnóstico completo
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
mcp__n8n__n8n_health_check({ mode: "status" })
|
||||||
|
mcp__n8n__n8n_health_check({ mode: "diagnostic", verbose: true })
|
||||||
|
```
|
||||||
|
|
||||||
|
Output esperado: status (OK/ERRO), URL, versão MCP, response time, workflows activos.
|
||||||
|
|
||||||
|
Erros comuns: Connection refused (n8n offline), 401 (API key inválida — regenerar), timeout (rede). Diagnóstico manual:
|
||||||
|
```bash
|
||||||
|
curl -I https://automator.descomplicar.pt
|
||||||
|
curl -H "X-N8N-API-KEY: $KEY" https://automator.descomplicar.pt/api/v1/workflows
|
||||||
|
tail ~/.claude/logs/mcp-n8n.log
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Webhook
|
||||||
|
|
||||||
|
Receber dados de sistemas externos.
|
||||||
|
|
||||||
|
```
|
||||||
|
/n8n webhook create <descrição>
|
||||||
|
/n8n webhook list
|
||||||
|
/n8n webhook test <workflow_id>
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
mcp__n8n__get_node({ nodeType: "nodes-base.webhook", detail: "standard", includeExamples: true })
|
||||||
|
mcp__n8n__validate_node({ nodeType: "nodes-base.webhook", config: { httpMethod: "POST", path: "meu-webhook", responseMode: "onReceived" }, mode: "minimal" })
|
||||||
|
mcp__n8n__n8n_create_workflow({ name: "Webhook - X", nodes: [...], connections: {...}, active: true })
|
||||||
|
```
|
||||||
|
|
||||||
|
Parâmetros: `httpMethod` (GET/POST/PUT/DELETE, default POST), `path` (obrigatório), `authentication` (none/basicAuth/headerAuth), `responseMode` (onReceived/lastNode).
|
||||||
|
|
||||||
|
URLs: produção `https://automator.descomplicar.pt/webhook/<path>` | teste `https://automator.descomplicar.pt/webhook-test/<path>`.
|
||||||
|
|
||||||
|
Nodes processamento: `nodes-base.set`, `nodes-base.if`, `nodes-base.code`, `nodes-base.httpRequest`.
|
||||||
|
|
||||||
|
Teste:
|
||||||
|
```js
|
||||||
|
mcp__n8n__n8n_test_workflow({ workflowId: "wf-xxx", inputData: { body: {test:"data"}, headers: {"Content-Type":"application/json"} } })
|
||||||
|
```
|
||||||
|
```bash
|
||||||
|
curl -X POST https://automator.descomplicar.pt/webhook/meu-webhook -H "Content-Type: application/json" -d '{"test":"data"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
Troubleshooting: 404 (workflow não activo), 401 (auth), dados não chegam (responseMode).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Schedule (cron)
|
||||||
|
|
||||||
|
Workflows com execução agendada.
|
||||||
|
|
||||||
|
```
|
||||||
|
/n8n schedule create <descrição>
|
||||||
|
/n8n schedule list
|
||||||
|
/n8n schedule disable <id>
|
||||||
|
```
|
||||||
|
|
||||||
|
Cron comuns: `0 9 * * *` (diário 9h), `0 9 * * 1-5` (Seg-Sex 9h), `0 */2 * * *` (cada 2h), `*/15 * * * *` (15min), `0 0 1 * *` (dia 1), `0 3 * * 0` (domingos 3h).
|
||||||
|
|
||||||
|
```js
|
||||||
|
mcp__n8n__validate_node({
|
||||||
|
nodeType: "nodes-base.scheduleTrigger",
|
||||||
|
config: { rule: { interval: [{ field: "cronExpression", expression: "0 9 * * 1-5" }] }, options: { timezone: "Europe/Lisbon" } },
|
||||||
|
mode: "minimal"
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Gestão:
|
||||||
|
```js
|
||||||
|
mcp__n8n__n8n_update_partial_workflow({ id: "wf-xxx", operations: [{ type: "deactivateWorkflow" }] })
|
||||||
|
mcp__n8n__n8n_update_partial_workflow({ id: "wf-xxx", operations: [{ type: "activateWorkflow" }] })
|
||||||
|
mcp__n8n__n8n_executions({ workflowId: "wf-xxx", limit: 10, status: "all" })
|
||||||
|
```
|
||||||
|
|
||||||
|
Exemplos: relatório diário (Schedule -> Postgres -> Set -> Email), backup semanal (Schedule -> SSH -> IF -> Slack), limpeza logs.
|
||||||
|
|
||||||
|
Troubleshooting: não executa (workflow inactivo), hora errada (timezone), duplicado (múltiplos triggers).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Sync (sincronização de dados)
|
||||||
|
|
||||||
|
```
|
||||||
|
/n8n sync create <origem> <destino>
|
||||||
|
/n8n sync list
|
||||||
|
/n8n sync status <workflow_id>
|
||||||
|
```
|
||||||
|
|
||||||
|
Padrões: One-Way (origem -> transform -> destino), Two-Way (com resolução conflitos), Hub-and-Spoke.
|
||||||
|
|
||||||
|
Nodes:
|
||||||
|
- APIs: `nodes-base.httpRequest`, `nodes-base.webhook`
|
||||||
|
- BD: `nodes-base.postgres`, `nodes-base.mySql`, `nodes-base.mongoDb`
|
||||||
|
- Ficheiros: `nodes-base.googleSheets`, `nodes-base.spreadsheetFile`, `nodes-base.ftp`
|
||||||
|
|
||||||
|
Estratégias: Full Sync, Incremental (updated_at), Delta (hashes).
|
||||||
|
|
||||||
|
Upsert:
|
||||||
|
```js
|
||||||
|
{ nodeType: "nodes-base.postgres", config: { operation: "upsert", table: "clientes", columns: "email,nome,empresa", conflictColumns: "email" } }
|
||||||
|
```
|
||||||
|
|
||||||
|
Erros: retry (`{ options: { retry: { maxRetries: 3, retryInterval: 1000 } } }`), Dead Letter Queue (Error Trigger -> BD -> Slack).
|
||||||
|
|
||||||
|
Exemplo CRM->Sheets: Schedule -> HTTP GET leads -> IF -> Set -> Google Sheets append -> Slack.
|
||||||
|
|
||||||
|
Troubleshooting: duplicados (upsert), timeout (batches menores), rate limit (delays).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Notify (alertas)
|
||||||
|
|
||||||
|
```
|
||||||
|
/n8n notify create <descrição>
|
||||||
|
/n8n notify slack <mensagem>
|
||||||
|
/n8n notify email <para> <assunto>
|
||||||
|
```
|
||||||
|
|
||||||
|
Canais: Slack (`nodes-base.slack`), Email (`nodes-base.emailSend`), Telegram, Discord, SMS Twilio.
|
||||||
|
|
||||||
|
Slack:
|
||||||
|
```js
|
||||||
|
mcp__n8n__validate_node({
|
||||||
|
nodeType: "nodes-base.slack",
|
||||||
|
config: { resource: "message", operation: "post", channel: "#alertas", text: "..." },
|
||||||
|
mode: "minimal"
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Mensagem formatada (Blocks): header + section com `mrkdwn` e `{{ $json.message }}`.
|
||||||
|
|
||||||
|
Email:
|
||||||
|
```js
|
||||||
|
mcp__n8n__validate_node({
|
||||||
|
nodeType: "nodes-base.emailSend",
|
||||||
|
config: { fromEmail: "alertas@descomplicar.pt", toEmail: "emanuel@descomplicar.pt", subject: "Alerta: {{ $json.title }}", text: "{{ $json.message }}" },
|
||||||
|
mode: "minimal"
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Padrões: Webhook->Slack, Monitor->Multi-canal (Schedule -> HTTP -> IF -> Slack+Email), Error Handler (Error Trigger -> Slack).
|
||||||
|
|
||||||
|
Níveis: Info (Slack), Warning (Slack+Email), Critical (Slack+Email+SMS) — implementar com IF aninhado por `severity`.
|
||||||
|
|
||||||
|
Troubleshooting: Slack não envia (token/canal), email em spam (SPF/DKIM), rate limited (agrupar).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Chatbot / AI Agents (LangChain)
|
||||||
|
|
||||||
|
```
|
||||||
|
/n8n chatbot create <descrição>
|
||||||
|
/n8n chatbot agent <tipo>
|
||||||
|
/n8n chatbot rag <knowledge_base>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Nodes LangChain
|
||||||
|
|
||||||
|
Core: `@n8n/n8n-nodes-langchain.agent`, `chainLlm`, `chainRetrievalQa`.
|
||||||
|
Modelos: `lmChatOpenAi`, `lmChatAnthropic`, `lmChatOllama`.
|
||||||
|
Memória: `memoryBufferWindow`, `memoryPostgresChat`, `memoryRedisChat`.
|
||||||
|
Tools: `toolCalculator`, `toolCode`, `toolHttpRequest`, `toolWorkflow`.
|
||||||
|
Vector Stores: `vectorStoreSupabase`, `vectorStorePinecone`, `vectorStorePgVector`.
|
||||||
|
|
||||||
|
### Chatbot básico
|
||||||
|
|
||||||
|
```
|
||||||
|
Webhook -> LLM Chat -> Memory Buffer -> Agent -> Resposta
|
||||||
|
```
|
||||||
|
|
||||||
|
### RAG
|
||||||
|
|
||||||
|
```
|
||||||
|
Documentos -> Embeddings -> Vector Store -> Query -> Retriever -> LLM
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
mcp__n8n__validate_node({
|
||||||
|
nodeType: "@n8n/n8n-nodes-langchain.vectorStoreSupabase",
|
||||||
|
config: { mode: "insert", tableName: "documents", queryName: "match_documents" },
|
||||||
|
mode: "minimal"
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### AI Agent com tools
|
||||||
|
|
||||||
|
```js
|
||||||
|
mcp__n8n__validate_node({
|
||||||
|
nodeType: "@n8n/n8n-nodes-langchain.agent",
|
||||||
|
config: { agentType: "conversationalAgent", systemMessage: "Tu és um assistente prestável...", options: { returnIntermediateSteps: true } },
|
||||||
|
mode: "minimal"
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Exemplos práticos
|
||||||
|
|
||||||
|
- Suporte: Webhook -> Memory Postgres -> Vector Store -> Chain Retrieval QA -> Webhook Response.
|
||||||
|
- Agent CRM: Webhook -> Agent (tools: pesquisar/criar lead/actualizar tarefa) -> Slack.
|
||||||
|
- Resumo PDFs: Webhook -> PDF Extract -> Text Splitter -> LLM Chain -> Email.
|
||||||
|
|
||||||
|
### Credenciais
|
||||||
|
|
||||||
|
OpenAI/Anthropic (API Key), Supabase (URL+Key), Pinecone (API Key).
|
||||||
|
|
||||||
|
### Boas práticas
|
||||||
|
|
||||||
|
System prompt claro | temperatura 0.1-0.3 | memória limitada | retry on error | logs de conversas.
|
||||||
|
|
||||||
|
### Troubleshooting
|
||||||
|
|
||||||
|
Inconsistente (baixar temperatura), contexto perdido (memória), RAG vazio (embeddings), timeout (limite), token limit (resumir).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Templates
|
||||||
|
|
||||||
|
```js
|
||||||
|
mcp__n8n__search_templates({ searchMode: "by_task", task: "ai_automation" })
|
||||||
|
mcp__n8n__search_templates({ searchMode: "keyword", query: "chatbot langchain openai" })
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Versão:** 2.0.0 (consolidação 6->1, 07-04-2026) | **Autor:** Descomplicar®
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
@@ -122,3 +122,15 @@ mcp__memory-supabase__save_memory {
|
|||||||
---
|
---
|
||||||
|
|
||||||
*Core Standards v1.1 | 2026-03-12*
|
*Core Standards v1.1 | 2026-03-12*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -1,149 +1,65 @@
|
|||||||
---
|
---
|
||||||
name: agent-context-injector
|
name: agent-context-injector
|
||||||
description: Injecção dinâmica de contexto específico para cada agente — MCPs disponíveis, skills relevantes e datasets Dify.
|
description: Injeccao dinamica de contexto (MCPs e Skills) nos agentes via script Python + hook SessionStart com deteccao de staleness.
|
||||||
user-invocable: false
|
user-invocable: false
|
||||||
allowed-tools: Read, Glob, Grep, ToolSearch
|
allowed-tools: Read, Glob, Grep, ToolSearch
|
||||||
---
|
---
|
||||||
|
|
||||||
# Agent Context Injector
|
# Agent Context Injector
|
||||||
|
|
||||||
Injecção dinâmica de contexto específico para cada agente.
|
Regeneracao automatica das seccoes "Your Available MCPs" e "Your Available Skills" em todos os agentes.
|
||||||
|
|
||||||
## Triggers
|
## Como funciona
|
||||||
|
|
||||||
Esta skill é activada automaticamente via hook `SubagentStart` quando:
|
1. **Hook SessionStart** (`~/.claude/hooks/agent-context-refresh.sh`) calcula hash dos inputs
|
||||||
- Um subagente é iniciado via Task tool
|
2. Se hash mudou → executa `~/.claude/scripts/regenerate-agent-context.py`
|
||||||
- Contexto precisa ser enriquecido com recursos do agente
|
3. Script le frontmatter de cada agente, inventario MCPs, mapeamento domain e skills dos plugins
|
||||||
|
4. Gera seccoes entre marcadores `<!-- BEGIN:AUTO-CONTEXT -->` / `<!-- END:AUTO-CONTEXT -->`
|
||||||
|
5. Guarda novo hash em `~/.claude/.agent-context-hash`
|
||||||
|
|
||||||
## Capabilities
|
## Ficheiros
|
||||||
|
|
||||||
### 1. Context Building
|
| Ficheiro | Funcao |
|
||||||
- Consultar mapeamento agente → recursos na BD
|
|----------|--------|
|
||||||
- Gerar lista de MCPs disponíveis para o agente
|
| `~/.claude/scripts/regenerate-agent-context.py` | Script principal de regeneracao |
|
||||||
- Gerar lista de skills relevantes
|
| `~/.claude/hooks/agent-context-refresh.sh` | Hook SessionStart com staleness |
|
||||||
- Incluir datasets Dify para consulta automática
|
| `~/.claude/_resources/domain-mcp-map.json` | Mapeamento domain -> MCPs recomendados |
|
||||||
|
| `~/.claude/_resources/mcps.json` | Inventario de 34+ MCPs |
|
||||||
|
| `~/.claude/.agent-context-hash` | Hash MD5 dos inputs (staleness) |
|
||||||
|
|
||||||
### 2. Token Optimization
|
## Dados de entrada
|
||||||
- Calcular tokens do contexto gerado
|
|
||||||
- Priorizar recursos por relevância
|
|
||||||
- Truncar se exceder limite (~800 tokens)
|
|
||||||
- Cache de contextos frequentes
|
|
||||||
|
|
||||||
### 3. Dynamic Injection
|
- **Agentes:** `~/.claude/agents/*.md` — frontmatter com `domain`, `skills`
|
||||||
- Adicionar contexto ao prompt do agente
|
- **MCPs:** `~/.claude/_resources/mcps.json` — lista com `id`, `name`, `category`
|
||||||
- Incluir instruções de uso dos recursos
|
- **Domain map:** `~/.claude/_resources/domain-mcp-map.json` — primary/recommended por domain
|
||||||
- Configurar auto-consult para datasets
|
- **Skills:** `descomplicar-plugins/*/skills/*/SKILL.md` — frontmatter com `name`, `description`
|
||||||
|
|
||||||
## Template de Contexto
|
## Performance
|
||||||
|
|
||||||
```markdown
|
| Cenario | Tempo |
|
||||||
## Recursos Disponíveis
|
|---------|-------|
|
||||||
|
| Sem mudancas (hash match) | ~66ms |
|
||||||
|
| Com regeneracao (61 agentes) | ~2-3s |
|
||||||
|
|
||||||
### MCPs Activos
|
## Manutencao
|
||||||
$MCP_LIST
|
|
||||||
- Usar proactivamente para operações relevantes
|
|
||||||
|
|
||||||
### Skills Recomendadas
|
- **Adicionar MCP:** actualizar `mcps.json` e `domain-mcp-map.json` → proximo SessionStart regenera
|
||||||
$SKILLS_LIST
|
- **Adicionar skill:** criar SKILL.md no plugin → proximo SessionStart regenera
|
||||||
- Invocar quando tarefa corresponder
|
- **Adicionar agente:** criar .md com frontmatter `domain:` → proximo SessionStart gera contexto
|
||||||
|
- **Mudar domain map:** editar `domain-mcp-map.json` → proximo SessionStart regenera
|
||||||
|
|
||||||
### Knowledge Base (Dify)
|
## Tarefa Desk
|
||||||
$DATASETS_LIST
|
|
||||||
- AUTO-CONSULT: Consultar ANTES de responder
|
|
||||||
- Query template: "$QUERY_TEMPLATE"
|
|
||||||
|
|
||||||
### Plugins
|
#1996 — Sistema injeccao Skills e MCPs nos agentes
|
||||||
$PLUGINS_LIST
|
|
||||||
- Comandos disponíveis: $PLUGIN_COMMANDS
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Workflow
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|
||||||
```
|
|
||||||
SUBAGENT START → QUERY BD → BUILD CONTEXT → INJECT → EXECUTE
|
|
||||||
```
|
|
||||||
|
|
||||||
1. **Hook SubagentStart** dispara
|
|
||||||
2. **Identificar agente** pelo `subagent_type`
|
|
||||||
3. **Query MySQL**:
|
|
||||||
```sql
|
|
||||||
SELECT r.resource_type, r.resource_id, r.priority
|
|
||||||
FROM cr_agent_resources r
|
|
||||||
JOIN cr_agents a ON r.agent_id = a.id
|
|
||||||
WHERE a.slug = '{agent_slug}'
|
|
||||||
AND r.auto_inject = TRUE
|
|
||||||
ORDER BY r.priority ASC;
|
|
||||||
```
|
|
||||||
4. **Consultar agent-knowledge-config.json** para datasets
|
|
||||||
5. **Gerar contexto** com template
|
|
||||||
6. **Calcular tokens** e optimizar se necessário
|
|
||||||
7. **Injectar** no prompt do agente
|
|
||||||
|
|
||||||
## Métricas Target
|
|
||||||
|
|
||||||
| Métrica | Target |
|
|
||||||
|---------|--------|
|
|
||||||
| Tempo de injecção | < 2s |
|
|
||||||
| Tokens médios | ~772 |
|
|
||||||
| Cache hit rate | > 60% |
|
|
||||||
| Erro rate | < 1% |
|
|
||||||
|
|
||||||
## Exemplo de Output
|
|
||||||
|
|
||||||
Para `wordpress-plugin-developer`:
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
## Recursos Disponíveis
|
|
||||||
|
|
||||||
### MCPs Activos
|
|
||||||
- `cwp` - Gestão servidor CentOS WebPanel
|
|
||||||
- `ssh-unified` - Acesso SSH a servidores
|
|
||||||
- `filesystem` - Operações de ficheiros
|
|
||||||
|
|
||||||
### Skills Recomendadas
|
|
||||||
- `/wp-dev` - Desenvolvimento WordPress
|
|
||||||
- `/wp-performance` - Optimização performance
|
|
||||||
- `/elementor` - Desenvolvimento Elementor
|
|
||||||
|
|
||||||
### Knowledge Base (Dify)
|
|
||||||
- `wordpress-development` - Docs WP, hooks, filters
|
|
||||||
- `woocommerce-api` - API WooCommerce
|
|
||||||
- AUTO-CONSULT: Consultar ANTES de implementar
|
|
||||||
|
|
||||||
### Plugins
|
|
||||||
- `superpowers` - TDD obrigatório
|
|
||||||
- `code-review` - Review automático
|
|
||||||
```
|
|
||||||
|
|
||||||
## Configuração
|
|
||||||
|
|
||||||
Ficheiro `agent-knowledge-config.json`:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"wordpress-plugin-developer": {
|
|
||||||
"datasets": ["wordpress-development", "woocommerce-api"],
|
|
||||||
"auto_consult": true,
|
|
||||||
"query_template": "WordPress {topic} best practices 2026",
|
|
||||||
"priority_datasets": ["wordpress-development"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Integração com Scripts Existentes
|
|
||||||
|
|
||||||
Este skill complementa (não substitui) os scripts Python existentes:
|
|
||||||
- `inject-mcp-context.py` - Continua activo
|
|
||||||
- `inject-skills-context.py` - Continua activo
|
|
||||||
|
|
||||||
A skill adiciona:
|
|
||||||
- Datasets Dify dinâmicos
|
|
||||||
- Plugins activos
|
|
||||||
- Contexto mais rico e actualizado
|
|
||||||
|
|
||||||
## Limites
|
|
||||||
|
|
||||||
- Máximo ~800 tokens de contexto injectado (para preservar espaço)
|
|
||||||
- Não modifica comportamento do agente, apenas enriquece contexto
|
|
||||||
- Depende de mapeamentos correctos em `cr_agent_resources`
|
|
||||||
- Cache de 5 minutos pode mostrar dados desactualizados
|
|
||||||
- Não funciona para agentes não registados na BD
|
|
||||||
|
|||||||
@@ -283,3 +283,14 @@ Component Generator:
|
|||||||
- Não cria componentes duplicados (verifica slug existente)
|
- Não cria componentes duplicados (verifica slug existente)
|
||||||
- Requer conexão MySQL para registo em cr_*
|
- Requer conexão MySQL para registo em cr_*
|
||||||
- Não modifica componentes existentes (usar Edit tool)
|
- Não modifica componentes existentes (usar Edit tool)
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -260,3 +260,15 @@ Resultado:
|
|||||||
- Backup não inclui tabelas não-cr_*
|
- Backup não inclui tabelas não-cr_*
|
||||||
- Optimização pode demorar em tabelas grandes (>1M registos)
|
- Optimização pode demorar em tabelas grandes (>1M registos)
|
||||||
- Não substitui backups gerais do Desk CRM
|
- Não substitui backups gerais do Desk CRM
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -203,3 +203,15 @@ Infrastructure Manager:
|
|||||||
- Detecção de órfãos limitada a tabelas cr_* conhecidas
|
- Detecção de órfãos limitada a tabelas cr_* conhecidas
|
||||||
- Não corrige problemas automaticamente (apenas reporta)
|
- Não corrige problemas automaticamente (apenas reporta)
|
||||||
- Telemetria depende de hooks activos e funcionais
|
- Telemetria depende de hooks activos e funcionais
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -175,3 +175,15 @@ Link Desk CRM: `https://desk.descomplicar.pt/admin/projects/view/65`
|
|||||||
---
|
---
|
||||||
|
|
||||||
**Desk CRM:** Projecto #65, Task #1637
|
**Desk CRM:** Projecto #65, Task #1637
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -18,30 +18,30 @@ Esta skill deve ser activada quando:
|
|||||||
|
|
||||||
## Capabilities
|
## Capabilities
|
||||||
|
|
||||||
### 1. Discovery
|
### 1. Gap Analysis
|
||||||
|
- Mapear funcionalidades existentes
|
||||||
|
- Identificar áreas sem cobertura
|
||||||
|
- Sugerir plugins ou skills a desenvolver
|
||||||
|
- Priorizar baseado em uso real
|
||||||
|
|
||||||
|
### 2. Discovery
|
||||||
- Pesquisar marketplaces oficiais e comunitários
|
- Pesquisar marketplaces oficiais e comunitários
|
||||||
- Avaliar relevância baseada no contexto actual
|
- Avaliar relevância baseada no contexto actual
|
||||||
- Identificar plugins com funcionalidades sobrepostas
|
- Identificar plugins com funcionalidades sobrepostas
|
||||||
- Detectar plugins desactualizados ou abandonados
|
- Detectar plugins desactualizados ou abandonados
|
||||||
|
|
||||||
### 2. Evaluation
|
### 3. Evaluation
|
||||||
- Analisar qualidade do código (se open source)
|
- Analisar qualidade do código (se open source)
|
||||||
- Verificar compatibilidade com sistema actual
|
- Verificar compatibilidade com sistema actual
|
||||||
- Avaliar segurança (hooks, permissões)
|
- Avaliar segurança (hooks, permissões)
|
||||||
- Medir popularidade e manutenção activa
|
- Medir popularidade e manutenção activa
|
||||||
|
|
||||||
### 3. Installation Management
|
### 4. Installation Management
|
||||||
- Instalar plugins recomendados
|
- Instalar plugins recomendados
|
||||||
- Configurar hooks e MCPs do plugin
|
- Configurar hooks e MCPs do plugin
|
||||||
- Resolver conflitos com plugins existentes
|
- Resolver conflitos com plugins existentes
|
||||||
- Gerir actualizações e rollbacks
|
- Gerir actualizações e rollbacks
|
||||||
|
|
||||||
### 4. Gap Analysis
|
|
||||||
- Mapear funcionalidades existentes
|
|
||||||
- Identificar áreas sem cobertura
|
|
||||||
- Sugerir plugins ou skills a desenvolver
|
|
||||||
- Priorizar baseado em uso real
|
|
||||||
|
|
||||||
## Marketplaces Conhecidos
|
## Marketplaces Conhecidos
|
||||||
|
|
||||||
| Marketplace | URL | Tipo |
|
| Marketplace | URL | Tipo |
|
||||||
@@ -56,12 +56,12 @@ Esta skill deve ser activada quando:
|
|||||||
|
|
||||||
```
|
```
|
||||||
score = 0
|
score = 0
|
||||||
score += keyword_match * 3 # Max 3
|
score += keyword_match * 3 # Max 3 (bool: 0|1)
|
||||||
score += category_align * 2 # Max 2
|
score += category_align * 2 # Max 2 (bool: 0|1)
|
||||||
score += popularity # Max 2 (>1k stars)
|
score += popularity # Max 2 (tiered: 0=<100 stars, 1=100-1k, 2=>1k)
|
||||||
score += recent_update # Max 1 (<30 days)
|
score += recent_update # Max 1 (bool: 1 se último commit <30 dias)
|
||||||
score += no_conflicts * 2 # Max 2
|
score += no_conflicts * 2 # Max 2 (bool: 0|1)
|
||||||
# Total max: 10
|
# Total max: 3 + 2 + 2 + 1 + 2 = 10
|
||||||
```
|
```
|
||||||
|
|
||||||
## Workflow
|
## Workflow
|
||||||
@@ -97,3 +97,16 @@ Assistant: [Activa plugin-curator]
|
|||||||
- NUNCA instalar plugins de fontes não verificadas
|
- NUNCA instalar plugins de fontes não verificadas
|
||||||
- Verificar SEMPRE conflitos antes de instalar
|
- Verificar SEMPRE conflitos antes de instalar
|
||||||
- Manter registo de todos os plugins avaliados
|
- Manter registo de todos os plugins avaliados
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"2026-04-06","issue":"Capabilities ordenadas por ordem diferente do Workflow (Discovery 1º, Gap Analysis 4º) — incoerência com fluxo ANALYSE GAPS → SEARCH → EVALUATE → RECOMMEND → INSTALL","fix":"Reordenadas Capabilities para seguir ordem do Workflow: 1.Gap Analysis 2.Discovery 3.Evaluation 4.Installation Management","source":"auto"}
|
||||||
|
{"date":"2026-04-06","issue":"Scoring algorithm: score += popularity sem multiplicador e sem documentar escala — ambíguo se max é 1 (bool) ou 2 (tiered)","fix":"Adicionados comentários inline a todos os campos: tipo (bool/tiered), escala e critério. Confirmada soma: 3+2+2+1+2=10.","source":"auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -141,3 +141,15 @@ Avalia todas as regras e sugere `/plugin-config apply` se detectar alteracoes ne
|
|||||||
---
|
---
|
||||||
|
|
||||||
*Skill v3.0.0 | 04-03-2026 | Descomplicar*
|
*Skill v3.0.0 | 04-03-2026 | Descomplicar*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -188,3 +188,15 @@ Quality Validator:
|
|||||||
- Não modifica componentes (apenas lê e reporta)
|
- Não modifica componentes (apenas lê e reporta)
|
||||||
- Não cria componentes (usar component-generator)
|
- Não cria componentes (usar component-generator)
|
||||||
- Não executa correções automáticas (usar /descomplicar:upgrade)
|
- Não executa correções automáticas (usar /descomplicar:upgrade)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -223,3 +223,15 @@ Relationship Manager:
|
|||||||
- Análise de impacto limitada a relacionamentos directos
|
- Análise de impacto limitada a relacionamentos directos
|
||||||
- Não propaga alterações automaticamente (requer confirmação)
|
- Não propaga alterações automaticamente (requer confirmação)
|
||||||
- Depende de consistência das tabelas cr_* na BD
|
- Depende de consistência das tabelas cr_* na BD
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "crm-ops",
|
"name": "crm-ops",
|
||||||
"description": "CRM operations, sales management, leads, customers, estimates, invoices, tickets and expense tracking with Desk CRM. Backed by NotebookLM notebooks.",
|
"description": "CRM operations, sales management, leads, customers, estimates, invoices, tickets and expense tracking with Desk CRM. Backed by NotebookLM notebooks.",
|
||||||
"version": "1.1.0",
|
"version": "1.2.0",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Descomplicar - Crescimento Digital",
|
"name": "Descomplicar - Crescimento Digital",
|
||||||
"url": "https://descomplicar.pt"
|
"url": "https://descomplicar.pt"
|
||||||
@@ -14,6 +14,8 @@
|
|||||||
"leads",
|
"leads",
|
||||||
"facturacao",
|
"facturacao",
|
||||||
"tickets",
|
"tickets",
|
||||||
"orcamento"
|
"orcamento",
|
||||||
|
"suporte",
|
||||||
|
"sla"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,184 @@
|
|||||||
|
---
|
||||||
|
name: support-specialist
|
||||||
|
description: >
|
||||||
|
Especialista de suporte D2 para triagem, atribuição e follow-up de tickets. Executor
|
||||||
|
autónomo baseado nos PROCs D2-SUP-001/002/003. Usar para: triagem tickets, atribuição
|
||||||
|
por prioridade SLA, follow-up clientes, verificação SLA, escalação automática, relatório
|
||||||
|
suporte, gestão tickets Desk CRM.
|
||||||
|
role: Especialista de Suporte D2
|
||||||
|
domain: Support, CRM
|
||||||
|
model: sonnet
|
||||||
|
tools: Read, Glob, Grep, ToolSearch
|
||||||
|
|
||||||
|
primary_mcps:
|
||||||
|
- desk-crm-v3
|
||||||
|
recommended_mcps:
|
||||||
|
- memory-supabase
|
||||||
|
- mcp-time
|
||||||
|
|
||||||
|
primary_skills:
|
||||||
|
- ticket-manage
|
||||||
|
- ticket
|
||||||
|
- ticket-triage
|
||||||
|
- crm
|
||||||
|
recommended_skills:
|
||||||
|
- today
|
||||||
|
- worklog
|
||||||
|
|
||||||
|
desk_project: 65
|
||||||
|
tags:
|
||||||
|
- agent
|
||||||
|
- suporte
|
||||||
|
- d2
|
||||||
|
- tickets
|
||||||
|
- sla
|
||||||
|
- desk-crm
|
||||||
|
version: "1.0"
|
||||||
|
status: active
|
||||||
|
quality_score: 75
|
||||||
|
compliance:
|
||||||
|
sacred_rules: true
|
||||||
|
data_sources: true
|
||||||
|
|
||||||
|
reports_to: Emanuel Almeida
|
||||||
|
collaborates_with:
|
||||||
|
- sales-manager
|
||||||
|
- lead-qualifier
|
||||||
|
escalates_to:
|
||||||
|
- Emanuel Almeida (P1 crítico, SLA violado)
|
||||||
|
- D7 Tecnologia (problemas técnicos complexos)
|
||||||
|
|
||||||
|
created: "2026-04-07"
|
||||||
|
updated: "2026-04-07"
|
||||||
|
author: "Descomplicar®"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Support Specialist Descomplicar
|
||||||
|
|
||||||
|
Especialista de suporte D2 responsável pela triagem, atribuição e follow-up de tickets no Desk CRM. Opera de forma autónoma seguindo os PROCs D2 Suporte (SUP-001, SUP-002, SUP-003).
|
||||||
|
|
||||||
|
## System Prompt
|
||||||
|
|
||||||
|
Você é o especialista de suporte D2 da Descomplicar®. A sua missão é garantir que todos os tickets de suporte são tratados com profissionalismo, dentro dos SLAs definidos, e que os clientes recebem respostas claras e soluções eficazes.
|
||||||
|
|
||||||
|
### Regras Obrigatórias (checklist antes de agir)
|
||||||
|
|
||||||
|
- [ ] **SLA Primeiro**: Verificar sempre o estado SLA antes de responder (`/ticket-manage sla`)
|
||||||
|
- [ ] **Contexto Cliente**: Consultar histórico do cliente via `/crm` antes de responder
|
||||||
|
- [ ] **Checklist Fecho**: NUNCA fechar ticket sem checklist 100% completa (`/ticket-manage close`)
|
||||||
|
- [ ] **Causa Raiz**: Identificar causa real, não só sintoma
|
||||||
|
- [ ] **Confirmar Resolução**: Aguardar confirmação do cliente antes de fechar
|
||||||
|
- [ ] **Registar Lições**: Documentar novos problemas na KB
|
||||||
|
|
||||||
|
### Prioridades de Actuação
|
||||||
|
|
||||||
|
1. **P1 Crítico** — Acção imediata (<30min). Notificar Emanuel se não resolvido em 1h
|
||||||
|
2. **P2 Funcional** — Resposta em 2h. Escalar para D7 se não resolvido em 12h
|
||||||
|
3. **P3 Dúvida** — Resposta em 4h. Consultar KB/WikiJS antes de responder
|
||||||
|
4. **P4 Melhoria** — Registar para sprint. Confirmar ao cliente o registo
|
||||||
|
|
||||||
|
### Output Format Padrão
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Ticket #X — [Assunto]
|
||||||
|
|
||||||
|
### Estado
|
||||||
|
- **Prioridade:** P[N] [Nome]
|
||||||
|
- **Cliente:** [Nome] ([email])
|
||||||
|
- **Aberto há:** Xh
|
||||||
|
- **SLA:** [OK/EM RISCO/VIOLADO]
|
||||||
|
|
||||||
|
### Acção Tomada
|
||||||
|
[Descrição do que foi feito]
|
||||||
|
|
||||||
|
### Próximo Passo
|
||||||
|
[Acção seguinte + responsável + prazo]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Responsabilidades
|
||||||
|
|
||||||
|
- Triagem diária de tickets novos (classificar P1-P4 por impacto)
|
||||||
|
- Atribuição correcta por área: técnica → D7, billing → D3, comercial → D1
|
||||||
|
- Primeira resposta dentro do SLA em todos os tickets
|
||||||
|
- Follow-up proactivo em tickets P1/P2 sem resposta do cliente >24h
|
||||||
|
- Verificação semanal de cumprimento SLA e relatório (`/ticket-manage report`)
|
||||||
|
- Fecho com checklist obrigatória e registo de lições aprendidas
|
||||||
|
|
||||||
|
## Workflows
|
||||||
|
|
||||||
|
### Workflow 1: Triagem Diária
|
||||||
|
```
|
||||||
|
1. /ticket-manage → Ver dashboard SLA + tickets em risco
|
||||||
|
2. Para cada ticket NOVO:
|
||||||
|
a. Classificar prioridade (P1-P4) por impacto
|
||||||
|
b. /ticket-manage assign <id> → Atribuir a responsável
|
||||||
|
c. Enviar confirmação de recepção ao cliente
|
||||||
|
3. Para cada ticket EM RISCO:
|
||||||
|
a. Avaliar estado de resolução
|
||||||
|
b. Escalar se necessário: /ticket-manage escalate <id>
|
||||||
|
4. Para cada ticket VIOLADO:
|
||||||
|
a. Notificar Emanuel imediatamente (P1) ou criar alerta (P2/P3)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Workflow 2: Resolver Ticket
|
||||||
|
```
|
||||||
|
1. /ticket view <id> → Ler histórico completo
|
||||||
|
2. /crm → Verificar contexto do cliente (projectos, histórico)
|
||||||
|
3. Diagnosticar: reproduzir problema, consultar KB
|
||||||
|
4. Se técnico WP/servidor: delegar para D7 (/ticket-manage escalate)
|
||||||
|
5. Se billing: verificar /billing-check
|
||||||
|
6. Aplicar solução e testar
|
||||||
|
7. Responder ao cliente com solução + passos prevenção
|
||||||
|
8. Aguardar confirmação → /ticket-manage close <id>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Workflow 3: Follow-up Semanal
|
||||||
|
```
|
||||||
|
1. Tickets no estado "Resolvido" há >3 dias → Contactar cliente
|
||||||
|
2. Verificar NPS respostas dos últimos 7 dias
|
||||||
|
3. /ticket-manage report → Gerar relatório SLA semanal
|
||||||
|
4. Se cumprimento <90% em qualquer prioridade → Criar tarefa melhoria no Desk
|
||||||
|
5. Registar acções correctivas como comentário no ticket #65
|
||||||
|
```
|
||||||
|
|
||||||
|
### Workflow 4: Escalação P1
|
||||||
|
```
|
||||||
|
1. Ticket P1 identificado → Acção imediata
|
||||||
|
2. Tentar resolução directa (máx 30min)
|
||||||
|
3. Se não resolvido: /ticket-manage escalate para D7
|
||||||
|
4. Notificar Emanuel: comentário interno + urgência
|
||||||
|
5. Acompanhar até resolução — actualizações cada 30min
|
||||||
|
```
|
||||||
|
|
||||||
|
## Knowledge Sources
|
||||||
|
|
||||||
|
### Referências PROCs (Consultar SEMPRE)
|
||||||
|
```
|
||||||
|
Read: /media/ealmeida/Dados/Hub/06-Operacoes/Procedimentos/D2-Suporte/PROC-D2-SUP-001-Atendimento-Cliente.md
|
||||||
|
Read: /media/ealmeida/Dados/Hub/06-Operacoes/Procedimentos/D2-Suporte/PROC-D2-SUP-002-Ticketing-Workflow.md
|
||||||
|
Read: /media/ealmeida/Dados/Hub/06-Operacoes/Procedimentos/D2-Suporte/PROC-D2-SUP-003-SLA-Management.md
|
||||||
|
```
|
||||||
|
|
||||||
|
### Desk CRM (Dados Reais)
|
||||||
|
```
|
||||||
|
mcp__desk-crm-v3__get_tickets({ status: [1,2,3] })
|
||||||
|
mcp__desk-crm-v3__get_ticket({ ticket_id: id })
|
||||||
|
mcp__desk-crm-v3__reply_ticket({ ticket_id: id, message: html, internal: false })
|
||||||
|
mcp__desk-crm-v3__close_ticket({ ticket_id: id })
|
||||||
|
```
|
||||||
|
|
||||||
|
## Métricas de Sucesso
|
||||||
|
|
||||||
|
| Métrica | Meta |
|
||||||
|
|---------|------|
|
||||||
|
| SLA resposta cumprido | >95% |
|
||||||
|
| SLA resolução cumprido | >90% |
|
||||||
|
| Resolução 1º contacto | >60% |
|
||||||
|
| NPS médio | >8/10 |
|
||||||
|
| Tickets P1 violados | 0/semana |
|
||||||
|
|
||||||
|
## Colaboração
|
||||||
|
|
||||||
|
- **Reporta a**: Emanuel Almeida
|
||||||
|
- **Colabora com**: sales-manager (tickets pós-venda), lead-qualifier (clientes novos)
|
||||||
|
- **Escalar para**: Emanuel (P1 crítico, SLA violado), D7 Tecnologia (tech complexo)
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
---
|
---
|
||||||
name: auto-expense
|
name: auto-expense
|
||||||
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.
|
description: Criação automática de despesas a partir de facturas detectadas no IMAP e tickets. Extrai dados, verifica duplicados por reference_no e cria despesas no Desk CRM com PDF anexo.
|
||||||
disable-model-invocation: true
|
disable-model-invocation: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# /auto-expense v1.0
|
# /auto-expense v1.1
|
||||||
|
|
||||||
Cria despesas automaticamente a partir de facturas detectadas pelo IMAP e tickets.
|
Cria despesas automaticamente a partir de facturas detectadas pelo IMAP e tickets.
|
||||||
|
|
||||||
@@ -49,28 +49,57 @@ Para cada factura na lista:
|
|||||||
|
|
||||||
3. EXTRAIR DO HTML:
|
3. EXTRAIR DO HTML:
|
||||||
- Valor (padroes: $XX.XX, XX,XX EUR, USD XX.XX, Total: XX.XX)
|
- Valor (padroes: $XX.XX, XX,XX EUR, USD XX.XX, Total: XX.XX)
|
||||||
- Referencia/Invoice number
|
- Referencia/Invoice number (OBRIGATORIO — guardar para dedup)
|
||||||
- Data da factura
|
- Data da factura
|
||||||
|
|
||||||
4. VERIFICAR DUPLICADO (2 camadas):
|
|
||||||
Camada 1 - Desk CRM:
|
|
||||||
Pesquisar: mesmo fornecedor + mesmo valor (±0.05) + mesma data (±3 dias)
|
|
||||||
Se match → NAO criar, registar como duplicado
|
|
||||||
|
|
||||||
5. CRIAR DESPESA:
|
|
||||||
mcp__desk-crm-v3__create_expense({
|
|
||||||
category: [cat_id da tabela],
|
|
||||||
amount: [valor],
|
|
||||||
date: [data factura YYYY-MM-DD],
|
|
||||||
expense_name: "[Fornecedor] - [Referencia]",
|
|
||||||
note: "Auto-criado via /auto-expense",
|
|
||||||
currency: [2=USD ou 3=EUR],
|
|
||||||
tax: [0 ou 1],
|
|
||||||
send_invoice_to_customer: 0
|
|
||||||
})
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Passo 3: PDF (se existir anexo)
|
### Passo 3: Verificar duplicados (OBRIGATORIO — 3 camadas)
|
||||||
|
|
||||||
|
> **CRITICO: Este passo NUNCA pode ser saltado. Se saltado, causa duplicacao massiva de despesas.**
|
||||||
|
|
||||||
|
```
|
||||||
|
Camada 0 — Referencia de factura (PRIMARIA, mais fiavel):
|
||||||
|
get_expenses(search: "<reference_no>")
|
||||||
|
Para cada resultado: comparar campo reference_no
|
||||||
|
Se alguma despesa tem reference_no IGUAL → DUPLICADO CONFIRMADO
|
||||||
|
→ NAO criar, registar como duplicado com ID existente
|
||||||
|
|
||||||
|
Camada 1 — Fornecedor + Valor + Data:
|
||||||
|
get_expenses(search: "<fornecedor>")
|
||||||
|
Filtrar: mesmo valor (±0.05) + mesma data (±3 dias)
|
||||||
|
Se match → NAO criar, registar como duplicado
|
||||||
|
|
||||||
|
Camada 2 — Expense name pattern:
|
||||||
|
get_expenses(search: "<fornecedor> - <reference_no>")
|
||||||
|
Se match exacto no expense_name → NAO criar, registar como duplicado
|
||||||
|
|
||||||
|
REGRA: Se QUALQUER camada detecta duplicado → PARAR imediatamente.
|
||||||
|
Nunca criar despesa sem passar as 3 camadas com sucesso.
|
||||||
|
Registar cada duplicado detectado no output JSON (campo "duplicados").
|
||||||
|
```
|
||||||
|
|
||||||
|
### Passo 4: Criar despesa
|
||||||
|
|
||||||
|
```
|
||||||
|
APENAS se Passo 3 passou sem detectar duplicado:
|
||||||
|
|
||||||
|
mcp__desk-crm-v3__create_expense({
|
||||||
|
category: [cat_id da tabela],
|
||||||
|
amount: [valor],
|
||||||
|
date: [data factura YYYY-MM-DD],
|
||||||
|
expense_name: "[Fornecedor] - [Referencia]",
|
||||||
|
reference_no: "[numero factura/referencia]",
|
||||||
|
note: "Auto-criado via /auto-expense",
|
||||||
|
currency: [2=USD ou 3=EUR],
|
||||||
|
tax: [0 ou 1],
|
||||||
|
send_invoice_to_customer: 0
|
||||||
|
})
|
||||||
|
|
||||||
|
OBRIGATORIO: campo reference_no DEVE ser preenchido com o numero
|
||||||
|
de factura extraido. Este campo e a chave primaria de deduplicacao.
|
||||||
|
```
|
||||||
|
|
||||||
|
### Passo 5: PDF (se existir anexo)
|
||||||
|
|
||||||
```
|
```
|
||||||
a. GUARDAR LOCAL:
|
a. GUARDAR LOCAL:
|
||||||
@@ -100,14 +129,14 @@ c. REGISTAR no Desk BD:
|
|||||||
d. LIMPAR temporarios
|
d. LIMPAR temporarios
|
||||||
```
|
```
|
||||||
|
|
||||||
### Passo 4: Actualizar CSV
|
### Passo 6: Actualizar CSV
|
||||||
|
|
||||||
```
|
```
|
||||||
CSV Path: /media/ealmeida/Dados/GDrive/Cloud/ADM_Descomplicar/Financeiro/Contabilidade/YYYY/MAPA-DESPESAS-YYYY.csv
|
CSV Path: /media/ealmeida/Dados/GDrive/Cloud/ADM_Descomplicar/Financeiro/Contabilidade/YYYY/MAPA-DESPESAS-YYYY.csv
|
||||||
Formato linha: id_desk;data;categoria;fornecedor;descricao;valor;SIM;ficheiro;email;Auto /auto-expense
|
Formato linha: id_desk;data;categoria;fornecedor;descricao;valor;SIM;ficheiro;email;Auto /auto-expense
|
||||||
```
|
```
|
||||||
|
|
||||||
### Passo 5: Escrever output JSON
|
### Passo 7: Escrever output JSON
|
||||||
|
|
||||||
```
|
```
|
||||||
Escrever em ~/.claude-work/today-expenses-{date}.json:
|
Escrever em ~/.claude-work/today-expenses-{date}.json:
|
||||||
@@ -115,12 +144,15 @@ Escrever em ~/.claude-work/today-expenses-{date}.json:
|
|||||||
"despesas_criadas": [
|
"despesas_criadas": [
|
||||||
{"id": 1180, "fornecedor": "MEO", "valor": 76.26, "moeda": "EUR", "referencia": "FT A/861215955"}
|
{"id": 1180, "fornecedor": "MEO", "valor": 76.26, "moeda": "EUR", "referencia": "FT A/861215955"}
|
||||||
],
|
],
|
||||||
"duplicados": 0,
|
"duplicados": [
|
||||||
|
{"fornecedor": "MEO", "referencia": "FT A/861215955", "existente_id": 1175, "camada": 0}
|
||||||
|
],
|
||||||
"flagged": [
|
"flagged": [
|
||||||
{"fornecedor": "Desconhecido", "nota": "TOConline - emitente desconhecido: XPTO LDA"}
|
{"fornecedor": "Desconhecido", "nota": "TOConline - emitente desconhecido: XPTO LDA"}
|
||||||
],
|
],
|
||||||
"erros": [],
|
"erros": [],
|
||||||
"total_processadas": 1
|
"total_processadas": 1,
|
||||||
|
"total_duplicados": 0
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -152,7 +184,7 @@ tax = 0 → Fornecedores estrangeiros
|
|||||||
|
|
||||||
send_invoice_to_customer = 0 → OBRIGATORIO (sem default na BD)
|
send_invoice_to_customer = 0 → OBRIGATORIO (sem default na BD)
|
||||||
|
|
||||||
reference_no → coluna correcta (NAO "reference")
|
reference_no → coluna correcta (NAO "reference") — CHAVE DE DEDUPLICACAO
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -167,7 +199,8 @@ reference_no → coluna correcta (NAO "reference")
|
|||||||
|--------|-----------|-------|-------|-----|-----|
|
|--------|-----------|-------|-------|-----|-----|
|
||||||
|
|
||||||
### Duplicados Detectados (Y)
|
### Duplicados Detectados (Y)
|
||||||
- [Fornecedor] [Valor] - ja existe como #ID
|
| Fornecedor | Ref | ID Existente | Camada |
|
||||||
|
|-----------|-----|-------------|--------|
|
||||||
|
|
||||||
### Pendentes Revisao (Z)
|
### Pendentes Revisao (Z)
|
||||||
- [Plataforma] - emitente desconhecido: [nome]
|
- [Plataforma] - emitente desconhecido: [nome]
|
||||||
@@ -179,11 +212,26 @@ reference_no → coluna correcta (NAO "reference")
|
|||||||
|
|
||||||
- NUNCA usar currency=1 (nao existe)
|
- NUNCA usar currency=1 (nao existe)
|
||||||
- NUNCA converter USD para EUR (manter original com currency=2)
|
- NUNCA converter USD para EUR (manter original com currency=2)
|
||||||
- NUNCA criar despesa sem verificar duplicado primeiro
|
- NUNCA criar despesa sem verificar duplicado primeiro (3 camadas obrigatorias)
|
||||||
- NUNCA omitir send_invoice_to_customer=0
|
- NUNCA omitir send_invoice_to_customer=0
|
||||||
|
- NUNCA omitir reference_no ao criar despesa (chave primaria de dedup)
|
||||||
|
- NUNCA saltar a Camada 0 (referencia de factura) — e a mais fiavel
|
||||||
- SEMPRE ler o email/ticket HTML para extrair valor real (nunca assumir)
|
- SEMPRE ler o email/ticket HTML para extrair valor real (nunca assumir)
|
||||||
- SEMPRE incluir reference_no quando disponivel
|
- SEMPRE incluir reference_no quando disponivel
|
||||||
|
- SEMPRE logar duplicados detectados no output JSON com camada e ID existente
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
*Skill v1.0.0 | 04-03-2026 | Descomplicar®*
|
*Skill v1.1.0 | 30-03-2026 | Descomplicar | Fix: dedup por reference_no (DES-137)*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -293,3 +293,15 @@ Skill:
|
|||||||
3. Executar workflow integrado
|
3. Executar workflow integrado
|
||||||
Output: [resultado completo com referências]
|
Output: [resultado completo com referências]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -223,3 +223,15 @@ Skill:
|
|||||||
3. Executar workflow integrado
|
3. Executar workflow integrado
|
||||||
Output: [resultado completo com referências]
|
Output: [resultado completo com referências]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -1,432 +0,0 @@
|
|||||||
---
|
|
||||||
name: crm-ops
|
|
||||||
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
|
|
||||||
|
|
||||||
Skill para operações CRM com verificações obrigatórias de duplicados e confirmações.
|
|
||||||
|
|
||||||
## Metadata
|
|
||||||
- **Version**: 1.2.0
|
|
||||||
- **Author**: Descomplicar
|
|
||||||
- **Date**: 2026-01-28
|
|
||||||
- **Status**: Active
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Quando Usar
|
|
||||||
|
|
||||||
- Criar lead, customer, proposal, estimate
|
|
||||||
- Pesquisar entidades CRM
|
|
||||||
- Converter lead para customer
|
|
||||||
- Operações que envolvem orçamentos/propostas
|
|
||||||
- Qualquer operação que pode criar duplicados
|
|
||||||
|
|
||||||
## Quando NÃO Usar
|
|
||||||
|
|
||||||
- Para desenvolvimento WordPress (usar /wp-dev)
|
|
||||||
- Para criar orçamentos completos (usar /orcamento)
|
|
||||||
- Para análise de leads (usar /lead-approach)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## DEFINIÇÕES CRÍTICAS
|
|
||||||
|
|
||||||
### Lead vs Customer
|
|
||||||
|
|
||||||
| Aspecto | LEAD | CUSTOMER |
|
|
||||||
|---------|------|----------|
|
|
||||||
| **O que é** | Contacto inicial, prospect | Cliente com relação comercial |
|
|
||||||
| **Quando usar** | Primeiro contacto, ainda a avaliar | Após qualificação, vai comprar |
|
|
||||||
| **Tabela** | `tblleads` | `tblclients` + `tblcontacts` |
|
|
||||||
| **Recebe** | Proposals (orçamentos) | Estimates, Invoices |
|
|
||||||
| **Conversão** | Pode virar Customer | Já é cliente |
|
|
||||||
|
|
||||||
**REGRA:** Novos contactos são SEMPRE leads primeiro. Só se tornam customers após qualificação.
|
|
||||||
|
|
||||||
### Proposal vs Estimate
|
|
||||||
|
|
||||||
| Aspecto | PROPOSAL (Orçamento) | ESTIMATE |
|
|
||||||
|---------|---------------------|----------|
|
|
||||||
| **Para quem** | **LEADS** (prospects) | **CUSTOMERS** (clientes) |
|
|
||||||
| **Quando usar** | Utilizador pede "orçamento" | Cliente existente, pedido formal |
|
|
||||||
| **Tabela** | `tblproposals` | `tblestimates` |
|
|
||||||
| **Converte para** | Nada (lead vira customer primeiro) | Invoice directamente |
|
|
||||||
| **Termo PT** | **Orçamento, Proposta** | Estimativa |
|
|
||||||
|
|
||||||
> **IMPORTANTE:** Quando o utilizador pede um "orçamento", usar **PROPOSAL** (para leads).
|
|
||||||
> Estimates são para clientes já existentes com pedidos formais.
|
|
||||||
|
|
||||||
### Fluxo Comercial Correcto
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────────────────────────────────────┐
|
|
||||||
│ FLUXO COMERCIAL PERFEX │
|
|
||||||
└─────────────────────────────────────────────────────────────────────┘
|
|
||||||
|
|
||||||
LEAD CUSTOMER
|
|
||||||
│ │
|
|
||||||
▼ ▼
|
|
||||||
PROPOSAL ──────────────────────▶ ESTIMATE
|
|
||||||
(orçamento) converter lead (formal)
|
|
||||||
│ para customer │
|
|
||||||
│ │ ▼
|
|
||||||
│ │ INVOICE
|
|
||||||
│ │ │
|
|
||||||
└───────────────┴──────────────────┘
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
PAYMENT
|
|
||||||
```
|
|
||||||
|
|
||||||
**Resumo:**
|
|
||||||
- Lead + Orçamento = **Proposal**
|
|
||||||
- Customer + Orçamento formal = **Estimate**
|
|
||||||
- Estimate aceite = **Invoice**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Protocolo
|
|
||||||
|
|
||||||
### REGRA 0: NUNCA CRIAR SEM VERIFICAR (CRÍTICA)
|
|
||||||
|
|
||||||
> **PROIBIDO criar Lead ou Customer sem verificar se já existe.**
|
|
||||||
|
|
||||||
Esta regra é INVIOLÁVEL. Mesmo que o utilizador peça para criar, PRIMEIRO:
|
|
||||||
|
|
||||||
```
|
|
||||||
1. Pesquisar em LEADS: get_leads() + filtrar por nome/email/empresa
|
|
||||||
2. Pesquisar em CUSTOMERS: search_customers(termo)
|
|
||||||
3. SE encontrar match:
|
|
||||||
- MOSTRAR resultados ao utilizador
|
|
||||||
- PERGUNTAR: "Encontrei [X]. É este ou criar novo?"
|
|
||||||
4. SE não encontrar:
|
|
||||||
- PERGUNTAR: "Não encontrei [Nome]. Confirmas criação?"
|
|
||||||
5. SÓ CRIAR após confirmação explícita
|
|
||||||
```
|
|
||||||
|
|
||||||
**Violação desta regra causa duplicados que prejudicam operações comerciais.**
|
|
||||||
|
|
||||||
### REGRA 1: VERIFICAR DUPLICADOS (Detalhado)
|
|
||||||
|
|
||||||
ANTES de criar QUALQUER entidade (Lead, Customer, Proposal, Estimate):
|
|
||||||
|
|
||||||
1. Pesquisar por nome/email/empresa:
|
|
||||||
- `search_customers` para clientes
|
|
||||||
- `get_leads` com filtro search para leads
|
|
||||||
2. Se match encontrado: MOSTRAR ao utilizador
|
|
||||||
3. Se match parcial: PERGUNTAR se é o mesmo
|
|
||||||
4. Se sem match: PERGUNTAR confirmação antes de criar
|
|
||||||
|
|
||||||
### REGRA 2: CONFIRMAR ANTES DE CRIAR
|
|
||||||
|
|
||||||
NUNCA criar entidade sem confirmação EXPLÍCITA:
|
|
||||||
|
|
||||||
- Lead: "Não encontrei este contacto. Criar lead [Nome] com email [Email]?"
|
|
||||||
- Customer: "Criar cliente [Empresa]? (ACÇÃO IRREVERSÍVEL - só para clientes qualificados)"
|
|
||||||
- Proposal: "Criar orçamento para lead [Nome] no valor de [X]?"
|
|
||||||
- Estimate: "Criar estimativa formal para cliente [Empresa] no valor de [X]?"
|
|
||||||
|
|
||||||
### REGRA 3: MODELO DE DADOS PERFEX
|
|
||||||
|
|
||||||
| Regra | Descrição |
|
|
||||||
|-------|-----------|
|
|
||||||
| Email em tblcontacts | Email do cliente está em tblcontacts, NÃO em tblclients |
|
|
||||||
| userid é o ID | Usar `userid` para clientes, não `customer_id` |
|
|
||||||
| Contacto principal | `is_primary = 1` para contacto principal |
|
|
||||||
| Source obrigatório | Leads precisam de source_id (buscar default) |
|
|
||||||
| Itens em tblitemable | Todos os itens (estimate, invoice, proposal) usam `tblitemable` com `rel_type` |
|
|
||||||
| rel_type para items | 'estimate', 'invoice', 'proposal', 'credit_note' |
|
|
||||||
|
|
||||||
## Comandos
|
|
||||||
|
|
||||||
| Comando | Descrição |
|
|
||||||
|---------|-----------|
|
|
||||||
| `/crm-ops search <termo>` | Pesquisa unificada em leads + customers |
|
|
||||||
| `/crm-ops lead create` | Criar lead COM verificação de duplicados |
|
|
||||||
| `/crm-ops lead convert <id>` | Converter lead em customer |
|
|
||||||
| `/crm-ops customer create` | Criar customer COM confirmação obrigatória |
|
|
||||||
| `/crm-ops estimate create` | Criar estimate COM validação cliente |
|
|
||||||
| `/crm-ops status` | Mostrar códigos de status |
|
|
||||||
|
|
||||||
## Fluxos Detalhados
|
|
||||||
|
|
||||||
### Criar Lead
|
|
||||||
|
|
||||||
```
|
|
||||||
1. Receber dados do lead (nome, email, empresa)
|
|
||||||
2. search_customers(email/nome)
|
|
||||||
3. get_leads(search=email/nome)
|
|
||||||
4. SE match encontrado:
|
|
||||||
- Mostrar resultados
|
|
||||||
- Perguntar: "Usar existente ou criar novo?"
|
|
||||||
5. SE criar novo:
|
|
||||||
- Buscar source default se não fornecido
|
|
||||||
- create_lead
|
|
||||||
6. Retornar ID do lead criado
|
|
||||||
```
|
|
||||||
|
|
||||||
### Converter Lead para Customer
|
|
||||||
|
|
||||||
```
|
|
||||||
1. Verificar lead existe: get_lead(lead_id)
|
|
||||||
2. Mostrar dados do lead ao utilizador
|
|
||||||
3. Perguntar: "Converter lead X para cliente?"
|
|
||||||
4. SE confirmado:
|
|
||||||
- convert_lead_to_customer
|
|
||||||
- Notas são transferidas automaticamente
|
|
||||||
5. Retornar ID do novo cliente
|
|
||||||
```
|
|
||||||
|
|
||||||
### Criar Customer (SEM lead)
|
|
||||||
|
|
||||||
```
|
|
||||||
1. SEMPRE perguntar confirmação ao utilizador
|
|
||||||
2. Verificar se existe lead para converter
|
|
||||||
- SE existe: usar convert_lead_to_customer
|
|
||||||
3. SE não existe lead:
|
|
||||||
- search_customers para verificar duplicados
|
|
||||||
- Confirmar criação
|
|
||||||
- create_customer
|
|
||||||
```
|
|
||||||
|
|
||||||
### Criar Estimate
|
|
||||||
|
|
||||||
```
|
|
||||||
1. Identificar cliente (perguntar se não especificado)
|
|
||||||
2. get_customer para verificar se existe
|
|
||||||
- SE não existe: PARAR, NÃO criar customer automaticamente
|
|
||||||
- Perguntar se deve criar customer primeiro
|
|
||||||
3. Confirmar itens e valores com utilizador
|
|
||||||
4. create_estimate
|
|
||||||
5. Perguntar se deve enviar: send_estimate
|
|
||||||
```
|
|
||||||
|
|
||||||
### Criar Proposal (Suporta Lead OU Customer)
|
|
||||||
|
|
||||||
> **CORRIGIDO v3.5.3:** Proposals agora suportam leads directamente.
|
|
||||||
|
|
||||||
```
|
|
||||||
1. Identificar se é Lead ou Customer
|
|
||||||
2. Usar o parâmetro correcto:
|
|
||||||
- Lead: create_proposal(lead_id=204, subject="...")
|
|
||||||
- Customer: create_proposal(client_id=42, subject="...")
|
|
||||||
3. NÃO usar ambos parâmetros (um OU outro)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Editar Proposal
|
|
||||||
|
|
||||||
```
|
|
||||||
1. Obter proposal_id
|
|
||||||
2. update_proposal(proposal_id=X, subject="...", status=2)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Status de Proposal:**
|
|
||||||
- 1 = Draft
|
|
||||||
- 2 = Sent
|
|
||||||
- 3 = Open
|
|
||||||
- 4 = Revised
|
|
||||||
- 5 = Declined
|
|
||||||
- 6 = Accepted
|
|
||||||
|
|
||||||
### Adicionar Itens a Proposal (v3.5.4)
|
|
||||||
|
|
||||||
```
|
|
||||||
1. Preparar array de itens com: description, qty, rate, unit, long_description
|
|
||||||
2. Chamar add_proposal_items:
|
|
||||||
add_proposal_items(
|
|
||||||
proposal_id=78,
|
|
||||||
clear_existing=true, // opcional: limpar itens anteriores
|
|
||||||
items=[
|
|
||||||
{ description: "Serviço X", qty: 1, rate: 500, unit: "un" },
|
|
||||||
{ description: "Horas Dev", qty: 10, rate: 60, unit: "hora" }
|
|
||||||
]
|
|
||||||
)
|
|
||||||
3. Total da proposta é actualizado automaticamente
|
|
||||||
```
|
|
||||||
|
|
||||||
### Listar Itens de Proposal
|
|
||||||
|
|
||||||
```
|
|
||||||
get_proposal_items(proposal_id=78)
|
|
||||||
```
|
|
||||||
|
|
||||||
Retorna lista de itens com quantidade, valor e total calculado.
|
|
||||||
|
|
||||||
### Converter Estimate para Invoice
|
|
||||||
|
|
||||||
```
|
|
||||||
1. get_estimate para verificar status
|
|
||||||
2. SE status != 4 (Aceite): PARAR e informar
|
|
||||||
3. Confirmar com utilizador
|
|
||||||
4. convert_estimate_to_invoice
|
|
||||||
5. Retornar ID da nova factura
|
|
||||||
```
|
|
||||||
|
|
||||||
## Status Codes
|
|
||||||
|
|
||||||
### Estimates
|
|
||||||
- 1 = Rascunho
|
|
||||||
- 2 = Enviado
|
|
||||||
- 3 = Visto
|
|
||||||
- 4 = Aceite (pode converter)
|
|
||||||
- 5 = Recusado
|
|
||||||
- 6 = Expirado
|
|
||||||
|
|
||||||
### Proposals
|
|
||||||
- 1 = Draft
|
|
||||||
- 2 = Sent
|
|
||||||
- 3 = Open
|
|
||||||
- 4 = Revised
|
|
||||||
- 5 = Declined
|
|
||||||
- 6 = Accepted
|
|
||||||
|
|
||||||
### Invoices
|
|
||||||
- 1 = Unpaid
|
|
||||||
- 2 = Paid
|
|
||||||
- 3 = Partially Paid
|
|
||||||
- 4 = Overdue
|
|
||||||
|
|
||||||
## MCP Tools
|
|
||||||
|
|
||||||
### Leads
|
|
||||||
- get_leads - Listar leads com filtros
|
|
||||||
- create_lead - Criar lead
|
|
||||||
- update_lead - Actualizar lead
|
|
||||||
- convert_lead_to_customer - Converter para cliente
|
|
||||||
- lead_scoring - Pontuar lead
|
|
||||||
- lead_analytics - Métricas
|
|
||||||
|
|
||||||
### Customers
|
|
||||||
- get_customers - Listar clientes
|
|
||||||
- get_customer - Detalhes cliente
|
|
||||||
- create_customer - Criar cliente
|
|
||||||
- search_customers - Pesquisa multi-campo
|
|
||||||
- update_customer - Actualizar
|
|
||||||
- delete_customer - Eliminar
|
|
||||||
- manage_customer_contacts - Gerir contactos
|
|
||||||
- create/get/update/delete_customer_note - Notas
|
|
||||||
|
|
||||||
### Estimates
|
|
||||||
- get_estimates - Listar orçamentos
|
|
||||||
- get_estimate - Detalhes
|
|
||||||
- create_estimate - Criar orçamento
|
|
||||||
- update_estimate - Actualizar
|
|
||||||
- send_estimate - Marcar como enviado
|
|
||||||
- convert_estimate_to_invoice - Converter para factura
|
|
||||||
- estimate_analytics - Métricas
|
|
||||||
|
|
||||||
### Proposals
|
|
||||||
- get_proposals - Listar propostas
|
|
||||||
- create_proposal - Criar proposta (suporta lead_id OU client_id)
|
|
||||||
- update_proposal - Editar proposta existente
|
|
||||||
- add_proposal_items - Adicionar itens/linhas a proposta
|
|
||||||
- get_proposal_items - Listar itens de uma proposta
|
|
||||||
- proposal_builder - Construtor interactivo
|
|
||||||
- proposal_analytics - Métricas
|
|
||||||
|
|
||||||
## Anti-Patterns (NUNCA fazer)
|
|
||||||
|
|
||||||
### Criação sem Verificação (CRÍTICO)
|
|
||||||
1. **NUNCA** criar lead sem pesquisar se já existe
|
|
||||||
2. **NUNCA** criar customer sem pesquisar se já existe
|
|
||||||
3. **NUNCA** assumir que entidade não existe - verificar SEMPRE
|
|
||||||
|
|
||||||
### Confusão de Entidades
|
|
||||||
4. Criar customer quando devia ser lead (novos contactos = leads)
|
|
||||||
5. Usar estimate para leads (usar proposal)
|
|
||||||
6. Usar proposal para customers qualificados (usar estimate)
|
|
||||||
7. Criar customer automaticamente para associar estimate
|
|
||||||
|
|
||||||
### Erros Técnicos
|
|
||||||
8. Converter estimate não-aceite para invoice
|
|
||||||
9. Aceder a email directamente em tblclients (usar JOIN com tblcontacts)
|
|
||||||
10. Usar tabelas inventadas (ex: tblitems_in) - verificar schema real primeiro
|
|
||||||
|
|
||||||
### Terminologia
|
|
||||||
- Utilizador diz "orçamento" para lead → usar **PROPOSAL**
|
|
||||||
- Utilizador diz "orçamento" para cliente existente → usar **ESTIMATE**
|
|
||||||
|
|
||||||
## Exemplos
|
|
||||||
|
|
||||||
### Exemplo 1: Criar lead com verificação
|
|
||||||
```
|
|
||||||
User: /crm-ops lead create nome="João Silva" email="joao@example.com"
|
|
||||||
→ Pesquisa em leads e customers
|
|
||||||
→ Não encontra duplicado
|
|
||||||
→ Pergunta: "Não encontrei João Silva. Confirmas criação?"
|
|
||||||
→ User: Sim
|
|
||||||
→ Cria lead #215
|
|
||||||
→ Confirma: "Lead #215 criado com sucesso"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Exemplo 2: Detectar duplicado
|
|
||||||
```
|
|
||||||
User: /crm-ops customer create empresa="TechStart Lda"
|
|
||||||
→ Pesquisa customers
|
|
||||||
→ Encontra match: TechStart Lda (#42)
|
|
||||||
→ Mostra: "Encontrei TechStart Lda (#42). É este ou criar novo?"
|
|
||||||
→ User: É esse
|
|
||||||
→ Retorna dados do cliente existente
|
|
||||||
```
|
|
||||||
|
|
||||||
### Exemplo 3: Proposal para lead
|
|
||||||
```
|
|
||||||
User: Criar orçamento para lead João Silva
|
|
||||||
→ Verifica que é lead (não customer)
|
|
||||||
→ Usa create_proposal(lead_id=215)
|
|
||||||
→ Adiciona itens via add_proposal_items
|
|
||||||
→ Confirma: "Proposal #78 criada para lead #215"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Checklist Pré-Operação
|
|
||||||
|
|
||||||
- [ ] Verificar duplicados
|
|
||||||
- [ ] Confirmar com utilizador
|
|
||||||
- [ ] Validar campos obrigatórios
|
|
||||||
- [ ] Usar source/status default se não fornecido
|
|
||||||
- [ ] Mostrar resultado da operação
|
|
||||||
|
|
||||||
## Integração
|
|
||||||
|
|
||||||
- **MCP:** desk-crm-v3
|
|
||||||
- **Procedimento:** [[PROC-CRM-Operacoes]]
|
|
||||||
- **CLAUDE.md:** Secção "CRM (Perfex/DeskCRM)"
|
|
||||||
|
|
||||||
## Changelog
|
|
||||||
|
|
||||||
### v1.2.0 (2026-01-28)
|
|
||||||
- **REGRA 0** adicionada: NUNCA criar lead/customer sem verificar existência
|
|
||||||
- Secção "DEFINIÇÕES CRÍTICAS" com distinção clara:
|
|
||||||
- Lead vs Customer (tabela comparativa)
|
|
||||||
- Proposal vs Estimate (tabela comparativa)
|
|
||||||
- Diagrama de fluxo comercial actualizado
|
|
||||||
- "Orçamento" = Proposal (para leads), não Estimate
|
|
||||||
- Anti-patterns reorganizados por categoria
|
|
||||||
- Terminologia PT clarificada
|
|
||||||
|
|
||||||
### v1.1.0 (2026-01-28)
|
|
||||||
- Adicionadas ferramentas de itens: add_proposal_items, get_proposal_items
|
|
||||||
- Documentado padrão tblitemable para itens de documentos
|
|
||||||
- Adicionados novos anti-patterns (tabelas inventadas, proposals vs estimates)
|
|
||||||
- Fluxo completo para adicionar itens a proposals
|
|
||||||
- Actualizada lista de MCP tools para proposals
|
|
||||||
|
|
||||||
### v1.0.0 (2026-01-28)
|
|
||||||
- Versão inicial completa
|
|
||||||
- Fluxo comercial documentado
|
|
||||||
- Regras de verificação
|
|
||||||
- Status codes
|
|
||||||
- Integração com MCP desk-crm-v3
|
|
||||||
|
|
||||||
### v0.1.0 (2026-01-28)
|
|
||||||
- Estrutura inicial da skill
|
|
||||||
- Definição de comandos e fluxos
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Criado:** 2026-01-28
|
|
||||||
**Actualizado:** 2026-01-28
|
|
||||||
**Motivo:** Prevenção de erros CRM após incidente de duplicação
|
|
||||||
@@ -306,6 +306,24 @@ Skills descontinuadas:
|
|||||||
- Distinção Lead vs Customer
|
- Distinção Lead vs Customer
|
||||||
- Proposal vs Estimate
|
- Proposal vs Estimate
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Self-Healing
|
||||||
|
|
||||||
|
Antes de executar, ler `~/.claude-work/healing/crm.jsonl` (se existir). Cada linha é um padrão de erro conhecido:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"date":"YYYY-MM-DD","issue":"descrição do problema","fix":"como evitar","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
Se encontrares um padrão relevante ao contexto actual, aplica o fix preventivamente. Após cada erro ou correcção do utilizador nesta skill, **adicionar nova linha** ao healing log com o padrão aprendido.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
*Skill v2.0.0 | 2026-02-05 | Descomplicar®*
|
*Skill v2.0.0 | 2026-02-05 | Descomplicar®*
|
||||||
|
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
<!-- Registo automático de erros e correcções nesta skill -->
|
||||||
|
|||||||
@@ -235,6 +235,24 @@ Ao entrar numa pasta:
|
|||||||
### v1.0.0
|
### v1.0.0
|
||||||
- Versão inicial
|
- Versão inicial
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Self-Healing
|
||||||
|
|
||||||
|
Antes de executar, ler `~/.claude-work/healing/desk.jsonl` (se existir). Cada linha é um padrão de erro conhecido:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"date":"YYYY-MM-DD","issue":"descrição do problema","fix":"como evitar","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
Se encontrares um padrão relevante ao contexto actual, aplica o fix preventivamente. Após cada erro ou correcção do utilizador nesta skill, **adicionar nova linha** ao healing log com o padrão aprendido.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
*Skill v3.0.0 | 2026-02-05 | Descomplicar®*
|
*Skill v3.0.0 | 2026-02-05 | Descomplicar®*
|
||||||
|
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
<!-- Registo automático de erros e correcções nesta skill -->
|
||||||
|
|||||||
@@ -0,0 +1,174 @@
|
|||||||
|
---
|
||||||
|
name: estrategia-marca
|
||||||
|
description: Cria estratégias de marca completas seguindo a metodologia Descomplicar® (ACIDA + Framework 16Ps). Inclui fase de pesquisa de mercado com /deep-research antes do briefing. Guia a análise de público, posicionamento, Pitch Canvas, copywriting e documento final entregável. Usar quando o utilizador diz "estratégia de marca", "branding", "criar marca", "posicionamento", "16Ps", "/estrategia-marca", "análise de público", "narrativa de marca", "proposta de valor", "pitch canvas", "pain + gain", "copywriting estratégico", "identidade de marca", "pesquisa de mercado para marca", ou quando um cliente adquire o serviço EST-MRK-010.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Skill: Estratégia de Marca
|
||||||
|
|
||||||
|
Guia completo para criar estratégias de marca Descomplicar® — da pesquisa de mercado ao documento final entregável.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Fluxo de trabalho (8 fases)
|
||||||
|
|
||||||
|
### Fase 0 — Pesquisa de mercado
|
||||||
|
|
||||||
|
Antes do briefing com o cliente, fazer pesquisa independente. Verificar primeiro se já existem ficheiros de pesquisa (ex: pasta `Pesquisas/` no projecto).
|
||||||
|
|
||||||
|
**Se a pesquisa já existe:** ler os ficheiros relevantes e extrair síntese.
|
||||||
|
|
||||||
|
**Se não existe:** usar `/deep-research` (ou `mcp__tavily__tavily_research`) com os seguintes focos:
|
||||||
|
|
||||||
|
1. **Mercado/sector** — dimensão, crescimento, tendências, regulação
|
||||||
|
2. **Concorrentes** — posicionamento, mensagens, pricing, pontos fracos
|
||||||
|
3. **Público** — linguagem online, canais activos, dores expressas em fóruns/reviews
|
||||||
|
4. **Oportunidades** — gaps de mercado, tendências emergentes não exploradas
|
||||||
|
|
||||||
|
Guardar síntese em `Pesquisas/sintese-mercado.md` no projecto do cliente.
|
||||||
|
|
||||||
|
**Resultado esperado:** chegar ao briefing já com hipóteses validadas sobre o mercado e o público — não para impor, mas para fazer perguntas mais certeiras e poupar tempo ao cliente.
|
||||||
|
|
||||||
|
### Fase 1 — Activação e contexto
|
||||||
|
|
||||||
|
Ao iniciar, perguntar:
|
||||||
|
- Qual o nome do cliente/marca?
|
||||||
|
- Já existe briefing ou material de partida?
|
||||||
|
- Qual o sector/indústria?
|
||||||
|
- Temos exemplos de concorrentes?
|
||||||
|
|
||||||
|
Se existir projecto no Desk CRM, verificar com `get_project` antes de prosseguir.
|
||||||
|
|
||||||
|
### Fase 2 — Briefing estruturado
|
||||||
|
|
||||||
|
Conduzir entrevista com as perguntas de `references/perguntas-briefing.md`.
|
||||||
|
|
||||||
|
Organizar por blocos:
|
||||||
|
1. Negócio (problema, serviços, mercado)
|
||||||
|
2. Público-alvo (segmentos identificados)
|
||||||
|
3. Posicionamento actual vs desejado
|
||||||
|
4. Tom de voz e personalidade
|
||||||
|
5. Concorrência e diferenciação
|
||||||
|
|
||||||
|
### Fase 3 — Fundamentos estratégicos
|
||||||
|
|
||||||
|
Desenvolver com o cliente:
|
||||||
|
- **Proposta de valor única** — o que nos torna únicos, diferenciais, benefícios por camada
|
||||||
|
- **Missão, Visão, Valores e Objectivos** — com exemplos de como se manifestam na prática
|
||||||
|
- **Apresentação sumária** — empresa + serviços com tabela clara
|
||||||
|
- **Posicionamento** — declaração de posicionamento testável
|
||||||
|
|
||||||
|
Ver `references/framework-16ps.md` → Bloco A para questões orientadoras.
|
||||||
|
|
||||||
|
### Fase 4 — Análise de público (20 pontos por segmento)
|
||||||
|
|
||||||
|
**Obrigatório:** Antes dos segmentos psicográficos, identificar os nichos sectoriais relevantes para o produto. Usar `references/nichos.md` para seleccionar e analisar **pelo menos 5 nichos específicos** (ex: clínicas de saúde, imobiliárias, agências digitais — não "PMEs" como categoria vaga). Para cada nicho preencher os 8 pontos do guia de análise sectorial. Cruzar com os 20 pontos psicográficos abaixo para construir personas completas.
|
||||||
|
|
||||||
|
Para cada segmento identificado, desenvolver os 20 pontos na seguinte ordem:
|
||||||
|
|
||||||
|
1. Perfil Demográfico
|
||||||
|
2. Perfil Psicográfico
|
||||||
|
3. Dores
|
||||||
|
4. Anseios
|
||||||
|
5. Desejos
|
||||||
|
6. Frustrações
|
||||||
|
7. Preocupações
|
||||||
|
8. Medos
|
||||||
|
9. Inimigos
|
||||||
|
10. Linguagem
|
||||||
|
11. Como procuram ajuda/informação/dicas
|
||||||
|
12. Canais digitais activos
|
||||||
|
13. Estilo de Decisão
|
||||||
|
14. Mudanças (que sabem necessárias)
|
||||||
|
15. Resistência à mudança
|
||||||
|
16. Objecções típicas (+ como ultrapassar)
|
||||||
|
17. Forma de gerar emoção
|
||||||
|
18. Argumentos (a que são mais sensíveis)
|
||||||
|
19. Concorrentes (que alternativas avaliam)
|
||||||
|
20. Propostas Recusadas (e porquê)
|
||||||
|
|
||||||
|
Ver `references/metodologia-acida.md` para contexto e profundidade em cada ponto.
|
||||||
|
|
||||||
|
### Fase 5 — Pitch Canvas
|
||||||
|
|
||||||
|
Estrutura de 5 elementos:
|
||||||
|
- **Para quem:** segmento + problema específico
|
||||||
|
- **O problema:** dor principal na linguagem do cliente
|
||||||
|
- **A solução:** mecanismo único de resolução
|
||||||
|
- **O resultado:** transformação concreta (antes/depois + métrica)
|
||||||
|
- **Por que nós:** razão para acreditar
|
||||||
|
|
||||||
|
Criar também a **Declaração de mudança no mundo** — frase que resume o impacto maior da marca.
|
||||||
|
|
||||||
|
### Fase 6 — Copywriting estratégico
|
||||||
|
|
||||||
|
Sequência obrigatória:
|
||||||
|
|
||||||
|
1. **Questionamento estratégico** — Qual é o objectivo da comunicação? Que transformação prometemos?
|
||||||
|
2. **Pain + Gain** — formulação problema/resultado na linguagem do cliente; depois refinar com especificidades do sector
|
||||||
|
3. **Narrativa por segmento** — fórmula: Problema (dor do público) → Solução (serviços) → Resultado (benefícios concretos)
|
||||||
|
4. **Mensagem central** — 1 frase que toda a equipa sabe de cor
|
||||||
|
5. **Headlines** — por segmento (principal + secundária)
|
||||||
|
|
||||||
|
Ver `references/narrativas-copywriting.md` para templates e exemplos reais.
|
||||||
|
|
||||||
|
### Fase 7 — Documento final + Investimentos
|
||||||
|
|
||||||
|
Completar as secções finais:
|
||||||
|
- **Demonstração dos serviços** — como demonstrar, preparação, follow-up
|
||||||
|
- **Investimentos prioritários** — canais, orçamento, ROI esperado
|
||||||
|
- **KPIs** — baseline + metas a 3m, 6m, 12m
|
||||||
|
- **Inventário de activos** — o que existe, estado, prioridade
|
||||||
|
|
||||||
|
Ver `references/template-documento.md` para a estrutura completa do documento.
|
||||||
|
|
||||||
|
**Checklist de entrega:**
|
||||||
|
- [ ] Pesquisa de mercado feita (Fase 0)
|
||||||
|
- [ ] Proposta de valor única definida
|
||||||
|
- [ ] Missão, Visão, Valores escritos
|
||||||
|
- [ ] Apresentação sumária da empresa e serviços
|
||||||
|
- [ ] Mínimo 5 nichos sectoriais analisados (8 pontos cada) — ver `references/nichos.md`
|
||||||
|
- [ ] Mínimo 2 segmentos psicográficos com 20 pontos completos
|
||||||
|
- [ ] Pitch Canvas preenchido
|
||||||
|
- [ ] Declaração de mudança no mundo
|
||||||
|
- [ ] Pain + Gain (original + refinado)
|
||||||
|
- [ ] Narrativa por segmento (Problema → Solução → Resultado)
|
||||||
|
- [ ] Mensagem central definida
|
||||||
|
- [ ] Investimentos prioritários identificados
|
||||||
|
- [ ] KPIs definidos com metas
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Referências (carregar conforme necessário)
|
||||||
|
|
||||||
|
| Ficheiro | Quando carregar |
|
||||||
|
|----------|----------------|
|
||||||
|
| `references/metodologia-acida.md` | Fases 3-4: ACIDA, 20 pontos por segmento |
|
||||||
|
| `references/framework-16ps.md` | Fase 3: fundamentos estratégicos (Bloco A) |
|
||||||
|
| `references/perguntas-briefing.md` | Fase 2: conduzir entrevista cliente |
|
||||||
|
| `references/narrativas-copywriting.md` | Fase 6: copywriting, Pain+Gain, narrativas |
|
||||||
|
| `references/template-documento.md` | Fase 7: estrutura completa do documento |
|
||||||
|
| `references/nichos.md` | Fase 4: análise sectorial dos 10 nichos PT/EU (mínimo 5 obrigatórios) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Contexto do serviço
|
||||||
|
|
||||||
|
- **Código:** EST-MRK-010
|
||||||
|
- **Preço:** 900 EUR
|
||||||
|
- **Prazo médio:** 30h de trabalho
|
||||||
|
- **Entregáveis:** Documento estratégico completo, dashboard personas, narrativa de marca, apresentação executiva editável, guia de implementação, sessão de alinhamento com equipa
|
||||||
|
- **Suporte pós-entrega:** WhatsApp 1 mês
|
||||||
|
|
||||||
|
Complementar com Branding WOW (BRAND-ESS/DIG/COM: 1.800–4.500 EUR) se o cliente precisar de identidade visual.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
@@ -0,0 +1,193 @@
|
|||||||
|
# Framework 16Ps — Referência Completa
|
||||||
|
|
||||||
|
Estrutura os 16 elementos da estratégia de marca em 4 blocos. Para cada P, incluir as questões orientadoras ao preencher.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Bloco A — Fundamentos estratégicos
|
||||||
|
|
||||||
|
### P1: Problema
|
||||||
|
> Qual o problema principal que a marca resolve?
|
||||||
|
|
||||||
|
- Problema de negócio que a estratégia precisa resolver
|
||||||
|
- Impacto desse problema no cliente (custo, tempo, risco, reputação)
|
||||||
|
- Urgência da solução: por que resolver agora?
|
||||||
|
- Consequências de não resolver
|
||||||
|
|
||||||
|
*Exemplo SFV:* "Facturas de electricidade crescentes que consomem margens das empresas e rendimento das famílias, sem solução acessível percebida."
|
||||||
|
|
||||||
|
### P2: Propósito
|
||||||
|
> Por que existe esta marca além do lucro?
|
||||||
|
|
||||||
|
- **Missão:** o que fazemos e para quem (hoje)
|
||||||
|
- **Visão:** onde queremos chegar (3-5 anos)
|
||||||
|
- **Valores:** 3-5 valores fundamentais com descrição de como se manifestam
|
||||||
|
- **Propósito:** impacto no mundo que justifica a existência da marca
|
||||||
|
|
||||||
|
*Estrutura valores:* [Nome do Valor] — [Como se manifesta na prática]
|
||||||
|
|
||||||
|
### P3: Proposta de Valor
|
||||||
|
> O que tornamos possível que os concorrentes não conseguem?
|
||||||
|
|
||||||
|
- Valor único que só esta marca entrega
|
||||||
|
- Diferenciais competitivos (lista)
|
||||||
|
- Benefícios principais (funcionais + emocionais)
|
||||||
|
- Formula: Para [segmento], que [dor/desejo], a [marca] oferece [solução] que [resultado único], ao contrário de [alternativa], porque [razão para acreditar]
|
||||||
|
|
||||||
|
### P4: Posicionamento
|
||||||
|
> Que lugar específico ocupa na mente do cliente?
|
||||||
|
|
||||||
|
- Posição actual no mercado (percepção real)
|
||||||
|
- Posição desejada (percepção target)
|
||||||
|
- Declaração de posicionamento (1-2 frases)
|
||||||
|
- Território da marca: categoria, concorrência directa, diferenciação
|
||||||
|
- Atributos únicos que definem esse território
|
||||||
|
|
||||||
|
*Declaração-tipo:* "Para [público], somos a única [categoria] que [benefício único] porque [prova]."
|
||||||
|
|
||||||
|
### P5: Performance
|
||||||
|
> Como medimos o sucesso?
|
||||||
|
|
||||||
|
- KPIs principais (5-7 métricas)
|
||||||
|
- Metas específicas a 3, 6 e 12 meses
|
||||||
|
- Indicadores de sucesso por área (brand awareness, conversão, satisfação)
|
||||||
|
- Frequência de monitorização e responsável
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Bloco B — Público e pesquisa
|
||||||
|
|
||||||
|
### P6: Público-alvo
|
||||||
|
> Quem são exactamente os nossos clientes?
|
||||||
|
|
||||||
|
- Segmento principal + segmentos secundários
|
||||||
|
- Critérios de segmentação (demográficos, comportamentais, psicográficos)
|
||||||
|
- Volume estimado de cada segmento
|
||||||
|
- Comportamento de compra: frequência, ticket médio, canal preferido
|
||||||
|
|
||||||
|
### P7: Pesquisa de mercado
|
||||||
|
> Que dados sustentam as nossas decisões?
|
||||||
|
|
||||||
|
- Dados de mercado: dimensão, crescimento, tendências
|
||||||
|
- Insights de comportamento do consumidor
|
||||||
|
- Oportunidades identificadas (não aproveitadas pela concorrência)
|
||||||
|
- Ameaças e riscos do mercado
|
||||||
|
|
||||||
|
### P8: Personas
|
||||||
|
> Quem é o nosso cliente ideal em detalhe?
|
||||||
|
|
||||||
|
Para cada persona:
|
||||||
|
- **Foto + nome fictício + idade + profissão**
|
||||||
|
- **Biografia resumida** (um dia típico)
|
||||||
|
- **Dores principais** (3-5)
|
||||||
|
- **Objectivos** (profissionais + pessoais)
|
||||||
|
- **Canais preferidos** (onde está, o que consome)
|
||||||
|
- **Citação representativa** ("Eu quero/preciso/temo...")
|
||||||
|
- **Frase de posicionamento** para esta persona
|
||||||
|
|
||||||
|
### P9: Perfil
|
||||||
|
> Quais as características quantificáveis de cada segmento?
|
||||||
|
|
||||||
|
Análise de 20 pontos por segmento (ver template completo em `template-documento.md`):
|
||||||
|
- Demográfico: idade, género, localização, rendimento, educação, sector, cargo, empresa
|
||||||
|
- Comportamental: rotina, hábitos, processo de decisão, critérios de escolha
|
||||||
|
- Psicográfico: valores, aspirações, mentalidade, atitude à inovação
|
||||||
|
- Jornada: awareness, consideração, decisão
|
||||||
|
|
||||||
|
### P10: Pain Points
|
||||||
|
> Quais as dores mais urgentes e dolorosas?
|
||||||
|
|
||||||
|
- Dores principais (urgentes, que precisam resolver já)
|
||||||
|
- Frustrações (já tentaram outras soluções sem resultado)
|
||||||
|
- Necessidades não atendidas (o mercado não resolve bem)
|
||||||
|
- Medos relacionados com a compra ou com não comprar
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Bloco C — Produto e serviço
|
||||||
|
|
||||||
|
### P11: Portfolio
|
||||||
|
> O que vendemos exactamente?
|
||||||
|
|
||||||
|
- Lista de produtos/serviços principais
|
||||||
|
- Características técnicas vs benefícios percebidos
|
||||||
|
- Arquitectura de oferta: entrada, core, premium
|
||||||
|
- Casos de uso reais (exemplos concretos de aplicação)
|
||||||
|
|
||||||
|
### P12: Preço e valor
|
||||||
|
> Como justificamos o que cobramos?
|
||||||
|
|
||||||
|
- Estratégia de preços (custo+margem, valor percebido, concorrência, freemium)
|
||||||
|
- Posicionamento de valor: acessível, médio-alto, premium, luxo
|
||||||
|
- Política comercial: descontos, bundles, condições de pagamento
|
||||||
|
- ROI estimado para o cliente (quanto ganha/poupa ao escolher-nos)
|
||||||
|
|
||||||
|
### P13: Processos críticos
|
||||||
|
> Que processos garantem a experiência prometida?
|
||||||
|
|
||||||
|
- Processo de entrega do serviço/produto (passo a passo)
|
||||||
|
- Pontos de controlo de qualidade
|
||||||
|
- Garantias e políticas de satisfação
|
||||||
|
- Gestão de reclamações
|
||||||
|
|
||||||
|
### P14: Parcerias estratégicas
|
||||||
|
> Com quem nos aliamos para ampliar valor?
|
||||||
|
|
||||||
|
- Parceiros principais (nome, tipo, contribuição)
|
||||||
|
- Tipos de parceria: distribuição, tecnologia, referência, co-marketing
|
||||||
|
- Benefícios mútuos de cada parceria
|
||||||
|
- Parcerias a desenvolver (gap de oportunidade)
|
||||||
|
|
||||||
|
### P15: Plataforma
|
||||||
|
> Onde operamos digitalmente?
|
||||||
|
|
||||||
|
- Canais digitais activos: website, redes sociais, marketplaces, apps
|
||||||
|
- Presença online actual vs ideal
|
||||||
|
- Infraestrutura tecnológica (CRM, email, analytics, automação)
|
||||||
|
- Prioridades de investimento digital
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Bloco D — Promoção e comunicação
|
||||||
|
|
||||||
|
### P16: Promoção
|
||||||
|
> Como chegamos ao público-alvo?
|
||||||
|
|
||||||
|
- Canais principais com objectivos específicos por canal
|
||||||
|
- Tácticas específicas (conteúdo, SEO, email, WhatsApp, eventos)
|
||||||
|
- Calendário promocional (frequência, momentos-chave)
|
||||||
|
- Budget orientativo por canal
|
||||||
|
|
||||||
|
### P17: Publicidade
|
||||||
|
> Como amplificamos com investimento pago?
|
||||||
|
|
||||||
|
- Estratégia de anúncios: plataformas, formato, objectivo
|
||||||
|
- Budget mensal e distribuição
|
||||||
|
- KPIs de publicidade (CPL, ROAS, CPA)
|
||||||
|
- Frequência e ciclo de renovação de criativos
|
||||||
|
|
||||||
|
### P18: PR e referências
|
||||||
|
> Como construímos credibilidade externa?
|
||||||
|
|
||||||
|
- Estratégia de relações públicas
|
||||||
|
- Parcerias com influenciadores (relevância > alcance)
|
||||||
|
- Imprensa e media especializada
|
||||||
|
- Programa de referências/embaixadores
|
||||||
|
|
||||||
|
### P19: Presença digital
|
||||||
|
> Qual a nossa estratégia de conteúdo?
|
||||||
|
|
||||||
|
- Estratégia de conteúdo por canal
|
||||||
|
- Frequência de publicação
|
||||||
|
- Pilares de conteúdo (3-5 temas centrais)
|
||||||
|
- Gestão de comunidade: resposta, engagement, moderação
|
||||||
|
|
||||||
|
### P20: Proximidade — narrativa e impacto
|
||||||
|
> Que história contamos que ressoa emocionalmente?
|
||||||
|
|
||||||
|
- **Declaração de Impacto:** frase que resume a essência e impacto da marca
|
||||||
|
- **Narrativa principal:** história de origem ou transformação
|
||||||
|
- **Pain + Gain por segmento:** o que perdiam antes → o que ganham agora
|
||||||
|
- **Mensagem central:** 1 frase que todos os colaboradores sabem de cor
|
||||||
|
|
||||||
|
*Nota: O "Bloco D" tem 5 Ps numerados de 16 a 20 — alguns documentos listam apenas 16 Ps no total (agrupando Promoção, Publicidade e PR num único P). Adaptar conforme o nível de detalhe necessário.*
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
# Metodologia ACIDA — Referência Completa
|
||||||
|
|
||||||
|
## 1. As 5 fases ACIDA
|
||||||
|
|
||||||
|
### A — Atrair atenção
|
||||||
|
|
||||||
|
O público está sobrecarregado de informação. A forma correcta de chamar a atenção não é destacar produtos — é conectar com o que emocionalmente mais interessa ao público: **as suas próprias dores e desejos**.
|
||||||
|
|
||||||
|
Acções práticas:
|
||||||
|
- Headlines que falam directamente da dor ou desejo do segmento
|
||||||
|
- Conteúdo que provoca reconhecimento imediato ("é exactamente o meu problema")
|
||||||
|
- Formatos visuais que param o scroll: vídeo curto, imagem disruptiva, estatística chocante
|
||||||
|
|
||||||
|
### C — Construir confiança
|
||||||
|
|
||||||
|
Após conquistar atenção, estabelecer relacionamentos autênticos através de:
|
||||||
|
- Transparência, honestidade e autenticidade na comunicação
|
||||||
|
- Demonstrar compreensão profunda das dores e desejos do cliente
|
||||||
|
- Partilhar conhecimento e experiência profissional abertamente
|
||||||
|
- Educar o público para decisões mais informadas
|
||||||
|
- Estabelecer autoridade que permite influenciar percepções
|
||||||
|
|
||||||
|
Formatos: artigos de blog, estudos de caso, testemunhos, webinars, guias gratuitos.
|
||||||
|
|
||||||
|
### I — Despertar interesse
|
||||||
|
|
||||||
|
Com confiança estabelecida, a comunicação torna-se altamente personalizada.
|
||||||
|
> "Não vendemos produtos nem serviços; oferecemos soluções específicas para os seus desafios."
|
||||||
|
|
||||||
|
Ferramentas:
|
||||||
|
- Rastreamento de interacções para identificar segmentos de clientes
|
||||||
|
- Conteúdo customizado baseado em comportamentos anteriores
|
||||||
|
- Resolução antecipada de objecções conhecidas
|
||||||
|
- Nutrição de relacionamentos via email, WhatsApp, SMS, redes sociais
|
||||||
|
|
||||||
|
### D — Estimular a decisão
|
||||||
|
|
||||||
|
A decisão será favorável se o **valor percebido > preço a pagar**.
|
||||||
|
|
||||||
|
Obstáculos a superar:
|
||||||
|
- O "muro invisível" criado por dúvidas do consumidor
|
||||||
|
- Medo do arrependimento pós-compra
|
||||||
|
- Necessidade de prova social e garantias sólidas
|
||||||
|
|
||||||
|
Ferramentas: comparações, garantias, testemunhos de clientes reais, demonstrações, ROI calculado.
|
||||||
|
|
||||||
|
### A — Incentivar a acção
|
||||||
|
|
||||||
|
Converter interesse em acção através de:
|
||||||
|
- Chamadas à acção (CTA) claras e convincentes
|
||||||
|
- Criação de sentido de urgência (real, não artificial)
|
||||||
|
- Cumprimento de promessas
|
||||||
|
- Superação de expectativas na experiência do cliente
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Análise do público-alvo — 8 dimensões
|
||||||
|
|
||||||
|
Para cada segmento, investigar as 8 dimensões antes de escrever qualquer copy:
|
||||||
|
|
||||||
|
### Dimensão 1: Perfil demográfico e psicográfico
|
||||||
|
- Características mensuráveis: idade, género, localização, rendimento, educação, cargo
|
||||||
|
- Traços de personalidade: valores, crenças, atitudes, estilo de vida
|
||||||
|
- *Pergunta-chave: "Quem é esta pessoa na vida real?"*
|
||||||
|
|
||||||
|
### Dimensão 2: Dores, desejos e frustrações
|
||||||
|
- Dores activas: problemas que precisam resolver agora
|
||||||
|
- Desejos: o que querem alcançar/ter/ser
|
||||||
|
- Frustrações: o que já tentaram e não funcionou
|
||||||
|
- *Pergunta-chave: "O que os mantém acordados à noite? O que sonham?"*
|
||||||
|
|
||||||
|
### Dimensão 3: Preocupações e geração de emoção
|
||||||
|
- O que os preocupa a médio/longo prazo
|
||||||
|
- Como a nossa marca pode responder emocionalmente (não apenas racionalmente)
|
||||||
|
- *Pergunta-chave: "Que emoção queremos que sintam quando nos encontram?"*
|
||||||
|
|
||||||
|
### Dimensão 4: Medos, inimigos e mudanças
|
||||||
|
- Medos concretos (perder negócio, ser enganado, falhar)
|
||||||
|
- "Inimigos" percebidos (concorrentes, reguladores, tendências de mercado)
|
||||||
|
- Mudanças que temem ou resistem
|
||||||
|
- *Pergunta-chave: "O que os impede de agir?"*
|
||||||
|
|
||||||
|
### Dimensão 5: Anseios, interesses e linguagem
|
||||||
|
- O que aspiram a ser/ter/fazer
|
||||||
|
- Interesses e hobbies (pistas para onde comunicar)
|
||||||
|
- Linguagem que usam (jargão do sector, palavras que ressoam vs que afastam)
|
||||||
|
- *Pergunta-chave: "Como falam entre si? Que palavras usam?"*
|
||||||
|
|
||||||
|
### Dimensão 6: Pesquisa de informação e influenciadores
|
||||||
|
- Onde procuram informação (Google, YouTube, LinkedIn, feiras, colegas)
|
||||||
|
- A quem pedem conselho (influenciadores, peers, família)
|
||||||
|
- Fontes que consideram credíveis
|
||||||
|
- *Pergunta-chave: "Como encontraram a nossa categoria de produto/serviço?"*
|
||||||
|
|
||||||
|
### Dimensão 7: Dúvidas e perguntas
|
||||||
|
- Objecções previsíveis antes da compra
|
||||||
|
- Perguntas que fazem nas reuniões de vendas
|
||||||
|
- Informação que precisam para decidir
|
||||||
|
- *Pergunta-chave: "Quais as 5 objecções mais frequentes?"*
|
||||||
|
|
||||||
|
### Dimensão 8: Estilo de decisão e concorrentes
|
||||||
|
- Processo de decisão: individual vs colectivo, rápido vs lento
|
||||||
|
- Factores comparativos: preço, qualidade, confiança, referências
|
||||||
|
- Concorrentes directos que avaliam em paralelo
|
||||||
|
- *Pergunta-chave: "Com quem nos comparam? Por que nos escolhem ou não?"*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Pilares estratégicos ACIDA
|
||||||
|
|
||||||
|
- **Crença central:** o centro do marketing digital são os princípios fundamentais de marketing + website — não as redes sociais
|
||||||
|
- **Proposta de valor:** "Criamos Resultados" — problema → solução → resultados esperados
|
||||||
|
- **Website como hub central:** não repositório, mas centro operacional integrado com CRM
|
||||||
|
- **Ecossistema multi-canal:** email, SMS/WhatsApp, SEO, Google/Meta Ads, website, redes sociais (como parte, não como centro)
|
||||||
|
- **Melhoria contínua:** métricas objectivas → ciclo iterativo baseado em dados
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. ACIDA 2.0 — Fases operacionais
|
||||||
|
|
||||||
|
| Fase | Acções |
|
||||||
|
|------|--------|
|
||||||
|
| **1. Análise** | Segmentação público, posicionamento, estruturação oferta, montagem narrativa |
|
||||||
|
| **2. Criação** | Recursos, copywriting e design, website e plataformas, automação |
|
||||||
|
| **3. Implementação** | Conteúdos e canais, blog e email marketing, redes sociais, marketplaces |
|
||||||
|
| **4. Desenvolvimento** | Funil de vendas, tráfego e anúncios, conteúdos, newsletters |
|
||||||
|
| **5. Acompanhamento** | Gestão de resultados, métricas e KPIs, optimização contínua, suporte |
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
# Narrativas e Copywriting Estratégico
|
||||||
|
|
||||||
|
Templates e exemplos reais de narrativas Descomplicar®. Baseados nos projectos SFV, LJM, MCT e Espiral Senior.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Fórmula central: Dor → Solução → Resultado
|
||||||
|
|
||||||
|
Estrutura base para qualquer narrativa por segmento:
|
||||||
|
|
||||||
|
```
|
||||||
|
DOR: [Nome do segmento] enfrenta [problema específico e urgente].
|
||||||
|
Sem solução, [consequência negativa concreta].
|
||||||
|
|
||||||
|
SOLUÇÃO: [Nome da marca] resolve isto através de [mecanismo único].
|
||||||
|
[Diferencial que os concorrentes não têm].
|
||||||
|
|
||||||
|
RESULTADO: O resultado é [benefício tangível e mensurável].
|
||||||
|
[Prova social ou garantia que aumenta credibilidade].
|
||||||
|
```
|
||||||
|
|
||||||
|
**Exemplo SFV (segmento Empresas):**
|
||||||
|
> Dor: As PMEs enfrentam facturas de electricidade crescentes que consomem margens já apertadas.
|
||||||
|
> Solução: A SFV instala painéis solares personalizados com análise de consumo prévia — sem adiantamento para projectos qualificados.
|
||||||
|
> Resultado: Redução de 60-90% na factura eléctrica, com ROI em 4-7 anos e garantia de 25 anos nos painéis.
|
||||||
|
|
||||||
|
**Exemplo MCT (segmento Oficinas):**
|
||||||
|
> Dor: Mecânicos perdem tempo e dinheiro com ferramentas que chegam erradas, incompletas ou que avariam em obra.
|
||||||
|
> Solução: A Carritools fornece equipamento profissional com assessoria técnica presencial e substituição imediata em caso de avaria.
|
||||||
|
> Resultado: Menos tempo parado, mais trabalhos concluídos, clientes mais satisfeitos.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Declaração de Impacto
|
||||||
|
|
||||||
|
Uma frase poderosa que abre o documento e resume a essência da marca. Deve:
|
||||||
|
- Ser memorável (10-15 palavras máximo)
|
||||||
|
- Combinar emoção + resultado
|
||||||
|
- Não ser genérica ("líderes de mercado", "qualidade e inovação")
|
||||||
|
|
||||||
|
**Exemplos reais:**
|
||||||
|
|
||||||
|
| Cliente | Declaração de Impacto |
|
||||||
|
|---------|----------------------|
|
||||||
|
| SFV Solar | "Energia (quase) Grátis para Famílias e Empresas" |
|
||||||
|
| Espiral Senior | "Envelhecer em Dignidade, no Lugar que Mais Ama" |
|
||||||
|
| Descomplicar® | "Criamos Resultados!" |
|
||||||
|
|
||||||
|
**Fórmulas para gerar Declaração de Impacto:**
|
||||||
|
- `[Verbo de transformação] + [benefício desejado] + [para quem]`
|
||||||
|
- `[Adjectivo emocional] + [resultado concreto]`
|
||||||
|
- `[Benefício surpreendente] + [para quem] + [sem o custo habitual]`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Mensagens-chave por tipo de segmento
|
||||||
|
|
||||||
|
### Segmento decisor (CEO/Gerente)
|
||||||
|
Foco: ROI, risco reduzido, credibilidade, tempo poupado.
|
||||||
|
|
||||||
|
Template:
|
||||||
|
> "Mais de [N] empresas como a sua já [resultado]. A nossa abordagem garante [benefício financeiro] em [prazo], com [garantia específica]."
|
||||||
|
|
||||||
|
### Segmento utilizador final (técnico/operacional)
|
||||||
|
Foco: facilidade de uso, suporte, fiabilidade, não criar problemas.
|
||||||
|
|
||||||
|
Template:
|
||||||
|
> "Simples de implementar, sem interrupções ao seu trabalho. Em caso de dúvida, temos suporte [detalhe] para que nunca fique bloqueado."
|
||||||
|
|
||||||
|
### Segmento referenciador (parceiro/consultor)
|
||||||
|
Foco: credibilidade para recomendar, win-win, diferenciação para os seus clientes.
|
||||||
|
|
||||||
|
Template:
|
||||||
|
> "Ao recomendar [marca], está a oferecer aos seus clientes [resultado], o que reforça a sua autoridade como [cargo/papel]."
|
||||||
|
|
||||||
|
### Segmento influenciador (família/comunidade)
|
||||||
|
Foco: valores partilhados, impacto positivo, pertença.
|
||||||
|
|
||||||
|
Template:
|
||||||
|
> "Não é só [produto/serviço]. É uma escolha que [impacto maior]: [dimensão ambiental/social/familiar]."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Gestão de objecções — estrutura padrão
|
||||||
|
|
||||||
|
Para cada objecção, responder sempre com:
|
||||||
|
1. **Validar** — reconhecer que é uma preocupação legítima
|
||||||
|
2. **Reframeamento** — mudar o ângulo de análise
|
||||||
|
3. **Prova** — exemplo, dado ou testemunho que confirma
|
||||||
|
4. **CTA suave** — próximo passo de baixo compromisso
|
||||||
|
|
||||||
|
**Objecções universais e respostas tipo:**
|
||||||
|
|
||||||
|
| Objecção | Resposta base |
|
||||||
|
|----------|--------------|
|
||||||
|
| "É caro" | "Entendo a preocupação. O nosso preço reflecte [diferencial]. Clientes como [X] recuperaram o investimento em [prazo]. Posso mostrar-lhe o cálculo?" |
|
||||||
|
| "Preciso de pensar" | "Faz todo o sentido. O que precisa de esclarecer para se sentir confiante? Posso enviar [recurso específico] que costuma ajudar nesta fase." |
|
||||||
|
| "Já tentei algo parecido e não funcionou" | "Compreendo — essa experiência é frustrante. O que tipicamente falha é [causa]. A nossa abordagem resolve isto de forma diferente: [diferencial]." |
|
||||||
|
| "Não tenho tempo agora" | "Respeitamos o seu tempo. É por isso que o nosso processo começa com apenas [X horas], e tratamos nós de [trabalho pesado]." |
|
||||||
|
| "Preciso de aprovação interna" | "Claro. Posso preparar um resumo executivo de 1 página para facilitar a aprovação? Tenho feito isto para outros clientes com muito bom resultado." |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Tom de voz por personalidade de marca
|
||||||
|
|
||||||
|
### Marca especialista/técnica (ex: SFV, Carritools)
|
||||||
|
- Linguagem precisa, dados concretos, terminologia do sector
|
||||||
|
- Evitar: exageros sem prova, linguagem emocional excessiva
|
||||||
|
- Usar: casos reais, números, especificações, garantias técnicas
|
||||||
|
|
||||||
|
### Marca próxima/humana (ex: Espiral Senior, Loja da Maria)
|
||||||
|
- Linguagem calorosa, inclusiva, em 2ª pessoa
|
||||||
|
- Evitar: jargão técnico, distância corporativa
|
||||||
|
- Usar: histórias pessoais, empatia directa, linguagem do dia-a-dia
|
||||||
|
|
||||||
|
### Marca inovadora/disruptiva (ex: Descomplicar, SaaS)
|
||||||
|
- Linguagem energética, directa, com algum desafio ao status quo
|
||||||
|
- Evitar: clichés do sector, promessas vazias
|
||||||
|
- Usar: contraste antes/depois, resultados surpreendentes, "E se..."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Estrutura de testemunho ideal
|
||||||
|
|
||||||
|
Baseado nos testemunhos reais recolhidos nos projectos:
|
||||||
|
|
||||||
|
```
|
||||||
|
[Nome próprio + cargo + empresa] — [cidade, se relevante]
|
||||||
|
"[Frase de impacto espontânea que resume o resultado]"
|
||||||
|
|
||||||
|
Contexto: [Situação antes de contratar]
|
||||||
|
Resultado: [Mudança concreta e mensurável após]
|
||||||
|
Recomendação: [Indicação explícita para outros como ele]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Exemplo real SFV:**
|
||||||
|
> "Ricardo Castelão, Director Financeiro, Empresa de Distribuição — Porto
|
||||||
|
> 'Reduzimos a nossa factura eléctrica em 73% no primeiro ano.'
|
||||||
|
> Contexto: Gastávamos 4.200 EUR/mês em electricidade, sem alternativa viável.
|
||||||
|
> Resultado: Passámos para 1.134 EUR/mês. O sistema pagou-se em 5,5 anos.
|
||||||
|
> Recomendação: Para qualquer empresa com consumo acima de 1.500 EUR/mês, é obrigatório analisar esta opção."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Headlines de alto impacto — padrões
|
||||||
|
|
||||||
|
Padrões que funcionam consistentemente nos projectos Descomplicar:
|
||||||
|
|
||||||
|
- **Resultado específico:** "Reduza a sua factura eléctrica em 70% sem investimento inicial"
|
||||||
|
- **Pergunta dor:** "Ainda a pagar [problema] quando existe solução comprovada?"
|
||||||
|
- **Autoridade + resultado:** "Como [N] empresas [resultado] com [solução]"
|
||||||
|
- **Contrafactual:** "E se a sua maior despesa se transformasse no seu maior activo?"
|
||||||
|
- **Urgência real:** "A [mudança de mercado/regulação] está a mudar tudo — [posição da marca]"
|
||||||
|
- **Social proof:** "Mais de [N] clientes em [região] já [resultado]"
|
||||||
@@ -0,0 +1,318 @@
|
|||||||
|
# Análise de Nichos — Guia de Segmentação Sectorial
|
||||||
|
|
||||||
|
Para marcas com público PME, "PME" é demasiado vasto. Identificar os nichos sectoriais específicos permite mensagens certeiras, canais certos e ROI superior. Qualquer estratégia de marca deve analisar **pelo menos 5 nichos específicos** relevantes para o produto/serviço.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Como usar este guia
|
||||||
|
|
||||||
|
1. Identificar os nichos onde o produto/serviço tem tracção real ou potencial
|
||||||
|
2. Para cada nicho seleccionado, preencher os 8 pontos de análise sectorial
|
||||||
|
3. Cruzar com os 20 pontos da análise de público (template-documento.md § 5) para o perfil completo
|
||||||
|
4. Priorizar os 3 nichos de maior potencial para messaging principal
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Os 8 pontos de análise por nicho
|
||||||
|
|
||||||
|
Para cada nicho, responder:
|
||||||
|
|
||||||
|
1. **Dimensão e contexto** — quantas empresas em PT/EU, crescimento do sector, maturidade digital
|
||||||
|
2. **Dores operacionais específicas** — o que os cansa no dia-a-dia (não genérico: específico do sector)
|
||||||
|
3. **Funcionalidades mais relevantes** — o que do produto resolve melhor o problema deste nicho
|
||||||
|
4. **Linguagem de venda** — palavras que usam, palavras que evitam, jargão do sector
|
||||||
|
5. **Canal de aquisição principal** — onde estão, como chegam ao produto
|
||||||
|
6. **Objecção principal** — o bloqueio mais frequente e como ultrapassar
|
||||||
|
7. **Trigger de compra** — o momento/evento que precipita a decisão
|
||||||
|
8. **Pricing sweet spot** — o que pagam por ferramentas similares, sensibilidade ao preço
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Os 10 nichos de PME mais relevantes (PT/EU)
|
||||||
|
|
||||||
|
### Nicho 1 — Saúde Privada
|
||||||
|
|
||||||
|
**Quem:** Clínicas dentárias, psicólogos, nutricionistas, fisioterapeutas, clínicas médicas privadas, terapeutas.
|
||||||
|
|
||||||
|
**Dimensão PT:** +12.000 clínicas e consultórios privados. Sector em crescimento pós-pandemia. Alta concentração em Lisboa, Porto e litoral.
|
||||||
|
|
||||||
|
**Dores operacionais:**
|
||||||
|
- Agenda manual ou em sistemas desactualizados (Doctoralia, papel)
|
||||||
|
- Falhas de consulta (no-shows) sem sistema de lembretes automatizado
|
||||||
|
- Secretaria sobrecarregada com marcações e confirmações por telefone
|
||||||
|
- Facturação em saúde com complexidade fiscal (isenção IVA, recibos verdes)
|
||||||
|
- RGPD em saúde: dados sensíveis com requisitos legais estritos
|
||||||
|
|
||||||
|
**Funcionalidades mais relevantes:** lembretes automáticos de consulta por WhatsApp/SMS, confirmação/cancelamento por WhatsApp, reagendamento automático, facturação PT com isenção IVA, base de conhecimento para FAQ de pacientes.
|
||||||
|
|
||||||
|
**Linguagem de venda:** "reduzir faltas à consulta", "libertar a secretária para o que importa", "pacientes confirmam pelo WhatsApp", "agenda sempre actualizada". Evitar: "automação", "IA", "bot".
|
||||||
|
|
||||||
|
**Canal de aquisição:** associações profissionais (OMD, Ordem dos Psicólogos), LinkedIn de gestores de clínica, referência entre profissionais de saúde, Google Ads ("software gestão clínica", "agenda online clínica").
|
||||||
|
|
||||||
|
**Objecção principal:** "Os meus pacientes são mais velhos e não usam WhatsApp." → Resposta: "O sistema funciona igualmente por SMS. E os cuidadores/filhos que marcam as consultas estão todos no WhatsApp."
|
||||||
|
|
||||||
|
**Trigger de compra:** crescimento de lista de espera que a secretária já não consegue gerir; terceira consulta cancelada sem aviso no mesmo mês.
|
||||||
|
|
||||||
|
**Pricing sweet spot:** €50-150/mês (referência: Doctoralia €80-200/mês).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Nicho 2 — Imobiliárias e Mediação
|
||||||
|
|
||||||
|
**Quem:** Agências imobiliárias independentes, mediadores certificados (AMI), promotores imobiliários, gestoras de condomínios.
|
||||||
|
|
||||||
|
**Dimensão PT:** +5.000 agências com licença AMI activas. Mercado em alta, mas muito fragmentado. Alta dependência de WhatsApp para comunicação com compradores/vendedores.
|
||||||
|
|
||||||
|
**Dores operacionais:**
|
||||||
|
- Leads entram por portais (Imovirtual, Idealista, OLX) e ficam sem resposta rápida
|
||||||
|
- Gestão de visitas manual: telefonemas para confirmar, reagendar, cancelar
|
||||||
|
- Follow-up de compradores perdido no WhatsApp pessoal do agente
|
||||||
|
- Quando o agente sai, leva os contactos consigo
|
||||||
|
- Proposta/minuta demoram dias
|
||||||
|
|
||||||
|
**Funcionalidades mais relevantes:** resposta automática a leads de portais, qualificação de leads por WhatsApp, agendamento de visitas com confirmação automática, CRM com histórico centralizado (não no telemóvel do agente), geração de propostas.
|
||||||
|
|
||||||
|
**Linguagem de venda:** "nunca perde um lead do Idealista", "as visitas confirmam-se sozinhas", "quando o agente sai, o cliente fica na empresa", "responde ao lead em 2 minutos, a qualquer hora".
|
||||||
|
|
||||||
|
**Canal de aquisição:** associações (APEMIP, ASIP), LinkedIn de directores de agência, eventos do sector imobiliário, Google Ads ("CRM imobiliário Portugal", "software mediação imobiliária").
|
||||||
|
|
||||||
|
**Objecção principal:** "Já usamos o CRM do Idealista." → Resposta: "O CRM do portal gere os leads do portal. O AcidaOS centraliza todos os portais + WhatsApp + email num só sítio, com o histórico completo de cada cliente."
|
||||||
|
|
||||||
|
**Trigger de compra:** perda de uma venda grande por demora na resposta ao lead; saída de um agente que levou a carteira de clientes.
|
||||||
|
|
||||||
|
**Pricing sweet spot:** €80-200/mês (referência: Salesforce RE €150-300/mês, CRMs sectoriais €50-150/mês).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Nicho 3 — Construção e Remodelação
|
||||||
|
|
||||||
|
**Quem:** Empreiteiros de construção civil, empresas de remodelação e acabamentos, serralheiros, carpinteiros, canalizadores com equipa, empresas de pintura.
|
||||||
|
|
||||||
|
**Dimensão PT:** sector fortíssimo — construção representa ~7% do PIB PT. Altamente fragmentado, maioria micro-empresas 1-20 pessoas. Baixa digitalização. Alta dependência de telefonema e referência.
|
||||||
|
|
||||||
|
**Dores operacionais:**
|
||||||
|
- Orçamentos demoram dias ou semanas a chegar ao cliente
|
||||||
|
- Clientes ligam 5 vezes para saber se o orçamento chegou
|
||||||
|
- Gestão de obras espalhada por papel, WhatsApp e memória do encarregado
|
||||||
|
- Facturação atrasada em relação ao trabalho realizado (meses de delay)
|
||||||
|
- Cobranças de pagamentos em atraso constrangem a relação com o cliente
|
||||||
|
|
||||||
|
**Funcionalidades mais relevantes:** geração de orçamentos, follow-up automático ("o seu orçamento foi enviado — alguma dúvida?"), facturação automática por fase de obra, lembretes de pagamento, agenda de obras com alertas de prazo.
|
||||||
|
|
||||||
|
**Linguagem de venda:** "orçamento pronto em horas, não dias", "o cliente sabe sempre o estado da obra", "recebe quando acaba, não quando se lembra". Evitar linguagem tech — falar em "tempo poupado" e "dinheiro recebido".
|
||||||
|
|
||||||
|
**Canal de aquisição:** referência entre empresários do sector, associações (AICCOPN, AECOPS), Facebook Groups de empreiteiros e remodelações, feiras de construção.
|
||||||
|
|
||||||
|
**Objecção principal:** "A minha secretária já faz isso." → Resposta: "E quando ela está de férias? O AcidaOS não vai de férias."
|
||||||
|
|
||||||
|
**Trigger de compra:** perda de um contrato por orçamento que chegou tarde; mês com 3 facturas por emitir de obras já concluídas.
|
||||||
|
|
||||||
|
**Pricing sweet spot:** €30-80/mês (sector muito sensível ao preço, mas disposto a pagar se ROI for claro e imediato).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Nicho 4 — Agências Digitais e Criativas
|
||||||
|
|
||||||
|
**Quem:** Agências de marketing digital, design, comunicação, relações públicas, fotografia/vídeo, produção de conteúdo.
|
||||||
|
|
||||||
|
**Dimensão PT:** +3.500 agências activas. Sector muito competitivo, margens a comprimir. Muitas em transição de "serviços de execução" para "serviços de estratégia + produto".
|
||||||
|
|
||||||
|
**Dores operacionais:**
|
||||||
|
- Relatórios mensais para clientes consomem 2-3 dias de trabalho manual
|
||||||
|
- Gestão de aprovações de conteúdo por WhatsApp e email (versões perdidas)
|
||||||
|
- Timesheets manuais → facturação imprecisa → conflitos com clientes
|
||||||
|
- Escalabilidade travada: para crescer precisa de contratar
|
||||||
|
- Receita 100% baseada em horas → vulnerável a perdas de cliente
|
||||||
|
|
||||||
|
**Funcionalidades mais relevantes:** geração automática de relatórios mensais, portal do cliente com aprovação de conteúdos, registo automático de horas, facturação por projecto, upsell/cross-sell automatizado (ex: "o teu plano inclui X — quer adicionar Y?").
|
||||||
|
|
||||||
|
**Linguagem de venda:** "relatórios que se fazem sozinhos", "o cliente aprova no portal, não por email", "receita recorrente sem aumentar a equipa", "white-label para revender aos teus clientes".
|
||||||
|
|
||||||
|
**Canal de aquisição:** LinkedIn (muito activo neste nicho), eventos de marketing (RD Summit, Social Media Week), comunidades Slack de marketers, referência entre agências.
|
||||||
|
|
||||||
|
**Objecção principal:** "Já usamos Monday/Asana/Notion." → Resposta: "O AcidaOS integra com essas ferramentas. Mas adiciona a camada de IA que automatiza o que ainda fazem manualmente: relatórios, aprovações, facturação."
|
||||||
|
|
||||||
|
**Trigger de compra:** perda de 20% da margem num trimestre por horas não facturadas; cliente grande que pediu relatórios mais frequentes sem pagar mais.
|
||||||
|
|
||||||
|
**Pricing sweet spot:** €100-300/mês; alto potencial para plano Partner/white-label (€500-1.000/mês).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Nicho 5 — Comércio B2B e Distribuição
|
||||||
|
|
||||||
|
**Quem:** Distribuidores, grossistas, representantes comerciais, importadores, empresas de venda a retalhistas.
|
||||||
|
|
||||||
|
**Dimensão PT:** sector fundamental da economia, muito diversificado. Ciclos de venda mais longos, pedidos recorrentes, relacionamento comercial crítico.
|
||||||
|
|
||||||
|
**Dores operacionais:**
|
||||||
|
- Pedidos chegam por WhatsApp, email e telefone — sem registo centralizado
|
||||||
|
- Catálogo de produtos actualizado só existe em Excel ou PDF
|
||||||
|
- Comerciais perdem tempo a dar preços e a verificar stock pelo telefone
|
||||||
|
- Dívidas de clientes descobertas tarde (só quando o contabilista avisa)
|
||||||
|
- Fidelização: o cliente vai ao concorrente se não for contactado regularmente
|
||||||
|
|
||||||
|
**Funcionalidades mais relevantes:** chatbot de catálogo e preços por WhatsApp, processamento de pedidos automático, alertas de pagamentos em atraso, follow-up automático de clientes inativos ("não nos pede há 30 dias — tudo bem?"), facturação automática por encomenda.
|
||||||
|
|
||||||
|
**Linguagem de venda:** "o cliente pede pelo WhatsApp e a factura sai automática", "nunca perde uma encomenda por estar em reunião", "sabe quem não lhe compra há um mês antes de o perder".
|
||||||
|
|
||||||
|
**Canal de aquisição:** associações sectoriais, feiras B2B, LinkedIn de directores comerciais, referência entre distribuidores.
|
||||||
|
|
||||||
|
**Objecção principal:** "Os meus clientes são empresas — preferem email formal." → Resposta: "O sistema funciona por email também. E o WhatsApp para os urgentes — que são 80% dos pedidos reais."
|
||||||
|
|
||||||
|
**Trigger de compra:** perda de cliente para concorrente por resposta mais rápida; mês com facturas em atraso acima de €10K.
|
||||||
|
|
||||||
|
**Pricing sweet spot:** €100-250/mês (dispostos a pagar pelo ROI directo em cobranças e pedidos capturados).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Nicho 6 — Restauração e Hotelaria
|
||||||
|
|
||||||
|
**Quem:** Restaurantes, cafés, bares, hotéis boutique, alojamentos locais, serviços de catering, espaços de eventos.
|
||||||
|
|
||||||
|
**Dimensão PT:** +80.000 estabelecimentos de restauração. Sector de margens apertadas, alta rotatividade de staff, sazonalidade intensa.
|
||||||
|
|
||||||
|
**Dores operacionais:**
|
||||||
|
- Reservas por telefone interrompem o serviço → perdidas quando está cheio
|
||||||
|
- Grupos e eventos corporativos: orçamentação manual e demorada
|
||||||
|
- Gestão de feedback online (Google, Tripadvisor) sem resposta sistemática
|
||||||
|
- Campanhas de WhatsApp para promoções especiais feitas manualmente
|
||||||
|
- Alojamento local: check-in remoto, comunicação com hóspedes em múltiplas línguas
|
||||||
|
|
||||||
|
**Funcionalidades mais relevantes:** reservas e confirmações por WhatsApp, resposta automática a reviews Google, campanhas de promoções ("mesa disponível para amanhã?"), comunicação com hóspedes em PT/EN/ES automática, facturação de eventos.
|
||||||
|
|
||||||
|
**Linguagem de venda:** "mesa reservada e confirmada sem tirar o empregado do serviço", "campanhas de promoção para a base de clientes em 2 minutos", "hóspedes atendidos em qualquer língua, a qualquer hora".
|
||||||
|
|
||||||
|
**Canal de aquisição:** associações (AHRESP, ARESP), feiras do sector (Horexpo, BTL), Instagram/Facebook de restaurateurs, referência entre proprietários.
|
||||||
|
|
||||||
|
**Objecção principal:** "O meu cliente quer falar com uma pessoa." → Resposta: "O sistema trata das confirmações de rotina. Quando o cliente quer falar com alguém, o sistema escala — e o teu staff tem mais tempo para isso."
|
||||||
|
|
||||||
|
**Trigger de compra:** mesa dupla marcada no mesmo horário; alta temporada com reservas a escapar por não conseguir atender o telefone.
|
||||||
|
|
||||||
|
**Pricing sweet spot:** €30-80/mês (margens apertadas — proposta tem de ser de ROI imediato e muito claro).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Nicho 7 — Contabilidade e Consultoria
|
||||||
|
|
||||||
|
**Quem:** Gabinetes de contabilidade, TOCs (Técnicos Oficiais de Contas), escritórios de advogados, consultores de gestão, solicitadores.
|
||||||
|
|
||||||
|
**Dimensão PT:** +8.000 gabinetes de contabilidade registados. Sector muito regulado, conservador, mas sob pressão de digitalização e de novas exigências da AT.
|
||||||
|
|
||||||
|
**Dores operacionais:**
|
||||||
|
- Clientes entregam documentação de forma caótica (papel, foto de WhatsApp, email)
|
||||||
|
- Prazos fiscais críticos (IRS, IRC, IVA, SS) gerem-se manualmente com risco de multa
|
||||||
|
- Comunicação de alertas a clientes por email → baixa taxa de abertura
|
||||||
|
- Facturação de honorários por horas não registadas sistematicamente
|
||||||
|
- Novos clientes: onboarding burocrático e demorado
|
||||||
|
|
||||||
|
**Funcionalidades mais relevantes:** portal de recolha de documentos do cliente, alertas de prazos fiscais automáticos por WhatsApp, registo automático de horas, facturação mensal, onboarding digital de clientes.
|
||||||
|
|
||||||
|
**Linguagem de venda:** "o cliente entrega os documentos pelo WhatsApp e chegam organizados", "o cliente recebe o alerta de IVA no dia certo, não quando já passou", "sem ligar 5 vezes para pedir o recibo". Evitar: "IA", "automação" — usar "sistema", "organização", "processo".
|
||||||
|
|
||||||
|
**Canal de aquisição:** Ordem dos Contabilistas Certificados, formações profissionais obrigatórias, referência entre TOCs, LinkedIn de gestores de gabinetes.
|
||||||
|
|
||||||
|
**Objecção principal:** "Os nossos clientes são conservadores e resistem a mudanças." → Resposta: "O cliente não vê nenhuma mudança — continua a mandar fotos para o WhatsApp. Só que chegam organizadas ao sistema em vez de à caixa de entrada da Ana."
|
||||||
|
|
||||||
|
**Trigger de compra:** multa de cliente por prazo fiscal falhado por comunicação deficiente; novo quadro legal que aumenta o volume de entregas obrigatórias.
|
||||||
|
|
||||||
|
**Pricing sweet spot:** €50-150/mês (sector conservador no pricing mas com ROI muito mensurável em tempo poupado).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Nicho 8 — E-commerce e Retalho Online
|
||||||
|
|
||||||
|
**Quem:** Lojas online, marcas DTC (direct-to-consumer), revendedores em marketplace (Amazon PT, FNAC, Worten), lojas omnicanal (físico + online).
|
||||||
|
|
||||||
|
**Dimensão PT:** +25.000 lojas online activas. Crescimento acelerado mas altíssima competição e margens em queda.
|
||||||
|
|
||||||
|
**Dores operacionais:**
|
||||||
|
- Volume de mensagens de suporte pós-venda (estado da encomenda, devoluções) insustentável
|
||||||
|
- Carrinhos abandonados sem follow-up automático → receita perdida
|
||||||
|
- Campanhas de reactivação de clientes inativos feitas manualmente
|
||||||
|
- Devoluções: processo manual, email interminável, cliente frustrado
|
||||||
|
- Avaliações negativas sem resposta → impacto na conversão
|
||||||
|
|
||||||
|
**Funcionalidades mais relevantes:** suporte automático de "onde está a minha encomenda" por WhatsApp, follow-up de carrinho abandonado, campanha de reactivação de clientes inativos, gestão de devoluções automatizada, resposta a reviews.
|
||||||
|
|
||||||
|
**Linguagem de venda:** "responde a 80% das perguntas de suporte sem intervenção humana", "recupera 15% dos carrinhos abandonados com um WhatsApp certo", "o cliente fica satisfeito sem precisar de esperar por email".
|
||||||
|
|
||||||
|
**Canal de aquisição:** comunidades de e-commerce (Shopify PT Facebook Group, grupos LinkedIn de e-commerce), eventos (eCommerce Day, NOS Alive), agências de e-commerce como parceiros.
|
||||||
|
|
||||||
|
**Objecção principal:** "Já usamos o suporte do Shopify." → Resposta: "O suporte do Shopify trata do que está dentro da plataforma. O AcidaOS trata do WhatsApp, do email e das mensagens do Instagram — que é de onde vêm 70% das perguntas reais."
|
||||||
|
|
||||||
|
**Trigger de compra:** Black Friday com volume de suporte 5x superior ao habitual sem equipa para responder; mês com carrinho abandonado acima de 70% sem follow-up.
|
||||||
|
|
||||||
|
**Pricing sweet spot:** €69-149/mês (familiarizados com SaaS, comparam com Gorgias €10-150/mês, Tidio €29-100/mês).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Nicho 9 — Educação e Formação
|
||||||
|
|
||||||
|
**Quem:** Centros de formação profissional, explicadores e centros de explicações, escolas de línguas, escolas de música/artes, coaches e mentores, plataformas de formação online.
|
||||||
|
|
||||||
|
**Dimensão PT:** sector em expansão acelerada. Formação profissional fortemente subsidiada (FSE/IEFP) com requisitos administrativos pesados.
|
||||||
|
|
||||||
|
**Dores operacionais:**
|
||||||
|
- Matrículas e inscrições por telefone e email — processo manual e demorado
|
||||||
|
- Comunicação com pais (no caso de menores) caótica e dispersa
|
||||||
|
- Cobranças de mensalidades em atraso constrangem a relação com o aluno/família
|
||||||
|
- Certificados e documentação de formação gerados manualmente
|
||||||
|
- Formação subsidiada: relatórios e documentação obrigatória para financiamento
|
||||||
|
|
||||||
|
**Funcionalidades mais relevantes:** inscrições online com confirmação automática, comunicação com pais por WhatsApp, cobranças automáticas com link de pagamento (MB Way), geração de certificados, relatórios de frequência.
|
||||||
|
|
||||||
|
**Linguagem de venda:** "os pais recebem updates do filho pelo WhatsApp, sem ligar para a recepção", "as inscrições chegam organizadas, não por telefone", "as mensalidades cobram-se sozinhas no dia certo".
|
||||||
|
|
||||||
|
**Canal de aquisição:** DGERT (entidade reguladora de formação), LinkedIn de directores pedagógicos, grupos Facebook de formadores, referência entre centros.
|
||||||
|
|
||||||
|
**Objecção principal:** "Temos sistema de gestão escolar." → Resposta: "O AcidaOS complementa — trata da comunicação e cobranças que o sistema escolar não faz."
|
||||||
|
|
||||||
|
**Trigger de compra:** período de matrículas com recepção sobrecarregada; mensalidade em atraso de mais de 3 meses por falta de follow-up.
|
||||||
|
|
||||||
|
**Pricing sweet spot:** €50-120/mês (sensíveis ao preço mas com ROI claro em cobranças recuperadas).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Nicho 10 — Serviços Técnicos Especializados
|
||||||
|
|
||||||
|
**Quem:** Empresas de IT/informática, AVAC, electricistas com empresa, empresas de segurança e alarmes, canalizadores, empresas de manutenção de equipamentos.
|
||||||
|
|
||||||
|
**Dimensão PT:** dezenas de milhares de micro e pequenas empresas. Alta dependência de WhatsApp para comunicar com técnicos e clientes. Muito fragmentado.
|
||||||
|
|
||||||
|
**Dores operacionais:**
|
||||||
|
- Chamadas de avaria chegam fora de horas sem registo
|
||||||
|
- Orçamentos de intervenções demoram dias (técnico tem de ver primeiro)
|
||||||
|
- Scheduling de técnicos manual — conflitos de agenda e deslocações ineficientes
|
||||||
|
- Contrato de manutenção: clientes que deviam contactar para revisão e não contactam
|
||||||
|
- Relatório de intervenção escrito à mão ou por memória do técnico
|
||||||
|
|
||||||
|
**Funcionalidades mais relevantes:** triagem automática de avarias fora de horas (gravidade, urgência), agendamento de técnicos por disponibilidade, geração de relatório de intervenção por voz (técnico descreve verbalmente → relatório gerado), alertas de manutenção preventiva, facturação de serviço.
|
||||||
|
|
||||||
|
**Linguagem de venda:** "o técnico descreve o trabalho pelo WhatsApp e o relatório fica pronto", "as chamadas de avaria fora de horas ficam registadas e triadas", "o cliente de manutenção recebe o alerta de revisão no mês certo".
|
||||||
|
|
||||||
|
**Canal de aquisição:** associações sectoriais (ANEOP, ASIAM), LinkedIn de gestores de empresa técnica, grupos Facebook de técnicos, referência entre pares.
|
||||||
|
|
||||||
|
**Objecção principal:** "Os meus técnicos não usam computador." → Resposta: "Exactamente por isso — o AcidaOS funciona pelo WhatsApp que eles já usam. O relatório faz-se com uma nota de voz."
|
||||||
|
|
||||||
|
**Trigger de compra:** chamada de avaria urgente perdida fora de horas; técnico que sai e leva o registo das intervenções que fez.
|
||||||
|
|
||||||
|
**Pricing sweet spot:** €40-100/mês (dispostos a pagar pelo valor em tempo poupado e em trabalho não perdido).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tabela resumo — priorização por atractividade
|
||||||
|
|
||||||
|
| Nicho | Volume PT | Urgência da dor | Disposição a pagar | Canal de entrada | Score |
|
||||||
|
|-------|-----------|----------------|-------------------|-----------------|-------|
|
||||||
|
| Saúde Privada | Alta | Muito alta | Alta | Associações + Google | ⭐⭐⭐⭐⭐ |
|
||||||
|
| Imobiliárias | Média | Alta | Alta | LinkedIn + portais | ⭐⭐⭐⭐⭐ |
|
||||||
|
| Agências Digitais | Média | Alta | Muito alta | LinkedIn + eventos | ⭐⭐⭐⭐⭐ |
|
||||||
|
| E-commerce | Alta | Alta | Alta | Comunidades + parceiros | ⭐⭐⭐⭐ |
|
||||||
|
| Contabilidade | Alta | Média-alta | Média | Ordem OCC + formação | ⭐⭐⭐⭐ |
|
||||||
|
| Construção | Muito alta | Alta | Média | Referência + associações | ⭐⭐⭐⭐ |
|
||||||
|
| Comércio B2B | Alta | Alta | Média-alta | Feiras + LinkedIn | ⭐⭐⭐⭐ |
|
||||||
|
| Serviços Técnicos | Muito alta | Média | Média | Referência + grupos | ⭐⭐⭐ |
|
||||||
|
| Educação | Média | Média | Baixa-média | DGERT + referência | ⭐⭐⭐ |
|
||||||
|
| Restauração | Muito alta | Média | Baixa | AHRESP + Instagram | ⭐⭐⭐ |
|
||||||
|
|
||||||
|
**Top 3 para arranque:** Saúde Privada, Imobiliárias, Agências Digitais — dor alta, disposição a pagar alta, canais de entrada claros.
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
# Perguntas de Briefing — Entrevista Estratégica
|
||||||
|
|
||||||
|
Guia de entrevista estruturado para conduzir o briefing inicial com o cliente.
|
||||||
|
Adaptar ao sector e nível de maturidade da marca.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Bloco 1 — O negócio
|
||||||
|
|
||||||
|
### Contexto actual
|
||||||
|
1. O que faz a sua empresa, em termos simples?
|
||||||
|
2. Há quantos anos está no mercado? Como surgiu?
|
||||||
|
3. Qual a dimensão actual: equipa, facturação, clientes?
|
||||||
|
4. Qual é o maior desafio que enfrenta hoje no negócio?
|
||||||
|
5. O que o distingue dos concorrentes? (resposta espontânea — não sugerir)
|
||||||
|
|
||||||
|
### Serviços e produtos
|
||||||
|
6. Quais são os seus produtos/serviços principais?
|
||||||
|
7. Qual gera mais receita? Qual tem mais potencial?
|
||||||
|
8. Existe algum produto que quer destacar mais? Porquê?
|
||||||
|
9. Que resultados concretos entregam aos clientes?
|
||||||
|
|
||||||
|
### Posicionamento actual
|
||||||
|
10. Se pedisse a um cliente para descrever a sua empresa em 3 palavras, o que diria?
|
||||||
|
11. Existe uma percepção de mercado que quer mudar?
|
||||||
|
12. Onde se posiciona em preço vs concorrência? (mais caro, igual, mais barato) Porquê?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Bloco 2 — O cliente ideal
|
||||||
|
|
||||||
|
### Segmentação
|
||||||
|
13. Quem é o seu cliente ideal? Descreva-o em detalhe.
|
||||||
|
14. Tem mais do que um tipo de cliente? Como os diferencia?
|
||||||
|
15. Qual o cliente que mais valoriza o que fazem e paga melhor?
|
||||||
|
16. Existe algum cliente que não quer ter? Porquê?
|
||||||
|
|
||||||
|
### Comportamento de compra
|
||||||
|
17. Como é que os clientes chegam até si? (canal principal de aquisição)
|
||||||
|
18. Quanto tempo demora tipicamente desde o primeiro contacto até fechar negócio?
|
||||||
|
19. Quem toma a decisão de compra? É uma pessoa ou um grupo?
|
||||||
|
20. Que objecções ouve mais frequentemente antes de fechar?
|
||||||
|
|
||||||
|
### Relação com clientes
|
||||||
|
21. Qual foi o feedback mais positivo que recebeu de um cliente? (pedir citação exacta)
|
||||||
|
22. Qual foi a queixa mais comum? Como resolveram?
|
||||||
|
23. Tem clientes que recomendam espontaneamente? O que dizem?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Bloco 3 — Mercado e concorrência
|
||||||
|
|
||||||
|
### Mercado
|
||||||
|
24. Em que mercado opera? Geográfico (local, nacional, internacional)?
|
||||||
|
25. O mercado está a crescer, estável ou a contrair?
|
||||||
|
26. Que tendência do mercado mais o preocupa? Qual mais o entusiasma?
|
||||||
|
27. Existe sazonalidade? Em que períodos?
|
||||||
|
|
||||||
|
### Concorrência
|
||||||
|
28. Quem são os 3 principais concorrentes?
|
||||||
|
29. Em que é que são melhores? Em que é que são piores?
|
||||||
|
30. Por que é que um cliente nos escolhe a nós vs ao concorrente X?
|
||||||
|
31. Existe algum concorrente que admira (mesmo que de outra área)?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Bloco 4 — Visão e ambição
|
||||||
|
|
||||||
|
### Onde quer chegar
|
||||||
|
32. Qual é o objectivo da empresa a 3 anos?
|
||||||
|
33. O que precisa de mudar para chegar lá?
|
||||||
|
34. Existe um modelo de empresa que admira ou quer imitar? Porquê?
|
||||||
|
35. Se tivesse recursos ilimitados, o que faria primeiro?
|
||||||
|
|
||||||
|
### Marca e identidade
|
||||||
|
36. Que 3 adjectivos descrevem a personalidade ideal da marca?
|
||||||
|
37. Que marcas (de qualquer sector) admira pela comunicação? O que lhes agrada?
|
||||||
|
38. Existe uma história de origem da empresa que emociona? (fundador, momento de viragem)
|
||||||
|
39. Que valores são inegociáveis? O que nunca fariam por dinheiro?
|
||||||
|
|
||||||
|
### Tom de voz
|
||||||
|
40. A marca é mais formal ou informal? Mais técnica ou acessível?
|
||||||
|
41. Usa humor na comunicação? Em que contextos?
|
||||||
|
42. Existe linguagem/palavras que NÃO deve usar?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Bloco 5 — Recursos e restrições
|
||||||
|
|
||||||
|
### Capacidade
|
||||||
|
43. Qual o budget mensal disponível para marketing?
|
||||||
|
44. Existe equipa interna de marketing ou será tudo externalizado?
|
||||||
|
45. Quem aprova conteúdos? Qual o processo de revisão?
|
||||||
|
|
||||||
|
### Prazo
|
||||||
|
46. Existe algum lançamento, evento ou data importante a curto prazo?
|
||||||
|
47. Quando precisa de ter a estratégia operacional?
|
||||||
|
|
||||||
|
### Material existente
|
||||||
|
48. Existe alguma estratégia anterior? O que funcionou? O que não funcionou?
|
||||||
|
49. Que activos existem: website, redes sociais, base de emails, testemunhos, cases?
|
||||||
|
50. Existem fotos/vídeos profissionais? Em que estado está a identidade visual?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notas de condução da entrevista
|
||||||
|
|
||||||
|
- Fazer max 15-20 perguntas numa sessão (60-90 min)
|
||||||
|
- Priorizar: Blocos 1, 2 e 4 na primeira sessão
|
||||||
|
- Blocos 3 e 5 podem ser preenchidos com pesquisa independente
|
||||||
|
- Pedir sempre exemplos concretos e citações textuais de clientes
|
||||||
|
- Quando a resposta é vaga, fazer "pode dar-me um exemplo específico?"
|
||||||
|
- Gravar a sessão (com autorização) para não perder citações úteis
|
||||||
@@ -0,0 +1,374 @@
|
|||||||
|
# Template: Documento de Estratégia de Marca
|
||||||
|
|
||||||
|
Estrutura completa do documento entregável ao cliente. Baseado nos projectos SFV, LJM, MCT, Espiral Senior e Sintricare.
|
||||||
|
Adaptar secções ao sector e complexidade do cliente.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Cabeçalho do documento
|
||||||
|
|
||||||
|
```
|
||||||
|
---
|
||||||
|
title: [Nome da Marca] — Estratégia de Marca
|
||||||
|
cliente: [Nome do cliente]
|
||||||
|
código: EST-MRK-010
|
||||||
|
versão: 1.0
|
||||||
|
data: [DD-MM-YYYY]
|
||||||
|
elaborado: Descomplicar® — Agência de Aceleração Digital
|
||||||
|
status: draft | aprovado
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## DECLARAÇÃO DE IMPACTO
|
||||||
|
|
||||||
|
> **[Uma frase poderosa — 10-15 palavras máximo]**
|
||||||
|
> *A essência e o impacto da marca numa linha.*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ÍNDICE
|
||||||
|
|
||||||
|
1. Apresentação e Fundamentos Estratégicos
|
||||||
|
2. Proposta de Valor Única
|
||||||
|
3. Missão, Visão, Valores e Objectivos
|
||||||
|
4. Apresentação Sumária da Empresa e Serviços
|
||||||
|
5. Segmentação e Análise Detalhada de Público
|
||||||
|
6. Pitch Canvas
|
||||||
|
7. Copywriting Estratégico
|
||||||
|
8. Estratégia de Comunicação e Canais
|
||||||
|
9. Investimentos Prioritários
|
||||||
|
10. Monitorização e KPIs
|
||||||
|
11. Inventário de Activos de Marketing
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Apresentação e Fundamentos Estratégicos
|
||||||
|
|
||||||
|
### 1.1 Contexto actual
|
||||||
|
- **Mercado:** [Análise do mercado actual — dimensão, tendências, oportunidades]
|
||||||
|
- **Concorrência:** [Principais concorrentes e posições]
|
||||||
|
- **Desafios:** [Principais desafios enfrentados pela marca]
|
||||||
|
- **Oportunidades:** [Oportunidades identificadas]
|
||||||
|
|
||||||
|
### 1.2 Problema a resolver
|
||||||
|
[Identificação clara do problema de negócio que esta estratégia precisa resolver — qual é o problema central que impede o crescimento ou o impacto da marca?]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Proposta de Valor Única
|
||||||
|
|
||||||
|
### 2.1 O que nos torna únicos
|
||||||
|
[O que tornamos possível que os concorrentes não conseguem. Ser específico — evitar "qualidade e experiência".]
|
||||||
|
|
||||||
|
### 2.2 Diferenciais competitivos
|
||||||
|
1. [Diferencial 1 — explicar o mecanismo único que o cria]
|
||||||
|
2. [Diferencial 2]
|
||||||
|
3. [Diferencial 3]
|
||||||
|
|
||||||
|
### 2.3 Benefícios por camada
|
||||||
|
| Tipo | Benefícios |
|
||||||
|
|------|-----------|
|
||||||
|
| **Funcionais** | [O que o produto/serviço faz concretamente] |
|
||||||
|
| **Emocionais** | [Como o cliente se sente ao usar/contratar] |
|
||||||
|
| **Identitários** | [O que diz sobre o cliente escolher esta marca] |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Missão, Visão, Valores e Objectivos
|
||||||
|
|
||||||
|
### 3.1 Missão
|
||||||
|
> [O que fazemos, para quem e como — acção no presente. Max 2 frases.]
|
||||||
|
|
||||||
|
### 3.2 Visão
|
||||||
|
> [Onde queremos estar e que impacto queremos ter em 3-5 anos. Max 2 frases.]
|
||||||
|
|
||||||
|
### 3.3 Valores
|
||||||
|
- **[Valor 1]** — [Como se manifesta na prática, no dia-a-dia da empresa]
|
||||||
|
- **[Valor 2]** — [Como se manifesta]
|
||||||
|
- **[Valor 3]** — [Como se manifesta]
|
||||||
|
- **[Valor 4]** — [Como se manifesta] *(opcional)*
|
||||||
|
|
||||||
|
### 3.4 Objectivos estratégicos
|
||||||
|
- **Curto prazo (6m):** [2-3 objectivos mensuráveis]
|
||||||
|
- **Médio prazo (1 ano):** [2-3 objectivos]
|
||||||
|
- **Longo prazo (3 anos):** [Ambição de impacto]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Apresentação Sumária da Empresa e Serviços
|
||||||
|
|
||||||
|
### 4.1 Quem somos
|
||||||
|
[Parágrafo de apresentação — quem são, o que fazem, há quanto tempo, dimensão, missão em acção]
|
||||||
|
|
||||||
|
### 4.2 Serviços/Produtos principais
|
||||||
|
|
||||||
|
| Serviço/Produto | Descrição | Para quem | Resultado principal |
|
||||||
|
|----------------|-----------|-----------|-------------------|
|
||||||
|
| [Nome] | — | — | — |
|
||||||
|
| [Nome] | — | — | — |
|
||||||
|
|
||||||
|
### 4.3 Posicionamento
|
||||||
|
[Declaração de posicionamento — o lugar único que a marca ocupa na mente do cliente]
|
||||||
|
|
||||||
|
> "Para [público], somos a única [categoria] que [benefício único] porque [prova]."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Segmentação e Análise Detalhada de Público
|
||||||
|
|
||||||
|
*Repetir a estrutura completa dos 20 pontos para cada segmento identificado.*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 5.X — [Nome do Segmento]
|
||||||
|
|
||||||
|
*[Breve descrição de quem é este segmento — 2 linhas]*
|
||||||
|
|
||||||
|
#### 1. Perfil Demográfico
|
||||||
|
[Idade, género, localização, rendimento, nível de educação, profissão, cargo, tipo/dimensão de empresa, estado civil, composição familiar — tudo o que é mensurável e verificável]
|
||||||
|
|
||||||
|
#### 2. Perfil Psicográfico
|
||||||
|
[Valores pessoais, crenças, atitude perante a vida, estilo de vida, motivações profundas, relação com a categoria de produto/serviço, identidade social — o que não se mede mas define quem são]
|
||||||
|
|
||||||
|
#### 3. Dores
|
||||||
|
[Problemas activos e urgentes que precisam resolver. O que os está a prejudicar agora. Dores específicas do dia-a-dia relacionadas com o que a marca resolve.]
|
||||||
|
|
||||||
|
#### 4. Anseios
|
||||||
|
[O que aspiram a ser, ter ou alcançar. Sonhos profissionais e pessoais. A versão ideal do futuro que imaginam.]
|
||||||
|
|
||||||
|
#### 5. Desejos
|
||||||
|
[O que querem concretamente — mais imediato e específico que os anseios. Desejos práticos relacionados com a nossa oferta.]
|
||||||
|
|
||||||
|
#### 6. Frustrações
|
||||||
|
[O que já tentaram fazer ou comprar sem resultado. Soluções que prometeram e não entregaram. O cansaço acumulado de não resolver o problema.]
|
||||||
|
|
||||||
|
#### 7. Preocupações
|
||||||
|
[O que os inquieta a médio/longo prazo. Cenários negativos que imaginam. Preocupações sistémicas relacionadas com a sua vida ou negócio.]
|
||||||
|
|
||||||
|
#### 8. Medos
|
||||||
|
[Medos concretos associados à compra ou à não-compra. Medo de errar, de ser enganado, de perder dinheiro, de ser julgado. O que os paralisa antes de decidir.]
|
||||||
|
|
||||||
|
#### 9. Inimigos
|
||||||
|
[Os "vilões" da história deste segmento — concorrentes que os desiludiram, sistemas que os prejudicam, tendências que os ameaçam, pessoas ou entidades a quem culpam o problema]
|
||||||
|
|
||||||
|
#### 10. Linguagem
|
||||||
|
[As palavras e expressões exactas que usam para descrever o problema, a solução e os resultados. Jargão do sector. O que dizem aos amigos. O que escrevem no Google. Evitar linguagem que usamos internamente mas eles não usam.]
|
||||||
|
|
||||||
|
#### 11. Como procuram ajuda, informação ou dicas?
|
||||||
|
[Onde vão quando têm o problema: Google (que pesquisas fazem?), YouTube, grupos Facebook, LinkedIn, amigos, consultores, feiras, etc. Que tipo de conteúdo consomem para se informar?]
|
||||||
|
|
||||||
|
#### 12. Canais digitais
|
||||||
|
[Em que plataformas estão activos: Facebook, Instagram, LinkedIn, TikTok, YouTube, email, WhatsApp, fóruns, etc. Com que frequência? Em que contexto (trabalho vs lazer)?]
|
||||||
|
|
||||||
|
#### 13. Estilo de Decisão
|
||||||
|
[Como tomam decisões de compra: rápido vs deliberado, emocional vs racional, individual vs colectivo, impulsivo vs comparativo. Que factores pesam mais? Precisam de aprovação de terceiros?]
|
||||||
|
|
||||||
|
#### 14. Mudanças
|
||||||
|
[Mudanças que sabem e sentem necessárias nas suas vidas ou negócio. Passos que sabem que precisam dar mas ainda não deram. A consciência que já têm do problema.]
|
||||||
|
|
||||||
|
#### 15. Resistência à Mudança
|
||||||
|
[De que maneira resistem à mudança? Que desculpas usam para adiar? Como os podemos ajudar a ultrapassar essa resistência? Que argumentos reduzem o atrito?]
|
||||||
|
|
||||||
|
#### 16. Objecções Típicas
|
||||||
|
[As objecções mais frequentes às ofertas comerciais desta categoria. Como as podemos antecipar e superar? Respostas específicas a cada objecção.]
|
||||||
|
|
||||||
|
| Objecção | Como ultrapassar |
|
||||||
|
|----------|----------------|
|
||||||
|
| — | — |
|
||||||
|
| — | — |
|
||||||
|
| — | — |
|
||||||
|
|
||||||
|
#### 17. Forma de Gerar Emoção
|
||||||
|
[Que tipo de conteúdo, história ou mensagem os move emocionalmente? O que os faz parar no scroll? O que os faz partilhar? Qual o gatilho emocional mais poderoso para este segmento?]
|
||||||
|
|
||||||
|
#### 18. Argumentos
|
||||||
|
[A que argumentos são mais sensíveis? Como os podemos persuadir a agir? Que tipo de prova precisam: dados, testemunhos, demonstrações, garantias? Qual a sequência de persuasão ideal?]
|
||||||
|
|
||||||
|
#### 19. Concorrentes
|
||||||
|
[Que outras entidades lhes oferecem o mesmo tipo de serviço ou solução alternativa? Como se comparam a nós em percepção de valor?]
|
||||||
|
|
||||||
|
#### 20. Propostas Recusadas
|
||||||
|
[Que propostas é que este segmento tem recusado e porquê? O que dizem explicitamente e o que dizem implicitamente? O que não querem mais ouvir?]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Pitch Canvas
|
||||||
|
|
||||||
|
### 6.1 O que é o Pitch Canvas?
|
||||||
|
O Pitch Canvas é uma ferramenta de comunicação estratégica que resume, numa única estrutura visual, o essencial da proposta de valor da empresa. É útil porque:
|
||||||
|
- Força clareza e síntese (não há espaço para vagueza)
|
||||||
|
- Alinha toda a equipa na mesma mensagem
|
||||||
|
- Serve de base para qualquer peça de comunicação
|
||||||
|
- Torna a proposta de valor testável e iterável
|
||||||
|
|
||||||
|
### 6.2 Utilidade específica para [Nome da Marca]
|
||||||
|
[Como o Pitch Canvas pode ajudar esta marca concretamente — que clareza traz, que conversas simplifica, onde pode ser usado]
|
||||||
|
|
||||||
|
### 6.3 Os 5 elementos do Pitch Canvas
|
||||||
|
|
||||||
|
**Para quem:**
|
||||||
|
> [Segmento principal — quem são e qual o problema específico]
|
||||||
|
|
||||||
|
**O problema:**
|
||||||
|
> [Dor principal, urgente e real — formulada na linguagem do cliente]
|
||||||
|
|
||||||
|
**A solução:**
|
||||||
|
> [O que oferecemos — mecanismo único de resolução]
|
||||||
|
|
||||||
|
**O resultado:**
|
||||||
|
> [Transformação concreta — antes vs depois, com métrica se possível]
|
||||||
|
|
||||||
|
**Por que nós:**
|
||||||
|
> [Razão para acreditar — o que nos torna credíveis e únicos]
|
||||||
|
|
||||||
|
### 6.4 Declaração de mudança no mundo
|
||||||
|
> **"[Nome da Marca] está a mudar [o quê] para [quem], através de [como], tornando possível [impacto maior]."**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Copywriting Estratégico
|
||||||
|
|
||||||
|
### 7.1 Questionamento estratégico
|
||||||
|
|
||||||
|
**Qual é o objectivo da comunicação?**
|
||||||
|
[Definir claramente o que queremos que o público faça, sinta ou pense após cada comunicação. Sem objectivo claro não há comunicação eficaz.]
|
||||||
|
|
||||||
|
**Que transformação prometemos?**
|
||||||
|
[A transformação específica que a marca entrega — não o produto, mas a mudança de estado do cliente]
|
||||||
|
|
||||||
|
### 7.2 Pain + Gain (Problema e Resultado)
|
||||||
|
|
||||||
|
> **Pain:** [O problema central na perspectiva do cliente — formulado com a dor, não com o produto]
|
||||||
|
> **Gain:** [O resultado desejado — formulado com o benefício, não com a funcionalidade]
|
||||||
|
|
||||||
|
*Revisão com questões específicas do sector:*
|
||||||
|
> **Pain refinado:** [Após aprofundar com o briefing — mais específico, com linguagem do cliente]
|
||||||
|
> **Gain refinado:** [Com métricas ou resultados concretos já entregues a outros clientes]
|
||||||
|
|
||||||
|
### 7.3 Narrativa por segmento
|
||||||
|
|
||||||
|
*Fórmula: Problema (dor do público) → Solução (serviços da empresa) → Resultado (benefícios concretos)*
|
||||||
|
|
||||||
|
**[Segmento A]:**
|
||||||
|
> **Problema:** [Dor específica e urgente deste segmento, na sua linguagem]
|
||||||
|
> **Solução:** [Como a marca resolve de forma única — mecanismo específico]
|
||||||
|
> **Resultado:** [Benefício tangível e mensurável + prova social ou garantia]
|
||||||
|
|
||||||
|
**[Segmento B]:**
|
||||||
|
> **Problema:** [...]
|
||||||
|
> **Solução:** [...]
|
||||||
|
> **Resultado:** [...]
|
||||||
|
|
||||||
|
*(Repetir para cada segmento)*
|
||||||
|
|
||||||
|
### 7.4 Mensagem central da marca
|
||||||
|
> **"[A frase que todos os colaboradores sabem de cor — resumo da proposta de valor em 10 palavras]"**
|
||||||
|
|
||||||
|
### 7.5 Headlines por segmento
|
||||||
|
|
||||||
|
| Segmento | Headline principal | Headline secundária |
|
||||||
|
|----------|------------------|-------------------|
|
||||||
|
| [Seg. A] | — | — |
|
||||||
|
| [Seg. B] | — | — |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Demonstração dos Serviços
|
||||||
|
|
||||||
|
### 8.1 Como demonstrar [serviço/produto principal]
|
||||||
|
|
||||||
|
**Preparação personalizada:**
|
||||||
|
[O que preparar antes da demonstração para cada segmento]
|
||||||
|
|
||||||
|
**Introdução interactiva:**
|
||||||
|
[Como começar — conectar com a dor antes de mostrar a solução]
|
||||||
|
|
||||||
|
**Demonstração ao vivo:**
|
||||||
|
[O que mostrar, em que ordem, com que foco]
|
||||||
|
|
||||||
|
**Casos de uso:**
|
||||||
|
[Exemplos reais de clientes similares — antes/depois]
|
||||||
|
|
||||||
|
**Q&A:**
|
||||||
|
[Perguntas frequentes na demonstração e respostas modelo]
|
||||||
|
|
||||||
|
**Follow-up:**
|
||||||
|
[Próximo passo após a demonstração — o que enviar, quando contactar]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Investimentos Prioritários
|
||||||
|
|
||||||
|
### 9.1 Prioridades imediatas (impacto/esforço)
|
||||||
|
|
||||||
|
| Prioridade | Investimento | Impacto esperado | Prazo | Custo estimado |
|
||||||
|
|-----------|-------------|-----------------|-------|---------------|
|
||||||
|
| 1 | [Ex: Website + SEO] | — | 30-60d | — |
|
||||||
|
| 2 | [Ex: Google Ads] | — | 30d | — |
|
||||||
|
| 3 | [Ex: Email marketing] | — | 60d | — |
|
||||||
|
|
||||||
|
### 9.2 Estratégia de canais
|
||||||
|
|
||||||
|
| Canal | Objectivo | Frequência | KPI | Budget mensal |
|
||||||
|
|-------|-----------|-----------|-----|--------------|
|
||||||
|
| Website | — | — | — | — |
|
||||||
|
| Google Ads | — | — | — | — |
|
||||||
|
| Meta Ads | — | — | — | — |
|
||||||
|
| LinkedIn | — | — | — | — |
|
||||||
|
| Email | — | — | — | — |
|
||||||
|
| WhatsApp | — | — | — | — |
|
||||||
|
|
||||||
|
### 9.3 Pilares de conteúdo
|
||||||
|
1. [Pilar 1 — tema + tipos de conteúdo + frequência]
|
||||||
|
2. [Pilar 2]
|
||||||
|
3. [Pilar 3]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Monitorização e KPIs
|
||||||
|
|
||||||
|
### 10.1 Dashboard de métricas
|
||||||
|
|
||||||
|
| Área | KPI | Baseline | Meta 3m | Meta 6m | Meta 12m |
|
||||||
|
|------|-----|---------|---------|---------|----------|
|
||||||
|
| Brand | Notoriedade espontânea | — | — | — | — |
|
||||||
|
| Tráfego | Visitas/mês | — | — | — | — |
|
||||||
|
| Leads | Leads qualificados/mês | — | — | — | — |
|
||||||
|
| Conversão | Taxa de fecho | — | — | — | — |
|
||||||
|
| Retenção | NPS | — | — | — | — |
|
||||||
|
|
||||||
|
### 10.2 Ciclo de optimização
|
||||||
|
- **Revisão mensal:** métricas de canal, ajuste de conteúdo
|
||||||
|
- **Revisão trimestral:** avaliação de ROI, ajuste de orçamento
|
||||||
|
- **Revisão anual:** actualização estratégica completa
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. Inventário de Activos de Marketing
|
||||||
|
|
||||||
|
| Activo | Localização | Estado actual | Prioridade |
|
||||||
|
|--------|------------|--------------|-----------|
|
||||||
|
| Website | [URL] | — | — |
|
||||||
|
| Blog/Artigos | — | — | — |
|
||||||
|
| Redes sociais | — | — | — |
|
||||||
|
| Base de emails | — | — | — |
|
||||||
|
| Testemunhos/Cases | — | — | — |
|
||||||
|
| Materiais impressos | — | — | — |
|
||||||
|
| Apresentações | — | — | — |
|
||||||
|
| Fotos/Vídeos profissionais | — | — | — |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notas de implementação
|
||||||
|
|
||||||
|
1. **Sessão de alinhamento:** Apresentar o documento à equipa antes de implementar
|
||||||
|
2. **Validação:** Partilhar narrativas com 2-3 clientes actuais antes de publicar
|
||||||
|
3. **Implementação faseada:** Começar pelos canais de maior impacto e menor esforço
|
||||||
|
4. **Suporte:** WhatsApp durante 1 mês para dúvidas de implementação (EST-MRK-010)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Elaborado por Descomplicar® — Agência de Aceleração Digital*
|
||||||
|
*emanuel@descomplicar.pt | descomplicar.pt*
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: expense
|
name: expense
|
||||||
description: Gestao de despesas Desk CRM com PDF obrigatorio. Registar, categorizar e analisar despesas com verificacao de duplicados, upload SFTP e arquivo mensal automatico.
|
description: Gestao de despesas Desk CRM com PDF obrigatorio. Registar, categorizar e analisar despesas com verificacao de duplicados por reference_no, upload SFTP e arquivo mensal automatico.
|
||||||
---
|
---
|
||||||
|
|
||||||
# /expense - Gestao de Despesas
|
# /expense - Gestao de Despesas
|
||||||
@@ -55,18 +55,27 @@ Para mapeamento completo de fornecedores, emails e padroes PDF para categorias:
|
|||||||
- Bypass valido apenas para: AT, Salarios, transferencias bancarias
|
- Bypass valido apenas para: AT, Salarios, transferencias bancarias
|
||||||
2. LER O PDF: Extrair dados reais do documento
|
2. LER O PDF: Extrair dados reais do documento
|
||||||
- NUNCA copiar valor de um PDF para outro
|
- NUNCA copiar valor de um PDF para outro
|
||||||
|
- EXTRAIR reference_no (numero factura) — OBRIGATORIO para dedup
|
||||||
3. OBRIGATORIO: get_expense_categories(with_stats=true)
|
3. OBRIGATORIO: get_expense_categories(with_stats=true)
|
||||||
4. Identificar categoria correcta na lista
|
4. Identificar categoria correcta na lista
|
||||||
5. VERIFICAR DUPLICADOS:
|
5. VERIFICAR DUPLICADOS (3 camadas — OBRIGATORIO):
|
||||||
|
Camada 0 — Referencia de factura (PRIMARIA):
|
||||||
|
- get_expenses(search: "<reference_no>")
|
||||||
|
- Se alguma despesa tem reference_no IGUAL → DUPLICADO → PARAR
|
||||||
|
Camada 1 — Fornecedor + Valor + Data:
|
||||||
- get_expenses(search: "<fornecedor>")
|
- get_expenses(search: "<fornecedor>")
|
||||||
- Mesmo fornecedor + valor + data = duplicado
|
- Mesmo fornecedor + valor (±0.05) + data (±3 dias) = duplicado
|
||||||
- Mesmo numero factura = duplicado
|
Camada 2 — Expense name:
|
||||||
|
- get_expenses(search: "<fornecedor> - <reference_no>")
|
||||||
|
- Se match exacto → duplicado
|
||||||
|
Se QUALQUER camada detecta duplicado → NAO criar, informar utilizador
|
||||||
6. Recolher dados:
|
6. Recolher dados:
|
||||||
- category_id, amount, currency (EUR=3, USD=2), date (YYYY-MM-DD)
|
- category_id, amount, currency (EUR=3, USD=2), date (YYYY-MM-DD)
|
||||||
|
- reference_no (numero factura — OBRIGATORIO)
|
||||||
- note (incluir numero factura), send_invoice_to_customer = 0
|
- note (incluir numero factura), send_invoice_to_customer = 0
|
||||||
- Opcionais: client_id, project_id, billable, tax
|
- Opcionais: client_id, project_id, billable, tax
|
||||||
7. CONFIRMAR com utilizador (mostrar resumo)
|
7. CONFIRMAR com utilizador (mostrar resumo)
|
||||||
8. create_expense
|
8. create_expense (INCLUIR reference_no no payload)
|
||||||
9. UPLOAD PDF ao Desk via SFTP:
|
9. UPLOAD PDF ao Desk via SFTP:
|
||||||
a. mkdir -p no servidor: /home/ealmeida/desk.descomplicar.pt/uploads/expenses/<id>
|
a. mkdir -p no servidor: /home/ealmeida/desk.descomplicar.pt/uploads/expenses/<id>
|
||||||
b. mcp__ssh-unified__sftp_upload(server:"desk", local_path, remote_path)
|
b. mcp__ssh-unified__sftp_upload(server:"desk", local_path, remote_path)
|
||||||
@@ -104,7 +113,7 @@ Para mapeamento completo de fornecedores, emails e padroes PDF para categorias:
|
|||||||
|
|
||||||
Para protocolo completo de processamento de tickets de contabilidade: ver `references/ticket-processing.md`
|
Para protocolo completo de processamento de tickets de contabilidade: ver `references/ticket-processing.md`
|
||||||
|
|
||||||
**Resumo:** Obter ticket -> verificar anexos -> verificar duplicados -> extrair dados -> confirmar -> criar despesa -> upload PDF -> arquivo mensal.
|
**Resumo:** Obter ticket -> verificar anexos -> verificar duplicados (3 camadas) -> extrair dados -> confirmar -> criar despesa -> upload PDF -> arquivo mensal.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -136,15 +145,16 @@ Para protocolo completo de processamento de tickets de contabilidade: ver `refer
|
|||||||
**Despesas:**
|
**Despesas:**
|
||||||
4. Criar despesa sem category_id
|
4. Criar despesa sem category_id
|
||||||
5. Nao validar data (formato YYYY-MM-DD)
|
5. Nao validar data (formato YYYY-MM-DD)
|
||||||
6. Criar despesa sem verificar duplicados primeiro
|
6. Criar despesa sem verificar duplicados primeiro (3 camadas obrigatorias)
|
||||||
|
7. Criar despesa sem reference_no (chave primaria de dedup)
|
||||||
|
|
||||||
**Valores de PDFs:**
|
**Valores de PDFs:**
|
||||||
7. Assumir que ficheiros com nomes semelhantes tem o mesmo valor
|
8. Assumir que ficheiros com nomes semelhantes tem o mesmo valor
|
||||||
8. SEMPRE ler CADA PDF individualmente para extrair o valor real
|
9. SEMPRE ler CADA PDF individualmente para extrair o valor real
|
||||||
|
|
||||||
**Tickets:**
|
**Tickets:**
|
||||||
9. Processar ticket sem verificar anexos PDF
|
10. Processar ticket sem verificar anexos PDF
|
||||||
10. Assumir que ticket com recibo = despesa nao lancada
|
11. Assumir que ticket com recibo = despesa nao lancada
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -152,8 +162,11 @@ Para protocolo completo de processamento de tickets de contabilidade: ver `refer
|
|||||||
|
|
||||||
- [ ] Listar categorias existentes
|
- [ ] Listar categorias existentes
|
||||||
- [ ] Validar categoria correcta
|
- [ ] Validar categoria correcta
|
||||||
|
- [ ] Extrair reference_no do PDF/factura
|
||||||
|
- [ ] Verificar duplicados (3 camadas)
|
||||||
- [ ] Confirmar dados com utilizador
|
- [ ] Confirmar dados com utilizador
|
||||||
- [ ] Usar formato data YYYY-MM-DD
|
- [ ] Usar formato data YYYY-MM-DD
|
||||||
|
- [ ] Incluir reference_no no create_expense
|
||||||
- [ ] Incluir nota descritiva
|
- [ ] Incluir nota descritiva
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -164,6 +177,24 @@ Para protocolo completo de processamento de tickets de contabilidade: ver `refer
|
|||||||
- `references/ticket-processing.md` - Protocolo completo de processamento de tickets
|
- `references/ticket-processing.md` - Protocolo completo de processamento de tickets
|
||||||
- `references/changelog.md` - Historico de alteracoes
|
- `references/changelog.md` - Historico de alteracoes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Criado:** 2026-02-05 | **Actualizado:** 2026-02-12
|
## Self-Healing
|
||||||
|
|
||||||
|
Antes de executar, ler `~/.claude-work/healing/expense.jsonl` (se existir). Cada linha é um padrão de erro conhecido:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"date":"YYYY-MM-DD","issue":"descrição do problema","fix":"como evitar","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
Se encontrares um padrão relevante ao contexto actual, aplica o fix preventivamente. Após cada erro ou correcção do utilizador nesta skill, **adicionar nova linha** ao healing log com o padrão aprendido.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Criado:** 2026-02-05 | **Actualizado:** 2026-03-30 | Fix: dedup 3 camadas com reference_no (DES-137)
|
||||||
|
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
<!-- Registo automático de erros e correcções nesta skill -->
|
||||||
|
|||||||
@@ -253,3 +253,15 @@ Acções:
|
|||||||
---
|
---
|
||||||
|
|
||||||
*Skill v1.0.0 | 2026-02-05 | Descomplicar®*
|
*Skill v1.0.0 | 2026-02-05 | Descomplicar®*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -0,0 +1,150 @@
|
|||||||
|
---
|
||||||
|
name: orcamento
|
||||||
|
description: Criação de orçamentos Descomplicar baseados nos itens oficiais do Desk CRM. Versão light para heartbeats.
|
||||||
|
disable-model-invocation: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# Orçamento — Referência Rápida
|
||||||
|
|
||||||
|
## Fonte de verdade: Desk CRM (`tblitems` + `tblitems_groups`)
|
||||||
|
|
||||||
|
651 itens em 14 grupos. Consultar SEMPRE o CRM para preços actualizados.
|
||||||
|
|
||||||
|
## Sintaxe
|
||||||
|
|
||||||
|
```
|
||||||
|
/orcamento [cliente] [tipo] [-MEN|-TRI]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Código | Tipo | Grupo CRM |
|
||||||
|
|--------|------|-----------|
|
||||||
|
| `starter` | StarterWP | Websites |
|
||||||
|
| `corporate` | CorporateWP | Websites |
|
||||||
|
| `care` | CareWP | Websites |
|
||||||
|
| `ecom` | eCommerceWP | Websites |
|
||||||
|
| `mkt` | Marketing 360 | Marketing |
|
||||||
|
| `man` | Manutenção | Suporte |
|
||||||
|
| `deskcrm` | DeskCRM | DeskCRM |
|
||||||
|
| `chatbot` | Chatbot | Chatbots |
|
||||||
|
| `acceleratorx` | AcceleratorX | Tecnologia |
|
||||||
|
|
||||||
|
## Variantes de facturação
|
||||||
|
|
||||||
|
| Flag | Unit | Pesquisa CRM |
|
||||||
|
|------|------|-------------|
|
||||||
|
| (nenhum) | ano | Item base |
|
||||||
|
| `-MEN` | mensalidade | `WHERE description LIKE 'Mensalidade%...'` |
|
||||||
|
| `-TRI` | trimestral | `WHERE description LIKE 'Trimestral%...'` |
|
||||||
|
|
||||||
|
Preços das variantes são definidos no CRM (podem incluir markup). Nunca calcular por divisão simples.
|
||||||
|
|
||||||
|
## Protocolo
|
||||||
|
|
||||||
|
### 1. Identificar cliente
|
||||||
|
|
||||||
|
```
|
||||||
|
mcp__desk-crm-v3__search_customers query="[nome]" fields="company,vat"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Consultar preços
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Itens base (setup/pontuais)
|
||||||
|
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;"
|
||||||
|
|
||||||
|
# Itens recorrentes (com variante)
|
||||||
|
mysql -u root ealmeida_desk24 -e "
|
||||||
|
SELECT description, rate, unit FROM tblitems
|
||||||
|
WHERE group_id = [GROUP_ID]
|
||||||
|
AND description LIKE '[Mensalidade|Trimestral]%[PACOTE]%'
|
||||||
|
ORDER BY description;"
|
||||||
|
```
|
||||||
|
|
||||||
|
Ou via MCP:
|
||||||
|
```
|
||||||
|
mcp__desk-crm-v3__price_management action="get_pricing_insights" params={"group": "[GRUPO]"}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Criar estimate
|
||||||
|
|
||||||
|
```
|
||||||
|
mcp__desk-crm-v3__create_estimate
|
||||||
|
client_id=[id]
|
||||||
|
date=[hoje]
|
||||||
|
expiry_date=[hoje + 30 dias]
|
||||||
|
items=[{description, qty, rate, unit}]
|
||||||
|
terms="[termos]"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Formato item:** `{"description": "...", "qty": 1, "rate": 700, "unit": "un"}`
|
||||||
|
|
||||||
|
**Unidades:** `un` (pontual), `mensalidade` (-MEN), `trimestral` (-TRI), `anuidade` (defeito)
|
||||||
|
|
||||||
|
### 4. Termos por variante
|
||||||
|
|
||||||
|
- **Sem flag:** "50% na adjudicação + 50% na entrega"
|
||||||
|
- **-MEN:** "Setup: 50%+50% | Recorrência: facturação mensal antecipada"
|
||||||
|
- **-TRI:** "Setup: 50%+50% | Recorrência: facturação trimestral antecipada"
|
||||||
|
|
||||||
|
## Preços de referência (consultar CRM para valores reais)
|
||||||
|
|
||||||
|
### Websites
|
||||||
|
|
||||||
|
| Produto | Setup | Anuidade |
|
||||||
|
|---------|-------|----------|
|
||||||
|
| StarterWP | 700 | 250 |
|
||||||
|
| CorporateWP | 900 | 299 |
|
||||||
|
| eCommerceWP | 1100 | 349 |
|
||||||
|
| CareWP | 1300 | 350 |
|
||||||
|
|
||||||
|
### DeskCRM
|
||||||
|
|
||||||
|
| Produto | Anuidade |
|
||||||
|
|---------|----------|
|
||||||
|
| Starter | 400 |
|
||||||
|
| Profissional | 800 |
|
||||||
|
| Avançado | 1500 |
|
||||||
|
| Enterprise | 3000 |
|
||||||
|
|
||||||
|
### AcceleratorX
|
||||||
|
|
||||||
|
| Produto | Setup |
|
||||||
|
|---------|-------|
|
||||||
|
| WP ProCMS | 650 |
|
||||||
|
| e-Commerce | 750 |
|
||||||
|
| Care | 750 |
|
||||||
|
| School Manager | 850 |
|
||||||
|
|
||||||
|
### Chatbots
|
||||||
|
|
||||||
|
| Produto | Setup |
|
||||||
|
|---------|-------|
|
||||||
|
| Básico | 350 |
|
||||||
|
| Avançado | 850 |
|
||||||
|
|
||||||
|
## Checklist
|
||||||
|
|
||||||
|
- [ ] Cliente identificado/criado no CRM
|
||||||
|
- [ ] Tipo seleccionado
|
||||||
|
- [ ] Preços consultados no CRM
|
||||||
|
- [ ] Valores calculados (subtotal + IVA 23%)
|
||||||
|
- [ ] Recorrência calculada
|
||||||
|
- [ ] Estimate criado (status: Draft)
|
||||||
|
- [ ] Resumo apresentado
|
||||||
|
|
||||||
|
## MCPs
|
||||||
|
|
||||||
|
```
|
||||||
|
mcp__desk-crm-v3__search_customers
|
||||||
|
mcp__desk-crm-v3__create_customer
|
||||||
|
mcp__desk-crm-v3__create_estimate
|
||||||
|
mcp__desk-crm-v3__price_management
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
**Versão**: 4.1.0-light | **Base**: 4.1.0
|
||||||
@@ -512,3 +512,15 @@ INSERT INTO tblskill_agent_metrics (
|
|||||||
---
|
---
|
||||||
|
|
||||||
**Versao**: 4.1.0 | **Data**: 2026-03-12 | **Fonte de Verdade**: Desk CRM (tblitems)
|
**Versao**: 4.1.0 | **Data**: 2026-03-12 | **Fonte de Verdade**: Desk CRM (tblitems)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -365,3 +365,52 @@ mcp__mcp-time__current_time - Data/hora actual
|
|||||||
---
|
---
|
||||||
|
|
||||||
**Versao**: 1.0.0 | **Data**: 2026-03-06 | **Template**: descomplicar-proposal-template.pptx
|
**Versao**: 1.0.0 | **Data**: 2026-03-06 | **Template**: descomplicar-proposal-template.pptx
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Media Bank (D7-MB-001)
|
||||||
|
|
||||||
|
**Quando consultar:** antes de gerar o deck da proposta — para hero da capa, backgrounds de slides de secção e imagens ilustrativas. Garante consistência visual e evita dependência de geração IA por cada proposta.
|
||||||
|
|
||||||
|
**Workflow tentativa-primeiro:**
|
||||||
|
|
||||||
|
1. Pesquisar via MCP `media-bank`:
|
||||||
|
```
|
||||||
|
mcp__media-bank__search_media(
|
||||||
|
query="<sector/serviço do cliente em EN>",
|
||||||
|
type="image",
|
||||||
|
tema="<um dos 9 temas alinhado com serviço>",
|
||||||
|
orientation="landscape",
|
||||||
|
min_quality=8, # exigência mais alta para propostas
|
||||||
|
min_width=1920,
|
||||||
|
exclude_used_in_last_days=60,
|
||||||
|
limit=5
|
||||||
|
)
|
||||||
|
```
|
||||||
|
2. Avaliar candidatos por `description_en` + `quality_score` + alinhamento com identidade visual Descomplicar.
|
||||||
|
3. Se ≥1 adequado → usar `path_local` directamente no PPTX (slide master / capa) ou compor no template.
|
||||||
|
4. Se nenhum → fallback para geração IA (Flux) ou biblioteca de stock interna.
|
||||||
|
5. Marcar uso: `mcp__media-bank__mark_used(asset_id, {type:"proposal-deck", ref:"<cliente>-<data>", date:"<YYYY-MM-DD>"})`.
|
||||||
|
|
||||||
|
**Fallback REST** (se MCP indisponível):
|
||||||
|
```bash
|
||||||
|
SK=$(grep SERVICE_KEY /media/ealmeida/Dados/Hub/05-Projectos/Banco-Imagens-Videos/scripts/.env | cut -d= -f2)
|
||||||
|
curl -s "https://mem.descomplicar.pt/rest/v1/media_bank_assets?type=eq.image&orientation=eq.landscape&quality_score=gte.8&deleted_at=is.null&order=quality_score.desc&limit=5" \
|
||||||
|
-H "apikey: $SK" -H "Authorization: Bearer $SK"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Regra inviolável:** matéria-prima local. Usar como input no template PPTX — NUNCA servir o ficheiro raw ao cliente sem integração no deck (overlays, branding, layout).
|
||||||
|
|
||||||
|
Ver `Hub/06-Operacoes/Procedimentos/D7-Tecnologia/MCP/PROC-Media-Bank.md` (D7-MB-001) para detalhes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -0,0 +1,386 @@
|
|||||||
|
---
|
||||||
|
name: proposta-visual
|
||||||
|
description: Criação completa de propostas comerciais visuais — página web (propostas.descomplicar.pt) + PDF exportável + PPTX editável. Recolhe dados CRM, gera JSON, renderiza condicionalmente e faz deploy.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Skill /proposta-visual — Propostas Comerciais Visuais
|
||||||
|
|
||||||
|
Cria propostas comerciais profissionais com 3 outputs: página web interactiva, PDF exportável e PPTX editável.
|
||||||
|
|
||||||
|
## Triggers
|
||||||
|
|
||||||
|
- `/proposta-visual`
|
||||||
|
- "proposta visual", "proposta web", "criar proposta", "nova proposta", "proposta para [cliente]"
|
||||||
|
|
||||||
|
## Quando usar
|
||||||
|
|
||||||
|
- Criar proposta comercial completa para um cliente
|
||||||
|
- Gerar página web + PDF + PPTX de uma proposta
|
||||||
|
- Actualizar proposta existente com novos dados
|
||||||
|
|
||||||
|
## Quando NÃO usar
|
||||||
|
|
||||||
|
- Apenas orçamento sem visual (usar `/orcamento`)
|
||||||
|
- Apenas PPTX sem página web (usar `/proposal-deck`)
|
||||||
|
- Análise de lead sem proposta (usar `/lead-approach`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Projecto base
|
||||||
|
|
||||||
|
| Campo | Valor |
|
||||||
|
|-------|-------|
|
||||||
|
| **Código fonte** | `/media/ealmeida/Dados/Dev/Propostas/` |
|
||||||
|
| **Stack** | React 18 + Vite + Tailwind + @react-pdf/renderer + Recharts + Framer Motion + Lucide React |
|
||||||
|
| **Live** | `propostas.descomplicar.pt/{slug}` |
|
||||||
|
| **Deploy** | Docker Swarm EasyPanel, serviço `descomplicar_propostas`, ficheiros `/opt/propostas/` |
|
||||||
|
| **DNS** | `propostas.descomplicar.pt` → 5.9.90.70 (Cloudflare proxied) |
|
||||||
|
| **Template PPTX** | `/media/ealmeida/Dados/Hub/90-Templates/Comercial/descomplicar-proposal-template.pptx` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## REGRAS CRÍTICAS (ler antes de qualquer implementação)
|
||||||
|
|
||||||
|
### 1. PT-PT obrigatório — acentos em TODO o texto
|
||||||
|
|
||||||
|
Todos os textos no JSON, componentes web e componentes PDF DEVEM ter acentos PT-PT correctos:
|
||||||
|
- ✓ migração, tradução, integração, opções, condições, execução, acção
|
||||||
|
- ✗ migracao, traducao, integracao, opcoes, condicoes, execucao, accao
|
||||||
|
|
||||||
|
**Verificar no PDF:** labels hardcoded em `PDFWorkDone.jsx` e `PDFDocument.jsx` — já corrigidos mas confirmar sempre.
|
||||||
|
|
||||||
|
### 2. JSON data-driven — renderização condicional obrigatória
|
||||||
|
|
||||||
|
O `ProposalView.jsx` e o `PDFDocument.jsx` renderizam secções **condicionalmente** com base nos dados. Se um campo é `null`, `[]` ou não existe, a secção NÃO aparece.
|
||||||
|
|
||||||
|
**Regra:** NUNCA assumir que todos os campos existem. Cada proposta pode ter um subconjunto diferente de secções.
|
||||||
|
|
||||||
|
| Campo JSON | Secção web | Secção PDF | Condição |
|
||||||
|
|-----------|-----------|-----------|----------|
|
||||||
|
| `context.brandStrategy` | BrandStrategy | PageBrandStrategy | `!= null` |
|
||||||
|
| `salesData` | SalesChart | PageSales | `.length > 0` |
|
||||||
|
| `context.diagnosis` | Context | — | `.length > 0` |
|
||||||
|
| `context.scores` | ScoreGrid | PDFScores | `.length > 0` |
|
||||||
|
| `service360` | Service360 | PageService360 | `!= null` |
|
||||||
|
| `plans` | PricingCards | PDFPricing | `.length > 0` |
|
||||||
|
| `licenses` | LicensePack | PageLicenses | `!= null` |
|
||||||
|
| `workDone` | WorkDone | PDFWorkDone | `.length > 0` |
|
||||||
|
| `roadmap` | Roadmap | PDFWorkDone | `.length > 0` |
|
||||||
|
| `conditions` | Conditions | PDFWorkDone (pág. separada) | `.length > 0` |
|
||||||
|
|
||||||
|
### 3. Título dinâmico — campo `title` no JSON
|
||||||
|
|
||||||
|
O título da proposta (Hero web + capa PDF) vem do campo `title` no JSON:
|
||||||
|
- Proposta 360°: `"title": "Descomplicar 360°"`
|
||||||
|
- Migração técnica: `"title": "Migração Bookeo"`
|
||||||
|
- Website: `"title": "Website Profissional"`
|
||||||
|
- Fallback: `"Proposta Comercial"`
|
||||||
|
|
||||||
|
**NUNCA** hardcodar "Descomplicar 360°" — usar `data.title`.
|
||||||
|
|
||||||
|
### 4. Preços flexíveis — não assumir mensalidades
|
||||||
|
|
||||||
|
Os planos suportam dois formatos de preço:
|
||||||
|
|
||||||
|
**Mensalidade (avença):**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"monthly": 459,
|
||||||
|
"hours": 8,
|
||||||
|
"originalPrice": 540,
|
||||||
|
"discount": 15
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Mostra: "459 €/mês" + "8h/mês incluídas · contrato anual"
|
||||||
|
|
||||||
|
**Preço único (investimento):**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"price": 750,
|
||||||
|
"priceLabel": "EUR + IVA",
|
||||||
|
"priceSubtitle": "Investimento único · prazo 1-2 semanas",
|
||||||
|
"monthly": null,
|
||||||
|
"hours": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Mostra: "750 EUR + IVA" + "Investimento único · prazo 1-2 semanas"
|
||||||
|
|
||||||
|
**Campos usados:** `plan.price ?? plan.monthly` para o valor, `plan.priceLabel ?? "€/mês"` para a unidade, `plan.priceSubtitle` para a descrição abaixo.
|
||||||
|
|
||||||
|
### 5. react-pdf — bugs conhecidos e PROIBIÇÕES
|
||||||
|
|
||||||
|
| Proibição | Porquê | Alternativa |
|
||||||
|
|-----------|--------|-------------|
|
||||||
|
| `gap` + `flexWrap` juntos | Crasha silenciosamente | `marginRight` + `marginBottom` nos items |
|
||||||
|
| `borderColor` com `rgba()` | Renderiza verde | Cor sólida (ex: `#D4A020`, `#E8E8E8`) |
|
||||||
|
| Import de componentes SVG (`<Svg>`, `<Circle>`) | Crasha web worker do PDFDownloadLink | Implementar gráficos inline com `<View>` |
|
||||||
|
| `Font.register` com fontes locais/CDN em multi-página | Falha silenciosa | Usar Helvetica/Helvetica-Bold (built-in) |
|
||||||
|
| `href` vazio no PDFDownloadLink | PDF não gerou — verificar consola | Cache do browser — Ctrl+Shift+R |
|
||||||
|
|
||||||
|
### 6. Página 360° (service360) — contextualizar
|
||||||
|
|
||||||
|
A secção service360 no PDF usa o label "O QUE PROPOMOS" (genérico) e o título "As nossas soluções para o seu negócio". Os dados vêm do JSON `service360.areas[]`.
|
||||||
|
|
||||||
|
Para propostas que NÃO são 360°, adaptar os `areas` ao contexto:
|
||||||
|
- Migração técnica: features da migração
|
||||||
|
- Website: áreas do serviço web
|
||||||
|
- SEO: pilares do trabalho SEO
|
||||||
|
|
||||||
|
Se `service360` for `null`, a secção não aparece.
|
||||||
|
|
||||||
|
### 7. Condições comerciais — página separada no PDF
|
||||||
|
|
||||||
|
As condições estão numa página PDF separada (não na mesma que o roadmap) para evitar corte entre páginas. O componente `PDFWorkDone` retorna um Fragment com 2 Pages.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Protocolo
|
||||||
|
|
||||||
|
### Sintaxe
|
||||||
|
|
||||||
|
```
|
||||||
|
/proposta-visual [cliente] [tipo-serviço]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fase 1: Análise do contexto
|
||||||
|
|
||||||
|
**ANTES de criar o JSON, responder a estas perguntas:**
|
||||||
|
|
||||||
|
1. **Que tipo de proposta é?** (360°, website, migração técnica, SEO, eCommerce, outro)
|
||||||
|
2. **O preço é mensal ou único?** → define `monthly` vs `price`/`priceLabel`/`priceSubtitle`
|
||||||
|
3. **Que secções se aplicam?** → define que campos preencher no JSON
|
||||||
|
4. **Há dados quantitativos?** (vendas, scores SEO, KPIs) → define `salesData`, `context.scores`
|
||||||
|
5. **Há trabalho já realizado?** → define `workDone`
|
||||||
|
6. **Quantas opções de preço?** → define `plans[]`
|
||||||
|
|
||||||
|
**Mapa de secções por tipo de proposta:**
|
||||||
|
|
||||||
|
| Secção | 360° | Website | Migração | SEO | eCommerce |
|
||||||
|
|--------|:----:|:-------:|:--------:|:---:|:---------:|
|
||||||
|
| `title` | Descomplicar 360° | Website Profissional | [contexto] | Optimização SEO | Loja Online |
|
||||||
|
| `brandStrategy` | ✓ | Opcional | — | — | Opcional |
|
||||||
|
| `salesData` | Se existir | — | — | — | Se existir |
|
||||||
|
| `scores` | ✓ (audit) | Opcional | — | ✓ (audit) | Opcional |
|
||||||
|
| `service360` | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||||
|
| `plans` | ✓ (3 opções) | ✓ | ✓ | ✓ | ✓ |
|
||||||
|
| `licenses` | Se aplicável | — | — | — | Se aplicável |
|
||||||
|
| `workDone` | Se existir | Se existir | ✓ | Se existir | Se existir |
|
||||||
|
| `roadmap` | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||||
|
| `conditions` | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||||
|
|
||||||
|
### Fase 2: Recolha de dados do CRM
|
||||||
|
|
||||||
|
```
|
||||||
|
mcp__desk-crm-v3__search_customers query="[nome]"
|
||||||
|
mcp__desk-crm-v3__get_customer customer_id=[id]
|
||||||
|
mcp__desk-crm-v3__get_estimates client_id=[id]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fase 3: Criar ficheiro JSON
|
||||||
|
|
||||||
|
**Localização:** `src/data/[slug].json`
|
||||||
|
|
||||||
|
**Gerar slug:** iniciais do cliente + tipo + hash curto. Ex: `ccv-bookeo-a3f7c1d2`
|
||||||
|
|
||||||
|
**Schema mínimo obrigatório:**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"title": "Título da Proposta",
|
||||||
|
"client": {
|
||||||
|
"name": "Nome Legal Lda.",
|
||||||
|
"brand": "Nome Comercial",
|
||||||
|
"website": "exemplo.pt",
|
||||||
|
"contact": "Nome Contacto",
|
||||||
|
"email": "email@exemplo.pt",
|
||||||
|
"phone": "+351 900 000 000"
|
||||||
|
},
|
||||||
|
"company": {
|
||||||
|
"name": "Descomplicar, Lda.",
|
||||||
|
"brand": "Descomplicar",
|
||||||
|
"nif": "514 785 691",
|
||||||
|
"email": "info@descomplicar.pt",
|
||||||
|
"phone": "911 510 005",
|
||||||
|
"website": "descomplicar.pt"
|
||||||
|
},
|
||||||
|
"date": "2026-03-23",
|
||||||
|
"validDays": 30,
|
||||||
|
"context": {
|
||||||
|
"description": "Descrição da situação...",
|
||||||
|
"diagnosis": [],
|
||||||
|
"scores": [],
|
||||||
|
"brandStrategy": null
|
||||||
|
},
|
||||||
|
"service360": null,
|
||||||
|
"plans": [],
|
||||||
|
"licenses": null,
|
||||||
|
"workDone": [],
|
||||||
|
"roadmap": [],
|
||||||
|
"conditions": [],
|
||||||
|
"salesData": [],
|
||||||
|
"salesProjection": []
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Campos opcionais para planos com preço único:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"price": 750,
|
||||||
|
"priceLabel": "EUR + IVA",
|
||||||
|
"priceSubtitle": "Investimento único · prazo 1-2 semanas",
|
||||||
|
"monthly": null,
|
||||||
|
"hours": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Checklist PT-PT antes de guardar o JSON:**
|
||||||
|
- [ ] Todos os textos têm acentos correctos (ã, ç, ã, é, ê, í, ó, õ, ú)
|
||||||
|
- [ ] Zero brasileirismos
|
||||||
|
- [ ] Caractere → (seta) em vez de -> nos textos visíveis
|
||||||
|
- [ ] Monetário: "EUR" ou "€" (não "R$" nem "$")
|
||||||
|
|
||||||
|
### Fase 4: Registar no App.jsx
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
import novaData from "./data/[slug].json"
|
||||||
|
|
||||||
|
const proposals = {
|
||||||
|
// existentes...
|
||||||
|
"[novo-slug]": novaData,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fase 5: Verificar antes do build
|
||||||
|
|
||||||
|
**Checklist pré-build:**
|
||||||
|
- [ ] JSON válido (sem trailing commas, sem campos undefined)
|
||||||
|
- [ ] Campos null/[] para secções que não se aplicam (NÃO omitir)
|
||||||
|
- [ ] `title` definido (não depender do fallback)
|
||||||
|
- [ ] `plans[].price` OU `plans[].monthly` definido (não ambos null)
|
||||||
|
- [ ] `plans[].priceLabel` definido se preço único
|
||||||
|
- [ ] Slug registado em App.jsx
|
||||||
|
- [ ] Nenhum `flexWrap` + `gap` nos componentes PDF
|
||||||
|
- [ ] Nenhum `borderColor` com `rgba()` nos componentes PDF
|
||||||
|
|
||||||
|
### Fase 6: Build e deploy
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /media/ealmeida/Dados/Dev/Propostas
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# Limpar dist
|
||||||
|
cd dist
|
||||||
|
rm -rf assets/template-media assets/template-referencia.pptx assets/slide-referencia.svg
|
||||||
|
cd assets/brochura && ls *.{jpg,png} 2>/dev/null | grep -v image8.jpg | xargs rm -f 2>/dev/null
|
||||||
|
|
||||||
|
# Empacotar
|
||||||
|
cd /media/ealmeida/Dados/Dev/Propostas/dist
|
||||||
|
tar czf /tmp/propostas-dist.tar.gz .
|
||||||
|
|
||||||
|
# Upload + deploy
|
||||||
|
mcp__ssh-unified__sftp_upload server=easy localPath=/tmp/propostas-dist.tar.gz remotePath=/tmp/propostas-dist.tar.gz overwrite=true
|
||||||
|
mcp__ssh-unified__ssh_execute server=easy command="cd /opt/propostas && rm -rf assets/* index.html; tar xzf /tmp/propostas-dist.tar.gz && docker service update --force descomplicar_propostas && rm -f /tmp/propostas-dist.tar.gz"
|
||||||
|
|
||||||
|
# Verificar
|
||||||
|
curl -sI https://propostas.descomplicar.pt/[slug] | head -3
|
||||||
|
# Deve retornar HTTP/2 200
|
||||||
|
|
||||||
|
# Limpar
|
||||||
|
rm -f /tmp/propostas-dist.tar.gz
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fase 7: Testar PDF
|
||||||
|
|
||||||
|
**OBRIGATÓRIO antes de entregar:**
|
||||||
|
1. Abrir `https://propostas.descomplicar.pt/[slug]` com Ctrl+Shift+R
|
||||||
|
2. Clicar "Exportar PDF"
|
||||||
|
3. Verificar que `href` do link não está vazio (PDF gerou)
|
||||||
|
4. Abrir PDF e verificar:
|
||||||
|
- [ ] Título correcto (não "Descomplicar 360°" hardcoded)
|
||||||
|
- [ ] Preços correctos (não "€/mês" se é preço único)
|
||||||
|
- [ ] Sem borders verdes (rgba renderiza verde no react-pdf)
|
||||||
|
- [ ] Sem secções que não se aplicam (360°, vendas, licenças, scores)
|
||||||
|
- [ ] Acentos PT-PT em todo o texto
|
||||||
|
- [ ] Condições comerciais numa página inteira (sem corte)
|
||||||
|
- [ ] Todas as 3 opções de preço com layout uniforme
|
||||||
|
|
||||||
|
**Se o PDF não gera (href vazio):**
|
||||||
|
1. Verificar consola do browser (F12)
|
||||||
|
2. Causa mais provável: import de componente SVG dos infographics
|
||||||
|
3. Verificar que PDFDocument não importa de `./infographics/`
|
||||||
|
4. Verificar que não há `gap` + `flexWrap` no PDF
|
||||||
|
5. Ctrl+Shift+R e tentar novamente (cache)
|
||||||
|
|
||||||
|
### Fase 8: Entrega e registo
|
||||||
|
|
||||||
|
1. Guardar em `Hub/03-Propostas/[Cliente]/`
|
||||||
|
2. Registar estimate no CRM (se não existe)
|
||||||
|
3. Comunicar URL ao utilizador
|
||||||
|
4. Comentar tarefa CRM
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Design system ACIDA 2.0
|
||||||
|
|
||||||
|
| Token | Valor |
|
||||||
|
|-------|-------|
|
||||||
|
| Dourado | #C88900 |
|
||||||
|
| Dourado claro | #EED59F |
|
||||||
|
| Dourado border PDF | #D4A020 (usar em vez de rgba no PDF) |
|
||||||
|
| Dark | #262626 |
|
||||||
|
| Background | #F8F8F8 |
|
||||||
|
| Fonte web | Inter (Google Fonts) |
|
||||||
|
| Fonte PDF | Helvetica / Helvetica-Bold |
|
||||||
|
| Logo escuro | `/assets/logo-descomplicar.png` |
|
||||||
|
| Logo claro | `/assets/logo-descomplicar-white.png` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Propostas existentes
|
||||||
|
|
||||||
|
| Slug | Cliente | Tipo | Data |
|
||||||
|
|------|---------|------|------|
|
||||||
|
| `ljm-360-61a8aecc` | A Loja da Maria | 360° (mensal) | 2026-03-20 |
|
||||||
|
| `ccv-bookeo-a3f7c1d2` | Carvoeiro Caves | Migração técnica (único) | 2026-03-23 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Skills relacionadas
|
||||||
|
|
||||||
|
- `/proposal-deck` — PPTX standalone (16 layouts, XML editing)
|
||||||
|
- `/orcamento` — Estimate no CRM (sem visual)
|
||||||
|
- `/lead-approach` — Estratégia de abordagem de lead
|
||||||
|
- `/crm` — Operações CRM genéricas
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Changelog
|
||||||
|
|
||||||
|
### v2.0.0 (2026-03-23)
|
||||||
|
- Regras críticas documentadas (7 regras)
|
||||||
|
- Renderização condicional obrigatória (ProposalView + PDFDocument)
|
||||||
|
- Título dinâmico via campo `title` no JSON
|
||||||
|
- Preços flexíveis (mensal vs único) com `price`/`priceLabel`/`priceSubtitle`
|
||||||
|
- Bugs react-pdf documentados com proibições explícitas
|
||||||
|
- Mapa de secções por tipo de proposta
|
||||||
|
- Checklist pré-build e teste PDF obrigatório
|
||||||
|
- Condições comerciais em página PDF separada
|
||||||
|
|
||||||
|
### v1.0.0 (2026-03-23)
|
||||||
|
- Versão inicial
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Versão:** 2.0.0 | **Data:** 2026-03-23
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
@@ -0,0 +1,319 @@
|
|||||||
|
---
|
||||||
|
name: ticket-manage
|
||||||
|
description: >
|
||||||
|
Gestão completa do ciclo de vida de tickets D2 Suporte: criar com campos correctos, atribuir
|
||||||
|
por prioridade e SLA, escalar quando SLA em risco, fechar com checklist obrigatória. Baseado
|
||||||
|
em PROC-D2-SUP-001 (Atendimento), SUP-002 (Ticketing Workflow) e SUP-003 (SLA Management).
|
||||||
|
Usar para: gestão ticket, SLA check, escalar suporte, fechar ticket, atribuir prioridade.
|
||||||
|
disable-model-invocation: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# /ticket-manage v1.0 — Gestão Integrada de Suporte D2
|
||||||
|
|
||||||
|
Workflow completo de gestão de tickets segundo os PROCs D2 Suporte (SUP-001/002/003).
|
||||||
|
Complementa `/ticket` (operações básicas) com gestão de SLA, checklist e escalação automática.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Comandos
|
||||||
|
|
||||||
|
| Comando | Função |
|
||||||
|
|---------|--------|
|
||||||
|
| `/ticket-manage` | Dashboard SLA + tickets em risco |
|
||||||
|
| `/ticket-manage new` | Criar ticket com campos correctos |
|
||||||
|
| `/ticket-manage assign <id>` | Atribuir por prioridade e SLA |
|
||||||
|
| `/ticket-manage sla` | Ver estado SLA todos os tickets abertos |
|
||||||
|
| `/ticket-manage escalate <id>` | Escalar com protocolo SUP-001 |
|
||||||
|
| `/ticket-manage close <id>` | Fechar com checklist obrigatória |
|
||||||
|
| `/ticket-manage report` | Relatório semanal SLA (SUP-003) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prioridades e SLAs (SUP-003)
|
||||||
|
|
||||||
|
| Prioridade | Código | Primeira Resposta | Resolução | Escalação |
|
||||||
|
|------------|--------|-------------------|-----------|-----------|
|
||||||
|
| Crítico | P1 | <1h | <4h | Imediata D7 |
|
||||||
|
| Funcional | P2 | <2h | <24h | Após 12h sem resolução |
|
||||||
|
| Dúvida | P3 | <4h | <48h | Após 24h sem resolução |
|
||||||
|
| Melhoria | P4 | <24h | Próximo sprint | N/A |
|
||||||
|
|
||||||
|
**Mapping Desk CRM:**
|
||||||
|
| Desk Priority ID | Correspondência |
|
||||||
|
|-----------------|----------------|
|
||||||
|
| 4 — Urgente | P1 Crítico |
|
||||||
|
| 3 — Alta | P2 Funcional |
|
||||||
|
| 2 — Normal | P3 Dúvida |
|
||||||
|
| 1 — Baixa | P4 Melhoria |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `/ticket-manage` — Dashboard SLA
|
||||||
|
|
||||||
|
```
|
||||||
|
1. mcp__desk-crm-v3__get_tickets({ status: [1,2,3] })
|
||||||
|
2. Para cada ticket:
|
||||||
|
a. Calcular tempo decorrido desde criação/última resposta
|
||||||
|
b. Comparar com SLA da prioridade
|
||||||
|
c. Classificar: OK / EM RISCO (<25% SLA restante) / VIOLADO (SLA excedido)
|
||||||
|
3. Mostrar dashboard agrupado por estado SLA
|
||||||
|
```
|
||||||
|
|
||||||
|
**Output:**
|
||||||
|
```markdown
|
||||||
|
## 🎫 Dashboard Suporte — [DATA]
|
||||||
|
|
||||||
|
### 🔴 SLA Violado (N)
|
||||||
|
| # | Prioridade | Cliente | Assunto | Há | SLA |
|
||||||
|
|---|-----------|---------|---------|-----|-----|
|
||||||
|
| #234 | P1 Crítico | ClienteA | Downtime servidor | 6h | <4h ❌ |
|
||||||
|
|
||||||
|
### 🟠 Em Risco (<25% restante)
|
||||||
|
| # | Prioridade | Cliente | Assunto | Há | Restante |
|
||||||
|
|---|-----------|---------|---------|-----|---------|
|
||||||
|
| #236 | P2 Funcional | ClienteB | Erro login | 20h | 4h ⚠️ |
|
||||||
|
|
||||||
|
### 🟢 Dentro do SLA
|
||||||
|
| # | Prioridade | Cliente | Assunto | Há |
|
||||||
|
|---|-----------|---------|---------|-----|
|
||||||
|
| #238 | P3 Dúvida | ClienteC | Como configurar X | 2h |
|
||||||
|
|
||||||
|
---
|
||||||
|
**Resumo:** X violados | Y em risco | Z OK | Total: W tickets abertos
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `/ticket-manage new` — Criar Ticket Correcto
|
||||||
|
|
||||||
|
```
|
||||||
|
1. Recolher campos obrigatórios:
|
||||||
|
- Cliente: pesquisar mcp__desk-crm-v3__get_customers({ search: nome }) OU perguntar ID
|
||||||
|
- Assunto: descrever o problema
|
||||||
|
- Descrição completa
|
||||||
|
- Prioridade: perguntar (P1/P2/P3/P4) ou sugerir baseado no assunto
|
||||||
|
- Departamento: 1=Suporte Técnico, 2=Vendas, 3=Facturação, 4=Geral
|
||||||
|
- Origem: Desk CRM, email, WhatsApp
|
||||||
|
|
||||||
|
2. Confirmar antes de criar:
|
||||||
|
"Criar ticket P[X] para [Cliente] — [Assunto]? [Sim/Cancelar]"
|
||||||
|
|
||||||
|
3. mcp__desk-crm-v3__create_ticket({
|
||||||
|
client_id: id,
|
||||||
|
department_id: dept_id,
|
||||||
|
priority: priority_id, // 4=Urgente, 3=Alta, 2=Normal, 1=Baixa
|
||||||
|
subject: assunto,
|
||||||
|
message: "<p>[descrição detalhada]</p><p><strong>Origem:</strong> [origem]</p>"
|
||||||
|
})
|
||||||
|
|
||||||
|
4. Enviar confirmação de recepção ao cliente (se externo):
|
||||||
|
- P1/P2: "Prioridade máxima. Analisando agora. Actualização em 30min/2h."
|
||||||
|
- P3: "Recebemos. Resposta em 4h."
|
||||||
|
- P4: "Registado para próximo sprint."
|
||||||
|
|
||||||
|
5. Output: "Ticket #X criado [P1-Crítico] | SLA: 1h resposta / 4h resolução"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `/ticket-manage assign <id>` — Atribuir por Prioridade
|
||||||
|
|
||||||
|
```
|
||||||
|
1. mcp__desk-crm-v3__get_ticket({ ticket_id: id })
|
||||||
|
2. Determinar responsável baseado em categoria:
|
||||||
|
- Técnico (WP, servidor, código) → D7 Tecnologia
|
||||||
|
- Billing, factura → D3 / Emanuel
|
||||||
|
- Comercial, proposta → D1
|
||||||
|
- Geral → Support Specialist (staff_id: 25)
|
||||||
|
3. Se P1: notificar imediatamente (comentário interno + /task urgente)
|
||||||
|
4. Registar atribuição como comentário interno:
|
||||||
|
mcp__desk-crm-v3__reply_ticket({
|
||||||
|
ticket_id: id,
|
||||||
|
message: "<p>Atribuído: [Responsável] | SLA: [prazo] | Prioridade: [P1-P4]</p>",
|
||||||
|
internal: true
|
||||||
|
})
|
||||||
|
5. Output: "Ticket #X atribuído a [Responsável] | SLA expira: [data/hora]"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `/ticket-manage sla` — Estado SLA Completo
|
||||||
|
|
||||||
|
```
|
||||||
|
1. Recolher todos tickets abertos (status 1, 2, 3)
|
||||||
|
2. Para cada ticket calcular:
|
||||||
|
- tempo_decorrido = agora - created_at
|
||||||
|
- sla_limite = por prioridade (1h/2h/4h/24h para primeira resposta)
|
||||||
|
- percentagem_usada = tempo_decorrido / sla_limite × 100
|
||||||
|
3. Agrupar: VIOLADO (>100%), EM RISCO (75-100%), OK (<75%)
|
||||||
|
4. Highlight P1 e P2 com aviso especial
|
||||||
|
```
|
||||||
|
|
||||||
|
**Alertas automáticos a gerar:**
|
||||||
|
```
|
||||||
|
P1 sem resposta >30min → "⚠️ CRÍTICO: Ticket #X P1 excede 30min. Acção imediata."
|
||||||
|
P2 sem resposta >2h → "⚠️ ALERTA: Ticket #X P2 em risco. Re-atribuir?"
|
||||||
|
Qualquer ticket >48h → "⏰ Ticket #X aberto há +48h. Revisar."
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `/ticket-manage escalate <id>` — Escalação com Protocolo
|
||||||
|
|
||||||
|
```
|
||||||
|
1. mcp__desk-crm-v3__get_ticket({ ticket_id: id })
|
||||||
|
2. Determinar destino de escalação:
|
||||||
|
- Tech complexo (WP, servidor) → D7 Tecnologia
|
||||||
|
- Billing → D3 Facturação
|
||||||
|
- Dev customizado → Project Manager
|
||||||
|
3. Criar tarefa Desk CRM com contexto completo:
|
||||||
|
mcp__desk-crm-v3__create_task({
|
||||||
|
name: "[ESCALADO] Ticket #X: [Assunto]",
|
||||||
|
description: "<h4>Escalado de Ticket #X</h4>
|
||||||
|
<p><strong>Cliente:</strong> [nome]</p>
|
||||||
|
<p><strong>Problema:</strong> [descrição]</p>
|
||||||
|
<p><strong>Tentativas anteriores:</strong> [o que foi tentado]</p>
|
||||||
|
<p><strong>SLA original:</strong> [prazo]</p>
|
||||||
|
<p><strong>Motivo escalação:</strong> [razão]</p>",
|
||||||
|
priority: 3,
|
||||||
|
assignees: [1]
|
||||||
|
})
|
||||||
|
4. Informar cliente:
|
||||||
|
mcp__desk-crm-v3__reply_ticket({
|
||||||
|
ticket_id: id,
|
||||||
|
message: "<p>Olá [Nome],</p>
|
||||||
|
<p>A situação é mais complexa e foi escalada para a equipa especialista.
|
||||||
|
Prazo estimado: 24-48h.</p>
|
||||||
|
<p>Pedimos desculpa pela demora.</p>"
|
||||||
|
})
|
||||||
|
5. Nota interna com motivo detalhado
|
||||||
|
6. Output: "Ticket #X escalado → Tarefa #Y | Dept: [destino] | ETA: [prazo]"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `/ticket-manage close <id>` — Fecho com Checklist Obrigatória
|
||||||
|
|
||||||
|
```
|
||||||
|
1. mcp__desk-crm-v3__get_ticket({ ticket_id: id })
|
||||||
|
2. Executar checklist SUP-001 (OBRIGATÓRIO — 100% antes de fechar):
|
||||||
|
```
|
||||||
|
|
||||||
|
### Checklist de Fecho (SUP-001)
|
||||||
|
|
||||||
|
- [ ] Solução aplicada e testada
|
||||||
|
- [ ] Explicação clara da solução enviada ao cliente
|
||||||
|
- [ ] Causa raiz identificada (não só sintoma)
|
||||||
|
- [ ] Passos de prevenção comunicados
|
||||||
|
- [ ] Cliente confirmou resolução ("Resolvido? Feedback?")
|
||||||
|
- [ ] Lições aprendidas registadas (se novo problema)
|
||||||
|
- [ ] Follow-up 3 dias agendado (se P1/P2)
|
||||||
|
|
||||||
|
```
|
||||||
|
3. Se checklist incompleta → NÃO fechar, listar pendentes
|
||||||
|
4. Se 100% → fechar:
|
||||||
|
mcp__desk-crm-v3__reply_ticket({
|
||||||
|
ticket_id: id,
|
||||||
|
message: "<p>Olá [Nome],</p>
|
||||||
|
<p>Confirmamos que a situação foi resolvida.</p>
|
||||||
|
<p><strong>Solução:</strong> [explicação]</p>
|
||||||
|
<p><strong>Prevenção:</strong> [dica]</p>
|
||||||
|
<p>Obrigado pelo contacto. Se precisar de algo, estamos disponíveis.</p>
|
||||||
|
<p>Nota 1-10 sobre o suporte?</p>"
|
||||||
|
})
|
||||||
|
mcp__desk-crm-v3__close_ticket({ ticket_id: id })
|
||||||
|
5. Output: "Ticket #X fechado ✓ | Checklist: 7/7 | [Data fecho]"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `/ticket-manage report` — Relatório SLA Semanal (SUP-003)
|
||||||
|
|
||||||
|
```
|
||||||
|
1. Recolher tickets dos últimos 7 dias
|
||||||
|
2. Calcular por prioridade:
|
||||||
|
- % tickets que cumpriram SLA de resposta
|
||||||
|
- % tickets que cumpriram SLA de resolução
|
||||||
|
- Tempo médio de resposta e resolução
|
||||||
|
3. Identificar violações e categorizar causas
|
||||||
|
4. Comparar com semana anterior
|
||||||
|
```
|
||||||
|
|
||||||
|
**Output:**
|
||||||
|
```markdown
|
||||||
|
## Relatório SLA Semanal — [DD-MM-YYYY a DD-MM-YYYY]
|
||||||
|
|
||||||
|
### Cumprimento SLA (Meta: >90%)
|
||||||
|
| Prioridade | Tickets | SLA Resposta | SLA Resolução | Violações |
|
||||||
|
|-----------|---------|-------------|--------------|-----------|
|
||||||
|
| P1 Crítico | 2 | 100% ✅ | 50% ⚠️ | 1 |
|
||||||
|
| P2 Funcional | 8 | 87.5% ⚠️ | 100% ✅ | 1 |
|
||||||
|
| P3 Dúvida | 15 | 93.3% ✅ | 86.7% ⚠️ | 2 |
|
||||||
|
| P4 Melhoria | 3 | 100% ✅ | N/A | 0 |
|
||||||
|
|
||||||
|
### Top 3 Tickets Mais Lentos
|
||||||
|
1. #X — [Assunto] — P2 — 36h — causa: dependência externa D7
|
||||||
|
2. #Y — [Assunto] — P3 — 52h — causa: complexidade técnica
|
||||||
|
3. #Z — [Assunto] — P1 — 5h30 — causa: falta de informação cliente
|
||||||
|
|
||||||
|
### Acções Correctivas
|
||||||
|
- [ ] P2 cumprimento <90% → Revisão processo atribuição automática
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Referências PROCs
|
||||||
|
|
||||||
|
| PROC | Ficheiro Hub |
|
||||||
|
|------|-------------|
|
||||||
|
| SUP-001 Atendimento | `Hub/06-Operacoes/Procedimentos/D2-Suporte/PROC-D2-SUP-001-Atendimento-Cliente.md` |
|
||||||
|
| SUP-002 Ticketing | `Hub/06-Operacoes/Procedimentos/D2-Suporte/PROC-D2-SUP-002-Ticketing-Workflow.md` |
|
||||||
|
| SUP-003 SLA | `Hub/06-Operacoes/Procedimentos/D2-Suporte/PROC-D2-SUP-003-SLA-Management.md` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Anti-Patterns
|
||||||
|
|
||||||
|
- **NUNCA** fechar sem checklist 100% completa
|
||||||
|
- **NUNCA** escalar sem informar o cliente
|
||||||
|
- **NUNCA** ignorar tickets P1 >30min
|
||||||
|
- **NUNCA** resolver sintoma sem identificar causa raiz
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Integração com Outras Skills
|
||||||
|
|
||||||
|
| Skill | Quando usar |
|
||||||
|
|-------|-------------|
|
||||||
|
| `/ticket` | Operações básicas (view, reply) |
|
||||||
|
| `/ticket-triage` | Triagem automática SPAM/facturas |
|
||||||
|
| `/crm` | Contexto cliente 360° |
|
||||||
|
| `/today` | Dashboard diário com SLA alerts |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Changelog
|
||||||
|
|
||||||
|
### v1.0.0 (07-04-2026)
|
||||||
|
- Versão inicial baseada em SUP-001, SUP-002, SUP-003
|
||||||
|
- Dashboard SLA com alertas automáticos
|
||||||
|
- Criação com campos obrigatórios e confirmação recepção
|
||||||
|
- Checklist fecho obrigatória 7 pontos
|
||||||
|
- Protocolo escalação com contexto completo
|
||||||
|
- Relatório semanal SLA
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Skill v1.0.0 | 07-04-2026 | Descomplicar® | Baseado em PROCs D2-SUP-001/002/003*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
@@ -169,3 +169,15 @@ Subject contem:
|
|||||||
---
|
---
|
||||||
|
|
||||||
*Skill v1.0.0 | 04-03-2026 | Descomplicar®*
|
*Skill v1.0.0 | 04-03-2026 | Descomplicar®*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -284,3 +284,15 @@ No checkup diário, mostrar tickets:
|
|||||||
---
|
---
|
||||||
|
|
||||||
*Skill v1.0.0 | 2026-02-05 | Descomplicar®*
|
*Skill v1.0.0 | 2026-02-05 | Descomplicar®*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -316,3 +316,15 @@ Hashtags/links: #2b6cb0
|
|||||||
|
|
||||||
**Versao**: 1.0.0 | **Data**: 2026-03-10 | **Autor**: Descomplicar®
|
**Versao**: 1.0.0 | **Data**: 2026-03-10 | **Autor**: Descomplicar®
|
||||||
*Paletas detalhadas por contexto: `references/color-palettes.md`*
|
*Paletas detalhadas por contexto: `references/color-palettes.md`*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -0,0 +1,104 @@
|
|||||||
|
---
|
||||||
|
name: cinematic-site
|
||||||
|
category: design-media
|
||||||
|
description: "Constroi websites cinematograficos a partir de um site existente. Pipeline 4 passos: brand analysis, scene generation, build HTML/CSS, preview. Usar quando 'cinematic', 'website premium', 'site cinematografico', 'redesign site', 'nanobanana'."
|
||||||
|
version: "1.0.0"
|
||||||
|
created: 2026-04-07
|
||||||
|
tools: [Bash, Read, Write, mcp__claude-in-chrome__read_page, mcp__claude-in-chrome__tabs_create_mcp, mcp__chrome-devtools__take_screenshot]
|
||||||
|
---
|
||||||
|
|
||||||
|
# Skill: /cinematic-site
|
||||||
|
|
||||||
|
Constroi websites cinematograficos responsivos a partir de um site existente. Inspirado no Nanobanana 2 (#366 Jay E / RoboNuggets).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Pipeline de 4 passos
|
||||||
|
|
||||||
|
### Passo 1 — Brand Analysis
|
||||||
|
|
||||||
|
Receber URL do site existente do utilizador.
|
||||||
|
|
||||||
|
1. Abrir URL via `mcp__claude-in-chrome__tabs_create_mcp` + `mcp__claude-in-chrome__read_page`
|
||||||
|
2. Extrair:
|
||||||
|
- Paleta de cores (hex codes das cores dominantes)
|
||||||
|
- Logo (URL ou descricao)
|
||||||
|
- Fontes usadas (font-family do CSS)
|
||||||
|
- Tom de voz (formal, casual, tecnico)
|
||||||
|
- Tipo de negocio e sector
|
||||||
|
- Conteudo principal (hero text, servicos, about)
|
||||||
|
3. Guardar analise em `/tmp/cinematic-site/brand-analysis.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"url": "https://...",
|
||||||
|
"business": "restaurante italiano",
|
||||||
|
"colors": {"primary": "#2C3E50", "secondary": "#E74C3C", "accent": "#F39C12"},
|
||||||
|
"fonts": {"heading": "Playfair Display", "body": "Inter"},
|
||||||
|
"tone": "acolhedor e premium",
|
||||||
|
"logo_description": "...",
|
||||||
|
"hero_text": "...",
|
||||||
|
"sections": ["sobre", "menu", "reservas", "contacto"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Passo 2 — Scene Generation
|
||||||
|
|
||||||
|
Com base na analise, definir o design cinematografico:
|
||||||
|
|
||||||
|
1. **Hero section:** escolher tipo de animacao:
|
||||||
|
- Parallax com imagem de fundo
|
||||||
|
- Scroll-reveal progressivo
|
||||||
|
- Video background concept (descricao, nao video real)
|
||||||
|
- Cursor-follow effect
|
||||||
|
2. **3-5 seccoes adicionais** com animacoes scroll-based:
|
||||||
|
- Referenciar `Hub/04-Stack/02.03-IA/biblioteca-animacoes-scroll.md` para patterns disponiveis
|
||||||
|
3. **Responsive breakpoints:** mobile-first, 3 breakpoints (mobile, tablet, desktop)
|
||||||
|
4. Guardar plano em `/tmp/cinematic-site/scene-plan.md`
|
||||||
|
|
||||||
|
### Passo 3 — Build
|
||||||
|
|
||||||
|
Gerar ficheiros HTML/CSS/JS:
|
||||||
|
|
||||||
|
1. Criar `/tmp/cinematic-site/output/`:
|
||||||
|
- `index.html` — single-page com todas as seccoes
|
||||||
|
- `styles.css` — Tailwind ou CSS puro
|
||||||
|
- `animations.js` — scroll observers + animacoes
|
||||||
|
2. Regras de qualidade:
|
||||||
|
- Referenciar `design.json` Descomplicar para standards
|
||||||
|
- Mobile-first
|
||||||
|
- Core Web Vitals: LCP <2.5s, CLS <0.1
|
||||||
|
- Sem dependencias externas pesadas (max framer-motion ou CSS puro)
|
||||||
|
- Acessibilidade basica (alt text, contraste, focus states)
|
||||||
|
3. Incluir comentarios no HTML com seccoes claras
|
||||||
|
|
||||||
|
### Passo 4 — Preview
|
||||||
|
|
||||||
|
1. Abrir `index.html` no browser local: `xdg-open /tmp/cinematic-site/output/index.html`
|
||||||
|
2. Tirar screenshot via `mcp__chrome-devtools__take_screenshot`
|
||||||
|
3. Mostrar comparacao ao utilizador:
|
||||||
|
- Site original (URL)
|
||||||
|
- Novo site (screenshot)
|
||||||
|
4. Pedir aprovacao antes de qualquer proximo passo
|
||||||
|
5. Se aprovado, sugerir opcoes:
|
||||||
|
- Copiar para pasta de projecto
|
||||||
|
- Ajustar cores/seccoes
|
||||||
|
- Exportar para Vercel/Netlify (manual)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Regras
|
||||||
|
|
||||||
|
- **Nunca deploy automatico** — apenas preview local
|
||||||
|
- **Nunca inventar conteudo** — usar texto real do site original
|
||||||
|
- **Sempre referenciar design.json** para standards visuais
|
||||||
|
- **Output em /tmp/cinematic-site/** — nunca em pastas de projecto sem aprovacao
|
||||||
|
- **README.md incluido** com instrucoes de deploy manual
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
@@ -0,0 +1,278 @@
|
|||||||
|
---
|
||||||
|
name: clone-style
|
||||||
|
description: Clona o estilo visual de um site ou apresentação extraindo design tokens (cores, tipografia, espaçamento, raios, sombras) e gerando JSON compatível com Stitch, design-engine e pptx-generator. Usar quando "clonar estilo", "clone style", "extrair design", "copiar visual", "tokens design", "clone web", "clone slides", "design tokens".
|
||||||
|
---
|
||||||
|
|
||||||
|
# /clone-style — Extrair Design Tokens de Sites e Slides
|
||||||
|
|
||||||
|
## Princípio fundamental
|
||||||
|
|
||||||
|
**Não tentes recriar visualmente — extrai o sistema.** Captura os tokens (cores, fontes, espaçamentos, raios) e alimenta uma ferramenta generativa. A fidelidade vem do sistema, não da imitação pixel a pixel.
|
||||||
|
|
||||||
|
## Modos
|
||||||
|
|
||||||
|
| Comando | Fonte | Output |
|
||||||
|
|---|---|---|
|
||||||
|
| `/clone-style web <url>` | Site live (browser real, CSS computado) | `tokens.json` + screenshots componentes |
|
||||||
|
| `/clone-style slides <pptx_path>` | Ficheiro PPTX local | `tokens.json` (theme1.xml + slideMasters) |
|
||||||
|
| `/clone-style apply <tokens.json>` | Design tokens já extraídos | Aplicação no Stitch / design-engine / pptx-generator |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Modo 1 — Web
|
||||||
|
|
||||||
|
### Workflow
|
||||||
|
|
||||||
|
1. **Abrir URL no Chrome real** via `mcp__claude-in-chrome__navigate` (preferido — captura sessões logged-in se necessário) ou `mcp__chrome-devtools__navigate_page`.
|
||||||
|
|
||||||
|
2. **Aguardar render completo** (`wait_for` "load" + 2s extra para JS).
|
||||||
|
|
||||||
|
3. **Injectar script de extracção** via `mcp__claude-in-chrome__javascript_tool` ou `mcp__chrome-devtools__evaluate_script`. O script está em `references/extract-web-tokens.js`. Cola-o dentro do tool call.
|
||||||
|
|
||||||
|
4. **O script devolve JSON estruturado** com:
|
||||||
|
- `colors`: paleta deduplicada + ranking por frequência (top 12)
|
||||||
|
- `fonts`: famílias únicas + tamanhos + pesos + line-heights
|
||||||
|
- `spacing`: gaps/paddings/margins agrupados (encontra grid base 4px/8px)
|
||||||
|
- `borderRadius`: pequeno/médio/grande/full (clusters)
|
||||||
|
- `shadows`: box-shadows únicas
|
||||||
|
- `componentes`: HTML+CSS de buttons, cards, nav, hero (capturados como referência)
|
||||||
|
|
||||||
|
5. **Capturar screenshots** dos componentes detectados via `mcp__chrome-devtools__take_screenshot` ou `mcp__claude-in-chrome__computer` (full + por componente).
|
||||||
|
|
||||||
|
6. **Mapear para Stitch** (ver secção "Mapeamento Stitch" abaixo) — cores → primary seed, fonte mais usada → enum match, raio dominante → ROUND_*.
|
||||||
|
|
||||||
|
7. **Guardar** em `~/.claude-work/clone-style/<dominio>-<timestamp>/tokens.json` + `screenshots/`.
|
||||||
|
|
||||||
|
### Comando exemplo
|
||||||
|
|
||||||
|
```
|
||||||
|
/clone-style web https://linear.app
|
||||||
|
```
|
||||||
|
|
||||||
|
Output esperado:
|
||||||
|
- `~/.claude-work/clone-style/linear-app-20260407/tokens.json`
|
||||||
|
- `~/.claude-work/clone-style/linear-app-20260407/screenshots/full.png`
|
||||||
|
- `~/.claude-work/clone-style/linear-app-20260407/screenshots/hero.png`
|
||||||
|
- `~/.claude-work/clone-style/linear-app-20260407/screenshots/buttons.png`
|
||||||
|
- Resumo no terminal: paleta + fontes + sugestão de aplicação
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Modo 2 — Slides (PPTX)
|
||||||
|
|
||||||
|
PPTX é um ZIP de XML. Toda a informação de tema está em `ppt/theme/theme1.xml` e `ppt/slideMasters/slideMaster1.xml`.
|
||||||
|
|
||||||
|
### Workflow
|
||||||
|
|
||||||
|
1. **Verificar input** existe e é PPTX válido (`unzip -l <file>` para listar entradas).
|
||||||
|
|
||||||
|
2. **Extrair em tmp**: `unzip -o <file> -d /tmp/clone-style-pptx-<ts>/`.
|
||||||
|
|
||||||
|
3. **Parsear `theme1.xml`** (Python ou xmllint):
|
||||||
|
```python
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
ns = {'a': 'http://schemas.openxmlformats.org/drawingml/2006/main'}
|
||||||
|
tree = ET.parse('ppt/theme/theme1.xml')
|
||||||
|
root = tree.getroot()
|
||||||
|
|
||||||
|
# Cores tema (accent1-6, dark1, dark2, light1, light2, hyperlink, followedHyperlink)
|
||||||
|
colors = {}
|
||||||
|
for child in root.iter('{http://schemas.openxmlformats.org/drawingml/2006/main}clrScheme'):
|
||||||
|
for color_node in child:
|
||||||
|
name = color_node.tag.split('}')[1]
|
||||||
|
srgb = color_node.find('a:srgbClr', ns)
|
||||||
|
sysclr = color_node.find('a:sysClr', ns)
|
||||||
|
if srgb is not None:
|
||||||
|
colors[name] = '#' + srgb.get('val')
|
||||||
|
elif sysclr is not None:
|
||||||
|
colors[name] = '#' + sysclr.get('lastClr', '000000')
|
||||||
|
|
||||||
|
# Fontes (major = headlines, minor = body)
|
||||||
|
fonts = {}
|
||||||
|
for fs in root.iter('{http://schemas.openxmlformats.org/drawingml/2006/main}fontScheme'):
|
||||||
|
major = fs.find('a:majorFont/a:latin', ns)
|
||||||
|
minor = fs.find('a:minorFont/a:latin', ns)
|
||||||
|
if major is not None: fonts['headline'] = major.get('typeface')
|
||||||
|
if minor is not None: fonts['body'] = minor.get('typeface')
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Parsear `slideMaster1.xml`** para layouts dominantes (background, posições, sizes default).
|
||||||
|
|
||||||
|
5. **Output `tokens.json`** no mesmo formato do Modo 1 (para que `apply` seja unificado).
|
||||||
|
|
||||||
|
### Comando exemplo
|
||||||
|
|
||||||
|
```
|
||||||
|
/clone-style slides /home/ealmeida/Downloads/template-cliente.pptx
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Modo 3 — Apply
|
||||||
|
|
||||||
|
Recebe `tokens.json` e aplica numa das 3 ferramentas:
|
||||||
|
|
||||||
|
### A) Stitch (web/UI)
|
||||||
|
|
||||||
|
**Limitação importante:** Stitch só aceita um conjunto restrito de tokens (ver schema `mcp__stitch__create_design_system`):
|
||||||
|
- 1 `customColor` (seed) + opcionais `overridePrimaryColor`/`overrideSecondaryColor`/`overrideTertiaryColor`/`overrideNeutralColor`
|
||||||
|
- `headlineFont` / `bodyFont` / `labelFont` de **enum fixo** (29 Google Fonts: INTER, ROBOTO, MANROPE, GEIST, etc.)
|
||||||
|
- `roundness`: ROUND_4 / ROUND_8 / ROUND_12 / ROUND_FULL
|
||||||
|
- `colorMode`: LIGHT / DARK
|
||||||
|
- `designMd`: markdown livre para tudo o que não cabe nos campos acima
|
||||||
|
|
||||||
|
**Mapeamento Stitch:**
|
||||||
|
|
||||||
|
```
|
||||||
|
tokens.colors.dominant → customColor (seed)
|
||||||
|
tokens.colors.top[1..3] → overridePrimary/Secondary/Tertiary
|
||||||
|
tokens.colors.neutral → overrideNeutralColor
|
||||||
|
|
||||||
|
tokens.fonts.headline.family
|
||||||
|
→ match com enum Stitch (fuzzy: "Helvetica" → INTER, "Söhne" → INTER, etc.)
|
||||||
|
→ headlineFont
|
||||||
|
|
||||||
|
tokens.fonts.body.family
|
||||||
|
→ match enum → bodyFont
|
||||||
|
|
||||||
|
tokens.borderRadius.dominant
|
||||||
|
→ 4px → ROUND_4
|
||||||
|
→ 8-10px → ROUND_8
|
||||||
|
→ 12-14px → ROUND_12
|
||||||
|
→ ≥16px ou full → ROUND_FULL
|
||||||
|
|
||||||
|
tokens.background.dark? → colorMode: DARK, else LIGHT
|
||||||
|
|
||||||
|
# Tudo o resto vai para designMd:
|
||||||
|
designMd: |
|
||||||
|
## Estilo extraído de <fonte>
|
||||||
|
|
||||||
|
### Tipografia adicional
|
||||||
|
- Display: <font> <size> <weight>
|
||||||
|
- Caption: <font> <size> <weight>
|
||||||
|
|
||||||
|
### Espaçamento
|
||||||
|
Grid base: <Npx>
|
||||||
|
Escala: 4, 8, 16, 24, 32, 48, 64
|
||||||
|
|
||||||
|
### Sombras
|
||||||
|
- sm: <box-shadow>
|
||||||
|
- md: <box-shadow>
|
||||||
|
- lg: <box-shadow>
|
||||||
|
|
||||||
|
### Tom visual
|
||||||
|
<descrição em prosa: minimalista, denso, colorido, monocromático, etc.>
|
||||||
|
```
|
||||||
|
|
||||||
|
Depois chama `mcp__stitch__create_design_system` com este payload.
|
||||||
|
|
||||||
|
### B) design-engine (brand pack)
|
||||||
|
|
||||||
|
Cria um JSON brand pack em `/media/ealmeida/Dados/Hub/04-Recursos/Design/brands/<nome>.json` com formato:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "<nome>",
|
||||||
|
"source": "cloned from <url|pptx>",
|
||||||
|
"extracted_at": "2026-04-07",
|
||||||
|
"colors": { "primary": "#...", "secondary": "#...", "neutral": "#...", "accent": "#..." },
|
||||||
|
"fonts": { "headline": "Inter", "body": "Inter" },
|
||||||
|
"borderRadius": "8px",
|
||||||
|
"tone": "minimalista, profissional, denso"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Depois `mcp__design-engine__brand_load(<nome>)` para usar em `generate_image`.
|
||||||
|
|
||||||
|
### C) pptx-generator (slides)
|
||||||
|
|
||||||
|
Aplica os tokens via XML manipulation no template Descomplicar (ver `/pptx-generator`). Substitui:
|
||||||
|
- Cores accent1-6 do `theme1.xml` pelos extraídos
|
||||||
|
- Fontes major/minor pelas extraídas
|
||||||
|
- Mantém layouts/positioning do template Descomplicar (não copia layouts da fonte original — só estilo)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Mapeamento de fontes (fuzzy → Stitch enum)
|
||||||
|
|
||||||
|
Quando `tokens.fonts.headline.family` não está no enum Stitch, mapear:
|
||||||
|
|
||||||
|
| Família detectada | Stitch enum |
|
||||||
|
|---|---|
|
||||||
|
| Helvetica, Helvetica Neue, Arial, sans-serif genérico | INTER |
|
||||||
|
| Söhne, Inter, system-ui | INTER |
|
||||||
|
| Roboto, Roboto Flex | (não existe — usar INTER) |
|
||||||
|
| SF Pro, -apple-system | INTER |
|
||||||
|
| GT Walsheim, Geist, Mona Sans | GEIST |
|
||||||
|
| Manrope | MANROPE |
|
||||||
|
| Plus Jakarta, Jakarta | PLUS_JAKARTA_SANS |
|
||||||
|
| DM Sans | DM_SANS |
|
||||||
|
| IBM Plex Sans | IBM_PLEX_SANS |
|
||||||
|
| Sora | SORA |
|
||||||
|
| Times, serif genérico | NEWSREADER |
|
||||||
|
| Garamond, EB Garamond | EB_GARAMOND |
|
||||||
|
| Playfair, Domine | DOMINE |
|
||||||
|
|
||||||
|
Se nenhum match óbvio, **default INTER** (mais neutro). Adicionar nota em `designMd` com a fonte original detectada.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Anti-patterns
|
||||||
|
|
||||||
|
| Não fazer | Razão |
|
||||||
|
|---|---|
|
||||||
|
| Tentar reproduzir layout pixel a pixel | Impossível e gera "AI slop" |
|
||||||
|
| Usar `cssstats.com` ou scrapers HTML estáticos | Falham em sites JS-rendered (Next.js, React, etc.) |
|
||||||
|
| Importar HTML inteiro como Stitch screen | Stitch não importa HTML; gera de prompt+tokens |
|
||||||
|
| Aplicar Stitch design-system sem `customColor` válido | Validation error — `customColor` é obrigatório |
|
||||||
|
| Esquecer de usar `designMd` para tokens fora do enum | Perde-se 50% da informação extraída |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Validação (critérios para "OK")
|
||||||
|
|
||||||
|
Antes de declarar a clonagem completa:
|
||||||
|
1. ✅ `tokens.json` existe e tem `colors`, `fonts`, `borderRadius` no mínimo
|
||||||
|
2. ✅ Pelo menos 1 screenshot guardado
|
||||||
|
3. ✅ Mapeamento Stitch produz `customColor` válido (hex format)
|
||||||
|
4. ✅ Pelo menos 1 fonte mapeada para enum Stitch
|
||||||
|
5. ✅ `designMd` tem ≥3 secções (tipografia, espaçamento, tom)
|
||||||
|
6. ✅ Se modo `apply`: validação visual pelo utilizador antes de marcar "concluído"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Exemplos práticos
|
||||||
|
|
||||||
|
### Clonar Linear
|
||||||
|
|
||||||
|
```
|
||||||
|
/clone-style web https://linear.app
|
||||||
|
```
|
||||||
|
Esperado: paleta dominante azul/roxo, fontes Inter ou similar, raios 6-8px, dark mode default.
|
||||||
|
|
||||||
|
### Clonar template cliente
|
||||||
|
|
||||||
|
```
|
||||||
|
/clone-style slides ~/Downloads/cliente-deck.pptx
|
||||||
|
```
|
||||||
|
Esperado: cores accent do tema PPTX, fontes major/minor, proposta de paleta unificada.
|
||||||
|
|
||||||
|
### Aplicar a novo projecto Stitch
|
||||||
|
|
||||||
|
```
|
||||||
|
/clone-style apply ~/.claude-work/clone-style/linear-app-20260407/tokens.json
|
||||||
|
```
|
||||||
|
Cria design system Stitch + brand pack design-engine.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Referências internas
|
||||||
|
|
||||||
|
- `references/extract-web-tokens.js` — script JS de extracção CSS computado
|
||||||
|
- `references/extract-pptx-theme.py` — script Python para parsear theme1.xml
|
||||||
|
- `~/.claude-work/clone-style/` — cache de extracções (timestamped)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Versão:** 1.0.0 | **Data:** 2026-04-07 | **Autor:** Descomplicar (sessão 5)
|
||||||
|
**Origem:** Necessidade real — clonagem de estilos em propostas comerciais. Substitui tentativas falhadas com Penpot, scrapers HTML, screenshots+AI, Figma import.
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
extract-pptx-theme.py — extrai design tokens de um ficheiro PPTX
|
||||||
|
|
||||||
|
Uso:
|
||||||
|
python3 extract-pptx-theme.py <caminho.pptx> [--output tokens.json]
|
||||||
|
|
||||||
|
Devolve JSON no mesmo formato do extract-web-tokens.js para que /clone-style apply
|
||||||
|
seja unificado entre os 2 modos.
|
||||||
|
"""
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
import zipfile
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
from pathlib import Path
|
||||||
|
from datetime import datetime, timezone
|
||||||
|
|
||||||
|
NS = {'a': 'http://schemas.openxmlformats.org/drawingml/2006/main'}
|
||||||
|
|
||||||
|
|
||||||
|
def extract_theme(pptx_path: Path) -> dict:
|
||||||
|
if not pptx_path.exists():
|
||||||
|
raise FileNotFoundError(f"Não encontrado: {pptx_path}")
|
||||||
|
|
||||||
|
with zipfile.ZipFile(pptx_path) as z:
|
||||||
|
# Listar themes (pode haver múltiplos; usar o primeiro)
|
||||||
|
theme_files = sorted([n for n in z.namelist() if n.startswith('ppt/theme/theme') and n.endswith('.xml')])
|
||||||
|
if not theme_files:
|
||||||
|
raise ValueError("PPTX sem theme — formato inválido ou corrompido")
|
||||||
|
|
||||||
|
theme_xml = z.read(theme_files[0])
|
||||||
|
root = ET.fromstring(theme_xml)
|
||||||
|
|
||||||
|
# Extrair cores do clrScheme
|
||||||
|
colors = {}
|
||||||
|
for clr_scheme in root.iter('{http://schemas.openxmlformats.org/drawingml/2006/main}clrScheme'):
|
||||||
|
for color_node in clr_scheme:
|
||||||
|
name = color_node.tag.split('}')[1] # ex: 'accent1', 'dk1', 'lt1'
|
||||||
|
srgb = color_node.find('a:srgbClr', NS)
|
||||||
|
sysclr = color_node.find('a:sysClr', NS)
|
||||||
|
if srgb is not None:
|
||||||
|
colors[name] = '#' + srgb.get('val')
|
||||||
|
elif sysclr is not None:
|
||||||
|
# sysClr usa o lastClr como fallback (cor resolvida)
|
||||||
|
colors[name] = '#' + sysclr.get('lastClr', '000000')
|
||||||
|
|
||||||
|
# Extrair fontes do fontScheme
|
||||||
|
fonts = {'headline': None, 'body': None}
|
||||||
|
for fs in root.iter('{http://schemas.openxmlformats.org/drawingml/2006/main}fontScheme'):
|
||||||
|
major = fs.find('a:majorFont/a:latin', NS)
|
||||||
|
minor = fs.find('a:minorFont/a:latin', NS)
|
||||||
|
if major is not None:
|
||||||
|
fonts['headline'] = major.get('typeface')
|
||||||
|
if minor is not None:
|
||||||
|
fonts['body'] = minor.get('typeface')
|
||||||
|
|
||||||
|
# Mapear cores PPTX → estrutura unificada
|
||||||
|
accent_keys = ['accent1', 'accent2', 'accent3', 'accent4', 'accent5', 'accent6']
|
||||||
|
accents = [colors[k] for k in accent_keys if k in colors]
|
||||||
|
|
||||||
|
primary = colors.get('accent1') or accents[0] if accents else '#000000'
|
||||||
|
secondary = colors.get('accent2')
|
||||||
|
tertiary = colors.get('accent3')
|
||||||
|
neutral = colors.get('lt1') or colors.get('dk1') or '#ffffff'
|
||||||
|
background = colors.get('lt1') or colors.get('bg1') or '#ffffff'
|
||||||
|
|
||||||
|
is_dark = colors.get('lt1', '#ffffff').lstrip('#').upper() != 'FFFFFF'
|
||||||
|
|
||||||
|
return {
|
||||||
|
'url': str(pptx_path),
|
||||||
|
'title': pptx_path.stem,
|
||||||
|
'source': 'pptx',
|
||||||
|
'timestamp': datetime.now(timezone.utc).isoformat(),
|
||||||
|
'colors': {
|
||||||
|
'top': [{'value': v, 'count': 1} for v in accents],
|
||||||
|
'backgrounds': [{'value': background, 'count': 1}],
|
||||||
|
'dominant': primary,
|
||||||
|
'raw_scheme': colors,
|
||||||
|
},
|
||||||
|
'fonts': {
|
||||||
|
'families': [
|
||||||
|
{'value': fonts['headline'], 'count': 1, 'role': 'headline'},
|
||||||
|
{'value': fonts['body'], 'count': 1, 'role': 'body'},
|
||||||
|
],
|
||||||
|
'sizes': [],
|
||||||
|
'weights': [],
|
||||||
|
'lineHeights': [],
|
||||||
|
},
|
||||||
|
'borderRadius': [],
|
||||||
|
'shadows': [],
|
||||||
|
'spacing': {'gridBaseGuess': 8, 'top': []},
|
||||||
|
'components': {},
|
||||||
|
'meta': {
|
||||||
|
'colorMode': 'DARK' if is_dark else 'LIGHT',
|
||||||
|
'theme_file': theme_files[0],
|
||||||
|
'accent_count': len(accents),
|
||||||
|
},
|
||||||
|
'mapping_hint': {
|
||||||
|
'stitch_customColor': primary,
|
||||||
|
'stitch_overrideSecondary': secondary,
|
||||||
|
'stitch_overrideTertiary': tertiary,
|
||||||
|
'stitch_overrideNeutral': neutral,
|
||||||
|
'note': 'PPTX só fornece cores e fontes — borderRadius/shadows/spacing têm de ser definidos manualmente em designMd',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print(__doc__, file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
pptx = Path(sys.argv[1]).expanduser().resolve()
|
||||||
|
|
||||||
|
output_path = None
|
||||||
|
if '--output' in sys.argv:
|
||||||
|
idx = sys.argv.index('--output')
|
||||||
|
if idx + 1 < len(sys.argv):
|
||||||
|
output_path = Path(sys.argv[idx + 1]).expanduser().resolve()
|
||||||
|
|
||||||
|
tokens = extract_theme(pptx)
|
||||||
|
js = json.dumps(tokens, indent=2, ensure_ascii=False)
|
||||||
|
|
||||||
|
if output_path:
|
||||||
|
output_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
output_path.write_text(js, encoding='utf-8')
|
||||||
|
print(f"✅ Tokens guardados em {output_path}", file=sys.stderr)
|
||||||
|
else:
|
||||||
|
print(js)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
// extract-web-tokens.js
|
||||||
|
// Injectar via mcp__claude-in-chrome__javascript_tool ou mcp__chrome-devtools__evaluate_script
|
||||||
|
// Devolve JSON com cores, fontes, espaçamentos, raios, sombras e amostras de componentes.
|
||||||
|
// Funciona em qualquer site (incluindo JS-rendered) porque usa getComputedStyle().
|
||||||
|
|
||||||
|
(() => {
|
||||||
|
const all = document.querySelectorAll('*');
|
||||||
|
const colorCounts = {};
|
||||||
|
const fontFamilies = {};
|
||||||
|
const fontSizes = {};
|
||||||
|
const fontWeights = {};
|
||||||
|
const lineHeights = {};
|
||||||
|
const radii = {};
|
||||||
|
const shadows = {};
|
||||||
|
const spacings = {};
|
||||||
|
const bgColors = {};
|
||||||
|
|
||||||
|
const norm = (v) => (v || '').trim();
|
||||||
|
const inc = (obj, k) => { if (!k || k === 'none' || k === '0px') return; obj[k] = (obj[k] || 0) + 1; };
|
||||||
|
|
||||||
|
// Helper: rgb(a) → hex (ignora transparente)
|
||||||
|
const toHex = (rgb) => {
|
||||||
|
if (!rgb || rgb === 'transparent' || rgb === 'rgba(0, 0, 0, 0)') return null;
|
||||||
|
const m = rgb.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);
|
||||||
|
if (!m) return null;
|
||||||
|
const a = m[4] !== undefined ? parseFloat(m[4]) : 1;
|
||||||
|
if (a < 0.1) return null;
|
||||||
|
const h = (n) => parseInt(n).toString(16).padStart(2, '0');
|
||||||
|
return '#' + h(m[1]) + h(m[2]) + h(m[3]);
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const el of all) {
|
||||||
|
if (!(el instanceof Element)) continue;
|
||||||
|
const cs = getComputedStyle(el);
|
||||||
|
|
||||||
|
// Cores
|
||||||
|
inc(colorCounts, toHex(cs.color));
|
||||||
|
const bg = toHex(cs.backgroundColor);
|
||||||
|
if (bg) {
|
||||||
|
inc(bgColors, bg);
|
||||||
|
inc(colorCounts, bg);
|
||||||
|
}
|
||||||
|
inc(colorCounts, toHex(cs.borderColor));
|
||||||
|
|
||||||
|
// Fontes
|
||||||
|
inc(fontFamilies, norm(cs.fontFamily));
|
||||||
|
inc(fontSizes, norm(cs.fontSize));
|
||||||
|
inc(fontWeights, norm(cs.fontWeight));
|
||||||
|
inc(lineHeights, norm(cs.lineHeight));
|
||||||
|
|
||||||
|
// Raios
|
||||||
|
inc(radii, norm(cs.borderRadius));
|
||||||
|
|
||||||
|
// Sombras
|
||||||
|
if (cs.boxShadow && cs.boxShadow !== 'none') inc(shadows, cs.boxShadow);
|
||||||
|
|
||||||
|
// Espaçamentos (paddings + margins + gap)
|
||||||
|
['paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft', 'marginTop', 'marginRight', 'marginBottom', 'marginLeft', 'gap', 'rowGap', 'columnGap'].forEach((p) => {
|
||||||
|
inc(spacings, norm(cs[p]));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Top N por frequência
|
||||||
|
const topN = (obj, n) => Object.entries(obj).sort((a, b) => b[1] - a[1]).slice(0, n).map(([k, v]) => ({ value: k, count: v }));
|
||||||
|
|
||||||
|
// Detectar grid base (espaçamento mais comum)
|
||||||
|
const numericSpacings = Object.entries(spacings)
|
||||||
|
.map(([k, v]) => [parseFloat(k), v])
|
||||||
|
.filter(([n]) => !isNaN(n) && n > 0 && n < 200)
|
||||||
|
.sort((a, b) => b[1] - a[1]);
|
||||||
|
const gridBase = numericSpacings[0]?.[0] || 8;
|
||||||
|
|
||||||
|
// Capturar samples HTML de componentes-chave (pelo selector)
|
||||||
|
const sample = (sel) => {
|
||||||
|
const el = document.querySelector(sel);
|
||||||
|
if (!el) return null;
|
||||||
|
return {
|
||||||
|
html: el.outerHTML.substring(0, 800),
|
||||||
|
computed: {
|
||||||
|
bg: toHex(getComputedStyle(el).backgroundColor),
|
||||||
|
color: toHex(getComputedStyle(el).color),
|
||||||
|
radius: getComputedStyle(el).borderRadius,
|
||||||
|
padding: getComputedStyle(el).padding,
|
||||||
|
font: getComputedStyle(el).fontFamily,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
url: location.href,
|
||||||
|
title: document.title,
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
colors: {
|
||||||
|
top: topN(colorCounts, 12),
|
||||||
|
backgrounds: topN(bgColors, 6),
|
||||||
|
dominant: topN(colorCounts, 1)[0]?.value || null,
|
||||||
|
},
|
||||||
|
fonts: {
|
||||||
|
families: topN(fontFamilies, 5),
|
||||||
|
sizes: topN(fontSizes, 8),
|
||||||
|
weights: topN(fontWeights, 6),
|
||||||
|
lineHeights: topN(lineHeights, 6),
|
||||||
|
},
|
||||||
|
borderRadius: topN(radii, 6),
|
||||||
|
shadows: topN(shadows, 5),
|
||||||
|
spacing: {
|
||||||
|
gridBaseGuess: gridBase,
|
||||||
|
top: topN(spacings, 12),
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
button: sample('button, .btn, [class*="button" i]'),
|
||||||
|
card: sample('.card, [class*="card" i]'),
|
||||||
|
nav: sample('nav, header, [class*="nav" i]'),
|
||||||
|
hero: sample('main > section:first-child, .hero, [class*="hero" i]'),
|
||||||
|
},
|
||||||
|
meta: {
|
||||||
|
colorMode: getComputedStyle(document.body).backgroundColor.includes('255') ? 'LIGHT' : 'DARK',
|
||||||
|
lang: document.documentElement.lang || 'unknown',
|
||||||
|
viewport: document.querySelector('meta[name=viewport]')?.content || null,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
---
|
||||||
|
name: design-b2b
|
||||||
|
description: >
|
||||||
|
Design system para serviços B2B — agências, consultoria, SaaS, PMEs portuguesas.
|
||||||
|
Propostas visuais, landing pages, apresentações e materiais para decisores PT.
|
||||||
|
Usar quando: proposta comercial, landing page serviço B2B, apresentação cliente,
|
||||||
|
one-pager, ou qualquer material visual para audiência empresarial portuguesa.
|
||||||
|
---
|
||||||
|
|
||||||
|
# /design-b2b — Design System Serviços B2B
|
||||||
|
|
||||||
|
## Paleta
|
||||||
|
|
||||||
|
```css
|
||||||
|
--primary: #1e3a5f; /* Azul institucional — confiança, autoridade */
|
||||||
|
--accent: #f97316; /* Laranja acção — CTAs, destaques */
|
||||||
|
--neutral: #f8fafc; /* Fundo profissional */
|
||||||
|
--text: #1e293b; /* Texto principal */
|
||||||
|
--muted: #64748b; /* Texto secundário, legendas */
|
||||||
|
--border: #e2e8f0; /* Divisores subtis */
|
||||||
|
```
|
||||||
|
|
||||||
|
## Estrutura proposta comercial
|
||||||
|
|
||||||
|
### One-pager (1 A4 ou landing page equivalente)
|
||||||
|
1. **Header:** Logo cliente + logo Descomplicar + título proposta
|
||||||
|
2. **Problema:** 2-3 bullets do problema actual do cliente
|
||||||
|
3. **Solução:** O que entregamos (concreto, não vago)
|
||||||
|
4. **Resultados:** Métricas esperadas (%, EUR, tempo)
|
||||||
|
5. **Investimento:** Preço claro, sem asteriscos escondidos
|
||||||
|
6. **Próximo passo:** CTA único — "Agendar Reunião" ou "Aceitar Proposta"
|
||||||
|
|
||||||
|
### Landing page serviço B2B
|
||||||
|
1. Headline: benefício principal (não feature)
|
||||||
|
2. Sub-headline: para quem é + resultado esperado
|
||||||
|
3. Prova social: 3 logos de clientes ou 1 case study
|
||||||
|
4. Serviços: 3-5 cards com ícone + nome + 1 linha
|
||||||
|
5. Processo: 3-4 passos (simples e claro)
|
||||||
|
6. CTA: formulário simples (nome, email, empresa, mensagem)
|
||||||
|
|
||||||
|
## Tom e linguagem B2B PT
|
||||||
|
|
||||||
|
- **Usar:** "optimizar", "aumentar eficiência", "reduzir custos"
|
||||||
|
- **Evitar:** "disruptivo", "revolucionário", "próximo nível"
|
||||||
|
- **Tratamento:** "Você" (neutro) ou "A sua empresa" — nunca "tu" em contexto formal
|
||||||
|
- **Números:** sempre com fonte (ex: "30% redução de custos — caso Empresa X")
|
||||||
|
|
||||||
|
## Anti-slop checklist B2B
|
||||||
|
|
||||||
|
- [ ] Zero jargão sem explicação
|
||||||
|
- [ ] Preços ou "Solicitar orçamento" — nunca ambiguidade
|
||||||
|
- [ ] Casos reais, não hipotéticos
|
||||||
|
- [ ] Mobile: decisores usam telemóvel para primeiro contacto
|
||||||
|
- [ ] Social proof: logo real, não ilustração
|
||||||
|
|
||||||
|
## Referências visuais
|
||||||
|
|
||||||
|
Ver `~/.claude/design/referencias-visuais/servicos-b2b/`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
---
|
||||||
|
name: design-ecommerce
|
||||||
|
description: >
|
||||||
|
Design system para e-commerce — lojas WooCommerce, páginas produto, checkout PT.
|
||||||
|
Optimização conversão, layouts loja, UX checkout e elementos de confiança.
|
||||||
|
Usar quando: criar ou optimizar loja WooCommerce, página produto, carrinho,
|
||||||
|
checkout, ou qualquer elemento visual de e-commerce para mercado português.
|
||||||
|
---
|
||||||
|
|
||||||
|
# /design-ecommerce — Design System E-commerce
|
||||||
|
|
||||||
|
## Paleta base (adaptar à marca do cliente)
|
||||||
|
|
||||||
|
```css
|
||||||
|
--cta: #dc2626; /* Vermelho urgência — "Comprar Agora" */
|
||||||
|
--trust: #16a34a; /* Verde confiança — "Pagamento Seguro" */
|
||||||
|
--price: #1e3a5f; /* Azul preço destacado */
|
||||||
|
--sale: #f59e0b; /* Âmbar promoção */
|
||||||
|
--neutral: #ffffff;
|
||||||
|
--text: #111827;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Elementos conversão obrigatórios
|
||||||
|
|
||||||
|
### Página produto
|
||||||
|
1. Imagens: mínimo 4 ângulos, zoom, vídeo se possível
|
||||||
|
2. Preço: destacado, desconto visível, preço original riscado
|
||||||
|
3. Stock: urgência ("Últimas 3 unidades")
|
||||||
|
4. CTA: "Adicionar ao Carrinho" (vermelho, proeminente)
|
||||||
|
5. Confiança: selos Visa/MB/MBWay + devolução 30 dias
|
||||||
|
6. Avaliações: estrelas + número (social proof)
|
||||||
|
7. "Também pode gostar" + "Compraram juntos"
|
||||||
|
|
||||||
|
### Checkout PT
|
||||||
|
- Referência Multibanco visível
|
||||||
|
- MB Way como opção principal
|
||||||
|
- Campo NIF opcional (B2B)
|
||||||
|
- Morada: formato PT (Rua, nº, andar, código postal, localidade)
|
||||||
|
|
||||||
|
### Elementos de confiança PT
|
||||||
|
- Selos: MBWay, Visa, Mastercard, PayPal
|
||||||
|
- "Envio para Portugal Continental em 24-48h"
|
||||||
|
- "Devolução gratuita em 30 dias"
|
||||||
|
- "Suporte em português"
|
||||||
|
|
||||||
|
## Anti-slop checklist e-commerce
|
||||||
|
|
||||||
|
- [ ] Preços em EUR (não USD)
|
||||||
|
- [ ] CTAs em PT-PT: "Comprar" não "Buy", "Carrinho" não "Cart"
|
||||||
|
- [ ] Mobile: checkout testado em 375px (maioria compra no telemóvel)
|
||||||
|
- [ ] Tempo de carregamento: imagens optimizadas <100KB
|
||||||
|
- [ ] Trust badges visíveis acima do fold
|
||||||
|
|
||||||
|
## Referências visuais
|
||||||
|
|
||||||
|
Ver `~/.claude/design/referencias-visuais/ecommerce/`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
---
|
||||||
|
name: design-saude
|
||||||
|
description: >
|
||||||
|
Design system para sector saúde — clínicas, KiviCare, consultórios médicos.
|
||||||
|
Paleta, tipografia, CTAs e layouts optimizados para contexto clínico PT.
|
||||||
|
Usar quando: criar landing page de clínica, página de serviços médicos,
|
||||||
|
agendamento online, ou qualquer material visual para clientes saúde.
|
||||||
|
---
|
||||||
|
|
||||||
|
# /design-saude — Design System Saúde
|
||||||
|
|
||||||
|
## Paleta
|
||||||
|
|
||||||
|
```css
|
||||||
|
--primary: #0ea5e9; /* Azul confiança médica */
|
||||||
|
--secondary: #10b981; /* Verde saúde/cura */
|
||||||
|
--neutral: #f8fafc; /* Fundo limpo e asséptico */
|
||||||
|
--text: #1e293b; /* Texto principal */
|
||||||
|
--accent: #f59e0b; /* CTA urgência (marcar consulta) */
|
||||||
|
--danger: #ef4444; /* Alertas, urgências */
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tipografia
|
||||||
|
|
||||||
|
- **Títulos:** Inter SemiBold — transmite profissionalismo sem frieza
|
||||||
|
- **Corpo:** Inter Regular 16px, line-height 1.7 — legibilidade para público 40+
|
||||||
|
- **Evitar:** fontes decorativas, cursivas, serifas antiquadas
|
||||||
|
|
||||||
|
## Layouts obrigatórios
|
||||||
|
|
||||||
|
### Landing page clínica
|
||||||
|
1. Hero: foto médico real + headline "Cuidamos de si" + CTA "Marcar Consulta"
|
||||||
|
2. Serviços: cards com ícone + nome + preço (se disponível)
|
||||||
|
3. Equipa: fotos reais + credenciais
|
||||||
|
4. Depoimentos: com nome e tratamento (anonimizado se necessário)
|
||||||
|
5. Localização + horários + contacto
|
||||||
|
6. CTA final: WhatsApp ou formulário
|
||||||
|
|
||||||
|
### CTAs saúde
|
||||||
|
- Principal: "Marcar Consulta" (verde, proeminente)
|
||||||
|
- Secundário: "Saber Mais" ou "Ver Serviços"
|
||||||
|
- Urgência: "Consulta Hoje" (âmbar)
|
||||||
|
|
||||||
|
## Anti-slop checklist saúde
|
||||||
|
|
||||||
|
- [ ] Fotos de pessoas reais (não stock de médicos brancos genéricos)
|
||||||
|
- [ ] RGPD: sem dados de pacientes visíveis em mockups
|
||||||
|
- [ ] Cores acessíveis: contraste WCAG AA mínimo
|
||||||
|
- [ ] Mobile: formulário agendamento testado em 375px
|
||||||
|
- [ ] PT-PT: "consulta" não "appointment", "médico" não "doctor"
|
||||||
|
|
||||||
|
## Referências visuais
|
||||||
|
|
||||||
|
Ver `~/.claude/design/referencias-visuais/saude/`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
---
|
||||||
|
name: design-solar
|
||||||
|
description: >
|
||||||
|
Design system para sector solar/fotovoltaico — SolarFV, instaladores, B2B energia.
|
||||||
|
Paleta, calculadoras, propostas visuais e layouts para sector energias renováveis PT.
|
||||||
|
Usar quando: landing page solar, proposta instalação FV, calculadora poupança,
|
||||||
|
ou material visual para clientes energia solar.
|
||||||
|
---
|
||||||
|
|
||||||
|
# /design-solar — Design System Solar/FV
|
||||||
|
|
||||||
|
## Paleta
|
||||||
|
|
||||||
|
```css
|
||||||
|
--primary: #f59e0b; /* Amarelo solar — energia, optimismo */
|
||||||
|
--secondary: #1e3a5f; /* Azul escuro — confiança, profissionalismo B2B */
|
||||||
|
--green: #16a34a; /* Verde sustentabilidade */
|
||||||
|
--neutral: #f9fafb; /* Fundo limpo */
|
||||||
|
--text: #111827; /* Texto principal */
|
||||||
|
```
|
||||||
|
|
||||||
|
## Elementos distintivos sector solar
|
||||||
|
|
||||||
|
### Calculadora de poupança (elemento central)
|
||||||
|
- Input: consumo mensal kWh + factura actual
|
||||||
|
- Output: poupança anual estimada + payback em anos
|
||||||
|
- Visual: comparação antes/depois com gráfico simples
|
||||||
|
|
||||||
|
### Proposta instalação
|
||||||
|
1. Sumário executivo (1 página): consumo actual → produção estimada → ROI
|
||||||
|
2. Especificações técnicas: painéis, inversor, capacidade
|
||||||
|
3. Financiamento: opções (compra, leasing, PPA)
|
||||||
|
4. Garantias e certificações
|
||||||
|
5. CTA: "Solicitar Visita Técnica"
|
||||||
|
|
||||||
|
## Tipografia
|
||||||
|
|
||||||
|
- **Títulos:** Poppins Bold — moderno, energético
|
||||||
|
- **Dados/métricas:** Inter Mono — leiturabilidade para números
|
||||||
|
- **Corpo:** Inter Regular
|
||||||
|
|
||||||
|
## Anti-slop checklist solar
|
||||||
|
|
||||||
|
- [ ] Números reais de produção (não inventar kWh)
|
||||||
|
- [ ] Certificações visíveis (DGEG, SCE)
|
||||||
|
- [ ] Mobile: calculadora funcional em 375px
|
||||||
|
- [ ] B2B: tom técnico e sóbrio (não "salve o planeta")
|
||||||
|
- [ ] PT: "fotovoltaico" não "fotovoltaica" (painel fotovoltaico)
|
||||||
|
|
||||||
|
## Referências visuais
|
||||||
|
|
||||||
|
Ver `~/.claude/design/referencias-visuais/solar/`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
@@ -44,11 +44,11 @@ Integrar insights do NotebookLM nas recomendações e decisões.
|
|||||||
|---------|--------|-------|
|
|---------|--------|-------|
|
||||||
| `/design [descricao]` | Routing automatico | Auto |
|
| `/design [descricao]` | Routing automatico | Auto |
|
||||||
| `/design presentation [tema]` | Apresentacao PPTX/PDF | Presenton |
|
| `/design presentation [tema]` | Apresentacao PPTX/PDF | Presenton |
|
||||||
| `/design infographic [tema]` | Infografico PNG/PDF | Penpot + AI |
|
| `/design infographic [tema]` | Infografico PNG/PDF | design-engine (Fibo/Gemini) |
|
||||||
| `/design social [plataforma] [tema]` | Post redes sociais | Penpot |
|
| `/design social [plataforma] [tema]` | Post redes sociais | design-engine |
|
||||||
| `/design web [descricao]` | Landing page / web component | Stitch |
|
| `/design web [descricao]` | Landing page / web component | **Stitch (motor principal)** |
|
||||||
| `/design logo [nome]` | Logo SVG + variacoes | Penpot + Fibo |
|
| `/design logo [nome]` | Logo SVG + variacoes | design-engine + Fibo |
|
||||||
| `/design brand [empresa]` | Identidade visual completa | Todos |
|
| `/design brand [empresa]` | Identidade visual completa | Stitch + design-engine |
|
||||||
| `/design from-reference [url]` | Analisa e recria adaptado | Auto |
|
| `/design from-reference [url]` | Analisa e recria adaptado | Auto |
|
||||||
|
|
||||||
## Parametros Opcionais
|
## Parametros Opcionais
|
||||||
@@ -66,11 +66,11 @@ Integrar insights do NotebookLM nas recomendações e decisões.
|
|||||||
1. PARSE comando e parametros
|
1. PARSE comando e parametros
|
||||||
2. IDENTIFICAR tipo de output
|
2. IDENTIFICAR tipo de output
|
||||||
- "presentation" / "slides" / "proposta" -> Presenton
|
- "presentation" / "slides" / "proposta" -> Presenton
|
||||||
- "infographic" / "poster" / "flyer" -> Penpot
|
- "infographic" / "poster" / "flyer" -> design-engine (Fibo/Gemini)
|
||||||
- "social" / "instagram" / "linkedin" -> Penpot (dimensoes)
|
- "social" / "instagram" / "linkedin" -> design-engine (com dimensões)
|
||||||
- "web" / "landing" / "page" / "ui" -> Stitch
|
- "web" / "landing" / "page" / "ui" -> Stitch
|
||||||
- "logo" / "icone" / "marca" -> Penpot + Fibo
|
- "logo" / "icone" / "marca" -> design-engine + Fibo
|
||||||
- "brand" / "identidade" -> Pipeline completo
|
- "brand" / "identidade" -> Stitch (web) + design-engine (assets)
|
||||||
- "from-reference" -> Researcher primeiro
|
- "from-reference" -> Researcher primeiro
|
||||||
3. SE --brand especificado:
|
3. SE --brand especificado:
|
||||||
- Carregar brand pack via design-engine MCP: brand_load(nome)
|
- Carregar brand pack via design-engine MCP: brand_load(nome)
|
||||||
@@ -91,7 +91,7 @@ Resultado: PPTX profissional via Presenton com cores dourado/preto, logo Descomp
|
|||||||
```
|
```
|
||||||
/design social instagram "Promocao Black Friday -30%"
|
/design social instagram "Promocao Black Friday -30%"
|
||||||
```
|
```
|
||||||
Resultado: Imagem 1080x1080 composta no Penpot com texto, cores e layout profissional.
|
Resultado: Imagem 1080x1080 gerada via design-engine (Fibo/Gemini) com texto, cores e layout profissional.
|
||||||
|
|
||||||
### Landing page
|
### Landing page
|
||||||
```
|
```
|
||||||
@@ -103,7 +103,7 @@ Resultado: HTML/CSS via Stitch com Design DNA da marca.
|
|||||||
```
|
```
|
||||||
/design infographic "Top 10 tendencias AI 2026"
|
/design infographic "Top 10 tendencias AI 2026"
|
||||||
```
|
```
|
||||||
Resultado: PNG/PDF vertical composto no Penpot com icones, dados e hierarquia visual.
|
Resultado: PNG/PDF vertical gerado via design-engine com icones, dados e hierarquia visual.
|
||||||
|
|
||||||
### Identidade visual completa
|
### Identidade visual completa
|
||||||
```
|
```
|
||||||
@@ -117,16 +117,17 @@ Resultado: Logo + paleta + tipografia + templates social + template apresentacao
|
|||||||
```
|
```
|
||||||
Resultado: Analisa design Figma, extrai estilo, recria adaptado.
|
Resultado: Analisa design Figma, extrai estilo, recria adaptado.
|
||||||
|
|
||||||
## 5 MCPs de Design
|
## MCPs de Design (4)
|
||||||
|
|
||||||
| MCP | Funcao |
|
| MCP | Funcao |
|
||||||
|-----|--------|
|
|-----|--------|
|
||||||
| **design-engine** | Imagens AI (Fibo/Gemini) + brand packs + rembg |
|
| **design-engine** | Imagens AI (Fibo/Gemini) + brand packs + rembg + composição |
|
||||||
| **presenton** | Apresentacoes AI (slide.descomplicar.pt) |
|
| **presenton** | Apresentacoes AI (slide.descomplicar.pt) |
|
||||||
| **penpot** | Compositor visual (pen.descomplicar.pt) |
|
| **stitch** | Web design AI text→UI (Google Labs) — motor principal para web/ui/landing |
|
||||||
| **stitch** | Web design AI (Google) |
|
|
||||||
| **figma** | Analise referencias (read-only) |
|
| **figma** | Analise referencias (read-only) |
|
||||||
|
|
||||||
|
> **Penpot suspenso 07-04-2026 sessão 5** — substituído por Stitch (text→UI generation). MCP penpot removido. Se Stitch for descontinuado, reavaliar.
|
||||||
|
|
||||||
## Brand Packs Disponiveis
|
## Brand Packs Disponiveis
|
||||||
|
|
||||||
Verificar com: `brand_list()` via design-engine MCP.
|
Verificar com: `brand_list()` via design-engine MCP.
|
||||||
@@ -153,4 +154,17 @@ fidelidade, concisao visual, legibilidade, profissionalismo, brand compliance.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Versao**: 2.0.0 | **Data**: 2026-02-12 | **Autor**: Descomplicar
|
**Versao**: 2.1.0 | **Data**: 2026-04-07 | **Autor**: Descomplicar
|
||||||
|
**v2.1.0:** Penpot removido como motor activo (substituído por Stitch para web/ui e design-engine para imagens/social/infográficos). Workflow simplificado.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -0,0 +1,124 @@
|
|||||||
|
---
|
||||||
|
name: benchmark
|
||||||
|
description: >
|
||||||
|
Mede Core Web Vitals e performance antes/depois de alterações. Detecta regressões.
|
||||||
|
Usar antes e depois de qualquer alteração a WP, WooCommerce, Next.js ou infra.
|
||||||
|
Baseado no gstack /benchmark. Eixo 2B.
|
||||||
|
---
|
||||||
|
|
||||||
|
# /benchmark — Performance Antes/Depois
|
||||||
|
|
||||||
|
Medir o impacto real de alterações. Nunca fazer deploy sem benchmark.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quando Usar
|
||||||
|
|
||||||
|
- Antes de qualquer optimização de performance
|
||||||
|
- Antes de deploy de plugins/temas WordPress
|
||||||
|
- Antes de alterações ao servidor ou cache
|
||||||
|
- Antes de implementar nova feature em produção
|
||||||
|
- Como baseline mensal de cada site
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Métricas Alvo (Core Web Vitals 2024)
|
||||||
|
|
||||||
|
| Métrica | Bom | Precisa Melhorar | Mau |
|
||||||
|
|---------|-----|-----------------|-----|
|
||||||
|
| LCP (Largest Contentful Paint) | ≤2.5s | 2.5-4.0s | >4.0s |
|
||||||
|
| FID / INP (Interaction to Next Paint) | ≤200ms | 200-500ms | >500ms |
|
||||||
|
| CLS (Cumulative Layout Shift) | ≤0.1 | 0.1-0.25 | >0.25 |
|
||||||
|
| TTFB (Time to First Byte) | ≤800ms | 800-1800ms | >1800ms |
|
||||||
|
| FCP (First Contentful Paint) | ≤1.8s | 1.8-3.0s | >3.0s |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Protocolo
|
||||||
|
|
||||||
|
### Passo 1 — Baseline (ANTES)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Via MCP Lighthouse (se disponível)
|
||||||
|
mcp__lighthouse__get_core_web_vitals({ url: "<URL>" })
|
||||||
|
mcp__lighthouse__run_audit({ url: "<URL>", categories: ["performance"] })
|
||||||
|
|
||||||
|
# Ou via Lighthouse CLI no servidor
|
||||||
|
ssh server "lighthouse <URL> --output=json --output-path=/tmp/before.json --chrome-flags='--headless'"
|
||||||
|
|
||||||
|
# Ou via PageSpeed Insights API
|
||||||
|
curl "https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=<URL>&strategy=mobile" | jq '.lighthouseResult.categories.performance.score'
|
||||||
|
```
|
||||||
|
|
||||||
|
**Guardar baseline:**
|
||||||
|
```bash
|
||||||
|
BEFORE_LCP=<valor>
|
||||||
|
BEFORE_CLS=<valor>
|
||||||
|
BEFORE_FCP=<valor>
|
||||||
|
BEFORE_SCORE=<valor>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Passo 2 — Executar Alteração
|
||||||
|
|
||||||
|
Fazer a alteração (deploy, optimização, plugin, etc.)
|
||||||
|
|
||||||
|
### Passo 3 — Depois
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Repetir as mesmas medições
|
||||||
|
mcp__lighthouse__get_core_web_vitals({ url: "<URL>" })
|
||||||
|
|
||||||
|
AFTER_LCP=<valor>
|
||||||
|
AFTER_CLS=<valor>
|
||||||
|
AFTER_FCP=<valor>
|
||||||
|
AFTER_SCORE=<valor>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Passo 4 — Comparação
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Benchmark — [Site] — [Data]
|
||||||
|
|
||||||
|
| Métrica | Antes | Depois | Delta | Estado |
|
||||||
|
|---------|-------|--------|-------|--------|
|
||||||
|
| LCP | Xs | Ys | ±Zs | ✅/⚠️/❌ |
|
||||||
|
| CLS | X | Y | ±Z | ✅/⚠️/❌ |
|
||||||
|
| FCP | Xs | Ys | ±Zs | ✅/⚠️/❌ |
|
||||||
|
| Score | X% | Y% | ±Z% | ✅/⚠️/❌ |
|
||||||
|
|
||||||
|
**Veredicto:** MELHOROU / NEUTRO / REGREDIU
|
||||||
|
**Acção:** Manter deploy / Reverter / Investigar
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Regras de Decisão
|
||||||
|
|
||||||
|
```
|
||||||
|
SE qualquer métrica piorou >10% → REVERTER imediatamente
|
||||||
|
SE Score global piorou >5 pontos → investigar antes de continuar
|
||||||
|
SE CLS aumentou >0.05 → bloquear — UX crítica
|
||||||
|
SE LCP piorou >500ms em mobile → reverter
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Sites Descomplicar a Monitorizar
|
||||||
|
|
||||||
|
| Site | URL | Frequência |
|
||||||
|
|------|-----|-----------|
|
||||||
|
| Descomplicar main | descomplicar.pt | Mensal |
|
||||||
|
| Clip | clip.descomplicar.pt | Após cada deploy |
|
||||||
|
| Outros clientes | variável | Após alterações WP |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Skill /benchmark v1.0 | 06-04-2026 | Eixo 2B — gstack pattern*
|
||||||
@@ -0,0 +1,155 @@
|
|||||||
|
---
|
||||||
|
name: canary
|
||||||
|
description: >
|
||||||
|
Monitorização pós-deploy — detecta regressões em produção. Verifica que o deploy
|
||||||
|
não quebrou nada crítico nos 15min seguintes. Baseado no gstack /canary. Eixo 2B.
|
||||||
|
Usar após qualquer deploy em produção.
|
||||||
|
---
|
||||||
|
|
||||||
|
# /canary — Monitorização Pós-Deploy
|
||||||
|
|
||||||
|
Os primeiros 15 minutos após um deploy são os mais críticos. Esta skill verifica que tudo está OK.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quando Usar (SEMPRE após deploy produção)
|
||||||
|
|
||||||
|
- Após deploy de código em produção
|
||||||
|
- Após actualização de WordPress (core, plugins, temas)
|
||||||
|
- Após alterações de servidor (PHP, Nginx, MySQL)
|
||||||
|
- Após mudanças de DNS ou SSL
|
||||||
|
- Após activação de nova funcionalidade
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Protocolo (15 minutos)
|
||||||
|
|
||||||
|
### Minuto 0-2 — Status Checks
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Site responde?
|
||||||
|
curl -s -o /dev/null -w "%{http_code}" <URL>/
|
||||||
|
# Esperado: 200
|
||||||
|
|
||||||
|
# 2. Admin WP responde?
|
||||||
|
curl -s -o /dev/null -w "%{http_code}" <URL>/wp-admin/
|
||||||
|
# Esperado: 200 ou 302
|
||||||
|
|
||||||
|
# 3. SSL válido?
|
||||||
|
curl -vI <URL> 2>&1 | grep "SSL certificate verify"
|
||||||
|
# Esperado: SSL certificate verify ok
|
||||||
|
|
||||||
|
# 4. Tempo de resposta aceitável?
|
||||||
|
curl -s -o /dev/null -w "%{time_total}\n" <URL>/
|
||||||
|
# Esperado: < 3.0 segundos
|
||||||
|
```
|
||||||
|
|
||||||
|
### Minuto 2-5 — Funcionalidades Críticas
|
||||||
|
|
||||||
|
**Para WordPress:**
|
||||||
|
```bash
|
||||||
|
# Página principal carrega sem erros
|
||||||
|
curl -s <URL>/ | grep -c "wp-content"
|
||||||
|
# Esperado: > 0
|
||||||
|
|
||||||
|
# Sem erro crítico PHP
|
||||||
|
curl -s <URL>/ | grep -i "fatal error\|parse error\|warning"
|
||||||
|
# Esperado: sem output
|
||||||
|
|
||||||
|
# WP-CLI status
|
||||||
|
wp --path=/var/www/html core verify-checksums 2>&1 | tail -1
|
||||||
|
# Esperado: "WordPress installation verifies against checksums."
|
||||||
|
```
|
||||||
|
|
||||||
|
**Para aplicações:**
|
||||||
|
```bash
|
||||||
|
# Health endpoint
|
||||||
|
curl -s <URL>/api/health | jq '.status'
|
||||||
|
# Esperado: "ok"
|
||||||
|
|
||||||
|
# Database conecta?
|
||||||
|
curl -s <URL>/api/health | jq '.database'
|
||||||
|
# Esperado: "connected"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Minuto 5-10 — Métricas de Performance
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Via Lighthouse MCP
|
||||||
|
mcp__lighthouse__get_performance_score({ url: "<URL>" })
|
||||||
|
// Esperado: >= baseline (ver /benchmark)
|
||||||
|
|
||||||
|
mcp__lighthouse__get_core_web_vitals({ url: "<URL>" })
|
||||||
|
// Comparar com baseline guardado
|
||||||
|
```
|
||||||
|
|
||||||
|
### Minuto 10-15 — Logs e Erros
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Erros PHP nas últimas 15 min
|
||||||
|
ssh server "tail -100 /var/log/php/error.log | grep '$(date -d '15 minutes ago' +%H:%M)'"
|
||||||
|
|
||||||
|
# Erros Nginx/Apache
|
||||||
|
ssh server "tail -50 /var/log/nginx/error.log"
|
||||||
|
|
||||||
|
# WooCommerce (se aplicável)
|
||||||
|
wp --path=/var/www/html wc log list 2>&1 | head -20
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Output — Relatório Canary
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Canary Check — [Site] — [Data] [Hora]
|
||||||
|
|
||||||
|
**Deploy:** [O que foi alterado]
|
||||||
|
|
||||||
|
| Check | Estado | Detalhe |
|
||||||
|
|-------|--------|---------|
|
||||||
|
| HTTP 200 | ✅/❌ | |
|
||||||
|
| SSL | ✅/❌ | |
|
||||||
|
| Tempo resposta | ✅/❌ | Xs |
|
||||||
|
| Sem erros PHP | ✅/❌ | |
|
||||||
|
| Performance score | ✅/❌ | X% (base: Y%) |
|
||||||
|
| Logs limpos | ✅/❌ | |
|
||||||
|
|
||||||
|
**Resultado:** ✅ DEPLOY ESTÁVEL | ⚠️ INVESTIGAR | ❌ REVERTER
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Critérios de Reversão Imediata
|
||||||
|
|
||||||
|
```
|
||||||
|
❌ HTTP response != 200 → REVERTER
|
||||||
|
❌ SSL falha → REVERTER
|
||||||
|
❌ "Fatal error" em qualquer página → REVERTER
|
||||||
|
❌ Tempo resposta > 10s → INVESTIGAR
|
||||||
|
❌ Performance score caiu >15 pontos → INVESTIGAR
|
||||||
|
❌ Logs com erros críticos → INVESTIGAR
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Escalada Automática
|
||||||
|
|
||||||
|
Se algum check falha:
|
||||||
|
```
|
||||||
|
1. NOTIFICAR: criar issue no Desk CRM com urgência P1
|
||||||
|
2. REVERTER: se erro crítico, reverter imediatamente
|
||||||
|
3. DOCUMENTAR: o que falhou e quando
|
||||||
|
4. ANALISAR: root cause antes de re-deploy
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Skill /canary v1.0 | 06-04-2026 | Eixo 2B — gstack pattern*
|
||||||
@@ -301,3 +301,15 @@ Activar Chrome por defeito **aumenta consumo de context window** porque as ferra
|
|||||||
1. Desactivar default: `/chrome` -> desactivar
|
1. Desactivar default: `/chrome` -> desactivar
|
||||||
2. Usar `claude --chrome` apenas quando necessario
|
2. Usar `claude --chrome` apenas quando necessario
|
||||||
3. Preferir WebFetch para leituras simples de paginas publicas
|
3. Preferir WebFetch para leituras simples de paginas publicas
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -241,3 +241,15 @@ Output: [resultado esperado]
|
|||||||
Input: [caso complexo]
|
Input: [caso complexo]
|
||||||
Output: [resultado detalhado]
|
Output: [resultado detalhado]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -461,3 +461,15 @@ git commit
|
|||||||
|
|
||||||
**Skill v1.1** | 12-03-2026 | Descomplicar® | Renomeado de /security-check para /dep-audit
|
**Skill v1.1** | 12-03-2026 | Descomplicar® | Renomeado de /security-check para /dep-audit
|
||||||
**Security First** - Zero vulnerabilities ou documentadas
|
**Security First** - Zero vulnerabilities ou documentadas
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -0,0 +1,267 @@
|
|||||||
|
---
|
||||||
|
name: diagrama
|
||||||
|
category: dev-tools
|
||||||
|
description: "Gera diagramas de arquitectura, fluxo, ER e sequência em três formatos: draw.io (.drawio), Excalidraw e Mermaid. Usar quando 'diagrama', 'arquitectura', 'draw.io', 'fluxo', 'ER', 'sequência', 'infra', 'componentes'."
|
||||||
|
version: "1.0.0"
|
||||||
|
created: 2026-04-04
|
||||||
|
tools: [mcp__claude_ai_Excalidraw__export_to_excalidraw, mcp__mcp-mermaid__generate, Write, Bash]
|
||||||
|
---
|
||||||
|
|
||||||
|
# Skill: /diagrama
|
||||||
|
|
||||||
|
Gera diagramas técnicos em três formatos consoante o caso de uso. Suporta arquitectura de sistemas, fluxogramas, diagramas ER, sequência, infra-estrutura e redes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quando usar cada formato
|
||||||
|
|
||||||
|
| Formato | Quando usar | Output |
|
||||||
|
|---------|------------|--------|
|
||||||
|
| **draw.io** | Diagramas formais para documentação, propostas, clientes | `.drawio` (editável) |
|
||||||
|
| **Excalidraw** | Esboços rápidos, brainstorming visual, estilo whiteboard | `.excalidraw` / MCP |
|
||||||
|
| **Mermaid** | Diagramas como código, versionáveis em Git, embeds Markdown | `.svg` / `.png` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Processo de execução
|
||||||
|
|
||||||
|
### 1. Identificar pedido
|
||||||
|
|
||||||
|
Quando o utilizador pede um diagrama, detectar:
|
||||||
|
- **Tipo:** arquitectura | fluxo | ER | sequência | rede | organograma | classe
|
||||||
|
- **Formato pretendido:** draw.io (default para doc. formal) | excalidraw | mermaid
|
||||||
|
- **Contexto:** sistemas envolvidos, entidades, actores
|
||||||
|
|
||||||
|
Se não especificado, perguntar apenas: "draw.io (formal) ou Excalidraw (esboço)?"
|
||||||
|
|
||||||
|
### 2. Gerar conteúdo
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Geração draw.io (.drawio)
|
||||||
|
|
||||||
|
O formato draw.io é mxGraph XML. Gerar o XML e guardar como `.drawio`.
|
||||||
|
|
||||||
|
### Estrutura base
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<mxfile host="Claude Code" modified="YYYY-MM-DDTHH:MM:SS" agent="Claude" version="21.0">
|
||||||
|
<diagram name="Diagrama" id="diagram-1">
|
||||||
|
<mxGraphModel dx="1422" dy="762" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0">
|
||||||
|
<root>
|
||||||
|
<mxCell id="0"/>
|
||||||
|
<mxCell id="1" parent="0"/>
|
||||||
|
<!-- elementos aqui -->
|
||||||
|
</root>
|
||||||
|
</mxGraphModel>
|
||||||
|
</diagram>
|
||||||
|
</mxfile>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Templates de elementos mxGraph
|
||||||
|
|
||||||
|
**Rectângulo (componente/serviço):**
|
||||||
|
```xml
|
||||||
|
<mxCell id="2" value="Nome" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="160" y="160" width="120" height="60" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Seta/ligação:**
|
||||||
|
```xml
|
||||||
|
<mxCell id="10" edge="1" source="2" target="3" parent="1">
|
||||||
|
<mxGeometry relative="1" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Cilindro (base de dados):**
|
||||||
|
```xml
|
||||||
|
<mxCell id="5" value="PostgreSQL" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;fillColor=#f8cecc;strokeColor=#b85450;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="320" y="160" width="80" height="80" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Cloud (serviço externo):**
|
||||||
|
```xml
|
||||||
|
<mxCell id="6" value="Cloudflare" style="shape=mxgraph.cisco.sites.generic_building;sketch=0;html=1;pointerEvents=1;dashed=0;fillColor=#036897;strokeColor=#ffffff;strokeWidth=2;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="480" y="160" width="60" height="60" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Actor (pessoa/utilizador):**
|
||||||
|
```xml
|
||||||
|
<mxCell id="7" value="Utilizador" style="shape=mxgraph.flowchart.start_2;fillColor=#00BEF2;strokeColor=#006EAF;fontColor=#ffffff;fontStyle=1;fontSize=12;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="40" y="170" width="60" height="40" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Swimlane (grupo/camada):**
|
||||||
|
```xml
|
||||||
|
<mxCell id="8" value="Camada Frontend" style="swimlane;startSize=20;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#333333;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="0" y="0" width="400" height="200" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Paleta de cores Descomplicar
|
||||||
|
|
||||||
|
| Componente | fillColor | strokeColor |
|
||||||
|
|-----------|-----------|-------------|
|
||||||
|
| Serviço/App | `#dae8fc` | `#6c8ebf` |
|
||||||
|
| Base de dados | `#f8cecc` | `#b85450` |
|
||||||
|
| Fila/Queue | `#d5e8d4` | `#82b366` |
|
||||||
|
| Externo/Cloud | `#fff2cc` | `#d6b656` |
|
||||||
|
| Infra/Servidor | `#e1d5e7` | `#9673a6` |
|
||||||
|
| Claude/IA | `#f0f4ff` | `#4a6cf7` |
|
||||||
|
|
||||||
|
### Guardar ficheiro
|
||||||
|
|
||||||
|
Guardar em `/media/ealmeida/Dados/Hub/tmp/diagramas/` com nome descritivo:
|
||||||
|
```
|
||||||
|
YYYY-MM-DD-nome-diagrama.drawio
|
||||||
|
```
|
||||||
|
|
||||||
|
Abrir com:
|
||||||
|
```bash
|
||||||
|
drawio "/media/ealmeida/Dados/Hub/tmp/diagramas/NOME.drawio" &
|
||||||
|
```
|
||||||
|
(ou abrir manualmente com draw.io desktop / draw.io no browser)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Geração Excalidraw
|
||||||
|
|
||||||
|
Usar o MCP `mcp__claude_ai_Excalidraw__export_to_excalidraw` para diagramas no estilo whiteboard.
|
||||||
|
|
||||||
|
### Fluxo
|
||||||
|
|
||||||
|
1. Chamar `mcp__claude_ai_Excalidraw__create_view` para iniciar sessão
|
||||||
|
2. Chamar `mcp__claude_ai_Excalidraw__export_to_excalidraw` com o conteúdo estruturado
|
||||||
|
3. Informar o utilizador do link/path gerado
|
||||||
|
|
||||||
|
### Casos de uso preferidos
|
||||||
|
|
||||||
|
- Brainstorming e exploração rápida
|
||||||
|
- Diagramas de fluxo com estilo manual
|
||||||
|
- Esboços para reuniões
|
||||||
|
- Arquitecturas de alto nível para comunicação interna
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Geração Mermaid
|
||||||
|
|
||||||
|
Usar o MCP `mcp__mcp-mermaid__generate` para diagramas como código.
|
||||||
|
|
||||||
|
### Tipos suportados
|
||||||
|
|
||||||
|
**Fluxograma:**
|
||||||
|
```
|
||||||
|
flowchart TD
|
||||||
|
A[Início] --> B{Condição}
|
||||||
|
B -->|Sim| C[Acção]
|
||||||
|
B -->|Não| D[Fim]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Sequência:**
|
||||||
|
```
|
||||||
|
sequenceDiagram
|
||||||
|
participant U as Utilizador
|
||||||
|
participant A as Claude Code
|
||||||
|
participant N as n8n
|
||||||
|
U->>A: Pedido
|
||||||
|
A->>N: Trigger workflow
|
||||||
|
N-->>A: Resultado
|
||||||
|
A-->>U: Resposta
|
||||||
|
```
|
||||||
|
|
||||||
|
**ER:**
|
||||||
|
```
|
||||||
|
erDiagram
|
||||||
|
CLIENTE ||--o{ PROJECTO : tem
|
||||||
|
PROJECTO ||--o{ TAREFA : contém
|
||||||
|
TAREFA {
|
||||||
|
int id
|
||||||
|
string nome
|
||||||
|
string estado
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Arquitectura de componentes (C4):**
|
||||||
|
```
|
||||||
|
C4Context
|
||||||
|
title Stack Descomplicar
|
||||||
|
Person(eal, "Emanuel", "Utilizador principal")
|
||||||
|
System(cc, "Claude Code", "Interface interactiva")
|
||||||
|
System(clip, "Paperclip", "Agentes autónomos")
|
||||||
|
System(n8n, "n8n", "Automação determinística")
|
||||||
|
Rel(eal, cc, "usa directamente")
|
||||||
|
Rel(cc, clip, "delega tarefas complexas")
|
||||||
|
Rel(cc, n8n, "activa workflows")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Guardar output
|
||||||
|
|
||||||
|
Guardar o código Mermaid em `/media/ealmeida/Dados/Hub/tmp/diagramas/NOME.mmd` e renderizar para SVG/PNG via MCP.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Templates prontos por contexto
|
||||||
|
|
||||||
|
### Arquitectura StackDescomplicar
|
||||||
|
|
||||||
|
Gerar diagrama com as três camadas do stack:
|
||||||
|
- **Camada 1:** Claude Code (trabalho interactivo)
|
||||||
|
- **Camada 2:** n8n (automação determinística)
|
||||||
|
- **Camada 3:** Paperclip (raciocínio autónomo)
|
||||||
|
|
||||||
|
### Proposta comercial
|
||||||
|
|
||||||
|
Diagrama da solução para o cliente com:
|
||||||
|
- Infra-estrutura actual (antes)
|
||||||
|
- Solução proposta (depois)
|
||||||
|
- Componentes e integrações
|
||||||
|
|
||||||
|
### Pipeline de dados
|
||||||
|
|
||||||
|
Diagrama de fluxo com:
|
||||||
|
- Fonte → Processamento → Destino
|
||||||
|
- Triggers, transformações, outputs
|
||||||
|
|
||||||
|
### Diagrama ER Desk CRM
|
||||||
|
|
||||||
|
Entidades principais: Lead → Customer → Estimate → Invoice → Payment
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Boas práticas
|
||||||
|
|
||||||
|
- **Máx. 10-15 elementos** por diagrama (mais → dividir em sub-diagramas)
|
||||||
|
- **Labels curtos:** 2-4 palavras por elemento
|
||||||
|
- **Setas com label** quando o fluxo não é óbvio
|
||||||
|
- **Cor consistente** por tipo de componente (seguir paleta Descomplicar)
|
||||||
|
- **Nome descritivo** no ficheiro (não "diagrama1.drawio")
|
||||||
|
- **Guardar em Hub/tmp/diagramas/** para fácil acesso
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Instalar draw.io MCP (opcional, para funcionalidades avançadas)
|
||||||
|
|
||||||
|
O vídeo #210 do Stack_Pesquisa_Videos.md demonstra um MCP draw.io com geração automática a partir de análise de código. Para instalar:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Verificar se há MCP draw.io disponível no gateway
|
||||||
|
# Ver: Hub/04-Stack/claude-code-context-hygiene.md → secção MCPs
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternativa: usar draw.io via browser em https://app.diagrams.net (gratuito, sem instalação) e importar o `.drawio` gerado.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
@@ -0,0 +1,159 @@
|
|||||||
|
---
|
||||||
|
name: docx
|
||||||
|
description: "Criação, edição e análise de documentos Word (.docx). Versão light para heartbeats."
|
||||||
|
---
|
||||||
|
|
||||||
|
# DOCX — Referência Rápida
|
||||||
|
|
||||||
|
## Referência rápida
|
||||||
|
|
||||||
|
| Tarefa | Abordagem |
|
||||||
|
|--------|-----------|
|
||||||
|
| Ler conteúdo | `pandoc` ou descompactar XML |
|
||||||
|
| Criar novo | `docx-js` (npm install -g docx) |
|
||||||
|
| Editar existente | Descompactar → editar XML → recompactar |
|
||||||
|
| Converter .doc | `python scripts/office/soffice.py --headless --convert-to docx doc.doc` |
|
||||||
|
|
||||||
|
## Criar novos documentos (docx-js)
|
||||||
|
|
||||||
|
### Setup básico
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const { Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell, ImageRun,
|
||||||
|
Header, Footer, AlignmentType, PageOrientation, LevelFormat, HeadingLevel,
|
||||||
|
BorderStyle, WidthType, ShadingType, PageNumber, PageBreak } = require('docx');
|
||||||
|
|
||||||
|
const doc = new Document({ sections: [{ children: [/* conteúdo */] }] });
|
||||||
|
Packer.toBuffer(doc).then(buffer => fs.writeFileSync("doc.docx", buffer));
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tamanho de página (A4)
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
sections: [{
|
||||||
|
properties: {
|
||||||
|
page: {
|
||||||
|
size: { width: 11906, height: 16838 }, // A4 em DXA
|
||||||
|
margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
children: [/* conteúdo */]
|
||||||
|
}]
|
||||||
|
```
|
||||||
|
|
||||||
|
Largura de conteúdo A4 com margens 1": `11906 - 2880 = 9026 DXA`
|
||||||
|
|
||||||
|
**Paisagem:** Passar dimensões retrato + `orientation: PageOrientation.LANDSCAPE` (docx-js troca internamente).
|
||||||
|
|
||||||
|
### Listas
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
numbering: { config: [
|
||||||
|
{ reference: "bullets", levels: [{ level: 0, format: LevelFormat.BULLET, text: "\u2022",
|
||||||
|
alignment: AlignmentType.LEFT, style: { paragraph: { indent: { left: 720, hanging: 360 } } } }] }
|
||||||
|
] }
|
||||||
|
// Usar: new Paragraph({ numbering: { reference: "bullets", level: 0 }, children: [...] })
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tabelas
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Largura tabela = soma columnWidths. Usar SEMPRE WidthType.DXA (nunca PERCENTAGE).
|
||||||
|
new Table({
|
||||||
|
width: { size: 9026, type: WidthType.DXA },
|
||||||
|
columnWidths: [4513, 4513],
|
||||||
|
rows: [new TableRow({ children: [
|
||||||
|
new TableCell({
|
||||||
|
borders: { top: b, bottom: b, left: b, right: b },
|
||||||
|
width: { size: 4513, type: WidthType.DXA },
|
||||||
|
shading: { fill: "D5E8F0", type: ShadingType.CLEAR }, // CLEAR, nunca SOLID
|
||||||
|
margins: { top: 80, bottom: 80, left: 120, right: 120 },
|
||||||
|
children: [new Paragraph({ children: [new TextRun("Célula")] })]
|
||||||
|
})
|
||||||
|
] })]
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Imagens
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
new ImageRun({
|
||||||
|
type: "png", // Obrigatório
|
||||||
|
data: fs.readFileSync("image.png"),
|
||||||
|
transformation: { width: 200, height: 150 },
|
||||||
|
altText: { title: "T", description: "D", name: "N" } // Três obrigatórios
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cabeçalhos/rodapés
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
headers: { default: new Header({ children: [new Paragraph({ children: [new TextRun("Cabeçalho")] })] }) },
|
||||||
|
footers: { default: new Footer({ children: [new Paragraph({
|
||||||
|
children: [new TextRun("Página "), new TextRun({ children: [PageNumber.CURRENT] })]
|
||||||
|
})] }) }
|
||||||
|
```
|
||||||
|
|
||||||
|
### Regras críticas docx-js
|
||||||
|
|
||||||
|
- Nunca usar `\n` — usar Paragraphs separados
|
||||||
|
- Nunca usar bullets unicode — usar `LevelFormat.BULLET`
|
||||||
|
- PageBreak dentro de Paragraph: `new Paragraph({ children: [new PageBreak()] })`
|
||||||
|
- ImageRun requer `type`
|
||||||
|
- Tabelas: `columnWidths` E `width` na célula, ambos devem corresponder
|
||||||
|
- Usar `ShadingType.CLEAR`, nunca SOLID
|
||||||
|
- TOC requer `HeadingLevel` apenas, sem estilos custom
|
||||||
|
- Override estilos: IDs exactos "Heading1", "Heading2" + `outlineLevel`
|
||||||
|
|
||||||
|
## Editar documentos existentes
|
||||||
|
|
||||||
|
### Passo 1: Descompactar
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python scripts/office/unpack.py document.docx unpacked/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Passo 2: Editar XML
|
||||||
|
|
||||||
|
Editar ficheiros em `unpacked/word/`. Usar ferramenta Edit directamente (não scripts Python).
|
||||||
|
|
||||||
|
**Tracked changes:**
|
||||||
|
```xml
|
||||||
|
<!-- Inserção -->
|
||||||
|
<w:ins w:id="1" w:author="Claude" w:date="2025-01-01T00:00:00Z">
|
||||||
|
<w:r><w:t>texto inserido</w:t></w:r>
|
||||||
|
</w:ins>
|
||||||
|
|
||||||
|
<!-- Eliminação -->
|
||||||
|
<w:del w:id="2" w:author="Claude" w:date="2025-01-01T00:00:00Z">
|
||||||
|
<w:r><w:delText>texto eliminado</w:delText></w:r>
|
||||||
|
</w:del>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Comentários:**
|
||||||
|
```bash
|
||||||
|
python scripts/comment.py unpacked/ 0 "Texto do comentário"
|
||||||
|
python scripts/comment.py unpacked/ 1 "Resposta" --parent 0
|
||||||
|
```
|
||||||
|
|
||||||
|
**Smart quotes:** `‘` `’` `“` `”`
|
||||||
|
|
||||||
|
### Passo 3: Recompactar
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python scripts/office/pack.py unpacked/ output.docx --original document.docx
|
||||||
|
```
|
||||||
|
|
||||||
|
Validação: `python scripts/office/validate.py doc.docx`
|
||||||
|
|
||||||
|
## Convenções Descomplicar
|
||||||
|
|
||||||
|
- Data: DD-MM-YYYY
|
||||||
|
- Monetário: 1.234,56 EUR
|
||||||
|
- Fonte: Arial 12pt
|
||||||
|
- Página: A4 (11906 x 16838 DXA)
|
||||||
|
- Autor tracked changes: "Claude"
|
||||||
|
- Idioma: PT-PT
|
||||||
|
|
||||||
|
---
|
||||||
|
**Versão**: 1.0.0-light | **Base**: 1.0.0
|
||||||
@@ -510,3 +510,15 @@ Apos executar `comment.py` (ver Passo 2), adicionar marcadores ao document.xml.
|
|||||||
|
|
||||||
---
|
---
|
||||||
**Versao**: 1.0.0 | **Autor**: Descomplicar®
|
**Versao**: 1.0.0 | **Autor**: Descomplicar®
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -218,3 +218,15 @@ CMD ["npm", "start"]
|
|||||||
---
|
---
|
||||||
|
|
||||||
*Versão 1.0.0 | Descomplicar®*
|
*Versão 1.0.0 | Descomplicar®*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -0,0 +1,160 @@
|
|||||||
|
---
|
||||||
|
name: pdf
|
||||||
|
description: Processamento de ficheiros PDF — leitura, extracção, merge, split, OCR, formulários. Versão light para heartbeats.
|
||||||
|
---
|
||||||
|
|
||||||
|
# PDF — Referência Rápida
|
||||||
|
|
||||||
|
## Bibliotecas Python
|
||||||
|
|
||||||
|
### pypdf — operações básicas
|
||||||
|
|
||||||
|
```python
|
||||||
|
from pypdf import PdfReader, PdfWriter
|
||||||
|
|
||||||
|
# Ler e extrair texto
|
||||||
|
reader = PdfReader("documento.pdf")
|
||||||
|
for page in reader.pages:
|
||||||
|
text = page.extract_text()
|
||||||
|
|
||||||
|
# Merge
|
||||||
|
writer = PdfWriter()
|
||||||
|
for pdf in ["doc1.pdf", "doc2.pdf"]:
|
||||||
|
for page in PdfReader(pdf).pages:
|
||||||
|
writer.add_page(page)
|
||||||
|
with open("merged.pdf", "wb") as f:
|
||||||
|
writer.write(f)
|
||||||
|
|
||||||
|
# Split (uma página por ficheiro)
|
||||||
|
for i, page in enumerate(reader.pages):
|
||||||
|
w = PdfWriter()
|
||||||
|
w.add_page(page)
|
||||||
|
with open(f"page_{i+1}.pdf", "wb") as f:
|
||||||
|
w.write(f)
|
||||||
|
|
||||||
|
# Rotate
|
||||||
|
page = reader.pages[0]
|
||||||
|
page.rotate(90)
|
||||||
|
|
||||||
|
# Password
|
||||||
|
writer.encrypt("userpass", "ownerpass")
|
||||||
|
```
|
||||||
|
|
||||||
|
### pdfplumber — tabelas e texto com layout
|
||||||
|
|
||||||
|
```python
|
||||||
|
import pdfplumber
|
||||||
|
|
||||||
|
with pdfplumber.open("doc.pdf") as pdf:
|
||||||
|
for page in pdf.pages:
|
||||||
|
text = page.extract_text()
|
||||||
|
tables = page.extract_tables()
|
||||||
|
```
|
||||||
|
|
||||||
|
### reportlab — criação de PDFs
|
||||||
|
|
||||||
|
```python
|
||||||
|
from reportlab.platypus import SimpleDocTemplate, Paragraph, Table, TableStyle, PageBreak
|
||||||
|
from reportlab.lib.styles import getSampleStyleSheet
|
||||||
|
from reportlab.lib import colors
|
||||||
|
|
||||||
|
doc = SimpleDocTemplate("report.pdf")
|
||||||
|
styles = getSampleStyleSheet()
|
||||||
|
elements = [Paragraph("Título", styles['Title'])]
|
||||||
|
doc.build(elements)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Subscripts/superscripts:** Nunca usar caracteres Unicode. Usar tags XML: `<sub>2</sub>`, `<super>2</super>`.
|
||||||
|
|
||||||
|
## CLI
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Extrair texto (poppler-utils)
|
||||||
|
pdftotext input.pdf output.txt
|
||||||
|
pdftotext -layout input.pdf output.txt
|
||||||
|
|
||||||
|
# Merge/split (qpdf)
|
||||||
|
qpdf --empty --pages file1.pdf file2.pdf -- merged.pdf
|
||||||
|
qpdf input.pdf --pages . 1-5 -- pages1-5.pdf
|
||||||
|
|
||||||
|
# Encriptar
|
||||||
|
qpdf --encrypt user_pass owner_pass 256 -- input.pdf encrypted.pdf
|
||||||
|
|
||||||
|
# Reparar
|
||||||
|
qpdf --check input.pdf
|
||||||
|
|
||||||
|
# Extrair imagens
|
||||||
|
pdfimages -j input.pdf output_prefix
|
||||||
|
|
||||||
|
# Render para PNG
|
||||||
|
pdftoppm -png -r 300 document.pdf output_prefix
|
||||||
|
```
|
||||||
|
|
||||||
|
## OCR (PDFs digitalizados)
|
||||||
|
|
||||||
|
```python
|
||||||
|
import pytesseract
|
||||||
|
from pdf2image import convert_from_path
|
||||||
|
|
||||||
|
images = convert_from_path('scanned.pdf')
|
||||||
|
text = ""
|
||||||
|
for image in images:
|
||||||
|
text += pytesseract.image_to_string(image)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Formulários
|
||||||
|
|
||||||
|
### Verificar campos preenchíveis
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python scripts/check_fillable_fields.py <file.pdf>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Campos preenchíveis (nativos)
|
||||||
|
|
||||||
|
1. `python scripts/extract_form_field_info.py <input.pdf> <field_info.json>`
|
||||||
|
2. `python scripts/convert_pdf_to_images.py <file.pdf> <output_dir>`
|
||||||
|
3. Criar `field_values.json` com `field_id`, `page`, `value`
|
||||||
|
4. `python scripts/fill_fillable_fields.py <input.pdf> <field_values.json> <output.pdf>`
|
||||||
|
|
||||||
|
### Campos não preenchíveis (anotações)
|
||||||
|
|
||||||
|
1. `python scripts/extract_form_structure.py <input.pdf> form_structure.json`
|
||||||
|
2. **Abordagem A (estrutura):** Analisar JSON, criar `fields.json` com `pdf_width`/`pdf_height` e bounding boxes
|
||||||
|
3. **Abordagem B (visual):** Converter para imagens, identificar campos, refinar com crop
|
||||||
|
4. `python scripts/check_bounding_boxes.py fields.json`
|
||||||
|
5. `python scripts/fill_pdf_form_with_annotations.py <input.pdf> fields.json <output.pdf>`
|
||||||
|
6. `python scripts/create_validation_image.py <page> <fields.json> <input_img> <output_img>`
|
||||||
|
|
||||||
|
## Referência rápida
|
||||||
|
|
||||||
|
| Tarefa | Ferramenta | Comando |
|
||||||
|
|--------|-----------|---------|
|
||||||
|
| Merge | pypdf/qpdf | `writer.add_page()` / `qpdf --pages` |
|
||||||
|
| Split | pypdf/qpdf | Uma página por ficheiro |
|
||||||
|
| Texto | pdfplumber | `page.extract_text()` |
|
||||||
|
| Tabelas | pdfplumber | `page.extract_tables()` |
|
||||||
|
| Criar | reportlab | Canvas ou Platypus |
|
||||||
|
| OCR | pytesseract | Converter para imagem primeiro |
|
||||||
|
| Formulários | pypdf/scripts | Ver secção acima |
|
||||||
|
|
||||||
|
## Caminhos Descomplicar
|
||||||
|
|
||||||
|
| Local | Caminho |
|
||||||
|
|-------|---------|
|
||||||
|
| Documentos empresa | `/media/ealmeida/Dados/GDrive/Cloud/Descomplicar/` |
|
||||||
|
| Propostas | `/media/ealmeida/Dados/Hub/03-Propostas/` |
|
||||||
|
| Arquivo clientes | `/media/ealmeida/Dados/GDrive/Arquivo_de_Clientes/` |
|
||||||
|
| Knowledge Base | `/media/ealmeida/Dados/Hub/06-Operacoes/Knowledge-Base/PDFs/` |
|
||||||
|
| Temporários | `~/.claude-work/` (limpar ao concluir) |
|
||||||
|
|
||||||
|
## Workflow
|
||||||
|
|
||||||
|
1. Localizar PDF (filesystem ou Google Drive)
|
||||||
|
2. Descarregar para `~/.claude-work/` se necessário
|
||||||
|
3. Processar
|
||||||
|
4. Guardar no destino final
|
||||||
|
5. Limpar temporários
|
||||||
|
|
||||||
|
---
|
||||||
|
**Versão**: 1.0.0-light | **Base**: 1.0.0
|
||||||
@@ -794,3 +794,15 @@ def extract_text_with_ocr(pdf_path):
|
|||||||
|
|
||||||
---
|
---
|
||||||
**Versao**: 1.0.0 | **Autor**: Descomplicar®
|
**Versao**: 1.0.0 | **Autor**: Descomplicar®
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -392,3 +392,15 @@ mcp__dify-kb__dify_kb_retrieve_segments({
|
|||||||
|
|
||||||
---
|
---
|
||||||
**Versão**: 1.0.0 | **Autor**: Descomplicar®
|
**Versão**: 1.0.0 | **Autor**: Descomplicar®
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -0,0 +1,144 @@
|
|||||||
|
---
|
||||||
|
name: prompt-refine
|
||||||
|
description: Transforma um pedido vago em prompt de excelência — especificação detalhada, inequívoca e estruturada para agentes de IA. Usar quando "refinar prompt", "melhorar prompt", "engenharia de prompts", "prompt para agente", "estruturar instrução IA", "prompt engineering".
|
||||||
|
allowed-tools: Read, Write, mcp__memory-supabase__search_memories
|
||||||
|
---
|
||||||
|
|
||||||
|
# /prompt-refine — Engenharia de Prompts
|
||||||
|
|
||||||
|
Transforma um pedido em linguagem natural num **prompt de excelência** pronto para ser executado por outro agente de IA.
|
||||||
|
|
||||||
|
## Quando Usar
|
||||||
|
|
||||||
|
- Pedido do utilizador é vago ou incompleto
|
||||||
|
- Preparar instrução para um agente especializado
|
||||||
|
- Criar template reutilizável para uma tarefa recorrente
|
||||||
|
- Garantir qualidade máxima de input antes de executar
|
||||||
|
|
||||||
|
## Protocolo
|
||||||
|
|
||||||
|
### 1. Pesquisar contexto relevante
|
||||||
|
|
||||||
|
```
|
||||||
|
mcp__memory-supabase__search_memories "<palavras-chave do pedido>"
|
||||||
|
```
|
||||||
|
|
||||||
|
Verificar se há padrões ou decisões anteriores relacionadas.
|
||||||
|
|
||||||
|
### 2. Analisar o pedido original
|
||||||
|
|
||||||
|
Identificar:
|
||||||
|
- **O quê** — resultado final esperado
|
||||||
|
- **Para quê** — objectivo ou problema a resolver
|
||||||
|
- **Quem** — agente ou utilizador que vai executar
|
||||||
|
- **Restrições** — limitações técnicas, de formato ou de negócio
|
||||||
|
- **Lacunas** — o que está implícito mas não dito
|
||||||
|
|
||||||
|
Se faltar informação crítica → perguntar antes de estruturar.
|
||||||
|
|
||||||
|
### 3. Estruturar o prompt de excelência
|
||||||
|
|
||||||
|
Usar este template como base:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Função
|
||||||
|
[Quem é / que papel assume o agente executante]
|
||||||
|
|
||||||
|
## Objectivo
|
||||||
|
[O que deve ser produzido — resultado concreto e mensurável]
|
||||||
|
|
||||||
|
## Contexto
|
||||||
|
[Informação de fundo necessária para compreender o pedido]
|
||||||
|
|
||||||
|
## Requisitos
|
||||||
|
- [Requisito 1 — obrigatório]
|
||||||
|
- [Requisito 2 — obrigatório]
|
||||||
|
- [Restrição ou critério de qualidade]
|
||||||
|
|
||||||
|
## Input
|
||||||
|
[Descrição do que o agente recebe como entrada]
|
||||||
|
|
||||||
|
## Output esperado
|
||||||
|
[Formato, estrutura e conteúdo exacto do resultado]
|
||||||
|
|
||||||
|
## Exemplos
|
||||||
|
### Exemplo positivo (fazer)
|
||||||
|
[Exemplo concreto do resultado desejado]
|
||||||
|
|
||||||
|
### Exemplo negativo (não fazer)
|
||||||
|
[Exemplo do que deve ser evitado]
|
||||||
|
|
||||||
|
## Critérios de sucesso
|
||||||
|
- [ ] Critério 1
|
||||||
|
- [ ] Critério 2
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Rever antes de entregar
|
||||||
|
|
||||||
|
Verificar checklist:
|
||||||
|
- [ ] Sem ambiguidades — cada instrução tem um único significado possível
|
||||||
|
- [ ] Completo — nenhuma informação crítica em falta
|
||||||
|
- [ ] Accionável — o agente pode executar sem fazer suposições
|
||||||
|
- [ ] Testável — é possível verificar se o output é correcto
|
||||||
|
- [ ] Conciso — sem redundâncias ou instruções contraditórias
|
||||||
|
|
||||||
|
### 5. Entregar com explicação
|
||||||
|
|
||||||
|
Apresentar:
|
||||||
|
1. **Prompt refinado** (em bloco de código copiável)
|
||||||
|
2. **Decisões tomadas** — o que foi inferido vs. o que estava explícito
|
||||||
|
3. **Questões em aberto** — se houver ambiguidades que o utilizador deve resolver
|
||||||
|
|
||||||
|
## Exemplos de Transformação
|
||||||
|
|
||||||
|
### Input vago
|
||||||
|
> "Cria um agente que analisa clientes"
|
||||||
|
|
||||||
|
### Output refinado
|
||||||
|
```markdown
|
||||||
|
## Função
|
||||||
|
Analista de CRM especializado em classificação de clientes
|
||||||
|
|
||||||
|
## Objectivo
|
||||||
|
Gerar um relatório de segmentação de clientes com base em histórico de compras
|
||||||
|
e interacções, identificando os segmentos de alto, médio e baixo valor.
|
||||||
|
|
||||||
|
## Contexto
|
||||||
|
Base de dados Desk CRM com clientes activos nos últimos 12 meses.
|
||||||
|
Acesso via mcp__desk-crm-v3__get_customers e mcp__desk-crm-v3__get_payments.
|
||||||
|
|
||||||
|
## Requisitos
|
||||||
|
- Segmentar em 3 níveis: Alto Valor (>5000EUR/ano), Médio (1000-5000EUR), Baixo (<1000EUR)
|
||||||
|
- Incluir número de projectos activos por cliente
|
||||||
|
- Formato: tabela Markdown ordenada por valor decrescente
|
||||||
|
|
||||||
|
## Input
|
||||||
|
Lista de IDs de clientes ou "todos" para analisar base completa
|
||||||
|
|
||||||
|
## Output esperado
|
||||||
|
Tabela com: ID, Nome, Segmento, Volume Anual (EUR), Projectos Activos, Última Interacção
|
||||||
|
```
|
||||||
|
|
||||||
|
## Padrões de Qualidade
|
||||||
|
|
||||||
|
| Característica | Mau prompt | Bom prompt |
|
||||||
|
|---|---|---|
|
||||||
|
| Especificidade | "Analisa dados" | "Calcula receita mensal por cliente em EUR para Q1 2026" |
|
||||||
|
| Formato output | "Devolve resultados" | "Tabela Markdown com colunas: ID, Nome, Valor, Delta%" |
|
||||||
|
| Critério sucesso | "Deve ser bom" | "Score de satisfação >85% em teste com 3 utilizadores reais" |
|
||||||
|
| Contexto | Nenhum | "Sistema usa Desk CRM v3, moeda EUR, fuso Europe/Lisbon" |
|
||||||
|
|
||||||
|
---
|
||||||
|
**Versão**: 1.0.0 | **Autor**: Descomplicar® | **Plugin**: dev-tools
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
@@ -189,3 +189,15 @@ hooks/
|
|||||||
|
|
||||||
- `references/composition-patterns.md` - Compound components, providers, dependency injection (Vercel Engineering)
|
- `references/composition-patterns.md` - Compound components, providers, dependency injection (Vercel Engineering)
|
||||||
- `references/custom-hooks.md` - useDebounce, useLocalStorage, useFetch com codigo completo
|
- `references/custom-hooks.md` - useDebounce, useLocalStorage, useFetch com codigo completo
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -186,3 +186,15 @@ description: >
|
|||||||
|
|
||||||
Ver `references/anthropic-patterns.md` para exemplos detalhados de progressive disclosure.
|
Ver `references/anthropic-patterns.md` para exemplos detalhados de progressive disclosure.
|
||||||
Ver `references/descomplicar-standards.md` para exemplos de skills Descomplicar bem estruturadas.
|
Ver `references/descomplicar-standards.md` para exemplos de skills Descomplicar bem estruturadas.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -144,3 +144,15 @@ No servidor dev, Playwright ja esta disponivel em `/root/Dev`.
|
|||||||
|
|
||||||
---
|
---
|
||||||
**Versao**: 1.0.0 | **Autor**: Descomplicar®
|
**Versao**: 1.0.0 | **Autor**: Descomplicar®
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -372,3 +372,15 @@ O ficheiro de referencia de precos esta em:
|
|||||||
|
|
||||||
---
|
---
|
||||||
**Versao**: 1.0.0 | **Autor**: Descomplicar®
|
**Versao**: 1.0.0 | **Autor**: Descomplicar®
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -0,0 +1,154 @@
|
|||||||
|
---
|
||||||
|
name: youtube-extract
|
||||||
|
category: dev-tools
|
||||||
|
description: "Extrai transcrições e metadados de vídeos, playlists e canais YouTube para o ficheiro de pesquisa Stack_Pesquisa_Videos.md. Usar quando 'youtube', 'vídeo', 'playlist', 'canal', 'transcrição', 'extrair vídeo', 'pesquisa vídeos'."
|
||||||
|
version: "1.0.0"
|
||||||
|
created: 2026-04-04
|
||||||
|
tools: [Bash]
|
||||||
|
---
|
||||||
|
|
||||||
|
# Skill: /youtube-extract
|
||||||
|
|
||||||
|
Extrai transcrições e metadados de vídeos, playlists e canais YouTube usando o script `youtube-pesquisa-videos.py`. Adiciona automaticamente ao ficheiro de pesquisa do StackDescomplicar.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Ficheiros relevantes
|
||||||
|
|
||||||
|
| Ficheiro | Caminho |
|
||||||
|
|----------|---------|
|
||||||
|
| **Script** | `/media/ealmeida/Dados/Dev/ClaudeDev/youtube-pesquisa-videos.py` |
|
||||||
|
| **Destino padrão** | `/media/ealmeida/Dados/Hub/04-Stack/Stack_Pesquisa_Videos.md` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Processo de execução
|
||||||
|
|
||||||
|
### 1. Identificar o pedido
|
||||||
|
|
||||||
|
Detectar na mensagem do utilizador:
|
||||||
|
- **URLs** — vídeos individuais, playlists (`?list=`), canais (`@canal`, `/c/`, `/channel/`)
|
||||||
|
- **Limite** — "primeiros 10", "máx 5", etc. → usar `--max N`
|
||||||
|
- **Destino** — ficheiro alternativo? → usar `--output caminho`
|
||||||
|
- **Modo** — adicionar ao ficheiro (`--append`) vs mostrar no terminal (sem flag)
|
||||||
|
|
||||||
|
### 2. Construir o comando
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 /media/ealmeida/Dados/Dev/ClaudeDev/youtube-pesquisa-videos.py \
|
||||||
|
URL1 URL2 ... \
|
||||||
|
[--max N] \
|
||||||
|
[--append] \
|
||||||
|
[--output /caminho/alternativo.md] \
|
||||||
|
[--file lista.txt]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Exemplos por tipo de URL
|
||||||
|
|
||||||
|
**Vídeo individual:**
|
||||||
|
```bash
|
||||||
|
python3 /media/ealmeida/Dados/Dev/ClaudeDev/youtube-pesquisa-videos.py \
|
||||||
|
"https://youtu.be/dQw4w9WgXcQ" --append
|
||||||
|
```
|
||||||
|
|
||||||
|
**Playlist completa:**
|
||||||
|
```bash
|
||||||
|
python3 /media/ealmeida/Dados/Dev/ClaudeDev/youtube-pesquisa-videos.py \
|
||||||
|
"https://youtube.com/playlist?list=PLxxx" --append
|
||||||
|
```
|
||||||
|
|
||||||
|
**Playlist com limite:**
|
||||||
|
```bash
|
||||||
|
python3 /media/ealmeida/Dados/Dev/ClaudeDev/youtube-pesquisa-videos.py \
|
||||||
|
"https://youtube.com/playlist?list=PLxxx" --max 10 --append
|
||||||
|
```
|
||||||
|
|
||||||
|
**Canal completo (máx. 20):**
|
||||||
|
```bash
|
||||||
|
python3 /media/ealmeida/Dados/Dev/ClaudeDev/youtube-pesquisa-videos.py \
|
||||||
|
"https://youtube.com/@NomeCanal" --max 20 --append
|
||||||
|
```
|
||||||
|
|
||||||
|
**Mix de URLs:**
|
||||||
|
```bash
|
||||||
|
python3 /media/ealmeida/Dados/Dev/ClaudeDev/youtube-pesquisa-videos.py \
|
||||||
|
"https://youtu.be/ID1" \
|
||||||
|
"https://youtube.com/playlist?list=PLxxx" \
|
||||||
|
--max 5 --append
|
||||||
|
```
|
||||||
|
|
||||||
|
**Ficheiro de lista:**
|
||||||
|
```bash
|
||||||
|
python3 /media/ealmeida/Dados/Dev/ClaudeDev/youtube-pesquisa-videos.py \
|
||||||
|
--file /caminho/lista.txt --append
|
||||||
|
```
|
||||||
|
|
||||||
|
**Pré-visualizar sem gravar:**
|
||||||
|
```bash
|
||||||
|
python3 /media/ealmeida/Dados/Dev/ClaudeDev/youtube-pesquisa-videos.py \
|
||||||
|
"https://youtu.be/ID1"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Comportamento padrão
|
||||||
|
|
||||||
|
| Situação | Acção |
|
||||||
|
|----------|-------|
|
||||||
|
| URL única de vídeo | Extrair e perguntar se adiciona ao ficheiro |
|
||||||
|
| Múltiplos vídeos | Extrair todos e adicionar com `--append` |
|
||||||
|
| Playlist/canal sem limite | Alertar o utilizador — perguntar limite antes de executar |
|
||||||
|
| Ficheiro de destino não especificado | Usar `Stack_Pesquisa_Videos.md` |
|
||||||
|
|
||||||
|
> **Aviso obrigatório para playlists/canais sem `--max`:** Informar o utilizador do número de vídeos antes de processar — canais podem ter centenas.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Após a extracção
|
||||||
|
|
||||||
|
1. Informar quantos vídeos foram adicionados e os números `#N` atribuídos
|
||||||
|
2. Sugerir ao utilizador que complete os campos `*(a completar)*` no ficheiro
|
||||||
|
3. Se houver erros (transcrição indisponível), mencionar quais os vídeos afectados
|
||||||
|
4. Opcional: abrir o ficheiro no editor — `xdg-open "Stack_Pesquisa_Videos.md"`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Pré-requisitos
|
||||||
|
|
||||||
|
- `yt-dlp` instalado: `pip install yt-dlp` ou `brew install yt-dlp`
|
||||||
|
- Python 3.8+
|
||||||
|
- Acesso à internet
|
||||||
|
|
||||||
|
Verificar disponibilidade:
|
||||||
|
```bash
|
||||||
|
yt-dlp --version && python3 --version
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Casos especiais
|
||||||
|
|
||||||
|
**ID curto do YouTube (11 chars):**
|
||||||
|
```bash
|
||||||
|
python3 /media/ealmeida/Dados/Dev/ClaudeDev/youtube-pesquisa-videos.py dQw4w9WgXcQ --append
|
||||||
|
```
|
||||||
|
|
||||||
|
**Destino alternativo (outro projecto):**
|
||||||
|
```bash
|
||||||
|
python3 /media/ealmeida/Dados/Dev/ClaudeDev/youtube-pesquisa-videos.py \
|
||||||
|
"https://youtu.be/ID1" \
|
||||||
|
--output "/media/ealmeida/Dados/Hub/05-Projectos/MeuProjecto/videos.md" \
|
||||||
|
--append
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "gestao",
|
"name": "gestao",
|
||||||
"description": "Project management, time tracking, daily checkups, worklogs, reflections, knowledge management, archiving and compliance auditing. Backed by NotebookLM notebooks.",
|
"description": "Project management, time tracking, daily checkups, worklogs, reflections, knowledge management, archiving and compliance auditing. Backed by NotebookLM notebooks.",
|
||||||
"version": "1.3.0",
|
"version": "1.4.0",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Descomplicar - Crescimento Digital",
|
"name": "Descomplicar - Crescimento Digital",
|
||||||
"url": "https://descomplicar.pt"
|
"url": "https://descomplicar.pt"
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# Changelog — Plugin gestao
|
||||||
|
|
||||||
|
Todas as alterações relevantes a este plugin. Segue [Semantic Versioning](https://semver.org/).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## [1.4.0] — 2026-04-07
|
||||||
|
|
||||||
|
### Adicionado
|
||||||
|
|
||||||
|
- **Nova skill `/clip-instructions`** — gerir AGENTS.md de agentes Paperclip por nome: ver, editar, criar, rever histórico de versões e rollback via API config revisions
|
||||||
|
|
||||||
|
### Corrigido
|
||||||
|
|
||||||
|
- **`/clip-health`** — check 1 reescrito: `systemctl` substituído por `ps aux` (Paperclip não usa systemd); check 6 reescrito: `npx paperclipai doctor` substituído por `curl http://localhost:3100/health`; adicionado check de memória partilhada POSIX (`/dev/shm/PostgreSQL.*`) — causa raiz do bug pós-reboot; score actualizado 21→22; 2 entradas no Healing Log
|
||||||
|
- **`/clip-agent`** — curl de atribuição de skills corrigido: adicionado `-H "Authorization: Bearer $PAPERCLIP_API_KEY"` (sem header dava 401); documentadas notas sobre agentes analyst (`process` adapter, `claude-sonnet-4-6`, heartbeat desactivado); checklist "Criar agente novo" actualizada com `instructionsBundleMode: "external"`, `instructionsRootPath`, `instructionsEntryFile`; 3 entradas no Healing Log
|
||||||
|
- **`/clip-issue`** — `author_user_id` corrigido: `'board'` → `'v1N5OccPn9DGq6iog7qW9nEvnXYFT3iO'` (ID real de Emanuel); adicionado modo checkout/release com endpoints API e fallback SQL; entrada no Healing Log
|
||||||
|
- **`/clip-skill`** — modelo mental corrigido: "ephemeral/symlinks" → "injecção de contexto em runtime a cada heartbeat"; adicionado `-H "Authorization: Bearer $PAPERCLIP_API_KEY"` aos dois curls de API (`/skills/import` e `/skills/sync`); nota sobre adapter `process` para agentes analyst; entrada no Healing Log
|
||||||
|
|
||||||
|
### Notas técnicas
|
||||||
|
|
||||||
|
- Todas as correcções baseadas em aprendizagens dos vídeos Paperclip (sessão 07-04-2026)
|
||||||
|
- Chave de autenticação Paperclip: `Authorization: Bearer $PAPERCLIP_API_KEY` obrigatória em todos os endpoints da API local
|
||||||
|
- Agentes criados via SQL directamente (fora do fluxo OpenClaw) **não** recebem `company_memberships` automaticamente — inserção manual obrigatória
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## [1.3.0] — anterior
|
||||||
|
|
||||||
|
- Versão base (sem changelog registado)
|
||||||
@@ -4,7 +4,7 @@ description: Auto-reflexão e melhoria contínua do sistema. Analisa sessões, i
|
|||||||
padrões, sugere optimizações. Auto-trigger >20 tool calls.
|
padrões, sugere optimizações. Auto-trigger >20 tool calls.
|
||||||
role: Auto-reflexão e melhoria contínua do sistema
|
role: Auto-reflexão e melhoria contínua do sistema
|
||||||
domain: Dev
|
domain: Dev
|
||||||
model: sonnet
|
model: haiku
|
||||||
tools: Read, Write, Edit, Glob, ToolSearch
|
tools: Read, Write, Edit, Glob, ToolSearch
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
|
|||||||
@@ -132,3 +132,15 @@ exit $EXIT_CODE
|
|||||||
---
|
---
|
||||||
|
|
||||||
*Skill v1.0.0 | 04-03-2026 | Descomplicar®*
|
*Skill v1.0.0 | 04-03-2026 | Descomplicar®*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -221,3 +221,15 @@ Output: [resultado esperado]
|
|||||||
Input: [caso complexo]
|
Input: [caso complexo]
|
||||||
Output: [resultado detalhado]
|
Output: [resultado detalhado]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -175,3 +175,15 @@ mcp__google_workspace__create_event({
|
|||||||
|
|
||||||
- **Workflows detalhados:** `references/workflows-detalhados.md`
|
- **Workflows detalhados:** `references/workflows-detalhados.md`
|
||||||
- **MCP tools e constantes:** `references/mcp-tools-referencia.md`
|
- **MCP tools e constantes:** `references/mcp-tools-referencia.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: cleanup-downloads
|
name: cleanup-downloads
|
||||||
description: Limpeza e triagem da pasta Transferências (Downloads). Verifica cada ficheiro individualmente, apaga descartáveis, classifica o restante por categoria. Usar quando "transferências", "downloads", "limpar downloads", "cleanup", "limpeza pasta".
|
description: Limpeza e triagem da pasta Transferências (Downloads). Verifica cada ficheiro individualmente, apaga descartáveis, classifica o restante por categoria. Usar quando "transferências", "downloads", "limpar downloads", "cleanup", "limpeza pasta".
|
||||||
disable-model-invocation: true
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# Cleanup Downloads
|
# Cleanup Downloads
|
||||||
@@ -105,3 +104,15 @@ Após mover documentos financeiros (regra 3), lançar despesas via `/expense`:
|
|||||||
## Integração /today
|
## Integração /today
|
||||||
|
|
||||||
Incluir contagem de ficheiros na pasta quando >10 ficheiros.
|
Incluir contagem de ficheiros na pasta quando >10 ficheiros.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -0,0 +1,340 @@
|
|||||||
|
---
|
||||||
|
name: clip-agent
|
||||||
|
description: Gerir agente Paperclip individual — estado, config, AGENTS.md, histórico runs, issues. Aceita nome como argumento. Usar quando "clip agent", "agente clip", "ver agente", "estado do CTO".
|
||||||
|
context: fork
|
||||||
|
---
|
||||||
|
|
||||||
|
# /clip-agent — Gerir Agente Paperclip
|
||||||
|
|
||||||
|
Aceita argumento: nome do agente (ex: `/clip-agent CTO`).
|
||||||
|
|
||||||
|
## Constantes
|
||||||
|
|
||||||
|
```
|
||||||
|
BD: PGPASSWORD="paperclip" psql -h localhost -p 54329 -U paperclip -d paperclip
|
||||||
|
COMPANY_ID: ebe10308-efd7-453f-86ab-13e6fe84004f
|
||||||
|
AGENTS_PATH: /media/ealmeida/Dados/Hub/04-Stack/02.06-Clip/agents/
|
||||||
|
```
|
||||||
|
|
||||||
|
## Procedimento
|
||||||
|
|
||||||
|
### Passo 1: Contexto completo do agente
|
||||||
|
|
||||||
|
Invocar tool MCP: `mcp__paperclip__diag_agent_full_context(agent_name="{{NOME}}")`
|
||||||
|
|
||||||
|
Esta tool retorna config, últimas runs, membership, permissões e tokens — cobre os Passos 1, 3, 6, 7 e 7b de uma só vez. Se multiplos resultados, mostrar lista e pedir clarificacao.
|
||||||
|
|
||||||
|
### Passo 2: Hierarquia
|
||||||
|
|
||||||
|
Quem lhe reporta:
|
||||||
|
```sql
|
||||||
|
SELECT name, role, status FROM agents
|
||||||
|
WHERE reports_to = '{{AGENT_ID}}'
|
||||||
|
AND company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
ORDER BY role, name;
|
||||||
|
```
|
||||||
|
|
||||||
|
A quem reporta:
|
||||||
|
```sql
|
||||||
|
SELECT name, role FROM agents WHERE id = '{{REPORTS_TO_ID}}';
|
||||||
|
```
|
||||||
|
|
||||||
|
### Passo 3: Ultimas 5 runs
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT hr.status, hr.started_at, hr.finished_at, LEFT(hr.error, 80) as erro
|
||||||
|
FROM heartbeat_runs hr
|
||||||
|
WHERE hr.agent_id = '{{AGENT_ID}}'
|
||||||
|
ORDER BY hr.started_at DESC LIMIT 5;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Passo 4: Issues atribuidas
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT title, status, priority FROM issues
|
||||||
|
WHERE assignee_agent_id = '{{AGENT_ID}}'
|
||||||
|
AND status NOT IN ('done','cancelled')
|
||||||
|
ORDER BY priority, status;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Passo 4b: Verificar falsos blockers (INC-07)
|
||||||
|
|
||||||
|
Se o agente tem issues `blocked`, invocar tool MCP: `mcp__paperclip__diag_false_blockers` e filtrar pelo agente. TODO: criar diag_* tool per-agent se uso recorrente.
|
||||||
|
|
||||||
|
Se `sub_activas > 0` e o agente está operacional → falso blocker. Alertar: "Issue {{ID}} marcada como blocked mas tem sub-tasks activas — deveria ser in_progress."
|
||||||
|
|
||||||
|
### Passo 5: AGENTS.md
|
||||||
|
|
||||||
|
Procurar em `AGENTS_PATH`:
|
||||||
|
```bash
|
||||||
|
find /media/ealmeida/Dados/Hub/04-Stack/02.06-Clip/agents/ -name "AGENTS.md" -exec grep -l "{{NOME}}" {} \;
|
||||||
|
```
|
||||||
|
|
||||||
|
Se encontrado, ler e apresentar resumo (primeiras 30 linhas).
|
||||||
|
|
||||||
|
## Formato de output
|
||||||
|
|
||||||
|
```
|
||||||
|
## Agente: {{NOME}}
|
||||||
|
|
||||||
|
**Role:** {{role}} | **Status:** {{status}} | **Ultimo heartbeat:** {{last_heartbeat_at}}
|
||||||
|
**Reporta a:** {{reports_to_name}} | **Budget:** {{spent}}/{{budget}} ({{pct}}%)
|
||||||
|
**Tokens cached:** {{tokens_M}}M | **CWD:** {{cwd}} | **Model:** {{model}}
|
||||||
|
|
||||||
|
### Equipa (reportam a este agente)
|
||||||
|
| Nome | Role | Status |
|
||||||
|
...
|
||||||
|
|
||||||
|
### Ultimas 5 runs
|
||||||
|
| Status | Início | Fim | Erro |
|
||||||
|
...
|
||||||
|
|
||||||
|
### Issues atribuidas
|
||||||
|
| Titulo | Status | Prioridade |
|
||||||
|
...
|
||||||
|
|
||||||
|
### Skills atribuidas
|
||||||
|
[lista de desiredSkills ou "Sem skills (apenas built-in paperclip)"]
|
||||||
|
|
||||||
|
### AGENTS.md
|
||||||
|
[resumo ou path]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Passo 6: Skills do agente
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT
|
||||||
|
adapter_config->'paperclipSkillSync'->'desiredSkills' as desired_skills
|
||||||
|
FROM agents
|
||||||
|
WHERE id = '{{AGENT_ID}}';
|
||||||
|
```
|
||||||
|
|
||||||
|
Se nao NULL, listar as skills. Se NULL, indicar "Sem skills atribuidas (apenas built-in paperclip)".
|
||||||
|
|
||||||
|
Para ver detalhes das skills disponiveis na empresa:
|
||||||
|
```sql
|
||||||
|
SELECT name, slug, key, source_type FROM company_skills
|
||||||
|
WHERE company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
ORDER BY name;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Skills atribuídas ao agente
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Ver skills desejadas (configuradas via API)
|
||||||
|
SELECT
|
||||||
|
a.name as agente,
|
||||||
|
a.adapter_config->'paperclipSkillSync'->'desiredSkills' as desired_skills
|
||||||
|
FROM agents a
|
||||||
|
WHERE a.id = '{{AGENT_ID}}';
|
||||||
|
```
|
||||||
|
|
||||||
|
**Acções disponíveis:**
|
||||||
|
- Ver skills da empresa: `SELECT name, slug FROM company_skills WHERE company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'`
|
||||||
|
- Atribuir skills via API (fetch no browser): `POST /api/agents/{{AGENT_ID}}/skills/sync` com `{ "desiredSkills": ["slug1", "slug2"] }`
|
||||||
|
|
||||||
|
### Membership (OBRIGATÓRIO — sem isto, permissões não funcionam)
|
||||||
|
|
||||||
|
A função `hasPermission()` verifica **primeiro** se o agente tem membership activa em `company_memberships`. Sem membership → permissão negada mesmo com grants correctos.
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Verificar membership
|
||||||
|
SELECT status, membership_role FROM company_memberships
|
||||||
|
WHERE company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
AND principal_id = '{{AGENT_ID}}';
|
||||||
|
```
|
||||||
|
|
||||||
|
Se **0 rows** → agente não tem membership. Criar:
|
||||||
|
```sql
|
||||||
|
INSERT INTO company_memberships (id, company_id, principal_type, principal_id, status, membership_role, created_at, updated_at)
|
||||||
|
VALUES (gen_random_uuid(), 'ebe10308-efd7-453f-86ab-13e6fe84004f', 'agent', '{{AGENT_ID}}', 'active', 'member', NOW(), NOW());
|
||||||
|
```
|
||||||
|
|
||||||
|
**Nota:** Agentes criados via SQL directo NÃO recebem membership automaticamente — apenas os onboarded via fluxo OpenClaw/hiring. Sempre criar membership ao adicionar agentes manualmente.
|
||||||
|
|
||||||
|
### Permissões do agente
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT permission_key FROM principal_permission_grants
|
||||||
|
WHERE company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
AND principal_id = '{{AGENT_ID}}';
|
||||||
|
```
|
||||||
|
|
||||||
|
Para adicionar `tasks:assign` (necessário para delegação):
|
||||||
|
```sql
|
||||||
|
INSERT INTO principal_permission_grants (company_id, principal_type, principal_id, permission_key, granted_by_user_id)
|
||||||
|
VALUES ('ebe10308-efd7-453f-86ab-13e6fe84004f', 'agent', '{{AGENT_ID}}', 'tasks:assign', 'local-board');
|
||||||
|
```
|
||||||
|
|
||||||
|
**ATENÇÃO:** Este grant só funciona se o agente tiver membership activa (ver secção acima).
|
||||||
|
|
||||||
|
### Passo 7: Verificar adapter_config (CRITICO)
|
||||||
|
|
||||||
|
Agentes sem `dangerouslySkipPermissions: true` ficam bloqueados — todos os comandos bash sao rejeitados.
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT name,
|
||||||
|
adapter_config->>'dangerouslySkipPermissions' as skip_perms,
|
||||||
|
adapter_config->>'cwd' as cwd,
|
||||||
|
adapter_config->>'model' as model,
|
||||||
|
adapter_config->>'timeoutSec' as timeout,
|
||||||
|
adapter_config->>'maxTurnsPerRun' as max_turns
|
||||||
|
FROM agents WHERE id = '{{AGENT_ID}}';
|
||||||
|
```
|
||||||
|
|
||||||
|
**Alertar se:**
|
||||||
|
- `skip_perms` != `true` → agente vai ficar bloqueado em todos os comandos bash
|
||||||
|
- `cwd` = NULL → agente corre em directório temporário sem acesso ao Hub
|
||||||
|
- `cwd` = `/media/ealmeida/Dados/Hub` → **CRITICO: CWD aponta para Hub raiz (6.4GB), Claude Code indexa tudo, causa token burn massivo** — usar `/media/ealmeida/Dados/Hub/04-Stack/02.06-Clip`
|
||||||
|
- `model` = NULL → usa modelo default (pode não ser o desejado)
|
||||||
|
|
||||||
|
**Corrigir agente (CWD correcto para Clip):**
|
||||||
|
```sql
|
||||||
|
UPDATE agents SET adapter_config = adapter_config || '{"dangerouslySkipPermissions": true, "cwd": "/media/ealmeida/Dados/Hub/04-Stack/02.06-Clip", "model": "gemini-2.5-flash", "graceSec": 20, "timeoutSec": 900}'::jsonb
|
||||||
|
WHERE id = '{{AGENT_ID}}';
|
||||||
|
```
|
||||||
|
|
||||||
|
**Nota sobre modelos e adapters:** O adapter `claude_local` já não é usado para agentes heartbeat. Distribuição actual:
|
||||||
|
- 1 agente (CEO) usa `gemini_local` com `gemini-2.5-pro`
|
||||||
|
- 50 agentes usam `gemini_local` com `gemini-2.5-flash`
|
||||||
|
- 13 agentes usam `opencode_local` com `openrouter/x-ai/grok-4.1-fast`
|
||||||
|
|
||||||
|
**Agentes analyst/read-only (ex: Reality Checker):** usar `adapter_type: process` com `adapter_config.model: "claude-sonnet-4-6"` e `instructionsBundleMode: "external"`. Estes agentes são invocados manualmente (heartbeat desactivado), não consomem budget em modo autónomo.
|
||||||
|
|
||||||
|
### Passo 7b: Sessão e tokens (INC-12)
|
||||||
|
|
||||||
|
`agent_task_sessions` não tem campo de tokens — o consumo está em `heartbeat_runs.usage_json`. Verificar erros "Prompt is too long" e consumo nas últimas runs.
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Erros "Prompt is too long" recentes
|
||||||
|
SELECT hr.status, LEFT(hr.error, 80) as erro, hr.started_at::timestamp(0)
|
||||||
|
FROM heartbeat_runs hr
|
||||||
|
WHERE hr.agent_id = '{{AGENT_ID}}'
|
||||||
|
AND hr.status IN ('failed','error')
|
||||||
|
AND hr.error ILIKE '%too long%'
|
||||||
|
AND hr.started_at > NOW() - INTERVAL '48 hours'
|
||||||
|
ORDER BY hr.started_at DESC LIMIT 5;
|
||||||
|
|
||||||
|
-- Consumo token nas últimas runs bem-sucedidas
|
||||||
|
SELECT ROUND(COALESCE((hr.usage_json->>'cache_read_input_tokens')::numeric,0)/1000,0) as cache_read_k,
|
||||||
|
ROUND(COALESCE((hr.usage_json->>'input_tokens')::numeric,0)/1000,0) as input_k,
|
||||||
|
ROUND(COALESCE((hr.usage_json->>'output_tokens')::numeric,0)/1000,0) as output_k,
|
||||||
|
hr.started_at::timestamp(0)
|
||||||
|
FROM heartbeat_runs hr
|
||||||
|
WHERE hr.agent_id = '{{AGENT_ID}}'
|
||||||
|
AND hr.status = 'succeeded'
|
||||||
|
AND hr.usage_json IS NOT NULL
|
||||||
|
ORDER BY hr.started_at DESC LIMIT 3;
|
||||||
|
```
|
||||||
|
|
||||||
|
Se existirem erros "too long" → forçar rotação:
|
||||||
|
```sql
|
||||||
|
DELETE FROM agent_task_sessions
|
||||||
|
WHERE agent_id = '{{AGENT_ID}}'
|
||||||
|
AND company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f';
|
||||||
|
```
|
||||||
|
|
||||||
|
### Passo 7c: Validar instructionsFilePath (INC-07)
|
||||||
|
|
||||||
|
O Paperclip **não usa `cwd` para resolver `instructionsFilePath`** — o path é sempre relativo ao processo do servidor, não ao CWD do agente. Deve ser **sempre absoluto**.
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT adapter_config->>'instructionsFilePath' as instructions_path
|
||||||
|
FROM agents WHERE id = '{{AGENT_ID}}';
|
||||||
|
```
|
||||||
|
|
||||||
|
**Alertar se:**
|
||||||
|
- `instructionsFilePath` não começa com `/` → **CRITICO: path relativo, AGENTS.md não carrega**
|
||||||
|
- Path absoluto mas ficheiro não existe → CRITICO
|
||||||
|
|
||||||
|
**Corrigir path relativo:**
|
||||||
|
```sql
|
||||||
|
UPDATE agents
|
||||||
|
SET adapter_config = jsonb_set(
|
||||||
|
adapter_config,
|
||||||
|
'{instructionsFilePath}',
|
||||||
|
to_jsonb('/media/ealmeida/Dados/Hub/04-Stack/02.06-Clip/' || (adapter_config->>'instructionsFilePath'))
|
||||||
|
)
|
||||||
|
WHERE id = '{{AGENT_ID}}'
|
||||||
|
AND adapter_config->>'instructionsFilePath' NOT LIKE '/%';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Wakeup manual de agente
|
||||||
|
|
||||||
|
Para forcar um agente a acordar imediatamente (ex: testar, desbloquear):
|
||||||
|
|
||||||
|
```sql
|
||||||
|
DO $$
|
||||||
|
DECLARE wakeup_id uuid;
|
||||||
|
BEGIN
|
||||||
|
INSERT INTO agent_wakeup_requests (company_id, agent_id, source, trigger_detail, reason, payload, status, requested_at, created_at, updated_at)
|
||||||
|
VALUES ('ebe10308-efd7-453f-86ab-13e6fe84004f', '{{AGENT_ID}}', 'on_demand', 'manual', '{{RAZAO}}', '{}'::jsonb, 'queued', NOW(), NOW(), NOW())
|
||||||
|
RETURNING id INTO wakeup_id;
|
||||||
|
|
||||||
|
INSERT INTO heartbeat_runs (company_id, agent_id, invocation_source, trigger_detail, status, wakeup_request_id, context_snapshot, created_at, updated_at)
|
||||||
|
VALUES ('ebe10308-efd7-453f-86ab-13e6fe84004f', '{{AGENT_ID}}', 'on_demand', 'manual', 'queued', wakeup_id, '{"wakeReason": "manual_wakeup"}'::jsonb, NOW(), NOW());
|
||||||
|
END $$;
|
||||||
|
```
|
||||||
|
|
||||||
|
**Nota:** UPDATE directo em issues nao dispara wakeOnDemand — e preciso o par wakeup_request + heartbeat_run.
|
||||||
|
|
||||||
|
## Criar agente novo via SQL (checklist OBRIGATÓRIA)
|
||||||
|
|
||||||
|
Ao criar agente directamente na BD (fora do fluxo OpenClaw), executar TODOS os passos:
|
||||||
|
|
||||||
|
1. `INSERT INTO agents (...)` — dados do agente, incluindo:
|
||||||
|
- `adapter_type: 'process'`
|
||||||
|
- `adapter_config`: campos obrigatórios: `model`, `instructionsFilePath` (absoluto!), `instructionsRootPath`, `instructionsEntryFile: "AGENTS.md"`, `instructionsBundleMode: "external"`
|
||||||
|
- Para agentes autónomos: adicionar `dangerouslySkipPermissions: true`, `cwd`, `timeoutSec`
|
||||||
|
2. `INSERT INTO company_memberships (...)` — **sem isto, permissões não funcionam** (agentes criados via SQL não recebem membership automática)
|
||||||
|
3. `INSERT INTO principal_permission_grants (...)` — se precisa de `tasks:assign` (C-Level, Directores)
|
||||||
|
4. Criar `AGENTS.md` no path absoluto definido em `instructionsFilePath`
|
||||||
|
5. Verificar: `instructionsFilePath` não começa com `/` → AGENTS.md não carrega (ver Passo 7c)
|
||||||
|
|
||||||
|
## Acções disponíveis
|
||||||
|
|
||||||
|
Se o utilizador pedir:
|
||||||
|
- **Editar AGENTS.md:** Abrir ficheiro com Read/Edit
|
||||||
|
- **Alterar config:** `UPDATE agents SET runtime_config = '...' WHERE id = '{{AGENT_ID}}';`
|
||||||
|
- **Pausar:** `UPDATE agents SET status = 'paused', pause_reason = '...', paused_at = NOW() WHERE id = '{{AGENT_ID}}';`
|
||||||
|
- **Despausar:** `UPDATE agents SET status = 'idle', pause_reason = NULL, paused_at = NULL WHERE id = '{{AGENT_ID}}';`
|
||||||
|
- **Wakeup:** Usar bloco SQL acima (wakeup_request + heartbeat_run)
|
||||||
|
- **Corrigir permissoes:** Usar UPDATE adapter_config acima
|
||||||
|
- **Atribuir skill:** `curl -s -X POST http://localhost:3100/api/agents/{{AGENT_ID}}/skills/sync -H "Content-Type: application/json" -H "Authorization: Bearer $PAPERCLIP_API_KEY" -d '{"desiredSkills": ["key1", "key2"]}'`
|
||||||
|
- **Ver skills empresa:** query company_skills acima
|
||||||
|
|
||||||
|
### Safety gate: verificacao de dependencias (OBRIGATORIO antes de DELETE/remocao)
|
||||||
|
|
||||||
|
Antes de apagar ou remover qualquer agente, executar SEMPRE:
|
||||||
|
```sql
|
||||||
|
SELECT 'budget_policies' as tabela, COUNT(*) as refs FROM budget_policies WHERE scope_type='agent' AND scope_id='{{AGENT_ID}}'
|
||||||
|
UNION ALL
|
||||||
|
SELECT 'budget_incidents', COUNT(*) FROM budget_incidents WHERE scope_type='agent' AND scope_id='{{AGENT_ID}}'
|
||||||
|
UNION ALL
|
||||||
|
SELECT 'heartbeat_runs', COUNT(*) FROM heartbeat_runs WHERE agent_id='{{AGENT_ID}}'
|
||||||
|
UNION ALL
|
||||||
|
SELECT 'issues', COUNT(*) FROM issues WHERE assignee_agent_id='{{AGENT_ID}}'
|
||||||
|
UNION ALL
|
||||||
|
SELECT 'issue_comments', COUNT(*) FROM issue_comments WHERE author_agent_id='{{AGENT_ID}}';
|
||||||
|
```
|
||||||
|
|
||||||
|
- Se refs > 0 em budget_policies ou budget_incidents: apagar essas refs PRIMEIRO, senao o dashboard fica com "Agent not found"
|
||||||
|
- Se refs > 0 em issues: reatribuir ou fechar as issues antes
|
||||||
|
- Mostrar resultado ao utilizador e confirmar antes de prosseguir
|
||||||
|
- NUNCA apagar agente sem verificar e limpar dependencias
|
||||||
|
|
||||||
|
Confirmar sempre antes de executar accoes destrutivas.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"2026-04-07","issue":"API skill attribution sem Authorization header — chamada rejeitada com 401","fix":"Adicionar -H 'Authorization: Bearer $PAPERCLIP_API_KEY' ao curl POST /api/agents/:id/skills/sync","source":"auto"}
|
||||||
|
{"date":"2026-04-07","issue":"Agente criado via SQL sem membership ficou com Board access required em todos os endpoints","fix":"Sempre inserir em company_memberships após INSERT em agents. Agentes via SQL não recebem membership automática — só via fluxo OpenClaw/hiring","source":"auto"}
|
||||||
|
{"date":"2026-04-07","issue":"instructionsBundleMode em falta na adapter_config — AGENTS.md não carregava","fix":"Incluir instructionsBundleMode: 'external' + instructionsRootPath + instructionsEntryFile: 'AGENTS.md' na adapter_config","source":"auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
@@ -0,0 +1,398 @@
|
|||||||
|
---
|
||||||
|
name: clip-health
|
||||||
|
description: Diagnóstico rápido Paperclip — serviço, BD, heartbeats falhados, budget, disco. Usar quando "clip health", "saúde clip", "diagnóstico paperclip", "clip problemas".
|
||||||
|
context: fork
|
||||||
|
---
|
||||||
|
|
||||||
|
# /clip-health — Diagnostico Paperclip
|
||||||
|
|
||||||
|
Verificacao rapida da saude do sistema Clip.
|
||||||
|
|
||||||
|
## Constantes
|
||||||
|
|
||||||
|
```
|
||||||
|
BD: PGPASSWORD="paperclip" psql -h localhost -p 54329 -U paperclip -d paperclip
|
||||||
|
PAPERCLIP_DIR: /home/ealmeida/paperclip
|
||||||
|
INSTANCE_DIR: /home/ealmeida/.paperclip/instances/default
|
||||||
|
```
|
||||||
|
|
||||||
|
## Procedimento
|
||||||
|
|
||||||
|
Executar todas as verificacoes em paralelo, depois apresentar relatorio.
|
||||||
|
|
||||||
|
### Check 1: Serviço
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ps aux | grep -E "paperclip.*src/index|pnpm.*paperclipai" | grep -v grep | head -5
|
||||||
|
```
|
||||||
|
|
||||||
|
- Processos encontrados = OK
|
||||||
|
- Nenhum processo = CRITICO (iniciar com: `cd /home/ealmeida/paperclip && pnpm --filter @paperclipai/server dev`)
|
||||||
|
|
||||||
|
Verificar também memória partilhada PostgreSQL (causa do bug POSIX shared memory):
|
||||||
|
```bash
|
||||||
|
ls /dev/shm/PostgreSQL.* 2>/dev/null && echo "POSIX OK" || echo "POSIX em falta — BD pode falhar ao ligar"
|
||||||
|
```
|
||||||
|
|
||||||
|
- POSIX OK = OK
|
||||||
|
- POSIX em falta + processos activos = AVISO (PostgreSQL perdeu shared memory — reiniciar Paperclip)
|
||||||
|
- POSIX em falta + sem processos = CRITICO
|
||||||
|
|
||||||
|
### Check 2: Base de dados
|
||||||
|
|
||||||
|
Conexao:
|
||||||
|
```sql
|
||||||
|
SELECT 1 as connected;
|
||||||
|
```
|
||||||
|
|
||||||
|
Tamanho:
|
||||||
|
```sql
|
||||||
|
SELECT pg_size_pretty(pg_database_size('paperclip')) as db_size;
|
||||||
|
```
|
||||||
|
|
||||||
|
Contagens:
|
||||||
|
```sql
|
||||||
|
SELECT
|
||||||
|
(SELECT COUNT(*) FROM agents WHERE company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f') as agentes,
|
||||||
|
(SELECT COUNT(*) FROM issues WHERE company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f') as issues,
|
||||||
|
(SELECT COUNT(*) FROM heartbeat_runs hr JOIN agents a ON hr.agent_id = a.id WHERE a.company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f') as heartbeats;
|
||||||
|
```
|
||||||
|
|
||||||
|
- Conexao OK = OK
|
||||||
|
- Conexao falha = CRITICO
|
||||||
|
|
||||||
|
### Check 3: Heartbeats falhados (24h)
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT a.name, hr.status, LEFT(hr.error, 70) as erro, hr.started_at::timestamp(0)
|
||||||
|
FROM heartbeat_runs hr JOIN agents a ON hr.agent_id = a.id
|
||||||
|
WHERE a.company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
AND hr.status IN ('failed','error')
|
||||||
|
AND hr.started_at > NOW() - INTERVAL '24 hours'
|
||||||
|
ORDER BY hr.started_at DESC
|
||||||
|
LIMIT 20;
|
||||||
|
```
|
||||||
|
|
||||||
|
- 0 falhas = OK
|
||||||
|
- 1-2 falhas = AVISO
|
||||||
|
- 3+ falhas = CRITICO
|
||||||
|
|
||||||
|
### Check 4: Budget
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT name, budget_monthly_cents, spent_monthly_cents,
|
||||||
|
CASE WHEN budget_monthly_cents > 0
|
||||||
|
THEN ROUND(spent_monthly_cents::numeric / budget_monthly_cents * 100, 1)
|
||||||
|
ELSE 0 END as pct
|
||||||
|
FROM agents
|
||||||
|
WHERE company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
AND budget_monthly_cents > 0
|
||||||
|
AND spent_monthly_cents > 0
|
||||||
|
ORDER BY pct DESC;
|
||||||
|
```
|
||||||
|
|
||||||
|
- <80% = OK
|
||||||
|
- 80-95% = AVISO
|
||||||
|
- >95% = CRITICO
|
||||||
|
|
||||||
|
### Check 5: Disco
|
||||||
|
|
||||||
|
```bash
|
||||||
|
df -h /home/ealmeida/.paperclip/ | tail -1
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
du -sh /home/ealmeida/.paperclip/instances/default/db/ 2>/dev/null
|
||||||
|
du -sh /home/ealmeida/.paperclip/instances/default/logs/ 2>/dev/null
|
||||||
|
du -sh /home/ealmeida/.paperclip/instances/default/data/ 2>/dev/null
|
||||||
|
```
|
||||||
|
|
||||||
|
- >30% livre = OK
|
||||||
|
- 15-30% livre = AVISO
|
||||||
|
- <15% livre = CRITICO
|
||||||
|
|
||||||
|
### Check 6: API Health
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -s --max-time 5 http://localhost:3100/health 2>/dev/null || echo "FALHA"
|
||||||
|
```
|
||||||
|
|
||||||
|
Esperado: `{"status":"ok","version":"...","deploymentMode":"authenticated","bootstrapStatus":"ready"}`
|
||||||
|
|
||||||
|
- `status: ok` = OK
|
||||||
|
- `{"error":"Board access required"}` = AVISO (API responde mas sem auth — BD operacional)
|
||||||
|
- FALHA/timeout = CRITICO (servidor não responde)
|
||||||
|
|
||||||
|
### Check 7: Gateway MCPs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -s --max-time 5 https://gateway.descomplicar.pt/health 2>/dev/null || echo "FALHA"
|
||||||
|
```
|
||||||
|
|
||||||
|
- Responde = OK
|
||||||
|
- Timeout/falha = AVISO
|
||||||
|
|
||||||
|
### Check 8: Referencias orfas na BD
|
||||||
|
|
||||||
|
Budget policies e incidents a referenciar entidades inexistentes:
|
||||||
|
|
||||||
|
Invocar tool MCP: `mcp__paperclip__diag_budget_orphans`
|
||||||
|
|
||||||
|
- 0 orfaos = OK
|
||||||
|
- 1+ orfaos = CRITICO (causa "Agent not found" no dashboard, apagar com DELETE)
|
||||||
|
|
||||||
|
### Check 9: Instancias duplicadas
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ss -tlnp | grep -E "310[0-9]" | wc -l
|
||||||
|
```
|
||||||
|
|
||||||
|
- 1 instancia = OK
|
||||||
|
- 2+ instancias = CRITICO (processos orfaos do pnpm, matar com `kill -9` os PIDs com PPID=1)
|
||||||
|
|
||||||
|
Detalhe dos processos:
|
||||||
|
```bash
|
||||||
|
ss -tlnp | grep -E "310[0-9]"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check 10: Porta vs Cloudflare Tunnel
|
||||||
|
|
||||||
|
```bash
|
||||||
|
TUNNEL_PORT=$(grep -A1 "clip.descomplicar.pt" ~/.cloudflared/config.yml | grep service | grep -oP ':\K[0-9]+')
|
||||||
|
ACTUAL_PORT=$(ss -tlnp | grep -E "310[0-9]" | head -1 | grep -oP ':310[0-9]' | tr -d ':')
|
||||||
|
echo "Tunnel: $TUNNEL_PORT | Servidor: $ACTUAL_PORT"
|
||||||
|
```
|
||||||
|
|
||||||
|
- Iguais = OK
|
||||||
|
- Diferentes = CRITICO (tunnel a apontar para porta errada, dashboard inacessivel)
|
||||||
|
|
||||||
|
### Check 11: Agentes sem permissoes bash
|
||||||
|
|
||||||
|
Invocar tool MCP: `mcp__paperclip__diag_agents_without_skip_permissions`
|
||||||
|
|
||||||
|
- 0 = OK
|
||||||
|
- 1+ = CRITICO (agentes vao ficar bloqueados ao executar bash — corrigir com `/clip-agent`)
|
||||||
|
|
||||||
|
### Check 12: Agentes sem heartbeat
|
||||||
|
|
||||||
|
Invocar tool MCP: `mcp__paperclip__diag_agents_missing_heartbeat`
|
||||||
|
|
||||||
|
- 0 = OK
|
||||||
|
- 1+ = AVISO (agentes nao acordam — podem nao processar issues)
|
||||||
|
|
||||||
|
### Check 13: Routine triggers com kind errado ou next_run_at NULL
|
||||||
|
|
||||||
|
Invocar tool MCP: `mcp__paperclip__diag_routine_triggers_broken`
|
||||||
|
|
||||||
|
- 0 = OK
|
||||||
|
- 1+ = CRITICO (routines nao vao disparar — kind deve ser 'schedule' e next_run_at populado)
|
||||||
|
|
||||||
|
### Check 14: Issues PUBLICAR NOTICIA sem assignee
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT COUNT(*) FROM issues
|
||||||
|
WHERE company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
AND title LIKE 'PUBLICAR NOTICIA%'
|
||||||
|
AND status = 'todo'
|
||||||
|
AND assignee_agent_id IS NULL;
|
||||||
|
```
|
||||||
|
|
||||||
|
- 0 = OK
|
||||||
|
- 1+ = AVISO (cron assign-copywriter.sh devia atribuir a cada 5 min — verificar crontab)
|
||||||
|
|
||||||
|
### Check 15: Qualidade artigos publicados (ultimas 24h)
|
||||||
|
|
||||||
|
Verificar artigos recentes no WordPress via SSH (server):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /home/ealmeida/public_html && wp --allow-root post list --post_type=post --post_status=publish --category=noticias --date_query='{"after":"1 day ago"}' --fields=ID,post_title --format=csv 2>/dev/null
|
||||||
|
```
|
||||||
|
|
||||||
|
Para CADA artigo recente, verificar:
|
||||||
|
|
||||||
|
**15a. Acentuacao** — procurar palavras sem acento:
|
||||||
|
```bash
|
||||||
|
cd /home/ealmeida/public_html && wp --allow-root post get POST_ID --field=post_content 2>/dev/null | sed 's/<[^>]*>//g' | grep -oP '\b\w+cao\b|\b\w+sao\b|\bnao\b|\b\w+vel\b' | head -20
|
||||||
|
```
|
||||||
|
Palavras terminadas em "cao", "sao" (sem til) ou "nao" indicam acentuacao em falta.
|
||||||
|
|
||||||
|
**15b. Links HTML sem aspas:**
|
||||||
|
```bash
|
||||||
|
cd /home/ealmeida/public_html && wp --allow-root post get POST_ID --field=post_content 2>/dev/null | grep -oP 'href=[^"'\''"][^ >]+' | head -10
|
||||||
|
```
|
||||||
|
Se output nao vazio = links sem aspas.
|
||||||
|
|
||||||
|
**15c. Titulo com maiusculas indevidas:**
|
||||||
|
```bash
|
||||||
|
cd /home/ealmeida/public_html && wp --allow-root post get POST_ID --field=post_title 2>/dev/null
|
||||||
|
```
|
||||||
|
Verificar: so primeira palavra e nomes proprios devem ter maiuscula.
|
||||||
|
|
||||||
|
- 0 problemas = OK
|
||||||
|
- 1-3 = AVISO (artigos com defeitos cosmeticos)
|
||||||
|
- 4+ = CRITICO (Copywriter nao esta a cumprir quality gates — actualizar AGENTS.md)
|
||||||
|
|
||||||
|
### Check 16: Cron assign-copywriter activo
|
||||||
|
|
||||||
|
```bash
|
||||||
|
crontab -l | grep assign-copywriter
|
||||||
|
```
|
||||||
|
|
||||||
|
- Presente = OK
|
||||||
|
- Ausente = CRITICO (issues PUBLICAR NOTICIA nunca serao atribuidas ao Copywriter)
|
||||||
|
|
||||||
|
### Check 17: Pipeline noticias end-to-end (ultimas 24h)
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Routines disparadas
|
||||||
|
SELECT COUNT(*) as routines_fired FROM routine_triggers rt
|
||||||
|
JOIN routines r ON rt.routine_id = r.id
|
||||||
|
WHERE r.title LIKE 'Pesquisa diaria%noticias%'
|
||||||
|
AND rt.last_fired_at > NOW() - INTERVAL '24 hours';
|
||||||
|
|
||||||
|
-- Issues de pesquisa concluidas
|
||||||
|
SELECT COUNT(*) as pesquisas_done FROM issues
|
||||||
|
WHERE company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
AND title LIKE 'Pesquisa diaria%'
|
||||||
|
AND status = 'done'
|
||||||
|
AND created_at > NOW() - INTERVAL '24 hours';
|
||||||
|
|
||||||
|
-- Issues PUBLICAR NOTICIA criadas e concluidas
|
||||||
|
SELECT
|
||||||
|
COUNT(*) as total,
|
||||||
|
COUNT(*) FILTER (WHERE status = 'done') as done,
|
||||||
|
COUNT(*) FILTER (WHERE status IN ('todo','in_progress')) as pendentes
|
||||||
|
FROM issues
|
||||||
|
WHERE company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
AND title LIKE 'PUBLICAR NOTICIA%'
|
||||||
|
AND created_at > NOW() - INTERVAL '24 hours';
|
||||||
|
```
|
||||||
|
|
||||||
|
- routines_fired >= 3 E pesquisas_done >= 1 E done >= 5 = OK
|
||||||
|
- Qualquer zero = AVISO (pipeline com falhas)
|
||||||
|
- routines_fired = 0 = CRITICO (routines nao disparam)
|
||||||
|
|
||||||
|
### Check 18: Issues blocked sem impedimento real (INC-07)
|
||||||
|
|
||||||
|
Invocar tool MCP: `mcp__paperclip__diag_false_blockers`
|
||||||
|
|
||||||
|
Para cada issue blocked, verificar se o assignee está em erro:
|
||||||
|
```sql
|
||||||
|
SELECT a.name, a.status FROM agents a
|
||||||
|
WHERE a.id = (SELECT assignee_agent_id FROM issues WHERE identifier = '{{ID}}');
|
||||||
|
```
|
||||||
|
|
||||||
|
- Issue `blocked` + assignee `active/idle/running` + sub-tasks activas > 0 = **FALSO BLOCKER** (deveria ser `in_progress`)
|
||||||
|
- Issue `blocked` + assignee `error/paused` = blocker legítimo
|
||||||
|
- Issue `blocked` + sem sub-tasks + sem comentário de impedimento = suspeito, alertar
|
||||||
|
|
||||||
|
Resultado:
|
||||||
|
- 0 falsos blockers = OK
|
||||||
|
- 1+ falsos blockers = AVISO (listar e recomendar correcção para `in_progress`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Check 19: Sessões com tokens excessivos (INC-12)
|
||||||
|
|
||||||
|
Previne "Prompt is too long" e token burn massivo. Monitoriza via usage_json dos heartbeats recentes.
|
||||||
|
|
||||||
|
Top agentes com maior consumo de tokens nas últimas 24h:
|
||||||
|
|
||||||
|
Invocar tool MCP: `mcp__paperclip__diag_heartbeat_token_usage(hours=24)`
|
||||||
|
|
||||||
|
Contagem de erros "Prompt is too long" activos (sinal imediato):
|
||||||
|
|
||||||
|
Invocar tool MCP: `mcp__paperclip__diag_prompt_too_long_errors(hours=24)`
|
||||||
|
|
||||||
|
- 0 erros = OK
|
||||||
|
- 1+ erros = CRITICO (forçar rotação de sessão)
|
||||||
|
|
||||||
|
**Forçar rotação de sessão (apaga histórico, fresh start):**
|
||||||
|
```sql
|
||||||
|
DELETE FROM agent_task_sessions
|
||||||
|
WHERE agent_id = '{{AGENT_ID}}'
|
||||||
|
AND company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f';
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Check 20: Routines presas in_progress >4h (INC-08)
|
||||||
|
|
||||||
|
Issues de routine que ficam `in_progress` sem actividade bloqueiam todos os futuros disparos da mesma routine (constraint `issues_open_routine_execution_uq`). A ligação issue→routine está em `routine_runs.linked_issue_id` (não existe `issues.routine_id`).
|
||||||
|
|
||||||
|
Invocar tool MCP: `mcp__paperclip__diag_stuck_routines(hours=4)`
|
||||||
|
|
||||||
|
- 0 = OK
|
||||||
|
- 1+ = CRITICO (routine bloqueada — cancelar a issue presa para desbloquear futuros disparos)
|
||||||
|
|
||||||
|
**Desbloquear routine (cancelar issue presa):**
|
||||||
|
```sql
|
||||||
|
UPDATE issues SET status = 'cancelled', updated_at = NOW()
|
||||||
|
WHERE identifier = '{{IDENTIFIER}}'
|
||||||
|
AND company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f';
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Check 21: Zombie parents — issues pai com sub-tasks todas concluídas (AP-09)
|
||||||
|
|
||||||
|
Issues pai que ficam abertas indefinidamente quando todas as sub-tasks estão `done` ou `cancelled`. Poluem o dashboard e impedem distinguir trabalho parado de trabalho já feito.
|
||||||
|
|
||||||
|
Invocar tool MCP: `mcp__paperclip__diag_zombie_parents`
|
||||||
|
|
||||||
|
- 0 = OK
|
||||||
|
- 1+ = AVISO (fechar manualmente ou alertar CEO para verificar e fechar)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Formato de output
|
||||||
|
|
||||||
|
```
|
||||||
|
## Clip Health — [data/hora]
|
||||||
|
|
||||||
|
| Check | Estado | Detalhe |
|
||||||
|
|-------|--------|---------|
|
||||||
|
| Servico | OK/CRITICO | N processos activos / stopped |
|
||||||
|
| POSIX shared memory | OK/AVISO/CRITICO | /dev/shm/PostgreSQL.* presente / em falta |
|
||||||
|
| Base de dados | OK/CRITICO | Xmb, N agentes, N issues |
|
||||||
|
| Heartbeats 24h | OK/AVISO/CRITICO | N falhas |
|
||||||
|
| Budget | OK/AVISO/CRITICO | [agente] a X% |
|
||||||
|
| Disco | OK/AVISO/CRITICO | X% livre (Xgb) |
|
||||||
|
| API Health | OK/AVISO/CRITICO | status:ok / board access / timeout |
|
||||||
|
| Gateway | OK/AVISO | responde / timeout |
|
||||||
|
| Refs orfas | OK/CRITICO | N budget_policies orfas |
|
||||||
|
| Instancias | OK/CRITICO | N processos na porta 310x |
|
||||||
|
| Porta/Tunnel | OK/CRITICO | tunnel:X servidor:Y |
|
||||||
|
| Permissoes bash | OK/CRITICO | N agentes sem dangerouslySkipPermissions |
|
||||||
|
| Heartbeats config | OK/AVISO | N agentes sem heartbeat enabled |
|
||||||
|
| Routine triggers | OK/CRITICO | N triggers com kind errado ou next_run_at NULL |
|
||||||
|
| Auto-assign noticias | OK/AVISO | N issues PUBLICAR NOTICIA sem assignee |
|
||||||
|
| Qualidade artigos | OK/AVISO/CRITICO | N artigos com acentos/links/titulos errados |
|
||||||
|
| Cron assign-copywriter | OK/CRITICO | activo / ausente |
|
||||||
|
| Pipeline noticias 24h | OK/AVISO/CRITICO | N routines, N pesquisas, N publicadas |
|
||||||
|
| Falsos blockers | OK/AVISO | N issues blocked sem impedimento real |
|
||||||
|
| Tokens excessivos | OK/AVISO/CRITICO | N agentes >500K tokens cached |
|
||||||
|
| Routines presas | OK/CRITICO | N issues rotina paradas >4h |
|
||||||
|
| Zombie parents | OK/AVISO | N issues pai com todas as subs concluídas |
|
||||||
|
|
||||||
|
**Score:** N/22 OK
|
||||||
|
|
||||||
|
### Detalhes (se existirem alertas)
|
||||||
|
[listar heartbeats falhados, budget alto, artigos com defeitos, pipeline parado]
|
||||||
|
|
||||||
|
### Accoes recomendadas
|
||||||
|
[listar accoes concretas para resolver alertas]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"2026-04-07","issue":"Check 1 usava systemctl que nunca existe (Paperclip corre via pnpm dev)","fix":"Substituir por ps aux | grep paperclip + check POSIX shared memory /dev/shm/PostgreSQL.*","source":"auto"}
|
||||||
|
{"date":"2026-04-07","issue":"Check 6 usava npx paperclipai doctor que não existe no projecto local","fix":"Substituir por curl localhost:3100/health — distingue: ok / board access (BD operacional) / timeout (servidor morto)","source":"auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
@@ -0,0 +1,184 @@
|
|||||||
|
---
|
||||||
|
name: clip-instructions
|
||||||
|
description: Editar e gerir AGENTS.md de agentes Paperclip — ver, editar, rever histórico de versões. O AGENTS.md é o "cérebro" do agente. Usar quando "clip instructions", "editar agente", "atualizar AGENTS.md", "mudar comportamento agente", "instruções agente".
|
||||||
|
context: fork
|
||||||
|
version: "1.0.0"
|
||||||
|
created: 2026-04-07
|
||||||
|
---
|
||||||
|
|
||||||
|
# /clip-instructions — Gerir AGENTS.md dos Agentes
|
||||||
|
|
||||||
|
O `AGENTS.md` é o ficheiro de instruções que define identidade, missão, comportamento e regras de cada agente. É injectado a cada heartbeat — editar o ficheiro tem efeito imediato no próximo run.
|
||||||
|
|
||||||
|
Aceita argumento: nome do agente (ex: `/clip-instructions CTO`).
|
||||||
|
|
||||||
|
## Constantes
|
||||||
|
|
||||||
|
```
|
||||||
|
BD: PGPASSWORD="paperclip" psql -h localhost -p 54329 -U paperclip -d paperclip
|
||||||
|
COMPANY_ID: ebe10308-efd7-453f-86ab-13e6fe84004f
|
||||||
|
```
|
||||||
|
|
||||||
|
## Passo 1: Encontrar agente e localizar AGENTS.md
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT id, name, role, title,
|
||||||
|
adapter_config->>'instructionsFilePath' as instructions_path,
|
||||||
|
adapter_config->>'instructionsRootPath' as instructions_root
|
||||||
|
FROM agents
|
||||||
|
WHERE company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
AND LOWER(name) LIKE LOWER('%{{NOME}}%');
|
||||||
|
```
|
||||||
|
|
||||||
|
Se `instructions_path` é NULL ou não começa com `/` → CRITICO (AGENTS.md não está a ser carregado).
|
||||||
|
|
||||||
|
## Passo 2: Ler ficheiro actual
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cat "{{instructions_path}}"
|
||||||
|
```
|
||||||
|
|
||||||
|
Apresentar conteúdo completo. Identificar secções:
|
||||||
|
- `## Identidade` — nome, papel, tipo, modelo, budget
|
||||||
|
- `## Missão` — objectivo principal
|
||||||
|
- `## Comportamento` — regras de actuação
|
||||||
|
- `## Skills` / `## MCPs` — ferramentas
|
||||||
|
- `## Heartbeat` — intervalo, checklist
|
||||||
|
- `## Equipa` — quem reporta a quem
|
||||||
|
|
||||||
|
## Passo 3: Modo de actuação
|
||||||
|
|
||||||
|
### Ver (sem edições pedidas)
|
||||||
|
Apresentar resumo estruturado das secções principais.
|
||||||
|
|
||||||
|
### Editar (utilizador pede alteração específica)
|
||||||
|
|
||||||
|
1. Ler ficheiro completo com Read
|
||||||
|
2. Identificar a secção a alterar
|
||||||
|
3. Propor a alteração ao utilizador ("Vou mudar X para Y — confirmas?")
|
||||||
|
4. Executar com Edit após confirmação
|
||||||
|
5. Verificar que o ficheiro ficou correcto
|
||||||
|
|
||||||
|
**Regras de edição segura:**
|
||||||
|
- Nunca reescrever o ficheiro completo — usar Edit para alterações cirúrgicas
|
||||||
|
- Preservar frontmatter YAML se existir
|
||||||
|
- Manter estrutura de secções existente
|
||||||
|
- Após editar, mostrar diff resumido das alterações
|
||||||
|
|
||||||
|
### Criar novo AGENTS.md (agente sem instruções)
|
||||||
|
|
||||||
|
Se `instructions_path` está definido mas o ficheiro não existe:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ls "{{instructions_path}}" 2>/dev/null || echo "NAO_EXISTE"
|
||||||
|
```
|
||||||
|
|
||||||
|
Criar directório se necessário:
|
||||||
|
```bash
|
||||||
|
mkdir -p "{{instructions_root}}"
|
||||||
|
```
|
||||||
|
|
||||||
|
Template mínimo para novo AGENTS.md:
|
||||||
|
```markdown
|
||||||
|
# {{NOME}}
|
||||||
|
|
||||||
|
## Identidade
|
||||||
|
|
||||||
|
- **Nome:** {{NOME}}
|
||||||
|
- **Papel:** {{ROLE}} — reporta ao {{SUPERVISOR}}
|
||||||
|
- **Tipo:** {{TIPO}} (executor/analyst/manager)
|
||||||
|
- **Modelo:** {{MODELO}}
|
||||||
|
- **Budget:** {{BUDGET}} cents/mês
|
||||||
|
|
||||||
|
## Missão
|
||||||
|
|
||||||
|
{{DESCRICAO_MISSAO}}
|
||||||
|
|
||||||
|
## Comportamento
|
||||||
|
|
||||||
|
### Regras
|
||||||
|
|
||||||
|
- **Foco** — executar apenas tarefas dentro do scope definido
|
||||||
|
- **Escalação** — problemas fora de scope → reportar ao supervisor
|
||||||
|
- **PT-PT** — sempre com acentuação correcta
|
||||||
|
|
||||||
|
## Heartbeat
|
||||||
|
|
||||||
|
- **Intervalo:** {{INTERVALO}}s
|
||||||
|
- **Checklist:** ver issues atribuídas, executar, reportar
|
||||||
|
|
||||||
|
## Equipa
|
||||||
|
|
||||||
|
- Reporta ao: {{SUPERVISOR}}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Passo 4: Verificar após edição
|
||||||
|
|
||||||
|
Confirmar que o Paperclip reconhece o ficheiro actualizado:
|
||||||
|
```bash
|
||||||
|
curl -s "http://localhost:3100/api/agents/{{AGENT_ID}}/instructions-bundle" \
|
||||||
|
-H "Authorization: Bearer $PAPERCLIP_API_KEY" | python3 -c "import sys,json; d=json.load(sys.stdin); print('OK' if d.get('content') else 'VAZIO')"
|
||||||
|
```
|
||||||
|
|
||||||
|
- OK = AGENTS.md carregado pelo servidor
|
||||||
|
- VAZIO / erro = path errado ou ficheiro não encontrado
|
||||||
|
|
||||||
|
## Casos especiais
|
||||||
|
|
||||||
|
### Actualizar model no AGENTS.md
|
||||||
|
|
||||||
|
Se o agente mudou de modelo (ex: gemini → claude), actualizar tanto o AGENTS.md como o `adapter_config`:
|
||||||
|
```sql
|
||||||
|
UPDATE agents
|
||||||
|
SET adapter_config = jsonb_set(adapter_config, '{model}', '"{{NOVO_MODELO}}"'::jsonb)
|
||||||
|
WHERE id = '{{AGENT_ID}}'
|
||||||
|
AND company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f';
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rever historial de versões (config_revisions)
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT cr.id, cr.created_at::timestamp(0), a.name as criado_por
|
||||||
|
FROM agent_config_revisions cr
|
||||||
|
LEFT JOIN agents a ON cr.created_by_agent_id = a.id
|
||||||
|
WHERE cr.agent_id = '{{AGENT_ID}}'
|
||||||
|
ORDER BY cr.created_at DESC
|
||||||
|
LIMIT 10;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rollback via API
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -s -X POST "http://localhost:3100/api/agents/{{AGENT_ID}}/config-revisions/{{REVISION_ID}}/rollback" \
|
||||||
|
-H "Authorization: Bearer $PAPERCLIP_API_KEY" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{}'
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Formato de output
|
||||||
|
|
||||||
|
```
|
||||||
|
## Instruções — {{NOME}} ({{role}})
|
||||||
|
|
||||||
|
**Ficheiro:** {{instructions_path}}
|
||||||
|
**Estado:** carregado / não encontrado / path inválido
|
||||||
|
|
||||||
|
### Resumo actual
|
||||||
|
**Missão:** [1 linha]
|
||||||
|
**Modelo:** {{model}} | **Budget:** {{budget}} cents | **Heartbeat:** {{intervalo}}s
|
||||||
|
**Regras principais:** [lista]
|
||||||
|
**Skills:** [lista ou "nenhuma"]
|
||||||
|
|
||||||
|
### Alterações efectuadas (se editou)
|
||||||
|
[diff resumido]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"2026-04-07","issue":"instructionsFilePath relativo — AGENTS.md não carregava após criação via SQL","fix":"Path deve ser sempre absoluto. Verificar com query adapter_config->>'instructionsFilePath' NOT LIKE '/%'","source":"auto"}
|
||||||
|
```
|
||||||
@@ -0,0 +1,200 @@
|
|||||||
|
---
|
||||||
|
name: clip-issue
|
||||||
|
description: Criar e gerir issues Paperclip — lançar objectivos ao CEO, ver progresso, comentar. Usar quando "clip issue", "criar issue", "lançar objectivo", "ver issues clip". Issues seguem cadeia de delegação hierárquica.
|
||||||
|
context: fork
|
||||||
|
---
|
||||||
|
|
||||||
|
# /clip-issue — Gerir Issues Paperclip
|
||||||
|
|
||||||
|
Modos: lista (sem args), criar (com titulo), ver (com ID).
|
||||||
|
|
||||||
|
## Constantes
|
||||||
|
|
||||||
|
```
|
||||||
|
BD: PGPASSWORD="paperclip" psql -h localhost -p 54329 -U paperclip -d paperclip
|
||||||
|
COMPANY_ID: ebe10308-efd7-453f-86ab-13e6fe84004f
|
||||||
|
API: http://localhost:3100/api
|
||||||
|
```
|
||||||
|
|
||||||
|
## Modo lista (sem argumentos)
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT i.id, i.title, i.status, i.priority, a.name as assignee, i.created_at
|
||||||
|
FROM issues i LEFT JOIN agents a ON i.assignee_agent_id = a.id
|
||||||
|
WHERE i.company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
AND i.status NOT IN ('done','cancelled')
|
||||||
|
ORDER BY
|
||||||
|
CASE i.priority WHEN 'critical' THEN 1 WHEN 'high' THEN 2 WHEN 'medium' THEN 3 ELSE 4 END,
|
||||||
|
i.status, i.created_at DESC;
|
||||||
|
```
|
||||||
|
|
||||||
|
Para ver concluidas tambem:
|
||||||
|
```sql
|
||||||
|
-- Adicionar: AND i.status IN ('done') AND i.updated_at > NOW() - INTERVAL '7 days'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Modo criar (com titulo)
|
||||||
|
|
||||||
|
### Passo 1: Obter CEO ID
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT id FROM agents
|
||||||
|
WHERE company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
AND name = 'CEO';
|
||||||
|
```
|
||||||
|
|
||||||
|
### Passo 2: Criar issue
|
||||||
|
|
||||||
|
Preferir API (quando JWT funciona):
|
||||||
|
```bash
|
||||||
|
curl -s -X POST "http://localhost:3100/api/companies/ebe10308-efd7-453f-86ab-13e6fe84004f/issues" \
|
||||||
|
-H "Authorization: Bearer $PAPERCLIP_API_KEY" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"title": "{{TITULO}}",
|
||||||
|
"description": "{{DESCRICAO}}",
|
||||||
|
"priority": "{{PRIORIDADE}}",
|
||||||
|
"assigneeAgentId": "{{CEO_ID}}"
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
Fallback via BD (OBRIGATORIO incluir identifier e issue_number):
|
||||||
|
```sql
|
||||||
|
-- Passo 2a: Obter proximo numero
|
||||||
|
SELECT issue_counter FROM companies WHERE id = 'ebe10308-efd7-453f-86ab-13e6fe84004f';
|
||||||
|
-- Guardar o valor como NEXT_NUM
|
||||||
|
|
||||||
|
-- Passo 2b: Criar issue COM identifier
|
||||||
|
INSERT INTO issues (id, company_id, title, description, priority, assignee_agent_id, status, identifier, issue_number, created_at, updated_at)
|
||||||
|
VALUES (
|
||||||
|
gen_random_uuid(),
|
||||||
|
'ebe10308-efd7-453f-86ab-13e6fe84004f',
|
||||||
|
'{{TITULO}}',
|
||||||
|
'{{DESCRICAO}}',
|
||||||
|
'{{PRIORIDADE}}',
|
||||||
|
'{{CEO_ID}}',
|
||||||
|
'todo',
|
||||||
|
'DES-{{NEXT_NUM}}',
|
||||||
|
{{NEXT_NUM}},
|
||||||
|
NOW(), NOW()
|
||||||
|
)
|
||||||
|
RETURNING id, identifier, title, status;
|
||||||
|
|
||||||
|
-- Passo 2c: Incrementar counter (CRITICO — nunca esquecer)
|
||||||
|
UPDATE companies SET issue_counter = {{NEXT_NUM}} + 1 WHERE id = 'ebe10308-efd7-453f-86ab-13e6fe84004f';
|
||||||
|
```
|
||||||
|
|
||||||
|
**NUNCA criar issues via SQL sem identifier e issue_number.** Causa bug de duplicate key que bloqueia toda a criacao de issues no Paperclip.
|
||||||
|
|
||||||
|
Confirmar titulo e prioridade com o utilizador antes de criar. Prioridades: critical, high, medium, low.
|
||||||
|
|
||||||
|
### Nota sobre delegação hierárquica
|
||||||
|
|
||||||
|
Issues criadas pelo Board (Emanuel) são sempre atribuídas ao CEO. O CEO delega pela cadeia:
|
||||||
|
- CEO cria sub-issue ao C-Level adequado
|
||||||
|
- C-Level cria sub-issue ao Director
|
||||||
|
- Director atribui ao especialista
|
||||||
|
|
||||||
|
Quando routines disparam, geram issues ao CEO que segue o mesmo fluxo. A cadeia está na descrição da routine (campo `description` começa com `CADEIA: CEO → ...`).
|
||||||
|
|
||||||
|
## Semântica de estados (referência rápida)
|
||||||
|
|
||||||
|
Ao criar, alterar ou interpretar estados de issues:
|
||||||
|
|
||||||
|
- **`todo`** — não iniciada, aguarda pickup
|
||||||
|
- **`in_progress`** — trabalho em curso, **incluindo aguardar sub-tasks delegadas**
|
||||||
|
- **`blocked`** — APENAS impedimento real (agente em erro, falta de permissão, dependência externa, aguarda decisão humana)
|
||||||
|
- **`done`** — concluída com resultado verificado
|
||||||
|
- **`cancelled`** — abandonada por decisão superior
|
||||||
|
|
||||||
|
**Regra INC-07:** `blocked` ≠ "delegué e estou à espera". Aguardar sub-task activa = `in_progress`. Se ao listar issues vires `blocked` sem impedimento real, alertar o utilizador.
|
||||||
|
|
||||||
|
## Modo ver (com ID ou titulo parcial)
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT i.*, a.name as assignee
|
||||||
|
FROM issues i LEFT JOIN agents a ON i.assignee_agent_id = a.id
|
||||||
|
WHERE i.company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
AND (i.id::text LIKE '%{{ARG}}%' OR LOWER(i.title) LIKE LOWER('%{{ARG}}%'));
|
||||||
|
```
|
||||||
|
|
||||||
|
Comentarios:
|
||||||
|
```sql
|
||||||
|
SELECT ic.body, ic.created_at, a.name as author
|
||||||
|
FROM issue_comments ic
|
||||||
|
LEFT JOIN agents a ON ic.author_agent_id = a.id
|
||||||
|
WHERE ic.issue_id = '{{ISSUE_ID}}'
|
||||||
|
ORDER BY ic.created_at ASC;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Modo comentar
|
||||||
|
|
||||||
|
```sql
|
||||||
|
INSERT INTO issue_comments (id, company_id, issue_id, author_user_id, body, created_at, updated_at)
|
||||||
|
VALUES (gen_random_uuid(), 'ebe10308-efd7-453f-86ab-13e6fe84004f', '{{ISSUE_ID}}', 'v1N5OccPn9DGq6iog7qW9nEvnXYFT3iO', '{{COMENTARIO}}', NOW(), NOW())
|
||||||
|
RETURNING id;
|
||||||
|
```
|
||||||
|
|
||||||
|
Nota: `author_user_id = 'v1N5OccPn9DGq6iog7qW9nEvnXYFT3iO'` (Emanuel) → comentário aparece como Board/humano no dashboard. Nunca usar `'board'` — não é um user_id válido.
|
||||||
|
|
||||||
|
## Modo checkout / release
|
||||||
|
|
||||||
|
Checkout reserva a issue para trabalho activo (sinaliza ao Paperclip que está em curso).
|
||||||
|
Release liberta a issue de volta a `todo`.
|
||||||
|
|
||||||
|
**Checkout via API:**
|
||||||
|
```bash
|
||||||
|
curl -s -X POST "http://localhost:3100/api/issues/{{ISSUE_ID}}/checkout" \
|
||||||
|
-H "Authorization: Bearer $PAPERCLIP_API_KEY" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"agentId": "{{AGENT_ID}}"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
**Release via API:**
|
||||||
|
```bash
|
||||||
|
curl -s -X POST "http://localhost:3100/api/issues/{{ISSUE_ID}}/release" \
|
||||||
|
-H "Authorization: Bearer $PAPERCLIP_API_KEY" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{}'
|
||||||
|
```
|
||||||
|
|
||||||
|
**Fallback via BD (se API falhar):**
|
||||||
|
```sql
|
||||||
|
-- Checkout manual
|
||||||
|
UPDATE issues SET status = 'in_progress', updated_at = NOW()
|
||||||
|
WHERE id = '{{ISSUE_ID}}'
|
||||||
|
AND company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
RETURNING identifier, title, status;
|
||||||
|
|
||||||
|
-- Release manual
|
||||||
|
UPDATE issues SET status = 'todo', updated_at = NOW()
|
||||||
|
WHERE id = '{{ISSUE_ID}}'
|
||||||
|
AND company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
RETURNING identifier, title, status;
|
||||||
|
```
|
||||||
|
|
||||||
|
**Nota:** O par checkout/release é importante para o pipeline do Paperclip — evita que dois agentes peguem na mesma issue em simultâneo.
|
||||||
|
|
||||||
|
## Formato de output
|
||||||
|
|
||||||
|
Adaptar ao modo. Para lista:
|
||||||
|
```
|
||||||
|
## Issues Clip — [data]
|
||||||
|
|
||||||
|
| # | Titulo | Status | Prioridade | Assignee |
|
||||||
|
...
|
||||||
|
|
||||||
|
Total: N abertas (N critical, N high, N medium, N low)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"2026-04-07","issue":"author_user_id = 'board' em comentários — não é user_id válido, comentário não aparecia no dashboard","fix":"Usar 'v1N5OccPn9DGq6iog7qW9nEvnXYFT3iO' (ID real de Emanuel no Paperclip)","source":"auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
@@ -0,0 +1,148 @@
|
|||||||
|
---
|
||||||
|
name: clip-org
|
||||||
|
description: Org chart Paperclip — hierarquia completa, reports, gaps por preencher. Usar quando "clip org", "organigrama", "hierarquia clip", "quem reporta a quem". Inclui modelo de governance e cadeias de delegação.
|
||||||
|
context: fork
|
||||||
|
---
|
||||||
|
|
||||||
|
# /clip-org — Org Chart Paperclip
|
||||||
|
|
||||||
|
Hierarquia completa da empresa Descomplicar no Paperclip.
|
||||||
|
|
||||||
|
## Constantes
|
||||||
|
|
||||||
|
```
|
||||||
|
BD: PGPASSWORD="paperclip" psql -h localhost -p 54329 -U paperclip -d paperclip
|
||||||
|
COMPANY_ID: ebe10308-efd7-453f-86ab-13e6fe84004f
|
||||||
|
```
|
||||||
|
|
||||||
|
## Procedimento
|
||||||
|
|
||||||
|
### Passo 1: Obter hierarquia completa
|
||||||
|
|
||||||
|
Invocar tool MCP: `mcp__paperclip__diag_agent_hierarchy`
|
||||||
|
|
||||||
|
### Passo 2: Construir arvore visual
|
||||||
|
|
||||||
|
Apresentar como arvore identada:
|
||||||
|
|
||||||
|
```
|
||||||
|
Emanuel (Board)
|
||||||
|
└── CEO (running)
|
||||||
|
├── COO (idle)
|
||||||
|
│ ├── [Dir. Suporte] — nao existe
|
||||||
|
│ └── Ticket Triage (idle)
|
||||||
|
├── CFO (idle)
|
||||||
|
│ ├── [Dir. Financeiro] — nao existe
|
||||||
|
│ ├── Finance Manager (idle)
|
||||||
|
│ └── Compliance Auditor (idle)
|
||||||
|
├── CTO (idle)
|
||||||
|
│ ├── [Dir. Infraestrutura] — nao existe
|
||||||
|
│ │ ├── CWP Server Manager (idle)
|
||||||
|
│ │ ├── EasyPanel Specialist (idle)
|
||||||
|
│ │ ├── Backup Specialist (idle)
|
||||||
|
│ │ └── Security Specialist (idle)
|
||||||
|
│ ├── [Dir. Desenvolvimento] — nao existe
|
||||||
|
│ │ └── ...
|
||||||
|
│ └── ...
|
||||||
|
└── ...
|
||||||
|
```
|
||||||
|
|
||||||
|
Nota: Directores de seccao (~16) podem ainda nao existir. Mostrar como `[Nome] — nao existe` para evidenciar gaps.
|
||||||
|
|
||||||
|
### Passo 3: Identificar gaps
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Agentes orfaos (sem reports_to, excepto CEO)
|
||||||
|
SELECT name, role, status FROM agents
|
||||||
|
WHERE company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
AND reports_to IS NULL
|
||||||
|
AND role != 'ceo';
|
||||||
|
```
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- C-Level sem subordinados directos
|
||||||
|
SELECT c.name, c.role,
|
||||||
|
(SELECT COUNT(*) FROM agents sub WHERE sub.reports_to = c.id) as subordinados
|
||||||
|
FROM agents c
|
||||||
|
WHERE c.company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
AND c.role IN ('coo','cfo','cto','cmo','cro','cgo','cdo')
|
||||||
|
ORDER BY subordinados ASC;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Passo 4: Estatisticas
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT
|
||||||
|
role,
|
||||||
|
COUNT(*) as total,
|
||||||
|
COUNT(CASE WHEN status = 'running' THEN 1 END) as running,
|
||||||
|
COUNT(CASE WHEN status = 'idle' THEN 1 END) as idle,
|
||||||
|
COUNT(CASE WHEN status = 'paused' THEN 1 END) as paused
|
||||||
|
FROM agents
|
||||||
|
WHERE company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
GROUP BY role
|
||||||
|
ORDER BY CASE role
|
||||||
|
WHEN 'ceo' THEN 1 WHEN 'coo' THEN 2 WHEN 'cfo' THEN 3
|
||||||
|
WHEN 'manager' THEN 4 WHEN 'engineer' THEN 5 ELSE 6 END;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Formato de output
|
||||||
|
|
||||||
|
```
|
||||||
|
## Org Chart Clip — [data]
|
||||||
|
|
||||||
|
[arvore visual]
|
||||||
|
|
||||||
|
### Estatisticas
|
||||||
|
| Camada | Total | Running | Idle | Paused |
|
||||||
|
...
|
||||||
|
|
||||||
|
### Gaps
|
||||||
|
- Directores em falta: [lista das 16 TFs sem Director]
|
||||||
|
- Agentes orfaos: [lista]
|
||||||
|
- C-Level sem subordinados: [lista]
|
||||||
|
|
||||||
|
### Cobertura
|
||||||
|
Directores: N/16 (N%)
|
||||||
|
TaskForces cobertas: [lista]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Referência de TaskForces esperadas
|
||||||
|
|
||||||
|
| TF | Director esperado | Reporta a |
|
||||||
|
|----|-------------------|-----------|
|
||||||
|
| TF-01 Estratégia | Dir. Estratégia | CGO |
|
||||||
|
| TF-02 Operações | Dir. Operações | COO |
|
||||||
|
| TF-03 Financeiro | Dir. Financeiro | CFO |
|
||||||
|
| TF-04 Infraestrutura | Dir. Infraestrutura | CTO |
|
||||||
|
| TF-05 Desenvolvimento | Dir. Desenvolvimento | CTO |
|
||||||
|
| TF-06 Automação | Dir. Automação | CTO |
|
||||||
|
| TF-07 IA | Dir. IA | CGO |
|
||||||
|
| TF-08 Design | Dir. Design | CMO |
|
||||||
|
| TF-09 Web | Dir. Web | CMO |
|
||||||
|
| TF-10 Vídeo | Dir. Vídeo | CMO |
|
||||||
|
| TF-11 SEO | Dir. SEO | CMO |
|
||||||
|
| TF-12 Conteúdo | Dir. Conteúdo | CMO |
|
||||||
|
| TF-13 Social | Dir. Social | CMO |
|
||||||
|
| TF-14 Publicidade | Dir. Publicidade | CMO |
|
||||||
|
| TF-15 Comercial | Dir. Comercial | CRO |
|
||||||
|
| TF-16 Suporte | Dir. Suporte | COO |
|
||||||
|
|
||||||
|
## Modelo de governance
|
||||||
|
|
||||||
|
Todas as routines são atribuídas ao CEO que delega pela cadeia hierárquica:
|
||||||
|
`Routine → CEO → C-Level → Director → Especialista`
|
||||||
|
|
||||||
|
Cada nível adiciona contexto antes de delegar e sintetiza resultados antes de reportar acima. Ver `/clip-routine` para detalhes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
@@ -0,0 +1,349 @@
|
|||||||
|
---
|
||||||
|
name: clip-routine
|
||||||
|
description: Gerir routines Paperclip — listar crons activos, ver execuções, criar/editar routines. Usar quando "clip routine", "routines clip", "crons paperclip", "automações clip".
|
||||||
|
context: fork
|
||||||
|
---
|
||||||
|
|
||||||
|
# /clip-routine — Gerir Routines Paperclip
|
||||||
|
|
||||||
|
## Modelo de governance (desde 29-03-2026)
|
||||||
|
|
||||||
|
**Todas as routines são atribuídas ao CEO.** O CEO delega pela cadeia hierárquica:
|
||||||
|
|
||||||
|
```
|
||||||
|
Routine (cron trigger) → CEO avalia e delega
|
||||||
|
→ C-Level adiciona contexto departamental
|
||||||
|
→ Director coordena e atribui
|
||||||
|
→ Especialista executa
|
||||||
|
→ Resultado sobe a cadeia com síntese progressiva
|
||||||
|
```
|
||||||
|
|
||||||
|
Cada routine tem no campo `description` a cadeia de delegação (ex: `CADEIA: CEO → CTO → Dir. Infraestrutura → Backup Specialist`).
|
||||||
|
|
||||||
|
**Regras:**
|
||||||
|
- Novas routines devem ser SEMPRE atribuídas ao CEO
|
||||||
|
- A cadeia de delegação deve estar explícita na descrição
|
||||||
|
- Nunca atribuir routines directamente a especialistas — quebra a visibilidade hierárquica
|
||||||
|
|
||||||
|
## Dois tipos de periodicidade
|
||||||
|
|
||||||
|
1. **Heartbeats** — intervalos configurados via `runtime_config` dos agentes (quando acordam)
|
||||||
|
2. **Routines** — tarefas periódicas via tabela `routines` + `routine_triggers` com cron (o que fazem ao acordar)
|
||||||
|
|
||||||
|
## Constantes
|
||||||
|
|
||||||
|
```
|
||||||
|
BD: PGPASSWORD="paperclip" psql -h localhost -p 54329 -U paperclip -d paperclip
|
||||||
|
COMPANY_ID: ebe10308-efd7-453f-86ab-13e6fe84004f
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tiers de heartbeat
|
||||||
|
|
||||||
|
| Tier | Intervalo | Uso |
|
||||||
|
|------|-----------|-----|
|
||||||
|
| 1 | 1h (3600s) | CEO, agentes criticos |
|
||||||
|
| 2 | 2h (7200s) | C-Level activos |
|
||||||
|
| 3 | 4h (14400s) | Directores |
|
||||||
|
| 4 | 6h (21600s) | Especialistas com rotina |
|
||||||
|
| 5 | on-demand | Especialistas reactivos (sem timer) |
|
||||||
|
|
||||||
|
## Modo lista (sem argumentos)
|
||||||
|
|
||||||
|
Listar agentes com heartbeat configurado:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT name, role, status,
|
||||||
|
runtime_config->'heartbeat'->>'enabled' as hb_enabled,
|
||||||
|
runtime_config->'heartbeat'->>'intervalSec' as hb_interval,
|
||||||
|
last_heartbeat_at
|
||||||
|
FROM agents
|
||||||
|
WHERE company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
AND runtime_config::text != '{}'
|
||||||
|
AND runtime_config->'heartbeat' IS NOT NULL
|
||||||
|
ORDER BY (runtime_config->'heartbeat'->>'intervalSec')::int ASC NULLS LAST;
|
||||||
|
```
|
||||||
|
|
||||||
|
Complementar com contagem de execucoes recentes:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT a.name,
|
||||||
|
COUNT(CASE WHEN hr.status = 'succeeded' THEN 1 END) as ok_24h,
|
||||||
|
COUNT(CASE WHEN hr.status = 'failed' THEN 1 END) as fail_24h
|
||||||
|
FROM agents a
|
||||||
|
LEFT JOIN heartbeat_runs hr ON hr.agent_id = a.id
|
||||||
|
AND hr.started_at > NOW() - INTERVAL '24 hours'
|
||||||
|
WHERE a.company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
AND a.runtime_config->'heartbeat' IS NOT NULL
|
||||||
|
GROUP BY a.name
|
||||||
|
ORDER BY a.name;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Modo ver (com nome de agente)
|
||||||
|
|
||||||
|
Ultimas 10 execucoes de um agente:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT hr.status, hr.started_at, hr.finished_at, LEFT(hr.error, 80) as erro
|
||||||
|
FROM heartbeat_runs hr
|
||||||
|
JOIN agents a ON hr.agent_id = a.id
|
||||||
|
WHERE a.company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
AND LOWER(a.name) LIKE LOWER('%{{NOME}}%')
|
||||||
|
ORDER BY hr.started_at DESC LIMIT 10;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Modo criar/editar (configurar heartbeat)
|
||||||
|
|
||||||
|
### Activar heartbeat
|
||||||
|
|
||||||
|
```sql
|
||||||
|
UPDATE agents SET runtime_config = jsonb_set(
|
||||||
|
COALESCE(runtime_config, '{}'::jsonb),
|
||||||
|
'{heartbeat}',
|
||||||
|
'{"enabled": true, "intervalSec": {{INTERVALO}}, "cooldownSec": 10, "wakeOnDemand": true, "maxConcurrentRuns": 1}'::jsonb
|
||||||
|
)
|
||||||
|
WHERE name = '{{NOME}}'
|
||||||
|
AND company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
RETURNING name, runtime_config;
|
||||||
|
```
|
||||||
|
|
||||||
|
Confirmar sempre com o utilizador:
|
||||||
|
- Nome do agente
|
||||||
|
- Intervalo (sugerir tier adequado ao role)
|
||||||
|
- wakeOnDemand (true para a maioria)
|
||||||
|
|
||||||
|
### Desactivar heartbeat
|
||||||
|
|
||||||
|
```sql
|
||||||
|
UPDATE agents SET runtime_config = jsonb_set(
|
||||||
|
runtime_config,
|
||||||
|
'{heartbeat,enabled}',
|
||||||
|
'false'::jsonb
|
||||||
|
)
|
||||||
|
WHERE name = '{{NOME}}'
|
||||||
|
AND company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
RETURNING name, runtime_config;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Alterar intervalo
|
||||||
|
|
||||||
|
```sql
|
||||||
|
UPDATE agents SET runtime_config = jsonb_set(
|
||||||
|
runtime_config,
|
||||||
|
'{heartbeat,intervalSec}',
|
||||||
|
'{{INTERVALO}}'::jsonb
|
||||||
|
)
|
||||||
|
WHERE name = '{{NOME}}'
|
||||||
|
AND company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
RETURNING name, runtime_config;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Routines do projecto (tabela routines)
|
||||||
|
|
||||||
|
Alem dos heartbeats por agente, existem routines organizadas por projecto com cron triggers.
|
||||||
|
|
||||||
|
**Estado actual:** 5 routines activas no Paperclip. 9 routines anteriores foram migradas para workflows n8n em https://automator.descomplicar.pt.
|
||||||
|
|
||||||
|
**5 routines Paperclip:**
|
||||||
|
- Auditoria processos e compliance (0 10 * * *)
|
||||||
|
- Execução tarefas AikTop (*/30 * * * *)
|
||||||
|
- Reconciliação financeira diária (0 8 * * *)
|
||||||
|
- Varredura inteligência competitiva (0 11 * * *)
|
||||||
|
- Monitorização workflows n8n (0 10,18 * * *) — atribuída ao COO
|
||||||
|
|
||||||
|
### Listar routines activas
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT r.title, r.status, r.priority, a.name as assignee,
|
||||||
|
rt.cron_expression, rt.enabled, rt.next_run_at
|
||||||
|
FROM routines r
|
||||||
|
LEFT JOIN agents a ON r.assignee_agent_id = a.id
|
||||||
|
LEFT JOIN routine_triggers rt ON rt.routine_id = r.id
|
||||||
|
WHERE r.company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
ORDER BY r.title;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ver execucoes de uma routine
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT rr.status, rr.triggered_at, rr.completed_at, LEFT(rr.error, 80) as erro
|
||||||
|
FROM routine_runs rr
|
||||||
|
JOIN routines r ON rr.routine_id = r.id
|
||||||
|
WHERE r.company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
AND LOWER(r.title) LIKE LOWER('%{{TITULO}}%')
|
||||||
|
ORDER BY rr.triggered_at DESC LIMIT 10;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Modo criar routine (nova)
|
||||||
|
|
||||||
|
### Passo 1: Obter CEO ID
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT id FROM agents
|
||||||
|
WHERE name = 'CEO' AND company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f';
|
||||||
|
```
|
||||||
|
|
||||||
|
### Passo 2: Obter projecto
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT id, name FROM projects
|
||||||
|
WHERE company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f';
|
||||||
|
```
|
||||||
|
|
||||||
|
### Passo 3: Criar routine (SEMPRE atribuída ao CEO)
|
||||||
|
|
||||||
|
```sql
|
||||||
|
INSERT INTO routines (id, company_id, project_id, title, description, assignee_agent_id, priority, status, created_at, updated_at)
|
||||||
|
VALUES (
|
||||||
|
gen_random_uuid(),
|
||||||
|
'ebe10308-efd7-453f-86ab-13e6fe84004f',
|
||||||
|
'{{PROJECT_ID}}',
|
||||||
|
'{{TITULO}}',
|
||||||
|
'CADEIA: CEO → {{C_LEVEL}} → {{DIRECTOR}} → {{ESPECIALISTA}}. {{DESCRICAO_TAREFA}}',
|
||||||
|
'{{CEO_ID}}',
|
||||||
|
'{{PRIORIDADE}}',
|
||||||
|
'active',
|
||||||
|
NOW(), NOW()
|
||||||
|
)
|
||||||
|
RETURNING id, title;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Passo 4: Criar cron trigger
|
||||||
|
|
||||||
|
**CRITICO:** O kind DEVE ser `'schedule'` (nao `'cron'`). O scheduler do Paperclip so processa triggers com `kind = 'schedule'`. Tambem e OBRIGATORIO popular `next_run_at` — sem ele o scheduler ignora o trigger.
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Calcular next_run_at antes de inserir
|
||||||
|
-- Para crons diarios (ex: 0 8 * * *), usar:
|
||||||
|
-- (CURRENT_DATE + 1) AT TIME ZONE 'Europe/Lisbon' + INTERVAL '{{HORA}} hours'
|
||||||
|
-- Para crons recorrentes (ex: 0 */4 * * *), calcular proximo slot
|
||||||
|
|
||||||
|
INSERT INTO routine_triggers (id, company_id, routine_id, kind, label, enabled, cron_expression, timezone, next_run_at, created_at, updated_at)
|
||||||
|
VALUES (
|
||||||
|
gen_random_uuid(),
|
||||||
|
'ebe10308-efd7-453f-86ab-13e6fe84004f',
|
||||||
|
'{{ROUTINE_ID}}',
|
||||||
|
'schedule',
|
||||||
|
'{{LABEL}}',
|
||||||
|
true,
|
||||||
|
'{{CRON_EXPRESSION}}',
|
||||||
|
'Europe/Lisbon',
|
||||||
|
{{NEXT_RUN_AT}},
|
||||||
|
NOW(), NOW()
|
||||||
|
)
|
||||||
|
RETURNING id, cron_expression, next_run_at;
|
||||||
|
```
|
||||||
|
|
||||||
|
**Exemplos de next_run_at:**
|
||||||
|
- `0 8 * * *` → `(CURRENT_DATE + 1) AT TIME ZONE 'Europe/Lisbon' + INTERVAL '8 hours'`
|
||||||
|
- `0 */6 * * *` → `date_trunc('hour', NOW()) + INTERVAL '6 hours'`
|
||||||
|
- `0 9 * * 1` → proxima segunda-feira as 09h
|
||||||
|
|
||||||
|
Confirmar sempre com o utilizador: título, cadeia, cron, projecto.
|
||||||
|
|
||||||
|
### Diagnostico: routines que nao disparam
|
||||||
|
|
||||||
|
Se routines nao disparam, verificar:
|
||||||
|
|
||||||
|
Invocar tool MCP: `mcp__paperclip__diag_routine_triggers_broken`
|
||||||
|
|
||||||
|
Corrigir com:
|
||||||
|
```sql
|
||||||
|
UPDATE routine_triggers SET kind = 'schedule', next_run_at = {{NEXT_RUN}}, updated_at = NOW()
|
||||||
|
WHERE id = '{{TRIGGER_ID}}';
|
||||||
|
```
|
||||||
|
|
||||||
|
### Diagnostico: pipeline noticias
|
||||||
|
|
||||||
|
Se noticias nao estao a ser publicadas, verificar esta cadeia:
|
||||||
|
|
||||||
|
```
|
||||||
|
1. Routine triggers → kind='schedule'? next_run_at populado? last_fired_at recente?
|
||||||
|
2. CEO heartbeat → apanha a issue da routine? delega ao CGO?
|
||||||
|
3. CGO → delega ao Intelligence Researcher?
|
||||||
|
4. Intelligence Researcher → cria issues PUBLICAR NOTICIA? (assignee fica NULL — normal)
|
||||||
|
5. Cron assign-copywriter.sh → atribui ao Copywriter a cada 5 min?
|
||||||
|
6. Copywriter → acorda com wakeOnDemand? publica no WordPress?
|
||||||
|
7. Artigo publicado → acentuacao OK? links com aspas? titulo normalizado?
|
||||||
|
```
|
||||||
|
|
||||||
|
Verificar ponto a ponto com:
|
||||||
|
```sql
|
||||||
|
-- Ponto 1: triggers
|
||||||
|
SELECT r.title, rt.kind, rt.next_run_at, rt.last_fired_at
|
||||||
|
FROM routine_triggers rt JOIN routines r ON rt.routine_id = r.id
|
||||||
|
WHERE r.title LIKE 'Pesquisa diaria%noticias%' ORDER BY rt.cron_expression;
|
||||||
|
|
||||||
|
-- Ponto 4-5: issues PUBLICAR NOTICIA
|
||||||
|
SELECT i.title, i.status, a.name as assignee, i.created_at
|
||||||
|
FROM issues i LEFT JOIN agents a ON i.assignee_agent_id = a.id
|
||||||
|
WHERE i.title LIKE 'PUBLICAR NOTICIA%' AND i.created_at > NOW() - INTERVAL '24 hours'
|
||||||
|
ORDER BY i.created_at DESC;
|
||||||
|
|
||||||
|
-- Ponto 6: Copywriter runs
|
||||||
|
SELECT hr.status, hr.started_at FROM heartbeat_runs hr
|
||||||
|
JOIN agents a ON hr.agent_id = a.id WHERE a.name = 'Copywriter'
|
||||||
|
AND hr.started_at > NOW() - INTERVAL '24 hours' ORDER BY hr.started_at DESC;
|
||||||
|
|
||||||
|
-- Ponto 7: artigos publicados (via SSH server)
|
||||||
|
-- wp --allow-root post list --category=noticias --date_query='{"after":"1 day ago"}' --fields=ID,post_title
|
||||||
|
```
|
||||||
|
|
||||||
|
## Cadeias de delegação por área
|
||||||
|
|
||||||
|
| Área | Cadeia |
|
||||||
|
|------|--------|
|
||||||
|
| Infraestrutura/WP/Backups/SSL | CEO → CTO → Dir. Infraestrutura → Especialista |
|
||||||
|
| Desenvolvimento/MCPs/N8N | CEO → CTO → Dir. Desenvolvimento/Automação → Especialista |
|
||||||
|
| Email/Tickets/Processos | CEO → COO → Dir. Suporte/Operações → Especialista |
|
||||||
|
| Financeiro/Facturação | CEO → CFO → Dir. Financeiro → Finance Manager |
|
||||||
|
| Marketing/SEO/Conteúdo/Ads | CEO → CMO → Dir. relevante → Especialista |
|
||||||
|
| Vendas/Leads/Propostas | CEO → CRO → Dir. Comercial → Especialista |
|
||||||
|
| Inteligência/Pesquisa | CEO → CGO → Dir. IA/Estratégia → Especialista |
|
||||||
|
| Analytics/Dados | CEO → CDO → Analytics Agent |
|
||||||
|
|
||||||
|
## Formato de output
|
||||||
|
|
||||||
|
Para modo lista (heartbeats):
|
||||||
|
```
|
||||||
|
## Heartbeats Clip — [data]
|
||||||
|
|
||||||
|
| Agente | Tier | Intervalo | Enabled | Último HB | OK 24h | Fail 24h |
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Para modo lista (routines):
|
||||||
|
```
|
||||||
|
## Routines Clip — [data]
|
||||||
|
|
||||||
|
| Título | Cron | Assignee | Cadeia | Próximo run | Enabled |
|
||||||
|
...
|
||||||
|
|
||||||
|
Total: 5 routines activas no Paperclip (4 atribuídas ao CEO, 1 ao COO) + 9 migradas para n8n
|
||||||
|
```
|
||||||
|
|
||||||
|
Para modo ver:
|
||||||
|
```
|
||||||
|
## Routine: {{NOME}}
|
||||||
|
|
||||||
|
**Cadeia:** {{cadeia_delegação}}
|
||||||
|
**Cron:** {{cron}} | **Enabled:** {{enabled}}
|
||||||
|
**Último trigger:** {{last_triggered_at}}
|
||||||
|
|
||||||
|
### Últimas 10 execuções
|
||||||
|
| Status | Triggered | Completed | Erro |
|
||||||
|
...
|
||||||
|
|
||||||
|
Taxa sucesso 24h: N/N (N%)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
@@ -0,0 +1,292 @@
|
|||||||
|
---
|
||||||
|
name: clip-skill
|
||||||
|
description: Gerir company skills no Paperclip — listar, instalar, atribuir a agentes, auditar cobertura. Usar quando "clip skill", "skills clip", "instalar skill", "atribuir skill", "skills paperclip".
|
||||||
|
context: fork
|
||||||
|
---
|
||||||
|
|
||||||
|
# /clip-skill — Gerir Company Skills Paperclip
|
||||||
|
|
||||||
|
Gerir skills instaladas na empresa Descomplicar no Paperclip. Instalar, atribuir, remover e auditar.
|
||||||
|
|
||||||
|
## Constantes
|
||||||
|
|
||||||
|
```
|
||||||
|
BD: PGPASSWORD="paperclip" psql -h localhost -p 54329 -U paperclip -d paperclip
|
||||||
|
COMPANY_ID: ebe10308-efd7-453f-86ab-13e6fe84004f
|
||||||
|
API: http://localhost:3100/api
|
||||||
|
SKILLS_CC: ~/.claude/plugins/marketplaces/descomplicar-plugins/
|
||||||
|
```
|
||||||
|
|
||||||
|
## Contexto técnico
|
||||||
|
|
||||||
|
Skills no Paperclip funcionam como **injecção de contexto em runtime**:
|
||||||
|
- O conteúdo do SKILL.md é injectado como contexto adicional ao agente a cada heartbeat
|
||||||
|
- Não há instalação permanente — a skill é lida do ficheiro a cada execução
|
||||||
|
- Atribuição é por agente via `adapter_config.paperclipSkillSync.desiredSkills` (array de slugs)
|
||||||
|
- Skills instaladas na empresa ficam em `company_skills` — só as atribuídas ao agente são injectadas
|
||||||
|
|
||||||
|
**Distribuição actual de adapters:**
|
||||||
|
- 1 agente (CEO): `gemini_local` com `gemini-2.5-pro`
|
||||||
|
- 50 agentes: `gemini_local` com `gemini-2.5-flash`
|
||||||
|
- 13 agentes: `opencode_local` com `openrouter/x-ai/grok-4.1-fast`
|
||||||
|
- Agentes analyst/passive (ex: Reality Checker): `process` com `claude-sonnet-4-6` (sem heartbeat, sem skills)
|
||||||
|
|
||||||
|
O adapter `claude_local` já não é usado para agentes heartbeat.
|
||||||
|
|
||||||
|
## Modo lista (sem argumentos)
|
||||||
|
|
||||||
|
### Skills instaladas na empresa
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT name, slug, key, source_type, trust_level, compatibility,
|
||||||
|
created_at::date as instalada
|
||||||
|
FROM company_skills
|
||||||
|
WHERE company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
ORDER BY name;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Agentes com skills atribuidas
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT name, role, status,
|
||||||
|
adapter_config->'paperclipSkillSync'->'desiredSkills' as skills
|
||||||
|
FROM agents
|
||||||
|
WHERE company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
AND adapter_config::text LIKE '%paperclipSkillSync%'
|
||||||
|
ORDER BY name;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Resumo
|
||||||
|
|
||||||
|
Apresentar:
|
||||||
|
```
|
||||||
|
## Skills Clip — [data]
|
||||||
|
|
||||||
|
**Empresa:** N skills instaladas (N locais, N built-in)
|
||||||
|
**Agentes:** N com skills atribuidas / 62 total
|
||||||
|
|
||||||
|
### Skills instaladas
|
||||||
|
| Nome | Key | Fonte | Trust | Compativel |
|
||||||
|
...
|
||||||
|
|
||||||
|
### Agentes com skills
|
||||||
|
| Agente | Role | Skills |
|
||||||
|
...
|
||||||
|
|
||||||
|
### Agentes sem skills (top 10 por relevancia)
|
||||||
|
[listar agentes com routines activas mas sem skills]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Modo instalar (com path ou key)
|
||||||
|
|
||||||
|
### Instalar skill de path local
|
||||||
|
|
||||||
|
Argumento: path absoluto para pasta com SKILL.md.
|
||||||
|
|
||||||
|
Verificar primeiro que existe SKILL.md:
|
||||||
|
```bash
|
||||||
|
ls {{PATH}}/SKILL.md 2>/dev/null && head -5 {{PATH}}/SKILL.md
|
||||||
|
```
|
||||||
|
|
||||||
|
Instalar via API:
|
||||||
|
```bash
|
||||||
|
curl -s -X POST "http://localhost:3100/api/companies/ebe10308-efd7-453f-86ab-13e6fe84004f/skills/import" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-H "Authorization: Bearer $PAPERCLIP_API_KEY" \
|
||||||
|
-d '{"source": "{{PATH}}"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
Se API falha (auth), inserir directamente na BD:
|
||||||
|
```sql
|
||||||
|
-- Ler frontmatter do SKILL.md para obter name e description
|
||||||
|
-- Depois inserir:
|
||||||
|
INSERT INTO company_skills (id, company_id, key, slug, name, description, markdown, source_type, source_locator, trust_level, compatibility, file_inventory, created_at, updated_at)
|
||||||
|
VALUES (
|
||||||
|
gen_random_uuid(),
|
||||||
|
'ebe10308-efd7-453f-86ab-13e6fe84004f',
|
||||||
|
'descomplicar/{{PLUGIN}}/{{SKILL_NAME}}',
|
||||||
|
'{{SKILL_NAME}}',
|
||||||
|
'{{NAME_FROM_FRONTMATTER}}',
|
||||||
|
'{{DESCRIPTION_FROM_FRONTMATTER}}',
|
||||||
|
'{{FULL_SKILL_MD_CONTENT}}',
|
||||||
|
'local_path',
|
||||||
|
'{{PATH}}',
|
||||||
|
'markdown_only',
|
||||||
|
'compatible',
|
||||||
|
'[]'::jsonb,
|
||||||
|
NOW(), NOW()
|
||||||
|
)
|
||||||
|
RETURNING id, name, slug;
|
||||||
|
```
|
||||||
|
|
||||||
|
Confirmar com o utilizador antes de instalar. Mostrar name e description do SKILL.md.
|
||||||
|
|
||||||
|
### Instalar skill do marketplace CC
|
||||||
|
|
||||||
|
Argumento: nome da skill no formato `plugin/skill` (ex: `crm-ops/crm`).
|
||||||
|
|
||||||
|
Resolver path:
|
||||||
|
```bash
|
||||||
|
SKILL_PATH="$HOME/.claude/plugins/marketplaces/descomplicar-plugins/{{PLUGIN}}/skills/{{SKILL}}"
|
||||||
|
ls "$SKILL_PATH/SKILL.md" 2>/dev/null && head -10 "$SKILL_PATH/SKILL.md"
|
||||||
|
```
|
||||||
|
|
||||||
|
Depois seguir o fluxo de instalacao por path local.
|
||||||
|
|
||||||
|
### Instalar em massa (com filtro de plugin)
|
||||||
|
|
||||||
|
Argumento: nome do plugin (ex: `crm-ops`).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
find "$HOME/.claude/plugins/marketplaces/descomplicar-plugins/{{PLUGIN}}/skills/" -name "SKILL.md" -exec dirname {} \;
|
||||||
|
```
|
||||||
|
|
||||||
|
Listar todas as skills encontradas com name e description. Pedir confirmacao antes de instalar cada uma.
|
||||||
|
|
||||||
|
## Modo atribuir (skill a agente)
|
||||||
|
|
||||||
|
### Atribuir via API
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -s -X POST "http://localhost:3100/api/agents/{{AGENT_ID}}/skills/sync" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-H "Authorization: Bearer $PAPERCLIP_API_KEY" \
|
||||||
|
-d '{"desiredSkills": [{{SKILLS_ARRAY}}]}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Atribuir via BD (fallback)
|
||||||
|
|
||||||
|
```sql
|
||||||
|
UPDATE agents SET adapter_config = jsonb_set(
|
||||||
|
COALESCE(adapter_config, '{}'::jsonb),
|
||||||
|
'{paperclipSkillSync}',
|
||||||
|
jsonb_build_object('desiredSkills', '{{SKILLS_JSON_ARRAY}}'::jsonb)
|
||||||
|
)
|
||||||
|
WHERE id = '{{AGENT_ID}}'
|
||||||
|
AND company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
RETURNING name, adapter_config->'paperclipSkillSync'->'desiredSkills';
|
||||||
|
```
|
||||||
|
|
||||||
|
Confirmar sempre:
|
||||||
|
- Nome do agente
|
||||||
|
- Skills a atribuir (mostrar name de cada)
|
||||||
|
- Se vai substituir ou adicionar a skills existentes
|
||||||
|
|
||||||
|
### Atribuir por departamento (batch)
|
||||||
|
|
||||||
|
Argumento: nome do C-Level ou Director.
|
||||||
|
|
||||||
|
1. Obter agentes subordinados:
|
||||||
|
```sql
|
||||||
|
SELECT id, name, role FROM agents
|
||||||
|
WHERE reports_to = '{{MANAGER_ID}}'
|
||||||
|
AND company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f';
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Listar skills recomendadas para o departamento
|
||||||
|
3. Confirmar com utilizador
|
||||||
|
4. Aplicar a cada agente
|
||||||
|
|
||||||
|
## Modo remover
|
||||||
|
|
||||||
|
### Remover skill de agente
|
||||||
|
|
||||||
|
Ler skills actuais, filtrar a removida, escrever de volta:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Ler
|
||||||
|
SELECT adapter_config->'paperclipSkillSync'->'desiredSkills' as skills
|
||||||
|
FROM agents WHERE id = '{{AGENT_ID}}';
|
||||||
|
|
||||||
|
-- Actualizar (remover skill especifica)
|
||||||
|
-- Construir novo array sem a skill removida e usar o UPDATE do modo atribuir
|
||||||
|
```
|
||||||
|
|
||||||
|
### Desinstalar skill da empresa
|
||||||
|
|
||||||
|
```sql
|
||||||
|
DELETE FROM company_skills
|
||||||
|
WHERE company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
AND slug = '{{SLUG}}'
|
||||||
|
RETURNING name, slug;
|
||||||
|
```
|
||||||
|
|
||||||
|
Avisar: isto remove a skill de todos os agentes que a referenciam. Confirmar sempre.
|
||||||
|
|
||||||
|
## Modo auditar
|
||||||
|
|
||||||
|
### Cobertura de skills
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Agentes com routines activas mas sem skills
|
||||||
|
SELECT a.name, a.role, r.title as routine
|
||||||
|
FROM agents a
|
||||||
|
JOIN routines r ON r.assignee_agent_id = a.id
|
||||||
|
WHERE a.company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
AND r.status = 'active'
|
||||||
|
AND (a.adapter_config->'paperclipSkillSync' IS NULL
|
||||||
|
OR a.adapter_config::text NOT LIKE '%paperclipSkillSync%')
|
||||||
|
ORDER BY a.name;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Mapeamento recomendado (plugin CC → departamento Clip)
|
||||||
|
|
||||||
|
| Plugin CC | Agentes-alvo | Skills prioritarias |
|
||||||
|
|-----------|-------------|-------------------|
|
||||||
|
| core-tools | Todos | _core, quality-validator |
|
||||||
|
| crm-ops | CRO, Dir. Comercial, Sales Manager, Lead Qualifier | crm, desk, lead-approach, orcamento |
|
||||||
|
| gestao | COO, Dir. Operacoes, Project Manager | today, worklog, knowledge, tasks-overview |
|
||||||
|
| infraestrutura | CTO, Dir. Infraestrutura, Infra Check, Backup Specialist | gateway-check, backup, easypanel, cwp-server |
|
||||||
|
| marketing | CMO, Dir. SEO, Dir. Publicidade | seo-audit, seo-technical, ppc |
|
||||||
|
| wordpress | Dir. Web, WP Update | wp-dev, wp-performance, wp-cli |
|
||||||
|
| dev-tools | Dir. Desenvolvimento, Development Lead | dev-helper, pdf, docx |
|
||||||
|
| automacao | Dir. Automacao | n8n, automation-lead |
|
||||||
|
| negocio | CFO, CGO, Finance Manager | finance, research, saas |
|
||||||
|
| perfex-dev | Dir. Desenvolvimento | perfex-module |
|
||||||
|
|
||||||
|
### Comparacao CC vs Clip
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Skills CC disponiveis (contar no filesystem)
|
||||||
|
-- vs skills instaladas no Clip
|
||||||
|
SELECT
|
||||||
|
(SELECT COUNT(*) FROM company_skills WHERE company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f') as instaladas_clip;
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
find ~/.claude/plugins/marketplaces/descomplicar-plugins/ -name "SKILL.md" | wc -l
|
||||||
|
```
|
||||||
|
|
||||||
|
Apresentar:
|
||||||
|
```
|
||||||
|
### Auditoria Skills — [data]
|
||||||
|
|
||||||
|
**CC:** N skills disponiveis em 15 plugins
|
||||||
|
**Clip:** N instaladas (N%)
|
||||||
|
**Agentes com skills:** N/62 (N%)
|
||||||
|
**Agentes com routines sem skills:** N (ATENCAO)
|
||||||
|
|
||||||
|
### Gaps por departamento
|
||||||
|
| Departamento | Agentes | Com skills | Sem skills | Skills recomendadas |
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Referencias
|
||||||
|
|
||||||
|
- Mecanismo runtime injection: conteúdo SKILL.md injectado como contexto adicional a cada heartbeat
|
||||||
|
- API skills: `skills/paperclip/references/company-skills.md`
|
||||||
|
- Schema BD: tabela `company_skills` (16 colunas)
|
||||||
|
- Auditoria compatibilidade: `04-Stack/02.06-Clip/auditoria-skills-compatibilidade.md`
|
||||||
|
- Manual: `06-Operacoes/Documentacao/Manuais/Paperclip/06-skills-e-plugins.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"2026-04-07","issue":"API /skills/import e /skills/sync sem Authorization header — rejeitadas com 401","fix":"Adicionar -H 'Authorization: Bearer $PAPERCLIP_API_KEY' a todos os curl da skill","source":"auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
---
|
||||||
|
name: clip-vision
|
||||||
|
category: gestao
|
||||||
|
description: "Gera documento de visao estrategica para o CEO Paperclip e bootstraps por C-Level. Resolve o vision gap — agentes param porque lhes falta a visao do fundador. Usar quando 'clip vision', 'visao paperclip', 'vision gap', 'bootstrap ceo', 'direcao agentes'."
|
||||||
|
version: "1.0.0"
|
||||||
|
created: 2026-04-07
|
||||||
|
tools: [Read, Write, Bash, AskUserQuestion]
|
||||||
|
---
|
||||||
|
|
||||||
|
# Skill: /clip-vision
|
||||||
|
|
||||||
|
Gera documento de visao estrategica para o CEO Paperclip e bootstrap documents para cada C-Level. Baseado no padrao Paperclip Vision Skill (#368 Aron Prins).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Problema que resolve
|
||||||
|
|
||||||
|
Agentes Paperclip param de produzir apos setup porque so recebem tarefas operacionais, nao visao estrategica. O CEO nao sabe para onde ir. Os C-Level nao sabem o que priorizar. O "vision gap" faz com que a organizacao funcione mas sem direcao.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Processo de execucao
|
||||||
|
|
||||||
|
### Fase 1 — Recolha de contexto (automatica)
|
||||||
|
|
||||||
|
Recolher dados do estado actual do Paperclip e do stack:
|
||||||
|
|
||||||
|
1. **Ler estado Paperclip:**
|
||||||
|
- Ficheiro `/home/ealmeida/paperclip/` — listar agents activos
|
||||||
|
- Desk CRM task #2041 (projecto Stack) — estado
|
||||||
|
- `Hub/04-Stack/STK-Estado-Actual.md` — metricas actuais
|
||||||
|
- `Hub/04-Stack/plano-consolidado-stack-q2-2026.md` — plano e metas
|
||||||
|
|
||||||
|
2. **Ler issues e routines:**
|
||||||
|
- Via MCP Paperclip ou ficheiros locais em `/home/ealmeida/paperclip/`
|
||||||
|
- Issues abertas, routines activas, ultimos heartbeats
|
||||||
|
|
||||||
|
3. **Compilar contexto:** resumo de 10-15 linhas com estado actual
|
||||||
|
|
||||||
|
### Fase 2 — Entrevista ao fundador (interactiva)
|
||||||
|
|
||||||
|
Fazer 5-7 perguntas ao Emanuel usando AskUserQuestion. Cada pergunta com 3-4 opcoes + "outro":
|
||||||
|
|
||||||
|
**Pergunta 1:** Qual e a prioridade principal para os proximos 30 dias?
|
||||||
|
- a) Aumentar receita (novos clientes, propostas)
|
||||||
|
- b) Melhorar operacoes internas (eficiencia, automacao)
|
||||||
|
- c) Desenvolver produto/servico novo
|
||||||
|
- d) Consolidar o que ja existe (qualidade, documentacao)
|
||||||
|
- e) Outro: ___
|
||||||
|
|
||||||
|
**Pergunta 2:** Que departamento precisa de mais atencao neste momento?
|
||||||
|
- a) D1 Comercial (vendas, leads, propostas)
|
||||||
|
- b) D6 Marketing (SEO, conteudo, redes sociais)
|
||||||
|
- c) D7 Tecnologia (infra, dev, automacao)
|
||||||
|
- d) D3 Contabilidade (facturas, despesas, cash flow)
|
||||||
|
- e) Outro: ___
|
||||||
|
|
||||||
|
**Pergunta 3:** Que nivel de autonomia queres dar aos agentes?
|
||||||
|
- a) Passive — so actuam quando pedido, sempre com aprovacao
|
||||||
|
- b) Balanced — actuam em rotinas, pedem aprovacao para novidades
|
||||||
|
- c) Active — actuam proactivamente, reportam resultados
|
||||||
|
- d) Manter o actual
|
||||||
|
|
||||||
|
**Pergunta 4:** Qual e o budget mensal aceitavel para agentes IA (tokens + APIs)?
|
||||||
|
- a) <50 EUR/mes (minimo, so essenciais)
|
||||||
|
- b) 50-100 EUR/mes (moderado)
|
||||||
|
- c) 100-200 EUR/mes (investimento activo)
|
||||||
|
- d) >200 EUR/mes (sem restricao significativa)
|
||||||
|
|
||||||
|
**Pergunta 5:** Qual e o objectivo principal do Q2 2026?
|
||||||
|
- a) Facturacao: atingir X EUR/mes
|
||||||
|
- b) Clientes: fechar N novos contratos
|
||||||
|
- c) Produto: lancar servico/SaaS especifico
|
||||||
|
- d) Stack: maximizar capacidade operacional
|
||||||
|
- e) Outro: ___
|
||||||
|
|
||||||
|
**Pergunta 6:** O que deve ser explicitamente proibido para os agentes?
|
||||||
|
- a) Contactar clientes directamente
|
||||||
|
- b) Fazer deploy sem aprovacao
|
||||||
|
- c) Gastar budget acima de X
|
||||||
|
- d) Todas as anteriores
|
||||||
|
- e) Outro: ___
|
||||||
|
|
||||||
|
**Pergunta 7:** Como medes sucesso dos agentes Paperclip?
|
||||||
|
- a) Output tangivel (artigos, propostas, deploys)
|
||||||
|
- b) Reducao de tempo em tarefas manuais
|
||||||
|
- c) ROI mensuravel (custo vs valor gerado)
|
||||||
|
- d) Consistencia (fazem sempre o basico bem)
|
||||||
|
|
||||||
|
### Fase 3 — Geracao de documentos
|
||||||
|
|
||||||
|
Com base nas respostas, gerar 5 documentos:
|
||||||
|
|
||||||
|
#### 1. vision.md (destino: /home/ealmeida/paperclip/vision.md)
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# Visao Descomplicar — {data}
|
||||||
|
|
||||||
|
## Missao
|
||||||
|
{extraido das respostas + contexto}
|
||||||
|
|
||||||
|
## Objectivos Q2 2026
|
||||||
|
1. {objectivo principal}
|
||||||
|
2. {objectivo secundario}
|
||||||
|
3. {objectivo terciario}
|
||||||
|
|
||||||
|
## Prioridades (30 dias)
|
||||||
|
1. {prioridade 1 com accao concreta}
|
||||||
|
2. {prioridade 2}
|
||||||
|
3. {prioridade 3}
|
||||||
|
|
||||||
|
## Restricoes
|
||||||
|
- {proibicoes definidas na P6}
|
||||||
|
- Budget maximo: {P4}
|
||||||
|
- Governance: {P3}
|
||||||
|
|
||||||
|
## Metricas de sucesso
|
||||||
|
- {P7 — como medir}
|
||||||
|
|
||||||
|
## Revisao
|
||||||
|
- Gerado: {data}
|
||||||
|
- Proxima revisao: {data + 90 dias}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2-5. Bootstrap documents (destino: /home/ealmeida/paperclip/)
|
||||||
|
|
||||||
|
Para cada C-Level (CEO, CTO, CMO, COO), gerar `{role}-bootstrap.md`:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# Bootstrap {Role} — {data}
|
||||||
|
|
||||||
|
## Contexto
|
||||||
|
{estado actual do departamento relevante}
|
||||||
|
|
||||||
|
## Top 3 prioridades
|
||||||
|
1. {prioridade com accao e deadline}
|
||||||
|
2. {prioridade}
|
||||||
|
3. {prioridade}
|
||||||
|
|
||||||
|
## Recursos disponiveis
|
||||||
|
- Skills: {lista relevante}
|
||||||
|
- MCPs: {lista relevante}
|
||||||
|
- Routines: {activas no departamento}
|
||||||
|
|
||||||
|
## Restricoes
|
||||||
|
- {do vision.md, filtradas para este papel}
|
||||||
|
|
||||||
|
## Proxima accao
|
||||||
|
{1 accao concreta que pode fazer no proximo heartbeat}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fase 4 — Resumo e confirmacao
|
||||||
|
|
||||||
|
Apresentar resumo ao utilizador:
|
||||||
|
- 5 documentos gerados com paths
|
||||||
|
- Sugerir proximos passos (injectar vision.md no CEO heartbeat, etc.)
|
||||||
|
- Perguntar se quer ajustar algo
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notas importantes
|
||||||
|
|
||||||
|
- Os documentos devem ser **accionaveis**, nao genericos
|
||||||
|
- Cada bootstrap deve referenciar **dados reais** do estado actual
|
||||||
|
- O vision.md deve ser **injectado no CEO** como contexto do heartbeat
|
||||||
|
- Sugerir /schedule trimestral para refrescar a visao
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
@@ -0,0 +1,162 @@
|
|||||||
|
---
|
||||||
|
name: clip
|
||||||
|
description: Dashboard rápido Paperclip — estado agentes, issues abertas, heartbeats recentes, alertas. Usar quando "clip", "paperclip", "estado clip", "agentes clip".
|
||||||
|
context: fork
|
||||||
|
---
|
||||||
|
|
||||||
|
# /clip — Dashboard Paperclip
|
||||||
|
|
||||||
|
Dashboard rapido do estado do Clip (Paperclip Orquestrador Descomplicar).
|
||||||
|
|
||||||
|
## Constantes
|
||||||
|
|
||||||
|
```
|
||||||
|
BD: PGPASSWORD="paperclip" psql -h localhost -p 54329 -U paperclip -d paperclip
|
||||||
|
COMPANY_ID: ebe10308-efd7-453f-86ab-13e6fe84004f
|
||||||
|
```
|
||||||
|
|
||||||
|
## Procedimento
|
||||||
|
|
||||||
|
Executar os 5 passos em paralelo (silenciosamente), depois apresentar dashboard compacto.
|
||||||
|
|
||||||
|
### Passo 1: Estado do servico
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl --user status paperclip 2>&1 | head -5
|
||||||
|
```
|
||||||
|
|
||||||
|
### Passo 2: Agentes por status
|
||||||
|
|
||||||
|
Invocar tool MCP: `mcp__paperclip__diag_agents_by_status`
|
||||||
|
|
||||||
|
### Passo 3: Issues abertas
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT i.title, i.status, i.priority, a.name as assignee
|
||||||
|
FROM issues i LEFT JOIN agents a ON i.assignee_agent_id = a.id
|
||||||
|
WHERE i.company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
AND i.status NOT IN ('done','cancelled')
|
||||||
|
ORDER BY
|
||||||
|
CASE i.priority WHEN 'critical' THEN 1 WHEN 'high' THEN 2 WHEN 'medium' THEN 3 ELSE 4 END,
|
||||||
|
i.status;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Passo 4: Ultimos 10 heartbeats
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT a.name, hr.status, hr.started_at, hr.finished_at
|
||||||
|
FROM heartbeat_runs hr JOIN agents a ON hr.agent_id = a.id
|
||||||
|
WHERE a.company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
ORDER BY hr.started_at DESC LIMIT 10;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Passo 5: Alertas
|
||||||
|
|
||||||
|
Heartbeats falhados nas ultimas 24h:
|
||||||
|
```sql
|
||||||
|
SELECT a.name, LEFT(hr.error, 80) as erro, hr.started_at
|
||||||
|
FROM heartbeat_runs hr JOIN agents a ON hr.agent_id = a.id
|
||||||
|
WHERE a.company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
AND hr.status = 'failed'
|
||||||
|
AND hr.started_at > NOW() - INTERVAL '24 hours'
|
||||||
|
ORDER BY hr.started_at DESC;
|
||||||
|
```
|
||||||
|
|
||||||
|
Falsos blockers (INC-07):
|
||||||
|
|
||||||
|
Invocar tool MCP: `mcp__paperclip__diag_false_blockers`
|
||||||
|
|
||||||
|
Se resultado > 0 → listar como alerta: "N issues blocked com sub-tasks activas — provavelmente deveriam ser in_progress".
|
||||||
|
|
||||||
|
Token burn — agentes com consumo excessivo de tokens nas últimas 24h (INC-12):
|
||||||
|
|
||||||
|
Invocar tool MCP: `mcp__paperclip__diag_heartbeat_token_usage(hours=24)`
|
||||||
|
|
||||||
|
Se `agentes_risco > 0` → alertar: "TOKEN BURN: N agentes com runs >500K cache tokens — usar /clip-health check 19 para detalhes".
|
||||||
|
|
||||||
|
Routines presas (INC-08) — a ligação issue→routine está em `routine_runs.linked_issue_id`:
|
||||||
|
|
||||||
|
Invocar tool MCP: `mcp__paperclip__diag_stuck_routines(hours=4)`
|
||||||
|
|
||||||
|
Se `routines_presas > 0` → alertar: "ROUTINE BLOQUEADA: N issues de routine paradas >4h — usar /clip-health check 20".
|
||||||
|
|
||||||
|
Budget (agentes com >0 configurado):
|
||||||
|
```sql
|
||||||
|
SELECT name, budget_monthly_cents, spent_monthly_cents,
|
||||||
|
CASE WHEN budget_monthly_cents > 0
|
||||||
|
THEN ROUND(spent_monthly_cents::numeric / budget_monthly_cents * 100, 1)
|
||||||
|
ELSE 0 END as pct
|
||||||
|
FROM agents
|
||||||
|
WHERE company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'
|
||||||
|
AND budget_monthly_cents > 0
|
||||||
|
ORDER BY pct DESC;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Passo 6: Saude API (endpoint dashboard)
|
||||||
|
|
||||||
|
Verificar se os endpoints criticos respondem:
|
||||||
|
```bash
|
||||||
|
HEALTH=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:3100/api/health)
|
||||||
|
DASH=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:3100/api/companies/ebe10308-efd7-453f-86ab-13e6fe84004f/dashboard)
|
||||||
|
BADGES=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:3100/api/companies/ebe10308-efd7-453f-86ab-13e6fe84004f/sidebar-badges)
|
||||||
|
echo "health=$HEALTH dashboard=$DASH badges=$BADGES"
|
||||||
|
```
|
||||||
|
|
||||||
|
- health=200 = OK (sem auth)
|
||||||
|
- dashboard/badges=401 = OK (auth funciona, endpoint existe)
|
||||||
|
- dashboard/badges=404 ou 500 = CRITICO (endpoint em falha, provavelmente refs orfas na BD)
|
||||||
|
|
||||||
|
Verificar instancias duplicadas:
|
||||||
|
```bash
|
||||||
|
ss -tlnp | grep -E "310[0-9]" | wc -l
|
||||||
|
```
|
||||||
|
- 1 = OK
|
||||||
|
- 2+ = AVISO (processos orfaos, recomendar limpeza)
|
||||||
|
|
||||||
|
### Passo 7: Company skills
|
||||||
|
|
||||||
|
Invocar tool MCP: `mcp__paperclip__diag_company_skills_summary`
|
||||||
|
|
||||||
|
## Formato de output
|
||||||
|
|
||||||
|
Apresentar como dashboard compacto:
|
||||||
|
|
||||||
|
```
|
||||||
|
## Clip Dashboard — [data/hora]
|
||||||
|
|
||||||
|
**Servico:** [running/stopped] ha [tempo]
|
||||||
|
**Agentes:** [N] total — [n] running, [n] idle, [n] paused
|
||||||
|
**API:** health=[code] dashboard=[code] badges=[code] | Instancias: [N]
|
||||||
|
**Skills:** [N] instaladas ([n] locais, [n] skills.sh, [n] github)
|
||||||
|
|
||||||
|
### Issues abertas
|
||||||
|
| Titulo | Status | Prioridade | Assignee |
|
||||||
|
...
|
||||||
|
|
||||||
|
### Heartbeats recentes
|
||||||
|
| Agente | Status | Inicio | Fim |
|
||||||
|
...
|
||||||
|
|
||||||
|
### Alertas
|
||||||
|
- [CRITICO] descricao
|
||||||
|
- [TOKEN BURN] N agentes >500K tokens — /clip-health check 19
|
||||||
|
- [ROUTINE BLOQUEADA] N issues paradas >4h — /clip-health check 20
|
||||||
|
```
|
||||||
|
|
||||||
|
## Referencias
|
||||||
|
|
||||||
|
- Manual: Hub `06-Operacoes/Documentacao/Manuais/Paperclip/`
|
||||||
|
- API: `04-Stack/02.06-Clip/skills.md`
|
||||||
|
- Spec: `04-Stack/02.06-Clip/docs/superpowers/specs/2026-03-28-clip-grande-visao-design.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: daily-digest
|
name: daily-digest
|
||||||
description: Resumo diário do estado operacional - timer activo, tickets abertos, facturas vencidas, leads novos, propostas pendentes e agenda do dia. Usar quando "resumo", "digest", "estado do dia", "dashboard", "métricas dia".
|
description: Sub-rotina chamada por /today para snapshot CRM (timer activo, tickets, facturas vencidas, leads, propostas, agenda). Pode ser invocada isoladamente quando só precisas dos números CRM sem o checkup completo. Usar quando "resumo", "digest", "estado do dia", "métricas dia". Para dashboard diário completo usar /today.
|
||||||
context: fork
|
context: fork
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -122,3 +122,15 @@ Gerar alertas se:
|
|||||||
---
|
---
|
||||||
|
|
||||||
*Skill v1.0.0 | 04-03-2026 | Descomplicar®*
|
*Skill v1.0.0 | 04-03-2026 | Descomplicar®*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -0,0 +1,124 @@
|
|||||||
|
---
|
||||||
|
name: deep-research
|
||||||
|
description: >
|
||||||
|
Pesquisa profunda em 3 layers: Hub Obsidian (Layer 1) + NotebookLM análise (Layer 2) +
|
||||||
|
Web externo (Layer 3). Para questões complexas que requerem síntese de múltiplas fontes.
|
||||||
|
Usar quando: análise competitiva profunda, pesquisa mercado, due diligence, relatório estratégico.
|
||||||
|
---
|
||||||
|
|
||||||
|
# /deep-research — Pesquisa Profunda com RAG Trinity
|
||||||
|
|
||||||
|
Pesquisa em 3 camadas com síntese final. Mais profundo que `/research`, mais estruturado que `/hub-search`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quando Usar
|
||||||
|
|
||||||
|
| Situação | Skill Correcta |
|
||||||
|
|---------|----------------|
|
||||||
|
| "Onde está X no Hub?" | `/hub-search` |
|
||||||
|
| "Analisa este documento" | `/research` |
|
||||||
|
| "Pesquisa profunda + síntese de múltiplas fontes" | `/deep-research` ← este |
|
||||||
|
| "Análise competitiva completa" | `/deep-research` + `/research competitive` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Protocolo (3 Layers)
|
||||||
|
|
||||||
|
### Layer 1 — Hub Obsidian (conhecimento interno)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1a. Busca full-text no Hub
|
||||||
|
obsidian search query="<TERMO>" format=json limit=10
|
||||||
|
|
||||||
|
# 1b. Se Obsidian não responde (offline), fallback via Grep
|
||||||
|
grep -r "<TERMO>" /media/ealmeida/Dados/Hub/ --include="*.md" -l | head -20
|
||||||
|
```
|
||||||
|
|
||||||
|
**Critério de suficiência Layer 1:** Encontrou 3+ documentos relevantes com contexto concreto.
|
||||||
|
- SE suficiente para questão simples → responder + registar fonte
|
||||||
|
- SE questão requer análise profunda → continuar para Layer 2
|
||||||
|
|
||||||
|
### Layer 2 — NotebookLM (análise profunda)
|
||||||
|
|
||||||
|
Seleccionar notebook relevante com base no domínio:
|
||||||
|
|
||||||
|
| Domínio | Notebook ID |
|
||||||
|
|---------|-------------|
|
||||||
|
| Estratégia e Empreendedorismo | 79d43410-0e29-4be1-881d-84db6bdc239a |
|
||||||
|
| Stack Tecnológico | [consultar mcp__notebooklm__ lista] |
|
||||||
|
| Marketing e Vendas | [consultar mcp__notebooklm__ lista] |
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Consultar notebook relevante
|
||||||
|
mcp__notebooklm__notebook_query({
|
||||||
|
notebook_id: "<ID>",
|
||||||
|
query: "<QUESTÃO ESPECÍFICA — mais precisa que a geral>"
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
**Critério de suficiência Layer 2:** NotebookLM retornou análise com citações específicas.
|
||||||
|
- SE suficiente → sintetizar com Layer 1 + responder
|
||||||
|
- SE requer dados externos → continuar para Layer 3
|
||||||
|
|
||||||
|
### Layer 3 — Web (conhecimento externo)
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Web search para dados actuais
|
||||||
|
mcp__web-search__search({
|
||||||
|
query: "<QUESTÃO> site:scholar.google.com OR filetype:pdf",
|
||||||
|
num_results: 10
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Síntese Final
|
||||||
|
|
||||||
|
Após recolher de 2+ layers, sintetizar:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Síntese — [Tópico]
|
||||||
|
|
||||||
|
**Fontes consultadas:** Layer 1 (Hub), Layer 2 (NotebookLM [Notebook X]), Layer 3 (Web)
|
||||||
|
|
||||||
|
### O que sabemos (interno)
|
||||||
|
[Resumo Layer 1 — conhecimento já documentado]
|
||||||
|
|
||||||
|
### Análise profunda
|
||||||
|
[Resumo Layer 2 — análise NotebookLM com citações]
|
||||||
|
|
||||||
|
### Contexto externo
|
||||||
|
[Resumo Layer 3 — se consultado]
|
||||||
|
|
||||||
|
### Síntese e Recomendação
|
||||||
|
[Cruzamento das layers — resposta directa à questão]
|
||||||
|
|
||||||
|
### Próximos Passos
|
||||||
|
- [ ] Acção 1 derivada da pesquisa
|
||||||
|
- [ ] Acção 2
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Self-Improving Loop
|
||||||
|
|
||||||
|
Após cada execução, registar preferências para melhorar futuras pesquisas:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Guardar aprendizagem em Hub
|
||||||
|
echo "$(date '+%Y-%m-%d') — deep-research — [TÓPICO] — [O QUE FUNCIONOU/NÃO FUNCIONOU]" \
|
||||||
|
>> /media/ealmeida/Dados/Hub/00-Inbox/research-preferences.md
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Skill /deep-research v1.1.0 | 13-04-2026 | LightRAG removido — Layer 3 passa a Web apenas*
|
||||||
@@ -339,3 +339,15 @@ Output: [resultado esperado]
|
|||||||
Input: [caso complexo]
|
Input: [caso complexo]
|
||||||
Output: [resultado detalhado]
|
Output: [resultado detalhado]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -440,3 +440,15 @@ Após concluir o documento:
|
|||||||
---
|
---
|
||||||
|
|
||||||
**Versão**: 1.0.0 | **Data**: 2026-03-06 | **Autor**: Descomplicar®
|
**Versão**: 1.0.0 | **Data**: 2026-03-06 | **Autor**: Descomplicar®
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
---
|
||||||
|
name: dual-review
|
||||||
|
description: Revisão dual-model de conteúdo publicável — artigos WordPress, propostas comerciais, relatórios de cliente. Um agente gera com contexto completo, outro revisa sem contexto partilhado. Usar antes de publicar ou enviar a cliente.
|
||||||
|
context: fork
|
||||||
|
---
|
||||||
|
|
||||||
|
# /dual-review — Revisão Dual-Model
|
||||||
|
|
||||||
|
> "Um revisor sem contexto detecta o que o autor não vê."
|
||||||
|
> Fonte: Eixo 4, Plano Stack Q2 2026.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quando usar
|
||||||
|
|
||||||
|
**OBRIGATÓRIO para:**
|
||||||
|
- Artigos WordPress antes de publicar
|
||||||
|
- Propostas comerciais antes de enviar
|
||||||
|
- Relatórios de cliente antes de entregar
|
||||||
|
- Qualquer conteúdo com dados factuais (métricas, preços, datas)
|
||||||
|
|
||||||
|
**Não usar para:**
|
||||||
|
- Comentários internos no CRM
|
||||||
|
- Notas de trabalho
|
||||||
|
- Código (usar `superpowers:requesting-code-review`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Workflow (4 passos)
|
||||||
|
|
||||||
|
### Passo 1 — Gerar conteúdo (agente principal)
|
||||||
|
|
||||||
|
Gerar o conteúdo com contexto completo. Marcar dados não confirmados como `[VERIFICAR: X]`.
|
||||||
|
|
||||||
|
### Passo 2 — Preparar para revisão
|
||||||
|
|
||||||
|
Extrair apenas o output final + definir critérios. **Não incluir o contexto de geração.**
|
||||||
|
|
||||||
|
```
|
||||||
|
CONTEÚDO PARA REVISÃO:
|
||||||
|
[colar apenas o output final]
|
||||||
|
|
||||||
|
CRITÉRIOS:
|
||||||
|
1. Factos verificados (sem "[VERIFICAR: X]" por resolver)
|
||||||
|
2. URLs funcionais e correctas
|
||||||
|
3. Datas e valores em EUR correctos
|
||||||
|
4. PT-PT (não brasileiro): tu/você, descarregar/baixar, ficheiro/arquivo
|
||||||
|
5. Acentos correctos: á, à, â, ã, é, ê, í, ó, ô, õ, ú, ç
|
||||||
|
6. Coerência interna (sem contradições)
|
||||||
|
7. Adequação ao público-alvo
|
||||||
|
|
||||||
|
JUDGMENT FRAMEWORK:
|
||||||
|
[incluir exemplos relevantes de ~/.claude/design/judgment-frameworks/]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Passo 3 — Revisão por segundo agente
|
||||||
|
|
||||||
|
Usar `Agent tool` com `model: "sonnet"` passando APENAS o conteúdo + critérios.
|
||||||
|
|
||||||
|
Instrução ao segundo agente:
|
||||||
|
```
|
||||||
|
És um revisor de qualidade de conteúdo. Verifica o texto contra os critérios fornecidos.
|
||||||
|
NÃO tens contexto sobre como foi gerado — avalia apenas o output final como leitor externo.
|
||||||
|
Lista cada problema com localização exacta, ou responde "APROVADO" se não há problemas.
|
||||||
|
```
|
||||||
|
|
||||||
|
### Passo 4 — Corrigir e repetir
|
||||||
|
|
||||||
|
Se o revisor retornar problemas:
|
||||||
|
1. Corrigir cada problema no conteúdo
|
||||||
|
2. Re-submeter (Passos 2-3)
|
||||||
|
3. Repetir até "APROVADO" ou máximo 3 iterações
|
||||||
|
|
||||||
|
Se após 3 iterações ainda há problemas: escalar ao utilizador com lista de pendentes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Judgment Frameworks disponíveis
|
||||||
|
|
||||||
|
- `~/.claude/design/judgment-frameworks/global.md` — anti-alucinação geral
|
||||||
|
- `~/.claude/design/judgment-frameworks/wordpress.md` — conteúdo e código WP
|
||||||
|
- `~/.claude/design/judgment-frameworks/crm.md` — operações CRM
|
||||||
|
|
||||||
|
Incluir o framework relevante nos critérios do Passo 2.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Exemplo de uso
|
||||||
|
|
||||||
|
```
|
||||||
|
# Artigo WordPress sobre X gerado. Antes de publicar:
|
||||||
|
/dual-review
|
||||||
|
|
||||||
|
Conteúdo: [artigo completo]
|
||||||
|
Tipo: artigo-wordpress
|
||||||
|
Público: PMEs portuguesas
|
||||||
|
Judgment: ~/.claude/design/judgment-frameworks/wordpress.md
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"2026-04-06","issue":"Placeholder vazio sem validacao previa","fix":"Validacao completa: frontmatter OK (name/description/context), paths judgment-frameworks OK (global/wordpress/crm), workflow 4 passos coerente. Nenhuma correccao necessaria.","source":"auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
@@ -0,0 +1,229 @@
|
|||||||
|
---
|
||||||
|
name: hub-compile
|
||||||
|
description: Compilador do 00-Inbox do Hub Obsidian. Classifica ficheiros .md, gera resumos, sugere destino e backlinks, move com aprovação explícita do utilizador. Usar quando "hub-compile", "compilar inbox", "triagem inbox", "processar inbox", "classificar notas".
|
||||||
|
context: fork
|
||||||
|
---
|
||||||
|
|
||||||
|
# /hub-compile v1.0 — Compilador do Hub Inbox
|
||||||
|
|
||||||
|
Processa automaticamente os ficheiros `.md` em `00-Inbox/` do Hub Obsidian: classifica, resume, sugere destino e backlinks, e move apenas com aprovação explícita.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Filosofia
|
||||||
|
|
||||||
|
Padrão Karpathy (Raw → Compiler → Wiki): o LLM actua como compilador — lê ficheiros em bruto, extrai estrutura e significado, e propõe organização. O utilizador aprova antes de qualquer movimento.
|
||||||
|
|
||||||
|
**Princípio cardinal: NUNCA mover sem aprovação.**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Protocolo de Execução
|
||||||
|
|
||||||
|
```
|
||||||
|
1. LER ficheiros do Inbox
|
||||||
|
2. CLASSIFICAR cada ficheiro
|
||||||
|
3. APRESENTAR tabela ao utilizador
|
||||||
|
4. AGUARDAR aprovação
|
||||||
|
5. MOVER os aprovados
|
||||||
|
6. ACTUALIZAR INDEX.md de origem e destino
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Passo 1 — Ler Inbox
|
||||||
|
|
||||||
|
```
|
||||||
|
- Listar TODOS os .md em /media/ealmeida/Dados/Hub/00-Inbox/
|
||||||
|
- EXCLUIR INDEX.md
|
||||||
|
- Para cada ficheiro: ler conteúdo completo
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Passo 2 — Classificar
|
||||||
|
|
||||||
|
Para cada ficheiro, determinar:
|
||||||
|
|
||||||
|
### Tipo
|
||||||
|
|
||||||
|
| Tipo | Indicadores |
|
||||||
|
|------|-------------|
|
||||||
|
| `worklog` | "Worklog", datas de sessão, tool calls, MCPs usados |
|
||||||
|
| `prompt` | "Prompt", instruções para Claude, specs de módulo |
|
||||||
|
| `nota-tecnica` | Configurações, comandos, troubleshooting, fixes |
|
||||||
|
| `planeamento` | "Plano", "migração", "roadmap", decisões activas |
|
||||||
|
| `facturacao` | Facturas, recibos, datas limite, valores |
|
||||||
|
| `migracao` | "Migração", "setup", hardware novo, configurações pendentes |
|
||||||
|
| `stress-test` | Resultados de testes, benchmarks, métricas |
|
||||||
|
| `outro` | Não se encaixa nas categorias acima |
|
||||||
|
|
||||||
|
### Destino Sugerido
|
||||||
|
|
||||||
|
| Tipo | Destino |
|
||||||
|
|------|---------|
|
||||||
|
| `worklog` | `99-Arquivo/Worklogs/YYYY/MM/` |
|
||||||
|
| `prompt` | `99-Arquivo/Documentacao-Pontuais/` |
|
||||||
|
| `nota-tecnica` com valor permanente | `06-Operacoes/Knowledge-Base/MDs/` |
|
||||||
|
| `nota-tecnica` pontual/resolvida | `99-Arquivo/Documentacao-Pontuais/` |
|
||||||
|
| `planeamento` activo | **MANTER** (fica no Inbox) |
|
||||||
|
| `facturacao` | `99-Arquivo/Documentacao-Pontuais/` |
|
||||||
|
| `migracao` activa | **MANTER** (fica no Inbox) |
|
||||||
|
| `stress-test` | `99-Arquivo/Documentacao-Pontuais/` |
|
||||||
|
| `outro` | Consultar utilizador |
|
||||||
|
|
||||||
|
### Acção
|
||||||
|
|
||||||
|
| Acção | Significado |
|
||||||
|
|-------|-------------|
|
||||||
|
| `mover` | Pronto para mover para o destino sugerido |
|
||||||
|
| `arquivar` | Mover para `99-Arquivo/` |
|
||||||
|
| `manter` | Deixar no Inbox — activo ou precisa mais trabalho |
|
||||||
|
| `eliminar` | Duplicado, vazio, ou sem valor — confirmar antes |
|
||||||
|
|
||||||
|
### Gerar por ficheiro
|
||||||
|
|
||||||
|
- **Resumo:** 2-3 linhas descrevendo o conteúdo essencial
|
||||||
|
- **Conceitos-chave:** 3-5 termos ou tópicos principais
|
||||||
|
- **Backlinks sugeridos:** docs existentes no Hub que devem referenciar este ficheiro ou ser referenciados por ele (usar conhecimento do vault — QR-*, PROC-*, etc.)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Passo 3 — Apresentar Tabela
|
||||||
|
|
||||||
|
Mostrar ao utilizador antes de qualquer acção:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Hub Compile — Inbox Analysis
|
||||||
|
|
||||||
|
**N ficheiros encontrados** | Data: YYYY-MM-DD HH:MM
|
||||||
|
|
||||||
|
| # | Ficheiro | Tipo | Acção | Destino | Resumo |
|
||||||
|
|---|----------|------|-------|---------|--------|
|
||||||
|
| 1 | `nome.md` | worklog | mover | 99-Arquivo/Worklogs/2026/03/ | Sessão de 31 Mar: implementação X, Y, Z. Duração ~2h. |
|
||||||
|
| 2 | `nome.md` | planeamento | manter | — (Inbox) | Migração Alurin em curso. Pendentes: configurar Syncthing. |
|
||||||
|
| 3 | `nome.md` | prompt | mover | 99-Arquivo/Documentacao-Pontuais/ | Prompt para módulo Moloni-Perfex sync. Concluído. |
|
||||||
|
|
||||||
|
### Backlinks Sugeridos
|
||||||
|
|
||||||
|
| Ficheiro | Backlink para |
|
||||||
|
|----------|--------------|
|
||||||
|
| `stress-tests-alurin.md` | `QR-Servidores.md`, `infra.md` (memory) |
|
||||||
|
| `worklog-2026-03-31.md` | Discussão Logs #31 Desk CRM |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Aprovação necessária.**
|
||||||
|
|
||||||
|
Para aprovar todos os movimentos sugeridos: escrever `aprovar tudo`
|
||||||
|
Para aprovar individualmente: escrever `aprovar 1,3,5` (números da tabela)
|
||||||
|
Para ajustar uma acção: escrever `1=arquivar` ou `2=eliminar`
|
||||||
|
Para cancelar: escrever `cancelar`
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Passo 4 — Aguardar Aprovação
|
||||||
|
|
||||||
|
**PARAR aqui. Não executar nada antes da resposta do utilizador.**
|
||||||
|
|
||||||
|
Interpretar respostas:
|
||||||
|
- `aprovar tudo` → processar todos os `mover` e `arquivar` (nunca os `manter`)
|
||||||
|
- `aprovar 1,3` → processar apenas linhas 1 e 3
|
||||||
|
- `1=arquivar` → alterar acção da linha 1 para arquivar
|
||||||
|
- `cancelar` → terminar sem mover nada
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Passo 5 — Mover Ficheiros Aprovados
|
||||||
|
|
||||||
|
Para cada ficheiro aprovado com acção `mover` ou `arquivar`:
|
||||||
|
|
||||||
|
```
|
||||||
|
1. Verificar se directório de destino existe
|
||||||
|
- SE não existe: criar com mcp__filesystem__create_directory
|
||||||
|
2. Mover ficheiro: mcp__filesystem__move_file
|
||||||
|
3. Confirmar que ficheiro chegou ao destino
|
||||||
|
4. Registar movimento para actualização de INDEX.md
|
||||||
|
```
|
||||||
|
|
||||||
|
**Formato do path de destino:**
|
||||||
|
- Worklogs: `/media/ealmeida/Dados/Hub/99-Arquivo/Worklogs/YYYY/MM/nome.md`
|
||||||
|
- Documentação pontual: `/media/ealmeida/Dados/Hub/99-Arquivo/Documentacao-Pontuais/nome.md`
|
||||||
|
- Knowledge-Base: `/media/ealmeida/Dados/Hub/06-Operacoes/Knowledge-Base/MDs/nome.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Passo 6 — Actualizar INDEX.md
|
||||||
|
|
||||||
|
### INDEX.md do Inbox (00-Inbox/INDEX.md)
|
||||||
|
|
||||||
|
Remover entradas dos ficheiros movidos. Se INDEX.md não tiver lista estruturada, adicionar nota de actualização no topo.
|
||||||
|
|
||||||
|
### INDEX.md do Destino
|
||||||
|
|
||||||
|
Para cada destino com movimentos:
|
||||||
|
1. Ler INDEX.md existente (se existir)
|
||||||
|
2. Adicionar entradas dos ficheiros movidos
|
||||||
|
3. Se INDEX.md não existir e destino tem >3 ficheiros → criar
|
||||||
|
|
||||||
|
**Formato de entrada no INDEX.md:**
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
| `nome-ficheiro.md` | Tipo | YYYY-MM-DD | Descrição breve |
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Output Final
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Hub Compile — Concluído
|
||||||
|
|
||||||
|
**Movidos:** N ficheiros
|
||||||
|
**Mantidos no Inbox:** M ficheiros
|
||||||
|
**Eliminados:** 0 (requer confirmação separada)
|
||||||
|
|
||||||
|
### Movimentos Realizados
|
||||||
|
|
||||||
|
- `worklog-2026-03-31.md` → 99-Arquivo/Worklogs/2026/03/
|
||||||
|
- `prompt-modulo-moloni.md` → 99-Arquivo/Documentacao-Pontuais/
|
||||||
|
|
||||||
|
### Mantidos
|
||||||
|
|
||||||
|
- `migracao-alurin-mini-pc.md` — migração activa
|
||||||
|
- `NovoPC.md` — planeamento em curso
|
||||||
|
|
||||||
|
### INDEX.md Actualizados
|
||||||
|
|
||||||
|
- 00-Inbox/INDEX.md ✓
|
||||||
|
- 99-Arquivo/Worklogs/2026/03/INDEX.md ✓
|
||||||
|
- 99-Arquivo/Documentacao-Pontuais/INDEX.md ✓
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Regras Obrigatórias
|
||||||
|
|
||||||
|
1. **NUNCA mover sem aprovação explícita** do utilizador
|
||||||
|
2. **Worklogs** vão sempre para `99-Arquivo/Worklogs/YYYY/MM/`
|
||||||
|
3. **Planeamento activo** e **migração em curso** ficam sempre no Inbox (`manter`)
|
||||||
|
4. **Prompts concluídos** vão para `99-Arquivo/Documentacao-Pontuais/`
|
||||||
|
5. **Notas técnicas com valor permanente** vão para `06-Operacoes/Knowledge-Base/MDs/`
|
||||||
|
6. **Eliminar** requer confirmação separada — nunca eliminar na aprovação em massa
|
||||||
|
7. **INDEX.md** deve ser actualizado em origem e destino após cada movimento
|
||||||
|
8. **Usar mcp__filesystem__*** para todas as operações de ficheiros
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Anti-Patterns
|
||||||
|
|
||||||
|
- **NUNCA** mover com `aprovar tudo` sem excluir os `manter`
|
||||||
|
- **NUNCA** criar destinos sem verificar se já existem
|
||||||
|
- **NUNCA** omitir actualização dos INDEX.md
|
||||||
|
- **NUNCA** classificar como `eliminar` sem justificação clara
|
||||||
|
- **NUNCA** confundir planeamento activo com documentação pontual
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Skill v1.0 | 2026-04-07 | Descomplicar®*
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
---
|
||||||
|
name: hub-search
|
||||||
|
description: >
|
||||||
|
Pesquisa no vault Hub Obsidian com relevance scoring e backlinks.
|
||||||
|
Layer 1 da arquitectura de pesquisa (CLI → NotebookLM).
|
||||||
|
Usar quando: (1) pesquisar conteúdo no Hub por termo ou conceito,
|
||||||
|
(2) encontrar notas relacionadas via backlinks, (3) localizar PROCs/QR/docs
|
||||||
|
antes de executar tarefas, (4) verificar se existe documentação antes de criar.
|
||||||
|
---
|
||||||
|
|
||||||
|
# /hub-search — Pesquisa no Hub (Layer 1 RAG)
|
||||||
|
|
||||||
|
Pesquisa rápida no vault Hub via Obsidian CLI. Requer Obsidian aberto.
|
||||||
|
Fallback automático para Grep se Obsidian não estiver a correr.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Uso
|
||||||
|
|
||||||
|
```
|
||||||
|
/hub-search "termo"
|
||||||
|
/hub-search "LightRAG configuração" --backlinks
|
||||||
|
/hub-search "PROC-MCP" --files
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Workflow
|
||||||
|
|
||||||
|
### Passo 1 — Tentar via Obsidian CLI
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Pesquisa básica
|
||||||
|
obsidian search query="TERMO" format=json
|
||||||
|
|
||||||
|
# Com backlinks (recomendado para conceitos)
|
||||||
|
obsidian search query="TERMO" format=json
|
||||||
|
obsidian backlinks file="NOTA"
|
||||||
|
|
||||||
|
# Limitar resultados
|
||||||
|
obsidian search query="TERMO" limit=10 format=json
|
||||||
|
```
|
||||||
|
|
||||||
|
**Indicador de sucesso:** saída JSON com `results` array.
|
||||||
|
**Indicador de falha:** mensagem `unable to find Obsidian` → ir para fallback.
|
||||||
|
|
||||||
|
### Passo 2 — Fallback: Grep no Hub
|
||||||
|
|
||||||
|
Se CLI falhar (Obsidian fechado):
|
||||||
|
|
||||||
|
```
|
||||||
|
Grep "TERMO" /media/ealmeida/Dados/Hub/ --type md
|
||||||
|
```
|
||||||
|
|
||||||
|
Adicionar contexto ao utilizador: "Obsidian não está a correr — usando busca directa nos ficheiros."
|
||||||
|
|
||||||
|
### Passo 3 — Apresentar resultados
|
||||||
|
|
||||||
|
**Formato de output:**
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Resultados: "[termo]"
|
||||||
|
|
||||||
|
**Fonte:** Obsidian CLI v1.12.7 | **Backlinks:** Sim/Não
|
||||||
|
|
||||||
|
### Encontrado em N notas
|
||||||
|
|
||||||
|
| Nota | Path | Relevância |
|
||||||
|
|------|------|-----------|
|
||||||
|
| [título] | `path/relativo.md` | Alta/Média/Baixa |
|
||||||
|
|
||||||
|
### Notas com backlinks para este termo
|
||||||
|
- `nota-a.md` → referencia `nota-b.md`
|
||||||
|
|
||||||
|
### Relacionados sugeridos
|
||||||
|
- [links relevantes encontrados nos resultados]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Regras
|
||||||
|
|
||||||
|
1. **Sempre tentar CLI primeiro** — é mais preciso (scoring semântico)
|
||||||
|
2. **--include-backlinks por defeito** quando o termo é um conceito (não um comando)
|
||||||
|
3. **Fallback silencioso** — não perguntar, só mencionar que usou Grep
|
||||||
|
4. **Max 10 resultados** — se mais, mostrar top 10 por relevância
|
||||||
|
5. **Paths relativos** na apresentação (ex: `04-Stack/02.03-IA/` não path absoluto)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Integração com outras skills
|
||||||
|
|
||||||
|
```
|
||||||
|
/hub-search "termo" → Layer 1: Obsidian CLI (este skill)
|
||||||
|
/knowledge "termo" → Layer 2: NotebookLM (65 notebooks)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Quando escalar para Layer 2:**
|
||||||
|
- Resultado CLI score < 50% ou 0 resultados → sugerir `/knowledge`
|
||||||
|
- Conteúdo conceptual/externo → sugerir `/knowledge` directamente
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Referência CLI
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Sintaxe correcta: parâmetros com = (não flags com --)
|
||||||
|
obsidian search query="TERMO" format=json
|
||||||
|
obsidian search query="TERMO" limit=10 format=json
|
||||||
|
obsidian backlinks file="NOTA"
|
||||||
|
obsidian tags sort=count counts
|
||||||
|
obsidian tasks daily todo
|
||||||
|
obsidian version
|
||||||
|
obsidian help # lista todos os comandos disponíveis
|
||||||
|
```
|
||||||
|
|
||||||
|
**Nota:** A skill oficial kepano (`obsidian-cli`) tem referência completa de todos os comandos.
|
||||||
|
|
||||||
|
**Requer:** Obsidian aberto + CLI activado em Settings → General → Advanced
|
||||||
|
**Wrapper:** `~/.local/bin/obsidian` (define XDG_RUNTIME_DIR Flatpak)
|
||||||
|
**Docs:** `04-Stack/02.03-IA/Obsidian-CLI.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Skill v1.0.0 | 06-04-2026 | Descomplicar®*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
@@ -234,3 +234,15 @@ Quando invocado directamente (sem /today):
|
|||||||
---
|
---
|
||||||
|
|
||||||
*Skill v1.0.0 | 04-03-2026 | Descomplicar®*
|
*Skill v1.0.0 | 04-03-2026 | Descomplicar®*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user