City-page FAQ rollout (faq-sync, faq-rollout.sh)
City-page FAQ rollout
Classic city pages (/estado/{uf}/{cidade}/, 10,479 pages) render a
deterministic FAQ section (#perguntas-frequentes), a factual definition
lead (#city-lead) and matching FAQPage + BreadcrumbList JSON-LD,
extending the #251 leilões-hub pattern (“question-shaped content is what AI
Overviews and answer engines quote”) to the money pages.
Everything is built from data the page already renders — IBGE population /
area / PIB per capita, the broker count, the leilões result count — by
citypage.BuildFAQs / citypage.BuildLead (site/citypage/faq.go,
unit-tested). No LLM, no searches, no invented numbers; the schema text
equals the visible text verbatim by construction. Pages with fewer than
three answerable facts and noindex placeholders get no FAQ; the lead renders
everywhere. Measurement: row 6 of AI-ANSWER-BASELINE-2026-11-06.md, added
only after the first batches are recrawled.
Timing doctrine: the rollout starts only after the ~Nov 12 WoW verdict, on the operator’s explicit call. Nothing here moves a lastmod before that.
# Plan batch 1 (dry): GSC earners first — the report shows counts + orderinggo run . faq-sync --gsc <export> --limit 400 --out cache/faq/batch-1.json# Regen those cities, rebuild the sitemap (stable lastmods), deploy through the gatescripts/faq-rollout.sh site/cache/faq/batch-1.json# Or walk the whole country unattended (deterministic state/city order, ~27 batches)scripts/faq-national-rollout.sh [--limit 400] [--states SP,RJ] [--max-batches 30]faq-sync selects a row when its rendered page is missing on disk or does
not carry the #perguntas-frequentes marker, so served pages are skipped
and repeated runs resume where the last batch ended — no bookkeeping file.
--gsc orders by impressions (earners first); without it the scope is
national in deterministic order. Manifest rows are consumed by
regenerate-city-pages --manifest unchanged.
Mutation budget
Each deployed batch ≈ --limit pages + ~51 sitemap files (a batch spread
across the lexical shard range rewrites every shard’s lastmods) + 1
agent-status ≈ 452 mutations < the 500 gate — no
--approve-large-deploy sign-off needed. 10,479 pages ÷ 400 ≈ 27 batches.
Per-batch operator procedure
Follow the rebase-state-group shape:
- Review
site/cache/deploy/last-diff.jsonagainst the batch:estado/prefixes + root (sitemap) +agent-statusonly. - Dated batch record on the #198 ledger first, capture the comment URL.
- Snapshot
public/(tar fromsite/). - Operator checkpoint — explicit go-ahead per batch (or once for the national loop, with per-batch diffs still reviewed).
scripts/faq-rollout.sh site/cache/faq/<manifest>.json- Post-gates:
go run . audit-metadata,go run . build-freshness --remote, and the next 03:00 build should read ~0 mutations.
Expected diff noise: pre-re-base pages may show extra hunks (stored
RightRep banner strips legitimately; see HANDOFF-LEILOES-SECTION-2026-11-05.md).
Golden-verification recipe (what was checked on 2026-11-06)
In a clean HEAD worktree with only this change applied:
- FAQ-absent case (builders forced nil): diff vs pre-change build shows only
the lead, the speakable selector and the BreadcrumbList node — byte
identical otherwise(html/template blank-line hygiene). - Full case: FAQPage
mainEntitytext == visible<h3>/<p>verbatim (python check), allld+jsonblocks parse, breadcrumbs positions 1–4,scripts/validate-schema.pyclean. - Determinism: regenerating the same cities twice is byte-identical (md5). Cities without leilões data drop the leilão question (4 items instead of 5).