Changelog¶
Todas as mudanças relevantes deste projeto são documentadas aqui.
O formato segue o Keep a Changelog e o projeto adere ao SemVer — ver versionamento.
Unreleased¶
0.30.0 - 2026-08-04¶
Adicionado¶
- Decisão 0019 — bibliotecas compartilhadas da casa. Infra idêntica cross-app (28 classes
duplicadas na auditoria de 2026-08-03) passa a viver num único repo
xadm-commons, cada lib = módulo Gradle com SemVer próprio, publicada como artefato Maven no Forgejo Packages; o app consome por versão (implementation("br.com.xadm:xadm-<lib>:X.Y.Z")+ registro Forgejo por<VAR>/env). Base de pacote/groupbr.com.xadm(int-sascar migra debiz.xadm). Rejeitados repo-por-lib e git submodule (versão=SHA). Fim do copy-paste de infra; reduz o risco de drift do IdP Firebase compartilhado. - Decisão 0020 — contrato app↔app. Estende a 0012 (rota/método) fechando o corpo: quem
recebe dita o contrato — o receptor publica OpenAPI (
micronaut-openapi), o consumidor gera@Client+DTOs (openapi-generator) no build; versionamento com compat (janela de deprecação); envelope M2M (Bearer<APP>_API_TOKENpor callee, RFC-7807+code, 1 token/instância); status por caso (200-sempre onde PowerSync/fila exige, status real no par novo sem fila); request-id/MDC propagado entre hops; contract test consumidor×spec. Riscos §1.2 (capacidade doopenapi-generator, janela de deprecação) declarados para a Fase 3.
Alterado¶
- Engenharia: padrões de plataforma da leva 0019/0020.
java-micronaut.md— HTTP app↔app dentro de Micronaut é@Client+@Retryable(OkHttp só em plain-Java), resolvendo a contradição com o transversal; camadas de lib embr.com.xadm.comum.*(pt-BR); nova seção registry de handler por tabela (XadmTableHandler<E>) como a forma anti-god-node de modelar o espelho X-Adm (refactor da Fase 4); o "gap declarado" de request-id/MDC vira norma (filtro noxadm-comum-web).integracao.md— nova tabela Arestas concretas (call-graph) (caller→callee : transporte : endpoint : auth).stack.mdepowersync.mdalinhados ao 0020 (OkHttp×@Client; o callback sempre-200 é o caso que exige 200 no status-por-caso). Constituição 0.27.5 (PATCH — sem artefato rastreado alterado; ADRs e páginas de engenharia são conteúdo de site, não templates do manifesto). /xadm-release: a lista de venenos da skill passa a nomear redirect (2>&1,> arquivo) ao lado do pipe — comando com redirect é composto e não casa allow-list por ferramenta. O gap era só a skill rastreada: a 0.27.3 documentou o sonde-bare emagentes.md/ferramentas.md(páginas de site, que não vão pro repo de app), mas o agente no repo de app só enxerga a SKILL, onde o veneno "pipe" não mencionava o2>&1.java -versiontenta o reflexo de anexar2>&1(escreve versão no stderr) — o bare já casajava *e o harness captura o stderr. Espelhado na cópia local.claude/skills/xadm-release/SKILL.md. Constituição 0.27.4 (PATCH —templates/xadm-release-skill.mdre-carimbado).
0.29.7 - 2026-07-31¶
Adicionado¶
/xadm-release: pré-flight passa a detectar teste OS-desabilitado e avisar sobre CI-verde.@DisabledOnOs(OS.WINDOWS)/@EnabledOnOs(OS.LINUX)é pulado nochecklocal (dev = Windows), o gate fica verde cego e a divergência só aparece na CI Linux, pós-tag (caso real:v0.0.5tagueada, CI vermelha depois). Agora o pré-flight Java procura essas anotações e, se acha, declara no relatório que N testes não rodaram (degradado, não silêncio) + recomenda rodar./gradlew checkno containerci-java:<v>(paridade Linux). O gate CI-verde é aviso, não bloqueio (o Coolify auto-deploya no push, item 62 — gatear o deploy é futuro): o relatório lembra de confirmar a run verde. Allowlist ganhoudocker run *. Doutrina nova emci-testes.md(§«Teste OS-desabilitado é gate cego no pré-flight») + ponteiro emjava.md§Testes. Constituição 0.27.2 (PATCH —templates/xadm-release-skill.mdre-carimbado).
Alterado¶
/xadm-release: allowlist do.claude/settings.jsonpassa a ser por ferramenta (git *,node *,npm *,python */python3 */py *,mkdocs *,docker *,rtk *), espelhado nos namespacesBash(...)ePowerShell(...), no lugar do allow-list por prefixo exato de argumento. O prefixo exato era quebradiço — cada variação de forma (interpretadorpython/py,npm installvsnpm i, flag antes do subcomando,npmde dependência dolint-mermaidausente) voltava a pedir prompt e travava o release no meio. Wildcard por ferramenta mantém o escopo (só as ferramentas do release) e elimina a fragilidade; ocurlsegue escopado de propósito. A garantia "só commita no release" continua sendo a REGRA Nº 2 (conduta), não o prompt. Venenos de comando composto (pipe,$(...), multi-linha) seguem valendo:ferramentas.md§Higiene eagentes.md§Loop de verificação ganham o mesmo padrão (sonde toolchain com comando bare, um por chamada —java -version, nãojava -version 2>&1 | head). Constituição 0.27.3 (PATCH —templates/xadm-release-skill.mdre-carimbado).
0.29.6 - 2026-07-31¶
Adicionado¶
/xadm-release: gate de container para stack Docker Compose (serviço self-hosted, ex. PowerSync) no pré-flight.docker buildprova que a imagem compila, não que a stack sobe — bootstrap (load de sync rules, migração) e healthcheck só rodam noup, e o primeiro a subir a stack de verdade é o Coolify em produção. Gate:docker compose -p <slug>-preflight up -d --wait(volume novo, healthchecks que a constituição §5 já obriga) +down -v; substitui odocker buildse a imagem é pull (sem Dockerfile), soma se o repo builda. Opcional e degradável (sem Docker / falta.env/ porta em uso = ambiente, não bug — declara no relatório). Allowlist ganhoudocker compose *nos dois namespaces. Ponteiro empowersync.md§Deploy. Constituição 0.27.1 (PATCH —templates/xadm-release-skill.mdre-carimbado).- Kit de UI: dois slots opcionais no navbar (
layout.html) —${appModo}(pill de ambiente à direita, renderiza quando presente) e${appVersao}(versão discreta) — nos dois fragments (navbarenavbarComMenu), com estilo nocustom-theme.css. Mata o hand-roll que já produzira drift (um app forkou olayout.html, outro pôs no conteúdo/navMenu). Receita emjava-micronaut.md§UI com oViewModelProcessorde referência que popula os dois em toda view:appModosó quando o ambiente ≠ produção (o layout não compara string),appVersaoda config; detecção de prod e versão ficam app-specific. Constituição 0.27.0 (MINOR — funcionalidade nova, compatível;layout.htmlecustom-theme.cssre-carimbados). - Armadilhas de render Thymeleaf em
java-micronaut.md§Armadilhas: Thymeleaf standalone não tem os objetos implícitos de web (param/session/request, são do Thymeleaf-Spring) — controller lê do request e passa ao modelo; link com variável de path é@{/x/{id}(id=${..})}, não concatenação de String. Cura da família: bullet em §Testes prescrevendo o teste@Clientque fazGETe renderiza de verdade (o./gradlew checknão renderiza template) + ponteiro emci-testes.md§E2E (view server-render é fronteira de contrato).
Alterado¶
- Publicidade de view sob
micronaut-security:@Secured(SecurityRule.IS_ANONYMOUS)na rota vira o idioma primário (rota-exata por construção, sem allowlist paralela pra driftar);isPublicView()naSecurityRulecustom fica para allowlist programática/dinâmica; segue proibidointercept-url-mapgreedy. Rota de view sem decisão explícita = 401. Atualizado emjava-micronaut.md§UI,seguranca.md§Authn/authz e no checklist do revisor.
0.29.5 - 2026-07-30¶
Adicionado¶
- Armadilha Gradle 9.5 + shadow +
application: jar base e shadowJar com o mesmoapp.jarquebramstartScripts/build. Com o pluginapplication,startScripts/distZipconsomem o output dojar; dividir o nomeapp.jarentrejarbase eshadowJarfaz o Gradle 9.5 acusar "uses this output of task ':shadowJar' without declaring … dependency"../gradlew checké imune e o Coolify usa o shadowJar direto (produção não quebra) — morde só o dev que roda./gradlew build. Cura:app.jarsó no shadowJar (dê nome/archiveClassifierdistinto ao jar base), oustartScripts { dependsOn(shadowJar) }. Bullet emjava-micronaut.md§Armadilhas + nota cruzada no §Deploy; ponto cego declarado (sem gate — nada no pipeline rodabuild). Página dev não rastreada → sem bump.
Corrigido¶
- Guarda de placeholder aninhado (
templates/ci.yml) reprovava comentário — falso-positivo. A regex\$\{[^}]*\$\{rodava em toda linha doapplication.yaml/.properties, inclusive comentário: um app que documenta a armadilha (# não use ${A:${B}}, full-line ou inline) fazia o CI falhar com::error::— o gate contra a armadilha proibia falar dela. Agora o step tira o comentário antes da regex (# no início ou pós-espaço) — o Micronaut não resolve comentário, então ignorá-lo é semanticamente correto;#literal em value (url http://a#b, propertiesk=a#b) fica intacto, e placeholder aninhado real (mesmo com comentário na cauda) segue reprovando. Constituição PATCH 0.26.6→0.26.7 (re-carimbo detemplates/ci.yml).
0.29.4 - 2026-07-30¶
Adicionado¶
- Norma "servidor local de verificação pega porta efêmera" (loop de verificação): subir servidor
para conferir — app em modo debug, E2E local, preview — não fixa porta (
8080/8000); pede porta efêmera e lê a URL que o processo imprime. Porta chutada colide com processo vivo ou zumbi e o sintoma engana (bind falha, ou responde outro servidor com build velho — episódio domkdocs servena 8000). Norma emagentes.md(§Loop de verificação) + ponteiro emci-testes.md§E2E; mecânica por stack: Micronaut (MICRONAUT_SERVER_PORT=-1, lerServer Running:;EmbeddedServer.getURI()no E2E) emjava-micronaut.md, Flutter web (flutter runjá é random + imprime a URL; antipadrão é fixar--web-port) emflutter.md. Páginas dev não rastreadas → sem bump.
Alterado¶
- Release da
/xadm-releaseroda sem prompt de ponta a ponta — tag de 1 linha + allowlist Python por SO: a tag anotada era multilinha (string com\nnão casa regra de prefixo) e pedia autorização em todo release — agora é resumo de uma linha (git tag -a v.. -m "v.. — resumo", o detalhe fica no CHANGELOG), casagit tag *, zero prompt. E o allowlist passou a cobrir o interpretador Python por SO (python3no Linux,python/pyno Windows) nos dois namespaces (Bash(...)/PowerShell(...)) — sem isso os gates do pré-flight pediam prompt um a um na máquina do dev. Vale para todos os apps: re-derivam a/xadm-releasevia/xadm-docse alargam o próprio allowlist. Constituição PATCH 0.26.5→0.26.6 (re-carimbo detemplates/xadm-release-skill.md).
0.29.3 - 2026-07-30¶
Adicionado¶
- Seed de teste de endpoint Micronaut:
@BeforeEach/@Sql, nunca no corpo do@Test+ HTTP (loop §6, feedback de app):@MicronautTestdefault (transactional=true) faz rollback do corpo do teste, e o servidor embutido atende em outra conexão → não vê o não-commitado; o defaultSEPARATE_TRANSACTIONScommita o@BeforeEach, por isso seed lá fica visível e seed no corpo some (teste verde medindo vazio). Regra + mecânica em java-micronaut §Testes e fixtures, ponteiro em ci-testes §E2E.transactional=falsenão é a cura reflexa (quebra JDBC cru do@BeforeEach). Ponto cego declarado: nenhum gate estático pega. Páginas dev não rastreadas → sem bump.
0.29.2 - 2026-07-30¶
Corrigido¶
- Placeholder aninhado no
application.yamldo Micronaut NÃO funciona — receita da 0.29.1 corrigida (loop §6, bug de produção): o item 101 documentou o fallback de migração de env inter-app como${NOVO:${ANTIGO:}}"o mesmo doSENTRY_DSN" — mas oSENTRY_DSNmora nologback.xml(motor que aninha, operador:-) e o Micronaut é OUTRO: oDefaultPropertyPlaceholderResolvercasa o primeiro}, não o balanceado, então${A:${B}}resolve pra lixo (token/URL inválido) sem erro de build → quebrou apps em produção. Correção: a receita de migração de env agora prescreve rename atômico ou resolve-in-code (duas props single-level), nunca cascata no yaml; armadilha nomeada em java-micronaut §Armadilhas (com a distinção logback×Micronaut); guarda nova notemplates/ci.yml(grep de${…${só em app Micronaut — Spring aninha certo) pega reincidência no CI do próprio app. Constituição PATCH 0.26.4→0.26.5 (re-carimbo detemplates/ci.yml).
0.29.1 - 2026-07-28¶
Adicionado¶
- Convenção — ENV de auth/URL inter-app nomeada pelo DESTINO (loop §6): um Bearer/base-URL entre
apps mora em
<APP>_URL+<APP>_API_TOKEN("como chamar o<APP>"); cada app valida o próprio<SELF>_API_TOKEN, cada chamador seta<DESTINO>_*. Token tem nome global com mesmo valor no callee (valida) e nos callers (mandam) → mapa de segredo coerente e sem colisão num app que é chamador e chamado (oAPI_BEARER_TOKENhomônimo com valor diferente por servidor foi o bug N-hop da integração Thoms). Um token por callee (trade-off declarado: revogar 1 caller rotaciona B pra todos). Migração de env sem quebrar produção por rename atômico ou resolve-in-code.
Regra no piso (seguranca.md §Segredos), receita de config em java-micronaut
§Específico, ponteiro em integracao.md. Escopo: só HTTP inter-app (+ terceiros PARCEIRO_*); DB/
Firebase/observabilidade seguem como estão. Páginas dev — sem bump.
- Java/Micronaut — 3 refinamentos vindos de feedback de app (loop §6): (a) convenção de rota
/api/<origem>/<recurso> para callback/poke de um app a outro (<origem> = app chamador; integrador
é o caso comum → /api/integrador/produto): /api/** é Bearer (ROLE_API), então o prefixo dá
auth uniforme e contrato de rota previsível (§Específico + ponteiro em integracao.md §Transporte);
(b) view pública se libera na SecurityRule da própria
view (isPublicView(), rota exata), nunca por intercept-url-map greedy — o
ConfigurationInterceptUrlMapRule roda em ordem -100 e ganha da SecurityRule custom, então
um pattern /*//** com ALLOWED vaza rota irmã (ex. /admin) sem erro nem sinal (refina o piso em
seguranca.md §Authn/authz + checklist do revisor; receita em java-micronaut §UI); (c)
read-model de tabela de terceiro marca @Nullable o campo que a fonte pode deixar null — sem
isso o Micronaut Data estoura "non-null constructor argument" e derruba o job inteiro (1 registro
anômalo mata o sweep); trate ausência como anomalia (Sentry/WARN), não falha fatal (§Banco).
Páginas dev, não rastreadas no manifesto → sem bump.
- Constituição §6 — ponteiro para a higiene do .claude/settings.json (0.26.4) — um app
perguntou se a constituição recomenda allow-list de permissões e concluiu "não" por olhar só a
constituição-arquivo; a regra existe, mas vive em engenharia/ferramentas.md + app-novo.md
(versionar o settings.json com padrões LARGOS dos comandos comuns — Bash(git *),
Bash(mkdocs *), Bash(python3 scripts/*)… —, pessoal em settings.local.json gitignored;
grant hiper-específico solta a tag da release via --amend). §6 ganhou um bullet-ponteiro (com a
âncora da regra) para fechar a fresta de descoberta de quem só lê a constituição. Bump text-only.
0.29.0 - 2026-07-28¶
Adicionado¶
- Gradle assado na imagem-fábrica
ci-java(constituição 0.26.2) — feedback §6 (bi-transporte-xls v2.1.3): em cache frio o./gradlewbaixava a dist do Gradle de host externo e umUnknownHostExceptiontransiente pintava o gate de vermelho aleatório — a exceção acidental ao "zero download por run" (decisão 0003). Agora aci-javapré-aquece a dist do wrapper (versão escalargradlenamatriz-baseline.json, casa-inteira) sobGRADLE_USER_HOME=/opt/gradle, no caminho-hash canônico; oci.ymlpassa a cachear só deps. Egress do runner medido aberto (Maven Central, plugins, dist alcançam) → sem 2º furo. Adendo na decisão 0003: pareamento comgradle-wrapper.properties(versão E variante-bin), premissadistributionBase, ordem de bump anti-deadlock. Validado no runner (cold-cache não baixa; o smoke da fábrica assere a dist assada em/opt/gradle/wrapper/dists/); os 8 apps Java já pinam a URL canônica. - Manifesto EOL-agnóstico + guarda pré-commit da
/xadm-release(constituição 0.26.3) — ogera-manifestohasheava bytes crus (read_bytes), então gerá-lo no Windows (autocrlf/CRLF) divergia do Linux (LF) e deixou um drift subir silencioso no 0.26.1 (a entrada doxadm-release-skill.mdnão batia nenhum commit; o CI não-gating do item 62 só avisa). Agorahash_conteudonormaliza\r\n→\nantes de hashear (rastreia conteúdo, não bytes; binário preservado), comtesta-gera-manifesto.pynovo no CI. E o §8 da/xadm-releaserodagera-manifesto --checkcomo último passo pré-commit, fechando a race carimba→edita→commita. - Norma anti-deadlock no batch upsert (java-micronaut §Banco) — feedback §6 de app
(Onpetro bi-comercial-xls v1.4.5, deadlock
40P01real em produção): o diff-aware (ON CONFLICT DO UPDATE … WHERE … IS DISTINCT FROM) tira row lock na arbitragem do conflito, antes de avaliar oWHERE— linha "inalterada" trava igual, e duas transações concorrentes com dimensões sobrepostas em ordens diferentes deadlockam. Bullet novo: todo batch upsert ordena as linhas pela chave natural antes de executar (executeBatch→sortedcomnullsFirst;COPY + TEMP TABLE→ORDER BYnoINSERT … SELECT), com a nuance multi-tabela e o teste proporcional (capturador de batch afirmando a ordem). Segundo feedback (bi-transporte-xls v2.1.3, mesmo risco corrigido preventivamente) completou o bullet: transação de mescla multi-fase (upsert +DELETEseletivo) serializa a fase de banco compg_advisory_xact_lock(<chave fixa do app>)— oDELETEtrava em ordem de scan, queORDER BYnão controla — e a declaração de que o deadlock em si não é testável deterministicamente: testa-se a pré-condição estrutural. Página não rastreada — sem obrigação nova. - Constituição 0.26.0→0.26.1 — allowlist Windows na
/xadm-releaseegitattributes-java(feedback §6 de app: release rodado em Windows nativo). (a) O bloco "Permissões — release sem prompt" do templatexadm-release-skill.mdsó tinha regrasBash(...); no Windows o harness usa a ferramenta PowerShell, cujo namespace de regra é próprio (PowerShell(...)) — nenhuma regra Bash casa, e todos os gates promptavam na mão. O bloco Bash também não cobria os gates (só git + echo) — os gates promptavam no Linux idem. Agora os dois blocos são simétricos: git + gates de código/container/docs por stack ("mantenha só as da sua stack";curlescopado emdocs.xadm.biz). Cortados da proposta original osGet-Content/Select-String/etc. — o template já manda inspecionar arquivo pela ferramentaRead, nunca shell. Mais dois venenos Windows na lista: prefixo de env inline ($env:X='...'; cmdé composto — cura estrutural:"env"nosettings.local.json) e sufixo; echo "EXIT=$LASTEXITCODE"(idem; o harness já reporta exit code). Segundo feedback (bi-transporte-xls, ~15 prompts num release Windows) confirmou o diagnóstico e somou a regrapython -m mkdocs build *(Windows raramente temmkdocsno PATH), o parcurl … http://localhost:8000/*pro preview local (o outro gerador recorrente de prompt) e a nota "URL antes do-o" no download de validadores; a receitagit archive … | docker build -proposta lá foi rejeitada com o porquê no template (pipe é veneno de prompt, PowerShell 5.1 corrompe stream binário no pipe, e buildaria o HEAD em vez da árvore em curso) — a cura canônica do CRLF é o.gitattributes. (b) Template novo rastreado e opcionaltemplates/gitattributes-java(gradlew text eol=lf): checkout Windows comautocrlfdeixa ogradlewcom CRLF, odocker buildCOPYa a árvore como está e o/bin/shdo Alpine morre com./gradlew: not found— o--chmod=0755do Dockerfile cura o bit de execução, não o fim de linha. Referenciado em constituição §3, templates.md (tabela + seção Container), app-novo.md §7, java-micronaut §Deploy, gate de container do release e mapeado pela/xadm-docs(gitattributes-java→.gitattributes). Bump PATCH; 4 rastreados re-carimbados (xadm-release-skill.md,xadm-docs-skill.md,dockerfile-java,gitattributes-java).
0.28.0 - 2026-07-23¶
Adicionado¶
-
Constituição 0.25.1→0.26.0 — plataforma de integração ganha topologia e fluxos em SVG autoral, o livro ganha capa obrigatória, e a taxonomia um 5º papel: app compartilhado. Pedido interno: a diretoria precisa ver a plataforma em uma tela (X-Adm no cliente, nuvem, terceiros). A
documentacao/integracao.mdera só prosa — sem figura, o chefe tinha que ler taxonomia + tipos + fronteiras para montar a topologia na cabeça. Adicionado no topo da página: §Topologia — depois de rodadas contra o layout automático (Dagre inverte ranks por ciclo/aresta;block-betadá grid mas sem rowspan nem título de composite), a figura final é SVG autoral (docs/assets/topologia-integracao.svg— base visual desenhada pelo Gustavo, paleta re-tokenizada para X-Adm royal#064490+ tipografia Inter, decisão 2026-07-22), embutida via--8<--, com Mermaid-base colapsado logo abaixo (??? info—pymdownx.detailshabilitado nomkdocs.yml) como fonte semântica lintada: mudou a topologia, atualiza o base primeiro e espelha no SVG. Norma nova: bullet "Figura autoral (SVG) — a exceção de capa" na constituição §5 + receita completa em templates.md §"Figura autoral em SVG" (as armadilhas reais: linha em branco ou<svg>sem wrapper<div>fatiam o SVG em<p>— python-markdown não trata<svg>como bloco;<style>sem prefixo vaza pro site;<img>não herda a webfont, daí--8<--), com o ponto cego declarado: nenhum gate valida o SVG em si — quem é lintado é o Mermaid-base. CSS auxiliar emdocs/stylesheets/xadm.css:.md-typeset .mermaidcomoverflow-x: auto(vale para os demais diagramas Mermaid do site). Rótulos da figura (por pedido interno): Hub = "Plataforma de Integração" +int.<cliente>.xadm.biz+ps.<cliente>.xadm.biz; banco = "PostgreSQL Cliente ¹" com nota de rodapé "Um banco de dados por cliente"; apps específicos = "Apps Específicas" (agrupapiedeexcel); app compartilhado = "Apps Compartilhados". Papel novo — App compartilhado: 1 instância multi-tenant que nasce quando o parceiro é global (mesmo endpoint para N clientes, cada um com sua credencial); não escreve no barramento (mantém §Fronteiras "um dono por tabela" intacta), conversa com o hub, que grava. Combina tipos ③+④ quando o parceiro é bidirecional. Motivo concreto:sascar.xadm.biz— o hub envia MDF-es abertos (chave/placa) ao app compartilhado, que faz polling na Sascar do cliente com credenciais próprias; quando o motorista chega ao destino, devolveencerradoao hub, que atualiza o status; o cliente Java lê via PowerSync e importa no ERP. Reator removido da taxonomia — reservado para uso futuro. O único caso concreto (thoms → e-commerce) foi confirmado como REST puro ao ler a UI do app rodando (POST /sync/erpemwebstorm-ecom.thoms.xadm.biz, sem PowerSync no servidor). A definição "não recebe de fora, consome o banco via PowerSync, empurra para fora" contradizia o caso real; thoms virou app específico (ecommerce.<cliente>) que recebe do hub via REST e fazPOSTno parceiro (WebStorm). O papel Reator fica reservado para casos futuros de notificação (email, push, alertas Telegram) — quando aparecer, volta à taxonomia. Aplicado em: figura (zonas Servidor X-Adm Cliente com ERP X-Adm ↔ Integrador Cliente — as saídas partem do Integrador, label "push tempo real"/"write-back" — / Terceiros / Nuvem 2x2 / Usuários com mockups de navegador e celular; Sascar → Apps Compartilhados viapull · MDF-e, odômetroe Plataforma ↔ Compartilhados viaREST · baixa MDF-e, odômetro; PowerSync PG → Usuários e PG → Integrador; write-back dos Usuários por fora; sem badges numerados — os 4 tipos são numerados no texto, não na figura); §Taxonomia (linha Reator removida, App consumidor menciona Web/Mobile); §Os 4 tipos (item 4 reescrito; admonition "Reator — reservado para uso futuro"); §Fronteiras (regra de tabela de status separada agora fala em app específico); §Transporte (PowerSync serve consumidor + cliente Java; hub↔apps específicos é REST); tabela de prefixos (<app>_citaxls_*, thoms_envio); constituição §8 (Taxonomia sem reator; PowerSync bidirecional distingue consumidor de app específico REST; fronteira §7 sem reator; contrato sem "packaging de reator"); glossário (seção Reator removida);engenharia/powersync.md(2 lugares). Rejeitado replicarsascar.<cliente>(N deploys idênticos batendo na mesma API, isolamento sem benefício), rota no hub (reintroduz o erro (a) da §integracao.md), e app compartilhado escrevendo no barramento (dois donos à tabela-espelho — quebra §Fronteiras). Terminologia — rename da taxonomia: "vertical" → app específico; "adaptador compartilhado" → app compartilhado (feedback interno: a taxonomia da plataforma agora fala em apps por papel, não em jargões técnicos). Aplicado em integracao.md (§Taxonomia + §Os 4 tipos + §Fronteiras + §Transporte), constituição §8, glossário (2 seções + Owner-writes), decisão 0018 (título + corpo; slug preservado0018-adaptador-compartilhado.mdpara não quebrar links; nota de terminologia dentro do arquivo) e nav do mkdocs. Também trocado "shape" por "tipo de fluxo" na página e no §8 — "shape" era jargão a mais para a equipe. "Shape" segue em outros contextos da constituição (formato de resposta HTTP, shape de fixture), onde não colide. Trocado "pola a API" por "faz polling na API" — anglicismo técnico consagrado, "pola" era gíria. Removidobi-commonsda doc normativa (integracao.md, constituição §8, glossário, powersync.md): a biblioteca não foi implementada ainda, e a doc presumindo sua existência viola §1.6 (não inventar). Decisões 0007 e 0014 preservam a menção como registro histórico da intenção — o dia que a biblioteca existir, volta à norma. Adicionado: decisão 0018 + linha na tabela §Taxonomia + nota "combinação ③+④" em §Os 4 tipos; §8 da constituição incluiapp compartilhadona taxonomia (anti-drift §8). Detalhe operacional (auth por cliente, schema do banco de trabalho, contrato exato com o hub) fica na arquitetura-alvo do integrador (§1.9: concreto no repo dono). §Fluxos novo na integracao.md: 3 SVGs autorais verticais (um por fluxo, cima→baixo:fluxo-saida.svg,fluxo-entrada.svg,fluxo-ciclo-mdfe.svg, mesma UI da topologia; escolhidos contra a variante combinada horizontal, que perdia legibilidade no downscale da coluna — a vertical cabe inteira, fonte no px desenhado) — saída X-Adm→Usuários (rotas tempo real e batch XLSX), entrada Externo→X-Adm (PIED, com devolução de status) e o ciclo completo do MDF-e (Sascar) — cada um com a faixa COMO ACOMPANHAR (exceções de software vão automaticamente ao GlitchTip com notificação à equipe; exceções de operação geram e-mail à equipe do cliente). Capa obrigatória no livro (cap. 0): a constituição §2 passa a exigir que a Documentação Completa abra com figura de topologia + fluxos principais com "como acompanhar" (Mermaid por padrão, SVG autoral permitido via §5);templates/projeto-index.mdganha a seção "0. Capa" com o marcador HUMANO — projeto novo nasce com capa, app existente adota por migração oportunista (§1.6). Rename editorial: "hub" → "Plataforma de Integração" em toda a doc normativa (integracao.md com desambiguação plataforma-conjunto × Plataforma-serviço, constituição §1.9 e §8, glossário, powersync.md, decisão 0018 — decisões 0007/0014/0016 ficam, são histórico) e "empurra" → "envia" (registro). Bump MINOR — a capa é obrigação nova sobre o livro (o resto é permissão + esclarecimento + rename); 0 rastreados mudaram (projeto-index.mdé scaffold de uma vez, não rastreado — quem o cobra é a constituição §2, não o manifesto). -
engenharia/java-micronaut.md§Banco — bullet novo: chave-de-mudança single-writer via@DateUpdated. Feedback de app (§6). A doc já tinha o par multi-writer (trigger Postgres, entidade não mapeia — evita null-wipe) mas nada para o caso simples: app dono único da tabela onde@DateUpdateddo Micronaut Data resolve de graça (carimba a cada write, rejeita valor externo, serveORDER BY updated_ata consumidor externo). Bullet novo entre§Espelho fiele§multi-writerfecha a matriz "dono da escrita → onde vive o bump" (single → ORM mapeia; multi → trigger, entidade não mapeia). Sem bump — página não rastreada; mudança de conselho, não de contrato. -
/xadm-releasepré-flight — aviso soft do bloco 'Publicar Release' comentado. Feedback de app (§6). Otemplates/release.ymltraz o bloco de asset e opermissions: contents: writecomentados por default (OPT-IN "só app que distribui artefato"). App que copiava o template e distribuía artefato mas esquecia de descomentar →valida-release.pyverde, tag pushada, aba Releases vazia, jar sem asset — descoberto só quando o operador ia baixar. Irmão silencioso do item 95 (descomentar sem trocarcontainer:é barulhento — guarda + 403 — ; NÃO descomentar quando deveria era o cego). Adicionado bullet no pré-flight dotemplates/xadm-release-skill.md: se.forgejo/workflows/release.ymlexistir, lê pela ferramentaReade procura DOIS marcadores literais (# - name: Publicar Release no Forgejoe# contents: write); se algum aparecer comentado, avisa no relatório final (não bloqueia — app só-deploya/doc-only ignora legitimamente). Semrelease.yml→ skip. Rejeitada a alternativa "cobrar campodistribui_artefatonoapp.json" (bandeira nova a manter, sem gate para cobrar); o próprio release.yml carrega os marcadores do template quando foi copiado → detecção sem inferência, sem falso positivo.xadm-release-skill.mdre-carimbado; cópia do central (.claude/skills/xadm-release/SKILL.md) inalterada — o central não distribui artefato (site MkDocs, deploy por push).
0.27.2 - 2026-07-20¶
Alterado¶
- Constituição 0.25.0→0.25.1 — o
checa-rotas.pyconfere rota, não forma: a fronteira agora é princípio, não nota de rodapé. Feedback de app: publicar um arquivo-fato de contrato ao lado de um OpenAPI cujo schema mentia (required/enum/nullability≠ runtime) passou os dois gates — quem pegou foi o teste de fio, não a toolchain. O ponto cego já estava declarado ("o check não sabe nada sobre corpo — só rota e método"), mas como nota mecânica. Avaliada e recusada a extensão a um check de schema-drift prosa×spec: o spec gerado é oráculo confiável de rota (path/verbo saem fielmente das annotations) mas frágil de forma (não vê validação imperativa, default, serialização custom), então um gate prosa×spec passaria verde com ambos mentindo juntos (o teste tautológico do item 88 por outro caminho) ou acusaria a prosa correta quando ela acerta o runtime e o spec erra — falso conforto. O oráculo independente de forma é o runtime = teste de fio, que já é piso §6 (E2E na fronteira de contrato). Reforço em três lugares: §Contrato REST (o princípio "rota é checável contra o spec, forma não é"), a docstring docheca-rotas.py, e o padrão do arquivo-fato empublicar-docs.md(o autor que escreve schema em prosa "a partir do código" atesta a forma por fio, não por gate). Sem mudança de comportamento — esclarecimento do escopo já existente; ocheca-rotas.py(rastreado) foi re-carimbado.
Adicionado¶
-
Constituição 0.24.1→0.25.0 — o kit de UI ganha
app.css: CSS de componentes do app, sempre linkado. Ohead(title)dolayout.htmlpassa a linkar/css/app.cssdepois docustom-theme.css, e a/xadm-docsscaffolda o arquivo detemplates/app.cssna criação do app. Dois CSS, dois donos (§1.9): ocustom-theme.cssé a identidade da casa — rastreado, verbatim, não se edita por app; oapp.cssé dos componentes do app (timeline, tiles, stepper, badges de domínio), não é rastreado e o central nunca o re-deriva. A 0015 fechou o slot de<head>com razão (dois<head>quebram toda view) mas deixou o app sem lugar para o CSS dele, e a saída prescrita — "escreva o<head>à mão nessa tela" — não escala para 16 telas. Não era hipótese: dois apps já contornavam a lacuna, de formas diferentes — oint-piedemitindo o<link>no<body>via fragment local, e obi-comercial-xlsforkando olayout.html. O fork é o dado que decide: o layout forkado ainda carregava um fragment morto que o central removera há duas versões — fork sai do radar do/xadm-docse para de receber correção. Os dois apps escolheram o mesmo path (/css/app.css) independentemente: o kit passa a prescrever o que já era fato. Detalhe em 0017 e na receita Java/Micronaut §UI.Nenhum app quebra: as views seguem chamando
head('Título')com um parâmetro, e não há segundo<head>— a 0015 continua valendo, slot de markup arbitrário no<head>segue não existindo. Migração: app que usa o kit e re-derivar olayout.htmlprecisa terpublic/css/app.css, nem que vazio (sem o arquivo, 404 em toda página). Os dois contornos atuais continuam funcionando — ninguém precisa correr.
Corrigido¶
-
Constituição 0.24.1→0.25.0 —
templates/mkdocs.ymldeclaravaexclude_docs:duas vezes: oprivado/sumia em silêncio. Bug introduzido na 0.24.0 (arquivo-fato): o segundoexclude_docs:, 48 linhas abaixo do primeiro, sobrescrevia o bloco de cima — e aquele bloco excluíaprivado/, o segmento reservado a confidencial de cliente (§5). Todo app que re-derivasse o template verbatim passaria a publicardocs/privado/no site. YAML não avisa sobre chave duplicada, e o--strictfica verde por estar certo: para o MkDocs a chave apagada nunca existiu. Repro:python3 -c "import yaml; print(yaml.safe_load(open('mkdocs.yml'))['exclude_docs'])". Cura: os dois blocos fundidos num só, com o porquê no topo. -
O
checa-nav.pypassa a reprovar chave YAML repetida nomkdocs.yml— a classe, não o sintoma: doisnav:, doisplugins:, doistheme:falham igual. Parser de indentação stdlib (o check roda no gate de código do app, onde não há PyYAML — eyaml.safe_loadnão serviria: ele é quem come a duplicata em silêncio; para vê-la é preciso olhar o texto). Verificado nos dois sentidos: reprova otemplates/mkdocs.ymlreal de antes da correção (exclude_docsna linha 91, já declarada na 43) e passa nos 7mkdocs.ymlreais da casa, sem falso positivo. A guarda deprivado/dodocs.ymlcontinua sendo a rede de baixo, mas só pega o sintoma daquela vez, depois do build e só nos apps que a têm. Detalhe em CI, gates e testes. -
Constituição 0.24.0→0.24.1 —
docs.ymlerelease.yml: ocontainer:e o bloco Java agora se amarram. Ocontainer:(topo) e o bloco de geração de API (~120 linhas abaixo, comentado) eram acoplados em silêncio: descomentar o bloco sem trocar ocontainer:deci-baseparaci-java:<v>derruba o workflow no push comJAVA_HOME is not set. O defeito é invisível a todos os gates — oci.ymljá vem comci-javae passa verde, e o pré-flight da/xadm-releasebuilda na máquina do dev, onde há JDK; só o push descobre, e norelease.ymla tag já está no ar. Pior: a mensagem nativa do gradlew manda setarJAVA_HOME, que é o antipadrão da casa (decisão 0003 — a toolchain vem da imagem, semsetup-java). Agora o comentário do bloco cobra a troca docontainer:e uma guarda (command -v java) transforma o erro numa instrução que aponta ocontainer:. Orelease.ymllevou a mesma guarda: ele já tinha o comentário e o mesmo defeito.
0.27.1 - 2026-07-17¶
Corrigido¶
- Constituição 0.24.0→0.24.1 — o Dockerfile canônico manda o app rodar como
USER appnum WORKDIR que é deroot. OWORKDIR /appcria a pasta como root (o--chowndoCOPYé do jar, não dela); depois doUSER app(uid 1001) qualquer escrita sob/app— log em caminho relativo, cache, upload, diretório de trabalho — falha comAccessDeniedExceptionem runtime, na produção: o build passa, o teste passa e odocker builddo pré-flight também. Reproduzido com Docker de verdade (mkdir /app/logsetouch /app/x→Permission denied). Nobi-comercial-processador-xlsisso derrubou todo o processamento (logback emlogs/app.log,createDirectories(/app/logs)falhando antes de qualquer trabalho). Agora otemplates/dockerfile-javatraz, no ponto exato antes doUSER app, a regra + a receita comentada (RUN mkdir -p /app/logs && chown app:app /app/logs), com o aviso de não usarchown app:app /appinteiro (o app sobrescreveria o próprioapp.jar— metade do motivo de rodar não-root) e de conferir o arquétipo antes (servidor loga em stdout, quem loga em arquivo é CLI/worker —logs/num servidor costuma serlogback.xmldo arquétipo errado). Ojava-micronaut.md§Deploy ganha o bullet-dono; ocoolify.mdtroca o exemplo/app/logsdeStorages(arquétipo errado) e documenta a herança de dono: volume nomeado herda o dono do diretório da imagem — se o diretório não existir, nasceroote quebra igual —, bind mount não herda (o dono no host é que precisa ser1001:1001).
0.27.0 - 2026-07-16¶
Adicionado¶
-
Constituição 0.23.3→0.24.0 — arquivo-fato ganha hospedeira obrigatória, e sai do build com
exclude_docs:. A 0.23.0 mandou o dono publicar o fato, mas a receita dizia que ele "vive emdocs/public/como qualquer página" e levanot_in_nav:— duas metades que não fecham: sem uma página que o embuta, o fato só existe noraw/, invisível no site do dono. Enot_in_nav:não esconde, só cala o aviso de órfã: o fragmento continua sendo buildado, ganha um H1 inventado do nome do arquivo ("Xadm ingest"), fica alcançável por URL e entra na busca — procurar "Envelope" devolve a hospedeira e a órfã, com o mesmo texto. Agora: a hospedeira (public/contratos/index.md, nonav:, com frontmatter) é obrigação do dono, e os fatos saem do build comexclude_docs:+!reincluindo a hospedeira. O--8<--e orclone/cpdoraw/seguem funcionando — leem do disco, não do build. Vale nos dois lados:_importado/também éexclude_docs:, senão o site do consumidor serve o contrato do dono como se fosse página dele — a cópia que o mecanismo existe para matar.not_in_nav:fica para o que deve sair no site sem estar no índice (o Javadoc emdev/api/). Decisão 0016.Migração — quem já publica fato troca
not_in_nav:porexclude_docs:Um repo publica arquivo-fato hoje (o hub de integração) e já tinha escrito a hospedeira por conta própria. Trocar o
not_in_nav:peloexclude_docs:dotemplates/mkdocs.ymltira a órfã do ar. Sem a troca nada quebra: o site só segue servindo a página órfã e duplicando o texto na busca. -
Página em
docs/public/leva frontmatter — inclusive a da API. Havia duas convenções: otemplates/public-api.mdsem frontmatter, a hospedeira do hub com. Governança por documento (§6) não abre exceção por a página ser pública, e para quem consome um contrato o cabeçalho é o que importa:atualizado:diz se o contrato está vivo,status:se dá para confiar,responsavel:a quem perguntar. O hook expõe o nome, nunca o e-mail. -
Constituição 0.23.1→0.23.2 —
checa-admonition.py: admonition cru vira gate. Omkdocs build --strictnão pega marcador mal indentado: para ele não há erro, só um parágrafo que começa com!!!— renderiza literal e sai verde, e quem paga é o leitor. Mesma classe do Mermaid que não parseia (a razão dolint-mermaid.mjs), e foi achado no olho de um humano, que é o gate que a §6 diz não servir. O check roda depois do build e confere o HTML, não o Markdown: ali não há ambiguidade —!!!em<pre>é código exibido (esta plataforma mostra orunbook.md, que tem um!!! warningde exemplo), em<p>é bug. Nobuild-site.yml, nodocs.ymldos apps e no pré-flight da/xadm-release.
Corrigido¶
-
checa-nav.py— a negação!deexclude_docs:era ignorada, e os globs vinham sem ordem. Dois bugs que só apareceram ao prescrever a hospedeira, e que a teriam transformado numa órfã silenciosa: o veredito parava no primeiro glob que casava (então/public/contratos/*.mddava a hospedeira como excluída e ela podia sumir donav:sem ninguém acusar), e os globs eram acumulados numset— sem ordem, num formato em que a ordem decide (última que casa vence, como no.gitignore). Um terceiro: o regex que varre omkdocs.ymlcapturava os próprios globs de exclusão como "menção de nav", dando passe livre a fato que nenhum exclude cobria. Três casos novos de regressão; mutação confirmada (o_excluidoantigo deixa caso vermelho). -
testa-checa-views.py— a fixture agora é o kit real, com guarda de mutação. OLAYOUT_OKera cópia à mão do layout e já tinha divergido dele uma vez (ficou com o layout quebrado da 0.21.0 e a suíte seguiu verde durante todo o bug). Agora lêtemplates/views/layout.html. A guarda existe porque ler o real só é melhor se a mutação for garantida:muta()exige que o alvo apareça exatamente uma vez — pega tanto o no-op (o kit mudou, o alvo sumiu) quanto o alvo ambíguo. Não é hipótese: ao trocar a fixture, os dois casos da regra G passaram a injetar o<head>defeituoso dentro do comentário de cabeçalho do kit (onde o parser não olha) e ficaram verdes testando nada — a guarda os pegou. -
Constituição 0.23.2→0.23.3 — o kit de UI da 0.21.0 estava quebrado no ar: slot de head removido. O fragment
headComExtras(title, extras)era um segundo elemento<head>nolayout.html, e um documento HTML tem um só: o parser funde o segundo no primeiro, e ohead('Título')passou a arrastar o${extras}do irmão —Error resolving fragment: "${extras}", 500 em toda view, inclusive nas que não usavam o slot. A afirmação da 0.21.0 de que "as telas que já chamamhead('Título')seguem intactas" era falsa. Reproduzido com Thymeleaf 3.1.5 antes de decidir: não é colisão de nome (renomear não cura) nem "head dentro de body" (dois<head>irmãos quebram igual) — basta serem dois. O slot foi removido em vez de consertado: 0 views o usavam, 126 chamavamhead(). Tela que precise de markup próprio no<head>escreve o<head>à mão e traz o caso ao central. Decisão 0015.Migração — quem copiou o kit 0.21.0/0.22.x re-deriva com
/xadm-docsO
layout.htmlvolta a ter sóhead(title). Nenhum app usava o slot, então não há chamada a corrigir: quem estava com o kit quebrado volta a renderizar; quem nunca adotou não faz nada. -
checa-views.py— regra G:<html>/<head>/<body>duplicado no mesmo arquivo reprova. É a guarda contra a reincidência do bug acima. Vale mesmo com nomes distintos e mesmo fora do<body>— o que quebra é o parser fundir elemento, não o nome (a regra A já cobria nome). Só declaração real conta: o cabeçalho do kit documenta o uso com um<head th:replace=...>dentro de comentário, e os três apps Micronaut reais têm isso — a regra lê o parser, nunca regex. Verificada nos dois sentidos: reprova olayout.htmlreal da 0.21.0 e passa nos 46 views reais dos três apps. -
testa-checa-views.py— a fixtureLAYOUT_OKera o layout quebrado. O "layout conformante mínimo" da suíte trazia o segundo<head>: o teste do checker atestava contra um defeito, que é a fixture inventada que a §6 nomeia — e o motivo de a suíte não ter pego nada. Corrigida, mais quatro casos da regra G (o bug real, os dois<head>irmãos,<body>duplicado e o negativo do<head>em comentário). -
checa-rotas.py— a mensagem de erro dizia onde pôr o escape de forma ambígua. Dizia "<!-- checa-rotas: ignorar -->na linha"; um dev de app leu como "na linha de cima" e perdeu um ciclo de gate. Agora diz na MESMA linha da rota, e que o marcador não aparece na página (é comentário HTML). Só a string mudou — o escape sempre foi por linha, e segue. -
Nota de migração da 0.23.1 renderizava crua na
/changelog/— o!!! noteestava indentado com 2 espaços dentro do bullet e saiu como texto literal na página publicada. Python-Markdown usatab_length = 4: parágrafo de continuação de item de lista aceita 2 espaços (lazy continuation), mas bloco novo — que é o que o admonition é — exige 4; com 2, ele cai fora da lista e vira parágrafo. O texto ao redor sai perfeito, então o erro não chama atenção no diff.
0.26.0 - 2026-07-16¶
Adicionado¶
- Constituição 0.21.0→0.22.0 — o contrato REST passa a ser checado contra o OpenAPI
gerado:
checa-rotas.py(loop §6, feedback de app). A §6 mandava a doc mudar no mesmo PR que muda o contrato, e nada detectava quando isso não acontecia — a própria §6 admitia não ter "detector automático de doc seguiu código". Num app, uma rota de upload foi renomeada no controller; o OpenAPI, que omicronaut-openapideriva dos@Controllerao compilar, acompanhou sozinho; a prosa não. Por 10 dias omkdocs build --strict, ocheca-nave oci.ymlficaram todos verdes enquanto o site publicado servia o contrato novo e a prosa com a rota morta, lado a lado. Ocheca-rotas.py(rastreado, stdlib, baixado fresco, tolerante) confere prosa → spec e roda noci.yml(depois do./gradlew check, que é quando o spec existe — o rename é evento de código) e nodocs.yml(prosa editada sem tocar código, inclusive pela web do Forgejo). Só cobra rota cujo primeiro segmento existe no spec, para não reprovar API de parceiro que o app só consome nem rota de app vizinho; aceita prefixo de família em diagrama; pula documentostatus: obsoleto; e tem escape de linha<!-- checa-rotas: ignorar -->para a decisão de remoção, que não tem como nomear a rota removida sem escrevê-la. Aplicado aos dois apps que geram OpenAPI, achou o drift do feedback e um segundo bug inédito (doc cuja seção diz "Envie um PUT" e cujo exemplo dizPOST, numa rota que só expõePUT/DELETE). Decisão 0012; detalhe em CI, gates e testes.
Corrigido¶
-
Constituição 0.23.0→0.23.1 — o kit de UI mandava o CSS para um diretório que não o serve (loop §6, feedback de app). A
/xadm-docsmapeavatemplates/views/**→src/main/resources/views/**, mastemplates/views/tinha dois arquivos com destinos diferentes: olayout.htmlé view, ocustom-theme.cssnão — quem serveviews/é o Thymeleaf, e o CSS precisa dostatic-resources(public/css/), como o próprio arquivo dizia no cabeçalho e o@{/css/custom-theme.css}do layout referenciava. Seguir o glob ao pé da letra sobe a tela sem estilo. Bug latente, nunca exercitado: os dois apps Micronaut reais têm o CSS no lugar certo porque nasceram antes do kit — o primeiro app novo a seguir a skill é que quebraria. A cura foi a origem, não o mapeamento: ocustom-theme.cssfoi paratemplates/public/css/, e a árvore do kit passa a espelhar a do app — os dois globs viram verdade (views/**→views/**,public/**→public/**), sem exceção por arquivo a manter em sincronia. Listar arquivo-por-arquivo na skill (o que o feedback pedia) duplicaria a tabela que já é dona nojava-micronaut.md— recriando o segundo dono que causou o bug. Guarda nova: ocheca-views.pyganha a regra F (arquivo não-.htmlemviews/reprova, apontandopublic/), que mata a classe e não só este arquivo.Nota de migração — só o path de ORIGEM muda
O destino no app não muda: quem já tem
public/css/custom-theme.cssestá correto e nada precisa fazer. Mudou o caminho no manifesto (templates/views/custom-theme.css→templates/public/css/custom-theme.css), então a/xadm-docsre-baixa do raw novo. App que tenha o CSS emviews/(nenhum conhecido): mova parapublic/css/— a tela está sem estilo.
Alterado¶
-
Constituição 0.22.1→0.23.0 — fato de outro repo: o dono publica em
raw/, o consumidor importa no build (loop §6, feedback de app). A 0.22.1 abriu transclusão para fato do mesmo repo e manteve "cross-repo é link, sempre". O caso que sobrou é o runbook de implantação de um vertical, que vive entre dois apps: o que ele implanta é seu, o contrato de ingestão que ele consome é do hub. O diagnóstico mudou a pergunta — o hub não publica o OpenAPI que ele já gera (step comentado), não temdocs/public/, e seu contrato vive espalhado em dez arquivos de prosa. Não havia o que linkar: a cópia era sintoma, o dono que não publica é a causa, e a regra parava no consumidor. Agora: o--8<--não atravessa repo, mas o build atravessa — o dono publica o.mdcru na raiz do seu prefixo (docs-sites/<slug>/raw/, aditivo, todo push, pelo mesmo critério que já põe oapp.jsonlá: é contrato entre apps, não conteúdo versionado), e o consumidor fazcurl -fparadocs/_importado/(efêmero:.gitignore+not_in_nav:) e embute. O fato chega fresco a cada build;curl -ffalha o build se o dono despublicar. Publicar é obrigação do dono, e quem rege a evolução de um repo não vira dono dos fatos dele — o projeto-mãe escreve o PR no dono e importa aqui, senão um hub compartilhado ganha um dono por consumidor. Decisão 0014; receita em Publicar docs. -
Constituição 0.22.0→0.22.1 — o runbook transclui do arquivo-dono; re-digitar é que é proibido (loop §6, feedback de app). A 0.20.2 fechou "o livro não entra no runbook" e mandou o runbook linkar; um dev aplicou a regra e reverteu, porque a versão conforme ficou pior para o uso real — mostrar a integração à equipe numa página. O ponto procede por um motivo mais forte que o custo ao leitor: a regra contradizia o princípio que deveria implementar (o §1.9 já dizia "linkam ou embutem (
pymdownx.snippets), não copiam"). Agora: onde o operador precisa do fato na mesma página, o runbook transclui do arquivo-dono — não há cópia para envelhecer. Transclui-se do arquivo-fato, nunca "da seção do livro" (o livro é narrativa e ele próprio embute os fatos); cross-repo continua link, que é onde o exemplo-que-mente nasceu. O §2 passa também a nomear o que fica no runbook (topologia de operação com diagrama, superfície, variáveis, passos/verificação/ reversão): ele só enumerava proibições, e a migração revertida cortou junto o Mermaid de topologia que o próprio molde prescreve — regra que só diz o que sai é aplicada cortando demais. Registrada a armadilha do--8<--(é pré-processador de linha: transclui dentro de bloco de código e de comentário HTML; escape é;) em Templates. Runbook que linka continua conforme — transcluir é permissão, não obrigação. Decisão 0013. -
Piso §6 — "o teste não reimplementa a lógica que atesta" (loop §6, feedback de app). A definição de pronto cobrava "teste proporcional ao risco" e já nomeava a fixture inventada como falso atestado, mas não o irmão dela: o teste que refaz no próprio corpo a conta da produção passa por construção — o
expecteddeixou de ser oráculo e virou um segundo palpite da mesma cabeça que escreveu o código. Caso real: um teste de agregação somava as linhas noteste comparava com a soma do serviço, verde sobre uma agregação errada. O piso agora exige oráculo de fora (valor literal, saída capturada, invariante independente), e o ci-testes registra o teste de mutação (PIT) como ferramenta de diagnóstico sob demanda — não gate, pela mesma razão de "cobertura é visível, não bloqueante". -
Constituição 0.20.2→0.21.0 — o kit de UI ganha o gate que faltava:
checa-views.py(loop §6, feedback de app). O kit de UI foi o primeiro template rastreado executável (os demais são Markdown, ou Python com teste de regressão), e para ele o central não tinha guarda nenhuma: o manifesto atesta que a cópia do app é idêntica à do central (sha256), nunca que ela funciona. Foi exatamente essa fresta que deixou a 0.19.0 publicar umlayout.htmlcom doisth:fragment="navbar"homônimos — sha íntegro,--checkverde, 500 em toda view de quem adotasse. O novo check é stdlib e offline (sem JVM): reprova fragment homônimo, chamada a fragment que o layout não declara, aridade divergente, chamada posicional contra fragment sem signature (o defeito da 0.19.2) e markup passado declarado fora do host doth:replace. Roda noci.ymlde todo app com view (tolerante: semsrc/main/resources/views/, sai 0) e no CI do central contratemplates/views/— na origem, antes de publicar, que é onde o defeito da 0.19.0 teria morrido. Verificado contra olayout.htmlreal da 0.19.0 (reprova) e contra as 38 views reais do integrador e do int-produtos-ecom (verde, sem falso positivo). Acompanhatesta-checa-views.py(12 casos, central-only). headComExtras(title, extras)no kit de UI — a tela que precisa de markup próprio dentro do<head>(típico<noscript><meta http-equiv="refresh">de fallback sem JS, inválido e ignorado fora do<head>) não tinha lugar canônico e empurrava o conteúdo para o<body>. Irmão nomeado dohead(title), como onavbarComMenué donavbar: sem overload por aridade, e as telas que já chamamhead('Título')seguem intactas.
Corrigido¶
- A receita não dizia ONDE a página declara o markup que passa (
~{::navMenu}): oth:replacesubstitui o elemento host inteiro — host e conteúdo somem do output. Declarado solto no<body>, oth:fragmentrenderiza duas vezes; o certo é aninhá-lo dentro do elemento que faz o replace, e isso só aparecia no exemplo para quem já soubesse. É silencioso (não dá 500, só sai errado na tela). Agora está no bloco de código da receita, no cabeçalho dolayout.html, e ocheca-views.pyreprova. th:fragment="styles"morto no<head>do kit — fragment vazio herdado do layout pré-kit do integrador na templatização da 0.19.0. Zero uso nos dois apps Micronaut, não documentado em lugar nenhum: sinalizava um slot que não entregava. Removido; quem precisa de markup no<head>usa oheadComExtras.
0.25.1 - 2026-07-16¶
Adicionado¶
- Constituição 0.20.1→0.20.2 — runbook de implantação vira molde, e o §2 ganha as três
regras que o pior dia cobra (loop §6, feedback de app). O nível 5 promete "runbooks
técnicos: deploy, recuperação, destrutivas", mas o único template era o
runbook.md, de procedimento pontual (operação única, disparada por incidente, num app só) — quem precisava documentar subir um sistema não tinha base, e a diferença não é de tamanho, é de eixo: o procedimento responde "como executo esta operação"; a implantação, "como este sistema fica de pé, e como eu o desligo". Agora hátemplates/implantacao.md, irmão dorunbook.md(não substituto): topologia de operação, superfície de operação, variáveis por servidor com os pares que têm de casar, passos, verificação, reversão. - Três regras no piso §2 (bullet Runbook) — cada uma de um defeito real que passou pela
revisão humana num doc de implantação escrito sem base: (1) a Reversão enumera
todas as vias e o que cada desligar isolado não para (sistema com webhook + varredura
precisa da tabela caminho → efeito, com os caminhos que não funcionam marcados — kill
switch não conferido contra o código é kill switch imaginário, e é lido no pior dia
possível); (2) todo passo de Verificação declara o resultado esperado conferido no
código — mesmo payload ≠ mesma versão: onde a chave-versão é bumpada por escrita
(
@DateUpdated, sem dirty-check), idempotência prova-se com uma escrita e vários ciclos do consumidor, nunca com duas; (3) valor de contrato externo sem fonte do outro lado é<PLACEHOLDER>+ bloco "A confirmar" com o efeito de errar — fixture nossa não confirma contrato de terceiro (javadoc "ex.:", seed e whitelist concordam entre si porque descendem da mesma suposição). Valem para os dois moldes: as duas primeiras cobram seções que todo runbook já tem.
Corrigido¶
- §2 ganha a metade que faltava da fronteira: "o livro não entra no runbook" — corolário simétrico do já escrito "o deploy não entra no livro". O doc que originou este feedback re-digitava três capítulos do livro (topologia-arquitetura, fluxo de eventos, contrato de entrada), contra §1.9 (um dono por fato) e §1.2 (o factual vem da fonte). Não é purismo: o contrato re-digitado longe do dono foi o que virou exemplo-que-mente. O molde novo linka o livro e escreve só o que é de operar.
Adicionado¶
-
Constituição 0.19.2→0.20.1 — o container do app vira artefato prescrito (loop §6, feedback de app: nasceu doc-only, virou código, passou em teste e e2e local e quebrou no deploy do Coolify por não ter Dockerfile). A plataforma nunca prescreveu container: todo o conhecimento vivia no registro "não pise nesta mina" (armadilhas de
.dockerignore/.git/HEAD), e o registro "isto é o que você constrói" nunca foi escrito —coolify.mddizia "Build Pack:Dockerfile" tratando o arquivo como fato da natureza. Havia contradição interna: a §5 exige health check obrigatório, mas a Estrutura padrão (§3) não listava o artefato onde oHEALTHCHECKvive. E era assimétrico:flutter.mdtinha receita,java-micronaut.mdnão citava Dockerfile em linha nenhuma — a stack que mais deploya era a sem receita. Agora: piso na §3 (app deployável levaDockerfile+.dockerignoredesde o 1º commit de código); templates rastreados e opcionaisdockerfile-java+dockerignore-java;## Deploy — o Dockerfileemjava-micronaut.md; gatedocker buildno pré-flight do/xadm-release(degradado sem daemon, declarado no relatório); trilha "repo que era só doc e passou a ter código" emapp-novo.md; decisão 0011. Motivo do gate: oci.ymlnão builda imagem e o Coolify builda o Dockerfile do repo — era o único artefato que nenhum CI tocava, e a produção era a primeira a exercitá-lo. -
Flutter §Deploy web — cache no nginx (loop §6, feedback de app). Receita nova:
main.dart.jséno-cache, não cache longo — o Flutter Web não versiona URL de filho (verificado no build 3.44:buildConfigtraz"mainJsPath":"main.dart.js"e o loader monta a URL sem query nem hash; o único?v=é doflutter_service_worker.js, e a casa builda--pwa-strategy=none). Errar isso é invisível no deploy e mata o auto-update: o banner de "nova versão" aparece, o usuário clica e o browser serve o mesmo bundle do cache por até 30 dias. Regra +mapde exemplo + os assets de nome fixo que também precisam revalidar (MaterialIcons-Regular.otf,sqlite3.wasm,powersync_db.worker.js) +curl -sI …/main.dart.jscomo verificação pós-deploy. Motivo de existir a receita: o bi-comercial corrigiu o bug em 2026-05-13 e o bi-transporte ficou dois meses com o comentário oposto emax-age=2592000em produção — o central não tinha dono do assunto.
Alterado¶
SENTRY_DSNé o env canônico do DSN em toda stack (antesGLITCHTIP_DSN). É o nome que o SDK do Sentry lê do ambiente por convenção (Java e Dart) e o GlitchTip é Sentry-compatível, então o nome canônico elimina o código que existia só para traduzir env. A constituição mandavaGLITCHTIP_DSN, mas metade dos repos Java (integrador, int-produtos-ecom, bi-transporte-xls) e todo o Flutter já usavamSENTRY_DSN— a mudança ratifica a maioria. Vale igual no Flutter (--dart-define=SENTRY_DSN) e é o nome que o/xadm-setupinjeta no Coolify (exceçãoglitchtip.dsn → SENTRY_DSNna tabelaENVS_CANONICOSdo broker). Atenção — o rename é SILENCIOSO, não barulhento: trocar o nome no Coolify sem o código já ler o novo não dá erro — o${…:-}resolve para vazio, o appender vira no-op e o app sobe normal, enquanto todo erro de produção para de ser reportado sem sinal nenhum. Ordem segura: código primeiro (com fallback${SENTRY_DSN:-${GLITCHTIP_DSN:-}}), deploy, aí o rename no Coolify, aí remove o fallback. A injeção do broker é upsert: reprovisionar criaSENTRY_DSNe deixa oGLITCHTIP_DSNórfão no recurso — apagar na mão.
Corrigido¶
-
Cache mount do Gradle no Dockerfile:
iddefault =target+ sharing default =shared(achado ao dogfoodar o template novo — buildá-lo contra um app real em vez de publicá-lo por inspeção). Os dois apps Java da casa usam--mount=type=cache,target=/root/.gradlebare; como oidde um cache mount default para o própriotarget, todos os apps Java dividem um único cache no servidor do Coolify, e o sharing defaultshared("can be used concurrently by multiple writers") é justamente o que o Gradle não tolera. Dois deploys concorrentes — ou um build morto que deixou lock stale — falham comTimeout waiting to lock journal cache (/root/.gradle/caches/journal-1). It is currently in use by another process, intermitente e com cara de bug do app. Reproduzido, não inferido. Template usaid=gradle-<slug>+sharing=locked(o que a doc do Docker prescreve para o apt, pela mesma razão); nota emjava-micronaut.md§Deploy. Migração oportunista nos apps existentes. -
.dockerignorenão é.gitignore— a diferença é silenciosa e um dos padrões quebraria o build. Verificado empiricamente (Docker 29.5), contra fonte que afirmava o contrário: o Docker casa padrões comfilepath.Matchdo Go, onde*não cruza/. Consequências que os repos atuais carregam sem saber:buildbare exclui só a raiz (sub/build/viaja pro daemon — inócuo em single-module, mina armada ao modularizar), e**/*.jarquebraria o build ao excluir ogradle/wrapper/gradle-wrapper.jar(ogradlewmorre com "Could not find or load main class org.gradle.wrapper.GradleWrapperMain"). O template usa**/builde mantém*.jarraiz-only de propósito, com o porquê escrito. A exceção!docs/app.jsondo item 79 foi verificada de fato funcionando (e só funciona depois dedocs: vence a última linha que casa, não a mais específica). -
Constituição 0.19.1→0.19.2 — kit de UI:
layout.htmldeclarava dois fragmentsnavbarhomônimos (loop §6, feedback de app). O layout tinhath:fragment="navbar"eth:fragment="navbar(menu)", mas o Thymeleaf resolve fragment por nome e não faz overload por aridade (confirmado na doc oficial) → as duas chamadas que a receita ensinava quebravam no render (500):~{layout :: navbar}casava a variante com signature ("Error resolving fragment:${menu}") e~{layout :: navbar(~{::navMenu})}casava a sem signature ("Signature navbar declares no parameters, but fragment selection did specify parameters"). Qualquer app que adotasse o kit da 0.19.0 batia nisso. A variante com menu virounavbarComMenu(menu)— nomes distintos, chamadas posicionais válidas nos dois lados, semth:ifno fragment (que cairia na armadilha de precedênciath:replace(100) <th:if(300) e contrariaria o corolário de "duas superfícies, dois fragmentos" já normatizado). Receita do Java/Micronaut §UI corrigida; apps re-derivam o kit via/xadm-docs. - Constituição 0.19.0→0.19.1 —
checa-navcasava globs comfnmatch, não com o formato.gitignore(loop §6, feedback de app). Os padrões denot_in_nav:/exclude_docs:seguem o formato .gitignore (doc do MkDocs), e o script os casava comfnmatch— semânticas diferentes, divergindo em três frentes: barra inicial (/privado/*nunca casava → falso positivo, gate vermelho num exclude legítimo — o caso do feedback), barra final (privado/não casava em nível algum — é oexclude_docs:do próprio central, inócuo só porque ainda não há.mdsobprivado/) e*cruzando/em padrão ancorado (rascunhos/*.mdabsolviarascunhos/mais/b.md→ falso negativo, órfão real passando). Trocado por um mini-matcher.gitignoreem stdlib (o check roda no gate de código do app, onde não há mkdocs nempathspec). checa-nav: menção em comentário domkdocs.ymlvalia como declaração denav:(mesmo feedback). O script varria o YAML cru com regex ([\w./*\-]+\.md), então um.mdcitado num comentário absolvia o arquivo órfão — falso negativo que escondia o falso positivo acima. Comentários agora são removidos antes do regex (preservando âncorapagina.md#secao, que não é comentário).testa-checa-nav.py(novo, central-only): regressão docheca-navem 9 casos versionados — os 4 bugs acima reprovam a versão anterior. Roda no CI (build-site.yml) e no pré-flight da/xadm-release, como otesta-valida-frontmatter.
0.24.0 - 2026-07-16¶
Adicionado¶
- Constituição 0.18.11→0.19.0 — UI unificada para apps server-render (loop §6, feedback de app).
A constituição regia doc e engenharia mas não tinha convenção de UI: cada app que renderiza
HTML no servidor (Micronaut Views/Thymeleaf) — telas de admin/ops/dev, mesmo internas e atrás
do gate de auth do Coolify — reinventava o visual (integrador padronizado × tradutor ecom com
<table border="1">cru), drift que só se pega no olho. Piso novo no §5 (UI dos apps): todo app server-render segue o layout padrão X-Adm (fragment base únicohead/navbar/scripts, Bootstrap 5, header escuro com logo, idiomas da casatable-striped/badge/alert) na paleta única doxadm.css; o app só escreve o conteúdo de cada tela. Kit rastreado opcional no manifesto (templates/views/layout.html+custom-theme.css+logo.png+favicon.ico; sincroniza pela/xadm-docs, ausente em app headless/Flutter não é defasagem) + item de conformidade §3b da/xadm-docs(tem views mas não usa o layout → não-conformidade). Detalhe operável + snippetstatic-resourcesemengenharia/java-micronaut.md§UI; re-derivado limpo na paleta canônica (o kit do integrador usava#0066CC, cor errada); decisão 0010. - Constituição 0.18.10→0.18.11 — espelho fiel ao X-Adm (nível de coluna) (loop §6, feedback da
integração PIED). A integração PIED promoveu chaves do vocabulário do parceiro (
codigo_alt,x_ped) a identidade de 1ª classe na tabela-espelho; a §Fronteiras só regia o prefixo de tabela, nada regia a identidade de coluna dentro do espelho. Piso novo no §8 (ao lado de owner-writes): a tabela-espelho modela a entidade do X-Adm, não a do parceiro — identidade em coluna nativa (conferida contra a spec de entidades do ERP), campo de origem externa entra prefixado (<origem>_) e só como rastreabilidade, nunca chave/join. Detalhe operável + tabela de coluna emdocumentacao/integracao.md§Fronteiras; eco server-side emengenharia/java-micronaut.md§Banco; decisão 0009. - Dois gotchas de stack no
java-micronaut.md(loop §6, feedback de app; engenharia-only, sem bump). (1) §Armadilhas:@Clientconfig-gated — declararmicronaut.http.services.<id>.urlcria umServiceHttpClientConfigurationeager (@EachProperty) que quebra o startup do contexto inteiro se a URL estiver vazia (Failed to inject value for parameter [url]; sintoma = N@MicronautTestem massa noNettyHttpServer.start/beforeAll). Cliente HTTP só-em-alguns- deploys:@Client("${prop.url}")na interface +BeanProvider<Client>(lazy), assim o bean nem nasce. (2) §Banco: chave-de-mudança de espelho multi-writer vive no banco (trigger), não no app —updated_atpor trigger Postgres (BEFORE INSERT OR UPDATE, bump só emIS DISTINCT FROM) cobre todos os escritores (apply, admin CRUD, PowerSync) num lugar; coluna trigger-managed não se mapeia na entidade (Micronaut Data fazUPDATEsó do mapeado → null-wipe no update). - Flyway em Postgres compartilhado — app secundário exige baseline (loop §6, feedback de app;
engenharia-only, sem bump). §Banco do
java-micronaut.md: com a história por app, o segundo app sobe com a sua tabela de histórico ainda inexistente contra um schema não-vazio (tabelas do app dono já lá) → o Flyway aborta ("Found non-empty schema(s) without schema history table"). Cura:baseline-on-migrate: true+baseline-version: 0— o primeiro deixa o Flyway marcar o schema como linha-base em vez de abortar; o segundo faz a própriaV1do app rodar (o default1pula a V1 do secundário silenciosamente). Só no app secundário; o dono do schema sobe do zero.
0.23.7 - 2026-07-14¶
Adicionado¶
- Higiene do
.claude/settings.jsonvira norma da casa (engenharia/ferramentas.md, com ponteiro noapp-novo.md): o arquivo versionado leva só o compartilhado (hooks +additionalDirectoriesrelativo + allow-list de padrões largos que absorvem os comandos comuns); grants pessoais/de-máquina vão para.claude/settings.local.jsongitignored. Sem isso o allow-list incha a cada sessão e ogit commit --amendresultante troca o hash sob a tag, soltando a release. O templategitignore-flutterpassa a ignorar osettings.local.json. - Estilo terso (caveman) ativado no repo central via hook
SessionStart(.claude/caveman.sh) — dogfood do padrão queagentes.md/app-novo.md/ferramentas.mdjá prescreviam; regra de higiene de arquivos afiada emferramentas.md("Bash executa, não lê" + blocklistsed/ls -la/grep -rn).
Corrigido¶
- Typo no
.gitignore(.claude/.settings.local.json→.claude/settings.local.json) que deixava os grants pessoais fora da proteção do repo (só o ignore global da máquina cobria).
0.23.6 - 2026-07-14¶
Adicionado¶
- Constituição 0.18.9→0.18.10 — o fechamento passa a recomendar
/compactdepois do commit (pedido do Gustavo; altitude decidida por AskUserQuestion = skill + constituição §6). O/x-documentaré o passo que persiste o durável emdocs/, então compactar o contexto ao fim do ciclo recupera tokens sem perda (linha de economia dos itens 56/57/66). A ordem importa: commit antes do/compact, senão a mensagem pronta pode ir embora no resumo e o dev ainda não salvou. Bullet do fluxo recomendado no §6 da constituição + item 4 no fechamento (§5) da skill/x-documentar(template rastreado → re-carimbo + cópia dogfood re-derivada). Bump PATCH. engenharia/java-micronaut.md§Armadilhas (loop §6, feedback de app): Thymeleaf bloqueia expressão String em atributo de evento (th:onclick/th:onload/th:on*). Por segurança (defesa contra injeção de JS via dado de usuário), o Thymeleaf 3.x só aceita nesses atributos expressão que retorna número ou boolean → String lançaTemplateProcessingException("Only variable expressions returning numbers or booleans are allowed…") no render, com o build verde. Padrão da casa p/ linha/ card clicável: dado numdata-*(th:attr="data-href=@{/rota/{id}(id=${x})}") + handler em JS no rodapé — nuncath:onclickcom a URL. Nova armadilha na família de view server-side (irmã dorecord/OGNL e doth:replace). Bônus (corolário atado ao bullet de precedênciath:replace×th:if, decisão do Gustavo — AskUserQuestion): duas superfícies de UI distintas (chrome público × navbar de operador) = dois arquivos de fragmento de layout separados, não um layout único comth:ifno menu. Engenharia-only, sem bump (java-micronaut.mdnão é rastreada).engenharia/java-micronaut.md§Armadilhas (loop §6, feedback de app):ViewModelProcessor+Map.of()do controller = HTTP 500 só nas rotas que devolvem imutável. UmViewModelProcessorinjeta dado transversal no modelo de toda view (usuário/tenant/versão no layout — padrãolayout.htmlGlobalViewModeldo molde do integrador) viamodel.put(...); se o controller devolveu umMap.of(...)(imutável, comum no ramo "não encontrado"), oputestouraUnsupportedOperationException→ 500, só naquelas rotas. Regra: view controller sempre devolve modelo mutável (LinkedHashMap), nuncaMap.of. Guarda barata: testeGETnuma rota de not-found esperando 200. Nova armadilha na família de view server-side (irmã dorecord/OGNL e doth:replace), engenharia-only, sem bump (java-micronaut.mdnão é rastreada).engenharia/java-micronaut.md§Erros e logging + §Armadilhas (loop §6, feedback de app): cliente HTTP + config vazia = 500 + registro preso. URI montada de config (baseUrl+ rota) com base vazia vira URI relativa →HttpRequest.newBuilderlançaIllegalArgumentException(não a exceção de domínio) → escapa docatch→ 500; pior, se a máquina de estados marcou o registro "em voo" (ENVIANDO) antes da chamada, ele fica preso sem transição de saída. Dividido em dois donos (decisão do Gustavo, AskUserQuestion): norma durável de resiliência em §Erros e logging (validar a montagem da chamada → exceção de domínio tratável;catchde chamada externa largo o bastante praRuntimeExceptioninesperada, garantindo transição pra estado terminal em qualquer exceção) + a armadilha concreta em §Armadilhas apontando pra norma. Engenharia-only, sem bump.- Constituição 0.18.8→0.18.9 — armadilha "Dockerfile lê
docs/app.json⇒ precisa da exceção!docs/app.jsonno.dockerignore" (loop §6, feedback de app; verificado no.dockerignoredo integrador, que excluidocs). A ponte de config da Central de Apps tem duas metades que viajam no mesmo PR: o Dockerfile lerdocs/app.json(Flutter viajq→--dart-defineem build-time; um servidor viaCOPY→leitura em runtime) e a exceção no.dockerignore— separar quebra o deploy (arquivo fora do contexto de build). Dono stack-neutro:infraestrutura/coolify.md, ao lado da gêmea "não leia.git/HEADno build", com o contraste preciso (aqui a negação!docs/app.jsonresolve — o arquivo é committado e está no contexto; lá o.gitnem chega ao contexto). Cross-link da receitajq docs/app.jsonemengenharia/flutter.md. A/xadm-setuppasso 5 (que manda "crie a ponte") passa a exigir as duas metades → bump PATCH e re-carimbo doxadm-setup-skill.md. Decisão do Gustavo (AskUserQuestion): altitude = também a skill rastreada. engenharia/powersync.md§Auth (loop §6, feedback de app PowerSync): a §Auth passa a distinguir dois modos de consumidor — app com usuário real (JWT do usuário via JWKS doauth, oujwks_urido Google no Firebase) vs cliente máquina-a-máquina (o cliente Java do ERP, os reatores — sem humano), que nasce self-signed + JWK inline: o cliente assina o próprio JWT com key privada em env e o PowerSync valida contra o JWK público inline — o mais simples e sem peça nova (sem broker, sem IdP), reservando Firebase/pAbast para quem tem usuário de verdade. Casa com três normas já existentes (Kerckhoffs emseguranca.md§Segredos,inline > jwks_urida própria §Auth, reusar-antes-de-inventar). A pegadinha dojwks_uri(timeout ~3s + NAT hairpin → falha intermitente, recorrente em produção) já estava documentada; ganhou nota de que vale para os dois modos e de que o self-sign já nasce inline. Ressalva anti-confusão: este M2M ≠ o M2M do broker de setup (lá quem assina é oauth; aqui, o próprio cliente). Engenharia-only, sem bump (powersync.mdnão é rastreada). Decisões do Gustavo (AskUserQuestion): altitude engenharia-only (não subir ao §8) e só a §Auth (sem eco naseguranca.md, que já cobre Kerckhoffs).
0.23.5 - 2026-07-13¶
Adicionado¶
-
engenharia/java-micronaut.md(loop §6, feedback de app — três gotchas de stack Micronaut/Thymeleaf): (a) §Armadilhas — oERROR Failed to inject … jsonMapper (JsonMessageHandler)no fim de uma run multi-classe@MicronautTesté artefato de teardown (o Micronaut derruba o contexto compartilhado e loga a injeção de um bean interno num contexto já desmontado), não bug: se a suíte fecha verde, não caçar — mesmo balde do falso-0% do JaCoCo e do Test Resources órfão. (b) §Armadilhas — Thymeleaf:th:replace/th:insert(precedência 100) rodam antes deth:if/th:unless(300), entãoth:ifno mesmo tag de umth:replacenão segura (o elemento já foi substituído quando oth:ifseria avaliado); cura =th:ifnum elemento pai (ou<th:block>). (c) §Testes — costura para testar controller cuja ação chama serviço com HTTP externo: oHttpClientinjetado por DI (base-url vazia em teste) aponta pro servidor embutido, não pra porta dinâmica do WireMock → teste o serviço com client construído à mão na porta do WireMock e o controller só nos ramos sem rede. Placement de (a) decidido pelo Gustavo (§Armadilhas, a família "parece bug, não é"). Sem bump (java-micronaut.mdnão é rastreada). -
engenharia/java-micronaut.md§Armadilhas (loop §6, feedback de app):recordno modelo do Thymeleaf estouraProperty … not found. Micronaut Views usa o Thymeleaf standalone, cuja linguagem de expressão é o OGNL, que resolve propriedade por getter JavaBean (getFoo()); umrecordgera acessorfoo(), nãogetFoo(), então${obj.foo}falha no render (erro de template, nãonull). Saídas: passar umMapno modelo ou invocar o método (${obj.foo()}). Sem bump (java-micronaut.mdnão é rastreada). Fora (decisão do Gustavo, não normatizado): "preferir cliente REST mão-livre (JDKHttpClient) a@Clientdeclarativo" — é consistência interna de 1 app, não prática da casa (≥2 repos);@Clienté idioma Micronaut válido. -
Constituição 0.18.8 — piso no §6 (Definição de pronto): contrato de entrada entre componentes NOSSOS (skill/cliente → endpoint first-party, ex. o broker
POST /api/setup/provisionque o/xadm-setupconsome) tem os campos obrigatórios travados nos DOIS lados — o cliente declara o contrato e o provedor tem teste que rejeita payload faltante (400 legível, não 500). Sem o par, driftam em silêncio: o guia dizia(app_id, feature), o broker passou a exigir mais → 500 em produção em vários apps antes de alguém notar (loop §6, feedback de app). Distinto do que já existia ("fixture de API externa é capturada, não inventada" = shape de resposta de terceiro; este = contrato de entrada first-party não-verificado no provedor). Detalhe cross-stack emengenharia/ci-testes.md§Definição de pronto (bullet novo, ao lado da fixture capturada); contrato operável do broker emdocumentacao/central-de-apps.md(bloco de identidade doapp.json:app_id,feature,grupo,cliente_id); síntese enganosa(app_id, feature)corrigida no template rastreadoxadm-setup-skill.md(l.47) e no diagrama decentral-de-apps.md. Bump PATCH 0.18.7→0.18.8 (xadm-setup-skill.mdre-carimbado). Handoff para o appauth(§6, Gustavo colar lá): o broker precisa do teste que rejeita/provisionsem os campos obrigatórios. -
engenharia/java-micronaut.md§Erros e logging +engenharia/seguranca.md§Validação de input (loop §6, feedback de app): quando o corpo problem+json carrega umcodede máquina que um consumidor NOSSO ramifica (ex. a Central lê ocodedo broker), esse discriminador tem de ser uniforme para toda a falha da mesma classe — a armadilha é o Bean Validation na borda (@Valid @NotBlank) produzir umcodederivado do status (BAD_REQUESTgenérico) enquanto uma checagem no service produz o code próprio da exceção de domínio, deixando o consumidor com metade das faltas de campo obrigatório num code e metade noutro. Norma: conserte o contrato, não o placement — mantenha o@Validna borda (norma da seguranca) e faça oErrorResponseProcessorde ponto único carimbar umcodeestável também nas falhas de Bean Validation (com a lista de campos). Refina o lado provedor do contrato de entrada travado dos dois lados (item 75): não basta rejeitar faltante com 400 — o 400 consumido por máquina precisa de code uniforme. Sem bump (java-micronaut.md/seguranca.mdnão são rastreadas). Handoff para o appauth(§6, Gustavo colar lá): validar o campo obrigatório de contrato no mesmo lugar que os demais (ou carimbar ocodede máquina no processor também para o Bean Validation) — hoje campos validados na borda saem com code derivado do status, inconsistente com os validados no service que a Central consome. -
engenharia/java-micronaut.md§Armadilhas (loop §6, feedback de app): a armadilha do Test Resources órfão ganha um segundo gatilho além do SIGTERM — rodar o gate com--no-daemone apagarbuild/entre execuções órfã o serviço de TR (sem daemon ele não sobrevive à JVM efêmera; orm -rf build/remove os arquivos de descoberta da porta) → mesma falha "Test resource service is not available" →initializationErrorem massa, que parece bug de código mas é infra. Lado da prevenção: rodar o gate com daemon (default) e nãorm -rf build/no meio de uma sessão de testes; se travar, o sintoma é service not available, não o código. Sem bump (java-micronaut.mdnão é rastreada).
Corrigido¶
engenharia/java-micronaut.md§Observabilidade (loop §6, feedback de app Java): a receita doSentryAppendercolocava o<dsn>flat no appender, mas emio.sentry:sentry-logback8.x oSentryAppendersó expõesetOptions(SentryOptions)—dsné propriedade doSentryOptions, não do appender.<dsn>fora de<options>não casa com setter nenhum e o logback ignora em silêncio (só um WARN no status interno; build verde) → DSN nunca setado → no-op invisível, e o erro real some em produção sem ninguém notar. Corrigido para<options><dsn>${GLITCHTIP_DSN:-}</dsn></options>(o<minimumEventLevel>é setter do appender e segue flat), com a nota do porquê e do porquê a rota/test/glitchtipexiste (pega justo esse buraco). Confirmado na doc oficial do Sentry (logback). Também ajustada a prosa da §Níveis de log que dizia "DSN no próprio appender". Sem bump (java-micronaut.mdnão é rastreada).
0.23.4 - 2026-07-11¶
Adicionado¶
- Constituição 0.18.7 — regra de layout de diagrama no §5: fluxograma Mermaid é
TB(vertical) por padrão. A página tem largura fixa e rolagem vertical infinita, então emTBcada linha usa a largura toda e o texto fica legível sem zoom; emLRo diagrama cresce na horizontal e aperta as caixas. Norma pede labels curtos edirection TBtambém dentro dossubgraph;LR/RLsó para pipeline curto e linear. Enforcement: olint-mermaid.mjs(rastreado) agora falha o build numflowchart LR/RLcom mais de 6 caixas, pedindoTB— escape hatch para o pipeline curto legítimo é um comentário%% lint-mermaid: LR-okno bloco. Bump PATCH 0.18.6→0.18.7. Loop §6 (feedback de app).
0.23.3 - 2026-07-10¶
Corrigido¶
-
Constituição 0.18.6 — o gate de formatação Dart checava reescrevendo: o comando da casa era
dart format --set-exit-if-changed ., e o default dodart formaté--output=write(grava em disco). O gate saía1e consertava os arquivos de passagem — rodar de novo dava verde, o vermelho parecia transitório e a correção ficava não-commitada (ogit adddo release leva só manifesto + CHANGELOG), de modo que o CI, com checkout limpo da tag, reprovava o que "passou" na máquina. Reabria exatamente o furo que a 0.18.5 fechou, e era invisível no CI (checkout efêmero). Agora o comando canônico édart format --output=none --set-exit-if-changed .(Flutter e Dart) em todos os pontos que o enunciam:/xadm-release,/x-implementar(+ reference Flutter),/x-planejar,/xadm-meta-audit-work,ci.yml,analysis_options.yaml,engenharia/flutter.md,engenharia/ci-testes.mdedocumentacao/app-novo.md. Princípio durável novo emci-testes.md§Definição de pronto: verificador não muta a árvore de trabalho — gate é check, nunca fix (vale paraspotlessApply/ktlintFormatdo lado Java; usespotlessCheck/ktlintCheck, que o./gradlew checkjá agrega). Corolário: se o gate mudou arquivo, o gate estava errado. O bloco Flutter do/xadm-releaseganhou também a nota do prefixofvmem repo com.fvmrc(dentro do containerci-flutter:<v>o SDK está no PATH e o prefixo não se usa). Loop §6, app Flutter. Bump PATCH 0.18.5→0.18.6. -
Constituição 0.18.5 — o pré-flight do
/xadm-releaseroda o gate de CÓDIGO da stack, não só o de docs (loop §6, app Java). O template enumerava os gates de docs por nome e tratava o código por uma frase genérica ("rode todos os checks do CI") — e o checkstyle, que só dispara dentro do./gradlew checke não é coberto pela análise estática feita lendo o diff, escapava até o push da tag (CI vermelho com a tag criada, exigindo release de correção). Agora cada bloco de stack em Particularidades traz a linha Gate de código (Java./gradlew check --no-daemon; Flutterdart format --output=none --set-exit-if-changed . && flutter analyze && flutter test; Nodenpm run lint && npm test) e o pré-flight tem dois bullets nomeados — código e docs —, vermelho em qualquer um = bloqueador. Máquina sem Docker/Testcontainers roda o degradado (checkstyleMain checkstyleTest) e o relatório final declara o gate degradado. Eco da norma emengenharia/ci-testes.md§CI de código. Bump PATCH 0.18.4→0.18.5.
0.23.2 - 2026-07-08¶
Adicionado¶
- Constituição 0.18.4 — princípio "fórmula de derivação de token é segredo se não há key separada"
(loop §6 do
auth) emengenharia/seguranca.md§Segredos: se um token de auth é derivável de uma fórmula sem um segredo à parte, a fórmula É o segredo — não vai em javadoc/comentário em claro (quem lê o fonte cunha um token válido = bypass); o certo é Kerckhoffs — derivar por HMAC com a key em env/secret (algoritmo público, só a key secreta). engenharia/flutter.md§Testes — verificação visual headless (loop §6, bi-transporte): a receita de screenshot (kScreenshotMode+ seedInMemoryAppDatabase) dobra como loop de verificação de mudança de pixel — renderizar pro PNG e ler a imagem confirma a mudança sem app rodando.engenharia/flutter.md§Arquitetura (loop §6, bi-transporte): padrão "extrair side-effect de serviço de estado — delegação, não listener". Quando o estado rastreado (intenção do usuário) ≠ oValueListenableexposto (efetivo/derivado, com ajustes automáticos), um listener emite eventos espúrios; o serviço delegaobserver.onChange(prev, next)no ponto da mudança de intenção e move a máquina (buffer/debounce/SDK de analytics) para fora. Ref.FilterAnalyticsObserver.- Constituição 0.18.3 — disciplina "caracterização precede refactor" (loop §6): antes de virar
tarefa de plano um "unificar/deduplicar N classes de mesmo nome", ler os corpos e confirmar a
identidade (caso real: 6 variantes
_Measureque pareciam 1). Emengenharia/ci-testes.md§Definição de pronto e no/x-desenhar(§2 explorar — design-time).
Alterado¶
/xadm-setup(constituição 0.18.4, loop §6 doauth): a nota de auth M2M passa a proibir derivar o token de serviço da fórmula mesmo com o fonte doauthà mão (o filtro de validação à vista) — peça o token ao usuário; computar da fórmula é bypass, não conveniência. Template rastreado → bump PATCH 0.18.3→0.18.4.engenharia/java-micronaut.md(loop §6, refinamentos verificados no integrador): corrige a receita da armadilha Test Resources órfão (era 0.23.1) —./gradlew --stopsozinho não resolve (a taskinternalStartTestResourcesServicefica UP-TO-DATE); o remédio universal é apagar o estado stale (rm -rf .micronaut/test-resources .gradle/configuration-cache). Nova nota no §Guarda de fronteiras: a guarda de arquitetura é bytecode — não vê dependência via constantestatic finalinlinada (limite conhecido, não violação a caçar). Expande a nota configuration-cache-safe (sem capturarlayout/project; ler o ÚLTIMO<counter>do XML do JaCoCo).engenharia/flutter.md§Piso: reforça que os lints de segurança assíncrona (unawaited_futures/cancel_subscriptions/close_sinks) pegaram 3 bugs reais na adoção — ligar cedo (na caracterização), não no fim.
0.23.1 - 2026-07-08¶
Adicionado¶
- Princípio de engenharia "reusar a infra da casa antes de inventar mecanismo" (loop §6): ao
desenhar transporte/gatilho entre serviços, confirmar a infra que já existe (PowerSync acoplado à
fonte da verdade) antes de propor um mecanismo novo — evita decisão auto-contraditória. Em
engenharia/index.md§Princípios. - Constituição 0.18.1 (loop §6) — cobertura de código: política + JaCoCo amarrado ao Java. A
política (visível não bloqueante por norma; piso bloqueante opt-in por app) entra em
engenharia/ci-testes.md§Definição de pronto; a tech emengenharia/java-micronaut.md§Testes, com a pegadinha crítica: JaCoCo <0.8.15 não instrumenta Java 25 (class major 69) → relatório válido na aparência mas vazio (falso 0% silencioso) — amarre atoolVersionao Java (Java 25 → ≥0.8.15) + nota configuration-cache-safe. Novo item de conformidade no/xadm-docs(§3b) checa isso. - Armadilha (loop §6) em
engenharia/java-micronaut.md§Armadilhas: gate morto por SIGTERM órfã um serviço na porta (daemon do Gradle ou Micronaut Test Resources) →initializationErrorem massa na run seguinte; remédio./gradlew --stop+ matar o órfão (e a norma da casa é o container singleton, que o Ryuk reapa). - Constituição 0.18.2 — disciplina de tokens propagada aos apps. O
claude-regras.md(CLAUDE.md que os apps herdam) ganha o ponteiro de gate-discipline (gates bare /rtk err/ sem pipe-git -C-2>&1; a frugalidade-na-fonte é o portável sem rtk) — antes só cobria caveman+enxuto, e o vazamento medido (rtk discover: ~561K tokens/30d) vivia nos apps. Allow-list do central ampliada (rtk read/grep/ls/find/wc/git diff).
0.23.0 - 2026-07-07¶
Adicionado¶
- Constituição 0.18.0 —
cliente_idé a chave canônica do tenant (loop §6, decisão 0008). Desconfla ocliente(rótulo de exibição) docliente_id(chaveclientes.cliente_id, minúscula) que a plataforma vinha derivando do display — a raiz de um incidente. Campocliente_idnovo notemplates/app.json(obrigatório quandogrupo=cliente); a/xadm-setuplê a chave, valida contra o catálogo doauth(fail-closed) e nunca deriva; guarda offline novalida-frontmatter(rejeitacliente_idmalformado — o incidente) com fixtures versionadas (incidente + happy-path); norma em §7 ecentral-de-apps.md. - Constituição 0.18.0 — Plataforma de Integração vira norma central (§8), no molde do §7
(decisão 0007). Nova
seção §8 (norma curta: organiza-se por shape; taxonomia hub/vertical/reator/app consumidor,
ortogonal ao
grupodo §5; owner-writes; transporte por direção; PowerSync bidirecional;bi-commons); página de detalhedocumentacao/integracao.md(4 shapes, fronteiras, transporte); techengenharia/powersync.md(connector, write-back, JWKS inline,edition:3, callback-200); invariante owner-writes no §Banco dojava-micronaut.md; 7 verbetes no glossário (shape, hub, vertical, reator, barramento, owner-writes, bi-commons). O desenho concreto/volátil (roadmap, D0–D13) migrou para aarquitetura.mdpublicada no repo do integrador — a §8/página linkam, não copiam.
Alterado¶
- Deploy do site volta ao auto-deploy do Coolify — o job
deploygated pelo CI (v0.22.0, faixa 3) foi revertido: exigia auto-deploy desligado no painel + os secretsCOOLIFY_WEBHOOK_URL/COOLIFY_API_TOKEN, que não foram configurados (o job falhava no push comsecret ... ausente). Por ora o Coolify auto-deploya no push e a falha do CI avisa no Telegram (webhook nativo da org, Forgejo ≥12); o deploy gated fica como melhoria futura (job comentado nobuild-site.yml; verinfraestrutura/coolify.md).
0.22.0 - 2026-07-06¶
Adicionado¶
-
Faixa 3 da auditoria (constituição 0.17.36): (a) deploy gated pelo CI — o
build-site.ymlganha o jobdeploy(needs: validar, só push em master) disparando o webhook do Coolify; CI vermelho = site antigo no ar (antes o auto-deploy ia pro ar com o CI vermelho; os dois modelos documentados eminfraestrutura/coolify.md; requer auto-deploy desligado no painel + secretsCOOLIFY_WEBHOOK_URL/COOLIFY_API_TOKEN). (b) Fábrica de imagens:build-push.shganha smoke test pré-push (java -version/flutter --version/toolchain da base — imagem quebrada não entra no registry) e isolamento de falha por item (upstream quebrado de uma stack não bloqueia o rebuild das outras; resumo das falhas no fim, exit 1). (c)references/docs.mdnas 5 skillsx-*com references — a stack do próprio central (concerns de entrevista/spec/refino/ plano/execução para repo MkDocs: slug/redirect, dono do fato, satélites, artefato rastreado → bump, gate docs completo); 5 novos rastreados no manifesto. -
CI do central = pré-flight nas duas direções:
build-site.ymlganhoucheca-nav.py(órfão de nav não falha o--strict— foi assim que um órfão real nasceu),valida-frontmatter.py docs/e opublica-versao.py --self-test(grátis, stdlib). sync-apps.sh: guarda de slug ([a-z0-9-]) nos nomes vindos do bucket — a key de escrita é única da org; slug malicioso/acidental com../, espaço ou aspas podia virar traversal no docroot, quebrar o loop ou corromper oindex.jsonde todos os apps./x-documentar: antes de apagar o andaime.ia/, conferegit log -- .ia/NNN-*— arquivo nunca commitado (ciclo inteiro numa sessão) não é apagado, entra no commit do ciclo (senão "o histórico fica no Git" era promessa falsa e o rastro L# se perdia).-
/xadm-release:disable-model-invocation: trueno frontmatter — só o usuário invoca a única skill autorizada a commitar/pushar (fecha o vetor de release não-comandado, REGRA Nº 2). -
Constituição 0.17.31: piso "saída do agente enxuta por default" na §6 — corta prosa conectiva e status óbvio (gate verde não se narra; nomeia-se só o que falhou), não re-descreve o que o diff/tool já mostram nem ecoa a escolha do usuário, e a prosa do fechamento §6 é terse (o literal — commit + linha §6 — não). Nunca comprime o carve-out. Vale com ou sem rtk/caveman. Detalhe e exemplos de mensagens recorrentes em
engenharia/agentes.md(nova seção "Status e fechamento — nomeie só o que falhou").
Alterado¶
- Constituição 0.17.36 — consolidação textual SEM mudança de norma (§6, §1.9, §2): o
bullet "Definição de pronto" (27 linhas, 4 níveis de parênteses) virou 3 sub-bullets
com o racional movido para
ci-testes.md(que ganhou os bullets "deferir é custo × valor" e "fixture capturada" na seção de detalhe); "No CI (código)" enxugado com a fidelidade-ao-artefato apontando pro dono; §1.9 estruturado em 4 consequências nomeadas (andaime / segredo / código×doc / um-fato-um-dono); §2 ganhou subseções navegáveis (livro, nav+resumo, conteúdo mínimo); o cabeçalho deixou de prometer "documento curto e estável" e passou a dizer o que é (o piso; detalhe nas áreas). -
engenharia/flutter.md§Específico reorganizado por tema (Build e versão do SDK / Config e Central de Apps / Observabilidade / Receitas) — era sedimento de feedbacks; bullets intactos. -
Faixa 2 da auditoria — o "miolo do código" vira norma escrita (constituição 0.17.35; destilado dos pilotos com leitura autorizada: auth, bi-transporte-xls, bi-comercial-xls, bi-transporte, bi-comercial, authui):
- Arquitetura v0.1 por stack:
engenharia/flutterganha §Arquitetura (layout feature-first, taxonomia de DI get_it/watch_it com lazy+dispose+dependsOn, estado no manager como valor observável, command_it, como nasce uma feature, variações declaradas) eengenharia/java-micronautidem (package-by-feature travado por ArchUnit, constructor injection puro, controller fino, record @Serdeable vs @MappedEntity, @ConfigurationProperties, nomes pt-BR citando decisões). - Erros e logging por stack: exceção tipada na borda + erro-como-valor + trio loading/vazio/erro + AppLog com breadcrumbs/tags (Flutter); HttpStatusException + RFC 7807 num ponto único + semântica ERROR/WARN/INFO consciente do SentryAppender + logback com tuning comentado (Micronaut). Gap de request-id declarado como pendência, não fingido como prática.
- Testes e fixtures: convenção golden-master datada com receita de captura no javadoc e anonimização obrigatória; WireMock com shape capturado (§6); Testcontainers com container compartilhado pinado à versão do deploy; unit×integração por environment (Micronaut) — e in-memory DB com DDL de produção, builders, seams nomeados, pushNewScope, teste de contrato do app.json (Flutter).
engenharia/seguranca.md(nova página): authn/authz fail-closed com tri-estado, tenancy pela claim (servidor decide), comparação em tempo constante, validação jakarta obrigatória em request novo, client-grade ≠ segredo, checklist do revisor.- Banco (Postgres compartilhado) em java-micronaut: Flyway
VN__pt_brcom história nomeada por app e destrutiva justificada; pool Hikari deliberadamente pequeno (o Postgres é compartilhado); CRUD via Micronaut Data + bulk via JDBC manual. - Gate Dart completo:
templates/analysis_options.yamlcanônico (novo rastreado, flutter_lints + regras de segurança assíncrona do piloto) edart format --set-exit-if-changed .no gate Flutter/Dart (ci.yml, páginas, skills x-planejar/ x-implementar/meta-audit — a varredura de satélites do 0.17.34 pegou os 5 pontos). -
Teste de regressão do valida-frontmatter: fixtures versionadas (
scripts/fixtures-valida-frontmatter/, 10 casos) +testa-valida-frontmatter.pyno CI e no pré-flight da release — era o script de maior blast radius sem cobertura; de quebra, frontmatter com YAML quebrado agora vira erro legível em vez de traceback. -
Constituição 0.17.34 — dois pisos de token viram norma escrita (pedido do Gustavo): (a) §6 (Regras de IA): o CLAUDE.md, além de roteador, é carregado inteiro em toda sessão — backlog/histórico concluído migra para arquivo-acervo não carregado (padrão
BACKLOG-HISTORICO.md; caso medido no central: −15k tokens/sessão); (b) §6: a saída do agente é tersa (estilo caveman) por default — telegráfica no chat, com carve-out explícito que agora inclui conteúdo de documentação (texto emdocs/sai em prosa normal pt-BR, §1.8) além da mensagem de commit, código, linha §6, tabelas e.ia/. Ecos: carve-out deengenharia/agentes.mdganha o item documentação; comentário dotemplates/claude-regras.md(rastreado, recarimbado) carrega os dois lembretes para os apps. -
Constituição 0.17.33 — §6 enxuto em tokens: os dois bullets operacionais de rtk/caveman ("saída enxuta" e "disciplina de tokens") encolhem para o piso + ponteiro; o como (envelope
rtk errnos gates, comando bare, exemplos de fechamento) já tinha dono emengenharia/agentes.mdeengenharia/ferramentas.md(um fato, um dono, §1.9). Norma inalterada. -
CLAUDE.md do central em dieta: o histórico do backlog (itens 0–52) migrou para
BACKLOG-HISTORICO.md(acervo, não carregado pelo Claude Code) — o CLAUDE.md era ~20k tokens carregados em toda sessão, ~85% histórico; fica com regras + contexto + pendências + itens recentes (~7k). Ganha também: bloco TOKENS (gates viartk err, comando bare), regra de migração contínua (>~10 itens → histórico) e a varredura de satélites no §8 (bump da constituição → conferir glossário/templates/publicar-docs/ app-novo/ia/READMEs — trata o candidato §6 da rodada anterior: o manifesto protege os artefatos copiados, as páginas do site só têm essa varredura). -
Constituição 0.17.30: o pré-flight do
/xadm-releasedeixa claro que worktree limpo com commits à frente do origin é o caso NORMAL — a IA não commita (REGRA Nº 2), então o conteúdo da sessão é commitado pelo usuário e o release apenas segue, sem auditar a autoria dos commits à frente. Evita o falso alarme de "commit que eu não fiz" no início do release. Tocado o template rastreadoxadm-release-skill.md(+ cópia instalada).
Corrigido¶
- Constituição 0.17.32 — rodada de reconciliação de drift (auditoria interna do central,
4 pareceres): (a)
templates/xadm.cssre-derivado da fonte do site — a cópia distribuída ainda carregava navy/burgundy, paleta que o logo real não tem (a vigente é azul royal#064490+ prata; comentários stale emtemplates/mkdocs.yml,mkdocs.ymletemplates.mdcorrigidos juntos); (b)templates/docs.ymlpasso versions.json usava o placeholder<app>hardcoded em vez de"$SLUG"(contradizia a fonte única do slug e quebrava o 1º release versionado do app); (c)templates/anexos-readme.mdprometia guarda extinta ("o CI bloqueia massa de dados") — agora diz a regra real (validador só bloqueia emdocs/public/; fora deprivado/publica, responsabilidade do autor); (d)xadm-meta-audit-workrealinhada ao pipeline atual — auditava a extinta/xadm-work(estágios*_phase, exigia mensagem de commit que o run concluído corretamente NÃO entrega desde a ordemimplementar → documentar → commit); (e) instrução de instalação de skills unificada (app-novo diz 10 core incluindoxadm-setup;templates.mdganhou a linha/seção da/xadm-setupe aposentou os nomes pré-renamespec/refine/plan/work;ia.md§Como adotar delega ao manifesto em vez de mandar copiar só 2); (f) exemplos que ensinavam errado:app.jsondepublicar-docs.mdsemaptabase_host(o contrato corrigido no 0.17.23),templates/app.jsoncom Flutter 3.35.0 fora da baseline (gate do release barraria),templates/riscos.mdcom nomenclaturaPROJ-legada, glossário 2 reorgs atrás (manual como nível 4,superado-por:sem aspas — formato que o validador rejeita) e estrutura legada (manual/,img/) empublicar-docs.md.
0.21.0 - 2026-07-04¶
Adicionado¶
- Constituição 0.17.29: §6 (No CI/código) ganha o piso "o gate é fiel ao artefato que
embarca" —
testroda no classpath, mas o que sobe é o fat jar/container; ordem, descoberta e configuração podem divergir (merge deMETA-INF, native-image, shading). O default é eliminar a divergência (determinismo/paridade), não "smoke em prod"; só onde a divergência é inevitável o gate exercita o artefato empacotado (sobe o jar/container e bate num endpoint). Detalhe do "como" emengenharia/ci-testes.md; regra concreta de stack (@ServerFilterhonra@Order,@Filterlegado não → ordem indefinida no fat jar) emengenharia/java-micronaut.md. Feedback §6 de app Micronaut. - Gate
toolchain ∈ baseline da fábrica: amatriz-baseline.jsonpassa a ser publicada em/toolchain/matriz-baseline.json; o pré-flight do/xadm-releasebloqueia e o/xadm-docs3b avisa cedo quando um app declara versão de stack (app.json/.fvmrc) não homologada na fábrica — pega o "manifest unknown" antes da tag, não mais só no 1º release (constituição 0.17.28, decisão 0003).
0.20.0 - 2026-07-04¶
Alterado¶
- Constituição 0.17.24: o passo analytics do
/xadm-setuppergunta o arquétipo do app (produto vs interno/admin) antes de sugerir eventos — produto mantém o baseline de product-analytics; interno/admin passa a mirar a ação sensível (quem fez), e não screen_view/retenção. Adicionado o caveat de que evento client-side é visibilidade operacional, não audit trail (auditoria de verdade pertence ao backend). Espelhado emcentral-de-apps.md. - Guia de IA (
transversais/ia.md): seção opcional de otimização de custo de tokens — ferramentas de arquivo/busca em vez de despejo de shell, comunicação enxuta onde não custa clareza, e ferramentas pessoais opcionais que o agente pode oferecer (nunca impor). - Constituição 0.17.25: higiene de saída de comando — nova seção em
engenharia/ci-testes.md(corte o verboso na fonte; reporter frugal sempre; nativas de arquivo sobre shell; proxy é complemento) + comando frugal por stack (flutter test -r failures-only,./gradlew test --quiet --console=plain, …) nas páginas de stack, e a §6 afirma que o gate roda com reporter enxuto (verboso só sob falha). - Nova página
engenharia/agentes.md(Trabalho com agentes de IA): consolida a disciplina de tokens do agente — input frugal (link p/ ci-testes) + output terso + carve-out verbatim (nunca comprimir: código, mensagem de commit, linha §6, tabelas de dado,.ia/). O estilo terso vira prática recomendada via hookSessionStart(caveman.sh, mesmo padrão do checa-constituicao; funciona sem plugin); passo no checklist de app novo.transversais/ia.mdreconciliada. Sem bump (só doc/engenharia, não rastreadas). - Nova página
engenharia/ferramentas.md(Ferramentas de token — rtk): o rtk (proxy que resume a saída de CLI antes do contexto) vira recomendação da casa — install/verify, habilitar (hookrtk hook claude), configurar como padrão (ignore_dirspor stack, tee em falha) e regras por stack (Gradle bare sem pipe +sdk default javap/ dispensar o prefixoJAVA_HOME=que fura o hook;gitbare sem--porcelain; nativas sobrecat/find; rtk não cobreflutter). Reconcilia o conflito| tailda norma frugal (flags de reporter ficam; pós-processamento com pipe cede ao bare+rtk).ci-testes.md/agentes.md/ia.mdreconciliadas. Sem bump (não rastreada). engenharia/ferramentas.mdpassa a cobrir rtk (input) + caveman (output) como ferramentas recomendadas simétricas, cada uma com install/habilitar/configurar. Install real por plataforma dos repos oficiais (rtk-ai/rtk: brew/curl/cargo/Windows +rtk init -g; juliusbrussee/caveman: plugin do Claude Code / instalador universal). A receita do hookcaveman.shmigrou deagentes.md(que ficou com o princípio + carve-out e aponta pra cá). Sem bump (não rastreada).- Constituição 0.17.26: auto-análise de uso das ferramentas de token no fechamento §6. A §6 e a
skill
/x-documentarganham o passo (condicional a usar rtk/caveman): ao fechar, o agente mede (rtk gain/rtk discover; caveman = qualitativo), auto-corrige (bare/nativas/terso+carve-out) e roteia o gap sistêmico — recipe de stack → §6 (outros apps aprendem); comando verboso sem handler nativo → envolver comrtk err/rtk summary(ajuste de uso, resolve a maioria), RTK tracker só o residual. Nova seção "Auto-análise" emengenharia/agentes.md+ hook opcional levetoken-check.sh(eficiência dortk gainno start); passo noapp-novo.
0.19.5 - 2026-07-04¶
Alterado¶
-
Client_grade de analytics inclui
aptabase_host(Aptabase self-hosted) (constituição 0.17.23; feedback §6). A keyA-SH-self-hosted é inútil no cliente sem o host — o SDK Flutter exigeInitOptions(host:)(≠ do DSN do GlitchTip, que já embute o host). Sem isso o/xadm-setuptinha que hardcodar/adivinhar o host e gravá-lo à mão noapp.json(sujeito a clobber num re-provision). Agora o client_grade =aptabase_key+aptabase_host;central-de-apps+xadm-setupatualizados. Handoffauth: oAptabaseProviderdevolveaptabase_hostno client_config. -
Metabase organiza por sub-pasta (
grupo/cliente → app_id → dashboard + cards) (feedback §6 — oauthimplementou, decisão 0014). Antes o central documentava dashboard+cards soltos numa collection (exigia sufixar os cards comapp_idpra não colidir). Agora cada app ganha uma sub-pasta (collection filha, nome =app_id) dentro da collection do grupo/cliente, contendo o dashboard + os cards com nome canônico (sem sufixo, já isolados). Espelha oapp.json.central-de-appsatualizado; andaime.ia/016-*apagado (feature pronta). Sem bump (docs page). -
§6: fixture de API externa é CAPTURADA da instância real, não inventada (constituição 0.17.22; feedback §6). Um teste (ex. WireMock) verde sobre um shape fabricado é falso atestado — o mesmo "validador stale = falso 0 erros" que o §6 já combate, aplicado a fixtures de API (quebrou 2× em prod: Aptabase e Metabase, com
app_key/id:-1inventados). Agora a §6 (norma) e ox-documentar(§3 auditoria de lacuna) exigem: fixture de API externa capturada da instância real, e provider de API externa só marca "ligada" com ≥1 resposta real capturada. -
/xadm-release: pré-flight roda o build de docs + CHANGELOG sem link relativo (constituição 0.17.21; feedback §6). (1) Referência no CHANGELOG = texto puro ou URL absoluta, nunca[texto](docs/…)relativo — oCHANGELOGé embutido emdocs/via snippet, o link viradocs/docs/…e quebra o--strict. (2) O pré-flight roda o BUILD de docs que odocs.ymlroda (mkdocs build --strictcom hooks +javadoc/dartdoc) — um gate de infra vermelho (dind) mascara os gates seguintes no CI, então rodá-los local evita descobrir em prod. -
/xadm-docs: relevância por stack (evita falso-positivo domudou_emstack-cego) (constituição 0.17.20; feedback §6). Omudou_emdo manifesto é por-arquivo-global, não por-stack — uma mudança Java-only (ex.ci.ymlTestcontainers) marcaci.ymldefasado em app Flutter. Agora o/xadm-docs, para arquivo multi-stack customizado-por-app (oci.yml, cujo diff verbatim é esperado), manda checar a entrada do CHANGELOG da versãomudou_empara ver se a mudança toca a stack do app — se não toca, não é defasagem pra ele (mantém a customização). Decisão: guidance, não campostacks:no manifesto — oci.ymlé multi-stack, e umstacks: [java]esconderia updates Flutter-relevantes (nav-check etc.).
Corrigido¶
ci.ymlTestcontainers:DOCKER_HOSTvia runner, nãodocker.sock(topologia dind isolado) (constituição 0.17.19; feedback §6 — corrige o v0.19.4). O DooD pordocker.sockque saiu no v0.19.4 não funciona no runner da org (act_runnercom dind privilegiado → o mount do socket do host vira "not a valid volume"), e todo@Testcontainersfalha no CI. Fix org-wide mantendo o isolamento: oconfig.yamldoact_runnerinjetaDOCKER_HOST=tcp://172.17.0.1:2375(gateway do dind) +TESTCONTAINERS_HOST_OVERRIDE+RYUK_DISABLEDnos jobs → otemplates/ci.ymlfica agnóstico (removido odocker.sock). Detalhe/config emforgejo.md. Pendência do Gustavo: configurar oact_runner.
0.19.4 - 2026-07-03¶
Alterado¶
-
Definição de pronto (§6): deferir teste é custo × valor, não racionalização (constituição 0.17.18; feedback §6). "Exercitado end-to-end" e "baixo risco" são justo as frases que deixam a guarda de regressão barata escapar — sobretudo em segurança/privacidade/contrato. Agora a §6 (norma) e as skills
x-implementar/x-documentarexigem, por lacuna de teste, uma classificação explícita custo × valor: default = escrever a guarda barata e proporcional agora; só deferir no quadrante caro E de baixo valor; comportamento sensível → escrever a guarda agora. Bump 0.17.17→0.17.18 (as duas skills rastreadas + §6). -
Fluxo do pipeline:
/x-implementar → /x-documentar → commit(constituição 0.17.17). O/x-implementar, ao concluir o plano, deixa de entregar a mensagem de commit — aponta pro/x-documentar, que faz a revisão geral (avalia lacuna de doc e de teste, §6), destila o durável pradocs/, apaga o andaime (.ia/NNN-*) e entrega a mensagem de commit do ciclo. Antes o commit era sugerido nox-implementar; agora o ciclo fecha nox-documentar. Bump 0.17.16→0.17.17 (as duas skills rastreadas +ia.md). -
Feedback §6 (docs de engenharia/central): paleta por grupo, receita de screenshots, gotchas, formas de provider — sem bump (engenharia/documentacao não são rastreadas). (1) A paleta do cliente passa a ser gatilhada pelo
grupo: clientedoapp.json(marca derivada do logo do cliente), não mais o "veste a marca declarado" do #31 — mais simples (engenharia/flutter). (2)screenshots-manualganha o seed com DDL do schema PowerSync + o gotcharegisterSingletonAsync. (3) gotcha doink_sparkle.fragem bump de SDK (flutter clean+pub get) emengenharia/flutter. (4)central-de-appsdestila as três formas de provider (find-before-create / forjar-token / reuso-persistido) ejava-micronautganha 2 armadilhas REST (PUTsubstitui coleção → read-modify-write; nomear por escopo em container compartilhado). -
Check de nav-drift (
checa-nav.py) no gate de código (constituição 0.17.16; feedback §6). Num repo stack+MkDocs o gate de código não roda mkdocs → um.mdnovo fora donav:só estoura nodocs.yml(que não roda a cada PR de código) e órfãos acumulam (o app relatou 3 decisões + 1 runbook órfãos por 2 fases). Novoscripts/checa-nav.py(stdlib): FALHA se um.mddedocs/não está nonav:nem excluído (isentaREADME.mdde pasta); rodado ativo noci.yml(tolerante semdocs/), publicado como os outros validadores. §6 esclarecida: "doc do estado atual" inclui aparecer no índice, não só existir. Dogfood: pegou odecisoes/0006órfão no próprio central (corrigido no nav). -
Constituição §2: provider automagico não precisa de runbook de "como usar" (constituição 0.17.15; feedback §6). O que roda sozinho (ex. provider build-time da Central de Apps — "como usar" = a skill, "porquê" = a decisão) não ganha runbook; sobra config-de-operador (envs + como obter) + diagnóstico, numa seção "Operar" da própria decisão, não num runbook que duplica o design. Os runbooks
provedor-*.md(noauth) morrem — cleanup doauth(handoff). -
Auto-config do Metabase no
/xadm-setup— fatia do central (constituição 0.17.14; feature 016, desenhada via/x-desenhar→/x-definir→/x-refinar→/x-planejar→/x-implementar). Depois do Aptabase, o broker auto-configura o Metabase (API real):collection(cliente) → dashboard(app) → cards baselineque adaptam aos eventos escolhidos; idempotência por id estável; resposta honesta com sub-estadosaptabase+metabase; 6 queries ClickHouse = template canônico no broker; gravametabase_dashboard_id(pro embed futuro).central-de-apps(provider analytics) +xadm-setup-skill(passo). A implementação do broker Metabase é do repoauth(handoff). -
Rota de diagnóstico
/testno baseline de observabilidade (opt-in) (constituição 0.17.13; feedback §6). Verificar pós-deploy que o erro chega no GlitchTip era improvisado por app; agoraengenharia/flutter(tela oculta login-gated com botão "enviar exceção de teste") eengenharia/java-micronaut(endpoint autenticado/test/glitchtip) trazem a receita, e o/xadm-setupoferece scaffoldar (opt-in, com o OK do dev) junto da instrumentação. Não obrigatório (backend/cron não é forçado a ter UI de diagnóstico). -
Aptabase no
/xadm-setup: provisão full-auto forjando o token (sem API) (constituição 0.17.12, mecanismo corrigido em 0.17.15; feedback §6 de um app). O Aptabase self-hosted não tem API e autentica por sessão. Descoberto empiricamente (decisão 0013 doauth): o token é um JWT simétrico (HS256) assinado com o secret do próprio tool → o broker forja o token (secret no env doauth) e abre sessão direto, depois cria o app →A-SH-…. (O "magic-link dos logs do Coolify" não funciona — o Coolify não expõe logs de service.) É o padrão "provider sem API → forjar o token"; guardas: fail-fast, versão fixada, secret forja sessão de qualquer usuário. Ocentral-de-appsdocumenta o fluxo + o padrão; o passo do/xadm-setuppassa a perguntar ao dev quais eventos registrar e scaffolda o helper só para os escolhidos. -
Ponte
app.json→--dart-defineno build Flutter-web +/xadm-setuphonesto (constituição 0.17.11; feedback §6 de um app Flutter-web da Central de Apps). O/xadm-setuppasso 5 assumia que "o Dockerfile/CI já lê oapp.json", mas o scaffold hardcodava ARGs e nem tinhajq.engenharia/flutterganha a receita concreta (instalarjq+flutter build … --dart-define= $(jq -r .features.<x>.<ref> docs/app.json)) e reconcilia "config no repo" (=app.json+ ponte, não hardcode; client-grade não precisa de build-arg do Coolify — só segredo). O passo 5 passa a mandar garantir/criar a ponte (aponta pra receita), não "confira que já existe". -
Identidade visual: app que veste a marca do cliente usa a marca do cliente, não a da casa (feedback §6 do bi-comercial/OnPetro). A
engenharia/fluttertratava "paleta = a da casa" como absoluto; agora a identidade da casa é o default (app da X-Adm / app de cliente sem marca própria) e um app exclusivo que veste a marca do cliente usa a paleta/logo/tipografia do cliente (declarado noapp.json). O gatilho é vestir a marca do cliente, não o merocliente:; o mecanismo da casa (tema porColorScheme, app-icon, feature-first) segue valendo em todo app. Sem bump (engenharia é regra viva, não rastreada).
0.19.3 - 2026-07-03¶
Corrigido¶
checa-dogfood.pyreconhece skills em diretório (destrava o deploy do v0.19.2). O gate de CI comparava.claude/skills/<nome>/SKILL.mdsó comtemplates/<nome>-skill.md(plano) e acusava as 6x-*(modelo diretório) como "sem template canônico" → jobvalidarvermelho → deploy travado. Agora compara o diretório inteiro (SKILL.md +references/) para asx-*e mantém o modelo plano para asxadm-*.
Alterado¶
- Pré-flight do
/xadm-releaseroda todos os checks do CI (constituição 0.17.10; feedback §6 do incidente acima). O gate local rodava sólint-mermaid+gera-manifesto --check+valida-frontmatter, mas o CI roda tambémcheca-dogfood.pyecheca-export-download.py— por isso o drift passou no pré-flight e só estourou no CI depois da tag pushada. O §1 agora manda rodar todos os checks do CI do repo (condicional "se o repo os tiver", pois são central-only).
0.19.2 - 2026-07-03¶
Adicionado¶
- Recipe GlitchTip/Sentry para Micronaut e armadilha
@Consumesem endpoint de<form>na páginaengenharia/java-micronaut.md(feedback §6 doauth). Sentry viaio.sentry:sentry+sentry-logback(SentryAppendernologback.xml,minimumEventLevel=ERROR, DSN vazio → no-op, zero código no negócio; espelha o bloco Flutter).@Consumes:@Postassume JSON → 415 em formx-www-form-urlencoded; armadilha de teste (oHttpClientmanda JSON por default).
Alterado¶
-
Contrato do
/provision(Central de Apps): injetar APLICA a config (reinicia), não só grava (constituição 0.17.9; feedback §6 doauth). Env upsertado não recarrega em processo vivo → o broker reinicia o recurso Coolify ao injetar, einjected:truepassa a significar "injetado E em vigor"; reinicia só quando o valor mudou (lê o atual + compara), pra não derrubar serviço sensível (auth) à toa em re-run. Provado noauth(decisão 0011). -
templates/ci.ymlJava dá Docker ao Testcontainers (DooD) (constituição 0.17.9; feedback §6 doauth). O jobcontainer: ci-javanão montava o socket do host → todo@Testcontainers(padrão da casa p/ "banco real") falhava no CI com "could not find a valid Docker environment", deixando o gate §6 "No CI (código)" vermelho crônico. Correção:container.volumesmonta/var/run/docker.sock; pré-requisito do runner (act_runnervalid_volumes) documentado eminfraestrutura/forgejo.md.TESTCONTAINERS_RYUK_DISABLED=truejá vinha no ambiente, mas não bastava — faltava o socket. -
Skills de workflow renomeadas e realinhadas ao ACT 1.0 (constituição 0.17.8). O pipeline
spec → refine → plan → work → compoundviroux-desenhar → x-definir → x-refinar → x-planejar → x-implementar → x-documentar, adotando o split entrevista/spec do ACT 1.0 (x-desenhar conduz a entrevista e grava o prompt.ia/NNN-*-prompt.mdcom o rastro L# embutido; x-definir escreve a spec referenciando os L#), tarefa = corpo de Work Item embarcado no plano, e especialização de stack viareferences/<stack>.md(Flutter portado do ACT + Micronaut autorado) carregada pelo §0 — sem variantes-skill. Preserva os invariantes da casa (NÃO commita, §0, gate da stack, §6, ghost mode, lineage.ia/, storage.ia/sem.act/). Cada skill agora é um diretóriotemplates/<nome>/(SKILL.md +references/). Manifesto,gera-manifesto.py,xadm-docse as referências (CLAUDE.md, ia.md, constituição, app-novo, templates.md, engenharia) atualizados. Apps migram oportunisticamente via/xadm-docs. Verdocs/decisoes/0006-skills-workflow-act1.md. -
Constituição 0.17.7 — "idempotente" = procura-antes-de-cria (feedback §6: dois projetos com o mesmo nome no GlitchTip). O contrato dizia só a palavra "idempotente", que a implementação leu como cria-depois-procura — e como o GlitchTip permite nome duplicado, um re-run (ou falha no find + nova chamada) duplicou o projeto. central de apps §Provedores agora define o mecanismo: o provider checa se o recurso já existe (por nome/
app_id) e reusa, nunca cria às cegas; onde o provedor permite nome duplicado, o find é obrigatório. O guard find-before-create em si é Camada 2 (auth — o377c050corrigiu o find). Bump PATCH 0.17.6→0.17.7. - Constituição 0.17.6 —
/provisionresponde estado real +/xadm-setupinstrumenta o código (feedback §6 da implementação doauth). Três furos: o/provisionrespondia 200 comenabled:truesemdsnquando o provider falhava (indistinguível de sucesso); a injeção no Coolify falhava em silêncio (best-effort, só WARN — token 401, DSN não injetado, ninguém soube); e o setup ligava a integração sem instrumentar o código. Correções em central de apps: a resposta do/provisioncarrega o estado real por provider — provisão (state/last_error) e injeção (injected+ motivo), com não-2xx se nada ligou; o/xadm-setupconfere e não gravaenabledsem o ref, avisa eminjected:false(setar o env à mão) e não re-chama provision "pra confirmar" (isso gerava projeto GlitchTip duplicado). E a skill passa a instrumentar o código (scaffold + guia, com OK do dev): instalar o SDK, envolver orunApp(SentryFlutter.init), guiar os pontos de captura — recipe emengenharia/flutter. O guard find-before-create do provider é Camada 2 (auth). Bump PATCH 0.17.5→0.17.6. - Constituição 0.17.5 — convenção: projeto GlitchTip nomeado pelo
app_id(feedback §6 da implementação doauth). O slug do projeto GlitchTip é sempreslugify(nome)(oslugdo corpo é ignorado, imutável por PUT) e odsnusa o id numérico, não o slug. Convenção registrada na skillxadm-setup(passo glitchtip) e em central de apps §Provedores: o broker nomeia o projeto peloapp_id(slug estável e curto), decorrência doapp_idcanônico. A trivia da API do GlitchTip (slug ignorado no corpo, PUT, DSN por id) fica noGlitchTipProviderdoauth(Camada 2), não no contrato central. Bump PATCH 0.17.4→0.17.5. - Identidade visual reconciliada com o logo + norma visual pra apps Flutter (feedback §6). O
xadm.cssafirmava paleta "extraída do logo", mas oxadm-logo.pngé azul royal + prata, sem o burgundy#8b3a3adocumentado (verificado amostrando o PNG). Decisão do Gustavo: derivar do logo real — a paleta da casa passa a ser azul royal#064490(primária) + médio#2a5b97(accent) / claro#7092bb/ escuro#042c5e+ prata#939495(neutro); sai o navy/burgundy.docs/stylesheets/xadm.cssvira a fonte-da-verdade dos tokens (docs e apps consomem), eengenharia/flutterganha a seção Identidade visual (paleta→ColorScheme, logo + receita de app-iconflutter_launcher_icons, tipografia/densidade como decisão). OThemeDatacompartilhado, o kit mínimo de componentes e a variação quadrada do logo ficam para uma spec do padrão de identidade visual de apps (barato agora, resto na spec). Sem bump da constituição (docs/assets, não artefato rastreado). - Constituição 0.17.4 — broker de setup autentica por token de serviço (M2M) (feedback §6 da
implementação do
auth). O contrato pressupunha login humano (JWT xadm admin/Firebase) pra chamar o/api/setup/**— mas é endpoint máquina-a-máquina (o/xadm-setup), e nenhum CLI tem como obter esse JWT (loopback-OAuth inexistente). Agrava que o/provisionrecebeproduction_urle injeta env no recurso Coolify → num endpoint aberto, a auth importa de verdade. Nova norma (§7 + central de apps seção "Auth do broker de setup" +xadm-setup-skill): token de serviço, com força casada à exposição (interno/VPN → simples; público → segredo forte ou rotativo por HMAC-de-data, nunca fórmula pública); a regra de geração vive fora de banda (servidor + admins), jamais na skill ou em doc publicada — a skill conhece só o formato e pede o valor. Registra o gap "como obter a credencial de setup". Bump PATCH 0.17.3→0.17.4; manifesto regenerado (xadm-setup-skill). - Constituição 0.17.3 — Central de Apps: injeção de config (não só secret) e web ≠ server
(feedback §6 da implementação do
auth). A tabela "duas naturezas" juntava web/server e dizia que o client-grade vai como build-arg — só vale pra web (bundle). Um app server lê config do env em runtime, então o client-grade dele (ex.SENTRY_DSN) também é env injetada no Coolify, não build-arg. Correções em central de apps: linguagem "injeção de secret" → "injeção de config" (client-grade + secret); tabela com colunas web / server / mobile; checkpoint de deploy garante a config (não só secret); ponteiro pro endpoint de env do Coolify. Bump PATCH 0.17.2→0.17.3. (Mantido o modelo de 3 checkpoints — não adotada a opção de dobrar a injeção no/provision.)
0.19.1 - 2026-07-01¶
Corrigido¶
- Diagrama Mermaid da Central de Apps + lint no gate local. O
sequenceDiagramdecentral-de-apps.mdtinha um;numa mensagem (separador de statement no Mermaid) que quebrava olint-mermaiddo CI e travava o deploy desde o push do build-time — sem aparecer em nenhum check local, porquemkdocs build --strictnão parseia diagramas. Corrigido o;; e o lint de Mermaid entra no gate local (constituição 0.17.2):/xadm-worke/xadm-plan(verify docs), pré-flight do/xadm-release(bloqueia antes de taggar) e o gate docs documentado em ci-testes. Bump PATCH 0.17.1→0.17.2; manifesto regenerado (skills work/plan/release).
0.19.0 - 2026-07-01¶
Adicionado¶
- Constituição 0.17.0 — Central de Apps (Camada 1, paradigma BUILD-TIME). Nova
## 7+ central de apps: a integração de um app com a infra X-Adm (erros/GlitchTip, arquivos/Garage, analytics Aptabase+Metabase, docs) é configurada em build-time, não amarrada em runtime. O app declara noapp.json(featuresvira objeto por funcionalidade); a skill nova/xadm-setup(entre codar e/xadm-release) pergunta o que ativar, provisiona via oauth-broker (que tem os tokens admin) e grava o resultado client-grade noapp.json— o build embarca, sem buscar config no boot. Runtime só o mínimo: corretores (embed Metabase/presign Garage) e feature flags (protocolo próprio — spec 014).auth= broker + configurador de secrets (Coolify/CI) + corretor;central.xadm.biz= dashboard (mostra o configurado + links, aprova acesso de terceiros). 3 checkpoints (setup → guard soft na/xadm-release→ guard de deploy noci.yml); 2 naturezas × plataforma (client-grade web=build-arg / mobile=--dart-define; secret web=Coolify / mobile=org-CI); fronteira de dados (auth×app;cliente_idclaim×FK). Tocados:templates/app.json(featuresobjeto),valida-frontmatter.py(rejeita chave desconhecida), skillxadm-setupnova, guard soft naxadm-release, placeholder de deploy noci.yml, ecos em publicar-docs/app-novo/flutter; Bugsink→GlitchTip reconciliado (grep=0). Bump MINOR 0.16.1→0.17.0. Substitui o desenho runtime anterior (não shipado). Camada 2 (código auth/central/apps) + feature flags (014) em specs próprias.
Alterado¶
- Constituição 0.17.1 — corretor autoriza por app + provisão por
app_id(achados do plano de implementação da Camada 2 noauth). O contrato do corretor exigia só JWT válido (autenticação); agora a §7 e central de apps exigem autorização por app — o claim do JWT casa com o app do recurso (403 cross-app): usuário logado no app A não cunha embed/presign de recurso do app B. E a §Catálogo separa provisão (porapp_id) de acesso (por (cliente, app), derivado dosoauth_access_grants) — não há tabela de pares para a provisão. Bump PATCH 0.17.0→0.17.1 (só docs de padrão; nenhum artefato rastreado mudou). - Constituição 0.16.1 — migração de conteúdo cross-repo + template×piloto (feedback §6 do
authui). A regra de migração só cobria conteúdo do próprio repo (
guias/por conteúdo); agora a §3 e a/xadm-docsdizem que doc/runbook que pertence a outro repo, achado neste, é realocado para o repo dono — não absorvido/relabelado nooperacao/local. E oapp-novo.mdesclarece template × piloto: o template (sincronizado via manifesto) é a única fonte de cópia; o app piloto/de referência é exemplo provado/destilado (Engenharia), nunca base de cópia. Bump PATCH 0.16.0→0.16.1; manifesto regenerado. - Constituição 0.15.3 —
/xadm-refine-speccom passada de contexto profunda. O refine da casa confirmava que os artefatos existiam, não que os fatos afirmados sobre eles eram verdadeiros — então não pegou o que o refine nativo do ACT pegou (ex.:app.jsonreal semslug,app_iddivergente, conflito de audiência doauthui). Correções no template e na cópia instalada: §1 vira passada profunda (ler o conteúdo de cada referência; conferir cada fato contra o artefato real; mapear tabelas/endpoints/identidade/namespaces; rastrear uma instância real ponta a ponta; e, se paralelizada, fazer isso UMA vez antes das dimensões); dimensão 2 cobra "fato conferido LENDO o artefato"; e uma lente transversal do implementador ("se eu fosse construir isto agora, onde travaria?"). Bump PATCH 0.15.2→0.15.3 (artefato rastreado mudou); manifesto regenerado. - Doc de infra — endpoint de env/secret da API do Coolify. O
coolify.mdpassa a documentar oPATCH /api/v1/applications/{uuid}/envs/bulk(upsert em lote, Bearer; "Secret" = env marcada como Secret, não um tipo à parte; flags Build/Runtime) que o guard de deploy da Central de Apps usa para injetar os secrets de build — tira a Fase 4 do broker noauthdo "spike do zero" (fato verificado na doc oficial do Coolify).
0.18.3 - 2026-06-30¶
Corrigido¶
- Constituição 0.15.2 — desambiguação versão-do-site × versão-da-constituição. Um app
em bootstrap (sem
/xadm-docsinstalada, só com o link da constituição) ficou em dúvida entre0.15.1(constituição) e0.18.2(site): o número do site aparece nu e gritante (VERSION,/versao.txt, tagvX.Y.Z, CHANGELOG, e mais ainda num clone local do repo central), enquanto o da constituição é discreto. Correções: a §6 da constituição passa a explicitar "duas versões, não confundir" (com a armadilha do clone local e do bootstrap); nova seção Duas versões: site x constituição emengenharia/versionamento.md; guard na skill/xadm-docs(a vigente vem só deconstituicao-versao.txt, nunca deVERSION/tag); nota roteadora noCLAUDE.mddo central; e correção do path staledocs/padroes/constituicao.mdna skill/xadm-release. /versao.txtauto-rotulado (site X.Y.Z). O Dockerfile passa a gravar o número do site rotulado em vez de nu, para não ser confundido com a versão da constituição.- Nota da distinção também no checklist de app novo (
app-novo.md§3): o que o app rastreia é sóconstituicao-versao.txt;VERSION//versao.txt/tag são do site. templates/mkdocs.yml— ordem dos plugins corrigida. Oprint-siteestava antes doswagger-ui-tag, contrariando o próprio comentário ("DEVE ser o último") e quebrando omkdocs build --strict(achado na adoção real). Reordenado paraprint-sitepor último.- Bootstrap sub-instalava as skills. O checklist de app novo (
app-novo.md) listava sóxadm-docsexadm-release, e omanifesto.jsonnão distinguia skill core de opcional — quem fazia bootstrap pela leitura instalava 2 de 8 (caso real). Correções: omanifesto.jsonganha o campoopcionais(hoje sóxadm-docx;gera-manifesto.pyemite e o--checkguarda); oapp-novo.mdpassa a mandar instalar todas as*-skill.mddo manifesto exceto asopcionais, listando as 8 core e apontando o manifesto como a lista mecânica completa; a/xadm-docspula asopcionaisna conferência de defasagem (opcional não-instalado não é defasagem).
0.18.2 - 2026-06-26¶
Adicionado¶
- Navegação Anterior/Próximo no rodapé das páginas (
navigation.footer). Habilitada a feature nativa do MkDocs Material no site central e notemplates/mkdocs.ymldos apps: cada página ganha links "Anterior" (esquerda) / "Próximo" (direita) derivados da ordem donav:, servindo o modo "ler como livro" (§1.7) — mais útil ainda no manual e no livro do projeto dos apps. Bump PATCH 0.15.0→0.15.1 (artefato rastreado mudou); apps re-baixam o template via/xadm-docsna migração oportunista.
Alterado¶
- Constituição 0.15.0 — screenshot do manual entra na definição de pronto (§6). A metade (2) "doc do estado atual" agora lista o screenshot do manual entre os "estados atuais que mentem": mudou UI retratada numa imagem (botão novo, rótulo, layout) → regenerar o PNG afetado é parte do pronto, e a verificação inclui abrir a imagem e confirmar o elemento novo, não só rodar o gerador (gerador que roda sem semear o estado certo "passa" mostrando a tela velha — a mesma falha da metade (1)). O runbook Screenshots do manual ganhou a seção "Revisar o diff antes de commitar" com a armadilha do diff de só-ruído (marca d'água/elemento aleatório → reverter os PNGs de só-ruído, manter o que teve mudança visual real). Loop §6 de um app de BI Flutter (vantroba-bi v1.5.0: botão de export novo, texto atualizado, .png ficou na tela velha — pego só depois).
Adicionado¶
- Engenharia/Flutter: padrão de export XLSX sem lib licenciada. Registrado na página
de Flutter: usar o
excel(justkawal, MIT) + pós-processar o OOXML comarchivepara freeze pane/autoFilter/outline (que oexcel4.0.6 não faz — verificado no fonte), em vez de trocar por Syncfusion (licenciado); com as armadilhas (Archiveimutável, download Web manual, edição idempotente + smoke real) e a nota de hierarquia × sort. Imagem/logo no XLSX ficou fora de escopo (sem receita de injeção). Loop §6 de um app de BI Flutter.
Corrigido¶
-
Menu de abas: o vão Teoria/Prática sumia na própria página Aplicações. A regra que empurra o grupo da direita (Aplicações · API Reference · Mudanças) mirava pelo href (
[href*="aplicacoes"]), mas o Material reescreve o link da aba ativa para./— que não contém "aplicacoes" — então, ao abrir Aplicações, omargin-left:autonão casava e todas as abas agrupavam à esquerda. Passou a mirar por posição (nth-last-child(3)= início do grupo da direita), imune ao estado ativo. Regra é exclusiva doxadm.cssdo portal central; apps não usam. -
Release: pré-flight pedia autorização (constituição 0.14.34): o
.claude/settings.jsoncentral não tinhagit status/git logno allow-list (o template da skill já os prescrevia — estavam dessincronizados), e o pré-flight foi rodado num bloco multi-linha comgit --no-pager …(duas coisas que o matcher recusa: comando composto não casa com um padrão, e a flag antes do subcomando quebra ogit status *). Allow-list ganhougit status/git log/git diff; a skill (template + cópia) deixa explícito: um comando por chamada Bash (sem bloco multi-linha) egitpuro sem--no-pager(4º veneno).
0.18.1 - 2026-06-26¶
Adicionado¶
slugnoapp.json— fonte única do identificador do app (constituição 0.14.32): o slug (pasta no bucketdocs-sites/, path dosite_url, nome do.docx) vivia duplicado emmkdocs.yml,docs.yml, CLAUDE.md e na skill de release, mas não noapp.json, seu lar natural. Agora o template doapp.jsontemslug(kebab-case, "para sempre"); odocs.ymlderiva dele o target do rclone e osite_url(em vez de hardcodar<app>); oexport_docxusa-o no nome do.docx(fallback p/ o diretório-raiz); e ovalida-frontmatterconfere que osite_urldomkdocs.ymlbate com oslug(igual ao cross-check decliente:). Opcional p/ app legado (migração oportunista).- Gate de CI da lista de download da
/xadm-docx(scripts/checa-export-download.py): confere que a lista hardcoded de arquivos baixados (skill + página) bate com o pipeline publicado (scripts/export-docx/+ reference/logo). Fecha o loop §6 doadmonitions.pyque defasou a lista.
Alterado¶
-
Export
.docx: nome de entrega auto-descritivo (constituição 0.14.31): sem 2º argumento, oexport_docx.pygera<slug>-<nível>[-v<versão>].docxna raiz do repo (antes:projeto.docx/pre-projeto.docxgenérico, que colidia entre apps/releases na entrega). slug = nome do diretório-raiz; nível = pre-projeto|projeto (pelo caminho); versão =git describe --tags→VERSION→ omitida; fallback genérico se não derivar. A skill/xadm-docxe a página passam a usar o default; o.gitignoredo app (e ogitignore-flutter) ganha/*.docx(root-anchored — não pega um pré-projeto.docxcommitado, §1.3). Correção junto: o download fresco da skill não baixava oadmonitions.py(passo do pipeline desde 0.14.26) — incluído na lista. -
Site central: ordem das abas, home e layout da Aplicações. Abas do topo reordenadas (Mudanças foi para o fim: Início · Documentação · Engenharia · Transversais · Aplicações · API Reference · Mudanças); a home ganhou um item explicando Transversais (IA, infraestrutura, glossário) com link; e as páginas Aplicações e API Reference (conteúdo montado via JS, sem headings no markdown → TOC vazio) receberam
hide: toc, colapsando a coluna direita vazia que deixava o layout "agrupado". Só apresentação do site central; nada de artefato rastreado.
Corrigido¶
-
App publicado só em
dev/aparecia em "Outros (sem app.json)" (constituição 0.14.33): no layout versionado (decisão 0004), o central lê aapp.jsonda raiz do bucket (docs-sites/<slug>/app.json), mas odocs.ymlsó a sincronizava em<slug>/dev/— e o passo que mexe na raiz é release-only (publica-versao.pynem toca na app.json). Logo, app que só deu push em master nunca categorizava (caía em "Outros"). Odocs.ymlagora fazrclone copyto site/app.json …/<slug>/app.json(aditivo) em todo push. Caso real:thoms-integracao-produto-ecom. -
Release sem prompt — inspeção de arquivo pela ferramenta
Read, não por shell (constituição 0.14.30): a skill/xadm-releasemandava ler oCHANGELOG.mdmas não dizia como, e uma inspeção com pipe (sed … | grep,rtk grep … | head) disparou o único prompt de um release (pipe é recusado por princípio, fora do allow-list). A skill (template + cópia deste repo) agora manda inspecionarVERSION/CHANGELOG/diff pela ferramentaRead(ougit diff), nunca porsed/grep/cat/rtk grep/| head— 3º veneno documentado. OReadnão precisa de allow-list nem confirma.
0.18.0 - 2026-06-26¶
Adicionado¶
- Gate de dogfood das skills no CI (
scripts/checa-dogfood.py): somos a vitrine, então as skills instaladas (.claude/skills/<nome>/SKILL.md) têm de bater com o template canônico (templates/<nome>-skill.md). O CI falha em drift — descoberto via loop §6: o próprio repo rodava/xadm-spec//xadm-refine-spec//xadm-plandefasados (sem NNN/segredo/lib-capability) porque as cópias nunca eram re-derivadas. As 3 cópias defasadas foram sincronizadas.xadm-releaseé adaptada por repo e fica de fora do gate.
Alterado¶
-
Spec/refine: verificar capacidade de lib de terceiro na FONTE antes de especificar (constituição 0.14.27): a
/xadm-spec(§1) passa a mandar confirmar, na fonte/changelog da versão em uso, que um recurso de lib/SDK externo do qual a feature depende existe — com o pesquisador de docs da stack (ex.act-flutter-docs-researcher) — antes de especificar; especificar API inexistente é inventar capacidade (§1.2). A dim. 2 (Premissas) da/xadm-refine-specreforça: recurso de lib assumido sem conferir no fonte = achado crítico. Origem: loop §6 do BI Transporte (feature de export xlsx — o researcher confirmou no fonte da lib 4.0.6 que não havia API de imagem/outline, evitando retrabalho). -
Export
.docx: fim do auto-anexo de.mdirmãos (constituição 0.14.28): oexport_docx.pydeixava de fora o que era embutido, mas anexava ao fim todo.mdirmão não-embutido — slurpando páginas que o livro só linka/resume (ex. etapas deprojeto/), gerando conteúdo duplicado e um anexo solto após as Decisões. Agora o.docxé o index + só o que ele embute via--8<--(igual ao site: link não entra, o link já é a relação). Pré-projeto passa a embutir seus anexos no fim doindex.md(cada#ainda ganha quebra de página). Avisado na página Exportar para .docx. -
Export
.docx: links para fora do Word viram texto (constituição 0.14.29): o livro linka legitimamente para ADRs (docs/decisoes/*.md) e outras páginas de nav — funcionam no site, mas no.docx(só o livro) virariam hyperlinks mortos (apontam para um.mdinexistente). Um filtro lua (frontmatter.lua) remove o href de links relativos (alvo fora do.docx), mantendo o texto; URL absoluta e âncora interna seguem clicáveis, e imagens (Mermaid) não são tocadas. Guidance na página: cross-ref de conteúdo só-no-site se cita por nome/número, não por link. Docx-only — no site os links funcionam.
0.17.1 - 2026-06-26¶
Adicionado¶
-
Export
.docx: admonitions viram callout (constituição 0.14.26):!!! tipo "Título"/??? tipo(que o pandoc não entende e despejava literal no Word) agora passam por um pré-processador (admonitions.py, antes do pandoc) que os converte em blockquote com título em negrito → estilo Block Text (callout) doxadm-reference.docx, com o tipo como rótulo pt-BR (Nota/Aviso/Dica/…). O autor mantém o!!!na fonte (box nativo no site); só o.docxé adaptado. Docx-only — o site já renderiza admonitions. -
Export
.docx: legenda por diagrama + estilo de código + Título 4–6 (constituição 0.14.25): (a)render_mermaidlê%% caption: <texto>no bloco e emite a legenda na figura do.docx; (b) oxadm-reference.docxe omake_reference.pyganharamSourceCode/VerbatimChar(monoespaçada, fundo e borda leves) — antes```json/códigoinline saíam na fonte do corpo — e Título 4–6 na identidade X-Adm (Verdana azul, decrescente), para o conteúdo que chega a H4+. (c) Documentada a convenção de que fragmento--8<--se autora no nível do embed (modelagem.md em###, não#) — nada rebaixa heading, no site nem no.docx(constituição §5). Só docx/reference; o site já estilizava código e todos os níveis via Material+CSS.
Corrigido¶
- Export
.docx: diagnóstico de Mermaid quando falta o Chrome (constituição 0.14.24): commmdcinstalado mas sem Chrome (de sistema ou do puppeteer — caso típico de CI/runner limpo), o erro dizia "mmdc ausente — instale o mmdc", mandando pro lado errado. Agora distingue "mmdc ausente" de "mmdc presente, Chrome falhou" e aponta as saídas offline (instalar chromium ·PUPPETEER_EXECUTABLE_PATH·npx puppeteer browsers install chrome-headless-shell), sem empurrar pro.ink. Nota de troubleshooting na página Exportar para .docx. (A detecção automática de Chrome do sistema +--no-sandboxjá existia na v0.17.0.)
0.17.0 - 2026-06-26¶
Adicionado¶
-
Pipeline de exportação para
.docxno padrão X-Adm (constituição 0.14.23): centraliza na toolchain o pipeline Markdown→Word (pandoc + reference-doc + Mermaid→PNG), derivado e saneado da PoC poc-pied. Python-only cross-platform (Linux/Windows/macOS) + o filtro nativo do pandoc (frontmatter.lua); reference client-neutral, Mermaid offline por default (mmdc;.inksó opt-in com aviso de confidencialidade, §1.9), pré-processador de--8<--(o pandoc não expande snippets). Distribuído como os validadores: scripts emscripts/export-docx/rastreados nomanifesto.jsone publicados em/toolchain/raw/scripts/export-docx/; o reference+logo publicados crus (binários, fora do manifesto). Inclui a skill/xadm-docx(baixa o pipeline fresco e gera o Word, sem commitar), a página Exportar para .docx e o §1.3 acionável — distinguindo asset de tooling (versionado: css, reference.docx, logo) de documento gerado (não commitado: o.docx, o site). -
Segredo nunca entra no Git — nem no andaime
.ia/(constituição 0.14.22, §1.9): o.ia/é versionado e o-prompt.md(cola crua do pedido) é onde uma credencial real vaza por descuido — aconteceu. Regra nova: nenhum arquivo do repo (.ia/,docs/, config) carrega segredo real; usar placeholder (<TOKEN>,${VAR}) + ponteiro pro valor real (secret da org no Forgejo, env, cofre); se vazou pro histórico, rotacionar (apagar o arquivo não basta — o Git guarda; mesma resposta dada ao vazamento das keysDOCS_S3)..ia/segue versionado (a trilha do andaime é o objetivo — não se gitignora). Eco no fluxo de IA e nas skills/xadm-spece/xadm-plan.
Corrigido¶
-
.ia/NNN-*—NNNé o id da linhagem, não sequência global de arquivos (constituição 0.14.21): as skills/xadm-spece/xadm-plannomeavam.ia/NNN-titulo-spec.md/NNN-titulo-plan.mdsem dizer o significado deNNN, e o agente tratava como sequência global de arquivos, ainda inventando um slug novo por estágio (ex. errado:001-definicao-prompt→002-integracao-...-spec), quebrando a rastreabilidade. Os dois templates passam a especificar queNNNidentifica a linhagem (a feature): prompt, spec e plan da mesma linha compartilhamNNNe slug, mudando só o sufixo de estágio; feature nova recebe o próximoNNN. Mesma definição reforçada no fluxo de IA (dono conceitual da regra). -
Bootstrap de app novo aponta para o mirror público, não o Forgejo privado: o checklist app novo e publicar docs mandavam copiar os templates de
fonte.xadm.biz/.../src/branch/master/templates/…— o Forgejo privado, que dá 404 sem auth (bootstrap de app novo, inclusive por agente de IA, falhava ou improvisava de um clone local defasado). Agora o bootstrap é manifesto-driven como a/xadm-docs: baixa do mirror públicodocs.xadm.biz/toolchain/raw/…, ancorado nomanifesto.jsoncomo fonte única, com nota de quefonte.xadm.bizé edição/hosting (privado) e consumo é sempre via mirror. Mesmo swap no link irmão de versionamento. gitignore-flutterpublicado no mirror: otemplates/gitignore-flutternão estava no manifesto, entãotoolchain/raw/templates/gitignore-flutterdava 404 — o link da engenharia Flutter já apontava pra lá (404 latente) e o de stack apontava pro Forgejo privado. O Dockerfile passa a publicá-lo cru noraw/templates/(artefato copy-once de bootstrap, fora do manifesto — cada app customiza o.gitignore, não há o que re-sincronizar), estack.mdaponta pro mirror.
0.16.10 - 2026-06-25¶
Corrigido¶
- Release sem prompt — pré-flight: o pré-flight ainda pedia autorização porque
(a)
git describe/git rev-parsenão estavam no allow-list e (b) usava substituição de comando$(git describe …), que o matcher de permissão recusa por princípio. Adicionadas as regras de leitura (git status/rev-parse/describe/log/echo) ao allow-list e ao template da skill, e documentado o veneno do$(...)(pegar o valor num passo, usar literal no próximo). Constituição v0.14.20.
0.16.9 - 2026-06-25¶
Adicionado¶
- Release sem prompt (opt-in): seção "Permissões" no template da skill
/xadm-releasedocumentando o allow-list do.claude/settings.json(git add/commit -m/tag/push origin) para o release não pedir autorização — com o trade-off explícito (remove a rede de segurança; a garantia vira a REGRA Nº 2) e a dica de rodar cadagitseparado (compound com pipe não casa o allow-list). Aplicado neste repo (.claude/settings.json+ skill local). Constituição v0.14.19.
0.16.8 - 2026-06-25¶
Alterado¶
- CI Flutter mais rápido (auditoria dos 3 apps + central): a imagem
ci-flutteragora traz clang/lld/cmake/ninja/pkg-config baked (native assets do PowerSync/sqlite3) — o app não instala mais toolchain nativa por run (~2m20 a menos noci.yml). Os templatesci.yml/docs.ymlganharam o passo Cache do pub (~/.pub-cache, key porpubspec.lock) e a nota de que a toolchain vem na imagem. Constituição v0.14.17. Migração: app Flutter re-deriva oci.yml(dropar o passo "Toolchain nativo") via/xadm-docs. - CI de docs mais rápido: o
docs.ymlganhou cache de pip + npm (~/.cache/pip+~/.npm) —mkdocsemermaidpassam a instalar do cache (sem re-download por run, ~20-35s/run). Avaliado e descartado assar numa imagemci-docs: olint-mermaid.mjsé ESM e não resolve módulo global (nem viaNODE_PATH), e imagem nova só pelo mkdocs (~15s) seria over-engineering. Constituição v0.14.18.
0.16.7 - 2026-06-25¶
Alterado¶
- Fábrica de CI (decisão 0003): a fonte das versões passou a ser a
ci-images/matriz-baseline.json— a leitura agregada dosapp.jsondo bucket foi removida. Ela criava um deadlock de bootstrap (oapp.jsonchega ao bucket viadocs.yml, que roda na imagem que a fábrica deveria ter buildado), travando o 1º app Flutter version-pinned (bi-transporte,flutter: 3.44.0). Adoção de versão nova = PR na baseline + push (a fábrica builda) antes de o app apontar ocontainer:. Baseline já comflutter: 3.44.0;ci-images.ymlsem o passo do bucket/DOCS_S3. Decisão 0003 ganhou nota datada;app-novo,engenharia/fluttere o runbook documentam a ordem. §6 do bi-transporte.
0.16.6 - 2026-06-24¶
Corrigido¶
- Fábrica de CI (
ci-images.yml): odocker builddo job falhava com "Cannot connect to the Docker daemon" — o runner da org usa DinD por TCP (sem socket unix no job). O passo de build agora derivaDOCKER_HOSTdo gateway default do job (= daemon do DinD). Runbookfabrica-imagens-ci.mdcorrigido: o socket-do-host do passo 1 só vale para runner sem DinD.
0.16.5 - 2026-06-24¶
Alterado¶
templates/docs.yml: passo Cache do Gradle no bloco de javadoc (paridade com oci.yml; o comentário já prometia mas não entregava) — todo app Java que gera Javadoc no CI de docs ganha o cache ao descomentar. Referência ao JDK deixou de citar versão fixa (era "JDK 21") e aponta a imagemci-java:<v>. Constituição v0.14.16. (§6 de app Java.)
Corrigido¶
- Imagem
ci-java:<v>da fábrica de CI estava semrclone— odocs.ymlde app Java falhava no "Publicar no Garage" (rclone: command not found), apesar de o comentário do template anunciar "toolchain pré-instalada". Adicionado aoci-images/Dockerfile.java(aci-basee aci-flutterjá tinham). Requer rebuild+push daci-java. (§6 de app Java.)
Revertido¶
- O fallback de
/commit.txtvia.git/HEAD(introduzido na v0.16.4) quebrava o build no Coolify:COPY .git/HEADfalha com"/.git/HEAD": not foundporque o Coolify não inclui o.gitno contexto de build — o deploy não subia./commit.txtvolta adev(cosmético conhecido); a receita emcoolify.mdvirou aviso de "não leia o.git/HEADno build — use Build Argument". O fix doexport TAGnorelease.yml(v0.16.4) permanece — é independente.
0.16.4 - 2026-06-24¶
Corrigido¶
templates/release.yml(bloco opt-in de Release no Forgejo): a tag saía como var de shell semexport, então opython3 -cfilho não a enxergava (KeyError: 'TAG'→ corpo do POST vazio → 422). Agoraexport TAG=…. Também documentado que a escrita no repo (permissions: contents: writeouRELEASE_TOKEN) é obrigatória — sem ela dá 403 antes do 422. Constituição v0.14.15. (§6 do maxsul-pied-simples, 1º app a habilitar o bloco.)/commit.txtcarimbavadev: o Coolify não passaSOURCE_COMMITcomo build-arg. ODockerfileagora tem fallback que lê o commit do.git/HEAD(checkout destacado do deploy = SHA);.dockerignoredeixa só oHEADentrar no contexto.
Adicionado¶
- Receita em
infraestrutura/coolify.mdpara carimbar o commit do deploy via.git/HEADquando o Coolify não passaSOURCE_COMMIT(opcional, para app que embute o commit; não é exigência da constituição).
0.16.3 - 2026-06-24¶
Corrigido¶
overrides-main.htmlechangelog.mdagora são rastreados (publicados raw + manifesto) — os dois scaffolds da doc versionada (overrides/main.htmldo banner;docs/changelog.mdda página "Mudanças") são estáticos-idênticos entre apps (como ocheckstyle.xml), mas estavam fora domanifesto.jsone doraw/do site → davam 404 e a/xadm-docsnão detectava defasagem nem conseguia re-baixá-los (só com checkout local do central). Adicionados aoRASTREADOS(auto-publicados emtoolchain/raw/templates/pelo Dockerfile) + destino documentado na skill/xadm-docs. Feedback de uso real via loop §6 (maxsul-pied-simples).
Alterado¶
release.yml: rótulo do artefato Flutter mais preciso — o comentário dizia "Flutter → bundle (apk/web)", misturando Flutter Web (que é deploy via Coolify, não artefato) com mobile/desktop (artefato distribuível → Release). Esclarecido: Web segue o caminho deploy (sem Release/asset); mobile (apk/IPA) e desktop (win/linux/mac) geram Release com asset. O como buildar cada alvo fica a definir quando surgir o 1º app (não normatizar no escuro, §1.2). Feedback de uso real via loop §6.release.yml: token da Release configurável +permissions— oGITHUB_TOKENautomático do Actions costuma ser só Actions (não cria Release → 403). O bloco opt-in agora orienta declararpermissions: contents: writeno job para elevar o auto-token e, se o instance restringir mesmo assim, usar um token dedicado da orgRELEASE_TOKEN(escopowrite:repository) — ocurlusaRELEASE_TOKENse existir, senão oGITHUB_TOKEN. Setup documentado em infraestrutura/forgejo. Feedback de uso real via loop §6 (maxsul-pied-simples).
0.16.2 - 2026-06-24¶
Alterado¶
- Dogfood: o central usa as próprias skills de workflow — instaladas
xadm-spec/refine-spec/plan/work/compound/meta-audit-workem.claude/skills/(antes só axadm-release); oCLAUDE.mdrecomenda o fluxo/xadm-*para feature não-trivial aqui. E o CI do próprio central (build-site.yml) passou a usar a imagemci-base(antes montava git+python via apt a cada run). Mudanças internas — não alteram o site publicado.
0.16.1 - 2026-06-24¶
Corrigido¶
- Build do site no Docker (deploy da v0.16.0) — o
mkdocs build --strictdoDockerfilefalhava porque o COPY seletivo do build stage não trazia da raiz ooverrides/(dotheme.custom_dir— banner de versão antiga) nem oCHANGELOG.md(embutido pela página "Mudanças" via snippet). Adicionados os dois COPY. Build local passava; o contexto enxuto do Docker não.
0.16.0 - 2026-06-24¶
Adicionado¶
- Release do Forgejo com artefato anexado (engenharia/versionamento) — no Forgejo tag ≠ Release: a tag sozinha deixava a aba Releases vazia e o jar sem proveniência. O
templates/release.ymlganhou um bloco opt-in, stack-aware que, para app que distribui artefato (jar/CLI/worker), builda o artefato no CI e publica a Release (tag + notas da seção do CHANGELOG + asset anexado), via API do Forgejo porcurl+secrets.GITHUB_TOKEN. O marco do que foi liberado passa a ser a Release (download reproduzível), não só a tag; o operador baixa o jar da aba Releases. Requer a imagemci-java:<v>(aci-basenão tem JDK) e token com escopo de escrita em release. Skill/xadm-releasee o modelo de distribuição atualizados. Feedback de uso real via loop §6 (maxsul-pied-simples). -
Documentação versionada por release (decisão 0004 / spec 011) — cada tag
vX.Y.Zpublica um snapshot imutável da doc emdocs-sites/<app>/<X.Y.Z>/, e um seletor de versão nativo do Material (extra.version.provider: mike) no topo lista as releases; a raiz abre na maior SemVer; master vira o previewdev/(fora do dropdown). Implementado:templates/mkdocs.yml(provider) +templates/docs.yml(gatilhotags,site_urlpor-versão, publish na subpasta — nuncarclone syncda raiz) + novoscripts/publica-versao.py(montaversions.json+redirect na raiz viarcat, publicado no site) +sync-apps.sh(detectaapi/na versão default). Invariantes duros:app.jsonfica na raiz (senão quebra a fábrica de imagens); forward-only (sem backfill). Spike confirmou na fonte do Material que osite_urlprecisa terminar na versão. Adoção por app é pós-release (odocs.ymlbaixa opublica-versao.pydo site). Dogfood do central e poda de storage: diferidos (spec 012 + brief). -
Página "Mudanças" (CHANGELOG) no site de cada app — o
CHANGELOG.mdda raiz do repo agora aparece no site, em entrada de nav própria no topo, embutido viapymdownx.snippets(--8<-- "CHANGELOG.md", fonte única §1.8/§1.9 — sem cópia, sem editar em dois lugares).templates/mkdocs.ymlganhou a entrada; novo scaffoldtemplates/changelog.md. Aplicado no central (dogfood) e nos pilotos. Casa com a doc versionada (spec 011): cada snapshot de versão mostra o changelog daquela release.
Alterado¶
release.ymlpassa a usar a imagem de CIci-base(decisão 0003) — faltou na migração inicial (sóci.yml/docs.ymltinham ido): rodava emnode:22-bookworm-slime instalava git+python viaapta cada release (~22s). Agora usaci-base(já traz git+python+curl) — só roda ovalida-release.py. −~22s por release.
0.15.0 - 2026-06-22¶
Adicionado¶
- Fábrica de imagens de CI por stack+versão + cache do Gradle (decisão 0003) — o runner Forgejo da org é efêmero e os templates
ci.yml/docs.ymlmontavam o ambiente do zero a cada run (apt/pip, download de JDK egit clonedo Flutter SDK — o maior custo). Agora: imagens por stack+versão servidas no registry do Forgejo (ci-base,ci-java:<v>,ci-flutter:<v>com o SDK baked), montadas por uma fábrica central (ci-images/+.forgejo/workflows/ci-images.yml) que lê o campo novotoolchaindosapp.jsonagregados do bucket (sem token de Git entre repos) + uma baseline, e builda/empurra a matriz. Os templates apontam ocontainer:da stack;actions/cache@v4cacheia o Gradle. Java 25 fixado como LTS da casa (stack). Pré-requisitos de infra (do operador): runner buildando imagem + push pelo endereço interno do registry (dribla o Traefik/499) + token de pacote da org — runbook em infraestrutura/fábrica-imagens-ci; o workflow já vem parametrizado (CI_REGISTRY_HOST/REGISTRY_TOKEN). Consolida o feedback de CI/deploy do piloto Flutter (loop §6):subositoquebrado, drift da versão do SDK (fonte única no.fvmrc, semFLUTTER_VERSIONno Coolify), asset gerado antes do test, config pública hardcode vs build-arg. toolchainobrigatório noapp.jsonpara app Java/Flutter (decisão 0003) — o validador agora falha se um app de stack Java/Micronaut não declarartoolchain.java(ou Flutter/Dart semtoolchain.flutter): sem a declaração a fábrica não builda a imagem-versão e ocontainer:do CI aponta para imagem inexistente, quebrando com erro de pull obscuro. Falha cedo e clara em vez de tarde e confusa. App docs-only (ci-base, sem versão) não declara. Documentado no contrato doapp.json(publicar-docs), engenharia e checklist app-novo.- Nota fixa "Build Argument × Environment Variable" no Coolify (infraestrutura/coolify + eco em engenharia/flutter) — pega-pé recorrente (mordeu 3× numa sessão:
FLUTTER_VERSION,SENTRY_DSN): valor que o build embute na imagem (--dart-define,ARG) precisa ser Build Argument (+ "Available at Buildtime"), não env de runtime — como runtime chega vazio ao bundle e o app sobe sem ele, sem erro. Mecânica bidirecional canônica em coolify.md (o sentido inverso — segredo de runtime como build arg vaza comoARG— é o caso dosDOCS_S3_*); eco específico de--dart-defineno flutter.md. Feedback de uso real via loop §6.
0.14.1 - 2026-06-22¶
Adicionado¶
- Conformidade de engenharia no loop de sincronização (constituição §6 +
/xadm-docs) — as regras de engenharia (engenharia/*) eram lidas ao vivo pelas skills mas ficavam invisíveis ao/xadm-docs, que só olhava o manifesto de templates; um app não detectava defasagem de regra de engenharia (e o raw das páginas dava 404). Agora o site publica as páginas de engenharia também cruas (.../toolchain/raw/engenharia/<stack>.md) e o/xadm-docsganhou o passo 3b: ao detectar bump, re-audita o código da stack do app contra a regra vigente (exit codes, libs, observabilidade, gate, definição de pronto) e propõe correções com aprovação — re-auditar, não re-baixar. As páginas não entram no manifesto por desenho (regra viva lida ao vivo ≠ artefato copiado que envelhece). Feedback de uso real via loop §6. - Exit code
4ocupado/lock na taxonomia de CLI/worker (engenharia/java) — a lista0ok ·1parcial ·2config/auth ·3externo não cobria "execução concorrente serializada por lock; nada feito; seguro repetir", desfecho recorrente em job reentrante (cron + gatilho sob demanda dividindo estado). Fixado também que a lista é o contrato canônico da casa (app não inventa código; desfecho novo entra por §6) e que o app documenta a saída no runbook deoperacao/. Feedback de uso real via loop §6 (auditoria maxsul-pied-simples, que já shippouexit 4na sua ADR 0003).
Corrigido¶
- Frontmatter YAML nos 6 templates de skill de workflow (
xadm-spec/refine-spec/plan/work/compound/meta-audit-work) — faltava o bloco--- name / description ---que o Claude Code usa para descobrir e rotear a skill (asxadm-docs/xadm-releasejá tinham). Sem ele, ao copiar verbatim para o app a skill aparecia com adescriptionvirando o comentário-cabeçalho e a invocação quebrava. Feedback de uso real via loop §6.descriptionno formato "o que faz + Use quando…".
0.14.0 - 2026-06-22¶
Adicionado¶
- Conjunto de skills de workflow X-Adm (constituição v0.13.0; decisão do Gustavo, 010c §13):
xadm-spec → xadm-refine-spec → xadm-plan → xadm-work → xadm-compound, modelado no ACT mas próprio da casa. Stack-aware — detectam a stack e seguem a base de conhecimento da Engenharia daquela stack.xadm-worknão commita (REGRA Nº 2);xadm-compounddestila paradocs/e refina a base de conhecimento (loop §6). Templates rastreados no manifesto (o/xadm-docs+ o hook de sessão acusam defasagem). Catálogo na IA e Claude Code. - Skills de workflow reescritas a fundo +
xadm-meta-audit-work(constituição v0.14.0; Gustavo comprou o ACT PRO vitalício e quis o workflow da casa "o mais parecido possível, inclusive os insights"): as 5 skills ganharam a profundidade do ACT adaptada à casa — contrato duro + invariantes que falham o workflow (xadm-work),map_flows/preview_outline/complexidade adaptativa (xadm-spec), regras não-negociáveis + formato de achados + review gate (xadm-refine-spec), pesquisa + style contract + checklist de qualidade (xadm-plan), extração paralela + quality bar (xadm-compound); preservados os inegociáveis X-Adm (não-commitar, destilar p/docs/, gate por stack, pt-BR, definição de pronto §6). Nova/xadm-meta-audit-workaudita um run da/xadm-work(confere não-commit, reconciliação do plano, gate da stack e a linha §6). - Princípio de engenharia "Simplicidade primeiro (sem over-engineering)" na Engenharia — busque o caminho mais simples que satisfaz a necessidade real e presente; abstração/camada/generalização só com necessidade concreta (YAGNI). As skills de workflow ecoam o princípio onde a IA decide escopo/desenho/implementação (
xadm-spec,xadm-plan,xadm-work) e axadm-refine-specganhou a 7ª dimensão de checagem (pega over-engineering já na spec). Irmão de engenharia do "enxuto por padrão" da constituição §1.5 (que vale para a doc).
0.13.0 - 2026-06-19¶
Adicionado¶
- Área Engenharia construída (
docs/engenharia/) — o lado "como construir" do padrão: Stack da casa (matriz app→stack + defaults opinativos), páginas por stack (Java/Micronaut servidor com guarda de fronteiras, Java app simples/CLI/worker, Flutter cliente), CI, gates e testes, e versionamento + health check. (Phases 1–5 do plano de Engenharia.) checkstyle.xml+suppressions.xmlcentralizados (templates/, rastreados no manifesto, publicados em/toolchain/raw/) — fonte única de estilo Java; para de copiar app-a-app.- Seção "Critérios de aceite e teste" no template de etapa (
doc-projeto.md) + marcador "regras arquiteturais guardadas por teste/lint" no livro — a ponte para quem valida.
Alterado¶
- Regras de engenharia movidas da constituição para a área Engenharia (CI por stack, SemVer/release, health check, branch
master, níveis de teste, deploy) com ponteiro curto — a constituição fica menor; o piso da definição de pronto permanece (§6). - Home (
index.md) reescrita — declara a constituição de arquitetura, engenharia e documentação, com os dois caminhos (Documentação · Engenharia); "Tudo numa página" sai do menu de abas; separador no menu entre as áreas de teoria e prática; menções a ZIM/ERP sem adjetivo.
0.12.0 - 2026-06-19¶
Adicionado¶
- Portal em duas áreas distintas: Documentação × Engenharia (constituição v0.12.0; decisão do Gustavo). O site reorganiza em abas (
navigation.tabs): Documentação (constituição, templates, publicar, app-novo, decisões), Engenharia (NOVA) e Transversais (IA, infraestrutura, glossário). As pastas no source espelham:docs/documentacao/,docs/engenharia/,docs/transversais/. A constituição passa a se chamar "Constituição da Documentação e Engenharia"; o site, "Padrões da Plataforma X-Adm". - Área Engenharia + Stack da casa (
docs/engenharia/): matriz opinativa app→stack (Micronaut servidor · +Thymeleaf view simples · Flutter cliente/web/mobile · Java puro app simples/CLI · ZIM legado) + defaults transversais (package-by-feature universal, OkHttp, Gradle KTS, JUnit5+WireMock, BigDecimal, Logback, PostgreSQL+Flyway, picocli). Default forte + exceção documentada. .gitignoreFlutter de referência (templates/gitignore-flutter; feedback via loop §6). Corrige dois bugs que o template legado da org propagava:pubspec.lockagora versionado num app (build reproduzível, sem*.lock); FVM usa.fvmrcversionado (sem o legado!.fvm/fvm_config.json). Referenciado na Stack da casa.
Alterado¶
- Toolchain de máquina migrado para
/toolchain/(constituição v0.12.1). Os artefatos que os apps baixam no CI (validadores, hooks,constituicao-versao.txt,raw/,manifesto.json) saem de/padroes/para/toolchain/— namespace neutro às duas áreas. O Dockerfile dual-publica (/padroes/segue vivo na transição → apps não quebram, re-derivam oportunisticamente). URLs de página antigas (/padroes/X) ganham redirect (mkdocs-redirects) para a área nova. - Campo
entregue: true|falsena etapa (constituição v0.11.1, §2; feedback via loop §6). Separa a entrega da feature dostatusdo doc no Resumo Executivo — permite "design aprovado, build pendente" (status: aprovado+entregue: false). Opcional e retrocompatível: sem o campo, cai no heurístico legado (status aprovado → entregue). Tocavisao-tecnica.py,valida-frontmatter.py, constituição §2 e o template de etapa. - Convenção
.ia/para andaime (constituição v0.11.1, §1.9; feedback via loop §6). Artefato de trabalho (spec, plano) vive em.ia/NNN-*.md, numerado por repo, fora dedocs/(não é conteúdo publicado).
0.11.1 - 2026-06-19¶
Adicionado¶
- Template
Guia do código(templates/guia-do-codigo.md) (constituição v0.11.0, §2/§4; feedback via loop §6 dos pilotos BI Transporte). Página Dev padrão de todo app com código: narrativa autorada da organização do código, com blocos por stack (Java package-by-feature / Flutter feature-first) e o marcador opcional de inventário. xadm.csscentralizado (templates/xadm.css) (constituição v0.11.0; feedback via loop §6). A identidade visual vira fonte única no central (antes duplicada por app) — inclui a regra.md-typeset a:not(.headerlink)(links de conteúdo com burgundy + sublinhado, antes pouco identificáveis). Apps copiam do central; mudança visual num lugar só.
Alterado¶
- Nav do template por ciclo de vida + seções Pré-projeto/Projeto (constituição v0.11.0, §2; feedback via loop §6). O
mkdocs.ymlcanônico passa a recomendar Resumo → Pré-projeto → Projeto → Operação → Dev → Público → Etapas → Decisões → Glossário, com Projeto = especificação e Etapas = execução explicitados (antes "Etapas" virava catch-all). Oresumo-executivo.mdganha o bloco "O que você encontra aqui". - Hook
visao-tecnica.pyremove<!-- GERADO: inventario -->não preenchido (feedback via loop §6). O inventário de classes é preenchido por um passo Javadoc/dartdoc nodocs.ymldo app; sem o passo, o hook compartilhado remove a linha (nunca embarca o marcador cru) — contrato documentado napublicar-docs.md. - Definição de pronto: a verificação exercita a plataforma real (constituição v0.10.15, §6; feedback via loop §6). O piso de teste ganha que a verificação tem que exercitar a plataforma/runtime real (Web, mobile, o build do app), não só
--strict/fixture — o risco recorrente em mudança de migração/toolchain é o gate "passar" sem tocar o sistema de verdade. - Branch principal padronizado em
master(constituição v0.10.17, §5; feedback via loop §6). Os templatesdocs.yml/ci.ymlvinham combranches: [main]e um comentário pedindo ajuste manual — o passo que falhava: num app emmaster, a CI nunca rodava em silêncio (só a release, por tag). Agora o template já vembranches: [master], sem ajuste por repo, e a convenção está na §5. - REGRA Nº 2: skills que commitam por padrão rodam em no-commit (constituição v0.10.16, REGRA Nº 2 / §6; feedback via loop §6). Skill de execução que commita sozinha (ex. ACT
act-workflow-work, que commita por fase) deve ser invocada sempre com a flag de não-commitar (--do-not-commit) — delegar a execução não delega a decisão de commit, que continua do dev ou da/xadm-release. /health:statusaceita liveness truthy (versionamento.md; auditoria do piloto BI Transporte). O valor exato deixou de ser normativo —"ok","UP", etc. valem; o/healthnativo do Micronaut ("UP") está conforme, sem remapear. Contrato segue: 200 + status vivo +versaolegível./healthdo Flutter web responde{status, versao}, não oversion.jsoncru (versionamento.md; auditoria do piloto BI Transporte Flutter). A receita por stack contradizia a §5 (que já exige o shape inclusive no Flutter web): o nginx monta o{status, versao}lendo a versão doversion.json; o/version.jsonsegue como endpoint separado do auto-update.- Versão em runtime nunca é literal hardcoded + receita de Java CLI (
versionamento.md; feedback via loop §6 do xadm-pied-cliente). Princípio explícito: a versão em runtime vem sempre do manifesto do release, nunca de um literal no código (literal mente e drifta, porque a/xadm-releasesó toca manifesto+CHANGELOG). Receita nova de Java CLI (picocli):--versionviaIVersionProviderlendo oversion.properties, não@Command(version="..."). - CI de docs falha cedo se faltar
DOCS_S3_*(templates/docs.yml; feedback do piloto). Guarda no passo "Publicar no Garage": secret vazio/ausente aborta com mensagem clara, em vez do crípticono such hostdo rclone após ~3min de retry.
Corrigido¶
- Banner de supersessão renderizava o número errado (
scripts/valida-frontmatter.py,frontmatter-cabecalho.py,templates/decisao.md; auditoria do piloto).superado-por: 0016sem aspas era lido como octal pelo YAML (0016 → 14), e a decisão obsoleta mostrava "superada pela 14" no site — e o validador checava a cadeia contra a decisão errada, em silêncio. Agora o validador falha sesuperado-por/supersedevier sem aspas, o template mostra"NNNN"e o hook renderiza 4 dígitos.
0.11.0 - 2026-06-18¶
Adicionado¶
projeto/mapeamento.mdopcional (constituição §2/§5): fonte embutida do cap. 4 do livro (mapeamento entrada↔dados — "origem → destino + transformação"), fragmento sem frontmatter, isento no validador (comomodelagem.md). Template novo.
Alterado¶
-
Release: versão Java também em
build.gradle.kts+ bootstrap de release mais visível (constituição v0.10.14; feedback via loop §6 — arquétipo Java CLI). Ovalida-release.pye a skill/xadm-releasepassam a ler a versão degradle.propertiesou do build script (build.gradle.kts/build.gradle, linha de topoversion = "..."), não só de gradle.properties. Oapp-novoganhou a instalação da skill/xadm-release(faltava — só listava a/xadm-docs) e a nota de que oCHANGELOG.mdnasce na 1ª release (inferido dogit log, cobre o histórico);versionamento.mdidem. Fecha o gap do PoC que adotou docs mas pulou o wiring de release. -
Modelo de dados generalizado: banco E/OU contrato de saída (constituição v0.10.13, §2/§5; feedback via loop §6 — arquétipo CLI sem banco).
modelagem.mddeixa de ser "só projeto com banco": vale também para o contrato dos artefatos de saída/integração (JSON, payload), e o cap. 3 do livro acomoda os dois. Corrige um over-fit ao piloto Java/Postgres.
Corrigido¶
- Scripts publicados também em
raw/scripts/(sha do manifesto verificável) (feedback via loop §6). Omanifesto.jsontraz o sha do arquivo cru dos scripts, mas o Dockerfile só publicava a forma carimbada (/padroes/<script>.py, versão na 1ª linha) — o sha nunca batia eraw/scripts/dava 404. Agora o Dockerfile publica também a forma crua em/padroes/raw/scripts/<script>(casa com o manifesto), mantendo a carimbada para execução. Contrato documentado em publicar-docs.
0.10.0 - 2026-06-17¶
Adicionado¶
- Definição de pronto unificada (mudou código → teste + doc no mesmo PR) (constituição v0.10.12, §6; feedback via loop §6). Fecha a assimetria: o §5 já pedia doc-no-mesmo-PR, mas faltava a metade simétrica de teste, e nenhuma era item de fechamento. O §6 passa a fixar o piso unificado — teste proporcional ao risco (mín.: nenhuma regressão sem teste de regressão) + doc do estado atual (mín.: nenhuma mudança de comportamento sem doc); pular metade é decisão explícita (REGRA Nº 3). É disciplina de fechamento + o gate do
ci.yml, não um gate que detecta "doc seguiu código" sozinho. A doutrina detalhada de teste (níveis, e2e em fronteira de segurança, paridade em refactor) fica para a área de Engenharia (futura). Item de fechamento condicionado a "mudou código" emclaude-regras.md/CLAUDE.md.
0.9.2 - 2026-06-17¶
Adicionado¶
- Ghost mode nas mensagens de commit geradas pela IA (constituição v0.10.8, §6;
feedback via loop §6). A mensagem que o agente escreve para o dev copiar sai
sem
Co-Authored-By, "Generated with" ou qualquer atribuição de IA — regra que sobrepõe o default do harness (que carimba co-autoria). Antes só a/xadm-releasetinha ghost mode; agora vale para toda mensagem gerada. Emtemplates/claude-regras.md(REGRA Nº 2), §6 e no CLAUDE.md do central. -
Oferta §6 no fechamento: obrigatória, acoplada ao commit e afirmativa (constituição v0.10.9, §6; feedback via loop §6). A regra existia em prosa mas dependia de o agente lembrar — e ele pulava. Agora a linha §6 (
§6: nada a reportarou§6: candidato a feedback — <o quê>) sai sempre junto da mensagem de commit, na mesma resposta; a ausência dela é sinal visível de passo pulado, não silêncio. Emtemplates/claude-regras.md(REGRA Nº 2), §6 e no CLAUDE.md do central. -
Guia "Como compilar e testar localmente" obrigatório no nível Dev (constituição v0.10.10, §2; pedido do Gustavo). App que executa traz em
docs/dev/um guia de como rodar localmente (modo simulação): pré-requisitos (runtime/versão, Docker p/ banco), passos e recomendações de ambiente. O detalhe fino por stack é da área de Engenharia (futura); aqui fica o requisito-de-existir.
Alterado¶
- §1.9 — destilar é obrigatório; apagar o andaime é recomendado, não obrigatório (constituição v0.10.11; refino pós-auditoria adversarial). Ao concluir uma spec/trabalho, destilar o conhecimento durável para
docs/é obrigatório (inclui o que ferramentas como/compoundgeram nos docs); apagar o artefato.ia/deixa de ser obrigatório — pode ficar versionado como andaime/histórico, desde que o durável já esteja emdocs/. Alinhado emtemplates/claude-regras.md.
Corrigido¶
<!-- HUMANO -->pendente falha o build em páginastatus: aprovado(constituição v0.10.11, §2; auditoria adversarial). Antes sóRECONCILIARfalhava — um livro (projeto/index.md) cheio deHUMANObuildava verde e publicava em branco (o comentário some no HTML). Agora o hookvisao-tecnica.pyfalha simétrico ao RECONCILIAR; em rascunho/em-revisão é WIP, preservado.
0.9.1 - 2026-06-16¶
Corrigido¶
templates/mkdocs.yml(constituição v0.10.2): o comentário do hookvisao-tecnica.pyainda descrevia o modelo antigo (montarvisao/index.mda partir decapitulo:) — contradizia a própria 0.10.x, em que o livro é autorado (projeto/index.md) ecapitulo:é legado. Comentário atualizado para "processa os marcadores do livro autorado". Feedback via loop §6.
Adicionado¶
- Lint de diagramas Mermaid no CI (constituição v0.10.4, §5; feedback via loop
§6). A constituição manda Mermaid (ER em
modelagem.md, fluxos nas etapas), mas diagrama com erro de sintaxe renderiza cru no site e passa pelo--strict— caso real:erDiagramcomukusado como TIPO renderizou cru por 6 versões. Novolint-mermaid.mjsextrai cada bloco``mermaid e rodamermaid.parse(Node + jsdom, **sem Chromium**); diagrama que não compila **falha o build**. Ligado nodocs.yml(apps) e nobuild-site.yml` (central); publicado e carimbado. tipo: livropara a Documentação Completa (constituição v0.10.5, §4; feedback via loop §6). O livro (projeto/index.md) era forçado a se declarartipo: projeto— e não é uma etapa. Agora tem tipo próprio;modulo:não se aplica (o livro é do app inteiro); ovalida-frontmatter.pyesperatipo: livronesse arquivo (e segue isentandoprojeto/modelagem.md, fragmento sem frontmatter).- Template do livro + guia de modelagem (constituição v0.10.6, §5; feedback via
loop §6).
templates/projeto-index.md(ex-visao.md) publica o esqueleto dos 8 capítulos com o embed domodelagem.mde o<!-- GERADO: changelog -->no lugar. E otemplates/modelagem.mdcravou o meio (antes improvisado caso a caso): ER Mermaid só para o overview de relacionamentos; o dicionário por tabela vai em tabela Markdown (coluna | tipo | chave | nulo? | desde | nota), porque oerDiagramnão expressaNOT NULLnem chave composta e fica ilegível em tabela larga; fluxo de dados opcional.
Alterado¶
- Ordem recomendada do nav do app (constituição v0.10.7): no
templates/mkdocs.yml, as duas portas (Resumo Executivo, Documentação Completa) primeiro; depois referência (Dev/API, Operação, Público); depois histórico (Etapas, Decisões); Glossário no fim. - Massa de dados: regra invertida para o modelo privado-por-padrão
(constituição v0.10.3, §5; feedback via loop §6). O
valida-frontmatter.pybloqueia massa de dados (.xlsx/.csv/.sql/...) só emdocs/public/(a superfície exposta), não mais "em tododocs/fora deanexos/" — a mensagem antiga ainda dizia "docs/ é público", desalinhada do §5. Em pasta privada é livre; risco declarado: até o login (spec 007), o portal servedocs/aberto excetoprivado/, então dado confidencial deve ficar emprivado/, sob responsabilidade do autor.
0.9.0 - 2026-06-16¶
Adicionado¶
- Modelo de dados obrigatório para projeto com banco:
docs/projeto/modelagem.md(ER Mermaid consolidado, fonte da verdade do schema, evoluído no mesmo PR), embutido no livro viapymdownx.snippets(constituição §5). checa-modelagem.py: aviso opt-in no CI de código quando o diff mexe numa migration sem tocar omodelagem.md(com suspeita deDROP/"legado" no SQL), tolerante e nunca fatal — publicado no site e carimbado.
Alterado¶
- Documentação Completa autorada no estado atual (constituição v0.10.x): o
livro deixa de ser montado por aspecto das etapas e passa a ser um esqueleto
autorado (
projeto/index.md) que mostra o sistema como ele é hoje, em ordem lógica que termina nos contratos públicos. O hookvisao-tecnica.pysó injeta marcadores (etapas no Resumo Executivo, changelog no livro) e falha o build em<!-- RECONCILIAR -->não resolvido. Configuração entra no livro, deploy fica emoperacao/,capitulo:vira legado. valida-frontmatter.py: supersessão de decisões verificada em cadeia (obsoleta tem que chegar a uma viva — referência quebrada/ciclo/dead-end = erro) edocs/projeto/modelagem.mdisento da validação de frontmatter.
0.8.0 - 2026-06-15¶
Alterado¶
- Constituição v0.9.0 — Documentação Completa por ASPECTO + Resumo Executivo das
etapas (feedback do Gustavo sobre a novo-4): o livro empilhava etapas inteiras
e virava copia-e-cola — porque os capítulos são aspectos (arc42) mas as folhas
são etapas que cruzam todos. Agora o hook extrai as seções
##de cada etapa e as reagrupa por capítulo (o "Modelo de dados" reúne o de todas as etapas, as "Decisões" vêm dedecisoes/), com atribuição "(Etapa NN)" — o livro arc42 que se lê por aspecto. Roteamento pelo nome da seção (canônicas do template de etapa),capitulo:vira fallback. E o Resumo Executivo (index.md) ganha o marcador<!-- etapas -->: o hook injeta "entregue/planejado" do campo novoentrega:(frase de negócio) +statusde cada etapa. Templatesdoc-projeto.mderesumo-executivo.mdatualizados; §2/§4 + app-novo.
Adicionado¶
- Constituição v0.8.3 — REGRA Nº 3: deferir é explícito, não silencioso. A
migração oportunista (§1.6) é legítima, mas vira escotilha silenciosa quando o
"deferi reescrever o conteúdo das etapas para a barra técnica nova" passa como
rodapé. Nova regra de IA (
claude-regras.md+ CLAUDE.md do central): adiar trabalho que o padrão recomenda é uma decisão — declarada em voz alta no fechamento ("deferido X porque…"); e se o repo ainda não publicou (sem slug no ar), o rename/redirect custa zero → fazer agora, não deferir como legado. Gancho na §1.6 e passo de fechamento na skill/xadm-docs. Feedback via loop §6.
Corrigido¶
- Constituição v0.8.2 — manifesto regenerado a cada bump (inclusive text-only):
um bump que mexe só no texto da constituição (como o v0.8.1) não tocava
artefato rastreado, então o
--checkpassava e o campomanifesto.constituicaoficava atrás da versão vigente (0.8.0 vs 0.8.1) — a/xadm-docsque confiasse nele subdetectaria mudanças. Prevenção: ogera-manifesto.py --checkagora falha semanifesto.constituicao != versão vigente; como o CI do central roda--check, todo bump passa a exigir--update(que re-carimba o campo) para passar — o esquecimento fica impossível. §6 atualizado. Feedback via loop §6.
0.7.0 - 2026-06-15¶
Alterado¶
-
Constituição v0.8.1 — etapa de projeto tecnicamente completa (§2): avaliação do doc fundador do piloto (PROJ-2026-001) mostrou que dava pra ler mas não dava pra implementar — faltava o modelo de dados (ER, tabelas, colunas, chaves), os contratos e a config; o template ainda dizia "não liste toda coluna". Novo critério: cada etapa é tecnicamente completa para o seu escopo (um dev/IA que nunca viu o código implementa o que ela introduz/muda), por composição sem repetir (referencia o que herda, re-enuncia só o que altera — §1.4); o livro (Documentação Completa) compõe o desenho completo do sistema. Seções de completude técnica no §2 (arquitetura, modelo de dados ER+tabelas+colunas+chaves, contratos, fluxos+estados, config, qualidade), com a navalha do §1.2 (design e contrato duráveis, não spec linha a linha). Template
doc-projeto.mdreescrito (modelo de dados com colunas/tipos/chaves; seções Contratos/Configuração/Qualidade). -
Constituição v0.8.0 — "Documentação Completa" (o livro) + Resumo Executivo + Etapas do Projeto (feedback do Gustavo sobre a novo-3): a antiga "Visão técnica" era só links e não virou livro — agora o hook
visao-tecnica.pyconcatena o CONTEÚDO das folhas por capítulo (rebaixa títulos, reescreve links/imagens, preserva Mermaid), virando a página Documentação Completa que se lê de cima a baixo. A home do app vira Resumo Executivo (porta do diretor: problema + solução sem jargão → Documentação Completa). Eprojeto/deixa de ser "PROJ-AAAA-NNN": são Etapas do Projeto —NN-titulo.md(duas casas, semPROJ-/ano), avulso emprojeto/diversos.md. §2/§3/§5 + templates (mkdocs nav, doc-projeto, visao-capitulo) + app-novo atualizados. Legado PROJ- aceito até migração oportunista. -
Constituição v0.7.3 — imagem de manual público vai em
docs/public/img/: a guarda depublic/(constituição §5) tratacomo referência, então um print emdocs/img/(fora depublic/) falhava — corretamente: imagem fora depublic/404 quando o portal trancar. Convenção alinhada: prints do manual (que é público) vivem emdocs/public/img/;docs/img/fica para imagens de páginas internas (raras — diagramas são Mermaid). §2/§3 + screenshots-manual.md - template do manual atualizados; mensagem da guarda agora cita imagem. Feedback do bi-transporte-xls via loop §6.
0.6.0 - 2026-06-15¶
Adicionado¶
-
Constituição v0.7.2 — referência de API gerada pelo CI de docs (§5): TODA doc, inclusive a ref de API, é gerada e publicada pelo pipeline de docs, nunca pelo build/deploy do app. O gerador roda antes do
mkdocs build, para dentro dedocs/→ o link é Markdown normal e o--strictvalida (acaba o anti-padrão do HTML-cru que driblava o strict e 404 no preview, e a duplicação por repo). Split de visibilidade: Javadoc/dartdoc (árvore de classes) → internodocs/dev/api/; OpenAPI (contrato) → públicodocs/public/api/embutido viamkdocs-swagger-ui-tag(spec gerado do código, ex. micronaut-openapi — não do app deployado).templates/docs.ymlganha o passo "Gerar referência de API" por stack;templates/public-api.mdnovo; pins no toolchain. Corrige também: odocs.ymlnão instalava omkdocs-print-site-plugin(bug da v0.6.0). Feedback do bi-transporte-xls via loop §6. -
Constituição v0.7.1 — modelo de acesso SIMPLIFICADO (supera o v0.7.0): o v0.7.0 (frontmatter
publico:+ build duplo + dois domínios) foi commitado mas nunca shipou — o Gustavo simplificou:docs/privado por padrão; o público vive emdocs/public/. O que é público é o que está na pastapublic/(public/index,public/manual/,public/api/swagger) — sem marcação por página, sem build separado, um site só, zero infra. O manual do usuário e a API exposta passam a morar empublic/. Guarda: o validador falha se uma página empublic/linkar para fora depublic/(senão quebraria quando o portal trancar).anexos/privado/segue excluído do build (guarda do que é sensível enquanto não há login). Toolchain do padrão (/padroes/) é pública por design (CIs dependem). Decisão do Gustavo: adiar dois domínios e login — viram specs futuras 006 (dois domínios) e 007 (Google auth); a 005 fecha aqui. Fase 3/4 de.ia/005. - Constituição v0.6.1 — validador fresco (validador stale é falso atestado):
os scripts publicados imprimem na 1ª linha a versão da constituição que
implementam (carimbada no publish pelo Dockerfile); a skill
/xadm-docs(e toda validação local) sempre baixa fresco e confere versão impressa == vigente antes de confiar no "0 erros" — nunca reusa cache de turno. Os scripts (valida-frontmatter.py,valida-release.py,frontmatter-cabecalho.py,visao-tecnica.py) entram nomanifesto.jsonnuma seçãoscriptsà parte dos templates: mudar um script obriga bump da constituição (o--checkfalha), o que torna o carimbo confiável. Origem: um validador da era 0.5.5 deu "0 erros" numa migração a 0.5.20, dando conformidade falsa (feedback §6). - Constituição v0.6.0 — Visão técnica (espinha narrativa): os seis níveis são
bons para consulta, mas uma pilha de folhas não se lê como livro. A Visão
técnica é uma página de leitura ordenada montada no build a partir do campo
capitulo:de cada folha (hookscripts/visao-tecnica.py,on_files+File.generated), na ordem de um esqueleto canônico (9 capítulos, negócio → técnico) — restaura o "ler de cima a baixo para entender" e a porta do diretor, sem desfazer a granularidade (as folhas seguem no seu nível). Pluginmkdocs-print-site-plugin(2.8) gera a página-única/PDF. Intro de capítulo opcional (docs/visao/NN-<capitulo>.md,templates/visao-capitulo.md). Origem: auditoria arc42×seis-níveis (.ia/004/005). Fase 1 da evolução (.ia/005).
Alterado¶
- §5 invertido ("docs/ privado por padrão; público em
docs/public/") + as três classes de acesso registradas. §2/§3: o manual do usuário (nível 6) passa a viver emdocs/public/manual/; estrutura ganha a pastapublic/. Validador: reconhecepublic/manual/(tipo manual) e ganha a guarda depublic/(link que sai depublic/falha). - §1.7 reescrito: de "pronto para IA" para "dois modos: consulta E compreensão" — otimizar só a consulta é a regressão típica da doc-de-folhas.
- §4: novo campo
capitulo:(opcional; enum do esqueleto; validador erra em valor inválido — um typo sumiria a folha do livro). - Hook e plugin distribuídos aos apps:
templates/mkdocs.yml(hook + print-site + nav),templates/docs.yml(curl do hook),Dockerfile(publica em/padroes/),requirements.txt(pin do print-site),app-novo.md(passo de adoção). Manifesto regenerado.
0.5.0 - 2026-06-13¶
Adicionado¶
decidido_em:no frontmatter de decisões (constituição §4) — data em que a decisão foi tomada, distinta deatualizado:(última edição). Cumpre a promessa de "retrato datado" quando o registro nasce retroativo numa migração. Opcional no validador (só confere formatoAAAA-MM-DDse presente, para não quebrar decisão legada). Feedback do bi-transporte-xls via loop §6.- Constituição v0.5.20 — 9 mudanças da auditoria arc42×seis-níveis (BI Vantroba; pauta §6, todas avaliadas e aprovadas pelo Gustavo):
- Hook
scripts/frontmatter-cabecalho.pyrenderiza Status · Responsável · Atualizado em no corpo de cada página (o frontmatter sumia no build) e abre decisão obsoleta com aviso de supersessão. Publicado no site e baixado pelodocs.ymldo app (igual ao validador); wired nos doismkdocs.yml+ Dockerfile. Constituição §6. (propostas #3 e #9 — a data vem doatualizado:, sem o plugin git-revision-date, que quebraria com o.gitfora do build.) navigation.path(breadcrumbs) nos doismkdocs.yml— "onde estou" ao chegar via busca. (#6)- Contrato do Javadoc não-órfão:
docs.ymlfalha sesite/api/existir sem nenhuma página linká-lo; receita empublicar-docs.md+ dica no template. Constituição §5. (#1) - Template opcional
templates/riscos.md(risk register transversal, consolida por link). Constituição §5. (#8) - Princípio anti-drift no §1.9 — um fato, um dono canônico; as demais páginas
linkam (ou
pymdownx.snippets), não copiam. (#7) - Mapa ADR-legado → decisão
NNNNna 1ª migração arc42→seis-níveis (app-novo.md+ skill/xadm-docs). (#10)
Validação¶
valida-frontmatter.pyganhou: aviso (não-fatal) sobre identificador de código volátil em título (*Test/Bulk*etc.) (#4); e erro quando a tabela de decisões de um doc de projeto reafirma um status que contradiz a decisão real (a decisão é a fonte única, §1.9/§5) (#5). Coluna "Status" removida do templatedoc-projeto.md.
Alterado¶
- Constituição v0.5.19 — §1.4 e §2 passam a distinguir correção factual de
superação num registro de decisão: fato incidental errado sobre o código
(número, property inexistente) corrige-se em-lugar com nota datada; só
premissa/raciocínio errado (a escolha poderia ter sido outra) exige superação
(
status: obsoleto+superado-por:). Antes, a regra "não se reescreve, supera-se" era absoluta e forçaria superar uma decisão por causa de um número errado. - §2 (Decisão) — "Alternativas consideradas" lista só as realmente
deliberadas; reconstruir alternativas nunca cogitadas (comum em registro
retroativo) é inventar deliberação (§1.2). Eco no template
templates/decisao.md.
0.4.2 - 2026-06-13¶
Adicionado¶
- Template
templates/release.yml(constituição §6) — separa a validação de contrato de release (push de tag →valida-release.py) doci.yml, que na v0.5.16 virou gate de qualidade e colidiu com oci.ymlantigo dos apps (que era o validador de release). Brecha do ho-scraper. Rastreado no manifesto; embutido emtemplates.md.
Alterado¶
- Constituição v0.5.18 (§6, manifesto): redefinição de propósito de um
template rastreado (mudar o que ele é, não só o conteúdo — ex.
ci.ymlrelease → qualidade) exige nota de migração no CHANGELOG e emapp-novo.md; um re-pull cego quebra o app. Regra que faltava quando a 0.5.16 abriu a brecha doci.yml. - Constituição v0.5.17 (§6): explicita dois workflows de código —
ci.yml(gate de qualidade: análise estática + testes, push/PR) erelease.yml(rede de segurança:valida-release.py, push de tag). Skill/xadm-releaserealinhada (aponta orelease.yml, não "o CI" genérico). Mínimo para app só-script: lint sempre (piso), testes da lógica pura onde existir, sem forçar suíte em script trivial. Migração: app comci.ymlantigo de release renomeia pararelease.ymle adota o novoci.yml.
0.4.1 - 2026-06-12¶
Alterado¶
- Constituição v0.5.16 — aviso de falha do CI agora é webhook nativo da org
(Forgejo 15; spec
.ia/001executada e apagada). O passo manual "Avisar falha no Telegram" (if: failure()) saiu dobuild-site.ymle dotemplates/docs.yml— a notificação vira config única na organização, sem YAML por workflow, cobrindo todos os repos.forgejo.mdreescrito (BotFather → getUpdates → webhook Telegram na org com evento Action Failure). Os secretsTELEGRAM_BOT_TOKEN/TELEGRAM_CHAT_IDda org ficaram órfãos (o webhook guarda token/chat na própria config) — podem ser removidos.
Adicionado¶
- Template
templates/ci.ymlcanônico (constituição §6, "No CI (código)"): gate de análise estática + testes por stack (Java/Gradle./gradlew check, Flutter/Dartanalyze && test, Nodelint && test), com basenode:*para o checkout (lição do ho-scraper) e sem passo de aviso (o webhook da org cobre). Rastreado no manifesto; embutido emtemplates.md. - Constituição v0.5.15 (§2 + screenshots-manual.md): fecha a receita de
screenshots Flutter (estava "em aberto"; spec
.ia/002apagada). Provada no bi-transporte (Vantroba), 9 telas com 1 comando. Correção à direção anterior:takeScreenshotnão roda no desktop Linux → captura comRepaintBoundary.toImage(); alvo é o build Linux desktop (mesmo Skia do web, sem chromedriver); seed via seam de DI em memória; flagkScreenshotMode(equivalente Flutter da dica do.fade); veredito pela existência dos PNGs, não pelo exit code; custo de adoção (suportelinux/, toolchain nativo) documentado. Convenção nova: nome de PNG semântico quando há 1 imagem por tela (dre.png), senão<slug>-NN.
0.4.0 - 2026-06-12¶
Alterado¶
- Constituição v0.5.14 (§5 + versionamento.md): o
/healthdeixa de ser formato livre e ganha shape mínimo ({status, versao}+ opcionais), pois o monitoramento (watchdog) acionou a cláusula "shape vira contrato". Receita de versão em runtime por stack (contribuição §6): Java/Micronaut (task Gradle →version.properties→InfoSourceem/infoe/health+ log nomain; versão do@OpenAPIDefinitioné contrato HTTP à parte), Node (package.json), Flutter web (tem/health, no app ou no nginx), Flutter mobile (sem HTTP → versão in-app viapackage_info_plus), app sem HTTP (log no startup), site estático (/versao.txt). Pertence à área Engenharia (spec 003) — fica em versionamento.md até migrar.
Adicionado¶
- Página Screenshots do manual (
padroes/screenshots-manual.md, constituição v0.5.13 §2): receita reproduzível para os PNGs do manual (regenerável com 1 comando; tooling emscripts/screenshots/, fora dedocs/), separada por stack — web renderizada no servidor (Micronaut/Java) tem a receita provada com shot-scraper +seed.sh+shots.yml(inclui a dica do.fade/modal do Bootstrap); Flutter usa mecanismo próprio (integration_test/flutter drive), com a receita canônica em aberto (shot-scraper não serve em canvas). Ponteiro no templatemanual-usuario.md. Contribuição do loop §6. - Constituição v0.5.12 (§2/§3/§5): define o lar de artefatos não-prosa e
tooling, lacuna achada nos
bi-*-processador-xls. O teste é a publicabilidade (docs/é público): referência não-prosa segura de publicar (schema de contrato, exemplo de payload,.httpsem segredo) vive emdocs/no nível a que pertence (ex.docs/dev/, ao lado dos.md); ferramenta executável, insumo de build e fixture (seed, config de shot-scraper,src/.../resources) ficam fora dedocs/.scripts/reconhecido na árvore do §3 como lar de helpers de dev/ops. - Constituição v0.5.11 (REGRA Nº 2 / §6): no ponto de fechamento de um
trabalho, junto da sugestão de commit, a IA passa a oferecer (em uma
linha) avaliar se o trabalho revelou lacuna/ambiguidade/atrito no padrão —
o loop §6 deixa de depender de o dev lembrar. Sincronizado em
templates/claude-regras.mde noCLAUDE.mddo repo. - Constituição v0.5.10 (§6, "No CI (código)"): o gate de build/test do app
passa a exigir o conjunto análise estática + testes da stack, não só os
testes — lint/estilo que só roda em
check/build(checkstyle,flutter analyze) precisa falhar o PR. Comandos por stack (Java/Gradle →./gradlew check; Flutter/Dart →analyze && test; Node →lint && test) + nota emapp-novo.md. Brecha pega no bi-transporte-xls (violação de checkstyle chegou ao master). Oci.ymlcanônico por stack fica para a migração ao Forgejo 15 (nasce sem o passo manual do Telegram).
Corrigido¶
- Template
xadm-docs-skill.mdganha frontmatter (name/description): sem ele a skill/xadm-docsnão é reconhecida pelo Claude Code, e cada app vinha adicionando na mão — a divergência silenciosa que o template existe para evitar (feedback do loop §6). - Hook
checa-constituicao.shdistingue a direção da diferença de versão: base atrás (migrar), ausente (registrar) ou à frente da publicada (anomalia — central atrasado/versão registrada cedo; não migrar pra baixo). Antes, qualquer diferença mandava "migrar", o que não fazia sentido com a base à frente. Constituição v0.5.9.
0.3.2 - 2026-06-12¶
Alterado¶
- Constituição v0.5.8 (§5):
privado/vira segmento reservado — qualquer pastaprivado/emdocs/é confidencial, não sóanexos/privado/. Os guards passam a casar o padrãoprivado/em vez da string fixa (exclude_docs, guard dosite/nodocs.yml,--excludedo rclone nosync-apps.sh), fechando o risco de um caminho privado novo escapar em silêncio (feedback). A regra de identificadores de código em doc durável passa a citar caminho de arquivo explicitamente: fixar path só quando é contrato (URL, estrutura padrão, config canônica); onde um arquivo mora internamente se descreve pelo papel. - Constituição v0.5.7 (REGRA Nº 2 / §6): a IA passa a sugerir o commit de
forma proativa ao fechar um trabalho e escrever a mensagem pronta para
copiar (sem nunca commitar sozinha). Fixado o formato: assunto de uma linha
(conventional commit) + um parágrafo curto de porquê, sem lista de arquivo
por arquivo. Sincronizado em
templates/claude-regras.mde noCLAUDE.mddo repo.
Adicionado¶
- Constituição v0.5.6 (§6): manifesto de templates — o site publica
padroes/manifesto.jsoncom o hash e a versãomudou_emde cada artefato copiado para os apps (workflowdocs.yml,mkdocs.yml,app.json, hook e skills), e os arquivos crus empadroes/raw/<arquivo>. A/xadm-docspassa a listar mecanicamente quais templates do app estão defasados (mudou_em> versão-base) e re-baixá-los, em vez de inferir da leitura — fechando o modo de falha em que uma mudança de template passou despercebida (ho-scraper).scripts/gera-manifesto.py(--checkno CI,--updateao mexer num template); o--checkfalha o build se um template mudou sem o manifesto refletir, e o--updatecobra o bump da constituição.
0.3.1 - 2026-06-11¶
Adicionado¶
- Constituição v0.5.5 (feedback do bi-transporte-xls): princípio §1.9
"Duas fontes da verdade: o código e
docs/" — artefato de trabalho (spec, plano, prompt) é andaime: destila paradocs/ao concluir e é apagado ("feature pronta" inclui poder apagá-lo sem perda);CLAUDE.mdé roteador, não acervo (§6: regras + versão-base + ponteiros; conhecimento durável vive emdocs/); convenção no §5 sobre identificadores de código em doc durável (citar nome concreto só quando ele é a interface; mecânica interna se descreve pelo papel).
0.3.0 - 2026-06-11¶
Adicionado¶
valida-frontmatter.pycruza ocliente:do frontmatter com oapp.json: app de cliente exige o campo igual em todo doc (pega ausência e typo); app da X-Adm não leva o campo. Semapp.json, não checa (feedback do BI Transporte Vantroba).- Checklist de app novo:
site/no.gitignore(build local gera a pasta; site gerado nunca é commitado) e conferência daconstituicao-versao.txtantes E depois de copiar os templates (release da constituição no meio de uma adoção já passou despercebido). - Versionamento: formato do payload do
/healthdeclarado livre — o contrato é 200 quando vivo + versão legível (oversion.jsondo build Flutter satisfaz); shape só vira contrato se houver monitoramento, e mudará no padrão primeiro. - Aviso de falha do CI no Telegram: passo canônico
if: failure()no final de cada job (mensagem com repo, workflow/job, ref e link da run), com secretsTELEGRAM_BOT_TOKEN/TELEGRAM_CHAT_IDherdados da organizaçãoxadm. Incluído notemplates/docs.ymle no workflow do site central; passo a passo (BotFather, chat_id, secrets) em infraestrutura/forgejo.md. Sem os secrets, o passo só loga — não falha.
0.2.3 - 2026-06-11¶
Adicionado¶
- Constituição v0.5.4 (§3 e §5): regra "docs/ é público" (nada de dado
real de cliente, credencial ou massa de dados solta — brecha apontada
pelo bi-transporte-xls) e pastas padrão
docs/anexos/(anexo público deliberado) edocs/anexos/privado/(confidencial, ex. planilha-base com dados reais — versionada no Git, nunca publicada), cada uma com README obrigatório (templates canônicos novos). - Três guardas independentes para
anexos/privado/:exclude_docsnomkdocs.ymlcanônico (e no do site central), falha no CI do app se a pasta aparecer nosite/(templates/docs.yml) e--excludeno rclone dosync-apps.sh— o portal recusa servir o caminho mesmo publicado por engano. valida-frontmatter.pybloqueia massa de dados (.xlsx,.csv,.sql,.zip...) emdocs/fora deanexos/;.docxdo pré-projeto continua liberado.
0.2.2 - 2026-06-11¶
Corrigido¶
- Constituição v0.5.3 (§3, nota de legado):
guias/migra por conteúdo, não por rename fixo — manual de usuário →manual/, runbook técnico →operacao/. A pasta legada abrigava os dois níveis; o mapa 1:1 anterior mandava runbook paramanual/errado (brecha apontada pelo ho-scraper). Mesmo ajuste notemplates/xadm-docs-skill.md.
Adicionado¶
- Padrões: seção "Ambiente local (Linux/Ubuntu)" em publicar-docs.md — MkDocs global via pipx (sem venv manual, respeitando o PEP 668 do Ubuntu 24.04+), com as versões pinadas da toolchain; link no checklist de app novo.
0.2.1 - 2026-06-11¶
Corrigido¶
- CI do site: o job de validação quebrava no checkout por falta de node no
container (
python:3.12-slim); o workflow agora usanode:22-bookworm-slimcom git e Python instalados antes do checkout — a falha impedia o próprio deploy (a v0.2.0 não tinha chegado a subir).
0.2.0 - 2026-06-11¶
Adicionado¶
- Constituição v0.4.0: modelo de seis níveis com nível Operação
(runbooks técnicos em
docs/operacao/,tipo: operacao) e nível Dev (API reference gerada +docs/dev/opcional para doc escrita à mão). - Template
runbook.md(O que é / Quando usar / Pré-requisitos / Passos / Verificação / Reversão), embutido na página de templates. - Validação do contrato de release no CI do site (
valida-release.pynobuild-site.yml; push de tagv*confere tag ×VERSION). - Constituição v0.4.1, governança: regra "IA não decide sozinha" — todo
repo que usa Claude Code abre o
CLAUDE.mdcom a regra de confirmar com o usuário antes de implementar quando houver ambiguidade ou mais de um caminho possível. - Constituição v0.5.1, governança: regra "IA não faz commit/push sozinha"
(única exceção: a skill
/xadm-release) e bloco canônicotemplates/claude-regras.mdcom as duas regras de IA, pronto para colar no CLAUDE.md de cada repo. - Constituição v0.5.0, governança: rastreio de versão-base — o app
registra em
constituicao:(docs/app.json) a versão que a doc segue; o site publica a vigente em/padroes/constituicao-versao.txte o fonte cru em/padroes/constituicao.md; skill canônica/xadm-docs(compara, avalia e migra com aprovação) e hookSessionStart(checa-constituicao.sh) que avisa ao abrir o Claude Code no repo. - Rodapé do site passa a exibir a versão vigente da constituição e a versão
do próprio site + copyright X-Adm (hook
scripts/copyright-versao.py, que lê o frontmatter da constituição e o arquivoVERSIONno build). - Página IA e Claude Code (
padroes/ia.md): o que é o Claude Code, as regras de governança de IA, o catálogo de skills da plataforma (/xadm-release,/xadm-docs), o hook de sessão e como adotar num repo; constituição v0.5.2 referencia a página no §6.
Alterado¶
- Nomenclatura definitiva das pastas de documentação:
design/→projeto/,rd/→decisoes/,guias/→manual/(tiposprojeto | decisao | dev | operacao | manual); o validador segue aceitando os nomes antigos até a migração oportunista dos repos. - Templates renomeados:
doc-projeto.md,decisao.md,manual-usuario.md. - Skill de release renomeada de
/releasepara/xadm-release(templatexadm-release-skill.mde a cópia instalada neste repo).
0.1.0 - 2026-06-11¶
Adicionado¶
- Site central de documentação (MkDocs Material, pt-BR, identidade visual X-Adm) com constituição, glossário da plataforma e docs de infraestrutura.
- Constituição da documentação v0.3.6 (níveis, frontmatter, convenções, governança com loop de feedback dos apps).
- Templates canônicos: design doc, RD, guia de usuário,
mkdocs.yml, workflowdocs.yml,app.jsone skill/release. - Pipeline descentralizado: apps publicam no bucket
docs-sitese o site sincroniza (~90s) com log de mudanças por app. - Listagem automática de aplicações e API references via
app.json+index.json. - Validadores
valida-frontmatter.pyevalida-release.py, publicados no site público para consumo pelos CIs dos apps. - Checklist de app novo e página de versionamento/release.
- Health check da imagem e carimbos de versão (
/versao.txt) e commit (/commit.txt).