↑ ↓ para mover · Enter para abrir · Esc para fecharToque em um resultado

Arquitetura · como o harness funciona

Entre o modelo e o disco, um hook.

O Claude Code traz o modelo e as ferramentas dele. O Nerviz acrescenta cinco tipos de peça em volta. Quatro orientam o modelo. A quinta roda como processo em cada evento e pode recusar a ação.

§ uma feature, passando pelos hooks

Um caso de uso encontra o harness

O UC-005 do bank-app, do primeiro prompt ao build verde, em nove passos. O terminal mostra quais modos de hook rodaram e o que imprimiram: as recusas são o texto dos próprios hooks.

1 / 9

Um prompt abre o turno

Você digita /new-feature. O guard prompt fecha a fase anterior, registra o que já está no disco e abre uma fase para new-feature, classe orchestrator. O corpo da skill entra no contexto e fica até o fim do run.

§ cinco tipos de peça

Quem carrega, quem chama, quem pode dizer não

  • CLAUDE.md

    Índice e tabela de roteamento. A norma em si fica na rule ou na skill para a qual ele aponta.

    Entra no contexto
    Sempre, no início da sessão
    Invocado por
    Ninguém: ele carrega
    Pode bloquear
    Não
  • rule

    Uma norma: o que precisa ser verdade. Uma folha: nunca cita skill, agent ou comando.

    Entra no contexto
    Quando um arquivo que casa com os paths dela é tocado
    Invocado por
    Ninguém: ela carrega
    Pode bloquear
    Não
  • skill

    Um procedimento. A classe fixa o modelo, as seções do corpo e onde ela pode escrever.

    Entra no contexto
    Na invocação, e fica para os turnos seguintes
    Invocado por
    Você, com /nome, ou o modelo
    Pode bloquear
    Não
  • agent

    Execução isolada: contexto próprio, tools restritas e modelo próprio.

    Entra no contexto
    Na delegação, num contexto limpo
    Invocado por
    Uma skill, pela Agent tool
    Pode bloquear
    Não
  • hookexit 2

    ArchHook.jar: Java, onze modos, sem shell. Ligado no settings.json.

    Entra no contexto
    Nunca como texto: roda como processo
    Invocado por
    O runtime, no evento
    Pode bloquear
    Sim, exit 2

Um agent só existe por um de três motivos: preservar contexto, restringir tools ou trocar de modelo. O que precisa valer sempre é hook ou regra de permissions.deny, nunca prosa em markdown.

§ o catálogo, contado

Quantas skills e agents

Toda skill e todo agent do nerviz pertence a uma classe em extensions.json, e o schema falha em qualquer arquivo que nenhuma classe liste. As classes são o catálogo: estes números são lidos delas na release mais recente, nunca digitados à mão.

32skills

Exportados para todo projeto gerado: 27

  • design 13
  • orchestrator 3
  • build 7
  • observer 2
  • meta 1
  • ops 4
  • report 2
7agents

Exportados para todo projeto gerado: 5

  • driver 1
  • executor 1
  • installer 4
  • verifier 1
Contagem ao longo do tempo
327
2026-09-112026-10-27
Adições mais recentes
  1. project-configskill · opsnova2026-10-24
  2. platform-upgradeskill · build2026-10-19
  3. new-projectskill · ops2026-10-15
  4. mapstruct-installeragent · installer2026-10-14
  5. ai-architectskill · design2026-10-13

Lido de extensions.json na release v0.44.0 do nerviz, publicada em 2026-10-27.

§ quem chama quem

Três comandos, três cadeias

Cada comando abre uma cadeia própria:

  • /init-project cria o projeto, uma única vez.
  • /new-feature projeta um caso de uso e entrega uma spec, sem código.
  • /new-feature-implement constrói o código a partir da spec aprovada.

Peças tracejadas só rodam quando se aplicam.

  • skill
  • agent
  • só quando se aplica
§ territory como dado

Cada classe só escreve nos próprios paths

Cada skill pertence a uma de sete classes, e cada agent a uma de quatro. A classe lista o que pode escrever no extensions.json, e o guard recusa todo o resto, deny by default. Escolha uma classe:

bank-app/
  • .claude/
  • CLAUDE.md
  • docs/
  • use-cases/BACKLOG.md
  • use-cases/UC-005-record-kyc-verdict/20-persistencia.md
  • use-cases/UC-005-record-kyc-verdict/UC-005-spec.md
  • lessons-learned/
  • src/main/java/…/domain/model/Customer.java
  • src/test/java/…/domain/model/CustomerTest.java
  • pom.xml
  • docker-compose.yml
  • .env.example
quem

write_allow

  • pode escrever
  • recusado: fora da territory
  • recusado: spec congelada
  • só fechamento de status e checklist
§ rules carregam por path

Tocou no arquivo, recebeu as normas

Toda rule declara paths. Quando um arquivo que casa é tocado, a rule entra no contexto sozinha, e ninguém precisa lembrar de citá-la. Estas são as 21 rules do bank-app, com os globs que o export escreveu para o blueprint dele. Escolha um arquivo:

  • architecture-ddd.md
  • value-objects.md
  • naming.md
  • code-quality.md
  • error-handling.md
  • logging.md
  • lombok.md
  • personal-data.md
  • secrets.md
  • api-rest.md
  • api-graphql.md
  • inbound-admission.md
  • authorization.md
  • observability.md
  • persistence.md
  • messaging.md
  • scheduling.md
  • http-client.md
  • ai.md
  • caching.md
  • search.md
  • testing.md
  • transport-security.md
  • spec-diagrams.md
  • 00-index.md
§ o mapa de hooks

Cada evento, cada modo

O que um projeto gerado registra no .claude/settings.json. Toda entrada roda java -jar .claude/hooks/ArchHook.jar <mode>, em exec form, igual no Linux, no macOS e no Windows. Escolha um evento para ver quando ele dispara.

Os eventos, na ordem em que disparam em um turno

UserPromptSubmitaudit promptguard prompt

Você aperta Enter. O hook roda antes de o Claude ler uma palavra.

Você digitou

youVocêdigita o comando
hookUserPromptSubmitabre o registro da run e tira um baseline do git
claudeClaudelê o prompt

Modos neste evento

  • audit prompt
    Abre o registro da run quando o prompt é de uma skill auditada, para atribuir tokens e arquivos a ela.o projeto pode desligar
  • guard prompt
    Fecha a fase anterior e abre a que o prompt nomeia, para os guards saberem qual skill está rodando.
PreToolUseguard callguard writeguard bashschemaaudit callaudit ask

O Claude está prestes a usar uma ferramenta. O hook ainda pode dizer não.

Você digitou

claudeClaudepersistence-architect quer escrever docker-compose.yml
hookPreToolUseguard write confere o território da classe dela
✓ a ferramenta roda
✕ exit 2: o motivo volta para o Claude e nada é escrito

Modos neste evento

  • guard call
    Impede que uma run de design alcance uma skill de build.pode bloquear

    Bloqueia: Uma chamada Skill a uma skill de classe build enquanto uma run de design está aberta.

  • guard write
    Toda skill e todo agente escreve só dentro do território da sua classe, e um spec aprovado fica congelado.pode bloquear

    Bloqueia: Uma escrita fora do território da skill ou do agente em execução, e qualquer escrita em um caso de uso aprovado, salvo o fechamento do status e o marcar de checklist.

  • guard bash
    A mesma checagem, vinda do shell: um heredoc, sed -i ou tee não pode fazer o que um Write não pode.pode bloquear

    Bloqueia: Uma escrita via shell em um lugar que a classe não pode escrever ou em um caso de uso congelado, e um force push em qualquer grafia.

  • schema
    Mantém válidos os arquivos de instrução do harness, para uma skill, um agente ou uma entrada de hook quebrada falhar na hora e não em uma run futura.pode bloquear

    Bloqueia: Um SKILL.md, agente, regra ou entrada de hook do settings.json inválido, e um segredo no .mcp.json.

  • audit call
    Registra cada chamada de Skill, Task ou Agent como um nó da cadeia.o projeto pode desligar
  • audit ask
    Anota que o Claude está esperando você, para a espera não contar como trabalho.o projeto pode desligar
SubagentStartcontext subagenttests agent-start

O Claude passa o trabalho a um subagente. O hook pode carregar contexto antes do primeiro turno dele.

Você digitou

claudeClaudedelega o código do caso de uso
hookSubagentStartcontext subagent entrega o catálogo de padrões
subjava-spring-boot-developercomeça com o catálogo no contexto

Modos neste evento

  • context subagent
    Entrega o catálogo de padrões de projeto a todo agente cuja classe o pede, antes do primeiro turno. Os outros agentes não recebem nada.
  • tests agent-start
    Anota que um subagente escritor está rodando, para os testes esperarem por ele.
PostToolUsecheckschemaformataudit fileaudit answer

Uma ferramenta acabou de rodar. A mudança já foi feita, e o hook olha para ela.

Você digitou

subjava-spring-boot-developeredita Customer.java
hookPostToolUsecheck, format e a trilha olham o arquivo
✓ limpo: o trabalho segue
✕ exit 2: o arquivo já foi escrito, e o Claude é mandado corrigir agora

Modos neste evento

  • check
    Segura a arquitetura enquanto o código é escrito: a fronteira é julgada a cada edição, não no review.pode bloquear

    Bloqueia: Um import ou nome qualificado proibido, ou uma compilação incremental que falha no módulo tocado. O arquivo já foi escrito, então o Claude é mandado corrigir.

  • schema
    Mantém válidos os arquivos de instrução do harness, para uma skill, um agente ou uma entrada de hook quebrada falhar na hora e não em uma run futura.pode bloquear

    Bloqueia: Um SKILL.md, agente, regra ou entrada de hook do settings.json inválido, e um segredo no .mcp.json.

  • format
    Roda spotless:apply no módulo tocado, para a formatação nunca custar um turno.
  • audit file
    Registra cada arquivo que uma run tocou.o projeto pode desligar
  • audit answer
    Registra cada pergunta e a sua resposta, com redação, no relatório.o projeto pode desligar
SubagentStopaudit agenttests agent-end

O subagente termina e devolve o resultado.

Você digitou

subjava-spring-boot-developertermina
hookSubagentStopfecha o relatório dele e libera os testes
claudeClauderecebe o resultado

Modos neste evento

  • audit agent
    Fecha o relatório do subagente. Os tokens dele vêm do próprio transcript.o projeto pode desligar
  • tests agent-end
    Libera os testes quando o subagente escritor termina.
Stopschemaguard sweepcompose gatetestsaudit flush

O Claude acha que terminou. É o último portão antes de o turno acabar.

Você digitou

claudeClaudediz que terminou
hookStopschema, guard sweep, compose gate e tests olham o que de fato mudou
✓ todos os portões verdes: o turno acaba
✕ um portão falha: o Claude continua e corrige

Modos neste evento

  • schema
    Mantém válidos os arquivos de instrução do harness, para uma skill, um agente ou uma entrada de hook quebrada falhar na hora e não em uma run futura.pode bloquear

    Bloqueia: Um SKILL.md, agente, regra ou entrada de hook do settings.json inválido, e um segredo no .mcp.json.

  • guard sweep
    O reforço no fim do turno: compara o disco com o baseline do git, então pega as escritas que nenhum guard em tempo de ferramenta conseguiu ler.pode bloquear

    Bloqueia: Qualquer mudança deste turno que a classe não pode escrever. Ele detecta; não previne.

  • compose gate
    Uma stack que não sobe é pega quando o turno acaba, não depois na máquina de alguém.pode bloquearo projeto pode ajustar

    Bloqueia: O fim do turno enquanto um serviço do compose está exited ou dead.

  • tests
    Um turno não termina com teste vermelho.pode bloquear

    Bloqueia: O fim do turno enquanto o verify falha nos módulos alterados desde o HEAD. Ele espera enquanto um subagente escritor roda.

  • audit flush
    Gera o relatório da run a partir do log e escreve a linha do ledger.o projeto pode desligar
PermissionRequest · PermissionDenied · PostToolUseFailure · PreCompact · StopFailure · SessionEndaudit permaudit failaudit compactaudit stopfailaudit close

Seis eventos discretos. Só escrevem na trilha de auditoria, e nenhum bloqueia.

Você digitou

claudeClauderoda git push, que fica em ask
youVocêresponde não
hookPermissionDeniedescreve uma linha na trilha

Modos neste evento

  • audit perm
    Registra uma permissão pedida ou negada.o projeto pode desligar
  • audit fail
    Registra uma ferramenta que falhou, como retrabalho.o projeto pode desligar
  • audit compact
    Registra uma compactação de contexto.o projeto pode desligar
  • audit stopfail
    Registra uma falha ao parar.o projeto pode desligar
  • audit close
    Fecha a run aberta quando a sessão termina.o projeto pode desligar

mode pode recusar com exit 2 · mode nunca bloqueia ·pode bloquear o projeto pode ajustar o projeto pode desligar

Por que cada modo existe, o que ele bloqueia e o que um projeto pode mudar: todos, em uma tabela, com o detalhe.

Abrir o catálogo de modos →
§ o harness, testado

Cada recusa acima roda no CI

O validate.yml roda em todo push e todo pull request. Os testes de hook executam o mesmo java -jar .claude/hooks/ArchHook.jar que os registros executam, no Ubuntu, no macOS e no Windows. Outro job verifica os invariantes do grafo de prompts, e outro exporta cada blueprint duas vezes e exige árvores idênticas.

Último run na mainstatus do validate.yml na main, ao vivo do GitHub
validate.yml · 9fb82ed · 2026-10-13 · 6m17s
  1. hooks · ubuntu-latest✓1m32s
  2. hooks · macos-latest✓1m37s
  3. hooks · windows-latest✓3m15s
  4. design invariants✓33s
  5. export is reproducible and self-contained✓55s
  6. exemplar imports resolve against the real classpath✓6m13s

Os seis jobs rodam em paralelo. Em cada job de hooks, o build --verify roda antes dos testes: o jar commitado precisa ser, byte a byte, o que o código-fonte compila, então os testes exercitam bytes revisados.

Abrir este run →
245/ 260

runs do validate.yml passaram desde 2026-09-11. 11 falharam e 4 foram cancelados. Contagem de 2026-10-13.

Os vermelhos continuam públicos no Actions. O badge acima é ao vivo; os números são um retrato.

Todos os runs →

Cada step desse run, em replay

Os 58 steps nomeados do validate.yml, com os tempos que o GitHub registrou no run acima, 12× mais rápido. O job de hooks roda cada step em três runners, um ponto para cada: Ubuntu, macOS e Windows.

6m17s / 6m17s12×
hooks3m15s
  1. Set up job · checkout · setup-java
  2. doctor
  3. committed ArchHook.jar is what the source compiles to
  4. the jar runs what the hooks run
  5. hook blocks forbidden import, from the payload and from argv
  6. format, check and tests hand Maven the module the edited file belongs to
  7. tests defers while a writer subagent of the session runs, and only then
  8. hook blocks a cwd-relative frontmatter injection
  9. schema blocks a migrations entry no project would see
  10. hook reports a compose image tag that disagrees with src/test
  11. guard keeps each skill inside its class's territory
  12. guard keeps each agent inside its class's territory
  13. guard bash refuses force pushes and holds shell writes to the phase
  14. guard sweep reports this turn's writes, never pre-existing dirt
  15. guard status prints the open phase the cockpit draws
  16. schema blocks a mod that would load half-way
  17. compose gate blocks a published service no host client can reach
  18. doctor gate fails on every gated line and only on those
  19. schema blocks a settings file that re-enables a colliding plugin
  20. doctor names a personal skill that shadows a project skill, and never gates
  21. doctor checks the agent instruction files against the blueprint, and never gates
  22. doctor sweeps every source file for forbidden imports, with check's own match
  23. export notes only real overwrites, and never guesses the stamp's commit
  24. context subagent hands the catalog to pattern_catalog agents only
  25. audit renders where the run spent, redacts tool errors, skips what class or project turns off
  26. audit genesis fills GENESIS from the transcripts, once
design invariants33s
  1. Set up job · checkout · setup-java
  2. frontmatter schema (extensions.json is the single owner — invariant 10)
  3. decisions/ doesn't grow paths or enter 00-index.md
  4. no hardcoded Spring/Java version outside decisions/ (invariant 8)
  5. new blueprint doesn't touch prompts
  6. rules is a leaf of the graph
  7. norm contains no code boilerplate
  8. no new commands/
  9. exemplars have the .example suffix at the end
  10. exemplar bodies carry no comment but Javadoc
  11. XML exemplars are well-formed
  12. spec template diagrams name only what their text defines
  13. cache exemplars decide every library default, and only they cache
  14. AI exemplars decide every library default, and only they reach the library
  15. GraphQL exemplars decide every limit and batch every child list
  16. document-family exemplars name collection, alias and version, and run a replica set
  17. search exemplars keep the index a strict, versioned projection
  18. auditing exemplars keep the history whole, its actor named and its prune safe
  19. REST exemplars version every handler from one configuration
  20. admission exemplars keep one bounded limiter per caller and an inbound cap ahead of idempotency
  21. blueprint-declared templates exist on disk
  22. issue forms cited by skills exist
  23. compose service templates merge and parse
  24. each norm has a single owner
  25. no dependencies outside the Java ecosystem
  26. every norm `paths` matches some blueprint
export is reproducible and self-contained55s
  1. Set up job · checkout · setup-java
  2. export twice per blueprint, require identical trees
  3. the exported tree carries nothing that only exists here
  4. the exported tree passes its own schema
  5. re-export deletes what export.retired names
exemplar imports resolve against the real classpath6m13s
  1. Set up job · checkout · setup-java
  2. reference project from the Initializr
  3. build the classpath
  4. every exemplar import exists in a JAR
  5. exemplars don't use known deprecated symbols

Cada passo do player, e o teste que o prova

  1. passo 4

    Uma skill de design não consegue escrever o docker-compose.yml. O caso que originou tudo é um dos casos.

    $ java .claude/.ci/SkillTerritoryTest.java✅ compose file outside the territory — blocked (exit 2)✅ compose allowed once docker-architect joined (exit 0)✅ the implement thread itself still may not write compose (exit 2)59 casos, todos verdes

    A mesma territory vale para escritas pelo shell, e toda grafia de force push é recusada.

    $ java .claude/.ci/BashGuardTest.java✅ `-f` — blocked✅ executor: `sed -i -e` on a file outside its territory — blocked29 casos, todos verdes
  2. passo 6

    Um agent é julgado pela própria classe, seja qual for a fase que quem o chamou deixou aberta.

    $ java .claude/.ci/AgentTerritoryTest.java✅ the executor writes main source (exit 0)✅ archunit-installer is refused docker-compose.yml (exit 2)37 casos, todos verdes

    O catálogo de design patterns só chega aos agents cuja classe o pede.

    $ java .claude/.ci/SubagentContextTest.java✅ general-purpose receives nothing✅ context subagent: catalog to pattern_catalog agents only, within max_chars.
  3. passo 7

    Um import proibido dá exit 2, pelo payload do hook e pelo check <path>.

    $ java .claude/.ci/BoundaryTest.java  ✓ stdin payload blocks the forbidden import  ✓ check <path> blocks it with stdin left open✅ Boundary enforced: forbidden import blocked with exit 2, from the payload and from argv.
  4. passo 9

    O sweep do Stop só aponta o que este turno escreveu, e nunca bloqueia duas vezes.

    $ java .claude/.ci/SweepTest.java✅ write outside the territory — reported, pre-existing dirt is not✅ stop_hook_active — does not block twice

    O tests espera enquanto um subagent escritor roda, e só nesse caso.

    $ java .claude/.ci/TestsDeferTest.java✅ tests: deferred while a writer subagent runs, Maven called otherwise.

O grafo de prompts, verificado como código

O job design invariants transforma cada regra da arquitetura do próprio harness num step que falha. Alguns deles, com o nome que têm no workflow:

  • frontmatter schema (extensions.json is the single owner — invariant 10)
  • rules is a leaf of the graph
  • new blueprint doesn't touch prompts
  • no hardcoded Spring/Java version outside decisions/ (invariant 8)
  • each norm has a single owner
  • every norm `paths` matches some blueprint

E em todo projeto gerado

O projeto leva o próprio CI. O job architectural boundaries roda o doctor gate, que falha quando o jar, os hooks, o schema ou as boundaries estão quebrados, ou quando algum arquivo-fonte tem um import proibido.

bank-app · build.yml · a3cc28a · 2026-10-15
  • architectural boundariesjava .claude/hooks/ArchHook.java doctor gate10s
  • build and tests3m37s
Abrir o run do bank-app →