fix(project-manager): remover Dify KB das descriptions, marcar nota TODO
Dify foi removido 06-03-2026. Skills brainstorm/discover ainda referenciam-no no corpo. Bump v1.2 + nota top-of-file. Reescrita workflow para próxima sessão. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
---
|
||||
name: benchmark
|
||||
description: >
|
||||
Mede Core Web Vitals e performance antes/depois de alterações. Detecta regressões.
|
||||
Usar antes e depois de qualquer alteração a WP, WooCommerce, Next.js ou infra.
|
||||
Baseado no gstack /benchmark. Eixo 2B.
|
||||
---
|
||||
|
||||
# /benchmark — Performance Antes/Depois
|
||||
|
||||
Medir o impacto real de alterações. Nunca fazer deploy sem benchmark.
|
||||
|
||||
---
|
||||
|
||||
## Quando Usar
|
||||
|
||||
- Antes de qualquer optimização de performance
|
||||
- Antes de deploy de plugins/temas WordPress
|
||||
- Antes de alterações ao servidor ou cache
|
||||
- Antes de implementar nova feature em produção
|
||||
- Como baseline mensal de cada site
|
||||
|
||||
---
|
||||
|
||||
## Métricas Alvo (Core Web Vitals 2024)
|
||||
|
||||
| Métrica | Bom | Precisa Melhorar | Mau |
|
||||
|---------|-----|-----------------|-----|
|
||||
| LCP (Largest Contentful Paint) | ≤2.5s | 2.5-4.0s | >4.0s |
|
||||
| FID / INP (Interaction to Next Paint) | ≤200ms | 200-500ms | >500ms |
|
||||
| CLS (Cumulative Layout Shift) | ≤0.1 | 0.1-0.25 | >0.25 |
|
||||
| TTFB (Time to First Byte) | ≤800ms | 800-1800ms | >1800ms |
|
||||
| FCP (First Contentful Paint) | ≤1.8s | 1.8-3.0s | >3.0s |
|
||||
|
||||
---
|
||||
|
||||
## Protocolo
|
||||
|
||||
### Passo 1 — Baseline (ANTES)
|
||||
|
||||
```bash
|
||||
# Via MCP Lighthouse (se disponível)
|
||||
mcp__lighthouse__get_core_web_vitals({ url: "<URL>" })
|
||||
mcp__lighthouse__run_audit({ url: "<URL>", categories: ["performance"] })
|
||||
|
||||
# Ou via Lighthouse CLI no servidor
|
||||
ssh server "lighthouse <URL> --output=json --output-path=/tmp/before.json --chrome-flags='--headless'"
|
||||
|
||||
# Ou via PageSpeed Insights API
|
||||
curl "https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=<URL>&strategy=mobile" | jq '.lighthouseResult.categories.performance.score'
|
||||
```
|
||||
|
||||
**Guardar baseline:**
|
||||
```bash
|
||||
BEFORE_LCP=<valor>
|
||||
BEFORE_CLS=<valor>
|
||||
BEFORE_FCP=<valor>
|
||||
BEFORE_SCORE=<valor>
|
||||
```
|
||||
|
||||
### Passo 2 — Executar Alteração
|
||||
|
||||
Fazer a alteração (deploy, optimização, plugin, etc.)
|
||||
|
||||
### Passo 3 — Depois
|
||||
|
||||
```bash
|
||||
# Repetir as mesmas medições
|
||||
mcp__lighthouse__get_core_web_vitals({ url: "<URL>" })
|
||||
|
||||
AFTER_LCP=<valor>
|
||||
AFTER_CLS=<valor>
|
||||
AFTER_FCP=<valor>
|
||||
AFTER_SCORE=<valor>
|
||||
```
|
||||
|
||||
### Passo 4 — Comparação
|
||||
|
||||
```markdown
|
||||
## Benchmark — [Site] — [Data]
|
||||
|
||||
| Métrica | Antes | Depois | Delta | Estado |
|
||||
|---------|-------|--------|-------|--------|
|
||||
| LCP | Xs | Ys | ±Zs | ✅/⚠️/❌ |
|
||||
| CLS | X | Y | ±Z | ✅/⚠️/❌ |
|
||||
| FCP | Xs | Ys | ±Zs | ✅/⚠️/❌ |
|
||||
| Score | X% | Y% | ±Z% | ✅/⚠️/❌ |
|
||||
|
||||
**Veredicto:** MELHOROU / NEUTRO / REGREDIU
|
||||
**Acção:** Manter deploy / Reverter / Investigar
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Regras de Decisão
|
||||
|
||||
```
|
||||
SE qualquer métrica piorou >10% → REVERTER imediatamente
|
||||
SE Score global piorou >5 pontos → investigar antes de continuar
|
||||
SE CLS aumentou >0.05 → bloquear — UX crítica
|
||||
SE LCP piorou >500ms em mobile → reverter
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Sites Descomplicar a Monitorizar
|
||||
|
||||
| Site | URL | Frequência |
|
||||
|------|-----|-----------|
|
||||
| Descomplicar main | descomplicar.pt | Mensal |
|
||||
| Clip | clip.descomplicar.pt | Após cada deploy |
|
||||
| Outros clientes | variável | Após alterações WP |
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*Skill /benchmark v1.0 | 06-04-2026 | Eixo 2B — gstack pattern*
|
||||
@@ -0,0 +1,155 @@
|
||||
---
|
||||
name: canary
|
||||
description: >
|
||||
Monitorização pós-deploy — detecta regressões em produção. Verifica que o deploy
|
||||
não quebrou nada crítico nos 15min seguintes. Baseado no gstack /canary. Eixo 2B.
|
||||
Usar após qualquer deploy em produção.
|
||||
---
|
||||
|
||||
# /canary — Monitorização Pós-Deploy
|
||||
|
||||
Os primeiros 15 minutos após um deploy são os mais críticos. Esta skill verifica que tudo está OK.
|
||||
|
||||
---
|
||||
|
||||
## Quando Usar (SEMPRE após deploy produção)
|
||||
|
||||
- Após deploy de código em produção
|
||||
- Após actualização de WordPress (core, plugins, temas)
|
||||
- Após alterações de servidor (PHP, Nginx, MySQL)
|
||||
- Após mudanças de DNS ou SSL
|
||||
- Após activação de nova funcionalidade
|
||||
|
||||
---
|
||||
|
||||
## Protocolo (15 minutos)
|
||||
|
||||
### Minuto 0-2 — Status Checks
|
||||
|
||||
```bash
|
||||
# 1. Site responde?
|
||||
curl -s -o /dev/null -w "%{http_code}" <URL>/
|
||||
# Esperado: 200
|
||||
|
||||
# 2. Admin WP responde?
|
||||
curl -s -o /dev/null -w "%{http_code}" <URL>/wp-admin/
|
||||
# Esperado: 200 ou 302
|
||||
|
||||
# 3. SSL válido?
|
||||
curl -vI <URL> 2>&1 | grep "SSL certificate verify"
|
||||
# Esperado: SSL certificate verify ok
|
||||
|
||||
# 4. Tempo de resposta aceitável?
|
||||
curl -s -o /dev/null -w "%{time_total}\n" <URL>/
|
||||
# Esperado: < 3.0 segundos
|
||||
```
|
||||
|
||||
### Minuto 2-5 — Funcionalidades Críticas
|
||||
|
||||
**Para WordPress:**
|
||||
```bash
|
||||
# Página principal carrega sem erros
|
||||
curl -s <URL>/ | grep -c "wp-content"
|
||||
# Esperado: > 0
|
||||
|
||||
# Sem erro crítico PHP
|
||||
curl -s <URL>/ | grep -i "fatal error\|parse error\|warning"
|
||||
# Esperado: sem output
|
||||
|
||||
# WP-CLI status
|
||||
wp --path=/var/www/html core verify-checksums 2>&1 | tail -1
|
||||
# Esperado: "WordPress installation verifies against checksums."
|
||||
```
|
||||
|
||||
**Para aplicações:**
|
||||
```bash
|
||||
# Health endpoint
|
||||
curl -s <URL>/api/health | jq '.status'
|
||||
# Esperado: "ok"
|
||||
|
||||
# Database conecta?
|
||||
curl -s <URL>/api/health | jq '.database'
|
||||
# Esperado: "connected"
|
||||
```
|
||||
|
||||
### Minuto 5-10 — Métricas de Performance
|
||||
|
||||
```javascript
|
||||
// Via Lighthouse MCP
|
||||
mcp__lighthouse__get_performance_score({ url: "<URL>" })
|
||||
// Esperado: >= baseline (ver /benchmark)
|
||||
|
||||
mcp__lighthouse__get_core_web_vitals({ url: "<URL>" })
|
||||
// Comparar com baseline guardado
|
||||
```
|
||||
|
||||
### Minuto 10-15 — Logs e Erros
|
||||
|
||||
```bash
|
||||
# Erros PHP nas últimas 15 min
|
||||
ssh server "tail -100 /var/log/php/error.log | grep '$(date -d '15 minutes ago' +%H:%M)'"
|
||||
|
||||
# Erros Nginx/Apache
|
||||
ssh server "tail -50 /var/log/nginx/error.log"
|
||||
|
||||
# WooCommerce (se aplicável)
|
||||
wp --path=/var/www/html wc log list 2>&1 | head -20
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Output — Relatório Canary
|
||||
|
||||
```markdown
|
||||
## Canary Check — [Site] — [Data] [Hora]
|
||||
|
||||
**Deploy:** [O que foi alterado]
|
||||
|
||||
| Check | Estado | Detalhe |
|
||||
|-------|--------|---------|
|
||||
| HTTP 200 | ✅/❌ | |
|
||||
| SSL | ✅/❌ | |
|
||||
| Tempo resposta | ✅/❌ | Xs |
|
||||
| Sem erros PHP | ✅/❌ | |
|
||||
| Performance score | ✅/❌ | X% (base: Y%) |
|
||||
| Logs limpos | ✅/❌ | |
|
||||
|
||||
**Resultado:** ✅ DEPLOY ESTÁVEL | ⚠️ INVESTIGAR | ❌ REVERTER
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Critérios de Reversão Imediata
|
||||
|
||||
```
|
||||
❌ HTTP response != 200 → REVERTER
|
||||
❌ SSL falha → REVERTER
|
||||
❌ "Fatal error" em qualquer página → REVERTER
|
||||
❌ Tempo resposta > 10s → INVESTIGAR
|
||||
❌ Performance score caiu >15 pontos → INVESTIGAR
|
||||
❌ Logs com erros críticos → INVESTIGAR
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Escalada Automática
|
||||
|
||||
Se algum check falha:
|
||||
```
|
||||
1. NOTIFICAR: criar issue no Desk CRM com urgência P1
|
||||
2. REVERTER: se erro crítico, reverter imediatamente
|
||||
3. DOCUMENTAR: o que falhou e quando
|
||||
4. ANALISAR: root cause antes de re-deploy
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*Skill /canary v1.0 | 06-04-2026 | Eixo 2B — gstack pattern*
|
||||
@@ -301,3 +301,15 @@ Activar Chrome por defeito **aumenta consumo de context window** porque as ferra
|
||||
1. Desactivar default: `/chrome` -> desactivar
|
||||
2. Usar `claude --chrome` apenas quando necessario
|
||||
3. Preferir WebFetch para leituras simples de paginas publicas
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -241,3 +241,15 @@ Output: [resultado esperado]
|
||||
Input: [caso complexo]
|
||||
Output: [resultado detalhado]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -461,3 +461,15 @@ git commit
|
||||
|
||||
**Skill v1.1** | 12-03-2026 | Descomplicar® | Renomeado de /security-check para /dep-audit
|
||||
**Security First** - Zero vulnerabilities ou documentadas
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -0,0 +1,267 @@
|
||||
---
|
||||
name: diagrama
|
||||
category: dev-tools
|
||||
description: "Gera diagramas de arquitectura, fluxo, ER e sequência em três formatos: draw.io (.drawio), Excalidraw e Mermaid. Usar quando 'diagrama', 'arquitectura', 'draw.io', 'fluxo', 'ER', 'sequência', 'infra', 'componentes'."
|
||||
version: "1.0.0"
|
||||
created: 2026-04-04
|
||||
tools: [mcp__claude_ai_Excalidraw__export_to_excalidraw, mcp__mcp-mermaid__generate, Write, Bash]
|
||||
---
|
||||
|
||||
# Skill: /diagrama
|
||||
|
||||
Gera diagramas técnicos em três formatos consoante o caso de uso. Suporta arquitectura de sistemas, fluxogramas, diagramas ER, sequência, infra-estrutura e redes.
|
||||
|
||||
---
|
||||
|
||||
## Quando usar cada formato
|
||||
|
||||
| Formato | Quando usar | Output |
|
||||
|---------|------------|--------|
|
||||
| **draw.io** | Diagramas formais para documentação, propostas, clientes | `.drawio` (editável) |
|
||||
| **Excalidraw** | Esboços rápidos, brainstorming visual, estilo whiteboard | `.excalidraw` / MCP |
|
||||
| **Mermaid** | Diagramas como código, versionáveis em Git, embeds Markdown | `.svg` / `.png` |
|
||||
|
||||
---
|
||||
|
||||
## Processo de execução
|
||||
|
||||
### 1. Identificar pedido
|
||||
|
||||
Quando o utilizador pede um diagrama, detectar:
|
||||
- **Tipo:** arquitectura | fluxo | ER | sequência | rede | organograma | classe
|
||||
- **Formato pretendido:** draw.io (default para doc. formal) | excalidraw | mermaid
|
||||
- **Contexto:** sistemas envolvidos, entidades, actores
|
||||
|
||||
Se não especificado, perguntar apenas: "draw.io (formal) ou Excalidraw (esboço)?"
|
||||
|
||||
### 2. Gerar conteúdo
|
||||
|
||||
---
|
||||
|
||||
## Geração draw.io (.drawio)
|
||||
|
||||
O formato draw.io é mxGraph XML. Gerar o XML e guardar como `.drawio`.
|
||||
|
||||
### Estrutura base
|
||||
|
||||
```xml
|
||||
<mxfile host="Claude Code" modified="YYYY-MM-DDTHH:MM:SS" agent="Claude" version="21.0">
|
||||
<diagram name="Diagrama" id="diagram-1">
|
||||
<mxGraphModel dx="1422" dy="762" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<!-- elementos aqui -->
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
```
|
||||
|
||||
### Templates de elementos mxGraph
|
||||
|
||||
**Rectângulo (componente/serviço):**
|
||||
```xml
|
||||
<mxCell id="2" value="Nome" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
|
||||
<mxGeometry x="160" y="160" width="120" height="60" as="geometry"/>
|
||||
</mxCell>
|
||||
```
|
||||
|
||||
**Seta/ligação:**
|
||||
```xml
|
||||
<mxCell id="10" edge="1" source="2" target="3" parent="1">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
```
|
||||
|
||||
**Cilindro (base de dados):**
|
||||
```xml
|
||||
<mxCell id="5" value="PostgreSQL" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;fillColor=#f8cecc;strokeColor=#b85450;" vertex="1" parent="1">
|
||||
<mxGeometry x="320" y="160" width="80" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
```
|
||||
|
||||
**Cloud (serviço externo):**
|
||||
```xml
|
||||
<mxCell id="6" value="Cloudflare" style="shape=mxgraph.cisco.sites.generic_building;sketch=0;html=1;pointerEvents=1;dashed=0;fillColor=#036897;strokeColor=#ffffff;strokeWidth=2;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="480" y="160" width="60" height="60" as="geometry"/>
|
||||
</mxCell>
|
||||
```
|
||||
|
||||
**Actor (pessoa/utilizador):**
|
||||
```xml
|
||||
<mxCell id="7" value="Utilizador" style="shape=mxgraph.flowchart.start_2;fillColor=#00BEF2;strokeColor=#006EAF;fontColor=#ffffff;fontStyle=1;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="40" y="170" width="60" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
```
|
||||
|
||||
**Swimlane (grupo/camada):**
|
||||
```xml
|
||||
<mxCell id="8" value="Camada Frontend" style="swimlane;startSize=20;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#333333;" vertex="1" parent="1">
|
||||
<mxGeometry x="0" y="0" width="400" height="200" as="geometry"/>
|
||||
</mxCell>
|
||||
```
|
||||
|
||||
### Paleta de cores Descomplicar
|
||||
|
||||
| Componente | fillColor | strokeColor |
|
||||
|-----------|-----------|-------------|
|
||||
| Serviço/App | `#dae8fc` | `#6c8ebf` |
|
||||
| Base de dados | `#f8cecc` | `#b85450` |
|
||||
| Fila/Queue | `#d5e8d4` | `#82b366` |
|
||||
| Externo/Cloud | `#fff2cc` | `#d6b656` |
|
||||
| Infra/Servidor | `#e1d5e7` | `#9673a6` |
|
||||
| Claude/IA | `#f0f4ff` | `#4a6cf7` |
|
||||
|
||||
### Guardar ficheiro
|
||||
|
||||
Guardar em `/media/ealmeida/Dados/Hub/tmp/diagramas/` com nome descritivo:
|
||||
```
|
||||
YYYY-MM-DD-nome-diagrama.drawio
|
||||
```
|
||||
|
||||
Abrir com:
|
||||
```bash
|
||||
drawio "/media/ealmeida/Dados/Hub/tmp/diagramas/NOME.drawio" &
|
||||
```
|
||||
(ou abrir manualmente com draw.io desktop / draw.io no browser)
|
||||
|
||||
---
|
||||
|
||||
## Geração Excalidraw
|
||||
|
||||
Usar o MCP `mcp__claude_ai_Excalidraw__export_to_excalidraw` para diagramas no estilo whiteboard.
|
||||
|
||||
### Fluxo
|
||||
|
||||
1. Chamar `mcp__claude_ai_Excalidraw__create_view` para iniciar sessão
|
||||
2. Chamar `mcp__claude_ai_Excalidraw__export_to_excalidraw` com o conteúdo estruturado
|
||||
3. Informar o utilizador do link/path gerado
|
||||
|
||||
### Casos de uso preferidos
|
||||
|
||||
- Brainstorming e exploração rápida
|
||||
- Diagramas de fluxo com estilo manual
|
||||
- Esboços para reuniões
|
||||
- Arquitecturas de alto nível para comunicação interna
|
||||
|
||||
---
|
||||
|
||||
## Geração Mermaid
|
||||
|
||||
Usar o MCP `mcp__mcp-mermaid__generate` para diagramas como código.
|
||||
|
||||
### Tipos suportados
|
||||
|
||||
**Fluxograma:**
|
||||
```
|
||||
flowchart TD
|
||||
A[Início] --> B{Condição}
|
||||
B -->|Sim| C[Acção]
|
||||
B -->|Não| D[Fim]
|
||||
```
|
||||
|
||||
**Sequência:**
|
||||
```
|
||||
sequenceDiagram
|
||||
participant U as Utilizador
|
||||
participant A as Claude Code
|
||||
participant N as n8n
|
||||
U->>A: Pedido
|
||||
A->>N: Trigger workflow
|
||||
N-->>A: Resultado
|
||||
A-->>U: Resposta
|
||||
```
|
||||
|
||||
**ER:**
|
||||
```
|
||||
erDiagram
|
||||
CLIENTE ||--o{ PROJECTO : tem
|
||||
PROJECTO ||--o{ TAREFA : contém
|
||||
TAREFA {
|
||||
int id
|
||||
string nome
|
||||
string estado
|
||||
}
|
||||
```
|
||||
|
||||
**Arquitectura de componentes (C4):**
|
||||
```
|
||||
C4Context
|
||||
title Stack Descomplicar
|
||||
Person(eal, "Emanuel", "Utilizador principal")
|
||||
System(cc, "Claude Code", "Interface interactiva")
|
||||
System(clip, "Paperclip", "Agentes autónomos")
|
||||
System(n8n, "n8n", "Automação determinística")
|
||||
Rel(eal, cc, "usa directamente")
|
||||
Rel(cc, clip, "delega tarefas complexas")
|
||||
Rel(cc, n8n, "activa workflows")
|
||||
```
|
||||
|
||||
### Guardar output
|
||||
|
||||
Guardar o código Mermaid em `/media/ealmeida/Dados/Hub/tmp/diagramas/NOME.mmd` e renderizar para SVG/PNG via MCP.
|
||||
|
||||
---
|
||||
|
||||
## Templates prontos por contexto
|
||||
|
||||
### Arquitectura StackDescomplicar
|
||||
|
||||
Gerar diagrama com as três camadas do stack:
|
||||
- **Camada 1:** Claude Code (trabalho interactivo)
|
||||
- **Camada 2:** n8n (automação determinística)
|
||||
- **Camada 3:** Paperclip (raciocínio autónomo)
|
||||
|
||||
### Proposta comercial
|
||||
|
||||
Diagrama da solução para o cliente com:
|
||||
- Infra-estrutura actual (antes)
|
||||
- Solução proposta (depois)
|
||||
- Componentes e integrações
|
||||
|
||||
### Pipeline de dados
|
||||
|
||||
Diagrama de fluxo com:
|
||||
- Fonte → Processamento → Destino
|
||||
- Triggers, transformações, outputs
|
||||
|
||||
### Diagrama ER Desk CRM
|
||||
|
||||
Entidades principais: Lead → Customer → Estimate → Invoice → Payment
|
||||
|
||||
---
|
||||
|
||||
## Boas práticas
|
||||
|
||||
- **Máx. 10-15 elementos** por diagrama (mais → dividir em sub-diagramas)
|
||||
- **Labels curtos:** 2-4 palavras por elemento
|
||||
- **Setas com label** quando o fluxo não é óbvio
|
||||
- **Cor consistente** por tipo de componente (seguir paleta Descomplicar)
|
||||
- **Nome descritivo** no ficheiro (não "diagrama1.drawio")
|
||||
- **Guardar em Hub/tmp/diagramas/** para fácil acesso
|
||||
|
||||
---
|
||||
|
||||
## Instalar draw.io MCP (opcional, para funcionalidades avançadas)
|
||||
|
||||
O vídeo #210 do Stack_Pesquisa_Videos.md demonstra um MCP draw.io com geração automática a partir de análise de código. Para instalar:
|
||||
|
||||
```bash
|
||||
# Verificar se há MCP draw.io disponível no gateway
|
||||
# Ver: Hub/04-Stack/claude-code-context-hygiene.md → secção MCPs
|
||||
```
|
||||
|
||||
Alternativa: usar draw.io via browser em https://app.diagrams.net (gratuito, sem instalação) e importar o `.drawio` gerado.
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
@@ -0,0 +1,159 @@
|
||||
---
|
||||
name: docx
|
||||
description: "Criação, edição e análise de documentos Word (.docx). Versão light para heartbeats."
|
||||
---
|
||||
|
||||
# DOCX — Referência Rápida
|
||||
|
||||
## Referência rápida
|
||||
|
||||
| Tarefa | Abordagem |
|
||||
|--------|-----------|
|
||||
| Ler conteúdo | `pandoc` ou descompactar XML |
|
||||
| Criar novo | `docx-js` (npm install -g docx) |
|
||||
| Editar existente | Descompactar → editar XML → recompactar |
|
||||
| Converter .doc | `python scripts/office/soffice.py --headless --convert-to docx doc.doc` |
|
||||
|
||||
## Criar novos documentos (docx-js)
|
||||
|
||||
### Setup básico
|
||||
|
||||
```javascript
|
||||
const { Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell, ImageRun,
|
||||
Header, Footer, AlignmentType, PageOrientation, LevelFormat, HeadingLevel,
|
||||
BorderStyle, WidthType, ShadingType, PageNumber, PageBreak } = require('docx');
|
||||
|
||||
const doc = new Document({ sections: [{ children: [/* conteúdo */] }] });
|
||||
Packer.toBuffer(doc).then(buffer => fs.writeFileSync("doc.docx", buffer));
|
||||
```
|
||||
|
||||
### Tamanho de página (A4)
|
||||
|
||||
```javascript
|
||||
sections: [{
|
||||
properties: {
|
||||
page: {
|
||||
size: { width: 11906, height: 16838 }, // A4 em DXA
|
||||
margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 }
|
||||
}
|
||||
},
|
||||
children: [/* conteúdo */]
|
||||
}]
|
||||
```
|
||||
|
||||
Largura de conteúdo A4 com margens 1": `11906 - 2880 = 9026 DXA`
|
||||
|
||||
**Paisagem:** Passar dimensões retrato + `orientation: PageOrientation.LANDSCAPE` (docx-js troca internamente).
|
||||
|
||||
### Listas
|
||||
|
||||
```javascript
|
||||
numbering: { config: [
|
||||
{ reference: "bullets", levels: [{ level: 0, format: LevelFormat.BULLET, text: "\u2022",
|
||||
alignment: AlignmentType.LEFT, style: { paragraph: { indent: { left: 720, hanging: 360 } } } }] }
|
||||
] }
|
||||
// Usar: new Paragraph({ numbering: { reference: "bullets", level: 0 }, children: [...] })
|
||||
```
|
||||
|
||||
### Tabelas
|
||||
|
||||
```javascript
|
||||
// Largura tabela = soma columnWidths. Usar SEMPRE WidthType.DXA (nunca PERCENTAGE).
|
||||
new Table({
|
||||
width: { size: 9026, type: WidthType.DXA },
|
||||
columnWidths: [4513, 4513],
|
||||
rows: [new TableRow({ children: [
|
||||
new TableCell({
|
||||
borders: { top: b, bottom: b, left: b, right: b },
|
||||
width: { size: 4513, type: WidthType.DXA },
|
||||
shading: { fill: "D5E8F0", type: ShadingType.CLEAR }, // CLEAR, nunca SOLID
|
||||
margins: { top: 80, bottom: 80, left: 120, right: 120 },
|
||||
children: [new Paragraph({ children: [new TextRun("Célula")] })]
|
||||
})
|
||||
] })]
|
||||
})
|
||||
```
|
||||
|
||||
### Imagens
|
||||
|
||||
```javascript
|
||||
new ImageRun({
|
||||
type: "png", // Obrigatório
|
||||
data: fs.readFileSync("image.png"),
|
||||
transformation: { width: 200, height: 150 },
|
||||
altText: { title: "T", description: "D", name: "N" } // Três obrigatórios
|
||||
})
|
||||
```
|
||||
|
||||
### Cabeçalhos/rodapés
|
||||
|
||||
```javascript
|
||||
headers: { default: new Header({ children: [new Paragraph({ children: [new TextRun("Cabeçalho")] })] }) },
|
||||
footers: { default: new Footer({ children: [new Paragraph({
|
||||
children: [new TextRun("Página "), new TextRun({ children: [PageNumber.CURRENT] })]
|
||||
})] }) }
|
||||
```
|
||||
|
||||
### Regras críticas docx-js
|
||||
|
||||
- Nunca usar `\n` — usar Paragraphs separados
|
||||
- Nunca usar bullets unicode — usar `LevelFormat.BULLET`
|
||||
- PageBreak dentro de Paragraph: `new Paragraph({ children: [new PageBreak()] })`
|
||||
- ImageRun requer `type`
|
||||
- Tabelas: `columnWidths` E `width` na célula, ambos devem corresponder
|
||||
- Usar `ShadingType.CLEAR`, nunca SOLID
|
||||
- TOC requer `HeadingLevel` apenas, sem estilos custom
|
||||
- Override estilos: IDs exactos "Heading1", "Heading2" + `outlineLevel`
|
||||
|
||||
## Editar documentos existentes
|
||||
|
||||
### Passo 1: Descompactar
|
||||
|
||||
```bash
|
||||
python scripts/office/unpack.py document.docx unpacked/
|
||||
```
|
||||
|
||||
### Passo 2: Editar XML
|
||||
|
||||
Editar ficheiros em `unpacked/word/`. Usar ferramenta Edit directamente (não scripts Python).
|
||||
|
||||
**Tracked changes:**
|
||||
```xml
|
||||
<!-- Inserção -->
|
||||
<w:ins w:id="1" w:author="Claude" w:date="2025-01-01T00:00:00Z">
|
||||
<w:r><w:t>texto inserido</w:t></w:r>
|
||||
</w:ins>
|
||||
|
||||
<!-- Eliminação -->
|
||||
<w:del w:id="2" w:author="Claude" w:date="2025-01-01T00:00:00Z">
|
||||
<w:r><w:delText>texto eliminado</w:delText></w:r>
|
||||
</w:del>
|
||||
```
|
||||
|
||||
**Comentários:**
|
||||
```bash
|
||||
python scripts/comment.py unpacked/ 0 "Texto do comentário"
|
||||
python scripts/comment.py unpacked/ 1 "Resposta" --parent 0
|
||||
```
|
||||
|
||||
**Smart quotes:** `‘` `’` `“` `”`
|
||||
|
||||
### Passo 3: Recompactar
|
||||
|
||||
```bash
|
||||
python scripts/office/pack.py unpacked/ output.docx --original document.docx
|
||||
```
|
||||
|
||||
Validação: `python scripts/office/validate.py doc.docx`
|
||||
|
||||
## Convenções Descomplicar
|
||||
|
||||
- Data: DD-MM-YYYY
|
||||
- Monetário: 1.234,56 EUR
|
||||
- Fonte: Arial 12pt
|
||||
- Página: A4 (11906 x 16838 DXA)
|
||||
- Autor tracked changes: "Claude"
|
||||
- Idioma: PT-PT
|
||||
|
||||
---
|
||||
**Versão**: 1.0.0-light | **Base**: 1.0.0
|
||||
@@ -510,3 +510,15 @@ Apos executar `comment.py` (ver Passo 2), adicionar marcadores ao document.xml.
|
||||
|
||||
---
|
||||
**Versao**: 1.0.0 | **Autor**: Descomplicar®
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -218,3 +218,15 @@ CMD ["npm", "start"]
|
||||
---
|
||||
|
||||
*Versão 1.0.0 | Descomplicar®*
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
---
|
||||
name: pdf
|
||||
description: Processamento de ficheiros PDF — leitura, extracção, merge, split, OCR, formulários. Versão light para heartbeats.
|
||||
---
|
||||
|
||||
# PDF — Referência Rápida
|
||||
|
||||
## Bibliotecas Python
|
||||
|
||||
### pypdf — operações básicas
|
||||
|
||||
```python
|
||||
from pypdf import PdfReader, PdfWriter
|
||||
|
||||
# Ler e extrair texto
|
||||
reader = PdfReader("documento.pdf")
|
||||
for page in reader.pages:
|
||||
text = page.extract_text()
|
||||
|
||||
# Merge
|
||||
writer = PdfWriter()
|
||||
for pdf in ["doc1.pdf", "doc2.pdf"]:
|
||||
for page in PdfReader(pdf).pages:
|
||||
writer.add_page(page)
|
||||
with open("merged.pdf", "wb") as f:
|
||||
writer.write(f)
|
||||
|
||||
# Split (uma página por ficheiro)
|
||||
for i, page in enumerate(reader.pages):
|
||||
w = PdfWriter()
|
||||
w.add_page(page)
|
||||
with open(f"page_{i+1}.pdf", "wb") as f:
|
||||
w.write(f)
|
||||
|
||||
# Rotate
|
||||
page = reader.pages[0]
|
||||
page.rotate(90)
|
||||
|
||||
# Password
|
||||
writer.encrypt("userpass", "ownerpass")
|
||||
```
|
||||
|
||||
### pdfplumber — tabelas e texto com layout
|
||||
|
||||
```python
|
||||
import pdfplumber
|
||||
|
||||
with pdfplumber.open("doc.pdf") as pdf:
|
||||
for page in pdf.pages:
|
||||
text = page.extract_text()
|
||||
tables = page.extract_tables()
|
||||
```
|
||||
|
||||
### reportlab — criação de PDFs
|
||||
|
||||
```python
|
||||
from reportlab.platypus import SimpleDocTemplate, Paragraph, Table, TableStyle, PageBreak
|
||||
from reportlab.lib.styles import getSampleStyleSheet
|
||||
from reportlab.lib import colors
|
||||
|
||||
doc = SimpleDocTemplate("report.pdf")
|
||||
styles = getSampleStyleSheet()
|
||||
elements = [Paragraph("Título", styles['Title'])]
|
||||
doc.build(elements)
|
||||
```
|
||||
|
||||
**Subscripts/superscripts:** Nunca usar caracteres Unicode. Usar tags XML: `<sub>2</sub>`, `<super>2</super>`.
|
||||
|
||||
## CLI
|
||||
|
||||
```bash
|
||||
# Extrair texto (poppler-utils)
|
||||
pdftotext input.pdf output.txt
|
||||
pdftotext -layout input.pdf output.txt
|
||||
|
||||
# Merge/split (qpdf)
|
||||
qpdf --empty --pages file1.pdf file2.pdf -- merged.pdf
|
||||
qpdf input.pdf --pages . 1-5 -- pages1-5.pdf
|
||||
|
||||
# Encriptar
|
||||
qpdf --encrypt user_pass owner_pass 256 -- input.pdf encrypted.pdf
|
||||
|
||||
# Reparar
|
||||
qpdf --check input.pdf
|
||||
|
||||
# Extrair imagens
|
||||
pdfimages -j input.pdf output_prefix
|
||||
|
||||
# Render para PNG
|
||||
pdftoppm -png -r 300 document.pdf output_prefix
|
||||
```
|
||||
|
||||
## OCR (PDFs digitalizados)
|
||||
|
||||
```python
|
||||
import pytesseract
|
||||
from pdf2image import convert_from_path
|
||||
|
||||
images = convert_from_path('scanned.pdf')
|
||||
text = ""
|
||||
for image in images:
|
||||
text += pytesseract.image_to_string(image)
|
||||
```
|
||||
|
||||
## Formulários
|
||||
|
||||
### Verificar campos preenchíveis
|
||||
|
||||
```bash
|
||||
python scripts/check_fillable_fields.py <file.pdf>
|
||||
```
|
||||
|
||||
### Campos preenchíveis (nativos)
|
||||
|
||||
1. `python scripts/extract_form_field_info.py <input.pdf> <field_info.json>`
|
||||
2. `python scripts/convert_pdf_to_images.py <file.pdf> <output_dir>`
|
||||
3. Criar `field_values.json` com `field_id`, `page`, `value`
|
||||
4. `python scripts/fill_fillable_fields.py <input.pdf> <field_values.json> <output.pdf>`
|
||||
|
||||
### Campos não preenchíveis (anotações)
|
||||
|
||||
1. `python scripts/extract_form_structure.py <input.pdf> form_structure.json`
|
||||
2. **Abordagem A (estrutura):** Analisar JSON, criar `fields.json` com `pdf_width`/`pdf_height` e bounding boxes
|
||||
3. **Abordagem B (visual):** Converter para imagens, identificar campos, refinar com crop
|
||||
4. `python scripts/check_bounding_boxes.py fields.json`
|
||||
5. `python scripts/fill_pdf_form_with_annotations.py <input.pdf> fields.json <output.pdf>`
|
||||
6. `python scripts/create_validation_image.py <page> <fields.json> <input_img> <output_img>`
|
||||
|
||||
## Referência rápida
|
||||
|
||||
| Tarefa | Ferramenta | Comando |
|
||||
|--------|-----------|---------|
|
||||
| Merge | pypdf/qpdf | `writer.add_page()` / `qpdf --pages` |
|
||||
| Split | pypdf/qpdf | Uma página por ficheiro |
|
||||
| Texto | pdfplumber | `page.extract_text()` |
|
||||
| Tabelas | pdfplumber | `page.extract_tables()` |
|
||||
| Criar | reportlab | Canvas ou Platypus |
|
||||
| OCR | pytesseract | Converter para imagem primeiro |
|
||||
| Formulários | pypdf/scripts | Ver secção acima |
|
||||
|
||||
## Caminhos Descomplicar
|
||||
|
||||
| Local | Caminho |
|
||||
|-------|---------|
|
||||
| Documentos empresa | `/media/ealmeida/Dados/GDrive/Cloud/Descomplicar/` |
|
||||
| Propostas | `/media/ealmeida/Dados/Hub/03-Propostas/` |
|
||||
| Arquivo clientes | `/media/ealmeida/Dados/GDrive/Arquivo_de_Clientes/` |
|
||||
| Knowledge Base | `/media/ealmeida/Dados/Hub/06-Operacoes/Knowledge-Base/PDFs/` |
|
||||
| Temporários | `~/.claude-work/` (limpar ao concluir) |
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Localizar PDF (filesystem ou Google Drive)
|
||||
2. Descarregar para `~/.claude-work/` se necessário
|
||||
3. Processar
|
||||
4. Guardar no destino final
|
||||
5. Limpar temporários
|
||||
|
||||
---
|
||||
**Versão**: 1.0.0-light | **Base**: 1.0.0
|
||||
@@ -794,3 +794,15 @@ def extract_text_with_ocr(pdf_path):
|
||||
|
||||
---
|
||||
**Versao**: 1.0.0 | **Autor**: Descomplicar®
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -392,3 +392,15 @@ mcp__dify-kb__dify_kb_retrieve_segments({
|
||||
|
||||
---
|
||||
**Versão**: 1.0.0 | **Autor**: Descomplicar®
|
||||
|
||||
---
|
||||
|
||||
## 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.*
|
||||
|
||||
@@ -130,3 +130,15 @@ Tabela com: ID, Nome, Segmento, Volume Anual (EUR), Projectos Activos, Última I
|
||||
|
||||
---
|
||||
**Versão**: 1.0.0 | **Autor**: Descomplicar® | **Plugin**: dev-tools
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -189,3 +189,15 @@ hooks/
|
||||
|
||||
- `references/composition-patterns.md` - Compound components, providers, dependency injection (Vercel Engineering)
|
||||
- `references/custom-hooks.md` - useDebounce, useLocalStorage, useFetch com codigo completo
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -186,3 +186,15 @@ description: >
|
||||
|
||||
Ver `references/anthropic-patterns.md` para exemplos detalhados de progressive disclosure.
|
||||
Ver `references/descomplicar-standards.md` para exemplos de skills Descomplicar bem estruturadas.
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -144,3 +144,15 @@ No servidor dev, Playwright ja esta disponivel em `/root/Dev`.
|
||||
|
||||
---
|
||||
**Versao**: 1.0.0 | **Autor**: Descomplicar®
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -372,3 +372,15 @@ O ficheiro de referencia de precos esta em:
|
||||
|
||||
---
|
||||
**Versao**: 1.0.0 | **Autor**: Descomplicar®
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
---
|
||||
name: youtube-extract
|
||||
category: dev-tools
|
||||
description: "Extrai transcrições e metadados de vídeos, playlists e canais YouTube para o ficheiro de pesquisa Stack_Pesquisa_Videos.md. Usar quando 'youtube', 'vídeo', 'playlist', 'canal', 'transcrição', 'extrair vídeo', 'pesquisa vídeos'."
|
||||
version: "1.0.0"
|
||||
created: 2026-04-04
|
||||
tools: [Bash]
|
||||
---
|
||||
|
||||
# Skill: /youtube-extract
|
||||
|
||||
Extrai transcrições e metadados de vídeos, playlists e canais YouTube usando o script `youtube-pesquisa-videos.py`. Adiciona automaticamente ao ficheiro de pesquisa do StackDescomplicar.
|
||||
|
||||
---
|
||||
|
||||
## Ficheiros relevantes
|
||||
|
||||
| Ficheiro | Caminho |
|
||||
|----------|---------|
|
||||
| **Script** | `/media/ealmeida/Dados/Dev/ClaudeDev/youtube-pesquisa-videos.py` |
|
||||
| **Destino padrão** | `/media/ealmeida/Dados/Hub/04-Stack/Stack_Pesquisa_Videos.md` |
|
||||
|
||||
---
|
||||
|
||||
## Processo de execução
|
||||
|
||||
### 1. Identificar o pedido
|
||||
|
||||
Detectar na mensagem do utilizador:
|
||||
- **URLs** — vídeos individuais, playlists (`?list=`), canais (`@canal`, `/c/`, `/channel/`)
|
||||
- **Limite** — "primeiros 10", "máx 5", etc. → usar `--max N`
|
||||
- **Destino** — ficheiro alternativo? → usar `--output caminho`
|
||||
- **Modo** — adicionar ao ficheiro (`--append`) vs mostrar no terminal (sem flag)
|
||||
|
||||
### 2. Construir o comando
|
||||
|
||||
```bash
|
||||
python3 /media/ealmeida/Dados/Dev/ClaudeDev/youtube-pesquisa-videos.py \
|
||||
URL1 URL2 ... \
|
||||
[--max N] \
|
||||
[--append] \
|
||||
[--output /caminho/alternativo.md] \
|
||||
[--file lista.txt]
|
||||
```
|
||||
|
||||
### 3. Exemplos por tipo de URL
|
||||
|
||||
**Vídeo individual:**
|
||||
```bash
|
||||
python3 /media/ealmeida/Dados/Dev/ClaudeDev/youtube-pesquisa-videos.py \
|
||||
"https://youtu.be/dQw4w9WgXcQ" --append
|
||||
```
|
||||
|
||||
**Playlist completa:**
|
||||
```bash
|
||||
python3 /media/ealmeida/Dados/Dev/ClaudeDev/youtube-pesquisa-videos.py \
|
||||
"https://youtube.com/playlist?list=PLxxx" --append
|
||||
```
|
||||
|
||||
**Playlist com limite:**
|
||||
```bash
|
||||
python3 /media/ealmeida/Dados/Dev/ClaudeDev/youtube-pesquisa-videos.py \
|
||||
"https://youtube.com/playlist?list=PLxxx" --max 10 --append
|
||||
```
|
||||
|
||||
**Canal completo (máx. 20):**
|
||||
```bash
|
||||
python3 /media/ealmeida/Dados/Dev/ClaudeDev/youtube-pesquisa-videos.py \
|
||||
"https://youtube.com/@NomeCanal" --max 20 --append
|
||||
```
|
||||
|
||||
**Mix de URLs:**
|
||||
```bash
|
||||
python3 /media/ealmeida/Dados/Dev/ClaudeDev/youtube-pesquisa-videos.py \
|
||||
"https://youtu.be/ID1" \
|
||||
"https://youtube.com/playlist?list=PLxxx" \
|
||||
--max 5 --append
|
||||
```
|
||||
|
||||
**Ficheiro de lista:**
|
||||
```bash
|
||||
python3 /media/ealmeida/Dados/Dev/ClaudeDev/youtube-pesquisa-videos.py \
|
||||
--file /caminho/lista.txt --append
|
||||
```
|
||||
|
||||
**Pré-visualizar sem gravar:**
|
||||
```bash
|
||||
python3 /media/ealmeida/Dados/Dev/ClaudeDev/youtube-pesquisa-videos.py \
|
||||
"https://youtu.be/ID1"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Comportamento padrão
|
||||
|
||||
| Situação | Acção |
|
||||
|----------|-------|
|
||||
| URL única de vídeo | Extrair e perguntar se adiciona ao ficheiro |
|
||||
| Múltiplos vídeos | Extrair todos e adicionar com `--append` |
|
||||
| Playlist/canal sem limite | Alertar o utilizador — perguntar limite antes de executar |
|
||||
| Ficheiro de destino não especificado | Usar `Stack_Pesquisa_Videos.md` |
|
||||
|
||||
> **Aviso obrigatório para playlists/canais sem `--max`:** Informar o utilizador do número de vídeos antes de processar — canais podem ter centenas.
|
||||
|
||||
---
|
||||
|
||||
## Após a extracção
|
||||
|
||||
1. Informar quantos vídeos foram adicionados e os números `#N` atribuídos
|
||||
2. Sugerir ao utilizador que complete os campos `*(a completar)*` no ficheiro
|
||||
3. Se houver erros (transcrição indisponível), mencionar quais os vídeos afectados
|
||||
4. Opcional: abrir o ficheiro no editor — `xdg-open "Stack_Pesquisa_Videos.md"`
|
||||
|
||||
---
|
||||
|
||||
## Pré-requisitos
|
||||
|
||||
- `yt-dlp` instalado: `pip install yt-dlp` ou `brew install yt-dlp`
|
||||
- Python 3.8+
|
||||
- Acesso à internet
|
||||
|
||||
Verificar disponibilidade:
|
||||
```bash
|
||||
yt-dlp --version && python3 --version
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Casos especiais
|
||||
|
||||
**ID curto do YouTube (11 chars):**
|
||||
```bash
|
||||
python3 /media/ealmeida/Dados/Dev/ClaudeDev/youtube-pesquisa-videos.py dQw4w9WgXcQ --append
|
||||
```
|
||||
|
||||
**Destino alternativo (outro projecto):**
|
||||
```bash
|
||||
python3 /media/ealmeida/Dados/Dev/ClaudeDev/youtube-pesquisa-videos.py \
|
||||
"https://youtu.be/ID1" \
|
||||
--output "/media/ealmeida/Dados/Hub/05-Projectos/MeuProjecto/videos.md" \
|
||||
--append
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
Reference in New Issue
Block a user