← Arquitetura da Casa

Avaliação · video-mocap

video-mocap — a esteira de leitura do corpo humano, e o README que ficou para trás

Sete etapas declaradas em código, sete pastas com o nome delas, e o disco como única memória. A metáfora está mais forte no código do que na vitrine: o README desenha a esteira de 28/09 e não cita o orquestrador uma única vez. O conceito central do produto — como um quadro termina — tem três escalas incompatíveis no mesmo nome de campo.

01 de outubro de 2026  ·  medido pela régua da casa  ·  HEAD 64d3030 (0.47.0)  ·  inclui o contrato do corpo do almost-humanoid  ·  notas submetidas a contraditório adversarial

20/30soma pela régua
0 / 0medidor de cinco segundos
(arquivos / identificadores, em 252)
Dcamada que puxou para baixo
(a prova)
3escalas de desfecho vivas
num campo chamado veredito

video-mocap — avaliação de arquitetura

Varredura de 01/10/2026, pela régua em REGUA.md. Inclui o almost-humanoid como dono do contrato do corpo, porque o mocap anima esse corpo.

Nota de método, que vale ler antes das notas. A régua da casa usa o video-mocap como calibrador — ele aparece como exemplo do que é bom (a esteira, o estado em disco, o teste de fronteira) e do que é ruim (a gaveta x/, a cópia datada da spec). Esta varredura não repetiu essas citações: conferiu cada uma contra o disco de hoje. Três afirmações da régua não se sustentam, e estão corrigidas no corpo do relatório — uma delas (o teste que reprova import indevido) está no arquivo errado e cobre menos do que a régua diz; outra (as duas traduções de osso que divergiriam) foi medida osso por osso e não divergem em nenhum.


1. A metáfora em uma frase

video-mocap é uma esteira de leitura do corpo humano: entra um vídeo por uma porta, ele passa por sete estações em fila — cada uma lê uma parte, escreve o seu arquivo e não sabe que as outras existem — e sai um humano animado pela entrega.

A metáfora é declarada, e é declarada em código, não em prosa: esteira/contrato.mjs:50 abre export const ETAPAS = [ com as sete estações, e esteira/contrato.mjs:5 diz o que esse arquivo é — "a tradução em código de docs/ETAPAS.md". As sete etapas têm pasta homônima no disco, e o laço carrega cada uma pelo nome (esteira/esteira.mjs:84-90).

Mas há um problema de porta de entrada, e ele é o achado nº 1 deste relatório. O README.md desenha outra esteira — a de 28/09, vídeo → quadros → pose → juízo → reparo → animação → pacote → acervo (README.md:46-50) — e documenta onze pastas em seções próprias (README.md:60 a :301), nenhuma das quais é uma das sete etapas vivas. Ele não menciona esteira/ uma única vez, e não linka docs/ETAPAS.md, que é o contrato da arquitetura. Quem entra pela frente aprende o vocabulário de uma esteira aposentada.

Isso não é metáfora fraca. É o oposto: a metáfora ficou mais forte no código do que na vitrine, em quatro dias de 264 commits e 63 mil linhas. A vitrine não acompanhou.


2. Notas

#CritérioNotaEvidência
1Metáfora central2esteira/contrato.mjs:50 (as 7 etapas em código) contra README.md:57 (desenha o fluxo aposentado) e zero menções a esteira/ em 382 linhas de README; 9 de 30 pastas pertencem à esteira
2Fisicalidade da metáfora3medidor devolve 0 e 0 em 252 arquivos; porta/armazem.mjs:1, limpeza/chao.mjs:2, entrega/boneco.mjs:2, maos/territorio.mjs:1, esteira/pasta.mjs:1
3Alcance da metáfora na estrutura2degrau 4 pleno (ETAPAS, ONDE_MORAM, DESLIGADAS); degrau 5 falha: 0 de 19 rotas no vocabulário da obra (porta/rotas.mjs:54-409), 0 de 9 tabelas, e porta/rotas.mjs:54 publica service: 'video-mocap'
4Linguagem ubíqua1três escalas num campo chamado veredito: limpeza/limpar.mjs:702, juizo/veredito.mjs:33, captura/alvo.mjs:215; maoEsq contra mao_e; e nenhum gate de vocabulário na suíte
5Modularidade2o disco como memória é real (esteira/contrato.mjs:19-33); mas esteira/ETAPA-NOVA.md:42 promete "uma linha" contra test/ligacao.mjs:90 (dois arquivos, três com o harness), e a troca de motor ficou em captura/, que não está em ONDE_MORAM
6Isolamento2gate real em test/animacao.mjs:749, com lista fixa de 8 arquivos (:755-758) num produto de 129 .mjs — 6,2% — e por regex de texto-fonte (:762), cega ao await import() que o próprio orquestrador usa (esteira/esteira.mjs:157)
7Coesão223 das 30 pastas passam no teste da frase; falham 7, e x/ não está nomeada (x/PROVAS.md:1 fala de outro assunto)
8Objetos a serviço da metáfora3zero Manager/Service/Handler; e os objetos com estado são coisas da metáfora: captura/motor.py:56 (Motor, "o motor carregado, de pé, pronto para receber quadro"), maos/py/ancora.py:53 (Ancora), maos/py/recorte.py:45, leitura/esqueleto_mhr.py:45
9Desenhabilidade2o desenho principal existe e roda (esteira/README.md:17-27); mas 14 das 30 pastas ficam de fora, e a etapa 5 exige legenda (esteira/contrato.mjs:167-173)
10Ausência de contradições internas19 contradições (seção 5), três delas no README.md, e a suíte vermelha no HEAD (test/receita.mjs:236, 610 ✓ / 1 ✗)

Soma: 20 / 30.

O medidor de cinco segundos — os dois números:

Os dois zeros confirmam a régua, e num projeto de 252 arquivos de código isso é o número mais limpo da casa.

A camada que puxou o resultado para baixo: a camada D — a prova. E ela puxou do jeito que a régua previu que puxaria: "a camada D verifica as camadas A–C". As notas baixas em metáfora central (1), alcance (3), linguagem ubíqua (4), isolamento (6) e contradições (10) têm todas a mesma raiz, e vale dizê-la em voz alta — este projeto escreve documentação excepcional e tem só dois gates reais, ambos de cobertura estreita.

Os dois gates são bons: test/animacao.mjs:749 prova que o produto não importa código de outro produto, e test/ligacao.mjs:90 prova que a esteira alcança as etapas que existem (e nasceu de um defeito real — três etapas prontas que a esteira não achava, esteira/esteira.mjs:116-120). Mas o primeiro cobre 8 de 129 arquivos, por regex de texto-fonte que não vê o await import() do próprio orquestrador. Nada na suíte roda o medidor de abstração. Nada recusa um nome de desfecho errado.

A régua foi desenhada exatamente para não premiar isso — "lei sem gate é intenção; estrutura que recusa o errado é arquitetura" — e está certa em não premiar. A única nota 3 que sobrevive a um ataque adversarial completo é a fisicalidade, e sobrevive porque é a única sustentada por uma medição (0 e 0) em vez de uma afirmação.

O que isso NÃO quer dizer. Não há camada mal arquitetada aqui. Há documentação de 28/09 descrevendo um código de 30/09, num repositório que fez 264 commits e 63 mil linhas em quatro dias. O custo de andar rápido foi pago na superfície de leitura, não na estrutura — e é por isso que quatro das sete ações abaixo custam duas horas ou menos.


3. O desenho

Em relatorios/video-mocap.svg, publicado junto com este relatório.

Ele desenha: a porta, a esteira com as sete estações em fila, a pasta de trabalho como o chão da esteira, a farm como máquina de fora, o pacote e o acervo, o leitor como prova escrita do outro lado, o contrato do corpo morando fora do produto — e, em cinza e tracejado, as duas gavetas, o fluxo aposentado e a peça invisível.

O desenho fechou sem inventar peça, e isso é informação: a arquitetura que o código tem é a que se desenha. As ligações são todas reais (arquivo em disco, HTTP, import), e estão rotuladas com o que passa — o vídeo, o miolo, a pose crua, o animacao.glb — não com "usa".


video-mocap — a esteira de leitura do corpo humano Cada caixa é uma coisa do mundo. Cada seta é uma ligação que existe no código, rotulada com o que passa por ela. Caixa cinza = peça sem equivalente físico. Linha tracejada = ligação que o desenho precisou e o código não tem. A PORTA porta/ · o celular entra Compartilhar → Video Mocap porta/esteira.mjs:1 A ESTEIRA — um orquestrador só, sete estações em fila esteira/contrato.mjs:50 · a lista de etapas é código, não configuração. A memória é o disco: presença do arquivo é prova de conclusão. 0 · ENTRADA entrada/ os bytes, intocados entrada.json 1 · CORTE corte/ não mede mais corte.json · miolo.mp4 2 · LEITURA leitura/ roda FORA — na farm leitura.json · .jsonl 3 · ESQUELETO esqueleto/ 22 ossos + 30 dedos esqueleto.json 4 · ROSTO rosto/ 52 pesos ARKit rosto.json 5 · LIMPEZA limpeza/ DESLIGADA, não pulada laudo.json · *.limpo.json 6 · ENTREGA entrega/ animacao.glb lado-a-lado.mp4 A PASTA DE TRABALHO — o disco é a única memória ~/.video-mocap/trabalho/<id>/ · esteira/pasta.mjs:40 · toda escrita é tmp + rename "apagar um arquivo é como se pede pra refazer" — esteira/contrato.mjs:29 cada estação escreve o seu arquivo e lê o da anterior — nenhuma chama a seguinte o meta de cada etapa RECUSA um "ok" sem dizer quantos quadros entregou (esteira/contrato.mjs:montarMeta) o vídeo, e nada mais A FARM — a máquina com placa outro parque, outro dono · fila/farm.mjs "a máquina com placa só lê" — nenhuma decisão de formato mora nela (docs/ETAPAS.md §Por que assim) o miolo.mp4 + a receita a pose crua, por quadro O CONTRATO DO CORPO mora FORA deste produto almost-humanoid CCP 1.5 · ossos VRM pecas.porOsso A CÓPIA DATADA pacote/CONTRATO.md:3 lida contra a 1.4 escreve 1.3, com motivo "sem ela, uma divergência futura seria invisível" O DIALETO a captura fala Mixamo o contrato fala VRM 52 pares, uma tradução só animacao/canonico.mjs:57 LeftArm é o BRAÇO, não o antebraço — a armadilha do nome que quase bate nenhuma linha importada a especificação, lida e datada O PACOTE pacote/ · o humano, em glb o manifest mora DENTRO do arquivo, não ao lado O ACERVO a estante da casa outro produto, outro repo quem consome pega de lá o animacao.glb O LEITOR — a prova escrita do outro lado da fronteira acervo/leitor.mjs:17 · não importa UMA linha deste repositório "um escritor que se valida sozinho prova apenas que é coerente consigo mesmo" lê o que está NO AR x/ 31 arquivos de diagnóstico datado ia/ 41 arquivos; a resposta do experimento foi NÃO O FLUXO APOSENTADO — declarado, não apagado fila/ · porta/rodada.mjs · juizo/ · captura/ · animacao/ · mundo/ · miolo/ fila/APOSENTADO.md põe os três orquestradores numa tabela, diz qual é o de verdade, e crava a condição de saída. No banco a separação é mecânica: o estado 'na_esteira'. O ATRITO: TRÊS escalas de desfecho, um só nome de campo laudo.json → BOM / REPARADO / LACUNA · corpo, mao_e, mao_d juiz.json → bom / suspeito / ruim / ausente · corpo, maoEsq, maoDir, rosto captura/alvo.mjs → INEXISTENTE / NAO-E-PESSOA / ALVO / PESSOA-SECUNDARIA os três chamam o campo de `veredito` — e nada reprova a escala errada A PEÇA INVISÍVEL — o README desenha a esteira de 28/09 (captura → juízo → animação → pacote) e não cita `esteira/` nem `docs/ETAPAS.md` uma única vez. O contrato vivo da arquitetura não tem porta de entrada. Quem chega pela frente aprende o vocabulário errado.
O desenho da arquitetura. Caixa cinza é peça sem equivalente físico; linha tracejada é ligação que o desenho precisou e o código não tem.

4. Onde o desenho não fechou

Peça invisível — a mais caras das três, e a razão da nota 2 em metáfora. O desenho precisa da esteira de sete etapas para fazer sentido, e ela não tem porta de entrada na documentação de superfície: README.md não cita esteira/ nem docs/ETAPAS.md. O contrato vivo da arquitetura só é encontrável por quem já sabe que ele existe.

Peça sem corpo — x/. 31 arquivos de diagnóstico datado (x/diag-74.mjs, x/diag-alcance-30set.mjs, x/suav-maru-30-09.mjs). x não é objeto nem gesto, é gaveta. E não está nomeada como gaveta: x/PROVAS.md:1 fala de provas de tela da porta, que é assunto de porta/. Nenhum arquivo de x/ é importado pela esteira.

Peça sem corpo — ia/. 41 arquivos, e o próprio .md dela registra que o experimento terminou em não (ia/IA-NOS-QUADROS.md:3-4: "A resposta, medida em 385 recortes de quatro vídeos: não"). A pasta se chama ia/ e o resultado dela é que IA não entrou. É arquivo de levantamento concluído ocupando nome de pasta de produto.

Ligação que não existe no mundo — trabalho/. O desenho põe a pasta de trabalho como o chão da esteira, e ela mora fora do repositório (esteira/pasta.mjs:42: join(homedir(), '.video-mocap', 'trabalho'), com a razão escrita — os vídeos originais do founder não podem estar sob um clone que um deploy substitui). Mas existe um trabalho/ dentro do repo, com um único filho: trabalho/_corpo/, guardando um .glb de 10 MB baixado do acervo (entrega/acervo.mjs:46). Não é versionado, mas ocupa o nome do conceito mais central da esteira para guardar cache de asset. Um agente que leia a árvore encontra trabalho/ e conclui a coisa errada.

Caixa cinza — o fluxo aposentado (fila/, porta/rodada.mjs, juizo/, captura/, animacao/, mundo/, miolo/, maos/). Estão no desenho em tracejado vermelho porque o projeto as declara aposentadas (fila/APOSENTADO.md), não porque sejam órfãs — a diferença importa, e é o que separa este caso de código morto.

A contagem que decide a nota 2 em desenhabilidade: somando o fluxo aposentado, as duas gavetas, teto/, pagina/, public/, pacote/ e acervo/, são 14 das 30 pastas que a esteira não alcança — quase metade. E uma caixa que está no desenho exige legenda em prosa: a etapa 5 roda mas não faz nada (esteira/contrato.mjs:167-173), e quem desenhar as sete estações tem de escrever ao lado da quinta "roda em modo cópia, e volta se o founder aprovar". A régua define nota 2 como "algumas caixas cinzas e ligações que precisam de legenda" — é exatamente este caso, e o que segura a nota em 2 e não em 1 é que o projeto sabe quais são as cinzas e por quê.

As sete pastas que falham no teste da frase sem "e". A contagem do critério 7, porque a régua pede número e não impressão — 23 das 30 passam, e falham estas:

pastaa frase que ela exigeevidência
porta/recebe o vídeo, e mostra a fila, e entrega o resultado, e avisa quando fica pronto — quatro assuntosporta/PORTA.md:13-14
entrega/escreve o .glb e o vídeo lado a lado e a página do celular — três produtosentrega/README.md:3-5
limpeza/conserta tremor e salto e pé no chão, em 16 arquivoslimpeza/LIMPEZA.md:1
mundo/trajetória e câmera e cena — e o arquivo principal se declara "A BANCADA"mundo/medir.mjs:2
teto/mede o limite e ancora o corpo e publica a página — e o assunto é o chãoteto/ancorar.py:3
x/gaveta, e não nomeada: o .md dela fala de outro assuntox/PROVAS.md:1
ia/degraus de leitura e montagem de página, 41 arquivosia/IA-NOS-QUADROS.md

Nenhuma delas derruba o projeto, e a régua é explícita sobre isso: "nota 3 não exige pureza, exige que as exceções sejam poucas e identificáveis". Sete em trinta é identificável — e é a definição da nota 2.

O que o desenho revelou e a leitura não mostrara: juizo/ saiu da esteira. Nenhuma das sete etapas chama juizo/. Quem o usa é limpeza/, e só pela geometria dele (limpeza/chao.mjs:51, limpeza/raiz.mjs:50 — mediana, MAD, percentil). O veredito do juizo/ não é consumido por ninguém do fluxo; o laudo da régua é produzido em limpeza/limpar.mjs:171. A pasta que o README apresenta como o coração da qualidade do produto (README.md:104) está fora do caminho, e isso não está escrito em lugar nenhum.


5. Contradições

Internas

(a) Duas esteiras documentadas, uma só viva. Tipo 3. README.md:46-50 desenha captura → juizo → animacao → pacote → acervo; docs/ETAPAS.md e esteira/contrato.mjs:50 declaram entrada → corte → leitura → esqueleto → rosto → limpeza → entrega. Deveria ganhar docs/ETAPAS.md — é o que o código executa, e é o documento que a própria esteira cita como fonte (esteira/contrato.mjs:5).

(b) TRÊS escalas de desfecho num campo com o mesmo nome. Tipo 5 (vocabulário), e é a mais caras das internas — é ela que sozinha derruba o critério 4 para 1. Três lugares emitem um campo chamado veredito, com três conjuntos de valores incompatíveis:

ondevalorespartes
limpeza/limpar.mjs:702 → laudo.jsonBOM · REPARADO · LACUNAcorpo, mao_e, mao_d
juizo/veredito.mjs:33 → juiz.jsonbom · suspeito · ruim · ausentecorpo, maoEsq, maoDir, rosto
captura/alvo.mjs:215,226,235INEXISTENTE · NAO-E-PESSOA · ALVO · PESSOA-SECUNDARIA—

Três arquivos que parecem o mesmo formato e não são. O rosto existe numa escala e não na outra, e a mesma mão é mao_e de um lado e maoEsq do outro — dois nomes na mesma língua, que é precisamente o que a régua define como falha (divergência de idioma teria desculpa; isto não tem). E o consumidor paga: maos/qualidade.mjs:67 faz q.partes[parte]?.veredito || 'ausente', ou seja, defaulta para o vocabulário de uma escala sem saber qual chegou. Deveria ganhar a escala da esteira (BOM/REPARADO/LACUNA, snake_case), porque é a que a régua do produto cita (docs/REGUA.md:19) e a que vira entrega. As outras duas ou se alinham, ou mudam o nome do campo para não serem homônimas.

(c) A doc da entrega lista o mesmo arquivo duas vezes. Tipo 3, barato. entrega/README.md:48 diz que glb.mjs é "o glTF binário, escrito direto"; entrega/README.md:57 diz que glb.mjs é "o glb de cápsulas — a QUEDA de quando o corpo não carrega". No disco há entrega/glb.mjs (que é o primeiro — confirmado em entrega/glb.mjs:2) e entrega/prova/glb.mjs. Ganha a linha 48; a 57 é resíduo de uma renomeação.

(d) "Uma linha fora da pasta" contra dois arquivos. Tipo 3. esteira/ETAPA-NOVA.md:42 promete: "É a única linha que você toca fora da sua pasta." Mas test/ligacao.mjs:90-94 reprova se ETAPAS (esteira/contrato.mjs:50) e ONDE_MORAM (esteira/esteira.mjs:84) não concordarem — são dois. Com o harness (test/run.mjs:16, lista à mão), três. Ganha o teste; a doc precisa dizer dois.

(e) Três versões do contrato do corpo em três documentos do mesmo repo. Tipo 2. docs/REGUA.md:60 fala em CCP 1.3; pacote/CONTRATO.md:3 diz "Leitura de 30/09/2026, contra o CCP 1.4"; e pacote/montar.mjs:80 emite VERSAO_MANIFEST = '1.3'. Os três são defensáveis isolados (a emissão é 1.3 de propósito, com motivo escrito em montar.mjs:68-70), mas um leitor que cruze os três não tem como saber qual é qual. Ganha pacote/CONTRATO.md, que é o documento que existe exatamente para essa pergunta.

(f) A suíte está vermelha no HEAD publicado, e o gate depende do ambiente. Tipo 1. npm test na árvore limpa: 610 passam, 1 falha em 10,4 s. A que falha é test/receita.mjs:229, que exige procedencia.nao_escolhidos não vazio — isto é, exige que exista uma segunda cópia do produto no disco para passar. Numa máquina com uma cópia só, o gate reprova sem haver defeito. Gate que depende do estado da máquina não é gate. Deveria ganhar o teste, reescrito para montar as duas cópias que ele quer medir, como test/ligacao.mjs:124 já faz com módulos de mentira numa pasta temporária.

E há um custo que não é o da falha em si: esteira/ETAPA-NOVA.md:42-44 manda quem escreve uma etapa nova conferir com node test/run.mjs, "custa milissegundos". Quem o faz hoje recebe um vermelho que não tem nada a ver com a etapa dele, e aprende a ignorar o placar. Gate com falso positivo permanente ensina a ignorar o gate — o que é pior que não ter gate, porque o próximo vermelho real também será ignorado.

(g) O README se contradiz consigo mesmo sobre o conceito central do produto. Tipo 3, e é a mais barata de consertar das nove. README.md:23 abre: "Todo quadro termina de um de três jeitos, e nunca em silêncio", e lista BOM / REPARADO / LACUNA numa tabela. Oitenta linhas abaixo, README.md:106: "o veredito é BOM/SUSPEITO/RUIM/AUSENTE". Três jeitos e quatro jeitos, no mesmo arquivo, sobre a promessa que abre o produto. Ganha a tabela da linha 23 — é a que a régua do projeto cita (docs/REGUA.md:19) e a que o laudo emite.

(h) O README promete uma troca que o próprio projeto registra não ter acontecido. Tipo 3, e é a mais consequente. README.md:52-53: "Cada um é trocável sozinho: o dia em que um modelo melhor aparecer, troca-se a pasta, e nada mais muda." O modelo melhor apareceu, e fila/APOSENTADO.md:43-46 registra o que de fato aconteceu: holistic.json e wilor.json continuam sendo lidos, "e a esteira não os produz e nenhuma etapa dela os lê". Contei quantos arquivos ainda leem o formato do leitor antigo: 33. Ganha o APOSENTADO.md, que é honesto; o README precisa parar de prometer custo zero de troca.

(i) A rota pública chama o produto de service. Tipo 4 (metáfora que se contradiz), e é pequena, mas é exatamente o caso que a régua da casa catalogou. porta/rotas.mjs:54 responde { vivo: true, service: 'video-mocap' }. O repositório cujo medidor de abstração devolve 0 em 252 arquivos publica, na borda, a primeira palavra da lista que o medidor procura. A régua nomeia o mesmo defeito no acervo ("o healthcheck que esquece o nome da casa", server.js:271), e diz onde a erosão começa: na superfície que ninguém lê como parte da obra. Ganha o vocabulário da obra — produto, app, ou simplesmente nome.

Com os vizinhos

(g) O mocap é invisível no contrato que ele consome. Tipo 5, e é a mais consequente das duas. video-mocap/README.md:33-35 declara que a especificação do pacote "mora no almost-humanoid", e pacote/CONTRATO.md:16 aponta os arquivos de lá nominalmente. Do outro lado: video-mocap tem zero ocorrências em todo o almost-humanoid. A seção "Para quem consome" do contrato (almost-humanoid/docs/CCP-MANIFEST-1.5.md:437-466) nomeia o editor de humano por número de tópico e nomeia o acervo — e não nomeia o mocap. O mocap só aparece como pedido histórico (almost-humanoid/src/envelope/manifest.js:85-86, "os cinco buracos que a frente de captura de vídeo apontou"). Deveria ganhar o mocap entrar na lista. Quem produz movimento para esse corpo é consumidor de primeira classe, e hoje uma mudança de contrato não tem como avisá-lo.

(h) Duas traduções do mesmo par, sem gate cruzado — e aqui a régua da casa precisa de correção. Tipo 2, mas latente, não materializada. video-mocap/animacao/canonico.mjs:57 tem 52 pares Mixamo→VRM; almost-humanoid/src/rig/mixamo-map.js:37 tem 67. A régua supõe que divirjam. Medidos osso por osso: toda chave compartilhada mapeia para o mesmo destino. Zero divergência. A diferença é de cobertura e de desenho — o lado do dono marca ossos de ponta (HeadTop_End, pontas de dedo) como null explícito para separar "ignorar de propósito" de "desconhecido" (almost-humanoid/src/rig/mixamo-map.js:52); o mocap tem dois estados e nomeia esses ossos em descartadas (animacao/canonico.mjs:159). A armadilha que custa caro — LeftArm é o braço de cima, LeftForeArm o de baixo — está documentada três vezes: animacao/canonico.mjs:17-27, inline no mapa em :66 e :76, e pacote/CONTRATO.md:119-124. Há teste provando-a (test/animacao.mjs:415-419) e provando bijetividade (:428). Mas o teste prova contra uma constante local, não contra a fonte do dono, e não existe nada que leia os dois mapas: grep por canonico.mjs no almost-humanoid dá vazio, e por mixamo-map no mocap também. Os dois concordam por disciplina humana. Quando divergirem, divergirão calados, e o sintoma — braços dobrados ao contrário — parece defeito de limite articular. Deveria ganhar um gate que compare os dois mapas; é a ação de maior valor deste relatório.

(i) ossos significa três coisas na casa. Tipo 2, hoje sem colisão. almost-humanoid/docs/CCP-MANIFEST-1.5.md:48 — proporcao.ossos é deslocamento absoluto em metros; almost-humanoid/src/envelope/pecas.js:87 — pecas.ossos é o endereço legado do mesmo dado, tolerado com justificativa medida (:69-85); video-mocap/pacote/da-captura.mjs:100 — procedencia.ossos é contagem de lacunas e canais omitidos. Vivem em documentos diferentes e não colidem. Nenhum deveria ganhar — o que falta é o nome distinguir, e o único dos três que pode mudar sem custo de publicação é o do mocap.

(j) A proporcao inteira não existe na cópia datada. Tipo 2, defensável. O CCP 1.5 acrescentou proporcao com seis campos, uma capability e dezessete códigos de erro (almost-humanoid/docs/CCP-MANIFEST-1.5.md:42-49, :416-431). A cópia do mocap não cita a palavra. É defensável pela mesma razão que a cópia já escreveu sobre a montagem por osso (pacote/CONTRATO.md:274-278: uma captura entrega o movimento que o humano executa, não o corpo que ele é) — e o 1.5 é aditivo e opcional, sem reempacotamento. Ganha a decisão de não usar; o que falta é escrevê-la, para a próxima leitura não reabrir a pergunta.


O que vale registrar como bom, porque é raro e sustenta as notas 3

Três padrões deste repositório merecem virar referência da casa, e nenhum deles é declaração — todos são mecanismo:

O disco como única memória. esteira/contrato.mjs:19-33 — a esteira não guarda "a etapa 3 está feita"; ela olha se esqueleto.json existe. Daí saem de graça: sobreviver a reinício, não haver duas verdades para conciliar, e "roda de novo" ser rm. O preço (toda escrita é tmp+rename, esteira/pasta.mjs:113) está declarado, e a razão também: um arquivo pela metade seria uma etapa mentindo que terminou.

A lacuna de contrato declarada pelo nome, não por campo vazio. leitura/adaptador.mjs:20-30 enumera as duas escolhas ruins e a boa: a etapa 2 escreve o contrato com o que a fonte sabe e declara em leitura.json, por nome, os campos que esta fonte não fornece, para a etapa 3 distinguir "o motor não viu a mão" de "esta fonte não me manda esse campo". É o LACUNA do domínio aplicado à própria fronteira entre etapas, e é o tipo de coisa que evita uma semana de busca pelo defeito na etapa errada.

O desligamento visível. esteira/contrato.mjs:167 — a limpeza está desligada por ordem do founder, e desligada não é pulada: a etapa roda, entrega os três arquivos em modo cópia, o laudo continua sendo medido, e ela aparece como desligada no estado do trabalho mesmo depois de feita (esteira/contrato.mjs:retrato). A razão está escrita: um pulo é invisível seis semanas depois, e o defeito acaba atribuído à etapa errada. A lista mora em código e não em variável de ambiente, com o motivo e a data ao lado.


6. Ações propostas

Ordenadas por nota que movem por hora gasta. As três primeiras custam uma hora cada e, juntas, movem quatro critérios.

AçãoHorasCritério que moveDe → para
1. Reescrever "Os estágios" do README.md com as sete etapas vivas; linkar docs/ETAPAS.md e esteira/ na primeira tela; marcar o diagrama da linha 57 como fluxo aposentado1 h1 — Metáfora central; 10 — Contradições2 → 3
2. Consertar as três contradições do próprio README.md: os três desfechos contra os quatro (linha 23 × 106), e a promessa de troca de custo zero (linha 52) contra os 33 arquivos presos no formato antigo1 h10 — Contradições; 4 — Linguagem ubíqua1 → 2
3. Desacoplar test/receita.mjs:236 do ambiente — montar as duas cópias que ele mede numa pasta temporária, como test/ligacao.mjs:124 já faz — e deixar a suíte verde1 h10 — Contradições1 → 2
4. Trocar a lista fixa de 8 arquivos do gate de fronteira (test/animacao.mjs:755) por varredura de todo o repo, somando await import(…) à regex3 h6 — Isolamento2 → 3
5. Unificar a escala de desfecho nos três lugares, ou renomear o campo onde a escala for outra — e pôr um gate que recuse valor fora da escala4 h4 — Linguagem ubíqua1 → 3
6. Um gate que compare os dois mapas de osso: ler animacao/canonico.mjs e o mixamo-map.js do dono como dado, e reprovar divergência de destino3 h4 e 10— (impede regressão)
7. Mover os 31 arquivos de x/ para diagnostico/ com um .md que diga que é gaveta datada; arquivar ia/, cujo .md já registra que o experimento terminou2 h7 — Coesão; 9 — Desenhabilidade2 → 3

Sobre a ordem, três notas.

A ação 1 é a mais barata do relatório e move o critério que a régua considera o mais importante. Ela e a 2 são o mesmo trabalho em dois arquivos: o README.md é hoje a maior fonte de dívida arquitetural deste projeto, e nenhuma linha de código precisa mudar para resolvê-la.

A ação 6 não move nota — os dois mapas concordam hoje, osso por osso, e eu medi. Ela está na lista porque a régua pede preferência explícita por quem constrói gate em vez de escrever regra, e porque o que ela previne é silencioso: quando os mapas divergirem, o sintoma será um corpo com os braços dobrados ao contrário, que parece defeito de limite articular e custa dias.

A ação 5 é a mais cara e a que move mais: linguagem ubíqua é o único critério em 1 que tem conserto mecânico. Ela vale a pena ser feita junto com um gate, não sozinha — unificar os nomes sem nada que recuse o nome errado é o padrão que a régua documenta como o que não pega.

O que ficou de fora de propósito. Renomear trabalho/_corpo/ (é cache; a ação certa é movê-lo para fora do repo na próxima mexida em entrega/acervo.mjs, não uma ação própria); trocar o service de porta/rotas.mjs:54 (é uma palavra, cabe em qualquer uma das ações acima); e qualquer coisa sobre as seis pastas do fluxo aposentado, porque fila/APOSENTADO.md já declara a condição de saída e antecipá-la quebraria bancada em uso.


7. O que eu não consegui avaliar