A federal foi decidida em 04/10; o documento de cidade passa a servir
inteiro à eleição de Lula. Saem conta eleitoral/cadeira de Solla,
concorrentes e pré-candidatos, emendas e entregas (sem fetch do Portal
da Transparência no builder), acervo de falas, panorama regional e
sinais/demandas; demografia, economia e transporte ficam como contexto
da visita.
A página 1 vira só mobilização: KPIs oficiais do artefato TSE 2026
(Lula/Δ, X₁/X₂, Solla), papel determinístico da cidade, quem mobiliza,
movimento local do 2º turno, riscos e o painel "O que pedir e falar"
(pedido Lula 13; guardrail de votos em jogo no lugar do defeso).
O checklist cai de 10 para 8 itens (emendas_web e quem_investe saem;
relacao_campo/disputa_local reancorados no 2º turno); listas
preCandidates/investments/emendasIndicators saem do contrato (arquivos
antigos seguem aceitos em replay). O snapshot enxuga para rede +
conjuntura + demografia (cityReportTerritory.mjs removido).
Prova: unit 5.232 verdes, int do snapshot sem PII e sem os grupos
aposentados, lint/format/typecheck/knip limpos e rebuild da fixture de
Cruz das Almas (9 seções, 16 páginas contra 21, página 1 fechando sem
fallback).
Fecha o resíduo da classe S6 da OPS119+ no resto de scripts/. F1: SCRIPTS_SPEC_PINNED (42 módulos scripts/** alcançáveis de specs unit+int) espalhado em HIGH_RISK_EXACT, sincronizado por invariante de igualdade que anda o grafo de imports dos specs (missing = lib nova pinada; stale = rename). F2: isCodePath cobre scripts/ (classifyStaticScope = code). Sem migration/access/Consent/UI. gate:fast verde.
Achado ao vivo (run 730): a expressão ${{ 5433 + (github.run_id % 100) }} no
ports do service não é avaliada pelo Forgejo 9 — o literal ia ao runner e o
job falhava em 1s. E portas fixas colidiriam entre runs concorrentes (o job
único segura os services pelo run inteiro). Correção: services sem publish
host, alcançados por nome na rede do job (postgres-int/postgres-build:5432)
— solução canônica do Actions, mata a colisão de raiz. Guards fail-closed
(LOCAL_HOSTS + assertTestDatabase) admitem os nomes dos services (hosts
internos do runner; hosts remotos continuam rejeitados); pins novos em
localHosts.unit.spec.ts e ciSkipInvariants (sem ports:, URLs por nome).
ci-pr.yml e ci.yml deixam de ter jobs irmãos: 1 job 'checks' com steps em
série (guards → lint → format → typecheck → knip → cycles → unit → int →
build → e2e). Step vermelho interrompe o job, o run falha e o slot é
liberado — sem API de cancel (Forgejo 9.0.3 não tem), sem watchdog, sem
upgrade do Forgejo. Skips do ci-scope.mjs viram step id 'scope'; e2e em 1
processo com PLAYWRIGHT_WORKERS=4 (substitui 2 shards × 2 workers); 2
services Postgres por run com portas host derivadas do run_id (runs
concorrentes não colidem); contexto 'CI (PR) / checks' preservado (job id
checks — contrato do automerger OPS61); deploy OPS53 gated em needs checks.
Plumbing morto removido (e2eShardConfig/e2e_shards). Docs: AGENT-OPS,
TESTING.md, changelog. Impl: docs/plans/ops62-ci-fail-fast-forgejo-impl.md
(a intenção watchdog+upgrade fica como histórico do gate).
Causa raiz (medida com o binário 1.58.2, config real): commander parseia
posicionais e -g/--list funcionam; o que arrastava a suíte era o closure de
dependências do dev mode (setup<-campaign<-frontend<-admin): filtrar um spec
do frontend puxava campaign(160)+setup(2). run-e2e-affected.mjs agora gera
test:e2e <passthrough verbatim> --no-deps -- <paths> via helpers puros em
scripts/lib/playwright-e2e-args.mjs (unit-pinned); passthrough corrigido
(pnpm consome o -- e o path era descartado); run-e2e-affected.mjs entrou em
HIGH_RISK_EXACT. Docs: receitas de filtro no playwright.config.ts, AGENTS.md,
changelog.