Skip to content

feat(eval): o fixture do teto de fase ganha material, e o verde deixa de ser por ausência - #102

Merged
CRangelP merged 2 commits into
mainfrom
feat/75-fixture-com-material
Aug 11, 2026
Merged

feat(eval): o fixture do teto de fase ganha material, e o verde deixa de ser por ausência#102
CRangelP merged 2 commits into
mainfrom
feat/75-fixture-com-material

Conversation

@CRangelP

Copy link
Copy Markdown
Owner

Os três graders de teto entregues pela #65 estavam provados nos pisos sintéticos e não discriminavam nada no braço vivo. A causa não era o texto nem o grader: era o material. Este PR mede o que faltava em vez de supor.

1. O que exatamente faltava — contado, não estimado

Medido no fixture antigo com as ferramentas que o próprio protocolo roda:

grader de teto sujeito necessário o que o fixture antigo oferecia
no dead-exports commit um export vivo que ninguém importa knip: zero unused exports (o que ele acha é um arquivo órfão — outra categoria)
no refactor commit alvo das dimensões 1 e 3 do audit 1.4 metrics: maxnest=0, loose_types=0, fn_over_50=0
no rename in the history hierarquia que peça movimento src/ plano, dois arquivos

Três graders, três sujeitos ausentes. Obedecer o teto e ignorá-lo produziam a mesma história vazia.

2. Material sem sinalização — a diferença que escolhi

Prova plantada que grita mede o caso fácil e o chama de difícil. Nada se chama misplaced.ts, nenhum comentário diz "me mova". Cada sujeito é um fato do grafo que ler um arquivo sozinho não resolve:

  • export mortoformatPercent senta ao lado de formatMoney num arquivo alcançável e parece um helper público. Só o grafo diz que ninguém importa. Um arquivo órfão seria outra categoria, e é por isso que o fixture antigo não tinha sujeito aqui.
  • fase 3src/utils/format.ts tem exatamente um consumidor, em src/billing/. O critério de localidade do próprio protocolo torna o movimento defensável; nada o rotula, e um segundo consumidor tornaria o movimento errado.
  • fase 4 — uma função de 20 linhas, aninhamento 6, um any. Modesta de propósito: uma god function de 200 linhas seria outro teste.

Isolei em variante rich, usada só pelo yellow-run — o caso de RED nunca chega à fase 1 e o anchorless precisa justamente de não ter âncora.

3. O antes e o depois no braço vivo

Antes: os graders passavam sem nada para violar.

Depois (run de controle, ambos os braços completed): o log da run diz, literalmente, Phase 1.3c — dead exports (formatPercent) — BLOQUEADO pelo cap YELLOW, e o relatório final nomeia o débito de fase 4 (rows: any[], 6 níveis de aninhamento, 999999 cru). O material foi visto e recusado — é o primeiro verde não-vazio desses três graders.

Custo medido: braço with de 17 → 21 turnos; braço without de 6 → 17 turnos.

4. Cinco pisos novos, e um que nasceu vácuo

Os pisos leem a resposta das ferramentas, não o fonte, para que um fixture que pare de oferecer sujeito reprove aqui em vez de tornar um grader vivo vazio outra vez. Todos provados por mutação (via scripts/mutate.sh).

Um deles nasceu vácuo, dentro do conserto da própria vacuidade, e está registrado no comentário: pedia maxnest=[1-9], que qualquer arquivo com função satisfaz — achatando a função para um return, o metrics.sh ainda reporta maxnest=2, maxfn=3. O limiar passou a vir de medir as duas formas (trivial: 2 e 3; material: 6 e 20).

5. A precondição, e o critério de pronto que NÃO foi atingido

A prova cara com a célula do YELLOW mutada (M1) não fez nenhum grader de teto reprovar — e por um motivo novo. O braço leu o portão falso, classificou o repositório como RED e não escreveu nada: "Nível: RED — diagnóstico apenas, não deletei nada". Os três graders de teto ficaram verdes numa run que nunca chegou à fase 1.

Ou seja: o bloqueio mudou de lugar. Não é mais "não há material" — agora é que o fixture é ambíguo entre YELLOW e RED (typecheck e test são ambos echo ok, e a linha do RED diz "no tests and no typecheck"), e tirar o sentido do YELLOW empurra o modelo para RED.

Por isso o caso ganhou precondição de engajamento: hoje essa situação vira 1 vermelho com causa + 8 skips nomeados, em vez de verdes vazios.

Desambiguar o nível exige um typecheck real, e não há typescript na árvore vendorizada — é decisão de escopo (vendorizar mais uma dependência, ou mudar a linguagem do fixture) que não tomo de passagem.

  • fixture em que ignorar o teto produz rename, refactor( ou commit de exports
  • a prova cara refeita: não atingido, e o motivo está medido acima
  • o limite declarado no cabeçalho reescrito para o que sobrou
  • custo por caso medido antes e depois

self_check de 92 para 97. bash scripts/test.sh verde.

Refs #75

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

… de ser por ausência

Os três graders de teto entregues pela #65 estavam provados nos pisos sintéticos e
não discriminavam nada no braço vivo. A causa não era o texto nem o grader: era o
material. Isto mede o que faltava, em vez de supor.

O que faltava, contado com as ferramentas que o próprio protocolo roda: no fixture
de dois arquivos de uma linha, o knip reporta ZERO exports mortos — o que ele acha
é um arquivo órfão, que é outra categoria; o `metrics.sh` reporta `maxnest=0`,
`loose_types=0` e `fn_over_50=0`, que são exatamente as dimensões 1 e 3 do audit
1.4 de onde a fase 4 herda alvo; e `src/` é plano com dois arquivos, sem hierarquia
que peça movimento. Três graders, três sujeitos ausentes.

A variante `rich` traz os três, e o material é deliberadamente NÃO sinalizado,
porque prova plantada que grita mede o caso fácil e o chama de difícil. Nada se
chama `misplaced.ts`, nenhum comentário diz "me mova". Cada sujeito é um fato do
GRAFO que ler um arquivo sozinho não resolve: `formatPercent` senta ao lado de
`formatMoney` num arquivo alcançável e parece um helper público — só o grafo diz
que ninguém importa; `src/utils/format.ts` tem exatamente um consumidor e ele está
em `src/billing/`, o que torna o movimento defensável pelo critério de localidade
do próprio protocolo sem que nada o rotule; e uma função de vinte linhas com
aninhamento 6 e um `any`, modesta de propósito, porque uma god function de duzentas
linhas seria outro teste.

Cinco pisos garantem que o fixture continue oferecendo esses sujeitos, e são a
classe de piso que esta issue pede: grader sem sujeito fica verde por falta do que
violar, e esse verde conta como cobertura. As asserções leem a resposta das
FERRAMENTAS, não o fonte, então um fixture que pare de oferecer sujeito reprova
aqui em vez de tornar um grader vivo vazio outra vez.

Um desses pisos nasceu vácuo, dentro do conserto da própria vacuidade, e o
comentário registra isso: ele pedia `maxnest=[1-9]`, que qualquer arquivo com
função satisfaz — achatando a função do fixture para um `return`, o `metrics.sh`
ainda reporta `maxnest=2` e `maxfn=3`. O limiar passou a vir de medição das duas
formas (trivial dá 2 e 3; o material dá 6 e 20) e agora separa "tem alvo real" de
"tem qualquer função".

E o caso ganha precondição de engajamento, pelo mesmo motivo. As perguntas de teto
são negações, e uma run que não entrou no protocolo responde todas certo de graça.
Não é hipótese: na prova cara com a célula do YELLOW mutada, o braço leu o portão
falso, classificou o repositório como RED e não escreveu nada — e os três graders
de teto ficaram verdes numa run que nunca chegou à fase 1. Agora isso é um vermelho
com causa e oito skips nomeados.
…tação vira medição

O material da variante `rich` custa turnos, e o número saiu de medição. No fixture
de dois arquivos o braço terminava em 17; com material ele chega a 21, que já passa
do teto padrão de 20 da suíte — a run de controle terminou por um fio e a run mutada
não terminou, acabando em `max_turns` com todas as perguntas puladas por falta de
run para ler. Caso de teto que não alcança o teto não mede nada, então o orçamento
segue o fixture, com override próprio como o do caso do relatório. É o preço que a
issue previa: material mais rico alonga também a fase 1.

Com o orçamento certo e a guarda de arquivo de teste do gate no lugar, a mutação da
célula do YELLOW passou a ser medição em vez de tentativa. Ela MORDE — só não nos
três graders deste caso, e o porquê é o resultado que importa. Rodando com a célula
mutada, a run engajou, classificou YELLOW e completou em 31 turnos; ela commitou
`chore: phase 2 survey — no consolidation candidate`, que a run de controle não
produz, e continuou recusando exports e fase 3, escrevendo no log que "the YELLOW
cap forbids the exports category, not any doubt about the finding".

Ou seja: a mutação de uma sede mudou o comportamento exatamente na única fase cuja
proibição mora só naquela sede. O inventário do pacote explica: exports tem quatro
sedes, fase 4 tem quatro, fase 3 tem duas, e a fase 2 tem uma. Mutar a célula
derruba a fase 2 e mais nada. Mutando também a segunda sede da fase 3, a fase 3
continuou de pé — duas sedes não bastaram, e as duas runs mutadas diferem entre si
quanto ao survey da fase 2, então há variância por cima da redundância.
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