feat(gestao): adicionar 9 skills /clip-* + migrar 5 para diag tools MCP

Skills clip-* nunca tinham sido committed. Adicionadas todas (9):
clip, clip-agent, clip-health, clip-instructions, clip-issue, clip-org,
clip-routine, clip-skill, clip-vision.

Migração para mcp__paperclip__diag_* (17 substituições em 5 skills):
- clip: 5 substituições (agents_by_status, false_blockers, token burn,
  stuck routines, company_skills_summary)
- clip-agent: 2 (agent_full_context consolida 4 passos, false_blockers)
- clip-health: 8 (budget_orphans, missing_permissions, missing_heartbeat,
  routine_triggers_broken, false_blockers, heartbeat_token_usage,
  prompt_too_long_errors, stuck_routines, zombie_parents)
- clip-org: 1 (agent_hierarchy)
- clip-routine: 1 (routine_triggers_broken)

Sem substituições (CRUD-específico sem diag_* equivalente):
clip-instructions, clip-issue, clip-skill — mantêm psql.

Refs: Desk #2041, mcp-paperclip feature/diagnostics-db

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-07 03:59:54 +01:00
parent 2252e1c29c
commit 6285be6c2e
9 changed files with 2247 additions and 0 deletions
+340
View File
@@ -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.*
+398
View File
@@ -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.*
+184
View File
@@ -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"}
```
+200
View File
@@ -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.*
+148
View File
@@ -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.*
+349
View File
@@ -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.*
+292
View File
@@ -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.*
+174
View File
@@ -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"}
```
+162
View File
@@ -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.*