Hero do roadmap recebe barra de progresso global (95%), cards de timeline-marker por fase e card destacando Stone como cliente piloto. Cohort STN-* pré-rebrand desenhado para janela espelho de 15-mai.
Cada KPI é rastreável: 8 dimensões em score-calculator.ts, modelos LLM em llm-probes.ts, 10 heurísticas seed em preference-engine.ts, cliente Stone documentado em geo-stone/audits/www-stone-com-br/.
Da semana 18 à 21, o checker passou de ferramenta interna para instrumento ao vivo num cliente pagante. Cada cartão é printável para uso direto em slides executivos.
Hero do roadmap recebe barra de progresso global (95%), cards de timeline-marker por fase e card destacando Stone como cliente piloto. Cohort STN-* pré-rebrand desenhado para janela espelho de 15-mai.
Stone vira oficialmente 'O Banco de Quem Empreende' em 15-mai-2026. QID Wikidata Stone Co. canonicalizado em Q105966359. Knowledge base canonical incrementada com 23.7k palavras Q1-Q2 2026. llms.txt template publicado.
Análise UX do rebrand Stone publicada (+8.2k palavras). 110 checkpoints GEO/SEO canonizados em taxonomia + distribuição por sprint. 50 conceitos GEO/SEO 2026 versionados como dicionário canônico do projeto.
NAIA auditou ao vivo 64 URLs de stone.com.br em 25-mai (10 dias pós-rebrand). Score Stone ~45/100. Mercado Pago 70, PagBank 60. 32 de 64 páginas com zero JSON-LD; nenhuma declara Organization/WebSite na home. Aplicação real do checker em cliente pagante.
Auditoria ao vivo NAIA cobriu 64 URLs de stone.com.br: 32 com zero JSON-LD, 32 só com FAQPage, nenhuma declara Organization na home. Score competitivo rebrand ~45/100 · 25 pts atrás de Mercado Pago.
Score Geo 7,9/10. Severidade low. Cobertura BR 3/4 · US 3/4 · EU 3/4. Validação de filter bubble regional via pairwise agreement entre Brasil, Estados Unidos e Europa.
A literatura 2025-2026 sobre Generative Engine Optimization (GEO) derrubou três premissas que ainda moldavam praticamente toda ferramenta de SEO/GEO do mercado:
O GEO Score Checker v2.0 foi desenhado de trás para frente a partir dessas três leis. Todo ponto do score é rastreável a um paper ou métrica validada publicamente, e a janela de uso real começou com cliente pagante (Stone) em maio de 2026.
Cada dimensão é derivada de um paper peer-reviewed ou preprint com forte tração acadêmica. Abaixo, a fundação teórica de cada uma.
O estágio de retrieval (indexação, robots.txt, sitemaps, llms.txt, crawlers de IA permitidos) precisa ser medido independentemente porque fixes em geração podem degradar esta camada. Aqui medimos se o site é alcançável e legível por crawlers como GPTBot, ClaudeBot, Google-Extended, PerplexityBot e CCBot.
Assume que o site foi encontrado. O reranker decide se ele merece estar no top-K das fontes passadas ao LLM. Sinais estruturais (JSON-LD válido, Schema.org canônico, hierarquia de headings, canonical + OG) ganham peso aqui — preservar esses sinais é o que o paper chama de stage-aware optimization.
Exposição é a taxa com que o site é citado em respostas sintetizadas. Medimos isso diretamente: perguntamos a 4 LLMs 'o que é [domínio]?' e contamos quantos reconhecem factualmente, mencionariam o domínio numa resposta natural e com qual nível de confiança.
Exposure sem verdade é ruído. Medimos se as informações retornadas pelos LLMs batem com o que o site declara no <title>, meta description e JSON-LD. Campos que não batem contam como alucinação e penalizam o score.
Quando os 4 LLMs contam histórias diferentes sobre a mesma marca, há ambiguidade explorável. Calculamos similaridade par-a-par (Dice coefficient sobre bigramas) entre as respostas e derivamos divergência média. Baixa divergência = narrativa sólida entre engines. A v2.2 anexa Fleiss kappa ao item exibido — penaliza concordância por chance.
Filter bubbles geográficos distorcem respostas: a mesma query de São Paulo vs Nova York pode gerar resultados distintos. A fase 4 dispara probes de múltiplas localidades (BR/US/EU) e mede consistência via pairwise agreement, com Perplexity recebendo peso 1.5x por ter geo nativo.
HTTPS, TTFB com gradiente 500-1500-3000ms, title triangular 30-65 chars, meta description 120-160 chars. Pré-requisitos que valiam 100% do v1, agora representando 10% do v2 — porque sozinhos não garantem compreensão por IA.
Requer histórico temporal. Quando há ≥3 snapshots do mesmo domínio, conseguimos atribuir mudanças de score a mudanças no site (antes/depois). Esta dimensão fica 'locked' nos primeiros snapshots. A janela espelho Stone pré 15-mai / pós 15-mai é exatamente o experimento natural para validar causalidade.
Zero cap artificial. Zero booleano binário onde pode haver gradiente. Todos os pontos das 8 dimensões somam exatamente 100. A v2.2 (08-abr-2026) acrescentou inferência estatística rigorosa via inference.ts.
O título precisa estar entre 30 e 65 caracteres (ideal). Abaixo de 30 ou acima de 90 vale 0. Entre os limites, valor decai linearmente. Isso dá crédito parcial em vez de on/off.
triangularScore(x, min=0, idealMin=30, idealMax=65, max=90): if x ≤ min or x ≥ max: return 0 if idealMin ≤ x ≤ idealMax: return 1 if x < idealMin: return (x - min) / (idealMin - min) if x > idealMax: return (max - x) / (max - idealMax) // Title de 28 chars → 5 × triangular(28) = 5 × 0.933 = 4.67 pts // Title de 50 chars → 5 × triangular(50) = 5 × 1.000 = 5.00 pts // Title de 80 chars → 5 × triangular(80) = 5 × 0.400 = 2.00 pts
Crawlers de IA abandonam requisições lentas. A curva privilegia rapidez extrema (≤500ms) e penaliza exponencialmente acima de 1500ms.
responseTimeFactor(ms): if ms ≤ 500: return 1.00 if ms ≤ 1500: return 1 - 0.5 × ((ms - 500) / 1000) // 1.00 → 0.50 if ms ≤ 3000: return 0.5 × (1 - (ms - 1500) / 1500) // 0.50 → 0.00 else: return 0
O pairwise agreement bruto inflaciona quando 3 engines dizem "yes" e 1 diz "no" (média ~0,83 parece "alto"). Fleiss kappa penaliza isso porque corrige o esperado por chance. Cada campo livre (name, category, proposition) vira shingle canônico antes de virar rótulo nominal.
fleissKappa(ratings): // N × K matriz de votos por categoria Pbar = (1/N) × Σ_i [ (Σ_j n_ij² - n) / (n × (n - 1)) ] Pe = Σ_j ( (Σ_i n_ij) / (N × n) )² κ = (Pbar - Pe) / (1 - Pe) // Interpretação Landis-Koch: // < 0.00 pobre | 0.41-0.60 moderado // 0.00-0.20 leve | 0.61-0.80 substancial // 0.21-0.40 razoável | 0.81-1.00 quase perfeito // score-calculator anexa kappa ao detail do item exibido: // "Engines contam uma história consistente sobre sua marca. // Fleiss kappa = 0.687 (substancial)."
Bias-Corrected and Accelerated bootstrap (Efron 1987) dá IC mais honesto que o percentile clássico. computeFinalScoreWithCI aceita B≥5 réplicas estocásticas e devolve { point, ci: { ciLower, ciUpper, biasZ0, acceleration } }. Permite relatar Score = 74 [69, 78] em vez de cravado.
bootstrapBcaCI(samples, statisticFn, confidence=0.95, B=1000):
theta_hat = statisticFn(samples)
boot = [statisticFn(resample(samples)) for _ in range(B)]
z0 = Φ⁻¹( (#{b: boot[b] < theta_hat}) / B ) // bias correction
// jackknife para aceleração
jack = [statisticFn(samples \ {i}) for i in range(n)]
jbar = mean(jack)
a = Σ(jbar - jack)³ / (6 × (Σ(jbar - jack)²)^(3/2)) // acceleration
α = (1 - confidence) / 2
α₁ = Φ( z0 + (z0 + Φ⁻¹(α)) / (1 - a × (z0 + Φ⁻¹(α))) )
α₂ = Φ( z0 + (z0 + Φ⁻¹(1-α)) / (1 - a × (z0 + Φ⁻¹(1-α))) )
return percentile(boot, [α₁, α₂])normalize(s) = lowercase + remove diacritics + remove punctuation
bigrams("openai") = {"op", "pe", "en", "na", "ai"}
diceSimilarity(a, b) = 2 × |bigrams(a) ∩ bigrams(b)| / (|a|-1 + |b|-1)
// similarity("OpenAI", "Open AI") ≈ 0.73
// similarity("Brasil GEO", "BrasilGEO") ≈ 0.89Os pesos atuais (15·15·20·15·10·10·10·5) são axiomáticos. O projeto Papers gera o dataset empírico que permite estimar pesos calibrados via regressão logística cujo target é a taxa real de citação observada nos 4 LLMs.
Pipeline de calibração:
Score Checker ──[D1..D8]──┐
├──> score_calibration_inputs (SQLite no papers/)
Papers (citations)──[k/n]──┘
│
v
scripts/calibrate_score.py
│
v
logit(P(cited|site)) = β0 + Σ β_d · D_d
│
v
w*_d = 100 · max(0, β_d) / Σ max(0, β_k)
// Modo simulado N=200:
// pseudo R² (McFadden): 0.1742
// 5-fold CV AUROC: 0.8146 ± 0.0253
// 5-fold CV Brier: 0.0370 ± 0.0039
// Spearman(score_atual, score_calibrado): 0.9495impact = gap × (dimension.maxScore / 20) // Esforço heurístico por palavras-chave if /robots|sitemap|llms\.txt|canonical|title|meta/: effort = 2 else if /schema|json-ld|og:|h1|h2|ssr/: effort = 4 else if /entidade|wikidata|autoridade|press/: effort = 7 else: effort = 5 priority = impact / max(effort, 1) recommendations.sortBy(priority DESC).slice(0, 12)
Atualizado em 27 de maio de 2026. Preço por 1 milhão de tokens. Gemini foi atualizado de 2.5-flash para 2.5-pro em 18-abr-2026 para elevar a qualidade do structured output. Cada probe espelha custo+tokens em finops_calls (Supabase) para FinOps unificado.
Usuário → POST /api/geo-check { domain, mode: "async" }
↓
[rota route.ts]
1. Normaliza + valida domínio
2. Checa SSRF (resolve DNS, bloqueia IPs privados)
3. Checa cache 24h em geo_analysis_jobs
4. Checa FinOps gate (budget diário US$ 5)
5. Insere job { status: "queued" } no Supabase
6. Retorna { job: { id, status: "queued" } }
↓
Frontend → GET /api/geo-check/[jobId] a cada 2,5s (polling)
↓
[Vercel Cron * * * * *]
→ POST /api/geo-check/worker
1. claimNextJob via UPDATE atômico (lock otimista)
SET status='running', locked_at=NOW(), locked_by='vercel-cron-...'
WHERE status='queued' AND id=<first FIFO>
2. Dead-lock recovery: libera jobs 'running' há >5min
3. Fase estática: collectStaticSignals(domain) → phase='static', 30%
4. Fase compreensão: runAllProbes em Promise.all → 4 fetches paralelos
(OpenAI gpt-4o-mini, Anthropic claude-haiku-4-5,
Google gemini-2.5-pro, Perplexity sonar)
→ aggregateComprehension(evals, staticSignals)
→ trackProbeCall espelha em finops_calls (fire-and-forget)
→ phase='comprehension', 60%, cost_delta_usd=0.035
5. Fase entity: Wikidata + Google KG cross-check → phase='entity', 90%
6. Fase semantic (PRO): geo-probes 4×3 geos → phase='semantic', 95%
7. calculateAllDimensions → score-calculator.ts
8. enrichWithPreferences (Fase 5 — preferences_learned)
9. completeJob(id, { final_score, dimensions, recommendations })
↓
Frontend detecta status='done' → renderiza scoreSete entregas em ordem cronológica. Cada fase aprofunda uma dimensão diferente do score e mantém compatibilidade backwards. Clique no número da fase no menu sticky acima para saltar.
Análise estática síncrona. 6 dimensões booleanas. Score com caps artificiais.
Refactor radical: pesos contínuos, crédito parcial, sinais enriquecidos, stage-aware.
Coração do v2. Pergunta real aos 4 LLMs, mede exposição, acurácia factual e bubble.
Cross-check de entidade contra Wikidata + Google Knowledge Graph. Custo: US$ 0 (APIs gratuitas).
12 chamadas LLM por job (4 provedores × 3 geos: BR, US, EU). Custo: ~US$ 0,10 adicional/job.
Heurísticas extraídas estatisticamente do histórico real via cron diário 4h AM.
Entregue 08-abr-2026 (commit 3072091). Move o checker de "calculadora de score" para "instrumento de medição com IC honesto".
Transparência total. Tarefas que dependem de dashboards externos, chaves e decisões estratégicas precisam de sua mão; tudo mais eu executo aqui no Claude Code.
inference.ts assim que houver ≥30 snapshots/admin/geo-prefsnpx next buildMedir compreensão por IA é difícil porque LLMs são não-determinísticos por padrão. A v2.2 elevou a régua: agora temos Cohen/Fleiss kappa, bootstrap BCa e pipeline de calibração contra dataset empírico do Papers.
Todos os 4 provedores são chamados com temperature zerada. Em ~95% dos casos a mesma query retorna JSON idêntico entre runs. Os 5% restantes variam em ~1-2 palavras, que o pairwise agreement + Fleiss kappa absorvem.
OpenAI json_schema strict, Google responseSchema, Anthropic prompt explícito. Zero parsing de texto livre — ou o LLM retorna o schema, ou falha visivelmente.
Faithful Credit compara name vs <title> e proposition vs meta description. Alucinações capturadas quando divergem do que o próprio site afirma.
4 engines independentes reduzem vieses específicos. Pairwise agreement elimina rajadas de um único modelo.
O prompt força o LLM a admitir desconhecimento em vez de chutar. Exemplos positivos e negativos no próprio prompt.
Cada LLM devolve hallucinationFlags[] listando afirmações incertas. Contadas e penalizadas na dimensão Faithful Credit.
cost_usd individual em evaluations[]; soma em geo_analysis_jobs.cost_usd. trackProbeCall espelha em finops_calls (cross-projeto).
Corrige pairwise agreement bruto pelo esperado por chance. Cada campo livre vira shingle canônico → rótulo nominal → kappa Landis-Koch.
Bias-Corrected and Accelerated (Efron 1987). Score = 74 [69, 78] em vez de cravado, quando há ≥5 réplicas.
score_calibration_inputs + scripts/calibrate_score.py. Logit com 5-fold CV AUROC ~0,81 em simulação N=200. Pesos calibrados quando dataset real maturar.
AUTOMATIZÁVEL: rodar mesmo domínio 10× e calcular variância dos scores por dimensão. Meta: std < 1 pt total.
SEMI-MANUAL: 20 marcas famosas + 20 desconhecidas, comparar contra anotação humana de 'reconhecimento factual'. Meta: accuracy > 85%.
AUTOMATIZÁVEL: gravar model + version em cada probe. Alerta quando provider muda internamente (custo/tokens médios saltam). Invalida comparação histórica.
Implementado em 06-abr (commit 4f24fc2). Cada job armazena rawText de cada probe; UI expõe via /api/geo-check/[id]?evidence=1.
5 camadas independentes de proteção contra runaway de custos LLM. Se uma falhar, a próxima ainda contém o estouro. A camada 6 (tracking transparente) ganhou tabela cross-projeto finops_calls em 07-abr.
src/app/api/geo-check/route.ts
Antes de enfileirar, consulta SUM(cost_usd) das últimas 24h em geo_analysis_jobs. Bloqueia novos jobs profundos quando ≥ GEO_CHECK_DAILY_BUDGET_USD (default US$ 5).
countTodayJobsByEmail() em queue.ts
Limite de GEO_CHECK_PRO_DAILY_PER_USER (default 5) análises Multi-Geo por dia por email credenciado.
findCachedResult() em queue.ts
Mesmo domínio analisado nas últimas 24h retorna o resultado cacheado em vez de queimar US$ 0,13. Reduz custo efetivo em ~70% quando há demanda repetida.
Vercel Dashboard → Usage → Spend Management
Hard pause quando billable usage ultrapassar limite configurado (recomendado US$ 50/mês). Camada externa que não depende do código.
Dashboard de cada provedor
OpenAI Platform, Anthropic Console, Google AI Studio, Perplexity — todos têm cap mensal. Em caso de chave comprometida, esta é a defesa final.
trackProbeCall em llm-probes.ts
Cada probe (cost, tokens, duração, modelo, sucesso) é espelhada fire-and-forget em finops_calls do Supabase. Permite agregação cross-projeto via geo-finops.
5 das 6 fases estão em produção e a Fase 5.5 (inferência estatística) acrescentou rigor empírico. As tarefas abaixo destravam Causal Impact e endurecem a operação com cliente Stone.
stone.com.br. Meta: levar score competitivo de ~45 → ≥60 até fim de junho.