PROJETO 3.4

🐳 Projeto 4: terceiro executor

Até aqui o curso falou de dois runtimes. Mas já existe um terceiro rodando na sua máquina há semanas: o dsh-sandbox, o agente da DeepSeek em container, com modelo local ou remoto. Ele tem três skills copiadas à mão (drift garantido) e nenhuma camada de contexto. Este projeto acrescenta um destino --dsh à fonte canônica de skills, dá ao dsh um prime que manda ler os arquivos certos, e faz o readback lá dentro — sem nunca juntar ~/projetos com provedor remoto.

6
Tópicos
~50
Minutos
Avançado
Nível
Projeto
Tipo

🎯 O projeto em uma tela

ObjetivoProvar que o núcleo portátil vale para um terceiro executor — o dsh-sandbox — e que as skills dele saem da mesma fonte canônica que Claude e Codex, sem cópia manual.
Você sai comUm sync-skills.sh com destino --dsh e drift check, uma skill prime em ~/projetos/dsh-skills, e um readback rodado no painel com modelo local e comparado com o remoto.
Critério de aceiteDrift zero nos três destinos; o dsh cita AGENTS.md, context/, tasks/current.md e handoffs/latest.md pelo nome; e nenhum passo usou remoto-projetos.
1

🐳 O que é o dsh-sandbox

O dsh-sandbox é o @deepseek-ai/dsh na versão 0.1.1-rc.1 rodando em Docker, com painel em 127.0.0.1:9080 e container dsh-orchestrator-runtime-1. A versão está congelada dentro de work/node_modules de propósito: um boot não volta ao registry, e atualizar é ato explícito. O controle todo passa por um script único na raiz do projeto — ./dsh — com cinco verbos.

O ponto que importa para este curso é o desenho dos modos. Não existe "ligar tudo": montagem de disco e provedor de modelo estão amarrados. No modo local, ~/projetos é montado dentro do container e o único provedor é o Ollama na própria máquina — os seus arquivos estão lá, mas nenhum byte sai. No modo remoto, o provedor é o OpenRouter e ~/projetos não é montado — o modelo é melhor, mas ele não vê nada seu. A combinação dos dois existe (remoto-projetos) e pede a palavra CONFIRMO digitada, porque é exatamente a combinação perigosa.

container dsh dsh-orchestrator-runtime-1 painel 127.0.0.1:9080 ./dsh local ~/projetos MONTADO provedor: só Ollama (na máquina) seus arquivos entram, nada sai ./dsh remoto ~/projetos FORA provedor: OpenRouter (internet) modelo melhor, sem ver seus arquivos skills montadas ~/projetos/dsh-skills → /work/.dsh/skills ./dsh remoto-projetos montagem + provedor remoto 269 arquivos de segredo em risco exige CONFIRMO digitado nunca para readback

Leia o desenho pelas setas que entram no container. Local traz os seus arquivos mas prende o modelo na máquina; remoto solta o modelo mas deixa os arquivos de fora. O bloco vermelho é a única combinação que junta os dois — e existe justamente para ser difícil de acionar por acidente.

Objetivo: subir o dsh no modo certo e confirmar que o painel responde antes de qualquer outra coisa.

cd ~/projetos/dsh-sandbox

# ver em que estado ele está agora (pode estar no ar há dias)
./dsh status

# para este projeto: modo local (projetos montados + só Ollama)
./dsh local

# o painel só escuta em loopback; de fora, use túnel SSH
curl -sf -o /dev/null -w '%{http_code}\n' http://127.0.0.1:9080
# esperado: 200

# container e teto de memória
docker ps --filter name=dsh-orchestrator-runtime-1

# ao terminar
./dsh off

Como verificar: ./dsh status diz o modo ativo e o curl devolve 200. Se precisar acessar de outra máquina, o caminho é ssh -L 9080:127.0.0.1:9080 … — o dsh recusa bind em 0.0.0.0 por decisão dos autores, e o app não tem autenticação nenhuma.

O container não é o custo: ele pesa uns 85 MB ocioso, com teto de 3 GB. O peso real é o modelo carregado no host, sem teto: de 17 GB a 45 GB dependendo do que você escolher. Esse é o número que decide se a máquina aguenta — não o Docker.

Conceitos-chave

Terceiro executor

Mais um consumidor do mesmo contexto portátil, ao lado de Claude e Codex.

Modos amarrados

Montagem e provedor decididos juntos, nunca em separado.

Versão congelada

0.1.1-rc.1 instalada localmente; o boot não busca atualização.

Só loopback

O painel não tem login; acesso remoto só por túnel SSH.

2

🧬 Cópia à mão é drift garantido

Hoje o dsh tem três skills, e as três chegaram lá por cp: formato-curso-v2, formato-curso-v5 e capa-inema (dependência das duas primeiras). Elas moram em ~/projetos/dsh-skills, montado no container como /work/.dsh/skills. O formato é compatível — é o mesmo SKILL.md do Claude — e por isso a cópia funciona. O problema não é ela não funcionar hoje; é ela não continuar igual amanhã.

Chame isso de drift: você corrige um bug na skill do Claude, testa, publica, e a cópia do dsh fica na versão antiga. Nada quebra com barulho. O dsh simplesmente gera um curso com o padrão de dois meses atrás e você descobre no output. O diagnóstico é claro sobre a escala do problema: já são quatro consumidores de skills, não dois — Claude (117), Codex (27), dsh (3 cópias manuais) e o openpcbotv3 (16 próprias). Sem fonte canônica, cada um diverge sozinho, e a divergência cresce com o tempo.

fonte canônica skills/<nome>/ (polyskill) um lugar, uma verdade build dist/<runtime>/ ~/.claude/skills117 skills ~/.codex/skills27 skills ~/projetos/dsh-skills 3 cópias à mão → ESTE PROJETO openpcbotv3/skills destino --v3, fica para depois drift compara cada destino com a saída do build meta: zero

Uma fonte canônica à esquerda, um build no meio, quatro destinos à direita. Os dois primeiros já saem do build; o terceiro (dsh) é o que este projeto acrescenta; o quarto fica para depois. A caixa da direita é o que transforma isso em garantia: sem drift, você tem quatro cópias e nenhuma prova de que são iguais.

✓ Skill gerada pelo build

  • Corrigiu na fonte, um build e um install atualizam todos os destinos.
  • O drift acusa antes do usuário acusar.
  • Backup automático do destino anterior a cada instalação.
  • Uma revisão só serve os quatro consumidores.

✗ Skill copiada à mão

  • Ninguém lembra qual cópia é a mais nova.
  • A divergência aparece no output, meses depois, e parece bug do modelo.
  • Corrigir vira quatro edições, e você esquece uma.
  • Sem verificador, "está sincronizado" é fé, não fato.

Cuidado com o nome da pasta: o destino é ~/projetos/dsh-skills, e não ~/projetos/skills — este último já é o repositório git inematds/skills do curso de Agent Skills. Copiar para o nome errado polui um repo publicado. Confira o caminho antes de rodar qualquer cp -a.

Conceitos-chave

Drift

Cópias que começam iguais e divergem sem ninguém perceber.

Fonte canônica

O único lugar que se edita; todo o resto é gerado.

Quatro consumidores

Claude, Codex, dsh e openpcbotv3 — todos querendo a mesma skill.

Falha silenciosa

Drift não gera erro; gera resultado errado com cara de certo.

3

🔧 Acrescentar o destino --dsh ao sync-skills.sh

O scripts/sync-skills.sh que você já usou na Trilha 2 tem quatro verbos: import, build, drift e install. Ele assume dois runtimes o tempo todo, com o laço for rt in claude codex e o caminho $HOME/.$rt/skills/$s — um truque elegante que funciona porque as duas pastas têm o mesmo formato de nome. O dsh quebra esse padrão: o destino dele é ~/projetos/dsh-skills/<nome>, que não cabe na fórmula.

A boa notícia é que o dsh aceita o mesmo SKILL.md do Claude. Então não é preciso um novo alvo de polyskill build: o que se copia para o dsh é o dist/claude/<nome> que o build já produz. A mudança é pequena e cirúrgica — uma função que resolve o caminho de destino por runtime, o caso --dsh no install, e a inclusão do dsh no laço do drift, que é a parte que realmente paga a conta.

Objetivo: aplicar o patch que acrescenta o terceiro destino, mantendo o drift como verificação dos três.

# --- em scripts/sync-skills.sh, logo depois do `mkdir -p skills dist` ---

# resolve a pasta de destino de cada runtime (dsh foge do padrão ~/.<rt>/skills)
dest_for() {
  case "$1" in
    claude|codex) printf '%s/.%s/skills/%s\n' "$HOME" "$1" "$2" ;;
    dsh)          printf '%s/projetos/dsh-skills/%s\n' "$HOME" "$2" ;;
    *) return 1 ;;
  esac
}
# o dsh consome o MESMO formato do Claude: a origem é dist/claude
src_for() {
  case "$1" in dsh) echo claude ;; *) echo "$1" ;; esac
}

# --- no verbo `drift`: trocar `for rt in claude codex` por: ---
      for rt in claude codex dsh; do
        out="$d/dist/$(src_for "$rt")/$s"; tgt="$(dest_for "$rt" "$s")"
        [ -d "$out" ] && [ -d "$tgt" ] || { echo "[não instalada] $s → $rt"; continue; }
        if diff -rq "$out" "$tgt" >/dev/null; then echo "[ok] $s → $rt"; else echo "[DRIFT] $s → $rt"; rc=1; fi
      done

# --- no verbo `install`: trocar `for rt in claude codex` por: ---
    for rt in claude codex dsh; do
      case "$tgt" in --both) [ "$rt" = dsh ] && continue ;; --all) ;; --$rt) ;; *) continue ;; esac
      out="skills/$s/dist/$(src_for "$rt")/$s"; [ -d "$out" ] || { echo "rode build antes: $out"; exit 1; }
      dest="$(dest_for "$rt" "$s")"
      [ -e "$dest" ] && cp -a "$dest" "$(dirname "$dest")/.$s.bak-$(date +%s)"
      mkdir -p "$(dirname "$dest")"; cp -a "$out" "$dest"; echo "instalada: $dest"
    done

Como verificar: bash -n scripts/sync-skills.sh passa sem erro de sintaxe, e scripts/sync-skills.sh drift passa a imprimir três linhas por skill em vez de duas — a terceira terminando em → dsh.

Objetivo: trazer as três skills copiadas à mão para dentro do fluxo canônico e zerar o drift.

cd ~/projetos/agente-claude-codex

# 1. guardar as cópias atuais antes de sobrescrever (elas são o estado bom conhecido)
cp -a ~/projetos/dsh-skills ~/projetos/dsh-skills.bak-$(date +%Y%m%d)

# 2. importar para a fonte canônica (a partir do original do Claude)
scripts/sync-skills.sh import formato-curso-v2 formato-curso-v5 capa-inema
scripts/sync-skills.sh build

# 3. instalar agora também no dsh
for s in formato-curso-v2 formato-curso-v5 capa-inema; do
  scripts/sync-skills.sh install "$s" --dsh
done

# 4. a prova
scripts/sync-skills.sh drift; echo "rc=$?"
# esperado: só linhas [ok], rc=0

Como verificar: rc=0 e nenhuma linha [DRIFT]. Se aparecer drift logo depois do install, a cópia à mão tinha alguma edição local que nunca voltou para a fonte — compare com o backup do passo 1 e leve a diferença para skills/<nome>/ antes de seguir.

Por que --both continua significando dois: o patch mantém --both como Claude+Codex e introduz --all para os três. Quem já tem o hábito de digitar --both não é surpreendido por uma instalação em lugar novo — mudança de comportamento de flag existente é o tipo de armadilha que só aparece três semanas depois.

Conceitos-chave

Destino fora do padrão

O dsh não mora em ~/.<runtime>/skills; precisa de resolvedor.

Reuso do dist/claude

Formato compatível: nenhum alvo novo de build é necessário.

Drift como contrato

Destino que não entra no drift não está de verdade no fluxo.

Flag estável

Acrescentar --all em vez de mudar o que --both faz.

4

🧭 Dar contexto ao dsh: a skill de prime

Skills resolvidas, falta o contexto. O dsh escaneia $DSH_HOME/skills e é só isso: ele não tem auto-load de AGENTS.md nem de CLAUDE.md. Se você abrir o painel dentro de um projeto migrado, ele vê os arquivos (no modo local) mas não sabe que deveria abri-los. Como não há hook, não há evento de abertura, e não há instrução global — a única alavanca disponível é a que ele já usa: uma skill.

Daí a skill de prime. Ela não faz nada além de mandar ler, na ordem certa: AGENTS.md, depois context/, depois tasks/current.md, depois handoffs/latest.md — a mesma ordem que o Claude e o Codex seguem por instrução. É a mesma ideia do tópico 5 do Projeto 2: quando o evento não existe, o comportamento vira leitura pedida explicitamente. E como o dsh aceita o formato do Claude, essa skill sai da mesma fonte canônica e vai para os três destinos.

1

Escrever o prime na fonte canônica

Um SKILL.md curto em skills/prime/, com a ordem de leitura e o formato da resposta.

2

Build e install nos três destinos

install prime --all leva a mesma skill para Claude, Codex e dsh.

3

Subir o dsh no modo local

Sem ~/projetos montado não há o que ler; o readback tem que ser no modo local.

4

Rodar as 5 perguntas no painel

As mesmas do readback da Trilha 2. O critério é citar o arquivo, não a beleza da resposta.

Objetivo: criar a skill de prime e instalá-la nos três destinos, incluindo o dsh.

cd ~/projetos/agente-claude-codex
mkdir -p skills/prime

cat > skills/prime/SKILL.md <<'MD'
---
name: prime
description: Carrega o contexto do projeto antes de qualquer trabalho. Use no
  começo de toda sessão, antes da primeira edição, e sempre que perder o fio.
---

# Prime — leia antes de agir

Leia, nesta ordem, e só então responda:

1. `AGENTS.md` na raiz do projeto — as regras estáveis.
2. `context/overview.md` — os fatos verificados. Se houver
   `context/decisions/`, leia também a decisão mais recente.
3. `tasks/current.md` — o que está em andamento agora.
4. `handoffs/latest.md` — o que a última sessão fez e qual é a próxima ação.

Se algum desses arquivos não existir, diga qual falta em vez de inventar.

Feche o prime com quatro linhas, cada uma citando o arquivo de onde veio:

- **Projeto:** o que é, em uma frase.
- **Estado:** o que está pronto e o que está pendente.
- **Próxima ação:** a frase exata escrita em `handoffs/latest.md`.
- **Regra que mais importa aqui:** a restrição do `AGENTS.md` que
  mais afeta a próxima ação.
MD

scripts/sync-skills.sh build
scripts/sync-skills.sh install prime --all
ls ~/projetos/dsh-skills/prime/SKILL.md

Como verificar: o ls encontra o arquivo, e scripts/sync-skills.sh drift mostra [ok] prime → dsh junto com claude e codex. Depois, no painel em 127.0.0.1:9080 com o dsh em modo local, peça "use a skill prime no projeto /projetos/<seu-piloto>" e confira se as quatro linhas voltam com nome de arquivo em cada uma.

Atenção às pontes de caminho: dentro do container, ~/projetos aparece como /projetos e as skills são vistas em /work/.dsh/skills. Há dois symlinks em work/ justamente para que os ~/... escritos nas skills resolvam lá dentro — eles aparecem quebrados quando você olha do host, e isso é esperado. Ao pedir algo pelo painel, use o caminho de dentro.

Conceitos-chave

Prime

A skill que substitui o auto-load inexistente por leitura pedida.

Ordem de leitura

AGENTS → context → tasks/current → handoffs/latest, sempre igual.

Ponte de caminho

Symlinks em work/ que fazem ~/… resolver dentro do container.

Citar a fonte

Resposta sem nome de arquivo não conta como leitura comprovada.

5

🔒 Segurança: 269 segredos e a regra que não se negocia

A auditoria contou 269 arquivos de segredo dentro de ~/projetos — entre eles os dois .env que o curso inteiro trata como fonte única de API keys, wifi/.env e openpcbotv2/.env. Montar essa árvore num container cujo provedor de modelo é remoto significa dar a um serviço de terceiros a chance de ler qualquer um deles, porque o agente decide sozinho quais arquivos abrir. Não existe "ele não vai olhar": a única garantia é a que está no desenho.

É por isso que montagem e provedor são amarrados. A decisão foi tomada uma vez, no script, e não em cada sessão: local dá acesso aos arquivos e prende o modelo dentro da máquina; remoto solta o modelo e tira os arquivos de cena. A terceira opção existe e pede CONFIRMO digitado — e a regra deste projeto é curta: nunca use remoto-projetos para readback. O readback é justamente o exercício de mandar um agente ler arquivos do seu disco; é o pior momento possível para ter um provedor externo na linha.

✓ Combinações permitidas

  • local para readback e para gerar curso: arquivos dentro, modelo dentro.
  • remoto para comparar qualidade de prosa com conteúdo colado à mão.
  • Painel só em 127.0.0.1; de fora, apenas por túnel SSH.
  • ./dsh off ao terminar, para não deixar montagem viva sem necessidade.

✗ Nunca

  • remoto-projetos para readback — junta os 269 segredos com provedor externo.
  • Expor o painel com --host 0.0.0.0: o app não tem autenticação nenhuma.
  • Copiar um .env para dentro de dsh-skills "para a skill achar".
  • Digitar CONFIRMO no automático — a fricção existe para você parar e pensar.

Objetivo: confirmar, antes de rodar o readback, que o modo ativo é o seguro — e medir o tamanho da superfície.

cd ~/projetos/dsh-sandbox

# quantos arquivos de segredo a montagem exporia (só a contagem, nunca o conteúdo)
find ~/projetos -maxdepth 3 \( -name '.env' -o -name '.env.*' -o -name '*credential*' \) \
  -type f 2>/dev/null | wc -l

# o modo ativo — antes de pedir qualquer coisa ao painel
./dsh status

# checagem direta: a montagem de /projetos existe neste container?
docker inspect dsh-orchestrator-runtime-1 \
  | python3 -c 'import json,sys; [print(m["Source"], "->", m["Destination"]) for m in json.load(sys.stdin)[0]["Mounts"]]'

# o painel não pode estar escutando fora do loopback
ss -ltnp 2>/dev/null | grep 9080
# esperado: 127.0.0.1:9080 — se aparecer 0.0.0.0:9080, derrube AGORA com ./dsh off

Como verificar: se o status disser local, o inspect mostrar /projetos montado e o ss mostrar só 127.0.0.1, pode seguir. Qualquer combinação diferente disso é motivo para parar e corrigir antes de digitar a primeira pergunta no painel.

Sobre o network_mode: host: o container roda sem isolamento de rede porque o dsh só aceita bind em 127.0.0.1 e, com bridge, o proxy do Docker não alcança o loopback interno. A consequência é que ele enxerga todos os serviços de loopback do host — Ollama em 11434, iccmonit em 9003, e o que mais estiver no ar. Não é um detalhe cosmético: some com a sensação de "está isolado porque é container". O isolamento real aqui vem dos modos, não da rede.

Conceitos-chave

Montagem amarrada

Quem vê os arquivos não fala com provedor externo, e vice-versa.

269 segredos

A superfície medida de ~/projetos; o número que justifica a regra.

Fricção proposital

CONFIRMO digitado existe para impedir o acidente, não o uso.

Container ≠ isolamento

Com network_mode: host, a rede do host está toda visível.

6

📉 Expectativa honesta: o que o modelo local entrega

O modelo local desta máquina é o qwen3.8:27b, cerca de 18 GB carregados no host, sem teto. Ele briga por RAM com o inemavox — e o histórico de travamentos por OOM está registrado no monitoramento, não é hipótese. Se você for rodar readback no dsh, faça o preflight: veja a memória livre antes, e não deixe uma síntese de voz pesada em andamento.

Sobre a qualidade, o recado do diagnóstico é direto: as skills foram escritas para o comportamento do Claude, e com modelo local o resultado fica aquém. Mas "aquém" precisa ser medido no eixo certo. O que este projeto testa é portabilidade de contexto, e o critério é citar os arquivos certos. Prosa mais pobre, estrutura mais frouxa e menos nuance são limite do modelo. Confundir os dois leva à conclusão errada — "a portabilidade falhou" quando o que falhou foi a expectativa de qualidade de escrita.

🧪 O teste que separa modelo de portabilidade

Rode a mesma pergunta nos dois modos. No remoto o dsh não enxerga ~/projetos, então cole o conteúdo dos arquivos na própria pergunta. Se a resposta melhorar muito, o gargalo era o modelo; se continuar sem citar arquivo nenhum, aí sim o problema é a sua camada de contexto.

EixoCritérioConclusão se falhar
PortabilidadeCita AGENTS.md, tasks/current.md, handoffs/latest.md pelo nomeFalta prime, montagem ou os arquivos
FidelidadeA próxima ação bate com a escrita no handoffLeu por cima; encurte os arquivos
Qualidade da prosaTexto organizado e sem repetiçãoLimite do modelo — não invalida nada
EstabilidadeTerminou sem OOMInfra: modelo grande demais para a RAM livre

Objetivo: fazer o preflight de memória e registrar o resultado do readback nos dois modos, sem tirar conclusão apressada.

# preflight: o modelo de ~18 GB cabe agora?
free -g | awk '/Mem:/ {print "livre:", $7, "GB"}'
# regra prática: menos de 24 GB livres, não suba o 27b junto com o inemavox

# quem já está segurando memória
ps -eo rss,comm --sort=-rss | head -5 | awk '{printf "%6.1f GB  %s\n", $1/1048576, $2}'

# modelos carregados no Ollama neste momento
ollama ps

# depois do readback, registre o resultado ao lado dos outros dois runtimes
cd ~/projetos/<seu-piloto>
mkdir -p relatorios
$EDITOR relatorios/readback-dsh-local.md    # quais arquivos foram citados, e a próxima ação que ele leu
$EDITOR relatorios/readback-dsh-remoto.md   # mesma pergunta, contexto colado à mão

Como verificar: os dois relatórios existem e o veredito está escrito em uma frase — "citou os quatro arquivos, prosa inferior ao Claude" é aprovação; "não citou nenhum arquivo nos dois modos" é reprovação da camada de contexto, e aí o problema está no prime ou na montagem, não no modelo.

Critérios de aceite (marque com evidência)

  • sync-skills.sh drift devolve rc=0 com os três destinos listados. Evidência: saída do comando.
  • As 3 skills antes copiadas à mão agora são geradas pelo build. Evidência: [ok] … → dsh para cada uma.
  • A skill prime existe nos três destinos. Evidência: ls nos três caminhos.
  • Readback no dsh cita os quatro arquivos pelo nome. Evidência: relatorios/readback-dsh-local.md.
  • Nenhum passo usou remoto-projetos. Evidência: ./dsh status registrado antes de cada rodada.
  • Nenhum OOM durante o exercício. Evidência: o preflight anotado e o inemavox parado ou intocado.

⚠️ Riscos deste projeto

  • OOM: o modelo de ~18 GB sobe sem teto e briga com o inemavox pela mesma RAM.
  • Usar remoto-projetos por conveniência e expor os 269 segredos.
  • Copiar para ~/projetos/skills em vez de dsh-skills e poluir um repo publicado.
  • O install --dsh sobrescrever uma cópia que tinha edição local nunca devolvida à fonte.
  • Concluir "a portabilidade falhou" olhando a qualidade da prosa em vez das citações.

↩️ Rollback em um comando

  • Skills do dsh: rm -rf ~/projetos/dsh-skills && mv ~/projetos/dsh-skills.bak-AAAAMMDD ~/projetos/dsh-skills.
  • Script: git checkout -- scripts/sync-skills.sh desfaz o patch inteiro.
  • Prime: rm -rf skills/prime na fonte e nos destinos; nada mais depende dela.
  • Container: ./dsh off derruba tudo e desmonta; Claude e Codex seguem intactos.
  • Memória: ollama stop qwen3.8:27b devolve os ~18 GB na hora.

Conceitos-chave

Preflight de RAM

Medir a memória livre antes de subir o modelo, não depois do travamento.

Critério certo

Citar os arquivos certos; a qualidade da prosa é outro eixo.

Comparar no remoto

Antes de culpar a portabilidade, teste com um modelo melhor.

Executor de segunda linha

O dsh não substitui Claude ou Codex; prova que o contexto viaja.

Auto-checagem (opcional): no readback do dsh em modo local, o modelo citou AGENTS.md, tasks/current.md e handoffs/latest.md, mas o texto ficou repetitivo e mal organizado. O que você conclui?

🎯 Resumo do projeto

Terceiro executor real — o dsh já roda em container, com painel em 127.0.0.1:9080 e modos local e remoto amarrando montagem e provedor.
Fim da cópia à mão — destino --dsh no sync-skills.sh, com as três skills entrando no drift check junto com Claude e Codex.
Contexto por skill — sem auto-load e sem hook, o prime manda ler AGENTS.md, context/, tasks/current.md e handoffs/latest.md.
Segurança e expectativa — nunca remoto-projetos para readback; e o critério é citar os arquivos certos, não a beleza da prosa.

Próximo projeto:

3.5 — Workspace de cliente: Venn, escopo e canários