Quando o loop converge e o curso está escrito, uma última coisa acontece sozinha: o curso é publicado. Dois níveis independentes — um gist privado, somente por link, e um site hospedado no Cloudflare Pages — dão ao trabalho um lugar para viver além da pasta em que nasceu. O course/ do repo continua sendo a casa canônica; publicar só amplia o alcance.
Todo loop termina da mesma forma. O artefato converge — ele realmente atinge o "pronto" mensurável que você definiu no início — e um curso pequeno e autossuficiente é escrito para explicá-lo. Nesse exato momento uma última coisa acontece automaticamente: o curso é publicado, para que viva em algum lugar além da pasta em que nasceu. Esse passo final é o Publish Gate.
A publicação acontece em dois níveis, e eles são independentes. O primeiro nível é um gist privado — um único instantâneo, somente por link, que você pode entregar a qualquer pessoa e que abre como um pequeno site navegável. O segundo nível é um site hospedado no Cloudflare Pages — uma URL real, no ar, numa rede global, mantida privada por um portão de login. Você pode ter um, ambos ou nenhum, e o sistema te diz exatamente quais níveis de fato saíram.
Este é o único momento em todo o loop em que o sistema alcança para fora por conta própria — ele cria algo na internet sem parar para perguntar. Isso soa ousado, então a regra ao redor é deliberadamente estreita: é a única ação para fora autorizada de antemão, ela só publica o curso que você acabou de fazer, e ela se pula no instante em que a situação diz que não deveria. Tudo o mais que o loop faz permanece na sua máquina.
Pense nisso como… terminar um livro. O manuscrito na sua mesa é o original real e editável — esse nunca desaparece. Mas, uma vez pronto, você também faz duas cópias que saem da mesa: uma única prova encadernada que você pode enviar a um amigo (o gist) e uma cópia colocada na prateleira de uma biblioteca, onde qualquer um com carteirinha pode ler (o site hospedado). A cópia da mesa continua sendo a casa; as outras duas só deixam o trabalho viajar.
O Publish Gate roda na convergência, depois que o curso do visual-teach passou pelo seu próprio Ship Gate. Ele é descrito na skill loop-engineering como a regra geral do Publish Gate: ao convergir, além de entregar o curso, publique-o. Dois scripts implementam os dois níveis — publish-course-gist.js e publish-course-pages.js — ambos invocados com node apontando para o diretório do curso.
Fora isso, o harness mantém as mãos na sua máquina. Publicar é a única exceção pré-aprovada (você não é perguntado a cada execução), e ela é cercada por três lados: publica apenas o artefato do curso, assume por padrão a visibilidade privada/secret, e é pulada sempre que o escopo proíbe publicar ou o CLI relevante não está autenticado. Esse cercamento é o que torna uma autorização permanente segura.
Ajuda manter três lugares na cabeça, porque eles fazem trabalhos diferentes.
O diretório course/ do repo é o original. É onde o curso é escrito e onde cada link já resolve. Nada na publicação o substitui — ele continua sendo a casa canônica e navegável do curso, e é o lugar que você continua editando.
O gist é um instantâneo privado, fora da máquina. Pense nele como uma cópia congelada que você pode compartilhar com um link, sem dar a ninguém acesso ao seu repo ou à sua máquina. Ele é sempre tentado, porque precisa de quase nada para funcionar.
O site no Cloudflare Pages é o nível hospedado — um site de verdade com seu próprio endereço, servido a partir de uma rede global rápida, que você pode manter privado atrás de um login. É o nível que você escolhe quando quer que as pessoas simplesmente abram um link no navegador e leiam, sem etapa de download.
A ideia-chave: estes são camadas, não substituições. O repo é a casa; o gist é uma cópia portátil; o site hospedado é a sala de leitura voltada ao público. Publicar amplia o alcance sem nunca tirar o original.
Um gist é estritamente flat: seu servidor rejeita qualquer push que contenha um subdiretório (pre-receive hook declined). A árvore do curso não é flat — ela tem lessons/, demos/ e pt/. Então publish-course-gist.js achata a árvore em nomes de arquivo de nível superior sem colisão e reescreve cada link relativo interno .html para seu novo nome flat. A recompensa: um ZIP baixado ou um git clone do gist abre como um curso totalmente navegável e, como cada página é autossuficiente (CSS/SVG/JS inline), páginas individuais também renderizam sozinhas via gistpreview.
O Cloudflare Pages preserva a árvore de diretórios e serve links relativos nativamente, então é um site de verdade, navegável, numa CDN, sem reescrita. Essa é a diferença estrutural entre os dois níveis: gist = instantâneo privado achatado; Pages = site hospedado que preserva a árvore.
O gist é o nível que quase sempre sai, porque pede tão pouco. Você aponta um script para a pasta do curso finalizado, ele empacota cada página num único gist privado, e devolve uma URL impressa. O gist é secret — o que no GitHub significa somente por link: não listado em lugar nenhum, não pesquisável, visível apenas para alguém a quem você entregar o link. Isso é o mais perto de privado que um gist chega.
O que você obtém é um instantâneo congelado no tempo. Ele não acompanha seu repo, não muda quando você continua editando — é o curso exatamente como estava no momento em que você publicou. Qualquer pessoa com o link pode lê-lo no navegador, ou baixar tudo como um ZIP e abrir offline, e ele ainda funciona como um curso clicável.
Há um pequeno detalhe de encanamento que vale conhecer: um gist não pode conter pastas. O curso vive em pastas. Então, antes de fazer o upload, o script silenciosamente achata tudo numa única camada de arquivos e reescreve os links entre as páginas para que ainda apontem para o lugar certo. Você nunca vê isso — você só recebe um gist que se comporta como o curso de verdade.
# run on convergence, pointed at the finished course directory node ~/.claude/skills/loop-engineering/publish-course-gist.js ./course # optional: give it a description; default visibility is SECRET (link-only) node ~/.claude/skills/loop-engineering/publish-course-gist.js ./course --desc "Loop Engineering — visual course" # requires the gh CLI to be authenticated first: gh auth status
~/.claude/skills/loop-engineering/publish-course-gist.js. Ele precisa do node e de um CLI gh autenticado — verifique com gh auth status e, se não estiver logado, rode gh auth login uma vez. Depois passe o diretório do curso como primeiro argumento. A visibilidade padrão é secret; você só adicionaria --public no raro caso de realmente querer um gist listado e pesquisável.Como um gist rejeita subdiretórios, o script percorre a árvore do curso (lessons/, demos/, pt/), mapeia cada caminho aninhado para um nome de arquivo flat único, e reescreve cada href relativo interno .html para coincidir. O resultado é sem colisão e autoconsistente: abra qualquer página do conjunto flat e seus links resolvem. O diretório repo/course continua sendo a casa canônica navegável; o gist é um instantâneo fora da máquina, compartilhável e privado — não a fonte da verdade.
O padrão é SECRET — não listado, somente por URL, o mais perto de "privado" que o GitHub oferece para um gist. --public sobrescreve (raramente desejado). O script termina imprimindo a URL do gist.
O segundo nível coloca o curso num site de verdade. Em vez de um instantâneo que você baixa, este é um endereço no ar na rede global da Cloudflare — rápido de carregar de qualquer lugar, e um site verdadeiro onde as pastas e os links funcionam exatamente como em casa, sem nada para achatar. Você o escolhe quando quer a experiência de leitura mais simples possível: envie um link, a pessoa clica, a pessoa lê.
Este nível pede um pouco mais de configuração. Uma vez, na sua máquina, você faz login na Cloudflare por uma ferramenta chamada wrangler. Esse login é um passo humano, único — você o faz num navegador, e o token de acesso nunca deixa o seu computador. Depois disso, o script de publicação pode fazer o deploy do site sempre que o loop convergir.
Por padrão, um site no Pages recém-deployado é acessível por qualquer um que saiba a URL. Para torná-lo genuinamente privado — legível apenas pelas pessoas que você nomear, de qualquer lugar — você ativa o Cloudflare Access, um portão de login, no painel da Cloudflare. Isso é um clique único que o humano faz; não dá para automatizar com o token de publicação, então o script simplesmente te lembra de fazê-lo em vez de fingir que consegue.
# one-time, on your machine — interactive OAuth in a browser (the human does this) npx wrangler login # then deploy the course to Pages and get a live URL node ~/.claude/skills/loop-engineering/publish-course-pages.js ./course # optional: name the project / pick the branch node ~/.claude/skills/loop-engineering/publish-course-pages.js ./course --project loop-course
~/.claude/skills/loop-engineering/publish-course-pages.js e precisa do node mais um wrangler autenticado e uma conta Cloudflare. Faça o npx wrangler login único você mesmo (OAuth no navegador). Para travar o site depois, abra o painel da Cloudflare: Workers & Pages → seu projeto → Settings → ative a política de Access, ou configure uma aplicação Zero Trust Access para <project>.pages.dev permitindo apenas o seu e-mail.O token OAuth do wrangler (do npx wrangler login) permite que o script faça deploy, mas ele não carrega escopo Zero-Trust — então um site no Pages recém-deployado é público-por-URL. Torná-lo privado é uma configuração de Access da Cloudflare, um passo único no painel que o humano executa (Workers & Pages → projeto → Settings → política de Access; ou Zero Trust → Access → Applications → self-hosted, domínio <project>.pages.dev, política Allow → seu e-mail). Não dá para fazer com o token do wrangler, então o script imprime o lembrete e deixa o humano finalizar.
O Pages preserva a árvore e serve links relativos nativamente (sem achatar/religar), entregando um site real hospedado em CDN. O gist é o instantâneo privado sempre-ativo; o Pages é o nível hospedado. A orientação da skill é rodar ambos na convergência.
Como publicar é o único movimento para fora que o loop faz por conta própria, ele segue uma regra simples e conservadora: publique na convergência, a menos que haja um motivo claro para não publicar. Há exatamente dois motivos para pular um nível — o escopo da tarefa proíbe explicitamente publicar, ou a ferramenta que aquele nível precisa não está logada. Se o escopo diz "mantenha isto interno", nada sai. Se o gh não está autenticado, o nível gist é pulado; se o wrangler não está logado, o nível Pages é pulado. Sem drama, sem falha — apenas um nível que silenciosamente não roda.
Vale ver como os três tipos de participantes do harness se relacionam com este único gate, porque cada um tem uma aposta diferente nele.
Você (humano)
Você recebe a recompensa: um instantâneo privado que pode entregar a qualquer pessoa por um link, e uma URL no ar que pode simplesmente abrir num navegador. Você também detém as chaves únicas — os logins do gh e do wrangler, e o interruptor do Cloudflare Access que torna o site hospedado de fato privado.
O LLM dirigindo o loop
Ele roda o gate automaticamente na convergência e reporta as URLs. Ele pula um nível apenas se o escopo proíbe publicar ou o CLI daquele nível não está autenticado — nunca por capricho. Ele não inventa outras ações para fora; esta é a única que tem permissão de tomar.
Os agentes & o repo
Entre os agentes delegados, o diretório course/ do repo continua a casa canônica navegável. O gist e o site são cópias derivadas que viajam; a fonte da verdade nunca sai da máquina, então todos seguem trabalhando contra o mesmo original.
Conclusão
Publicar é alcance, não mudança de endereço. Na convergência o loop empurra um gist privado e (quando configurado) um site hospedado, pula um nível apenas quando o escopo ou a autenticação manda, e deixa o course/ do repo como casa.
Sinta como os dois níveis dependem de suas precondições. Cada nível de publicação — gist e cloudflare-pages — só sai quando o loop converged e o CLI certo está autenticado. Ligue um nível de publicação enquanto sua precondição está desligada e um aviso desliza, dizendo exatamente o que está faltando; a linha de resumo sempre relata quais níveis estão de fato no ar, com o course/ do repo sempre por trás deles.
O que está publicado
Os níveis são um registro booleano flat; um segundo objeto lista as precondições que cada um requer. Após qualquer toggle, o editor checa cada nível habilitado contra sua lista requires. Um nível de publicação que está ligado mas sem uma precondição está insatisfeito — ele desenha o aviso inline e é excluído do conjunto publicado que o resumo relata. As duas precondições base mapeiam para as regras reais de pulo: gh-auth guarda o gist, wrangler-login guarda o Pages, e converged guarda ambos.
const requires = { converged: [], // the gate only fires after convergence gh_auth: [], // gh CLI authenticated wrangler_login: [], // one-time browser OAuth gist: ['converged', 'gh_auth'], // skipped if gh is unauthenticated pages: ['converged', 'wrangler_login'] // skipped if wrangler is not logged in }; function publishedSet() { // a publish tier counts only when ON and all preconditions are satisfied return ['gist', 'pages'].filter(id => flags[id] && missingDeps(id).length === 0); }