video-mocap — avaliação de arquitetura
Varredura de 01/10/2026, pela régua em
REGUA.md. Inclui oalmost-humanoidcomo 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-mocapcomo calibrador — ele aparece como exemplo do que é bom (a esteira, o estado em disco, o teste de fronteira) e do que é ruim (a gavetax/, 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ério | Nota | Evidência |
|---|---|---|---|
| 1 | Metáfora central | 2 | esteira/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 |
| 2 | Fisicalidade da metáfora | 3 | medidor 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 |
| 3 | Alcance da metáfora na estrutura | 2 | degrau 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' |
| 4 | Linguagem ubíqua | 1 | trê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 |
| 5 | Modularidade | 2 | o 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 |
| 6 | Isolamento | 2 | gate 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) |
| 7 | Coesão | 2 | 23 das 30 pastas passam no teste da frase; falham 7, e x/ não está nomeada (x/PROVAS.md:1 fala de outro assunto) |
| 8 | Objetos a serviço da metáfora | 3 | zero 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 |
| 9 | Desenhabilidade | 2 | o 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) |
| 10 | Ausência de contradições internas | 1 | 9 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:
- arquivos com nome de abstração (
manager|service|handler|util|helper|processor|controller|factory|provider|adapter|wrapper|engine): 0 em código do projeto. A palavrapipelineaparece 34 vezes, só em comentário e doc. - identificadores (
class|function|const|let+ sufixo de abstração): 0.
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".
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:
| pasta | a frase que ela exige | evidência |
|---|---|---|
porta/ | recebe o vídeo, e mostra a fila, e entrega o resultado, e avisa quando fica pronto — quatro assuntos | porta/PORTA.md:13-14 |
entrega/ | escreve o .glb e o vídeo lado a lado e a página do celular — três produtos | entrega/README.md:3-5 |
limpeza/ | conserta tremor e salto e pé no chão, em 16 arquivos | limpeza/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ão | teto/ancorar.py:3 |
x/ | gaveta, e não nomeada: o .md dela fala de outro assunto | x/PROVAS.md:1 |
ia/ | degraus de leitura e montagem de página, 41 arquivos | ia/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:
| onde | valores | partes |
|---|---|---|
limpeza/limpar.mjs:702 → laudo.json | BOM · REPARADO · LACUNA | corpo, mao_e, mao_d |
juizo/veredito.mjs:33 → juiz.json | bom · suspeito · ruim · ausente | corpo, maoEsq, maoDir, rosto |
captura/alvo.mjs:215,226,235 | INEXISTENTE · 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ção | Horas | Critério que move | De → 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 aposentado | 1 h | 1 — Metáfora central; 10 — Contradições | 2 → 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 antigo | 1 h | 10 — Contradições; 4 — Linguagem ubíqua | 1 → 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 verde | 1 h | 10 — Contradições | 1 → 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(…) à regex | 3 h | 6 — Isolamento | 2 → 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 escala | 4 h | 4 — Linguagem ubíqua | 1 → 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 destino | 3 h | 4 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 terminou | 2 h | 7 — Coesão; 9 — Desenhabilidade | 2 → 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
- A esteira rodando de ponta a ponta.
docs/ESTADO-2026-09-30.mdregistra que a leitura do vídeo do founder está parada em 75 de 449 quadros, porque a única máquina com o motor é o notebook dele, fora do ar. Avaliei o contrato entre as etapas e as provas em texto, não o comportamento com dado real atravessando as sete. - As provas que exigem GPU, modelo ou quadro de vídeo. A suíte do projeto é lógica pura por desenho (
test/run.mjs:5-12), e as provas caras rodam porheavy run --noturna. Não as rodei: este tópico é de leitura, e a bateria pesada não é pré-condição de nada aqui. - O acervo (
asset-pipeline-dashboard) de dentro. Entrou neste relatório só pela fronteira — os nomes de osso, a colunapapel, a rota de peças. A arquitetura dele é assunto de outra varredura. - Se os dois mapas de osso vão continuar concordando. Medi que concordam hoje, em 01/10. Não há mecanismo que me permita afirmar nada sobre amanhã, e é exatamente por isso que a ação 2 existe.