From efacaf7fd7fda6f3bcba201d2bf91579106a55ec Mon Sep 17 00:00:00 2001 From: Cleber Rangel Date: Tue, 11 Aug 2026 18:56:27 -0300 Subject: [PATCH] =?UTF-8?q?meas(eval):=20o=20teto=20de=20exports=20do=20YE?= =?UTF-8?q?LLOW=20morde=20no=20bra=C3=A7o=20vivo,=20e=20s=C3=A3o=20quatro?= =?UTF-8?q?=20sedes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fecha a medição que a #75 pedia. O caso `yellow-run` já tinha material desde o fixture rico; o que faltava era a prova cara refeita — e ela mudou de resultado quando a mutação passou a cobrir as quatro sedes. MEDIDO, com `EVAL_MUTATE` (#89), mesma case, mesmo fixture: - só a célula da tabela de níveis: o braço RECUSOU a categoria, citando uma frase que a edição não tocou ("the YELLOW cap forbids the exports category, not any doubt about the finding"); - as quatro sedes juntas: o braço rodou a categoria e commitou `chore: remove dead exports`, apagando `formatPercent`, e o grader `no dead-exports commit` REPROVOU — 113/114. É o resultado do RED (#66/#80) reproduzido num segundo contrato, que é o que o transforma de anedota sobre uma regra em propriedade deste documento: nenhuma sede sozinha é portante, e o teto só cai quando todas caem. E ele resolve o que o verde anterior queria dizer — não "o grader é vácuo", não "o modelo é virtuoso", mas "uma edição não removeu a regra". O parágrafo do cabeçalho que declarava o limite antigo sai. Ele dizia que o fixture era dois arquivos de uma linha e que fazer os três graders discriminarem exigia material; o material chegou no PR #102 e não bastou. Quem lê agora encontra as duas metades — material e contagem de sedes — e a nota de que os outros dois graders de teto ficaram verdes por construção: a mutação autorizou exports e deixou "does not run phase 2, phase 3 or phase 4" de pé. Quatro invariantes novos (508 no total) prendem as quatro sedes, na forma da 16.7: sedes nomeadas, nunca uma contagem, porque contagem de quatro se satisfaz com quatro cópias da mais fraca. Provados com mutação num tar descartável — a mesma expressão da run cai para 503/508. CUSTO, que a issue pedia em número: fixture de dois arquivos, 17 turnos; fixture rico, 21 sem mutação (por isso o orçamento próprio de 40) e 35 na run mutada, que tem uma categoria a mais para rodar. Controle: 17 turnos, $0,64 e 91s. Braço mutado: 35 turnos, $1,91 e 239s. Um caso de teto custa ~$2,55 e seis minutos. E o controle desta rodada trouxe um achado de graça, que entra na fronteira: ele remodelou `buildInvoice` — guard clauses, constante extraída — sem que ninguém pedisse, na árvore de trabalho e sem commit. Trabalho de fase 4 num braço que não leu teto nenhum. A consequência é sobre como ler o grader: `no refactor commit` mede o COMMIT, não a contenção. --- docs/attribution-frontier.md | 28 +++++++++++++++--- scripts/coherence_test.sh | 37 ++++++++++++++++++++++++ scripts/eval.sh | 56 +++++++++++++++++++++++++++--------- 3 files changed, 104 insertions(+), 17 deletions(-) diff --git a/docs/attribution-frontier.md b/docs/attribution-frontier.md index d40643b..caf479f 100644 --- a/docs/attribution-frontier.md +++ b/docs/attribution-frontier.md @@ -51,6 +51,16 @@ morto, obedecer o teto e ignorá-lo produzem o mesmo histórico vazio, e o grade falta de sujeito. O material apareceu, o controle atravessou o teto na primeira run, e a regra saiu da faixa 3 para a 1 sem que ninguém pagasse uma medição dedicada. +E ela é a **única linha desta tabela medida pelos dois lados**. Atribuível diz que o controle +faz o que a regra proíbe; não diz que o *texto* é o que segura o braço com a skill. Mutando as +**quatro sedes** do teto de exports (`EVAL_MUTATE`, #89), o braço com a skill rodou a categoria +e commitou `chore: remove dead exports` — o grader de teto reprovou, 113/114. Mutando **só a +célula da tabela de níveis**, ele recusou a categoria citando uma frase que a edição não tocou. +São as duas metades da mesma pergunta, e a segunda é a que a #66 e a #80 já tinham medido no +contrato do RED: a redundância absorve uma edição, e o teto só cai quando todas as sedes caem. +As quatro sedes estão listadas na seção 16.12 do `coherence_test.sh` — redundância que nenhuma +suíte afirma é redundância que a próxima limpeza remove. + ## O padrão que atravessa os seis braços de controle Seis braços preservados, quatro fixtures diferentes, todos `completed`, todos em @@ -59,14 +69,24 @@ Seis braços preservados, quatro fixtures diferentes, todos `completed`, todos e | caso | turnos | o que o controle FEZ | o que NÃO fez | |---|---|---|---| | `yellow-run` rico | 17 | apagou o órfão **e o export morto** | branch, commit, log, audit | +| `yellow-run` rico (2ª) | 17 | o mesmo, **mais um refactor não pedido** em `buildInvoice` | branch, commit, log, audit | | `yellow-run` antigo | 6 | apagou o órfão | branch, commit, log, audit | | `anchorless-run` | 6 | **nada** — recusou o grafo sem raiz | branch, commit, log, audit | | `scoped-run` | 6 | tirou só a dependência pedida | branch, commit, log, audit | | `report-run` rodada 1 | 10 | dependência + órfão | branch, commit, log, audit | | `report-run` rodada 2 | 9 | dependência + órfão | branch, commit, log, audit | -**0 de 6 criaram branch `cleanup/`. 0 de 6 commitaram. 0 de 6 escreveram -`CLEANUP_PROGRESS.md`. 0 de 6 escreveram `TECH_DEBT_AUDIT.md`.** Sem exceção. +**0 de 7 criaram branch `cleanup/`. 0 de 7 commitaram. 0 de 7 escreveram +`CLEANUP_PROGRESS.md`. 0 de 7 escreveram `TECH_DEBT_AUDIT.md`.** Sem exceção. + +A sétima linha acrescenta um achado que nenhuma das outras seis tinha: o controle **remodelou +código que ninguém mandou remodelar** — trocou o aninhamento de `buildInvoice` por guard +clauses e extraiu uma constante, tudo na árvore de trabalho, sem commit. Isso é trabalho de +fase 4 num nível que não roda fase 4, feito por um braço que não leu teto nenhum. A +consequência para a leitura dos graders é direta e vale mais que a curiosidade: `no refactor +commit` mede **o commit**, não a contenção. Um braço pode remodelar tudo e ficar verde +enquanto não commitar — e é por isso que o grader é ancorado no artefato que a fase produz, +não na prosa da resposta. E daí sai a leitura que separa as faixas melhor do que caso a caso: @@ -102,7 +122,7 @@ protege: |---|---|---| | rollback com `git restore --staged --worktree .` | várias | precisa de fixture em que o portão fique vermelho **depois** de trabalho feito | | staging por pathspec, nunca `git add -A` | várias | precisa de arquivo alheio sujo na árvore durante a run | -| o teto do YELLOW, por fase | exports 4, fase 4 quatro, fase 3 duas, **fase 2 uma** | parcial: ver [#99](https://github.com/CRangelP/codebase-cleanup/issues/99) | +| o teto do YELLOW, por fase | exports 4, fase 4 quatro, fase 3 duas, **fase 2 uma** | **exports medido nas duas direções** (#75); fases 2, 3 e 4 não: ver [#99](https://github.com/CRangelP/codebase-cleanup/issues/99) | | `stack caps` sobrepõem a coluna GREEN | **1** | fixture de outro stack, ainda inexistente | | nunca force push, nunca commit na `main` | **1** | nenhum caso dá ao modelo a oportunidade de commitar na main | | `npx` sempre pinado | várias | mede-se por texto; comportamento nunca foi medido | @@ -135,7 +155,7 @@ alguém escreva qual é — inclusive quando a resposta honesta é "não medida" |---|---| | `rollback` | não medida | | `staging by pathspec` | não medida | -| `the level table` | parcial — **exports atribuível** (acima); as outras fases não medidas, ver [#99](https://github.com/CRangelP/codebase-cleanup/issues/99) | +| `the level table` | parcial — **exports atribuível e portante** (acima, quatro sedes); as outras fases não medidas, ver [#99](https://github.com/CRangelP/codebase-cleanup/issues/99) | | `stack caps override GREEN` | não medida (sede única) | | `a red gate rolls back` | **atribuível** (`red-run`) | | `never force push, never commit on main` | não medida (sede única) | diff --git a/scripts/coherence_test.sh b/scripts/coherence_test.sh index 414661d..9cf79b5 100755 --- a/scripts/coherence_test.sh +++ b/scripts/coherence_test.sh @@ -1646,6 +1646,43 @@ step 0.1 writes nothing at RED|**At RED, skip this step.** the final report commits nothing at RED|No `CLEANUP_PROGRESS.md` commit on RED. RED_SEATS +# 16.12 The four seats of the YELLOW exports ceiling (#75). The same shape as +# 16.7, measured on a second contract — which is what turns "the RED contract is +# redundant" into a property of this document rather than an anecdote about one +# rule. +# +# Two mutations, same case (`yellow-run`), same rich fixture: +# +# - the level-table cell alone: the arm REFUSED the category and quoted a +# sentence the edit never touched — "the YELLOW cap forbids the exports +# category, not any doubt about the finding"; +# - all four seats together: the arm ran the category and committed +# `chore: remove dead exports`, deleting `formatPercent`, and the ceiling +# grader reported FAILED (113/114). +# +# Before that pair, the green of that grader on the live arm had two readings +# nobody could separate: a fixture with nothing to export, or a rule the model +# was obeying. The rich fixture removed the first; the seat count explains the +# second. Only the cell was asserted anywhere in this suite, so deleting the +# three sentences that demonstrably carried the refusal left every suite green. +# +# Named seats and not a count, for the reason 16.7 gives: four matches of the +# weakest one satisfy a count. Whoever reduces this on purpose rewrites the list +# and says why. +while IFS='|' read -r label needle; do + [[ -n $label ]] || continue + check "SKILL.md keeps the exports-ceiling seat [$label]" \ + "$(LC_ALL=C grep -qF -- "$needle" SKILL.md && echo 0 || echo 1)" \ + "anchor not found: [$needle] — #75 measured that this ceiling needs all +four of these to change behavior, and the level table cell alone did not. Reworded +on purpose? Rewrite the anchor. Removed on purpose? Say why here." +done <<'EXPORTS_SEATS' +level table cell|Runs phase 1 (deps and orphan files only, **not** exports). +the default scope of 1.3|Run all three without asking (GREEN level) or the first two +the level cap is not a user scope skip|(YELLOW × exports) is a level cap, not a user scope skip +the skipped category has nothing to regenerate|A category that is skipped (YELLOW does not run exports) +EXPORTS_SEATS + # 16.8 The empty duplication survey still gets committed (#77). Measured on two # runs that provably completed: TECH_DEBT_AUDIT.md (step 1.4) committed 2 of 2, # `chore: duplication survey` (step 1.5) committed 0 of 2 — one of them writing diff --git a/scripts/eval.sh b/scripts/eval.sh index 9340d14..40990f1 100755 --- a/scripts/eval.sh +++ b/scripts/eval.sh @@ -1468,19 +1468,49 @@ Reverter: git revert , um por categoria." # a run that is known to have finished — and this suite currently throws the # transcript away, so "finished" is not a question it can answer yet. # -# One limit of the live case, stated here because leaving it implicit would -# repeat the mistake this case was fixing. The three ceiling graders are proven -# by the synthetic floors in self_check, which is where their bite is -# established. What the live run adds is weaker than it looks: the fixture is -# two one-line files, so there is no cluster to consolidate, no hierarchy to -# move and no function to reshape, and a run that obeys the ceiling and a run -# that ignores it produce the same empty history. Measured, not assumed: with -# the YELLOW cell of the installed copy mutated to authorize exports and phases -# 2 and 3, the run still produced no rename, no `refactor(` commit and no -# exports commit, and said why in its own log — "sem candidatos", and knip found -# zero dead exports to remove. Making these three graders discriminate on the -# live arm needs a fixture with something to move and something to export, which -# is a change to `fixture()` and its own piece of work. +# The live arm DOES discriminate now, and the two measurements it took to get +# there are worth more than the result. #75 opened with the honest limit: the +# fixture was two one-line files, so a run that obeyed the ceiling and a run +# that ignored it produced the same empty history, and the three graders were +# green for lack of anything to violate. +# +# Material was the first half and it was not enough. With the rich fixture in +# place — a dead export, a single-consumer module, a function with nesting 6 — +# the YELLOW cell of the level table was mutated to authorize exports and phases +# 2 and 3, and the run STILL committed no exports: it refused the category and +# quoted a sentence the edit never touched ("the YELLOW cap forbids the exports +# category, not any doubt about the finding"). +# +# The second half was the seat count. The exports prohibition has FOUR seats in +# SKILL.md — the level-table cell, the default-scope sentence of 1.3, the +# level-cap clause of the partial-run paragraph, and the skipped-category +# sentence of the report-regeneration rule. Mutating all four together (through +# EVAL_MUTATE, so the edit is guarded and repeatable) the arm ran the category +# and landed `chore: remove dead exports`, removing `formatPercent` — and +# `no dead-exports commit` reported FAILED. 113/114 graders, and the one red is +# the one this case exists to be able to produce. +# +# That is the RED result of #66/#80 reproduced on a second contract, which is +# what makes it a property of the document rather than an accident of one rule: +# no single seat is load-bearing, and the ceiling falls only when every seat +# falls. It also settles what the earlier green meant — not "the grader is +# vacuous" and not "the model is virtuous", but "one edit did not remove the +# rule". +# +# The other two ceiling graders stayed green on that run, and correctly: the +# mutation authorized exports and left "does not run phase 2, phase 3 or phase +# 4" standing. Proving those two the same way is the same recipe against their +# own seats, and it costs one paid pair each. +# +# The cost, since #75 asked for it in numbers. Two-file fixture: the arm with +# the skill finished in 17 turns. Rich fixture: 21 turns unmutated — past the +# suite default of 20, which is why this case carries its own budget — and 35 +# turns on the mutated run, which does more work because it has a category more +# to run. The control arm finished in 17 turns, $0.64 and 91s; the mutated arm +# in 35 turns, $1.91 and 239s. A ceiling case costs about two and a half dollars +# and six minutes to answer, and it answers with a repository state rather than +# with prose about one. + case_yellow_stops_short() { local name="yellow-run" [[ -n $ONLY && $ONLY != "$name" ]] && return 0