Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6285be6c2e | |||
| 2252e1c29c | |||
| 19f89e0d69 | |||
| 19da1bed48 | |||
| 8bf46bcaf0 | |||
| b1d31ef152 | |||
| e2b086acbf | |||
| 24b0b68ed0 |
@@ -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,316 @@
|
|||||||
|
---
|
||||||
|
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 `mcp-hub.descomplicar.pt`.
|
||||||
|
|
||||||
|
## Contexto
|
||||||
|
|
||||||
|
```
|
||||||
|
Repositórios Gitea:
|
||||||
|
acidaos-core → Rust Core
|
||||||
|
acidaos-dashboard → Next.js Dashboard
|
||||||
|
|
||||||
|
Runners:
|
||||||
|
self-hosted @ mcp-hub.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
|
||||||
@@ -0,0 +1,191 @@
|
|||||||
|
---
|
||||||
|
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
|
||||||
@@ -0,0 +1,232 @@
|
|||||||
|
---
|
||||||
|
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
|
||||||
@@ -0,0 +1,239 @@
|
|||||||
|
---
|
||||||
|
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
|
||||||
@@ -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.*
|
||||||
|
|||||||
@@ -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)
|
||||||
@@ -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.*
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
---
|
||||||
|
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
|
||||||
@@ -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_missing_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.*
|
||||||
@@ -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,255 @@
|
|||||||
|
---
|
||||||
|
name: monday-briefing
|
||||||
|
description: Briefing semanal automatizado com 4 componentes — tendências de mercado, métricas chave, acção da semana e contra-argumentos. Usar quando "monday", "briefing segunda", "resumo semanal", "briefing semana", "monday briefing".
|
||||||
|
context: fork
|
||||||
|
---
|
||||||
|
|
||||||
|
# /monday-briefing v1.0
|
||||||
|
|
||||||
|
Briefing semanal com 4 perspectivas: tendências, métricas, acção e realidade.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Protocolo
|
||||||
|
|
||||||
|
### Passo 1: Recolher data e período
|
||||||
|
|
||||||
|
```
|
||||||
|
mcp__mcp-time__current_time → data actual
|
||||||
|
Calcular:
|
||||||
|
- semana_actual: Segunda a Domingo desta semana
|
||||||
|
- semana_anterior: Segunda a Domingo da semana passada
|
||||||
|
- periodo_atual: "Semana W{N} ({DD Mmm} – {DD Mmm YYYY})"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Passo 2: Recolher dados em paralelo
|
||||||
|
|
||||||
|
> Executar TUDO em paralelo. Registar erros sem bloquear — continuar com dados disponíveis.
|
||||||
|
|
||||||
|
```
|
||||||
|
Em paralelo:
|
||||||
|
|
||||||
|
[A] DESK CRM — Métricas da semana
|
||||||
|
mcp__desk-crm-v3__get_tasks({ date_from: inicio_semana_anterior, date_to: fim_semana_anterior, status: 5 })
|
||||||
|
→ tarefas_concluidas_semana_ant
|
||||||
|
mcp__desk-crm-v3__get_tasks({ date_from: inicio_semana, date_to: fim_semana, status: [1,2,3] })
|
||||||
|
→ tarefas_abertas_semana_atual
|
||||||
|
mcp__desk-crm-v3__get_timesheets({ date_from: inicio_semana_anterior, date_to: fim_semana_anterior })
|
||||||
|
→ horas_semana_ant
|
||||||
|
mcp__desk-crm-v3__get_tickets({ status: [1,2,3] })
|
||||||
|
→ tickets_abertos
|
||||||
|
|
||||||
|
[B] MOLONI — Facturação da semana
|
||||||
|
mcp__moloni-mcp__list_documents({
|
||||||
|
document_type: "invoice",
|
||||||
|
date_from: inicio_semana_anterior,
|
||||||
|
date_to: fim_semana_anterior
|
||||||
|
})
|
||||||
|
→ facturas_semana_ant (valor total + contagem)
|
||||||
|
mcp__moloni-mcp__list_documents({
|
||||||
|
document_type: "invoice",
|
||||||
|
date_from: inicio_semana,
|
||||||
|
date_to: fim_semana
|
||||||
|
})
|
||||||
|
→ facturas_semana_atual (se já existirem)
|
||||||
|
|
||||||
|
[C] DESK CRM — Leads e pipeline
|
||||||
|
mcp__desk-crm-v3__get_leads({ status: [7,14], limit: 20 })
|
||||||
|
→ leads_novos
|
||||||
|
mcp__desk-crm-v3__get_estimates({ status: [3,4], limit: 20 })
|
||||||
|
→ propostas_pipeline
|
||||||
|
|
||||||
|
[D] TENDÊNCIAS — WebSearch
|
||||||
|
WebSearch: "marketing digital tendencias semana {data_atual}"
|
||||||
|
WebSearch: "SEO updates {mes} {ano}"
|
||||||
|
WebSearch: "WordPress news {mes} {ano}"
|
||||||
|
→ 3 tendências relevantes ao negócio Descomplicar
|
||||||
|
|
||||||
|
[E] GOOGLE WORKSPACE — Agenda da semana
|
||||||
|
mcp__google-workspace__calendar_get_events({
|
||||||
|
user_google_email: "emanuelalmeidaa@gmail.com",
|
||||||
|
time_min: "{inicio_semana}T00:00:00Z",
|
||||||
|
time_max: "{fim_semana}T23:59:59Z"
|
||||||
|
})
|
||||||
|
→ eventos_semana
|
||||||
|
```
|
||||||
|
|
||||||
|
### Passo 3: Calcular métricas comparativas
|
||||||
|
|
||||||
|
```
|
||||||
|
Calcular variações:
|
||||||
|
delta_horas = horas_semana_ant vs semana anterior a essa (% variação)
|
||||||
|
delta_facturas = valor_semana_ant vs média das últimas 4 semanas
|
||||||
|
taxa_conclusao = tarefas_concluidas / (tarefas_concluidas + abertas) * 100
|
||||||
|
|
||||||
|
SE dados incompletos: usar "N/D" e indicar fonte em falta
|
||||||
|
```
|
||||||
|
|
||||||
|
### Passo 4: Gerar briefing em 4 secções
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Output
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# Monday Briefing — {periodo_atual}
|
||||||
|
*Gerado em {data_hora_atual} | Descomplicar®*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Trend Researcher — O Que Mudou Esta Semana
|
||||||
|
|
||||||
|
> Tendências relevantes para o negócio (marketing digital, SEO, WordPress, automação)
|
||||||
|
|
||||||
|
**[Tendência 1]**
|
||||||
|
_Fonte: [URL]_
|
||||||
|
Impacto potencial: [curto resumo do que muda para a Descomplicar]
|
||||||
|
|
||||||
|
**[Tendência 2]**
|
||||||
|
_Fonte: [URL]_
|
||||||
|
Impacto potencial: [curto resumo]
|
||||||
|
|
||||||
|
**[Tendência 3]**
|
||||||
|
_Fonte: [URL]_
|
||||||
|
Impacto potencial: [curto resumo]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Analytics Reporter — Métricas vs Semana Anterior
|
||||||
|
|
||||||
|
### Produtividade
|
||||||
|
| Métrica | Semana Anterior | Esta Semana | Δ |
|
||||||
|
|---------|----------------|-------------|---|
|
||||||
|
| Horas registadas | X h | Y h | ±Z% |
|
||||||
|
| Tarefas concluídas | X | Y | ±Z |
|
||||||
|
| Tickets abertos | X | Y | ±Z |
|
||||||
|
|
||||||
|
### Pipeline Comercial
|
||||||
|
| Métrica | Valor | Estado |
|
||||||
|
|---------|-------|--------|
|
||||||
|
| Facturação semana ant | {valor} EUR | {vs média} |
|
||||||
|
| Leads novos | X | — |
|
||||||
|
| Propostas pendentes | X | Total: Y EUR |
|
||||||
|
| Propostas aceites | X | Total: Y EUR |
|
||||||
|
|
||||||
|
### Agenda da Semana
|
||||||
|
| Data | Evento |
|
||||||
|
|------|--------|
|
||||||
|
| {DD Mmm} | {evento} |
|
||||||
|
| … | … |
|
||||||
|
|
||||||
|
> Fontes: Desk CRM + Moloni + Google Calendar
|
||||||
|
> Dados Google Analytics / GSC: configurar via /n8n-webhook ou GSC MCP
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Growth Hacker — 1 Acção Para Esta Semana
|
||||||
|
|
||||||
|
**Acção:** [Nome curto e concreto]
|
||||||
|
|
||||||
|
**Porquê agora:** [Justificação baseada nos dados das secções 1 e 2]
|
||||||
|
|
||||||
|
**3 Passos para executar:**
|
||||||
|
|
||||||
|
1. **[Passo 1]** — [Descrição detalhada, quem faz, quando]
|
||||||
|
2. **[Passo 2]** — [Descrição detalhada, ferramentas necessárias]
|
||||||
|
3. **[Passo 3]** — [Métrica de validação: como saber que funcionou]
|
||||||
|
|
||||||
|
**Tempo estimado:** X horas
|
||||||
|
**Impacto esperado:** [Métrica específica]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Reality Checker — Contra-Argumentos
|
||||||
|
|
||||||
|
> Questionar os pressupostos das secções anteriores antes de agir.
|
||||||
|
|
||||||
|
**Sobre as tendências (secção 1):**
|
||||||
|
- [Contra-argumento]: Pode ser que [tendência X] não se aplique porque [razão específica ao contexto Descomplicar]
|
||||||
|
- Pergunta a fazer: Temos capacidade para responder a esta tendência esta semana?
|
||||||
|
|
||||||
|
**Sobre as métricas (secção 2):**
|
||||||
|
- [Contra-argumento]: A variação de [±Z%] pode ser [sazonalidade / evento pontual / dado incompleto]
|
||||||
|
- Atenção: [Métrica Y] está a [subir/descer] — verificar se é tendência real ou ruído
|
||||||
|
|
||||||
|
**Sobre a acção (secção 3):**
|
||||||
|
- [Contra-argumento]: A acção proposta assume que [pressuposto] — validar antes de executar
|
||||||
|
- Risco principal: [O que pode correr mal e como mitigar]
|
||||||
|
- Alternativa mais simples: [Versão reduzida da acção com menor risco]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Próximo briefing: Segunda, {data_prox_segunda} 09:00*
|
||||||
|
*Para agendar: `/schedule "monday-briefing" cron:"0 9 * * 1"`*
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Envio Automático (opcional)
|
||||||
|
|
||||||
|
```
|
||||||
|
SE argumento "email":
|
||||||
|
mcp__google-workspace__gmail_send_email({
|
||||||
|
to: "emanuelalmeidaa@gmail.com",
|
||||||
|
subject: "Monday Briefing — {periodo_atual}",
|
||||||
|
body: {output_markdown_acima},
|
||||||
|
format: "html"
|
||||||
|
})
|
||||||
|
|
||||||
|
SE argumento "inbox" OU sem argumento:
|
||||||
|
Guardar em: /media/ealmeida/Dados/Hub/00-Inbox/monday-briefing-{YYYY-MM-DD}.md
|
||||||
|
Formato: frontmatter YAML + conteúdo markdown
|
||||||
|
|
||||||
|
SE argumento "terminal":
|
||||||
|
Mostrar directamente no terminal (default)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Como Agendar
|
||||||
|
|
||||||
|
Para receber automaticamente todas as segundas às 9h:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Via skill /schedule:
|
||||||
|
/schedule "monday-briefing" cron:"0 9 * * 1"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Fontes de Dados
|
||||||
|
|
||||||
|
| Fonte | MCP / Ferramenta | Dados |
|
||||||
|
|-------|-----------------|-------|
|
||||||
|
| Desk CRM | `mcp__desk-crm-v3` | Tarefas, tickets, timesheets, leads, propostas |
|
||||||
|
| Moloni | `mcp__moloni-mcp` | Facturação semanal |
|
||||||
|
| Google Calendar | `mcp__google-workspace` | Agenda da semana |
|
||||||
|
| Tendências | `WebSearch` | Novidades mercado digital |
|
||||||
|
| Google Analytics | n8n BI workflow | Sessions, conversões (a configurar) |
|
||||||
|
| Google Search Console | GSC MCP (quando disponível) | Keywords, cliques orgânicos |
|
||||||
|
|
||||||
|
> GA4 e GSC: quando MCPs dedicados estiverem configurados, adicionar ao Passo 2[A]. Ver `/n8n-webhook` para workflow BI existente.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Anti-Patterns
|
||||||
|
|
||||||
|
- NUNCA bloquear o briefing por falta de dados GA4/GSC — usar "N/D" e continuar
|
||||||
|
- NUNCA inventar tendências — apenas WebSearch com fontes verificáveis
|
||||||
|
- NUNCA recomendar mais de 1 acção na secção 3 (Growth Hacker)
|
||||||
|
- SEMPRE usar mcp-time para calcular períodos (nunca assumir datas)
|
||||||
|
- SEMPRE incluir secção Reality Checker — é o que diferencia este briefing
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Skill v1.0.0 | 07-04-2026 | Descomplicar®*
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: reflect
|
name: reflect
|
||||||
description: Alias de /worklog. Auto-reflexão e registo de trabalho unificado. /reflect = /worklog (mesmo resultado). /reflect deep = análise profunda com histórico. /reflect week = revisão semanal. Usar quando "reflect", "reflexão", "análise", "melhoria", "insight".
|
description: Alias de /worklog. Auto-reflexão e registo de trabalho unificado. /reflect = /worklog (mesmo resultado). /reflect view = ver últimos registos. /reflect deep = análise profunda com histórico → Discussão #32. /reflect week = revisão semanal → Discussão #32. Usar quando "reflect", "reflexão", "análise", "melhoria", "insight".
|
||||||
context: fork
|
context: fork
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -8,15 +8,18 @@ context: fork
|
|||||||
|
|
||||||
**`/reflect` = `/worklog`** - Produzem o mesmo resultado.
|
**`/reflect` = `/worklog`** - Produzem o mesmo resultado.
|
||||||
|
|
||||||
Desde v4.0, worklog e reflect estao unificados. Toda a logica, formatos e workflows estao em `/worklog`.
|
Desde v4.0, worklog e reflect estao unificados. Toda a logica, formatos e workflows estao em `/worklog` (v4.2.0).
|
||||||
|
|
||||||
## Comandos
|
## Comandos
|
||||||
|
|
||||||
| Comando | Equivalente | Descrição |
|
| Comando | Equivalente worklog | Descrição |
|
||||||
|---------|-------------|-----------|
|
|---------|---------------------|-----------|
|
||||||
| `/reflect` | `/worklog` | Registo + reflexão da sessão → Discussão #31 |
|
| `/reflect` | `/worklog` | Registo + reflexão da sessão → Discussão #31 |
|
||||||
| `/reflect deep` | (exclusivo) | Análise profunda com histórico → Discussão #32 |
|
| `/reflect view` | `/worklog view` | Ver últimos registos (discussão #31) |
|
||||||
| `/reflect week` | (exclusivo) | Revisão semanal → Discussão #32 |
|
| `/reflect deep` | `/reflect deep` | Análise profunda com histórico → Discussão #32 |
|
||||||
|
| `/reflect week` | `/reflect week` | Revisão semanal → Discussão #32 |
|
||||||
|
|
||||||
|
> **Nota:** `/reflect deep` e `/reflect week` são comandos partilhados — existem tanto no worklog como aqui. Não são exclusivos do reflect.
|
||||||
|
|
||||||
## Instrução
|
## Instrução
|
||||||
|
|
||||||
@@ -24,9 +27,26 @@ Ao receber `/reflect` (sem argumentos):
|
|||||||
1. Executar exactamente o protocolo de `/worklog`
|
1. Executar exactamente o protocolo de `/worklog`
|
||||||
2. Ver skill `/worklog` (SKILL.md) para formato, workflow e storage
|
2. Ver skill `/worklog` (SKILL.md) para formato, workflow e storage
|
||||||
|
|
||||||
|
Ao receber `/reflect view`:
|
||||||
|
1. Executar o protocolo de `/worklog view` (ver secção em `/worklog` SKILL.md)
|
||||||
|
|
||||||
Ao receber `/reflect deep` ou `/reflect week`:
|
Ao receber `/reflect deep` ou `/reflect week`:
|
||||||
1. Ver secções específicas na skill `/worklog`
|
1. Ver secções específicas na skill `/worklog`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
*Skill v4.0.0 | 2026-02-06 | Descomplicar(R)*
|
*Skill v4.0.1 | 2026-04-06 | Descomplicar(R)*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Healing Log
|
||||||
|
|
||||||
|
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||||
|
|
||||||
|
```jsonl
|
||||||
|
{"date":"2026-04-06","issue":"Comandos /reflect deep e /reflect week marcados como '(exclusivo)' na tabela mas existem no worklog SKILL.md — causava confusão sobre origem dos comandos","fix":"Remover '(exclusivo)', mapear correctamente para equivalente worklog e adicionar nota explicativa","source":"auto"}
|
||||||
|
{"date":"2026-04-06","issue":"Versão reflect desactualizada (v4.0.0) face a worklog (v4.2.0) — utilizador podia assumir reflect obsoleto","fix":"Actualizar referência de versão do worklog para v4.2.0 na descrição; reflect mantém v4.0.1 (alias sem lógica própria)","source":"auto"}
|
||||||
|
{"date":"2026-04-06","issue":"/worklog view não referenciado em reflect — utilizador com /reflect não sabia como ver registos anteriores","fix":"Adicionar /reflect view como alias de /worklog view na tabela de comandos e na secção de instrução","source":"auto"}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Adicionar nova linha após cada erro corrigido.*
|
||||||
|
|||||||
Reference in New Issue
Block a user