A varredura estava em /private/tmp — 242 KB de trabalho medido que sumiria no próximo restart. Agora é `docs/audits/2026-08-14-afirmacoes-de-estado.md`, com o COMANDO de cada achado preservado. É o comando que faz o documento valer: quem for tratar um achado mede de novo em vez de confiar na linha. O relatório envelhece exatamente como aquilo que ele critica, e diz isso no topo. Junto, a evidência do alinhamento do canal `stable` (`2026-08-14-alinhamento-stable-v1.3.0.md`): os três pacotes tinham `stable` e `1.3.0` em digests diferentes, e agora batem. Medido ANONIMAMENTE depois, com token de pull público — escrita que só se confirma pela sessão que a fez não está confirmada. `latest` e `main` conferidos como controle: intactos. ## A triagem é por TIPO de documento, não por gravidade Foi a chave que faltava, e ela inverte o que eu faria sozinha: gravidade alta num documento-retrato **não** se conserta. **RETRATO** (`current-state.md`, `harness-audit.md`) — carimbados, não corrigidos. Os dois já traziam `audited_against: 789dfa6` no front-matter, e ninguém lê front-matter: o corpo falava no presente. O carimbo agora é a primeira coisa visível, com a distância medida — **1.014 commits e 71 migrations** entre o commit auditado e hoje — e declara que nada ali é mantido. Documento honestamente datado nunca mente; documento atualizado uma vez volta a mentir na semana seguinte, e pior, porque a atualização recente faz confiar mais. **AUTORIDADE** — corrigidos, e onde deu, a afirmação virou COMANDO: - os três READMEs diziam "**Quatro checks são obrigatórios**". São cinco. Em vez de trocar o número, entrou o `gh api … --jq '.required_status_checks.contexts'` com a saída do dia — e a admissão de que a linha já disse "quatro" e "cinco"; - os três READMEs mandavam ter o Google Authenticator à mão porque "o primeiro login de admin exige MFA". **Não exige** — o `bootstrap-owner.ts` grava `mfa_required: false` explícito. Um comprador espera uma tela que não vem; - os três diziam que o comando local era "a lista **completa** dos gates obrigatórios". Não é: `e2e` e `imagens-ok` só rodam no CI. Verde na sua máquina não é verde no merge; - `AGENTS.md` afirmava que **6 vars de `lib/env.ts` faltam no `.env.example`, incluindo 3 secrets**. Medido: das 45 chaves, a única ausente é `NODE_ENV`, e os três secrets nomeados estão todos lá. A regra do DoD continua; a dívida caiu; - `AGENTS.md` também dizia que login/signup/convite estavam sem rate limit. O `lib/auth/rate-limit.ts` cobre os quatro, por IP e por identificador hasheado. Crons e MCP seguem sem, e isso ficou escrito; - `AGENTS.md` prometia um "DoD de 15 itens" — agora são 16, e a linha virou o `grep` que conta, em vez de um número que envelhece de novo no próximo item. **PLANEJAMENTO** (`docs/stories/`, epics) — intocado. É onde vivem 385 dos ponteiros mortos do repo, e registro histórico pode apontar para o que nunca existiu. O gate já exclui essa pasta de propósito. ## O processo — duas linhas, não um sprint 1. `CONTRIBUTING.md`: quem toca um doc de autoridade corrige as afirmações **daquele** doc. Não sai caçando nos outros — a dívida decai sozinha se ninguém a alimentar. 2. `CLAUDE.md`, DoD item 16: se o PR muda comportamento, procurar a afirmação de estado sobre esse comportamento. Só sobre o que mudou. E onde puder virar comando, trocar em vez de corrigir. ## Um erro de instrumento, no meio disto O script com que filtrei os achados "que passam de afirmação envelhecida" imprimia sempre a MESMA citação — variável de loop vazando para o loop seguinte. As saídas medidas estavam certas, as citações não. Reescrito e refeito: 25 achados, não os 43 que a primeira passada listou. Um instrumento quebrado não devolve erro; devolve uma lista plausível. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RKm2XcTcfgi1vdMcDYSRWa
3.2 KiB
Alinhamento do canal stable da v1.3.0 — evidência
Data: 2026-08-14 · Operação: re-aponte da tag stable para o manifest da 1.3.0,
nos três pacotes. Sem rebuild — o mesmo índice OCI, sob outra tag.
Por que foi preciso
O workflow reagia a push: tags e a release: published. gh release create faz as
duas coisas, então o mesmo commit foi construído duas vezes (19:53 e 19:58 de 2026-08-13).
O segundo run moveu 1.3.0 e 1.3 para o build novo e não moveu stable, que ficou no
build anterior. revision e version eram idênticos nos seis manifests; só o created
diferia. Gatilho removido no PR #251, com guarda em
tests/unit/packaging-artefato-do-cliente.test.ts.
Como foi feito
O daemon do Docker estava parado, então em vez de docker buildx imagetools create a
operação foi feita pela API do registry — que é o que o imagetools faz por baixo: GET
do índice de 1.3.0 e PUT do mesmo corpo sob a tag stable, com o mesmo
Content-Type: application/vnd.oci.image.index.v1+json. Blob nenhum foi copiado: o índice
referencia os manifests filhos por digest, e eles já estavam no mesmo repositório.
Os três PUT responderam HTTP 201.
Antes e depois
A medição do "depois" foi feita com token anônimo de pull, não com a credencial que escreveu — uma escrita que só se confirma pela própria sessão que a fez não está confirmada.
| pacote | tag | antes | depois | |
|---|---|---|---|---|
deskcommcrm |
1.3.0 |
fc10b029e326 |
fc10b029e326 |
alinhado ✓ |
deskcommcrm |
1.3 |
fc10b029e326 |
fc10b029e326 |
alinhado ✓ |
deskcommcrm |
stable |
c4bc70b606c8 |
fc10b029e326 |
alinhado ✓ (alterado) |
deskcommcrm |
latest |
2f90346bf86d |
2f90346bf86d |
controle — não podia mudar ✓ |
deskcommcrm |
main |
2f90346bf86d |
2f90346bf86d |
controle — não podia mudar ✓ |
deskcomm-worker |
1.3.0 |
81e5af567cc8 |
81e5af567cc8 |
alinhado ✓ |
deskcomm-worker |
1.3 |
81e5af567cc8 |
81e5af567cc8 |
alinhado ✓ |
deskcomm-worker |
stable |
3fe292cad2bd |
81e5af567cc8 |
alinhado ✓ (alterado) |
deskcomm-worker |
latest |
6f7c03a5b96c |
6f7c03a5b96c |
controle — não podia mudar ✓ |
deskcomm-worker |
main |
6f7c03a5b96c |
6f7c03a5b96c |
controle — não podia mudar ✓ |
deskcomm-scheduler |
1.3.0 |
4396263ba807 |
4396263ba807 |
alinhado ✓ |
deskcomm-scheduler |
1.3 |
4396263ba807 |
4396263ba807 |
alinhado ✓ |
deskcomm-scheduler |
stable |
a0d5c3ad2296 |
4396263ba807 |
alinhado ✓ (alterado) |
deskcomm-scheduler |
latest |
c6be866e2b26 |
c6be866e2b26 |
controle — não podia mudar ✓ |
deskcomm-scheduler |
main |
c6be866e2b26 |
c6be866e2b26 |
controle — não podia mudar ✓ |
Confira você mesmo
for p in deskcommcrm deskcomm-worker deskcomm-scheduler; do
for t in 1.3.0 1.3 stable; do
echo -n "$p:$t "
docker buildx imagetools inspect ghcr.io/melgarafael/$p:$t | awk '/^Digest:/{print $2}'
done; done
Os três de cada pacote têm que bater. Se não baterem, alguma coisa republicou depois do push da tag — e isso é o invariante 3 da doutrina quebrado dentro de casa.