Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ContentHub

Uma ideia vira artigo, carrossel e Reel — pela mesma esteira.

Com gates que impedem a peça de afirmar o que a apuração não sustenta.

Licença: MIT Node Python Testes


Não é um gerador de post. É um capataz de 13 etapas que manda no Claude Code, guarda estado em arquivo, e para quando alguma coisa não fecha.

A diferença está no que ele recusa a publicar.

flowchart LR
    A[pauta] --> B[apuração]
    B --> C[ganchos]
    C --> D[roteiro]
    D --> E[foto]
    E --> F{validação}
    F --> G{gate factual}
    G --> H{editor}
    H --> I[montagem]
    I --> J[artigo]
    J --> K[promoção]
    K --> L[Reel]

    style F fill:#B4651C,color:#fff
    style G fill:#B0392C,color:#fff
    style H fill:#B4651C,color:#fff
Loading

Os três losangos param a peça. O vermelho é código puro e não pode ser convencido.


O que sai no fim

_saida/<conta>/<AAAA-MM-DD>/<peça>/
├── carrossel/
│   ├── slide-01.png … slide-10.png    prontos pro Instagram
│   ├── legenda.md
│   ├── reel.mp4  reel-web.mp4         com legenda palavra a palavra
│   └── revisao.html                   página pra revisar antes de postar
└── artigo/
    └── artigo.md                      o post do blog

Uma apuração, três formatos, o mesmo fato. O artigo e o carrossel falam da mesma coisa no mesmo dia porque saem da mesma ficha — não porque alguém lembrou de sincronizar.


Por que os gates existem

Cada regra deste repositório nasceu de uma peça que saiu errada. Os comentários no código contam qual — eles são o mais valioso que tem aqui.

O gate factual é código, não julgamento

ficha diz:  "entre 33% e 46% já usavam a ferramenta"
peça diz:   "Até 46% já usavam"                        ← REPROVADO

Citar só o teto transforma o intervalo de uma estimativa em fato. O gate compara valor canônico, não grafia: a ficha escreve 500.000, a peça escreve "500 mil", e ele sabe que é o mesmo número.

Ele existe porque um editor por IA reprovou uma peça apontando dois erros factuais e, no dia seguinte, aprovou o mesmo arquivo byte por byte, rebaixando os dois a "ressalva menor". Julgamento de agente varia. Factualidade não pode variar.

Por isso ele roda antes do editor: julgamento editorial pode reprovar, nunca liberar o que a factualidade reprovou.

O gancho passa por três camadas independentes

camada quem é o que faz
autor hook-editor escreve 5 ganchos, cada um citando quais fatos da ficha o sustentam
fact-check agente separado julga cada gancho contra a ficha: SUPPORTED / UNSUPPORTED
juiz agente separado escolhe só entre os SUPPORTED

O juiz existe porque quem escreve tende a preferir a frase segura: o autor produziu uma opção boa e elegeu a mais morna. Separar escrita de escolha custou um incidente para ser aprendido.

E fato classificado como NEGADO na ficha não pode virar afirmação em slide nenhum — a esteira rastreia por índice qual fato sustenta qual frase.

A rejeição do editor gruda no texto

editor rejeita  →  veredito é gravado com o HASH do roteiro
texto muda      →  vale pedir de novo
texto igual     →  a porta continua fechada

Apagar o arquivo de aprovação não reabre nada. Sem isso, "rodar de novo" era re-sortear o editor até ele ceder — o que é contornar o gate, não corrigir a peça.

Gosto não vira regex

O validador mecânico tem 48 regras, e todas são de coisa física (cabe no quadro, tem foto, o destaque renderiza) ou operacional (tem fonte, tem legenda, o Instagram aceita).

"Está fraco" não está lá. Quatro regras de gosto já entraram como erro neste arquivo, e as quatro foram derrubadas ao ver a peça que elas barravam. Julgamento mora nos agentes, em metodo/, onde pode ser discutido — não numa expressão regular.


Começando

O que precisa ter

pra quê obrigatório
Node ≥ 18 e Python ≥ 3.10 o capataz e a fábrica de vídeo sim
Claude Code, logado é quem faz o trabalho — ~10 sessões por peça, no seu plano sim
ffmpeg + ffprobe vídeo pro Reel
edge-tts narração, grátis pro Reel
faster-whisper legenda palavra a palavra pro Reel
Playwright vira o slide HTML em PNG pro carrossel
ComfyUI + GPU gerar imagem não — você pode pôr as suas

Instalar

git clone https://github.com/thallisribeiro/contenthub && cd contenthub
npm install
pip install -r requirements.txt

npm test

Os testes não chamam agente nenhum. Se passam, o motor está inteiro; se quebram, quebraram antes de custar um token.

1 · Seu perfil

cp -r perfis/exemplo perfis/minha-conta

Edite perfis/minha-conta/perfil.json — nicho, público, territórios, paleta, CTA, estilo — e os cinco documentos em data/:

tone-of-voice.md      como esta conta fala (frases de exemplo, não adjetivos)
avatar.md             uma pessoa, não um segmento
content-pillars.md    os assuntos, e o que cada um entrega
anti-patterns.md      erros já cometidos, pra não repetir
visual-identity.md    como as peças parecem

Isso é o onboarding. Não há wizard: é um JSON e cinco markdowns, comentados campo a campo. Todo campo _alguma_coisa explica o campo acima dele.

2 · A primeira peça, devagar

node core/pipeline-editorial.js --perfil minha-conta --parar-em triagem

Para depois de escolher a pauta, antes de gastar o resto. Olhe:

_trabalho/<id>/
├── 01-candidatos.json    o que a busca achou
├── 02-triagem.json       por que descartou cada um
└── 02-escolhido.json     a pauta

Gostou? Continue:

node core/pipeline-editorial.js --perfil minha-conta --id <id>

Rodar de novo é seguro. Etapa cujo artefato já existe é reaproveitada — queda no meio não recobra o que já foi pago.

3 · Ou entre por um link

node core/pipeline-editorial.js --perfil minha-conta --link https://veiculo.com/materia

O link substitui a busca de pauta e não pula a apuração. Sem ficha, o gate factual não teria contra o que comparar, e a peça poderia afirmar qualquer coisa. O link entra na frente do corredor, nunca no meio.


Estilos

editorial foto sangrando no quadro, manchete grande. Notícia com imagem que se sustenta
post-social cartão claro com avatar e @. Tese, opinião, frase que se cita
{ "estilo": "post-social" }

Fazer um novo: copie um diretório, mude o CSS, mantenha as âncoras e as classes. O contrato está em estilos/LEIA.md, e a carga confere — template incompleto falha ali, não no olho de quem revisa.

A primeira versão do post-social inventou nomes de classe próprios e renderizou a manchete despedaçada, sem erro nenhum. A conferência existe por causa disso.


Idioma

As regras de texto são listas de palavras em idiomas/<lang>.json. Acompanham pt-BR e en-US.

ESTEIRA_IDIOMA=en-US node core/pipeline-editorial.js --perfil minha-conta

Sem a lista do seu idioma, essas regras não reprovam — elas deixam de existir. Falha aberta é pior que falha fechada, porque quem opera acha que está protegido. Por isso o validador avisa alto quando não acha a lista, em vez de seguir mudo.

Ao traduzir, traduza a função de cada lista — descrita em idiomas/en-US.json — não as palavras. E use radical: cust* pega custa, custou, custando. Listar verbo forma a forma em língua flexionada é garantia de falso positivo.


Configurar

variável pra quê
ESTEIRA_TETO_CHAMADAS teto de sessões de agente por execução. Ligue. Uma peça ruim passa de 20
ESTEIRA_IDIOMA qual idiomas/<lang>.json usar. Padrão pt-BR
FABRICA_REELS onde está a fábrica de vídeo, se você a moveu
BLOG_REPO repositório do blog, se você publica artigo

Medir antes de mudar

_estado/execucoes.jsonl    uma linha por etapa: ms, sessões de agente, resultado

É o que responde onde a esteira queima retrabalho — antes de você cortar etapa por intuição. O relatório também agrega por estilo, território e formato de capa, para que a escolha de aparência seja medida e não decorada.


Testes

npm test              # 7 suítes, nenhum agente chamado
npm run test:pipeline # o orquestrador inteiro, com os agentes bloqueados
suíte casos
orquestrador 60
validador de carrossel 48
ponte peça → Reel 29
gate factual 12
publicador do Instagram 10
teto de gasto 5
portão editorial do Reel 4
gate factual do artigo

O self-test do orquestrador roda o pipeline como processo filho com os agentes bloqueados por trava, não por convenção: tentar chamar um agente ali é erro. Já foi convenção, e um caso escapou e ficou pendurado num claude -p de verdade dentro do que devia ser teste seco.


Como o repositório está organizado

core/
├── pipeline-editorial.js       o capataz: 13 etapas, estado em arquivo
├── adaptadores/
│   ├── carrossel/              validador, gate factual, montagem
│   ├── artigo/                 gate factual do artigo
│   └── reel/                   a ponte peça → brief
├── reel/fabrica/               o motor de vídeo (TTS, legenda, montagem)
├── publicador/verde/           Instagram e YouTube
├── fonte/                      de onde vem a pauta (adapters plugáveis)
└── feedback/                   métricas voltando pra decisão de pauta

metodo/
├── EDITORIAL.md                a direção editorial
├── SWIPE.md                    o que já funcionou
└── agents/                     16 agentes, um arquivo cada

estilos/   idiomas/   perfis/

Licença

MIT. Use, modifique, venda — só mantenha o aviso de copyright.


Os comentários no código contam por que cada regra existe, quase sempre com a peça que a originou.
Cada um custou um erro real. É a parte que não dá pra reescrever do zero.

About

Uma ideia vira artigo, carrossel e Reel — pela mesma esteira, com gates que impedem a peça de afirmar o que a apuração não sustenta.

Resources

Stars

9 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages