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:
@@ -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.*
|
||||
Reference in New Issue
Block a user