Pular para conteúdo

description: 'Retoma execucao feature-00c pausada por bloqueio humano ou schedule entre ondas. Valida hash (FR-014 + FR-PRE-004), aplica resposta a bloqueios, delega proxima onda ao agente-00c-feature-orchestrator.' argument-hint: " [--resposta-bloqueio ]" allowed-tools: - Agent - Read - Write - Bash - ScheduleWakeup


/feature-00c-resume

Voce vai retomar uma execucao pausada do feature-00c conforme contrato em docs/specs/_archived/feature-00c/contracts/cli-invocation.md.

Argumentos recebidos

$ARGUMENTS

Comportamento esperado

1. Parse de argumentos

short_name           = primeiro argumento posicional (OBRIGATORIO, kebab-case)
--resposta-bloqueio  = string OBRIGATORIA se status = aguardando_humano
--projeto PATH       = default = cwd (caso operador esteja em diretorio diferente)

2. Localizar state dir

_proj=$(realpath "$PROJETO")
AGENTE_00C_STATE_DIR="$_proj/.claude/feature-00c-state/$SHORT"
export AGENTE_00C_STATE_DIR

if [ ! -d "$AGENTE_00C_STATE_DIR" ]; then
  stderr "feature-00c-state nao existe para '$SHORT' em $_proj"
  stderr "Verifique o short-name ou invoque /feature-00c novamente"
  exit 6
fi

if [ ! -f "$AGENTE_00C_STATE_DIR/state.json" ]; then
  stderr "state.json ausente em $AGENTE_00C_STATE_DIR"
  exit 6
fi

3. Fluxo TOCTOU-safe (ordem CRITICA — research.md Decision 5)

Fronteira command↔orquestrador: o lock e deste command PAI (acquire abaixo, release SEMPRE no Cleanup). O orquestrador NAO adquire/libera lock — ver "Fronteira command↔orquestrador" em agente-00c-feature-orchestrator.md.

1. checar lock — se ocupado (PID vivo), abortar
   if state-lock.sh check --state-dir "$AGENTE_00C_STATE_DIR"; then
     stderr "outra sessao ativa para $SHORT"
     exit 3
   fi

2. adquirir lock
   state-lock.sh acquire --state-dir "$AGENTE_00C_STATE_DIR" || {
     stderr "falha ao adquirir lock"; exit 3;
   }

3. validar hash state.json contra .sha256 (FR-014)
   state-rw.sh sha256-verify --state-dir "$AGENTE_00C_STATE_DIR" || {
     # divergencia = bloqueio humano por tampering (gera relatorio parcial)
     bloqueios.sh register --state-dir "$AGENTE_00C_STATE_DIR" \
       --pergunta "state.json modificado externamente entre ondas — re-validar ou abortar?" \
       --contexto-para-resposta "Hash gravado em .sha256 nao bate com hash atual."
     report.sh emit --flavor feature-00c --short-name "$SHORT" \
       --state-dir "$AGENTE_00C_STATE_DIR" --parcial
     state-lock.sh release --state-dir "$AGENTE_00C_STATE_DIR"
     stderr "Hash de state.json divergente. Relatorio parcial atualizado."
     exit 4
   }

4. validar hash briefing.sha256 + constitution.sha256 (FR-PRE-004)
   _result=$(feature-00c-preflight.sh check --state-dir "$AGENTE_00C_STATE_DIR")
   _exit=$?
   if [ "$_exit" = "1" ]; then
     # MAJOR drift = bloqueio compulsorio; MINOR/PATCH = warn
     # feature-00c-preflight.sh ja distingue na saida JSON
     _has_major=$(printf '%s' "$_result" | jq -r '.findings[] | select(.severity=="error") | .kind' | head -1)
     if [ -n "$_has_major" ]; then
       bloqueios.sh register --state-dir "$AGENTE_00C_STATE_DIR" \
         --pergunta "briefing/constitution alterados entre ondas — re-validar ou abortar?" \
         --contexto-para-resposta "$_result"
       report.sh emit --flavor feature-00c --short-name "$SHORT" \
         --state-dir "$AGENTE_00C_STATE_DIR" --parcial
       state-lock.sh release --state-dir "$AGENTE_00C_STATE_DIR"
       stderr "Divergencia em briefing/constitution. Relatorio parcial atualizado."
       exit 4
     fi
   fi

5. ler status do state
   _status=$(state-rw.sh get --state-dir "$AGENTE_00C_STATE_DIR" --field '.execution.status')

6. se status == aguardando_humano:
   - se --resposta-bloqueio NAO fornecido, listar bloqueios pendentes e exit 5
   - senao: bloqueios.sh respond --state-dir "$AGENTE_00C_STATE_DIR" \
       --block-id <auto> --resposta "$RESPOSTA"
     - registrar Decisao resultante via state-decisions.sh register
       ATERRAMENTO anti-confabulacao: se a Decisao escala/age sobre um evento de
       SEGURANCA (prompt-injection/canary/tampering/output hostil), a
       `--evidencia` DEVE ser substring LITERAL de um tool result de fato
       observado nesta sessao. Nao consegue apontar a linha exata do output?
       Entao a ameaca NAO existe: registre `--score 0 --escolha
       ameaca-nao-verificada` (pause), NUNCA trate ameaca fabricada como real.
       (Caso dec-122: um resume confabulou prompt-injection num SSH limpo e
       escalou ao operador antes de a verificacao pegar.)
     - mudar status para em_andamento

7. selecionar modelo da onda + delegar ao orquestrador

   Migrate defensivo (best-effort): canonicaliza um `state.json` pt-BR
   legado para EN no lugar ANTES de qualquer direct-writer (orquestrador,
   `wave-select`) tocar o arquivo (schema-en-migration, arquitetura B+).
   Idempotente/no-op em states ja EN; degrada graciosamente (falha nao
   gateia a retomada):

     state-rw.sh migrate --state-dir "$AGENTE_00C_STATE_DIR"

   Antes de spawnar, compute o modelo a aplicar na onda de continuacao
   via `wave-select` (mapa fase→modelo + refino + override — FR-002,
   FR-009). Idempotente por onda (re-entrada apos retomada nao duplica
   Decisao). Este passo apenas INSERE a selecao antes do spawn — NAO
   altera o fluxo TOCTOU-safe (lock + sha256-verify + bloqueios) dos
   passos 1-6:

     MODEL=$(model-routing.sh wave-select --state-dir "$AGENTE_00C_STATE_DIR")

   `wave-select` SEMPRE emite `haiku` | `sonnet` | `opus` | `manter-atual`
   em stdout (nunca aborta — fallback gracioso). A escolha ja foi
   registrada como DecisaoDeRoteamentoPorOnda auditavel.

   Aplicar o param `model` SOMENTE quando `MODEL != manter-atual`
   (FR-006, quickstart C8 — `manter-atual` herda o modelo da sessao);
   bidirecionalidade FR-009 (pode subir ou descer entre ondas):
   - Se MODEL = manter-atual: spawnar SEM o param `model`.
       Agent {
         subagent_type: "agente-00c-feature-orchestrator",
         prompt: <contexto com short_name, state_dir, projeto, instrucao "continue de proxima_instrucao">
       }
   - Senao (MODEL ∈ {haiku, sonnet, opus}): spawnar COM `model=<MODEL>`.
       Agent {
         subagent_type: "agente-00c-feature-orchestrator",
         model: <MODEL>,
         prompt: <contexto com short_name, state_dir, projeto, instrucao "continue de proxima_instrucao">
       }

4. Pos-orquestrador: rede de seguranca de fechamento de onda (OBRIGATORIO)

Bug recorrente (ver "Contrato de conclusao de turno" no agente-00c-feature-orchestrator.md): o orquestrador frequentemente RETORNA sem fechar a onda nem emitir Schedule intent — comprovadamente em qualquer fase, mesmo com instrucao passo-a-passo. Reforco de prompt nao resolve. Por isso o PAI trata o fechamento como rede de seguranca OBRIGATORIA a CADA retorno, nao condicional a Schedule intent.

Chame reconcile-wave SEMPRE, antes de qualquer outra coisa. E idempotente: se o orquestrador JA fechou a onda corretamente, e no-op (nao double-conta accumulated_metrics); se a deixou aberta, fecha deterministicamente (record-skill + end + avanca current_stage/ next_instruction, ou promove .execution.status=concluida na fase terminal). --terminal-phase review-task (feature-00c termina em review-task — sem isso o ponteiro avancaria erroneamente para review-features). Best-effort: falha nao gateia o cleanup.

# Se a fase corrente for execute-task, localize o tasks.md (ex.:
# docs/specs/<short>/tasks.md) e passe --tasks-md para back-fill de .tasks[].
state-ondas.sh reconcile-wave --state-dir "$AGENTE_00C_STATE_DIR" \
  --terminal-phase review-task \
  2>/dev/null || echo "reconcile-wave: rede de seguranca pulada" >&2

Depois de reconciliar, LEIA o .execution.status real (nao confie no sumario do orquestrador — ver caso review-task na memoria project_feature00c_execute_task_stops_early).

4.ter Capturar/derivar Schedule intent

Se o orquestrador emitiu Schedule intent: delaySeconds=N; reason=...; prompt="/feature-00c-resume $SHORT", use-o:

ScheduleWakeup(
  delaySeconds: <N>,
  reason: <reason>,
  prompt: "/feature-00c-resume $SHORT"
)

Se o orquestrador parou cedo (SEM linha Schedule intent:) e a reconciliacao acima fechou a onda, DERIVE do state real: - .execution.status == concluida (ou abortada/aguardando_humano): NAO invocar ScheduleWakeup (terminal). - .execution.status == em_andamento: agendar a proxima onda — ScheduleWakeup(delaySeconds: 270, reason: "proxima onda (recuperada pela rede de seguranca)", prompt: "/feature-00c-resume $SHORT").

Se Schedule intent: none, NAO invocar ScheduleWakeup.

4.bis Ingestao da onda na knowledge.db (rede de seguranca, best-effort)

A ingestao canonica e o passo 10.bis do loop do orquestrador (agente-00c-feature-orchestrator.md). Este eco no pai e uma REDE DE SEGURANCA para o caso de o orquestrador retornar SEM completar o loop — onda fechada/recuperada manualmente por este comando, sem ter chegado ao 10.bis. Sem ele, a knowledge.db fica sem o conhecimento da onda.

# Idempotente (upsert por chave natural): re-ingerir apos o 10.bis e
# inofensivo. Read-only sobre o state.json; escreve so em ~/.claude/cstk/
# knowledge.db. NUNCA gateia — toda falha degrada para no-op.
cstk recall --ingest --state-dir "$AGENTE_00C_STATE_DIR" 2>/dev/null \
  || echo "knowledge-db: ingestao (rede de seguranca) pulada — cstk/sqlite3/jq ausentes" >&2

5. Cleanup

  • state-lock.sh release --state-dir "$AGENTE_00C_STATE_DIR" SEMPRE.
  • git commit -m "feature-00c resume: $SHORT (onda N)" apos artefatos atualizados.

Exit codes

Exit Significado
0 Retomada com sucesso
3 Lock ocupado
4 Hash divergente (state/briefing/constitution) — bloqueio humano gerado
5 Bloqueio pendente sem --resposta-bloqueio
6 state.json inexistente ou corrompido

Listar bloqueios pendentes (exit 5)

bloqueios.sh list --state-dir "$AGENTE_00C_STATE_DIR" --status aguardando | jq -r '.[] | "\(.id): \(.question)\n  contexto: \(.context_for_answer)"' >&2
stderr ""
stderr "Para responder, re-invoque:"
stderr "  /feature-00c-resume $SHORT --resposta-bloqueio \"<sua resposta>\""
exit 5

Anti-padroes

  • NAO pular a validacao de hash (passo 3) — TOCTOU window e onde tampering escapa.
  • NAO validar hash ANTES de adquirir lock — outra sessao pode estar escrevendo state.json.
  • NAO chamar ScheduleWakeup se a onda terminou em bloqueio_humano, aborto ou concluido.
  • NAO assumir que --resposta-bloqueio aplica a TODOS os bloqueios pendentes — opera no primeiro aguardando em ordem cronologica; multiplos bloqueios exigem re-invocacoes sucessivas.