diff --git a/gestao/skills/clip-agent/SKILL.md b/gestao/skills/clip-agent/SKILL.md new file mode 100644 index 0000000..cf07aa1 --- /dev/null +++ b/gestao/skills/clip-agent/SKILL.md @@ -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.* diff --git a/gestao/skills/clip-health/SKILL.md b/gestao/skills/clip-health/SKILL.md new file mode 100644 index 0000000..e451ee7 --- /dev/null +++ b/gestao/skills/clip-health/SKILL.md @@ -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.* diff --git a/gestao/skills/clip-instructions/SKILL.md b/gestao/skills/clip-instructions/SKILL.md new file mode 100644 index 0000000..49b982a --- /dev/null +++ b/gestao/skills/clip-instructions/SKILL.md @@ -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"} +``` diff --git a/gestao/skills/clip-issue/SKILL.md b/gestao/skills/clip-issue/SKILL.md new file mode 100644 index 0000000..02d2938 --- /dev/null +++ b/gestao/skills/clip-issue/SKILL.md @@ -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.* diff --git a/gestao/skills/clip-org/SKILL.md b/gestao/skills/clip-org/SKILL.md new file mode 100644 index 0000000..d6948b2 --- /dev/null +++ b/gestao/skills/clip-org/SKILL.md @@ -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.* diff --git a/gestao/skills/clip-routine/SKILL.md b/gestao/skills/clip-routine/SKILL.md new file mode 100644 index 0000000..0fbcf36 --- /dev/null +++ b/gestao/skills/clip-routine/SKILL.md @@ -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.* diff --git a/gestao/skills/clip-skill/SKILL.md b/gestao/skills/clip-skill/SKILL.md new file mode 100644 index 0000000..e81eaa6 --- /dev/null +++ b/gestao/skills/clip-skill/SKILL.md @@ -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.* diff --git a/gestao/skills/clip-vision/SKILL.md b/gestao/skills/clip-vision/SKILL.md new file mode 100644 index 0000000..69a4236 --- /dev/null +++ b/gestao/skills/clip-vision/SKILL.md @@ -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"} +``` diff --git a/gestao/skills/clip/SKILL.md b/gestao/skills/clip/SKILL.md new file mode 100644 index 0000000..17b1e48 --- /dev/null +++ b/gestao/skills/clip/SKILL.md @@ -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.*