Pipeline completo de publicação no LinkedIn: evaluator → redator → editor → art → director → publisher - Seed com 37 posts em _sugestoes.md - Sorteio de formato com N=3 bloqueados (format-history) - Reciclagem mensal de posts com rotação de formato - Revisão via Telegram com chat livre (Gemini 2.5 Flash) - Publicação via LinkedIn API (OAuth2) - Makefile com targets para Windows/Linux/ARM64 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5.0 KiB
5.0 KiB
ldpost-squad — Instruções Gerais
Princípio Central: Testabilidade Independente
Cada CLI deve rodar de forma isolada, sem depender que outro CLI tenha rodado antes.
Regras:
- Toda CLI aceita
--post <slug>como entrada principal - Toda CLI aceita
--dry-runpara operar sem side effects (sem salvar arquivo, sem chamar API externa) - Toda CLI pode ser testada com um fixture manual (arquivo criado à mão no workspace)
- Nenhuma CLI assume estado global — lê e escreve apenas no workspace do post
Workspace Layout
$LDPOST_WORKSPACE/
<slug>/
post.json ← metadados: tema, formato, imagens desc, status
draft.md ← rascunho cru (gerado pelo redator)
final.md ← versão formatada LinkedIn (gerado pelo editor)
img/
cover.png ← imagem principal
slide-*.png ← slides do carrossel (se aplicável)
status.json ← pipeline state: pending|approved|published + URL
Como testar qualquer CLI isoladamente:
# Crie o fixture mínimo manualmente
mkdir -p "$LDPOST_WORKSPACE/meu-slug"
echo '{"slug":"meu-slug","topic":"IA no RH","format":"lista"}' \
> "$LDPOST_WORKSPACE/meu-slug/post.json"
# Agora rode qualquer CLI contra esse slug
ldpost-redator --post meu-slug --dry-run
ldpost-editor --post meu-slug --no-interactive
ldpost-art --post meu-slug --dry-run
ldpost-director --post meu-slug --skip-telegram
ldpost-publisher --post meu-slug --dry-run
Variáveis de Ambiente
Arquivo .env na raiz do workspace ou exportadas no shell.
# Obrigatórias
GROQ_API_KEY= # modelo rápido (redator, evaluator)
GEMINI_API_KEY= # imagens e análise (art, editor)
LDPOST_WORKSPACE=C:\Textos-LinkedIn
# Telegram (director)
TELEGRAM_BOT_TOKEN=
TELEGRAM_CHAT_ID=
# LinkedIn (publisher) — opcional, fallback manual
LINKEDIN_ACCESS_TOKEN=
LINKEDIN_CLIENT_ID=
LINKEDIN_CLIENT_SECRET=
Cada CLI deve chamar godotenv.Load() no init para carregar .env automaticamente se presente.
Estrutura de Módulo Go
Cada CLI é um módulo Go independente dentro de C:\gocode\jobmaker-ldpost\:
jobmaker-ldpost/
shared/ ← módulo compartilhado (go.mod: ldpost/shared)
evaluator/ ← go.mod: ldpost/evaluator
redator/ ← go.mod: ldpost/redator
editor/ ← go.mod: ldpost/editor
art/ ← go.mod: ldpost/art
director/ ← go.mod: ldpost/director
publisher/ ← go.mod: ldpost/publisher
CLIs dependem de ldpost/shared via replace no go.mod:
require ldpost/shared v0.0.0
replace ldpost/shared => ../shared
Convenções de Código
Flags padrão (toda CLI implementa)
| Flag | Tipo | Descrição |
|---|---|---|
--post |
string | Slug do post (obrigatória na maioria) |
--dry-run |
bool | Opera sem salvar/publicar |
--model |
string | Override do modelo LLM |
--workspace |
string | Override de LDPOST_WORKSPACE |
--verbose |
bool | Log detalhado |
Saída padrão
- Sucesso: imprime caminho do arquivo gerado ou URL publicada
- Erro:
fmt.Fprintf(os.Stderr, "erro: %v\n", err)+os.Exit(1) - Dry-run: imprime conteúdo que seria gerado/enviado
Arquivo post.json (schema mínimo)
{
"slug": "ia-no-rh-2026",
"topic": "IA no recrutamento em 2026",
"format": "lista",
"images": [
{"index": 1, "prompt": "robô entrevistando humano, estilo flat design"},
{"index": 2, "prompt": "dashboard de triagem de currículos com IA"}
],
"created_at": "2026-05-02T11:00:00Z"
}
Arquivo status.json
{
"slug": "ia-no-rh-2026",
"pipeline_status": "pending",
"steps_completed": ["evaluated", "drafted", "edited"],
"approved_at": null,
"published_url": null
}
Padrões do jobmaker-squad (reutilizar)
Referência: C:\gocode\jobmaker-squad\
| Padrão | Onde está | O que reusar |
|---|---|---|
| Gemini API calls | jobmaker-redator/main.go |
Stream + retry pattern |
| Imagen (geração de imagem) | jobmaker-art/main.go |
Gemini Imagen 3.0 call |
| Telegram bot | jobmaker-editor/internal/telegram/ |
Keyboard inline, await response |
| Config loader | jobmaker-editor/internal/config/ |
.env + flags merge |
| Vector store local | jobmaker-editor/internal/vectorstore/ |
chromem-go pattern |
Como Rodar Testes
# Cada CLI
cd evaluator && go test ./... -v
# Shared
cd shared && go test ./... -v
# Smoke test completo (requer .env configurado)
./scripts/smoke-test.sh meu-slug
Ordem de Implementação
Seguir essa ordem — cada passo desbloqueia o próximo:
shared/— structs + workspace utilsevaluator/— sem este, nenhum slug existeredator/— depende depost.jsondo evaluatoreditor/— depende dedraft.mddo redatorart/— depende depost.json(descriptions de imagem)director/— depende definal.md+ imagenspublisher/— depende destatus.jsonaprovado
Mas cada um pode ser desenvolvido/testado isoladamente com fixtures manuais.