▲ Delonix Docs
v0.1.0
Portuguese only. This guide is authored in Portuguese; the language toggle does not translate its body.

Promessa de estabilidade da CLI

Aplica-se a partir da v0.42.3. Escrita para o 0.x — cada quebra listada abaixo tinha de esperar por um major. A v1.0.0 é esse major: fechou a única quebra pendente (os atalhos de topo), e esta lista passa a valer como a promessa de semver real de resto em diante — um breaking change deixa de caber num 1.x.

Um motor sem contrato não se automatiza. Quem escreve um Makefile, um passo de CI ou um script de deploy precisa de saber o que pode partir num upgrade — e a resposta «é 0.x, tudo pode partir» é verdadeira e inútil: garante que ninguém depende de nada, o que é o mesmo que ninguém adoptar.

Isto listava o que se compromete e o que não se compromete dentro do 0.x, que é o que falta a maior parte dos projectos nessa fase. Desde a v1.0.0 é mais do que isso: é o contrato de semver do projecto.

Estável — não quebra sem um major

Os verbos de ciclo de vida de container, com os nomes e a semântica que Docker e Podman lhes dão:

container run  create  ps  stop  start  restart  kill  rm  exec  logs  attach  stats
                wait   inspect   port   rename   pause   unpause
image     pull  ls  remove (rm)  tag  save  load  push   build (delonix build)
raiz      run  create  ps  start  stop  restart  kill  rm  exec  logs  attach  stats
          pull  images  rmi  tag  save  load  push            (aliases dos de cima)
          wait                                        (polimórfico — ver abaixo)

Concretamente, garante-se:

Quebra de contrato na v1.0.0. Até à v0.69.0 os atalhos de topo (ps, run, exec, logs, rm, images) estavam aqui, como reescrita de argv para container <verbo>/image list. Saíram — corte limpo, sem alias: a grafia antiga falha com unrecognized subcommand, nunca em silêncio, a mesma regra que a reorganização da v0.30.0 já seguia. Os grupos continuam: delonix container ps, delonix container run, delonix container exec, delonix container logs, delonix container rm, delonix image list (ver a nota da v2.0.0 abaixo — essa grafia mudou outra vez). Os códigos de saída não mudam nesta versão — ver a secção abaixo.

Reintrodução na v5.x. Os atalhos de topo VOLTARAM — delonix run, create, ps, start, stop, restart, rm, exec, logs, pull — por uma razão que a nota da v1.0.0 não pesou: a familiaridade de quem vem de Docker/Podman vale mais do que a pureza de uma CLI sem sinónimos, e o objectivo declarado é trocar o executável e manter o fluxo. NÃO é a reescrita de argv de outrora (a grafia antiga, frágil, que esta mesma nota tinha razão em cortar): cada verbo de topo é agora um subcomando clap de pleno direito que carrega a MESMA struct de argumentos e despacha para o MESMO handler do grupo — não há segundo caminho de código a divergir, e o --help é o mesmo módulo a módulo. É por isso que entram na promessa de estabilidade acima, e não numa à parte: o que delonix container run promete, delonix run promete pela mesma linha. O conjunto reintroduzido na primeira passagem foi o dos fluxos mais frequentes.

Tabela completada na linha 0.1.0 (o renumber que sucede à baseline histórica v5.1.x). Os restantes verbos da tabela Docker/Podman entraram pelo mesmo mecanismo — subcomando clap de pleno direito, MESMA struct de argumentos, MESMO handler do grupo: os de container kill, attach, stats, e os de imagem images (alias de image ls), rmi (alias de image rm), tag, save, load, push. Ficam de fora só login/logout — não constam da tabela pedida, e a sua forma de grupo (image login/logout) chega.

Comandos genéricos: política de resolução, nunca adivinhação. Três nomes da tabela colidem com significados que este motor já tinha ou que seriam ambíguos; resolvem-se por regra escrita, não por palpite:

  • wait é um só verbo com duas formas, escolhidas pela GRAMÁTICA. Um ou mais operandos posicionais de container ⇒ a forma docker wait (bloqueia até cada um sair e imprime o código de saída — o MESMO handler que container wait). Zero operandos ⇒ a forma de manifesto (delonix wait -f <ficheiro>, a que este motor já tinha). As duas gramáticas são disjuntas; misturá-las — um operando de container junto de -f/--timeout — é RECUSADO em voz alta, nunca resolvido em silêncio. A forma de container herda a promessa do grupo container; a de manifesto continua classificada com o resto da superfície de manifesto (NÃO estável).
  • inspect e diff ficam COM TIPO (type-scoped). Não há um delonix inspect <nome> genérico que decida sozinho se o nome é um container ou uma imagem: container inspect resolve só containers (JSON de docker inspect), image describe só imagens, container diff só containers, e delonix diff/delonix wait -f na raiz são do MANIFESTO. É a mesma regra que mantém separadas operações com efeitos diferentes (remover um recurso vs limpar os não usados): um resolvedor genérico que adivinhasse o Kind é exactamente o que esta CLI recusa fazer.

Quebra de contrato na próxima major (ADR-0062). container run de uma imagem que declara USER passa a correr como esse utilizador, como no Docker e no Podman; até à v4.5.0 corria como uid 0 dentro do container, declarasse a imagem o que declarasse. --user 0 (ou user: "0" num manifesto) é a forma explícita de ficar root. Uma imagem sem USER não muda. E um container com utilizador não-root deixou de ser dono do seu rootfs e de re-apropriar bind mounts do host: escreve só onde a imagem lhe dá posse, num volume nomeado vazio, ou onde as permissões do host deixam.

Quebra de contrato na v2.0.0. O B2 da reestruturação da CLI (v0.67.0) tinha renomeado image ls/image rm para image list/image remove — a única excepção de nomenclatura numa CLI onde as outras 15 folhas do tipo "listar" usam ls (network ls, volume ls, vm ls, pod ls, secret ls, stack ls, …), seguindo o padrão Docker/Podman que este mesmo documento já cita para os verbos de container. Revertido: image list volta a image ls (image remove fica). Corte limpo, sem alias — a grafia list falha com unrecognized subcommand, nunca em silêncio.

Códigos de saída

Alteração de contrato na v0.49.0. Até à v0.48.0 toda a falha do motor era 1 — «não existe» e «rebentou» eram o mesmo número. Continua a valer que 0 é sucesso e não-zero é falha, portanto um if delonix …; then não muda de comportamento; o que muda é para quem testa [ $? -eq 1 ] à espera de uma falha específica. Ver a nota de migração no fim desta secção.

Alteração de contrato na linha 0.1.0. Com --detailed-exitcode, um stack plan cujo plano tem um Conflict — um recurso com o carimbo delonix.io/stack de outra stack — respondia 0, porque um conflito não é uma alteração. Passa a responder 5 (DX-5601), o mesmo que o stack apply recusaria, e ganha ao 2. Um gate escrito como «0 passa, 2 é deriva, o resto é erro» fica certo sem mudança; quem só testava [ $? -eq 0 ] passa a ver vermelho exactamente onde o apply ia falhar. Sem a flag, o plan continua a responder 0.

Alteração de contrato na linha 0.1.0 (2). O stack plan (e o plan) ganhou --prune, e passou a planear com as flags do apply. Sem --prune, um recurso que esta stack possui e o manifesto já não declara continua listado (-), mas como mantido: changed: false no -o json e fora do --detailed-exitcode. Antes contava como alteração, e um gate de deriva sem poda respondia 2 para sempre, porque o apply que o acompanha nunca o remove. Com --prune responde como antes: a remoção é uma alteração (2). Quem fazia o gate dar 2 com recursos que saíram do manifesto passa a precisar de --prune. O action continua delete, e o planDigest não muda.

Alteração de contrato na linha 0.1.0 (3). O stack apply --dry-run (e o delonix apply --dry-run, o mesmo caminho) só imprimia o manifesto com os defaults e respondia 0 sem ler a máquina — um plano que o apply recusa passava na pré-visualização. Continua a imprimir o mesmo manifesto no stdout, mas agora corre tudo o que o apply corre antes da primeira escrita e sai como ele sairia:

  • 5 (DX-5601) com um recurso que outra stack carimbou;
  • 5 (DX-5390) com um --plan-digest que já não é o plano;
  • 1 (DX-1000) com um Replace ou um Reboot sem --replace ou --reboot, com uma gralha nessas flags, ou com um valor que não tem a forma <Kind>/<nome>, nome ou all;
  • 77 (DX-7000) quando o root do estado não se deixa ler e preparar.

Nenhum recurso é criado nem mudado e nenhuma revisão é gravada. Mas o root não fica intocado: os stores criam as suas directorias e a chave do keyring dos túneis, como o stack validate já fazia. Quem queria só o manifesto, sem a máquina, tem o delonix manifest render, que continua a responder 0.

código significado
0 sucesso
1 falha sem classe própria (o default de sempre)
2 uso inválido (o do clap) — e, em stack plan --detailed-exitcode, «há alterações»
3 o recurso existe mas não está a correr
4 não existe esse recurso
5 conflito — o nome já está tomado; e, em stack plan --detailed-exitcode e stack apply --dry-run, um plano com um recurso que outra stack carimbou (DX-5601)
69 capacidade que este host não tem — uma ferramenta por instalar, um backend indisponível
74 o sistema de ficheiros disse que não — disco cheio, caminho impossível
77 permissão negada — o remédio é uma permissão, e depois repetir
124 o prazo esgotou-se — stack wait --timeout, e o que vier a ter prazo

3 e 4 não são números inventados: são os códigos de estado do LSB que o systemctl ainda fala (3 = o programa não está a correr, 4 = não há tal unidade). 5 não tem convenção por trás — é o número livre seguinte, abaixo da gama que a shell usa (126/127, e 128+N para sinais).

74 e 77 saíram do balde do 1, e não de nenhuma classe publicada. Até à v0.66.1 uma falha de I/O respondia 1, que a linha de cima descreve como «falha sem classe própria» — dar-lhe classe é o que esta tabela existe para fazer, e um script com *) exit 1 continua a cair no mesmo ramo. O 77 é recortado do 74 pelo kind do erro, porque é assim que ele chega: medido contra um state root sem bit de escrita, volumes create e secret create vêm ambos como permissão negada. É a falha mais accionável que existe — corrige a permissão e repete — e respondia o mesmo número que um disco cheio.

69 e 124 também não. 69 é o EX_UNAVAILABLE do sysexits.h; 124 é o que o timeout(1) devolve quando o prazo passa, e está portanto já nos dedos de quem embrulha um comando num. Entraram porque tinham produtores reais mal classificados, não para completar uma tabela: um stack wait que esgotava o tempo respondia 1 — o mesmo número de um apply rebentado, no comando cuja função inteira é ser lido por CI — e um wg/virt-customize/ngrok em falta respondia 1 também, indistinguível de um erro de escrita numa flag. As duas chamadas seguintes de um reconciliador são opostas: esperar mais, ou parar e instalar alguma coisa.

delonix stack wait -f delonix-manifest.yaml --timeout 120
case $? in
  0)   ;;                     # tudo de pé
  124) exit 0 ;;              # ainda a subir — o pipeline seguinte volta a tentar
  69)  echo "falta uma ferramenta neste nó" >&2; exit 1 ;;
  *)   exit 1 ;;              # qualquer outra coisa: pára
esac

O número do dicionário: DX-CDNN

O código de saída e o DX_* dizem a classe. O número DX-CDNN diz qual falha (ADR-0043): o milhar é a classe, a centena o domínio, os dois últimos a falha, e 00 a própria classe. A CLI imprime-o na linha de erro — error[DX-4501] no such VM: dev — e delonix explain DX-4501 diz o que significa e o que fazer (--json para scripts). O dicionário completo está em delonix explain codes e na página Dicionário de códigos, gerada da mesma tabela.

Um número nunca muda de significado nem é reutilizado: pode acrescentar-se, e uma falha que deixe de existir fica com o número retirado. A mensagem ao lado pode ser reescrita e é traduzida; o número é o contrato. Enquanto um sítio do motor ainda não tem entrada própria, responde com a entrada genérica da sua classe (DX-4000, DX-1000, …).

A identidade textual: DX_*

O número serve quem lê $?. Quem lê texto — um cliente HTTP, um consumidor de -o json, um pipeline de logs — tem o código DX_*, que é a mesma classificação noutra grafia:

DX_* código quando
DX_NOT_FOUND 4 não existe esse recurso
DX_NOT_RUNNING 3 existe, mas não está a correr
DX_CONFLICT 5 o nome já está tomado
DX_UNAVAILABLE 69 capacidade que este host não tem
DX_TIMEOUT 124 o prazo esgotou-se
DX_INVALID_ARGUMENT · DX_REGISTRY · DX_SYSCALL_FAILED · DX_INVALID_STATE · DX_IO 1 falhas sem número próprio

Estes nomes são contrato: um código pode ser ACRESCENTADO; um existente nunca muda de grafia nem de significado.

A relação é assimétrica de propósito. Um DX_* mapeia sempre para UM número — se mapeasse para dois, o $? e o texto contradiziam-se para a mesma falha. Mas o 1 carrega VÁRIOS códigos, porque é o balde «sem classe própria» e o texto pode dar-se ao luxo de ser mais fino: cada NÚMERO é uma promessa que tem de valer o resto do 0.x, enquanto DX_REGISTRY ao lado de DX_INVALID_ARGUMENT não custa nada. Há teste a exigir as duas metades desta regra, incluindo que o balde continue a ser um balde.

Hoje o código sai na API de gestão (delonix serve api), como campo acrescentado ao corpo de erro — {"error": "...", "code": "DX_NOT_FOUND"}. O campo error não foi tocado: a regra do ADR-0005 (acrescentar sim, remover ou mudar de tipo não) vale aqui como vale no -o json.

O que continua sem código próprio, e é honesto dizê-lo: permissão negada e falha temporária foram considerados e ficaram de fora — não há hoje uma variante de erro que os produza (as falhas de permissão chegam embrulhadas no errno de uma syscall, e o retry que existe acontece dentro do motor e nunca chega a quem chama). Publicar um número que nada constrói é um número que nunca pode voltar.

O que isto resolve é concreto: um reconciliador — o Makefile, o passo de CI, o ciclo em bash que conduz esta CLI — não conseguia separar «cria, porque falta» de «pára, porque falhou» sem ler a MENSAGEM de erro. E a mensagem é traduzida (--l18n=pt), portanto um script que faz grep 'no such' funciona na máquina onde foi escrito e deixa de classificar num nó com outra locale.

delonix container inspect web >/dev/null 2>&1
case $? in
  0) ;;                       # está lá
  4) delonix container run -d --name web nginx ;;   # falta — cria
  3) delonix container start web ;;                 # existe, parado — arranca
  *) exit 1 ;;                # qualquer outra coisa: pára, não adivinhes
esac

O código de um run/exec continua a ser o do WORKLOAD, não o do motor. run em primeiro plano devolve o código do processo do container, exec o do comando, e healthcheck sai 1 quando não saudável — as três promessas de sempre, inalteradas. A consequência a reter: um container que saia 4 sai 4, logo o $? de um run/exec nunca se lê como uma das classes acima — esse número foi escolhido pelo workload, não pelo motor.

O que fica de fora, e é honesto dizê-lo: uma pré-condição do host por satisfazer (uma sessão sem delegação de cgroup, por exemplo) não tem código próprio — o motor avisa e continua, portanto não há falha para classificar. E os grupos ainda não estáveis (ver a lista mais abaixo) podem responder 1 onde um comando estável já responde 4: o workload describe de um nome que não existe é o caso conhecido.

Migrar

Estável em conteúdo, não em formato

As tabelas de ls/ps. As colunas podem mudar de largura, de ordem ou ganhar irmãs — são feitas para humanos e medem-se pelo conteúdo real. Um script que faça awk '{print $3}' sobre elas parte, e isso não conta como quebra de contrato.

Para automação há -o json, e é ele que é estável: um array JSON por recurso, campos podem ser ACRESCENTADOS mas não removidos nem com o tipo mudado (ADR-0005). Verificado a funcionar (2026-09-25, v4.4.0) em container ps, image ls, volume ls, network ls, vm ls, secret ls, workload ls e no verbo genérico get <plural> (get pods, get volumes, …), que é o caminho de listagem dos Kinds sem ls próprio — o pod ls já não existe, e o grupo storage fundiu-se no volume. Também inspect e -q/--quiet. Excepção medida: backup ls ainda não aceita -o json.

Uma versão anterior deste documento dizia que -o json estava «por fazer e é a lacuna reconhecida aqui». Estava errado — existe desde a ADR-0005. É exactamente o erro que o paridade-docker-podman.md abre por corrigir: inferir ausência a partir de um sintoma, sem ir ver.

O schema dos manifestos — estável, e é o que mais importa

Esta secção substitui a linha que dizia que o schema «é aditivo na prática, mas não é uma promessa». Era o compromisso ao contrário: a CLI estava mais protegida que o formato declarativo, quando é o formato que as pessoas põem em git e revêem em PR. Um delonix-manifest.yaml só se versiona se se souber que não parte sozinho.

Para os Kinds com spec tipado — Container, Pod, Volume, Network — garante-se, dentro do 0.x:

A verdade não é este texto, é o schema: delonix manifest schema emite-o a partir do próprio código (ADR-0007), e o mesmo ficheiro está publicado em schema/v1/delonix.json. Um teste do repositório falha se o publicado deixar de ser o gerado, precisamente para esta página não voltar a poder mentir.

O que o schema RECUSA, e vale saber porque é o que aparece sublinhado no editor: um campo desconhecido (um typo), um kind que o motor não conhece — um typo no nome, ou um Kind removido — e um apiVersion que não é o grupo daquele Kind. Até à v0.65.x o kind era uma string livre e qualquer nome passava, por isso um kind: Contaner validava limpo e um Egress já removido também; e o apiVersion era fixo no legado, por isso a grafia de grupo — a canónica — era sublinhada como se fosse erro. Um validador que discorda do motor é pior do que nenhum, porque o visto verde é o que as pessoas seguem.

Aponta o editor e escreve manifestos com completação e validação:

# yaml-language-server: $schema=https://ngolacloud.github.io/delonix/schema/v1/delonix.json
apiVersion: compute.delonix.io/v1alpha1
kind: Pod
metadata: { name: web }
spec:
  containers:
    - name: web
      image: nginx:1.27

Há também uma extensão de VS Code que traz isto já ligado, mais um template por Kind: angolardevops/delonix-vscode. Aponta para o MESMO ficheiro publicado acima — buscado ao vivo, não embutido — por isso o editor e o stack apply não podem discordar.

Para saber o que mudou entre duas versões, não há uma página escrita à mão — haveria a segunda fonte de verdade que a ADR-0007 aboliu. Há um comando:

scripts/schema-diff.sh v0.46.0          # dessa tag até à árvore actual
scripts/schema-diff.sh v0.46.0 v0.47.0  # entre duas tags

Compara campo a campo (nome e tipo), não o JSON cru, e sai 1 quando há diferenças — serve directamente como gate de CI. Um campo removido ou com o tipo mudado é assinalado como quebra de contrato, que é o que esta secção promete não acontecer.

Todos os Kinds têm hoje schema gerado. Esta secção dizia que Vm, Cluster, ShareVolume, Image, Secret, Ingress, FirewallPolicy, HTTPRoute, Tunnel, Workload e Stack não o tinham — deixou de ser verdade: delonix explain <Kind> responde para cada Kind que delonix api-resources lista (verificado a 2026-09-25, v4.4.0), com os nomes canónicos (VirtualMachine, KubernetesCluster, NetworkPolicy, Gateway; os nomes antigos Vm/Cluster/FirewallPolicy/Tunnel continuam a resolver como alias). ShareVolume já não existe: é um kind: Volume com bloco share:. Se um Kind futuro chegar sem schema, o delonix explain recusa-o a dizer que Kinds o têm, em vez de o omitir.

Três Kinds deixaram de existir nesta série, fundidos no que já faziam: Egress → FirewallPolicy com direction: egress; Dependency → FirewallPolicy (açúcar, reduzido no load); Storage → kind: Volume com um bloco nfs:/cifs:/webdav:. Os nomes antigos continuam a carregar, com aviso de depreciação — a regra do «corte limpo» aplica-se a comandos, e um manifesto em git merece um degrau em vez de um erro.

O ficheiro de providers do nó — config.delonix.io/v1

O providers.yaml (ADR-0054) diz que providers o nó tem, como o motor chega a cada um e qual serve um pedido que não nomeia nenhum. Desde o catálogo 1.1.0 (ADR-0059 F1) aceita também um appliance OPNsense (type: opnsense) e o bloco networkDefaults, que diz que provider responde a cada papel de rede (segment, gateway; nat, ipam e dns são recusados até existir quem os sirva). Desde o ADR-0064 D6 aceita também type: powerdns: a credencial do PRÓPRIO motor para um servidor PowerDNS (url, controllers, auth.keyFile, allowPlainHttp), usada só para remover os registos de gateway que o nó Proxmox escreve e nunca remove. O defaultProvider continua a ser só o de computação. Procura-se por esta ordem, e o primeiro ficheiro que existe ganha, sem fusão: DELONIX_PROVIDERS_CONFIG, $XDG_CONFIG_HOME/delonix/providers.yaml (ou ~/.config/…), /etc/delonix/providers.yaml.

É um formato publicado, com a mesma promessa que o schema dos manifestos dentro do 0.x: uma chave nunca é removida nem muda de significado, uma chave nova é sempre opcional, e apiVersion: config.delonix.io/v1 só muda com um v2 que não sai sem o v1 continuar a ser lido.

A verdade é o schema, gerado dos tipos que o motor lê: delonix provider config schema, publicado em schema/v1/providers.json, com o mesmo teste a falhar se o publicado deixar de ser o gerado. O schema recusa uma chave desconhecida, outra versão, um tipo de provider que não existe e um segredo escrito no próprio ficheiro (tokenSecret, password, secret — só por referência: tokenSecretFile, passwordFile, secretFile, secretRef).

O schema diz se o ficheiro está bem escrito; o delonix provider config validate diz se ele serve: um defaultProvider ou um networkDefaults sem entrada no ficheiro, um ficheiro de token ou de segredo legível por outros utilizadores, uma CA que não existe. Nenhum dos dois contacta um nó.

# yaml-language-server: $schema=https://ngolacloud.github.io/delonix/schema/v1/providers.json
apiVersion: config.delonix.io/v1
defaultProvider: libvirt
providers:
  - type: libvirt
  - type: opnsense
    url: https://fw.example
    auth: { keyFile: /etc/delonix/opnsense.key, secretFile: /etc/delonix/opnsense.secret }
networkDefaults:
  gateway: opnsense

NÃO estável — pode mudar em qualquer versão

Mudou na v0.67.0: delonix backup <kind> <nome> passou a delonix backup create <kind> <nome>, e o delonix restore de raiz passou a delonix backup restore <arquivo> — sem o <kind> posicional, que o arquivo já regista (continua a poder afirmar-se com --kind para que uma discordância seja recusada). O agendamento saiu de flags do backup para delonix backup schedule, com a mesma semântica: instala o temporizador e tira o primeiro arquivo. Corte limpo, sem aliases — a forma antiga falha com «unrecognized subcommand», nunca em silêncio.

delonix system backup não foi tocado nessa data. É outro âmbito — o state root inteiro de um nó — e não uma segunda porta para este grupo.

Mudou depois (Sprint 4 da reestruturação da CLI, 2026-09-12): o próprio system backup/system restore foi renomeado para system snapshot create/system snapshot restore — mesmo vocabulário de vm snapshot/ volume snapshot (captura num instante), só que à escala do nó. O ÂMBITO não mudou nem se fundiu com este grupo — só a PALAVRA partilhada («backup») desapareceu, que era a fonte real da confusão que o parágrafo anterior já andava a explicar por escrito. Corte limpo: a forma antiga falha com «unrecognized subcommand». * gitops (reconcile/status/suspend/resume, ADR-0021) — grupo novo a 2026-10-12, NÃO estável. Age sobre uma kind: GitOpsSource que já existe; a fonte declara-se com stack apply, como qualquer outro Kind. O registo e o estado de cada passagem em $DELONIX_ROOT/gitops/ são estado interno (lê-se com gitops status -o json, nunca do disco). * oci-runtime (create/start/state/kill/delete, ADR-0080) — a CLI compatível com o runc: o init do próprio motor por trás do contrato do runc, para poder ocupar o lugar do runc/crun. Superfície nova e EXPERIMENTAL — o contrato que ela imita é o do runc, não uma promessa própria deste motor, e os verbos/estados podem ainda mudar enquanto a conformidade assenta. * Tudo o que começa por net netns — plumbing interno exposto por conveniência de depuração. * O formato dos ficheiros de estado em $DELONIX_ROOT. Lê-se pelo inspect, nunca do disco. * stack history, stack rollback e o conteúdo de $DELONIX_ROOT/stacks/ (ADR-0019). É um registo do que foi aplicado, e o desenho promete explicitamente que nada o lê para decidir o que existe: apagar essa pasta não muda o que o plan, o apply, o prune ou o destroy fazem — só perde o histórico, e há gate na bateria E2E a exigi-lo. Automação que dependa da presença de uma revisão está a apostar contra essa promessa.

Como uma quebra é feita, quando tem de acontecer

Precedente já cumprido pelo projecto: a reorganização da v0.30.0 (netns → net netns, cri → serve cri, …) foi um corte limpo, sem aliases — a forma antiga falha com «unrecognized subcommand», nunca em silêncio.

Isso mantém-se como regra: falhar alto. Um alias de compatibilidade que muda de comportamento é pior que um erro.

E uma lição que custou esta sessão: essa quebra deixou um chamador INTERNO por actualizar (o delonix-cri continuou a invocar delonix netns attach), o que partiu a criação de pod rootless durante meses — ver cri-conformance.md. Um corte limpo obriga a fazer o grep por chamadores em TODO o workspace, não só na documentação.

Delonix Engine · Apache-2.0 · ngolacloud/delonix · Referência gerada do --help real do binário por docs/gen.py.Delonix Engine · Apache-2.0 · ngolacloud/delonix · Reference generated from the real --help of the binary by docs/gen.py.