Manutenção da Stack lt (todos os repositórios base)
Os sete repositórios base são mantidos e lançados em ordem de dependência. A fonte canônica é github.com/lenneTech; para lançar é necessário um clone local de cada um, e o caminho do checkout difere por máquina — localize-o em vez de assumir um:
find "$HOME" -maxdepth 5 -type d -name nest-server-starter -not -path '*/node_modules/*' 2>/dev/null
Se um repositório não estiver em nenhum checkout, clone-o no mesmo diretório de workspace que seus irmãos. Estado final desejado: todo repositório atualizado, check verde em todos, pacotes npm publicados, templates tagueados — comprovado por uma execução completa de /lt-dev:fullstack:smoke-test.
Grafo de dependências (dita a ordem)
Onda 1 (paralelizável): nuxt-extensions nest-server lt-monorepo cli
│ │
▼ (aguarde a publicação npm!)
Onda 2 (paralelizável): nuxt-base-starter nest-server-starter
│
▼
Validação: /lt-dev:fullstack:smoke-test (exercita TODOS os repositórios ao vivo)
│
▼
Onda 3 (apenas com achados): correções de patch → relançar repositórios afetados (nest-server-starter: apenas push)
Regra: Um starter só é atualizado quando seu pacote npm realmente resolve no npm, não quando o lançamento do GitHub existe — a ação publish.yml leva minutos.
Consulte o endpoint específico de versão, não npm view. npm view e https://registry.npmjs.org/<pkg> leem o mesmo packument em cache no CDN, e ele fica minutos atrás da publicação:
curl -s -o /dev/null -w '%{http_code}' https://registry.npmjs.org/<pkg>/<version>
# 200 = resolvível agora. Alternativa: invalidar cache com -H 'Cache-Control: no-cache' mais um parâmetro de consulta.
Medido em 04/09/2026: uma sessão consultou npm view por dez minutos e leu "ainda não publicado" enquanto @lenne.tech/[email protected] já estava disponível o tempo todo — o endpoint específico de versão respondeu 200 imediatamente. Da perspectiva do chamador, "ainda não está lá" e "o instrumento está lendo um cache" parecem idênticos, e é por isso que o endpoint é o que deve ser consultado.
Executando as ondas em sessões paralelas
As ondas acima dizem "paralelizável" e isso é literal: uma sessão do Claude Code por repositório, em seu próprio terminal, é como um lançamento de stack realmente fica rápido. A Onda 1 contém quatro repositórios independentes e a Onda 2 mais dois, então o piso de tempo real é o lançamento de um repositório, não seis em sequência.
Isso só funciona se as sessões coordenarem quatro coisas. Tudo executa no protocolo coordinating-peer-sessions, e a divisão por repositório é exatamente o limite que esse protocolo pede: duas sessões nunca tocam na mesma árvore de trabalho.
1. Reivindique um repositório antes de começar. Registre-o no livro-razão primeiro, depois anuncie:
bash "${CLAUDE_PLUGIN_ROOT}/scripts/peer-ledger.sh" read # quem já possui o quê
bash "${CLAUDE_PLUGIN_ROOT}/scripts/peer-ledger.sh" claim "repo:nest-server" "Lançamento Onda 1"
A parte do livro-razão importa mais aqui do que em qualquer outro lugar: uma rodada de lançamento leva horas, sessões vão e vêm, e uma reivindicação que vive apenas em uma mensagem é perdida no momento em que seu terminal fecha. claim recusa um repositório que outra sessão ativa possui e a nomeia; uma reivindicação cuja sessão morreu lê [stale] e está livre para ser tomada, então uma falha nunca abandona um repositório. Libere com peer-ledger.sh release "repo:nest-server" "<version>" quando o repositório for lançado. Sem nada disso, duas sessões lançam nest-server e a segunda cunha uma versão sobre a primeira.
[CLAIM] nest-server — assumindo o lançamento da Onda 1 para este repositório.
Betrifft: o lançamento da stack; ninguém mais deve versioná-lo ou publicá-lo.
Nötig: escolha outro repositório da Onda 1.
Frei: quando eu reportar PRONTO com a versão publicada.
2. Sinalize a Onda 2 com PRONTO, não a faça esperar. A espera entre as ondas é um atraso real de propagação do npm, e a sessão que espera não tem como saber o momento em que ele é limpo, a não ser perguntando ao registro repetidamente. A sessão que publica sabe exatamente quando. Ela envia um PRONTO com a versão:
[READY] @lenne.tech/[email protected] está publicado e resolvível no registro.
Betrifft: nuxt-base-starter — a atualização de dependência da Onda 2 pode começar.
Nötig: pnpm add @lenne.tech/[email protected] e continuar.
A sessão da Onda 2 também pode se inscrever com notify_when_idle na sessão da Onda 1 em vez de fazer polling. De qualquer forma, ninguém fica em um loop sleep contra o registro.
3. Envie SOLVED para qualquer coisa ambiental. As armadilhas empíricas nesta skill são quase todas da máquina inteira, não específicas do repositório: uma leitura remota que silenciosamente não retornou nada, um registro que não propagou, uma fila de runner CI acumulando, uma versão de toolchain que quebrou. A primeira sessão a diagnosticar uma já pagou por ela, e as outras cinco estão caminhando para a mesma parede. Um SOLVED e elas não pagam.
[SOLVED] `git ls-remote` falha no stderr com stdout vazio, então as verificações de tag leem como "sem tags".
Betrifft: todo repositório nesta rodada de lançamento; sua verificação de tag mente da mesma forma.
Nötig: verifique o código de saída ou leia via HTTPS — veja a regra do canal de push.
4. Reporte o fim com LANDED, para que o teste de fumaça comece uma vez. O portão de validação executa depois que todo repositório é lançado. Quem termina por último o inicia; os outros dizem que terminaram e param.
O que não passa por mensagens: quais repositórios existem e em que ordem eles vão (esta skill diz), e em qual versão um repositório está (o registro e as tags dizem). E nenhuma sessão atribui um repositório a outra. O usuário decide quem pega o quê, ou cada sessão reivindica um livre e diz qual.
Regras transversais (todos os repositórios)
-
Pacotes críticos de conexão movem-se em AMBOS os repositórios de framework, de uma só vez. Algumas dependências não são assunto de um repositório — são um protocolo com duas pontas, e nest-server e nuxt-extensions possuem cada um uma ponta.
better-authé o caso que nos ensinou; trate qualquer pacote que ambos os frameworks importam da mesma forma.Ambos o declaram como peer com uma faixa que é byte-idêntica nos dois manifests, e estreita:
>=<menor conhecido-bom> <<próximo minor>, nunca^. better-auth quebra em lançamentos MINOR, então um circunflexo convida a mesma divisão um lançamento depois. Leia a faixa atual dos manifests em vez de daqui — ela se move, e uma versão escrita nesta skill é uma versão que fica desatualizada:node -e 'for (const p of ["nest-server","nuxt-extensions"]) console.log(p, require(`${process.env.HOME}/code/lenneTech/${p}/package.json`).peerDependencies["better-auth"])'Aumentá-la significa: eleve a faixa no nest-server E no nuxt-extensions, fixe a nova versão no nest-server-starter E no nuxt-base-starter, lance todos os quatro. Nunca metade, nem mesmo "só para desbloquear o frontend". Aumentar apenas o LIMITE INFERIOR também é um aumento — é o que diz qual patch é conhecido como bom, e um limite inferior que discorda entre os dois repositórios é o mesmo defeito que uma divisão de versão, um lançamento antes.
O piso não é uma questão de gosto: ele deve satisfazer os PEERS IRMÃOS também. Um pacote como
better-authvem com companheiros (@better-auth/passkey,@better-auth/core) que, por sua vez, exigem como peer uma versão dele. Um piso abaixo do que um companheiro exige abençoa um pareamento que não pode realmente instalar —>=1.7.0permitiu better-auth 1.7.0 ao lado de passkey 1.7.1, que o próprio passkey rejeita (^1.7.1). A faixa não estava errada em geral; ela admitia exatamente uma combinação cruzada inválida, que é precisamente o tipo que nenhuma instalação em qualquer repositório jamais atingiria. Derive o piso do manifesto do companheiro, não da intuição:node -e 'console.log(require("./node_modules/@better-auth/passkey/package.json").peerDependencies)'nuxt-extensions afirma isso mecanicamente em
test/peer-dependency-ranges.test.ts(piso vs. exigência do companheiro, e cada faixa contra a devDependency realmente testada). Vale a pena copiar onde quer que uma faixa peer tenha companheiros.O custo de uma divisão, medido: nest-server fixou better-auth 1.6.26 como dependência direta enquanto nuxt-extensions declarou um peer, então o app moveu para 1.7.1 e a api não pôde seguir. 1.7 dá a
twoFactor.enableum resultado discriminado carregandomethod, que 1.6.26 nunca envia — toda ativação de 2FA em todo projeto fullstack falhou, com um erro de cliente genérico e nada incomum no log do servidor. Ambos os repositórios'checkestava verde o tempo todo: cada um era internamente consistente, e apenas o workspace montado tem ambas as metades.Três guardas capturam isso hoje, e nenhum deles substitui esta regra — eles capturam o erro, a regra o previne:
-
Quando os manifests são mesclados (lt CLI
hoist-workspace-pnpm-config.ts, desde 1.45.0). O hoist é último-escritor-vencedor, o que é certo para raiz-vs-sub e uma armadilha entre irmãos. Reportado: dois subprojetos definindo uma chave diferentemente na mesma execução; o caso incremental (add-apientãoadd-app, onde a execução anterior já hoistou e esvaziou sua fonte); e um repositório contradizendo a SI MESMO através depackage.json#pnpme seu própriopnpm-workspace.yaml.allowBuildsnão é meramente reportado mas mesclado negação-vencedora — um aviso não para um script de instalação que um projeto explicitamente recusou, eoverridespermanece apenas reportado porque não há direção segura para uma versão. -
No workspace montado (
lt-monorepo/scripts/check-workspace-consistency.mjs, desde 3.10.0). Falha quando api e app resolvem um pacote crítico de conexão diferentemente, quando os dois frameworks prometem faixas peer diferentes, ou quando um membro tem o pacote instalado mas não o fixa em lugar nenhum —autoInstallPeerspadrão é verdadeiro, então um peer não fixado concorda hoje e está livre para derivar na próxima instalação. -
Em comportamento (
nuxt-base-starter/.github/workflows/test.yml, jobe2e-auth, verde desde 2.22.3). Inicializa MongoDB e nest-server-starter e executa a suíte de autenticação contra uma API real. A única camada que vê um contrato quebrado em vez de uma diferença de versão — a outra compara declarações, e as declarações estavam verdes durante toda a divisão.Duas coisas que ele precisa e que são fáceis de perder, ambas encontradas por suas próprias primeiras execuções: as dependências do template devem ser instaladas separadamente (ele tem seu próprio lockfile, e sua cadeia de verificação começa com
cross-env— uma de suas próprias devDependencies), e um banco de dados vazio roteia todo visitante para/auth/setup, então o primeiro admin deve ser criado viaPOST /system-setup/initantes da suíte executar.
O teste de fumaça é o portão de ponta a ponta: ele constrói um projeto fullstack real, então é o único lugar onde uma divisão de conexão aparece como um fluxo falho em vez de como uma diferença de versão.
-
-
Nada é publicado antes de
/lt-dev:reviewter executado sobre o diff de lançamento daquele repositório (/lt-dev:review --base=<última tag de lançamento>, que inclui arquivos não comitados e não rastreados), após sua manutenção e antes de seu aumento de versão. Pegue a tag deorigin/main:git describe --tags --abbrev=0 origin/main. Tags de lançamento ficam emmainem todo repositório base, e as do nest-server são commits de merge quedevelopnunca contém, então uma consulta a partir deHEADretorna uma tag com lançamentos de idade (medido em 27/10/2026 no nest-serverdevelop:11.33.1em vez de12.0.0, uma revisão sobre 851 arquivos em vez de 14). Cada repositório de uma cadeia passa por seu próprio diff; um achado que a revisão não pôde corrigir para o lançamento daquele repositório e tudo a jusante dele. Decidido por Kai em 21/10/2026, para que uma cadeia de lançamento automatizada nunca publique código que ninguém revisou. -
Nenhuma mudança → nenhum lançamento. O ÚNICO caso que pula um lançamento é um repositório onde realmente NADA mudou (árvore de trabalho limpa E nenhum commit desde a última versão lançada) — nunca cunhe uma versão que não contém nenhuma mudança. QUALQUER mudança real no repositório — atualizações de dependência, código, scripts, lockfile, configurações de ferramentas — justifica uma nova versão; não julgue se uma mudança é "digna de lançamento". Um repositório inalterado é reportado como "já atual — nenhum lançamento" e pulado. A única exceção é nest-server-starter: sua versão se move apenas com uma versão do nest-server, então suas próprias mudanças são comitadas e enviadas sem um lançamento e são entregues sob a próxima (recipes.md, nest-server-starter). A referência é o ARTEFATO PUBLICADO: para pacotes npm, commits que não podem alcançar o tarball (fora do conjunto
filesdo package.json — por exemplo,.claude/agent-memory/**, configuração CI) não disparam um lançamento próprio; verifique comnpm pack --dry-runquando estiver em dúvida. Tais commits simplesmente acompanham o próximo lançamento real. Para templates, o artefato é o próprio repositório, então todo commit conta. -
Canal de push: pergunte ao script, que decide funcionalmente:
bash "${CLAUDE_PLUGIN_ROOT}/scripts/check-push-channel.sh" [<raiz-do-rep>] # omita dentro do repositório; nunca passe "$(pwd)" # -> ssh<TAB>github.com<TAB>autenticado como: Hi kaihaase! … # -> https<TAB>github.com<TAB>sem autenticação SSH (…)Em
https, envie via HTTPS:git -c credential.helper='!gh auth git-credential' push https://github.com/lenneTech/<repo>.git <branch>.gh release createnão é afetado de qualquer forma.Execute a verificação quando um push falhar em algo que parece um problema de direitos. Medido em 08/09/2026 no nest-server-starter:
git push origin mainfalhou comPlease make sure you have the correct access rights and the repository exists, enquanto um push para nest-server via SSH funcionou nos mesmos minutos. Nada estava errado com a conta, o status de colaborador ou a URL remota — SSH para github.com estava morto para aquele caminho apenas, a verificação disse `httpsgithub.comsem resposta do fr
... [truncado para tradução]