← Arquitetura da Casa

Avaliação · acervo

O acervo — a casa que guarda corpos, e a coisa guardada não tem corpo

Entra pela porta, a oficina mede o que custa, a esteira produz o leque, a lixeira recebe o que ninguém quis — e quem edita mora fora. A metáfora é física, chega até o campo JSON e até o Dockerfile, e nunca foi escrita. O que falta é um corpo para a única coisa que a casa existe para guardar.

01 de outubro de 2026  ·  medido pela régua da casa  ·  HEAD 1826b91 (0.21.0)  ·  quatro varreduras e um contraditório adversarial

21/30soma pela régua
1 / 2medidor de cinco segundos
(arquivos / identificadores, em 56)
Bcamada que puxou para baixo
(o alcance)
23/08a data que divide o repositório
em duas eras de vocabulário
Desenho da arquitetura do acervo.
O desenho da arquitetura. Caixa ciano é peça com equivalente no mundo; caixa cinza tracejada é peça sem corpo físico — e cada uma delas é um achado.

O acervo — avaliação de arquitetura

Varredura de ~/ved/asset-pipeline-dashboard (assets.did.lu), no commit 1826b91 (0.21.0), em 01/10/2026. Medida pela régua da casa (REGUA.md), que foi escrita no mesmo dia.

>

Quatro varreduras independentes cobriram metáfora, alcance, forma e contradições; um agente adversarial contestou as notas antes do fecho. Onde a régua usa este projeto como exemplo de calibração, as afirmações dela foram reverificadas uma a uma contra o código de hoje — e três delas não se confirmaram. Estão corrigidas na seção final.

1. A metáfora em uma frase

O acervo é uma casa que guarda corpos. Entra pela porta, a oficina mede o que custa, a esteira produz o leque de tamanhos, a peça fica guardada, a ficha diz o que ela é, a galeria mostra, a lixeira recebe o que ninguém quis — e quem edita mora fora.

Essa frase não existe escrita em lugar nenhum do repositório. Ela foi construída a partir dos cabeçalhos, e cada substantivo dela vem de um arquivo que se declara assim na primeira linha útil: src/oficina.js:1, src/esteira.js:1, src/routes/porta.js:2, src/lixeira.js:1, src/ficha-publica.js:2, src/galeria-publica.js:2, src/corpo-canonico.js:2. Não foi inventada pelo avaliador — foi lida.

A frase mais próxima de uma declaração é um título: docs/editores.md:1 — "# Editores — o acervo guarda, quem edita mora fora". Ela declara uma fronteira da casa, não a casa. Grep por metáfora|vocabulário em README.md, PROGRESS.md e docs/ devolve 8 ocorrências, todas de uso técnico; não há docs/metafora.md.

A metáfora é única e se compõe, e isso foi testado, não assumido. O critério foi o objeto circulante: "corpo" e "peça" atravessam porta, oficina, esteira, ficha, galeria e lixeira — cada módulo não tem a sua própria imagem, é uma estação por onde o mesmo corpo passa. E as imagens se citam hierarquicamente, não em paralelo: src/esteira.js:4-6 declara que "a oficina mora no acervo, na subida", e src/variantes.js:3-5 diz que "a esteira sabe apertar um .glb; a oficina sabe medir o que ele custa. Este módulo é o que liga as duas ao acervo". A relação é sempre de contenção: o acervo é a casa, os outros são cômodos. Uma oficina dentro de uma casa que guarda material é um museu com ateliê de restauro — existe no mundo, e é por isso que a composição se sustenta.

Duas peças ficam fora da casa, e a própria obra as marca como fora: bancada/LEIA-ME.md:3-4 (a bancada é oficina de quem constrói o acervo, não da casa — "não entram no servidor, não são provas do corredor") e src/ceu.js:4-7 (o céu é item guardado, não cômodo).

A bancada/ merece uma nota, porque pela forma ela parece o x/ que a régua condena no video-mocap — 16 arquivos diag- e print- versionados — e não é. Cada um tem seção própria no LEIA-ME.md dizendo que pergunta responde e que defeito real o motivou: a ficha da peça sem CSS, a barra de carregamento que nunca saía, o canvas colapsado em 150 px, os oito cartões vazios da galeria em produção. O documento diz por que nenhum deles aparecia no corredor — "o cartão desenhou?' não é uma pergunta que se faça ao servidor". Gaveta é onde se põe o que não se soube classificar; aqui cada ferramenta nasceu de um defeito nomeado. É o inverso.

O que contradiz a frase é o documento de entrada. README.md:1 abre com "assets.did.lu — Pipeline universal de assets" e README.md:5 chama a interface de "Painel". O texto que um agente lê primeiro diz pipeline e painel; o código que ele vai editar diz acervo e estante.


2. Notas

#CritérioNotaEvidência
1Metáfora central2Operante em 39 de 56 arquivos (src/esteira.js:1, src/oficina.js:1, src/routes/porta.js:2); nunca declarada; README.md:1 contradiz; pastas de 1º nível não contam história
2Fisicalidade da metáfora3Medidor: 1 arquivo (vendor) e 1 falso positivo em 56; zero agentes-que-mandam; src/peca-de-humano.js:2, src/fila-oficina.js:2, src/chave-de-edicao.js:2
3Alcance na estrutura3Degrau 5 em 13 conceitos: migrations/026_peca_de_humano.sql:174-180 (CHECK de 55 ossos), MIME application/vnd.did.acervo.arvore+json (src/navegador.js:108), resposta pública em PT (src/catalog.js:360-409)
4Linguagem ubíqua1Dos 8 conceitos centrais, 1 tem nome único; /api/projects e /api/projetos vivos (server.js:354,371); "corpo" com 2 sentidos na mesma frase (src/routes/porta.js:209); nenhum gate de vocabulário
5Modularidade2Troca real em 0.20.0 (e0b99d0) fechou buraco de conferência; GCS sai com 1 arquivo; mas SQL cru em 30 arquivos
6Isolamento2152 asserções no gate curto (test/integracao-editores.js:564-589,654); public/app.js com 4.616 linhas e zero vazamento; mas sem gate estrutural de fronteira, assets escrita de 16 lugares
7Coesão2Zero pastas-gaveta; 33 de 41 passam no teste da frase; mas public/app.js com 12 assuntos e src/ plano com 41 arquivos
8Objetos a serviço da metáfora2Zero classes e zero Manager/Service/Handler — mas a obra tem coisas (item, peça, corpo, coleção) e nenhuma existe como objeto: 16 arquivos escrevem assets por SQL, 13 dão UPDATE, e não há src/item.js
9Desenhabilidade221 das 23 caixas têm corpo e as ligações são relações (não imports), mas a caixa central é a cinza — ver §4
10Ausência de contradições2Três buracos vivos (§5), mas toda disputa de posse está decidida e escrita; as 49 rotas batem 100% com os 4 docs que as citam

Soma: 21 / 30.

O critério 8 saiu de 3 para 2 no passe adversarial, e vale dizer por quê: o argumento que sustentava o 3 era que "o único módulo com estado é src/fila-oficina.js — uma fila, que é coisa, com estado, chamada de fila". A afirmação é falsa. São sete: src/contratos.js:32, src/corpo-canonico.js:68, src/esteira.js:119, src/esteira-ceu.js:110, src/esteira-miniatura.js:84, src/gcs.js:7, src/tipos-da-casa.js:471 — cinco deles caches de boot, que não são coisas. Com a premissa caindo, o que resta é o teste inverso que a régua manda aplicar, e ele reprova: a obra tem coisas evidentes e nenhuma delas é objeto no código.

O medidor de cinco segundos. Arquivos com nome de abstração no projeto inteiro (fora node_modules): 1 — public/vendor/BufferGeometryUtils.module.js, vendor do Three.js. Identificadores em src/: 1 — fonteUtilizavel (src/fonte.js), falso positivo, adjetivo em português. Ampliando para public/ (que a régua não varreu): mais 1 — installPasteHandler (public/app.js), verdadeiro positivo.

A régua registrou "1 em 36 arquivos de src/". Hoje são 56 (41 em src/ + 15 em src/routes/): o projeto cresceu 20 arquivos sem produzir um único gerenciador. A busca explícita por abstração com nome bonito — orquestrador, maestro, regente, gestor, coordenador, despachante — devolve zero.

A camada que puxou o resultado para baixo é a B (o alcance), e dentro dela o critério 4. E o diagnóstico é preciso: não é que o alcance seja raso — ele é 3. É que a metáfora alcançou fundo sem aposentar o que havia antes, e as duas eras coexistem no mesmo nível, publicadas.

A nota 3 em alcance foi atacada e resistiu, e o argumento que a salvou merece registro porque inverte uma leitura fácil. O ataque é forte no papel: 39 das 67 rotas são inglês técnico e 9 das 12 tabelas também, o que parece a descrição literal da nota 2 ("código e dado falam outra língua"). Mas a pergunta certa não é que nome tem a tabela — é que nome tem o campo que o consumidor recebe. src/catalog.js:351-432 é a função que monta a resposta de toda busca e listagem: dos 33 campos publicados, só cinco são inglês (id, slug, url, sha256, status), e quatro desses são vocabulário universal da web. Os outros 28 são nome, categoria, licenca, origem, autor, uso, medidas, osso, projeto, url_canonica, url_imutavel, exige_credito. E a escolha é declarada: src/catalog.js:343-345 — "Vocabulário estável e em português — quem lê isso está decidindo se usa o asset, não inspecionando o banco." A tabela é inglês; o dado que atravessa a fronteira é português. É o critério 6 ajudando a pontuar o 3: o consumidor não precisa saber o nome da coluna, e não sabe.

Um dado que a régua não previu e que vale para o critério 3: a metáfora chegou ao Dockerfile. Dockerfile:2 abre com "A imagem do acervo — Node, e as duas ferramentas da OFICINA", e as 110 linhas de comentário do arquivo explicam que a oficina é quem decidiu a imagem-base, porque uma das ferramentas dela não é Node. A régua tem cinco degraus de profundidade e o quinto é "dado e borda"; o empacotamento está abaixo disso, e mesmo lá o vocabulário se sustenta.


3. O desenho

relatorios/acervo.svg — publicado junto com este relatório.

Cada caixa é um objeto que o código nomeia; cada seta é uma ligação que existe (import, chamada HTTP, escrita em disco, registro em banco). Caixa cinza é peça sem corpo físico; linha tracejada é ligação que o desenho precisou e o código não tem. A cor separa o que nasceu depois de setembro do que é de abril e não foi convertido — porque essa fronteira, como se verá, explica quase tudo.


4. Onde o desenho não fechou

① Peça sem corpo: a coisa que a casa guarda não tem corpo no código. O acervo é uma casa que guarda itens, e não existe src/item.js — nem src/peca.js, nem src/acervo.js. A coisa guardada mora como linha na tabela assets, e 29 dos 56 arquivos escrevem SQL direto nela; 13 dão UPDATE. Cada cômodo tem nome, prosa de abertura e assunto próprio; a coisa que eles guardam, não. É por isso que a caixa do meio do desenho é cinza: todas as setas passam por um lugar que ninguém batizou. O conceito mais central do produto é o único sem peça.

② Ligação que não existe no mundo: a estante. No desenho, a estante é o móvel onde as coisas ficam — é o que a palavra promete. No código ela é só uma tela (server.js:392, public/app.js:3695) que lê a listagem de projetos: não guarda nada, não tem módulo em src/, não tem dado. O próprio projeto sabe e escreveu: test/integracao-estante.js:5-7 — "Ela não tem porta própria: lê a mesma listagem que todo editor lê." O móvel virou vitrine, e no desenho isso aparece como uma caixa que recebe seta e não emite nenhuma.

③ Duas peças invisíveis. A primeira é o encaixe — a pose da peça sobre o osso. Ele é dado real: lido (src/humano.js:262), servido na ficha (src/ficha-publica.js:589), documentado (docs/tipos-da-casa.md:415). Mas não tem módulo, coluna nem prova — e palavra sem dono ganha segundo sentido: em test/unidade-oficina.js:5 e test/integracao-oficina.js:18, "prova-se o encaixe" quer dizer "prova-se a integração". A mesma palavra nomeia um dado do domínio e uma categoria de teste. A segunda é a ausência de qualquer peça entre o código e o banco. O desenho precisou de uma prateleira e encontrou uma tabela que 29 arquivos tocam diretamente. Não há camada de persistência; src/db.js é um Pool de nove linhas com query() pass-through. É isso que torna o Postgres a única dependência que nenhuma troca contorna.


5. Contradições

Internas

C1 — A porta aceita um campo e o joga fora. Tipo 3. (a mais cara, e a única que já custa dinheiro)

O EZ3D mediu isto em produção: ez3d/src/acervo.js:234-236 — "Medido em 30/09 contra a porta de PRODUÇÃO com arquivo real: depositei com descricao preenchida, respondeu 201, e a ficha saiu description: null." E construiu uma segunda chamada HTTP por cima (descrever(), ez3d/src/acervo.js:255) cujo comentário diz que ela desaparece sozinha no dia em que a porta aceitar. A contradição não só existe — já pagou desenho alheio. Dois detalhes mostram como o buraco se esconde. src/routes/ferramentas.js:208 tem um comentário afirmando que o sync protege description de ser apagada pela curadoria automática — protege um campo que nunca foi gravado. E src/routes/ferramentas.js:277 devolve descricao: resultado.description na resposta: a porta publica de volta o campo que nunca gravou, então quem depositou recebe um eco vazio e tem motivo para acreditar que funcionou. test/integracao-ez3d-sync.js não pega.

Deve ganhar o acervo: gravar a coluna. Aceitar, responder 201 e descartar é a pior falha possível — a que parece sucesso.

C2 — O mesmo UPDATE em dois lugares, já divergindo. Tipo 1.

src/escrita-de-corpo.js:1-18 foi criado exatamente para matar essa duplicação e nomeia as três portas; src/routes/porta.js:69 importa o módulo e :379 promete que "passam pelo mesmo código" — mas o ramo da linha 422 ainda escreve por conta própria. E os dois já divergiram: src/escrita-de-corpo.js:264-269 preserva medida_autor/unidade_autor da versão anterior ("um lápis continua tendo 18 cm depois de ganhar mais polígonos"); src/routes/porta.js:432 passa as medidas cruas. Um item que sobe por esse ramo perde a medida declarada pelo autor — divergência silenciosa, o tipo mais caro. E o agravante que fecha o caso: src/escrita-de-corpo.js:255-263 escreve que "sem este resgate, uma versão corrigida do modelo apagaria em silêncio a medida que alguém declarou". O outro caminho faz exatamente o que esse comentário diz que não se pode fazer. Os dois UPDATE são idênticos byte a byte nas oito colunas; a única diferença é o parâmetro que carrega o estrago. Além disso, src/routes/uploads.js:230 chama ligacoes.validar() direto, sem passar pelo módulo comum: a convergência das três portas é 2/3, não 3/3 como o commit e0b99d0 afirma.

Deve ganhar escrita-de-corpo.js — o projeto já decidiu isso por escrito; falta terminar.

C3 — 142 KB de documentação descrevem um produto que não existe mais. Tipo 3.

Não é só atraso: os dois documentos declaram ativamente a metáfora antiga. README.md:1 e PROGRESS.md:1 abrem com "Pipeline universal de assets", e PROGRESS.md:13 descreve o produto como "Serviço universal pra gestão de assets (arte, áudio, etc)" — sem uma palavra de corpo, osso, peça, humano, editor ou lixeira, que é tudo o que o projeto fez nos últimos quarenta dias.

Isto agrava o critério 1 além do que eu havia escrito. Não é que a metáfora não esteja declarada: é que a declaração mais visível que o projeto faz sobre si mesmo é a da metáfora que ele abandonou. Um agente que chega lê 142 KB dizendo pipeline e painel, abre src/ e encontra oficina, esteira e lixeira. A doc não está em silêncio — está dizendo a coisa errada, alto.

C7 — Sete das onze provas de tela não têm comando que as rode. Tipo 3.

O diagnóstico está escrito pelo próprio projeto, duas linhas acima da declaração: test/corredor.js:5-9 — "uma suíte que só roda quando alguém se lembra dela não é uma rede de segurança: é um arquivo." Aplicado a si mesmo, sete arquivos. O corredor resolveu esse problema para as provas de texto e não o resolveu para as de tela.

Com os vizinhos

C4 — O leitor do mocap exige o que o acervo não garante. Tipo 2.

Um pacote sem idle passa pelo acervo como humano animado válido e reprova no mocap. Um pacote com o manifesto num nó é legível pelo mocap e invisível para o acervo. Deve ganhar almost-humanoid, que é o dono declarado do contrato — e o acervo já cede a posse por escrito em src/tipos-da-casa.js:156-160: "O dono do contrato NÃO é o acervo." A spec tem de dizer onde o manifesto pode morar; hoje cada lado assume.

C5 — O acervo lê CCP 1.4 e não declara que lê. Tipo 2, atenuado.

Aqui a régua está desatualizada: a 1.5 isentou o acervo por escrito (CCP-MANIFEST-1.5.md:459-461 — "O campo pecas.ossos que já existe lá não precisa mudar de lugar") e escreveu a precedência (:250 — "quando os dois endereços existem, proporcao.ossos vence"). Isso é dívida com dono, motivo medido e regra escrita — o padrão que a própria régua elogia. A contradição residual é menor e real: o acervo não declara que versão suporta. Um pacote 1.5 com proporcao.ossos entra, o acervo não vê a seção, não avisa, e a ficha sai incompleta em silêncio.

C6 — "Projeto" é duas coisas, com dois endereços públicos vivos. Tipo 2.

Duas entidades distintas, dois endereços, e a única diferença entre os endereços é a língua em que a mesma palavra foi escrita. public/app.js:3616-3628 documenta a ambiguidade em doze linhas — honestamente, mas em comentário. Custa uma leitura a cada vez, para sempre, e nada reprova quem errar. O mesmo padrão em coleções (/api/collections e /c/:slug). Deve ganhar a obra para /api/projetos, e a pasta deveria se chamar outra coisa — mas o dado já está publicado, e esta é a contradição mais cara de desfazer de todas.

O que foi investigado e descartado

Oito suspeitas não produziram os dois lados e por isso não entram, mas vale dizer quais, porque metade do valor de uma varredura é o que ela isenta: rotas documentadas que não existem (as 49 rotas batem 100% com os quatro docs que as citam); código morto em src/ (zero arquivos sem importador); public/editor-de-mentira/ (é dublê vivo da suíte, usado 10 vezes em test/integracao-editores.js); as três esteiras escrevendo a mesma tabela (fronteira declarada em src/esteira-ceu.js:12-14, um dono de dado e três produtores de bytes); miniaturas.js + esteira-miniatura.js (produtor e persistidor, separação justificada em src/miniaturas.js:5-7); custo calculado em dois lugares (há um único UPDATE assets SET custo no repositório); contratos duplicados nos vizinhos (zero ocorrências de marked-scene e did-project fora do acervo); e metáfora que se contradiz — procurei o par incompatível e não achei.


6. Ações propostas

Ordenadas por nota que movem por hora gasta. Horas são de trabalho de agente.

#AçãoHorasCritérioDe → para
1Gravar description no INSERT de src/routes/ferramentas.js:210 e cobrir em test/integracao-ez3d-sync.js0,5 h10reforça 2
2Reescrever as 20 primeiras linhas de README.md e PROGRESS.md com a frase da metáfora, e trocar public/index.html:61 h1, 2, 101: 2 → 3
3Terminar a extração: src/routes/porta.js:422 passa a chamar escrita-de-corpo.js, e src/routes/uploads.js:230 idem2 h10, 510: 2 → 3
4Um gate que carregue public/corpo/humanoid-base.bonemap.json e o confronte com almost-humanoid/src/rig/canonical-bones.js3 h4, 104: 1 → 2
5Versionar as portas de que o acervo é dono (porta-de-escrita@1, porta-dos-editores@1), com a sentinela que já existe para marked-scene@1.04 h6, 46: 2 → 3
6Dar corpo à coisa guardada: um src/item.js dono das leituras e escritas de assets, começando pelos 13 que dão UPDATE8 h5, 6, 7, 8, 98: 2 → 3; 9: 2 → 3
7Aposentar um dos dois nomes de "projeto": /api/projetos fica com a obra, a pasta é renomeada, /api/projects responde com aviso de depreciação8 h4, 104: 2 → 3

A ação 6 não é a mais barata, mas é a única estruturalmente necessária — e isso só ficou claro no passe adversarial. O acervo tem um defeito de arquitetura, e ele aparece três vezes na régua com nomes diferentes: no critério 8 (não há objeto onde a obra tem coisa), no 5 (o banco é substrato, não peça) e no 9 (a caixa cinza no meio do desenho). Não são três problemas que por acaso convergem — é um só, visto de três ângulos. Enquanto a coisa guardada não tiver corpo, 16 arquivos continuam negociando direto com a tabela, e nenhum dos três critérios sobe.

As ações 1 a 4 somam 6,5 horas, movem três critérios e são todas de acabamento: as 1 e 3 restauram gate que o projeto já decidiu ter, e a 4 constrói o gate que falta na jornada inteira — ele não existe em nenhum dos cinco repositórios.

A ação 2 mudou de natureza no passe adversarial e ficou mais urgente do que eu havia escrito. Eu a tinha formulado como "escrever a frase que falta". É pior: README.md:1 e PROGRESS.md:1 declaram ativamente a metáfora antiga — "Pipeline universal de assets" —, e PROGRESS.md:3 está datado de 22/09 com a última versão citada sendo a 0.17.3 contra a 0.21.0 em produção. Os dois documentos maiores do repositório, somando 142 KB, descrevem um produto que não existe mais: não mencionam humano, peça, osso, editor nem lixeira. Não é lacuna, é contradição tipo 3 na superfície mais lida — e é uma hora de trabalho.


7. O que eu não consegui avaliar


8. Onde a régua precisa ser corrigida

A régua usa este projeto como calibração em seis pontos. Quatro se confirmaram; três não. Como outras varreduras vão herdar essas afirmações, elas precisam ser corrigidas na fonte.

ERRADO — mixamorigHead não é o dialeto do acervo. A régua cita src/corpo-canonico.js:16-18 como prova de que o acervo fala Mixamo, e conclui que a jornada tem quatro dialetos de osso em conflito. As linhas citadas são o comentário que explica por que existe um mapa de tradução: "O corpo herdou os nomes do Mixamo (mixamorigHead) e a captura usa os padronizados da casa (head)." O mixamorigHead está do lado do arquivo, não do vocabulário. O acervo fala VRM puro — src/peca-de-humano.js:69-124 lista os 55 ossos como head, neck, leftUpperArm, hips, e migrations/026_peca_de_humano.sql:174-180 os crava num CHECK. Isso muda a resposta à pergunta do founder: a jornada EZ3D → acervo → mocap → humano animado não quebra no nome do osso. Três dos quatro projetos falam VRM; o único divergente é o video-mocap, que fala Mixamo-limpo porque captura de um rig Mixamo de verdade, e a divergência tem ponte. A lacuna real é menor e mais barata: não existe teste que confronte os dois mapas (a ação 4).

ERRADO — "pipeline" não é resíduo do nome do repositório. A régua diz que o nome do repo é "o único artefato que ainda diz pipeline dashboard". A palavra está viva em seis superfícies: public/index.html:6 (o título da aba de quem abre assets.did.lu), src/gcs.js:4 (GCS_PREFIX = 'assets-pipeline', que põe a palavra na URL de cada peça já publicada — https://st.did.lu/assets-pipeline/…), server.js:399 (o log de boot), package.json:2, package.json:5 (a description, que é a definição da obra que todo agente e todo painel de deploy lê) e README.md:1. Só "dashboard" é resíduo morto. A do bucket é a única que não dá para consertar de graça — as outras cinco são cinco linhas.

OMISSÃO — a régua não rodou no acervo o teste que ela mesma chama de "o mais rápido que existe". As pastas de primeiro nível (bancada contratos docs migrations public scripts src test) lidas em sequência não contam história: 6 de 8 são layout de qualquer projeto Node. Toda a metáfora vive dentro de um src/ plano de 41 arquivos em ordem alfabética, com routes/ como única subdivisão — e routes/ é divisão por tipo de arquivo, não por tema. É por isso que a nota em metáfora central aqui é 2 e não 3, divergindo da leitura implícita da régua.

DESATUALIZADO. A contagem do medidor era "1 em 36 arquivos de src/"; hoje são 56, e o numerador continua 1. A régua não conhece a migração 028 (4 colunas novas, todas em português) nem as 8 rotas de lixeira/varredura. E a afirmação de que "balde só vive em comentário" deixou de valer na 0.20.0: test/integracao-editores.js:76 declara const balde = new Map() e :166 registra app.get('/balde/*') — o sinônimo que vivia em comentário virou identificador.

CERTO, e vale registrar. O par calibrador lixeira (degrau 5) × estante (degrau 3) confirma-se em todas as cinco células. A tabela asset_parts com coluna papel e comentário em português (migrations/006_collections.sql:193-205) são mesmo três vocabulários em cinco linhas. "Corpo" tem mesmo dois sentidos em src/routes/porta.js, e na mesma frase: a mensagem de erro da linha 209 é "corpo vazio — mande os bytes do arquivo no corpo do PUT". E o veredito do medidor de cinco segundos — degrau 3 — sustenta-se melhor hoje do que quando foi escrito.


9. A leitura que eu levaria para a mesa

O acervo não tem problema de rigor. Tem uma conversão que parou no meio.

A evidência que organiza tudo é cronológica, e é quase binária. Datei a criação dos 56 arquivos de código do servidor e cruzei com a presença do cabeçalho que nomeia o objeto físico. Dos 14 nascidos até 04/08, zero têm cabeçalho. Dos 42 nascidos de 23/08 em diante, 39 têm. A mesma fronteira explica o banco (9 tabelas em inglês até a 027, 3 em português depois), as rotas (39 em inglês nos arquivos de 001–018, 28 em português nos de 019 em diante, zero exceções nos dois sentidos) e a divisão entre src/catalog.js e src/peca-de-humano.js.

Isso não é "a metáfora não alcança a infraestrutura", que seria limitação natural e cara. É "a metáfora nasceu em agosto e ninguém voltou para converter o que já estava construído" — que é trabalho finito, e barato, porque a parte cara já foi paga. Decidir qual é a imagem é o difícil, e está feito. O que falta é terminar.

E onde o projeto decidiu, decidiu com uma qualidade acima da média da casa. Cada gate abre com o incidente datado que o motivou e com o raciocínio de por que a saída óbvia seria pior: test/unidade-tipos-da-casa.js:12 — "Uma conferência que nunca reprova é um comentário", que é a tese central da régua escrita pelo projeto antes de a régua existir. scripts/confere-contratos.js:8-20 explica por que a cópia vendorizada continua sendo o que executa (ler a URL no upload poria o servidor de outra casa no caminho crítico da porta e tornaria a entrada não-determinística) e por que a sentinela separada é o que avisa. test/corredor.js:17-37 documenta por que uma prova foi expulsa do gate curto: media tempo de montagem junto com permissão, e o que separa o código do ar não pode depender de quanto a máquina está ocupada.

A régua abre dizendo que na casa a lei sem gate não pegou e o gate sem lei pegou. O acervo é a prova positiva dessa tese: nunca escreveu lei de vocabulário nenhuma, e tem nove gates executáveis, quatro deles no caminho da publicação.

Mas há um defeito que não é de acabamento, e o passe adversarial foi quem o isolou. Eu havia distribuído o problema em três critérios diferentes, com três nomes diferentes. É um só: a coisa que a casa guarda não tem corpo no código. Não existe src/item.js. O item mora como linha na tabela assets, e por isso 16 arquivos negociam diretamente com ela e 13 dão UPDATE. Esse único fato é o que aparece como nota 2 no critério 8 (não há objeto onde a obra tem coisa), como nota 2 no critério 5 (o banco é substrato, não peça trocável) e como a caixa cinza no meio do desenho, no critério 9.

A consequência prática é visível: a contradição C2 — dois UPDATE idênticos, um dos quais apaga em silêncio a medida declarada pelo autor — só é possível porque não há dono. Num projeto onde o item fosse um objeto, não haveria dois lugares escrevendo as mesmas oito colunas, porque não haveria dois lugares.

O resumo que eu levaria à mesa, então, é de duas frases. O acervo tem uma metáfora física genuína, consistente da primeira linha dos arquivos até o campo JSON que sai pela borda e até o Dockerfile — e ela nunca chegou à única coisa que a casa existe para guardar. A dívida de acabamento é grande mas barata (seis horas e meia movem três critérios); a dívida estrutural é uma só, custa oito horas, e é a diferença entre um projeto bem escrito e um projeto bem construído.

Sobre futuro, que é o que importa: este é um projeto que sabe decidir e sabe provar. Ele construiu nove gates sem nunca ter escrito uma lei, documentou cada um com o incidente que o motivou, e expulsou do caminho crítico a prova que não cabia ali. A régua diz que um projeto que tira 14 com metáfora clara tem mais futuro que um que tira 22 sem nenhuma. Este tira 21 com metáfora clara, e a lista do que falta cabe num dia de trabalho.