Skip to content

feat(eval): a mutação cara passa pela guarda — EVAL_MUTATE através do mutate.sh - #108

Merged
CRangelP merged 1 commit into
mainfrom
feat/89-mutacao-pelo-helper
Aug 11, 2026
Merged

feat(eval): a mutação cara passa pela guarda — EVAL_MUTATE através do mutate.sh#108
CRangelP merged 1 commit into
mainfrom
feat/89-mutacao-pelo-helper

Conversation

@CRangelP

Copy link
Copy Markdown
Owner

Fecha o último item aberto da #89 — o que ficou de fora de propósito porque o eval.sh estava sendo trabalhado em paralelo nas #70 e #83, agora mergeadas.

O que muda

EVAL_MUTATE='<expr>' bash scripts/eval.sh yellow-run aplica a expressão à cópia instalada dentro do fixture, através do scripts/mutate.sh. O procedimento antigo era à mão — copiar o repositório inteiro, editar com perl -0pi, conferir por grep, rodar a cópia — e carregava os dois modos de falha que este repositório já mediu: a edição que não aplica (a run acontece contra o texto original e o verde se lê como "o caso não morde") e o SKILL_ROOT da cópia resolvendo para /.

Três decisões, cada uma nascida de um defeito

O aborto mora no preflight. O fixture() roda dentro de uma substituição de comando: um exit ali mata o subshell e a suíte segue com um caminho vazio. O preflight roda no processo da suíte, contra uma cópia descartável do arquivo, e sai 2 antes de existir qualquer fixture — 2 e não 1, porque é a suíte se recusando a medir, resposta diferente de um grader vermelho.

A mutação sai em stderr. O fixture imprime no stdout o diretório que construiu, e os chamadores capturam isso; uma linha de conversa no stdout viraria parte do caminho.

O run_arm recusa braço sem fixture. Medido, não temido: ( cd "" && pwd ) imprime o diretório atual e sai 0 — a falha de qualquer fixture apontaria o modelo para o diretório de onde a suíte foi chamada, que é este repositório.

Provas

  • 7 pisos novos (97 → 104), nas duas direções: expressão que não casa para a suíte; expressão que casa passa (preflight que sempre aborta não é preflight); a edição chega à cópia que o braço lê; o braço mutado começa com árvore limpa; e o SKILL.md deste repositório fica byte a byte igual depois de tudo.
  • 4 invariantes novos (500 → 504): a rota pelo mutate.sh, a ausência de um perl -0pi paralelo, e os dois READMEs nomeando o interruptor.
  • Os três primeiros invariantes provados com mutação, num tar descartável e pelo próprio mutate.sh: cada um reprova 503/504 quando a rota some.
  • scripts/test.sh verde: 145 gate, 47 guard, 5 rollback, 37 metrics, 504 invariantes, 14/14 mutações.

…a suíte antes do primeiro minuto de modelo

Último item da #89. Provar que um caso de eval morde é mutar a cópia instalada da
skill e rodar o modelo contra ela — e até aqui isso era feito à mão: copiar o
repositório inteiro, editar com `perl -0pi`, conferir por `grep`, rodar a cópia.
Dois modos de falha, os dois já observados neste repositório. A expressão que não
casa faz a run acontecer contra o texto ORIGINAL e volta verde, que se lê como "o
caso não morde" ao preço de uma run paga. E rodar uma cópia do `eval.sh` a partir
de /tmp resolve `SKILL_ROOT` para `/`, que é o incidente pelo qual a guarda dentro
do `fixture()` existe.

`EVAL_MUTATE='<expr>'` tira a cópia e o hábito do caminho. A expressão é aplicada
à cópia INSTALADA dentro de cada fixture, nunca a este repositório, e passa pelo
`scripts/mutate.sh` — a única coisa aqui que compara checksum e aborta.

Três decisões que o desenho força, e cada uma nasceu de um defeito:

O aborto mora no PREFLIGHT, não no `fixture()`. O `fixture` roda dentro de uma
substituição de comando, então um `exit` lá mata o subshell e a suíte segue com um
caminho vazio. O preflight roda no processo da suíte, contra uma cópia descartável
do arquivo, e sai 2 antes de qualquer fixture existir — 2 e não 1, porque isto é a
suíte se recusando a medir, que é resposta diferente de um grader vermelho.

A mutação sai em stderr. O `fixture` imprime no stdout o diretório que construiu e
os chamadores capturam isso: uma linha de conversa no stdout vira parte do caminho.

E o `run_arm` passou a recusar braço sem fixture. Medido, não temido: `( cd "" &&
pwd )` imprime o diretório atual e sai 0 — ou seja, a falha de qualquer fixture
apontaria o modelo para o diretório de onde a suíte foi chamada, que é este
repositório.

Sete pisos novos (104 no total), e eles cobrem as duas direções: expressão que não
casa PARA a suíte; expressão que casa passa (preflight que sempre aborta não é
preflight); a edição chega à cópia que o braço lê; o braço mutado ainda começa com
árvore limpa; e o `SKILL.md` deste repositório fica byte a byte igual depois de
tudo.

Quatro invariantes (504 no total) prendem a rota: o `eval.sh` tem de chamar o
`mutate.sh`, não pode ter um caminho `perl -0pi` próprio ao lado, e os dois READMEs
têm de nomear o interruptor — mecanismo que nenhum README nomeia é mecanismo que a
próxima pessoa substitui por uma cópia editada à mão. Os três primeiros foram
provados com mutação no próprio `mutate.sh`, num tar descartável: cada um reprova
503/504 quando a rota some.
@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.

@CRangelP
CRangelP merged commit b016e85 into main Aug 11, 2026
2 checks passed
@CRangelP
CRangelP deleted the feat/89-mutacao-pelo-helper branch August 11, 2026 21:42
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