Skip to content

Feat/similaridade lexical candidatos - #31

Merged
Gabriel-Arantes-git merged 10 commits into
mainfrom
feat/similaridade-lexical-candidatos
Aug 13, 2026
Merged

Feat/similaridade lexical candidatos#31
Gabriel-Arantes-git merged 10 commits into
mainfrom
feat/similaridade-lexical-candidatos

Conversation

@Gabriel-Arantes-git

Copy link
Copy Markdown
Collaborator

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

…sente

audit ganha dois achados de eficiência além dos dois que já tinha: tabela
sem chave primária (com promoção de UNIQUE NOT NULL quando o catálogo já
prova, ou sondagem por contagem completa quando não) e coluna quente sem
índice, recomendando o método certo pelo operador observado e pelo tipo da
coluna — btree por padrão, GIN para contenção e full-text, gin_trgm_ops para
LIKE de infixo, HNSW para pgvector, sempre condicionado à extensão estar
instalada. A sondagem de chave é a única leitura de dado do comando, opcional
e limitada por teto (--no-probe-keys, --probe-keys-max-rows).

Quando o terminal é interativo, toda tabela que a sondagem automática deixar
sem chave confirmada é resolvida numa única decisão por execução — nunca
tabela a tabela: o comando resume quantas tabelas estão pendentes, quantas
têm candidato composto (as FKs de coluna única da própria tabela, que a
heurística automática não enxerga) e a convenção de nome de PK que o schema
já declara, com exemplos concretos, e pergunta uma vez o que recomendar. Uma
coluna sintética nunca é nomeada por texto digitado — sempre a convenção que
o resto do schema já usa. Resposta não reconhecida é reportada como inválida
e perguntada de novo, nunca tratada como pular. Fora de terminal interativo,
ou com --no-probe-keys, o comportamento é idêntico ao catálogo-puro.
…solution

Ambas implementadas e verificadas nesta branch. Os dez requirements novos de
structural-audit e o requirement novo de usage-evidence entram na spec viva
em openspec/specs/, e os dois diretórios de change vão para
openspec/changes/archive/.
…ranch

Um conflito real: internal/model/schema.go. A main removeu
HasSingleColumnPK() ao generalizar o pipeline para chave composta — "só
coluna única" deixou de ser um conceito válido. Resolução: acompanhar a main,
inlinando o único uso (a detecção de convenção de nome de PK em
internal/profile/detect.go) como len(t.PrimaryKey) == 1. As adições desta
branch no mesmo arquivo (HasPrimaryKey, PromotableUnique, allNotNull,
UniqueConstraint) não têm equivalente na main e ficaram intactas, ao lado do
comentário mais rico que a main deu a ColumnRef.

Todo o resto mesclou sem sobreposição de linha. Verificado com go build, go
vet (com e sem a tag integration) e go test ./... limpos após a resolução.
…-resolution

# Conflicts:
#	internal/cli/output.go
… lista de conhecidos

O commit que trouxe hot_column_unindexed, jsonb_containment,
missing_pk_composite, missing_pk_fk_bridge, missing_pk_promotable e
pgvector_unindexed nunca atualizou knownFixtures, fazendo
TestNoOrphanFixtures falhar mesmo com os seis já usados de verdade por
suites reais em internal/cli e internal/validate.
… abaixo de 1ms

Duration.Milliseconds() trunca para baixo, e SET LOCAL statement_timeout = 0
significa "desligado" para o Postgres — um teto de 1ns virava ausência de
teto, exatamente o oposto do que TestProbeUniquenessTimeoutResolvesWithoutAborting
esperava provar. O mesmo padrão existia em runQuery, o caminho principal de
validação de FK, não só no keyprobe. Extraído statementTimeoutMillis
(arredonda para cima, nunca abaixo de 1) e travado com teste de unidade que
não depende de Docker.
…nchmark-harness

similaridade-lexical-candidatos funde SigNameSimilarity em
candidate-generation e candidate-scoring. corpus-benchmark-harness não tem
specs próprios (--skip-specs), é infraestrutura de medição pura.
ALTER TABLE ... ADD PRIMARY KEY USING INDEX <nome> só aceita índice
autônomo, e o índice de toda UNIQUE constraint já nasce associado a ela —
Postgres rejeita com "index is already associated with a constraint". Bug
pré-existente em main, achado via make test-integration
(TestSuggestedKeysArtifactPromotesLiveUnique), não relacionado à feature de
similaridade lexical.

writePromoteUnique passa a gerar DDL de três passos, comentada, no mesmo
padrão que os vizinhos writeConfirmedPrimaryKey/writeSyntheticPrimaryKey já
usam para CREATE INDEX CONCURRENTLY: constrói índice novo autônomo, promove,
descarta a UNIQUE antiga. Texto corrigido em quatro lugares que prometiam
"at no cost"/"without rewriting a row" — o requisito em
openspec/specs/structural-audit/spec.md já dizia só "custo baixo", nunca
custo zero; a implementação que prometia mais do que o spec.

Achado durante a correção: dois testes em internal/report/sql_test.go
codificavam o próprio bug como requisito (um exigia a linha sem comentário,
o outro tinha exceção nomeada pra não reclamar dela) — nenhum dos dois roda
contra Postgres de verdade, por isso nunca pegaram o erro. Reescritos junto.

openspec/changes/fix-promocao-unique-para-pk
@Gabriel-Arantes-git
Gabriel-Arantes-git merged commit 328db9c into main Aug 13, 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.

2 participants