Verificando acesso...

MÓDULO 2.2

⛔ Install Gate + State Machine + /doctor

A peça que impede o Claude de "inventar" que instalou. State machine + hook SessionStart + validação profunda + drift detection.

6
Tópicos
~50
Minutos
Médio
Nível
Sistema
Tipo
1

🗄️ State machine em _install-state.json

O ficheiro ~/.claude/skills/_install-state.json é a fonte da verdade. Tudo o que vês em /install-status, no gate, e no /doctor vem daqui.

As 6 fases

  1. 1. prereqs — Node, Python, Git, Claude Code validados
  2. 2. sinapsis-engine — Sinapsis copiado para ~/.claude
  3. 3. context-files — soul.md, me.md, decisions-log.md criados
  4. 4. operator-state — operator-state.json inicializado
  5. 5. welcome-completed — welcome-quick-win passou (gera 1 entregável)
  6. 6. deep-dive-completed — entrevista 22-25 dimensões (deferrable)

Os 5 estados possíveis

done — fase concluída e validada
in-progress — começou mas não terminou
pending — ainda não começou
failed — tentou e falhou (com errorMsg)
skipped — utilizador optou por saltar (só deferrable)

💡 5 required + 1 deferrable

As primeiras 5 fases são required: true (instalação só está "pronta" quando todas done). A 6ª (deep-dive) é deferrable — podes saltá-la no início e fazer mais tarde com /deep-dive.

2

⛔ Hook SessionStart (_install-gate.sh)

Script em ~/.claude/skills/_install-gate.sh. Corre antes de cada sessão começar. Lê o state file; se há fases required pendentes, injeta aviso ao modelo via additionalContext.

Anatomia do hook

#!/usr/bin/env bash
# ~/.claude/skills/_install-gate.sh
# SessionStart hook — fail-open if anything breaks

set +e  # never crash the session

STATE_FILE="$HOME/.claude/skills/_install-state.json"
[[ ! -f "$STATE_FILE" ]] && exit 0  # no state → no gate

# Parse state via node (fallback to no-op if node missing)
command -v node >/dev/null 2>&1 || exit 0

PENDING=$(node -e "
  const s = require('$STATE_FILE');
  const pending = Object.entries(s.phases)
    .filter(([k,v]) => v.required && v.status !== 'done')
    .map(([k]) => k);
  console.log(JSON.stringify(pending));
")

[[ "$PENDING" == "[]" ]] && exit 0  # all done

# Emit additionalContext for the model
cat <<EOF
{"additionalContext": "INSTALLATION INCOMPLETE. Pending: $PENDING.
Do NOT respond to user requests. Tell them to run /install."}
EOF

🛡️ Fail-open

Se o hook crashar (script com bug, node em falta, JSON inválido), a sessão continua normalmente. Princípio: o gate nunca bloqueia o utilizador por erro nosso. Pior caso = sem aviso, melhor caso = aviso correto.

3

📥 additionalContext JSON injetado ao modelo

O hook devolve JSON com chave additionalContext. O Claude Code injeta isto no contexto da sessão antes de qualquer mensagem do utilizador. O modelo lê isto com prioridade.

📊 Fluxo de uma sessão

  1. Utilizador abre Claude Code no repo
  2. Claude Code corre todos os hooks SessionStart (incluindo o gate)
  3. Gate lê state file, vê que welcome-completed: pending
  4. Gate emite {"additionalContext": "INSTALLATION INCOMPLETE..."}
  5. Claude recebe o additionalContext + qualquer mensagem que o utilizador escreva
  6. Claude prioriza o additionalContext → responde "vamos primeiro completar instalação"

💡 Por que isto funciona

É enforcement estrutural, não confiança no modelo. Sem o additionalContext, o Claude poderia "esquecer" e responder direto. Com ele, é praticamente impossível porque vê o aviso antes da tua mensagem.

4

📊 Comandos /install e /install-status

Duas peças diferentes com responsabilidades claras: /install age, /install-status só observa.

/install (orquestrador)

  • • Lê state, identifica próxima fase pendente
  • • Executa fases conversacionais (welcome, deep-dive)
  • • Pede para correres bash em fases técnicas
  • • Aceita --resume (default) e --force-reinstall
  • • Atualiza state após cada fase

/install-status (dashboard)

  • • Read-only — não toca em nada
  • • Mostra estado das 6 fases em tabela visual
  • • Indica próxima ação sugerida
  • • Reporta drift entre state e disco
  • • Útil para "estou bloqueado?" sem risco

🎯 Fases técnicas vs conversacionais

Técnicas (prereqs, sinapsis-engine, context-files, operator-state) → instalador bash. Conversacionais (welcome-completed, deep-dive-completed) → entrevista dentro do Claude Code. /install sabe qual chamar em cada fase.

5

🩺 /doctor + validação profunda

O /doctor invoca a skill health-check. Não é só test -f <ficheiro> — faz validação real do conteúdo.

O que valida realmente

  • JSON parseable: _install-state.json, operator-state.json, settings.json
  • Hooks executáveis: _install-gate.sh tem permissão +x
  • Conteúdo >100 chars: soul.md, me.md não estão vazios
  • Estrutura de pastas: brand-context/voice/, context/ existem
  • Settings registado: hook em ~/.claude/settings.json
  • Skills válidas: cada SKILL.md tem frontmatter parseável

Output 🟢🟡🔴

🟢 OK    State file valid (6 phases)
🟢 OK    Sinapsis hooks executable
🟡 WARN  brand-context/voice/voice-profile.md empty (12 chars)
🟢 OK    All 23 skills have valid frontmatter
🔴 FAIL  install-gate hook NOT registered in settings.json

Suggested fixes:
  1. Run /deep-dive to populate voice-profile.md
  2. Run bash scripts/install.sh --resume to re-register hook

💡 Auto-fix com confirmação

Para problemas comuns, /doctor propõe o comando exato para corrigir. Não executa automaticamente — pede confirmação. Tu mantens o controlo.

6

🌊 Drift detection

Drift = state diz uma coisa, disco diz outra. O /doctor cruza os dois e apanha incoerências que de outro modo passariam despercebidas.

Cenários de drift comuns

Cenário 1:

State diz context-files: done mas context/me.md tem 0 bytes (apagaste sem querer).

→ /doctor reverte state para pending e sugere /install --resume.

Cenário 2:

Sync entre 2 máquinas correu mal — state da máquina A diz done mas a máquina B não tem os ficheiros.

→ /doctor deteta na máquina B, propõe reinstalar a fase em falta.

Cenário 3:

Mudaste de versão do OS (git pull) e novo install adicionou fase nova — state antigo não a tem.

→ /doctor injeta a fase nova como pending sem perder as done existentes.

🔍 Quando correr /doctor

  • • Após git pull (sobretudo se houve mudanças em scripts/ ou .claude/)
  • • Quando trocas de máquina ou sincronizas via cloud
  • • Antes de começar trabalho importante (rápido sanity check)
  • • Quando algo se comporta de forma estranha sem motivo claro

💡 Filosofia

State file é hipótese, disco é facto. Quando divergem, o disco ganha. /doctor ajusta o state para refletir a realidade, e propõe ações para reconciliar.

Resumo do Módulo

State machine: 6 fases × 5 estados — fonte da verdade da instalação
5 required + 1 deferrable (deep-dive) — instalação "pronta" = 5 done
Hook SessionStart bloqueia respostas — fail-open se algo crashar
additionalContext JSON antes da tua mensagem — enforcement estrutural
/install age, /install-status só observa — separação clara
/doctor faz validação real do conteúdo — não só ficheiro existe
Drift detection: disco ganha sempre — state ajusta-se à realidade

Próxima Trilha:

Trilha 3 — Brand Context: voice profile com 3 registos, ICP, positioning. A peça que faz outputs soarem a TI.