Skip to content

Fix/penalidade generica nao corta - #41

Merged
lvcas-dotcom merged 5 commits into
mainfrom
fix/penalidade-generica-nao-corta
Aug 18, 2026
Merged

lvcas-dotcom merged 5 commits into
mainfrom
fix/penalidade-generica-nao-corta

Conversation

@lvcas-dotcom

Copy link
Copy Markdown
Owner

What changes, and why

How it was verified

  • make fmt && make lint && make test
  • make test-integration (if it touches SQL, the catalog, or validation)

Checks

  • Nothing writes to the target database
  • No row value can reach output, logs or errors
  • New behaviour has a change under openspec/, validating with --strict
  • A new dependency, if any, is justified with measured numbers

…zinha

O spec sempre disse que ela existe para "empurrar os achados valiosos para o
fim" — ordenação. A implementação comparava MetaScore, já com a penalidade
descontada, contra o limiar, e o candidato sumia antes de qualquer validação.

Medido contra Postgres real, schema em inglês, perfil en:
category_id → categories somava 0,65, levava -0,30, ficava em 0,35 sob limiar
de 0,50 e era descartado. A relação que o dado confirmaria com containment de
100% nunca chegou a ser consultada, e o relatório padrão só mostrava a
contagem, sem dizer qual sumiu.

Passou despercebido porque com casamento exato a conta fecha em exatamente
0,50 e sobrevive por aritmética. Só morde quando a tabela é plural e o
casamento é normalizado, a 0,15 — todo schema Rails ou Django. O teste que
cobria a penalidade usava alvo no singular e ainda baixava MinScore para 0,01.

O limiar passa a ver cutScore, sem o sinal genérico; MetaScore continua
descontando, então a ordenação não muda. A isenção é de um sinal só: alvo
ambíguo afirma que a hipótese é menos provável, e continua cortando. Candidato
que já estava abaixo do limiar sem a penalidade continua descartado.

Custo: uma query de validação a mais por chave de domínio real. O corpus
público não mede isto — é DDL sem linha, e a penalidade exige estimativa de
linha, então nunca é emitida lá. Recall e contagem de candidatos saem
idênticos aos publicados, e a proposal registra isso como limite da medição.
bench/corpus.toml promete que o dump local ausente é declarado em vez de
omitido, e o comentário do harness repete a promessa. A declaração ia para
t.Logf — o log do teste, que docs/benchmark/recall.md não carrega.

Quem rodasse `make benchmark` sem o dump opcional republicava o arquivo com a
seção do municipal-ptbr apagada, e o resultado lê como corpus completo em vez
de corpus parcialmente medido. A remoção é invisível na revisão a menos que
alguém compare com uma cópia que por acaso lembrasse.

WriteReports passa a receber os pulados e a nomeá-los no documento.
TestStagesAccountForTheRun exigia duração estritamente positiva por estágio.
A detecção de nomenclatura é trabalho em memória sobre catálogo já lido — a
tabela de custo publicada a imprime como `0s` mesmo no Linux — e o relógio
monotônico do Go no Windows é mais grosso que isso: medi 200 de 200 amostras
sub-milissegundo dando exatamente zero. A suíte ficava vermelha num clone
limpo para quem contribui daquela plataforma, e o CI nunca pegava porque só
roda integração no ubuntu.

Zero é medição verdadeira de trabalho mais rápido que o relógio. O que a
asserção queria pegar — estágio que sumiu — é pego pela lista exaustiva de
estágios no fim do teste, porque um estágio pulado não gera entrada nenhuma
(ver timeline.mark). Passa a rejeitar só duração negativa.
"Four dependencies in the binary" era verdade em 2026-08-06 e envelheceu
quando o guia interativo entrou. São seis diretas e vinte e cinco módulos
linkados, 11 MB — medido no artefato de release, linux/amd64, como
openspec/project.md exige. A frase está no parágrafo que diz que quem aprova
rodar isto em produção abre o go.mod primeiro; era a afirmação mais fácil de
conferir e a única errada.

O default de perfil é pt-br e o README não dizia isso em lugar nenhum. Quem
roda contra schema em inglês lê `profile pt-br` na primeira linha da saída sem
nunca ter escolhido. Agora diz, e diz o que --profile en compra: as regras de
plural. Sem elas o casamento cai no fallback lexical, com metade do peso de
nome (0,08 contra 0,15 para category_id, medido), não some — a primeira versão
desta frase dizia "não gera candidato", que é falso.

"Weak and rejected are reported too" era verdade sobre weak e meia verdade
sobre rejected: o descarte é contado em toda execução e nomeado por
--include-rejected.

O badge de status era "pre-release" escrito à mão, com três releases
publicados. Passa a ler o release mais recente do GitHub, para não envelhecer
de novo.
Minor, não patch: `audit` ganhou uma classe de achado que não tinha, e a
descoberta passa a levantar e confirmar relações que a ferramenta descartava.
A política declarada no topo do arquivo é que feature em 0.x vai em minor, e
um release que muda o que volta de uma execução não deve chegar numerado como
se nada tivesse mudado.

scripts/release-notes.sh v0.2.0 extrai a seção inteira; a fiação de
--release-notes contra o estágio de changelog do goreleaser continua correta.
O carimbo de versão foi conferido pelo mesmo caminho de ldflags do release.
Falta rodar `make release-check` inteiro, que precisa de goreleaser — o job
release-config do CI cobre isso no push.
@lvcas-dotcom
lvcas-dotcom merged commit cacd5e1 into main Aug 18, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant