Skip to content

009 — Blog AI-first auto-publish coordenado via SQLite kanban (board commitado no git)

Status: Aceita (2026-06-03)

Blog PT-BR é vetor #1 de growth (CEO #9 + docs/SEO.md). Bootstrap = sem time editorial. SEO.md já cravou pillars (8), clusters (25+), cadência (20-30 backlog pré-launch + 2/sem). Falta decidir production model + coordenação de pipeline (multiple agents/workers fazendo partes do fluxo: gerar draft, fact-check, publish, indexar pra RAG, extrair insights do agent, agregar FAQ).

Tradeoff conhecido: AI puro auto-publish escala (custo near-zero, 20+ posts/sem possível) mas tem risco Google Helpful Content Update (penalty se conteúdo for genérico). Híbrido (human-led pillars + AI clusters) seria mais seguro mas exige tempo de founder que não tem.

Coordenação entre workers (writer, judge, publisher, indexer, extractor, aggregator) precisa primitivo simples: sem servidor, sem ORM, sem queue infra (Redis/SQS overkill MVP), sem race condition entre workers.

1. Production model: AI-first auto-publish com guardrails EEAT obrigatórios.

LLM gera draft → LLM judge fact-checa → publisher publica direto, sem human gate por default. Guardrails non-negotiable:

  • EEAT schema agressivo: Article.author real (founder bio), datePublished/dateModified, reviewedBy (humano nominal), Organization.foundingDate. Schema.org Article + FAQPage + HowTo conforme post type.
  • Originalidade via dados próprios: cada cluster post precisa citar pelo menos uma stat do agent (anonimized, k-anonymity ≥ 50). Sem stat → judge mata. Pillars podem ser evergreen sem stat (são human-reviewed inicialmente).
  • Fact-check judge gate: LLM-judge segundo (modelo diferente do writer, ou prompt adversarial) valida números, claims, ausência de hallucination de produto. Falha → killed com reason. Aprovação parcial → review (queue manual).
  • GSC kill switch: queda > 20% impressions/semana em pillar = config.auto_publish_enabled = false. Publisher worker checa antes de cada claim.
  • Pillars stay human-led MVP: 8 pillars do SEO.md são moat. AI puro só clusters + refresh. Pillars entram via enqueue source='backlog' pillar=<x> com human draft já no payload; pipeline pula direto pra review.

2. Coordenação: SQLite kanban commitado no git (content/board.sqlite).

Sem servidor, sem queue, sem ORM. Workers (qualquer agente — Claude session, cron shell, founder manual) interagem via bash + sqlite3 CLI conforme content/README.md. Estado é uma tabela items com FSM backlog → drafting → fact-check → review → publishing → published → archived | killed. Audit trail em transitions. Claim atômico via UPDATE ... WHERE id=(SELECT ... LIMIT 1) RETURNING. Lease TTL (300s default) + requeue-stale recovery.

Board commitado pra: (a) source of truth durável sem infra, (b) qualquer agente em qualquer máquina pulla trabalho com git pull && sqlite3 ..., (c) audit/lead-time queryable, (d) merge conflict raro (binário, mas regenerável).

Positivas:

  • Custo de blog tende a zero (LLM API + Astro build hosting). Cabe em bootstrap.
  • Escala destravada: add worker = nada de config. Pull-based.
  • Audit trail nativo via transitions table. Lead time + throughput queryable. Já alinha com ## Lead time tracking do AGENTS.md (tags git pra scenarios + queries SQL pra blog).
  • Sem servidor de queue = sem ops overhead. SQLite + git já no stack.
  • Workers stateless. Crash = lease expira, próximo pega.
  • ContentBoard fica fora do domínio TypeScript: zero código aplicação MVP. Promove pra TS aggregate (content/ context) quando aparecer caso pra integrar com agent tools (ex: agent loga em board via TS).

Negativas/risks:

  • Google Helpful Content penalty é risco real. Mitigação via guardrails acima. Não há plano B além de migrar pra híbrido (pillars human-led já é primeiro passo). Acompanha via GSC monitoring + kill switch.
  • Brand risk: post AI ruim publicado = brand hit. Judge gate + sample manual review (founder olha 10% random/semana) mitiga.
  • Binary diff no git: board.sqlite polui diff. Aceitável pra MVP (commit batched, schema.sql é a verdade legível). Quando virar dor, dump .sql opcional commitado em paralelo.
  • Single-writer SQLite: workers no mesmo host serializam writes. OK pra MVP (low contention, workers rápidos). Distribuído real → migrar pra Postgres + adapter TS (port ContentBoard já no design implícito do README).
  • Multi-host setup só via git pull: dois workers em hosts diferentes pulando trabalho simultaneamente precisam coordenar via pull/push. MVP = single-host (laptop founder ou 1 VPS).
  • RETURNING exige SQLite 3.35+: macOS default e brew OK. CI Docker base precisa conferir.
  • AI + human editor (recommended pelo Claude inicial): mais seguro mas exige tempo founder = 30min/post × 50 posts = 25h. Bootstrap não tem. Adia pra pós-tração.
  • AI puro sem guardrails: máximo risco penalty, brand hit. Rejeitado.
  • Human-led pillars + AI cluster (híbrido full): meio-caminho. Cluster AI puro ficou OK (decidido); pillars human-led já caem nessa categoria por exceção. Híbrido por tier é o que se materializou na prática.
  • Redis/SQS/Postgres queue: ops overhead. Sem time SRE bootstrap. SQLite + git resolvem MVP.
  • Files no git (markdown com frontmatter status: drafting): race condition entre workers, sem atomicidade, conflict de merge constante. Rejeitado.
  • GitHub Issues / Projects como kanban: dependência externa, API rate limits, sem queryable analytics local, perde se mudar de host. Rejeitado.
  • Aggregate TS ContentItem + port ContentBoard + adapter Sqlite (proposta inicial): over-engineering pra MVP que não tem código de aplicação tocando o board ainda. Workers atuais são bash/cron/Claude session. Promove a TS quando agent precisar logar/ler do board via tool — port + adapter encaixam no padrão 007/012.
  • content/README.md — recipes bash + TL;DR wrappers + git workflow + gotchas
  • content/schema.sql — DDL completa
  • content/board.sqlite — board inicializada (commitada)
  • scripts/board.sh — CLI wrapper (subcommands: enqueue/claim/release/kill/requeue-stale/list/status/wip/throughput/inspect/pause/resume/help)
  • scripts/workers/ — 6 workers bash que pullam do board: writer (backlog→fact-check), judge (fact-check→review|killed, EEAT validator enforça dataStat em clusters), publisher (publishing→published, frontmatter patch, respeita kill switch), indexer (flag embedded:true), insights-extractor (cron, pillars vazios), faq-aggregator (cron, PT-BR intents). LLM_CMD env swap mock→real
  • apps/landing/src/content.config.ts — schema estendido com status/pillar/cluster/source/boardItemId/dataStat/reviewedBy/authorBio (Astro = content truth)
  • apps/docs/.../cmo/content-calendar.mdx — CMO dashboard (snapshot vivo do board)
  • docs/SEO.md — pillars/clusters/cadência (pre-existe; produção model section vai ganhar update apontando aqui)
  • docs/CEO.md #9 — blog/waitlist primeiro move
  • ADR 005 — Astro content collection é destino dos posts publicados
  • ADR 006 — anonymous-first; blog CTA → wa.me direct (sem email)
  • ADR 007 — wa.me CTA do blog é conversão final
  • ADR 008 — voz mel aplica a posts via system prompt do writer worker
  • Google Search Central — Helpful Content Update — origem do risco penalty
  • Schema.org Article — EEAT markup obrigatório