Skip to content

Latest commit

 

History

History
202 lines (157 loc) · 9.37 KB

File metadata and controls

202 lines (157 loc) · 9.37 KB

PRD: prostaff-hooks

Problema

O fluxo de desenvolvimento do ProStaff API no Claude Code sofre de três ineficiencias de contexto:

  1. Input verboso de CLI: bundle exec rspec gera 400+ linhas; brakeman escupe JSON bruto; docker compose logs traz noise de health checks. Tudo isso vai direto pro contexto do Claude.

  2. CLAUDE.md monolitico: 300+ linhas carregadas toda sessao, independente de qual modulo esta sendo trabalhado. Mexendo em ai_intelligence, nao ha razao de carregar as regras de Riot API sync ou infraestrutura Docker.

  3. Sem orientacao de dominio: Claude nao sabe automaticamente que esta no modulo auth vs ai vs matches - precisa inferir do contexto, o que consome tokens e pode errar.

Inspiracao

  • RTK (Rust Token Killer): CLI proxy que intercepta comandos via PreToolUse hook, executa o comando real, comprime o output antes de devolver ao Claude. Economiza 60-90% de tokens de input.
  • Caveman: Plugin Claude Code que injeta modo terseness via SessionStart hook. Economiza 65-75% de tokens de output.

Solucao: prostaff-hooks

Plugin Claude Code exclusivo para ProStaff API. Tres mecanismos independentes que se complementam.

Mecanismo 1: Command Compressor (PreToolUse)

Intercepta chamadas Bash, reescreve comandos ProStaff para passar pelo ps-filter.js, que executa o comando original e comprime o output.

Claude executa: bundle exec rspec spec/controllers/
       |
pre-tool-use.js reescreve para:
  node /path/bin/ps-filter.js rspec -- bundle exec rspec spec/controllers/
       |
ps-filter.js roda o comando real, aplica lib/filters/rspec.js
       |
Claude ve: "FAILURES (2):\n  1) PlayersController...\n\nSUMMARY: 45 examples, 2 failures"
  em vez de 400 linhas

Comandos interceptados:

Comando original Filtro Reducao medida
bundle exec rspec rspec.js 44% a 99%
brakeman brakeman.js 91%
bundle exec rubocop rubocop.js 91%
bundle exec bundler-audit bundler_audit.js nao medido
docker compose logs docker.js 81%
docker <container> logs docker.js 81%
rails db:migrate rails.js 91%

Medido com npm run measure, contra saida real guardada em tests/fixtures/. Nao ha taxa unica: a saida comprimida tem tamanho quase constante, entao a reducao cresce com o tamanho da saida original. A faixa do rspec vai de uma suite pequena com quatro falhas (44%) ate uma suite que nao carrega e repete o mesmo erro por arquivo de spec (99%), passando pela suite real do projeto, com 43 falhas em 3330 exemplos (87%).

O numero do rails db:migrate e de um banco zerado, com 138 migrations. Rodar uma migration so nao comprime nada, de proposito: ate cinco migrations o DDL vai inteiro, porque ali ele e a resposta e nao ruido.

O bundler-audit e o unico filtro roteado sem numero: ele tem teste unitario, mas nao ha fixture de saida real, e sem isso a taxa seria chute. Fica sem numero ate alguem capturar um run contra o prostaff-api.

Ativacao: so para sessoes cujo transcript_path inclui prostaff-api.

Mecanismo 2: Domain Context Injector (SessionStart)

Ao iniciar uma sessao em prostaff-api/, detecta o dominio ativo via git status --short e injeta um contexto minimo e especifico, em vez de carregar o CLAUDE.md inteiro.

Dominios:

Dominio Detectado por Contexto injetado
ai modules/ai_intelligence/ modificado DraftAnalyzer, AiChampionVector/Matrix, agent: ai-intelligence-specialist
auth modules/authentication/ modificado JWT, Pundit, SSRF whitelist, agent: security-specialist
analytics analytics/ modificado PlayerPerformanceService, eager loading, cache 5min
scouting scouting/ modificado organization_scoped, Meilisearch
matches matches/ modificado Riot API + PandaScore, Sidekiq, circuit breaker
players players/ modificado SyncPlayerJob, player_match_stats, KDA guard
infra docker-compose, Gemfile, .github/ Redis ports, Coolify, Docker network
testing spec/ modificado CRITICO: .env.test, nunca producao, rails_helper guard
general default Regras gerais: complexity, patterns, sem emojis

Mecanismo 3: Mode Commander (skills do plugin)

Comandos para gerenciar o estado dos hooks durante a sessao.

Este mecanismo foi desenhado como hook de UserPromptSubmit e nunca funcionou. O TUI resolve qualquer texto que comece com / contra o registry de comandos antes de submeter, e aborta com Unknown command quando nao encontra. Sem submissao o hook nao dispara, entao ele estava correto e inalcancavel ao mesmo tempo. Um comando com : no nome so existe como skill de plugin, onde plugin/skills/<dir>/SKILL.md vira /<plugin>:<name>.

Desde a v0.3.0 os comandos sao skills do plugin ps, e o hook foi removido.

Comando Acao
/ps:domain Mostra dominio detectado atualmente
/ps:domain <nome> Forca um dominio manualmente
/ps:check Instrucoes para rodar brakeman + rubocop comprimidos
/ps:full Desabilita compression para esta sessao (debug)
/ps:help Lista todos os comandos

Skill: ps-check

Skill Claude Code para /ps:check - roda brakeman + rubocop com output comprimido e reporta no formato estruturado.

Statusline

Script statusline.sh que le o flag de dominio e exibe badge no statusline do Claude Code: [PS:AI] / [PS:AUTH] / [PS:ANALYTICS] / etc.

Arquitetura

prostaff-hooks/
├── PRD.md
├── package.json
├── install.sh
├── statusline.sh
├── hooks/
│   ├── pre-tool-use.js       # Reescreve comandos ProStaff -> ps-filter
│   ├── session-start.js      # Detecta dominio, injeta contexto minimo
│   └── hooks.json            # Registro dos hooks no manifesto do plugin
├── bin/
│   ├── ps-filter.js          # CLI: executa cmd + aplica filtro
│   └── ps-domain.js          # CLI: le ou define o dominio da sessao
├── lib/
│   ├── domain-detector.js    # git status -> dominio
│   ├── domain-store.js       # dominio da sessao em disco
│   ├── domains.js            # lista de dominios validos
│   ├── project.js            # raiz do projeto, versao do Rails pelo lockfile
│   ├── shell.js              # quoting de caminho em linha de comando
│   └── filters/
│       ├── rspec.js          # Failures + summary
│       ├── brakeman.js       # HIGH/CRITICAL only
│       ├── rubocop.js        # Grouped by cop, top 10
│       ├── bundler_audit.js  # Advisories por gem
│       ├── docker.js         # Last 30 meaningful lines
│       ├── rails.js          # Migrations run + errors
│       └── outcome.js        # Veredito por exit code, nao por texto
└── skills/                   # Comandos /ps: do plugin
    ├── ps-help/SKILL.md
    ├── ps-domain/SKILL.md
    ├── ps-check/SKILL.md
    └── ps-full/SKILL.md

Diferenciais vs RTK e Caveman

Feature RTK Caveman prostaff-hooks
Command compression 100+ generic - 6 ProStaff-specific
Context injection - Verbose->terse Domain-aware: slice do CLAUDE.md
Memory integration - compress skill Le /memory/ existente
Domain detection - - git status -> modulo ativo
Escopo Global Global Exclusivo prostaff-api
Runtime Rust binary JS/Python Node.js puro (sem deps)

Decisoes de Design

Por que PreToolUse rewrite em vez de PostToolUse? RTK provou que reescrever o comando funciona. PostToolUse nao consegue modificar o output do tool (so adiciona contexto). Reescrever para ps-filter.js garante que o Claude veja apenas o output comprimido.

Por que Node.js sem dependencias externas? Zero npm install. O filtro e executado a cada comando - startup tem que ser rapido. Node.js stdlib (child_process, fs, path) e suficiente para todos os filtros.

Por que project-local settings.json? Hooks instalados em prostaff-api/.claude/settings.json - nao interferem com outros projetos. RTK e Caveman sao globais; prostaff-hooks e intencional e cirurgico.

Por que domain detection via git status? git status --short e rapido (< 100ms), reflete o trabalho atual, e nao requer configuracao. O desenvolvedor ja esta commitando mudancas no modulo que esta trabalhando.

Metricas de Sucesso

  • RSpec output: de ~400 linhas para ~10-20 linhas (>90% reducao)
  • Brakeman output: de ~200 linhas JSON para ~15 linhas (>90% reducao)
  • RuboCop output: de ~500 linhas para ~15 linhas (>95% reducao)
  • Context injection: de 300+ linhas do CLAUDE.md para ~5-8 linhas de contexto de dominio
  • Overhead por comando: < 50ms (ps-filter.js startup + filter)

Instalacao

cd /home/bullet/PROJETOS/prostaff-hooks
bash install.sh
# Reiniciar Claude Code

O install.sh escreve os hooks e a statusLine no settings.json sozinho: nao ha passo manual. Statusline de terceiro na mesma chave e preservada; a nossa e reescrita a cada instalacao, e hook orfao apontando para script que sumiu e podado.

Status

  • PRD
  • Implementacao core (todos os arquivos)
  • Testes dos filtros com output real (tests/fixtures/, npm run measure)
  • Validacao do formato de rewrite do PreToolUse hook (tests/conformance.test.js)
  • Statusline integrada (escrita pelo install.sh, coberta na conformidade)
  • Fixture de saida real do bundler-audit para medir o unico filtro sem numero