@payconductor/houndsman 0.1.0 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -89
- package/assets/logo-legacy.png +0 -0
- package/assets/logo.png +0 -0
- package/package.json +3 -2
- package/src/cli/index.ts +101 -10
- package/src/core/assets.ts +11 -0
- package/src/core/brief.ts +27 -5
- package/src/core/commands/findings.ts +618 -0
- package/src/core/commands/review.ts +2 -0
- package/src/core/commands/scaffold.ts +33 -44
- package/src/core/config.ts +42 -0
- package/src/core/diff-source.ts +140 -0
- package/src/core/file-classifier.ts +50 -2
- package/src/core/finding-anchor.ts +147 -0
- package/src/core/findings-state.ts +556 -0
- package/src/core/fix-batch.ts +236 -0
- package/src/core/git-revision.ts +105 -0
- package/src/core/jev/index.ts +1 -0
- package/src/core/jev/jev-client.ts +72 -11
- package/src/core/jev/jev-detector.ts +21 -19
- package/src/core/jev/jev-verify.ts +178 -0
- package/src/core/orchestrator.ts +362 -23
- package/src/core/paths.ts +9 -0
- package/src/core/registry-check.ts +15 -0
- package/src/core/report-builder.ts +118 -9
- package/src/core/run-status.ts +123 -0
- package/src/core/types.ts +10 -0
- package/src/core/verify.ts +175 -0
- package/src/core/watchdog-registry.ts +1 -2
- package/src/index.ts +78 -2
- package/src/server/artifacts.ts +67 -0
- package/src/server/client/App.tsx +158 -0
- package/src/server/client/ArtifactsPanel.tsx +48 -0
- package/src/server/client/Filters.tsx +83 -0
- package/src/server/client/FindingCard.tsx +122 -0
- package/src/server/client/FindingsList.tsx +54 -0
- package/src/server/client/RunList.tsx +52 -0
- package/src/server/client/SummaryBar.tsx +21 -0
- package/src/server/client/api.ts +37 -0
- package/src/server/client/constants.ts +94 -0
- package/src/server/client/index.tsx +12 -0
- package/src/server/client/types.ts +52 -0
- package/src/server/client-build.ts +47 -0
- package/src/server/index.ts +376 -0
- package/src/skill/AUDIT-PROTOCOL.md +2 -2
- package/src/skill/README.md +43 -11
- package/src/skill/SETUP.md +16 -4
- package/src/skill/SKILL.md +48 -0
- package/src/skill/fix.md +206 -0
- package/src/skill/{houndsman.md → hunt.md} +83 -33
- package/src/skill/{houndsman-update.md → train.md} +12 -12
- package/src/skill/verify.md +70 -0
- package/src/tests/findings-anchor.test.ts +120 -0
- package/src/tests/findings-commands.test.ts +476 -0
- package/src/tests/findings-state.test.ts +325 -0
- package/src/tests/fix-batch.test.ts +257 -0
- package/src/tests/review-scripts.test.ts +299 -0
- package/src/tests/run-status.test.ts +147 -0
- package/src/tests/scaffold.test.ts +59 -0
- package/src/tests/server.test.ts +242 -0
- package/src/tests/verify.test.ts +170 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: houndsman
|
|
3
|
+
description: 'Revisa Pull Requests com watchdogs especializados por domínio de negócio e mantém essas regras alinhadas ao projeto. Use para revisar/code review de PR, atualizar as regras de revisão dos watchdogs e corrigir/verificar os findings da revisão. Capabilities: `hunt` (revisar a PR), `train` (atualizar regras), `fix` (corrigir achados), `verify` (violações resolvidas?).'
|
|
4
|
+
argument-hint: 'Capability: hunt | train | fix | verify (default: hunt)'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# houndsman — {{projectName}}
|
|
8
|
+
|
|
9
|
+
O **houndsman** revisa Pull Requests com **watchdogs** — agentes especialistas por domínio de
|
|
10
|
+
negócio. Cada watchdog audita a parte do diff que é sua e grava **findings** (achados); o motor
|
|
11
|
+
consolida tudo num relatório. O motor é o CLI **`houndsman`**; as regras do projeto vivem em
|
|
12
|
+
`houndsman.config.ts` + `.houndsman/`.
|
|
13
|
+
|
|
14
|
+
**Terminologia:** **houndsman** = orquestrador/treinador (CLI + motor) · **watchdog** = agente
|
|
15
|
+
especialista por domínio · **finding** = um achado da revisão · **Jev** = pré-análise opcional.
|
|
16
|
+
|
|
17
|
+
## Capabilities
|
|
18
|
+
|
|
19
|
+
| Capability | Objetivo | Documento |
|
|
20
|
+
|---|---|---|
|
|
21
|
+
| **`hunt`** | Revisar uma Pull Request e produzir o relatório de achados. | `.houndsman/core/skill/hunt.md` |
|
|
22
|
+
| **`train`** | Manter as regras dos watchdogs alinhadas ao que o projeto aplica. | `.houndsman/core/skill/train.md` |
|
|
23
|
+
| **`fix`** | Corrigir os achados de uma revisão já finalizada. | `.houndsman/core/skill/fix.md` |
|
|
24
|
+
| **`verify`** | Conferir se as violações foram resolvidas, sem re-revisar a PR. | `.houndsman/core/skill/verify.md` |
|
|
25
|
+
|
|
26
|
+
## Invocação
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
/houndsman → hunt (default)
|
|
30
|
+
/houndsman hunt → revisar a Pull Request
|
|
31
|
+
/houndsman train → atualizar as regras dos watchdogs
|
|
32
|
+
/houndsman fix → corrigir os findings
|
|
33
|
+
/houndsman verify → conferir se as violações foram resolvidas
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Um argumento extra é o alvo da capability (ex.: `/houndsman hunt feature/minha-branch`).
|
|
37
|
+
Escolha a capability pelo que o usuário quer, leia o documento correspondente em
|
|
38
|
+
`.houndsman/core/skill/<capability>.md` e siga-o.
|
|
39
|
+
|
|
40
|
+
> **Depois de revisar (`hunt`), valide na UI:** `bun run houndsman server --open` — revise os
|
|
41
|
+
> achados e marque os que devem ser executados (`execute`) antes de rodar `fix`.
|
|
42
|
+
|
|
43
|
+
## Referências
|
|
44
|
+
|
|
45
|
+
- `.houndsman/core/skill/OUTPUT-FORMAT.md` — schema do JSON de saída dos watchdogs.
|
|
46
|
+
- `.houndsman/core/skill/AUDIT-PROTOCOL.md` — taxonomia da auditoria de regras (Modo B do `train`).
|
|
47
|
+
- `.houndsman/core/skill/SETUP.md` · `.houndsman/core/skill/README.md` — configuração e visão geral.
|
|
48
|
+
- `.houndsman/core/skill/example-review.md` — exemplo de relatório.
|
package/src/skill/fix.md
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# houndsman — {{projectName}} · `fix` (correção dos findings)
|
|
2
|
+
|
|
3
|
+
> **Documento canônico da capability `fix`.** O entry point do skill é o `SKILL.md`
|
|
4
|
+
> (`.agents/skills/houndsman/SKILL.md` e `.claude/skills/houndsman/SKILL.md`).
|
|
5
|
+
|
|
6
|
+
Corrige os achados de uma revisão **já finalizada** (`hunt`): lê a triagem, aplica as
|
|
7
|
+
correções marcadas e mantém o estado de triagem em dia — **sem editar o `state.json` à mão**.
|
|
8
|
+
|
|
9
|
+
Invocação: `/houndsman fix`. Não revisa nem altera regras; consome o que o `hunt` produziu.
|
|
10
|
+
|
|
11
|
+
**Quando usar:**
|
|
12
|
+
|
|
13
|
+
- Depois de `/houndsman` (ou `houndsman --finalize`), para corrigir os achados.
|
|
14
|
+
- O usuário marcou achados como `execute` na UI (`bun run houndsman server --open`) ou via
|
|
15
|
+
`findings set <id> --decision execute`.
|
|
16
|
+
- "Corrija os findings", "aplica as correções", "resolve os bloqueantes".
|
|
17
|
+
|
|
18
|
+
> **Pré-requisito:** existe `.houndsman/.runs/<branch-slug>/state.json` da run atual
|
|
19
|
+
> (gerado no `--finalize`). Se não existir, a revisão não foi finalizada — rode o `hunt` antes.
|
|
20
|
+
> A triagem (`execute`) é feita na UI (`bun run houndsman server --open`) ou via `findings set`,
|
|
21
|
+
> e é o que alimenta a fila de correção.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Modelo de triagem
|
|
26
|
+
|
|
27
|
+
Cada finding tem duas dimensões independentes (ver `findings-state.ts`):
|
|
28
|
+
|
|
29
|
+
- **decision:** `pending` · `execute` · `ignore` (+ `comment` opcional).
|
|
30
|
+
- **execState:** `pending` · `in_progress` · `done` · `stale`.
|
|
31
|
+
|
|
32
|
+
`fix` atua **somente** sobre `decision: execute`. Achados `pending` (ainda não triados) e
|
|
33
|
+
`ignore` (descartados) ficam intocados — não "conserte" o que o usuário não pediu.
|
|
34
|
+
|
|
35
|
+
> **A linha de um finding não é a identidade.** A identidade é o **fingerprint** de conteúdo
|
|
36
|
+
> (arquivo + regra + âncora). As correções deslocam linhas; o motor reancora pelo conteúdo.
|
|
37
|
+
> Ocorrências byte-idênticas (mesmo trecho E mesmo contexto) compartilham o id — tratadas
|
|
38
|
+
> como um grupo (`×N`); corrigir uma resolve o grupo.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Procedimento (incremental — nunca de uma vez)
|
|
43
|
+
|
|
44
|
+
Em PRs grandes há muitos achados. **Nunca** carregue a fila inteira: o `batch` entrega um
|
|
45
|
+
**grupo coeso, já paginado**, e a fila avança sozinha conforme você conclui os itens.
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
repita:
|
|
49
|
+
1. findings summary --json # contagem barata da fila
|
|
50
|
+
2. fila vazia? → fim
|
|
51
|
+
3. findings batch --json # grupo atual + outros grupos (sem parâmetros)
|
|
52
|
+
4. corrigir APENAS o grupo atual
|
|
53
|
+
5. findings sync # reancora por conteúdo (uma vez)
|
|
54
|
+
6. findings done <ids> | set --decision pending --comment <motivo>
|
|
55
|
+
até a fila esvaziar
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### 1. Medir a fila
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
bun run houndsman findings summary --json
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
`byDecision.execute` (menos os `done`) é o tamanho da fila. Se for `0`, acabou.
|
|
65
|
+
|
|
66
|
+
### 2. Pegar o lote (contexto para correção)
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
bun run houndsman findings batch --json
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
O `batch` decide sozinho o **melhor agrupamento** para a run atual (por arquivo, por regra ou
|
|
73
|
+
por watchdog) e devolve:
|
|
74
|
+
|
|
75
|
+
- o **grupo atual** (paginado) — a unidade de trabalho;
|
|
76
|
+
- a lista dos **outros grupos disponíveis**;
|
|
77
|
+
- os totais (`fila`, `retornados`, `grupos`).
|
|
78
|
+
|
|
79
|
+
Sem parâmetros, ele devolve **o primeiro grupo**. Como a fila exclui o que já está `done`,
|
|
80
|
+
cada chamada após progresso traz **o próximo grupo naturalmente** — não há contador para
|
|
81
|
+
gerenciar.
|
|
82
|
+
|
|
83
|
+
Flags (use só quando precisar — o mínimo de decisão):
|
|
84
|
+
|
|
85
|
+
| Flag | Quando usar |
|
|
86
|
+
|---|---|
|
|
87
|
+
| `--severity blocking` | Só os bloqueantes (ex.: "quero corrigir apenas os bloqueantes"). |
|
|
88
|
+
| `--group <key>` | Focar um grupo específico (a key aparece em "outros grupos"). |
|
|
89
|
+
| `--offset <n>` | Paginar dentro de um grupo grande. Raramente necessário. |
|
|
90
|
+
| `--include-done` | Auditar/rever itens já concluídos. |
|
|
91
|
+
|
|
92
|
+
### 3. Corrigir apenas o grupo atual
|
|
93
|
+
|
|
94
|
+
Para cada finding do grupo: abra o arquivo, leia o trecho ancorado (`line` é cache; confirme
|
|
95
|
+
pelo conteúdo) e aplique a **correção mínima** que satisfaz a `rule`, seguindo a **`action`** e
|
|
96
|
+
a `evidence`. Respeite o padrão que o watchdog cobra — não introduza um novo anti-padrão para
|
|
97
|
+
"calar" o finding. Marque antes: `findings set <id> --exec in_progress`.
|
|
98
|
+
|
|
99
|
+
**Contexto grande? Use um subagente** (ver abaixo) para o grupo — um grupo por vez.
|
|
100
|
+
|
|
101
|
+
### 4. Reancorar o estado
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
bun run houndsman findings sync
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
O `sync` reancora cada finding por **conteúdo** (trecho + contexto) e reporta `ok` / `moved` /
|
|
108
|
+
`stale`: âncora corrigida → vira `done` (quando a decisão era `execute`); âncora sumida de
|
|
109
|
+
outro modo → `stale` (revisar).
|
|
110
|
+
|
|
111
|
+
### 5. Confirmar ou devolver
|
|
112
|
+
|
|
113
|
+
Antes de fechar, confirme com o `verify` (barato): ele diz o que **resolveu** (`resolved`), o que
|
|
114
|
+
**persiste** e o que ficou **incerto** — sem re-revisar a PR. Com `--apply`, os `resolved` viram
|
|
115
|
+
`done` automaticamente.
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
bun run houndsman findings verify # relatório (não altera o estado)
|
|
119
|
+
bun run houndsman findings verify --apply # marca os resolvidos como done
|
|
120
|
+
bun run houndsman findings done <id...> # corrigidos (manual)
|
|
121
|
+
bun run houndsman findings set <id> --decision pending --comment "<motivo / falta>" # não corrigidos
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Não deixe achado `execute` no limbo. `--decision ignore` só quando o achado for aceito como
|
|
125
|
+
não-aplicável.
|
|
126
|
+
|
|
127
|
+
### 6. Repetir
|
|
128
|
+
|
|
129
|
+
Volte ao passo 1. A fila encolhe a cada volta; o `batch` traz o próximo grupo sem `--offset`.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Perguntas de decisão ao usuário
|
|
134
|
+
|
|
135
|
+
Pergunte (ferramenta de perguntas do harness) **antes** de corrigir quando o achado for:
|
|
136
|
+
|
|
137
|
+
- ambíguo ou com **múltiplas correções válidas**;
|
|
138
|
+
- uma mudança de **produto/arquitetura** (não é "só código");
|
|
139
|
+
- conflitante com outro achado/grupo.
|
|
140
|
+
|
|
141
|
+
Apresente o achado (`rule`, `message`, `action`, `evidence`) e as opções. Com a resposta,
|
|
142
|
+
registre-a: `findings set <id> --comment "<decisão>"`. Sem resposta, devolva à fila com
|
|
143
|
+
`--decision pending --comment "Aguardando decisão: …"` — **nunca "chute"**.
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Subagentes — contexto, não velocidade
|
|
148
|
+
|
|
149
|
+
Subagente serve para **isolar contexto**, não para paralelizar. Regras:
|
|
150
|
+
|
|
151
|
+
- **Um grupo por vez, em sequência.** Não dispare uma onda paralela: grupos podem editar o
|
|
152
|
+
mesmo arquivo, arquivos relacionados, imports ou código gerado — correções concorrentes
|
|
153
|
+
colidem.
|
|
154
|
+
- O subagente recebe **só** o grupo atual (findings + arquivo) e devolve um resumo compacto
|
|
155
|
+
(ids corrigidos / não corrigidos + motivo). Assim o agente principal não carrega o arquivo.
|
|
156
|
+
- A escrita do `state.json` fica **centralizada no agente principal**: o subagente apenas
|
|
157
|
+
lê/edita; `sync` / `done` / `set` são do orquestrador. Nada de `findings` dentro do subagente.
|
|
158
|
+
- Grupos pequenos (1–2 findings) o próprio agente corrige inline.
|
|
159
|
+
|
|
160
|
+
Prompt do subagente (modelo):
|
|
161
|
+
|
|
162
|
+
```
|
|
163
|
+
Corrija APENAS os findings abaixo, sem tocar em mais nada. Aplique a correção mínima que
|
|
164
|
+
satisfaz cada `rule`, seguindo `action`/`evidence`. Não rode comandos `findings`.
|
|
165
|
+
Retorne: id → corrigido/não corrigido + 1 linha de motivo.
|
|
166
|
+
|
|
167
|
+
Arquivo: <file>
|
|
168
|
+
- <id> [<severity>] <rule> (linha <line>) — <message>
|
|
169
|
+
Ação: <action>
|
|
170
|
+
Evidência: `<evidence>`
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Verificação
|
|
176
|
+
|
|
177
|
+
- `bun run houndsman findings summary` → os corrigidos saíram de `execute`/`in_progress`.
|
|
178
|
+
- `bun run houndsman findings sync` → sem `stale` inesperado.
|
|
179
|
+
- `bun run houndsman findings verify` → o que **resolveu** / **persiste** / ficou **incerto**
|
|
180
|
+
(sem re-revisar). Use `--apply` para marcar os `resolved` como `done`.
|
|
181
|
+
- Rode o build/testes do **projeto consumidor** (não o houndsman) depois das correções.
|
|
182
|
+
- Se a mudança for grande, reexecute o `hunt` para uma segunda passada:
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
bun run houndsman --base main
|
|
186
|
+
# ... subagentes ...
|
|
187
|
+
bun run houndsman --finalize
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
> O `--finalize` preserva os ids/fingerprints entre execuções (reancoragem por conteúdo);
|
|
191
|
+
> use `--clean` só quando quiser descartar a triagem anterior.
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Anti-padrões
|
|
196
|
+
|
|
197
|
+
- ❌ Carregar a fila inteira de uma vez (`findings list` sem filtro) — use `findings batch`.
|
|
198
|
+
- ❌ Corrigir vários grupos em paralelo (subagentes simultâneos sobre arquivos que se relacionam).
|
|
199
|
+
- ❌ Editar `.houndsman/.runs/<slug>/state.json` à mão — use os comandos `findings`.
|
|
200
|
+
- ❌ Corrigir findings `pending` ou `ignore` sem o usuário marcar `execute`.
|
|
201
|
+
- ❌ Chavear por `(file, line)` — a confiança é o **fingerprint** de conteúdo.
|
|
202
|
+
- ❌ Correção cosmética para "sumir" com o finding sem atender a `rule`.
|
|
203
|
+
- ❌ Reescrever o arquivo inteiro — correção mínima e localizada.
|
|
204
|
+
- ❌ Inventar mudança de produto/arquitetura para fechar um achado ambíguo — pergunte.
|
|
205
|
+
- ❌ Marcar `done` sem ter aplicado a correção (o `sync` reancora; o achado volta).
|
|
206
|
+
- ❌ Reexecutar o `hunt` inteiro só para conferir o fix — use `findings verify`.
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
# houndsman — {{projectName}} (
|
|
1
|
+
# houndsman — {{projectName}} · `hunt` (revisão de PR)
|
|
2
2
|
|
|
3
|
-
> **Documento canônico do skill
|
|
4
|
-
> (`.agents/skills/houndsman
|
|
3
|
+
> **Documento canônico da capability `hunt`.** O entry point do skill é o `SKILL.md`
|
|
4
|
+
> (`.agents/skills/houndsman/SKILL.md` e `.claude/skills/houndsman/SKILL.md`).
|
|
5
5
|
|
|
6
6
|
Revisão de PR: classificação de arquivos → revisão paralela por domínio → consolidação.
|
|
7
|
-
O motor é o CLI **`houndsman`**;
|
|
7
|
+
Invocação: `/houndsman` (default) ou `/houndsman hunt`. O motor é o CLI **`houndsman`**;
|
|
8
|
+
as regras do projeto ficam em `houndsman.config.ts` + `.houndsman/`.
|
|
8
9
|
|
|
9
|
-
**
|
|
10
|
-
|
|
11
|
-
**Jev** = pré-análise opcional (Passo 1.5).
|
|
10
|
+
**Quando usar:** revisar PR antes de merge · code review de feature branch · validar
|
|
11
|
+
mudanças antes de push.
|
|
12
12
|
|
|
13
13
|
## Quem executa o quê
|
|
14
14
|
|
|
15
|
-
- **Você** só invoca o skill: `/houndsman`. Não precisa rodar nenhum script à mão.
|
|
15
|
+
- **Você** só invoca o skill: `/houndsman [hunt]`. Não precisa rodar nenhum script à mão.
|
|
16
16
|
- **O skill** orquestra: executa o CLI `houndsman` e despacha os subagentes.
|
|
17
17
|
- **O CLI** tem passos distintos, um comando cada:
|
|
18
18
|
|
|
@@ -21,9 +21,10 @@ especialista por domínio que audita o diff (antigo "revisor"); **review/revisã
|
|
|
21
21
|
| 0. Contexto | `houndsman context` | subagente | `context.json` + `context-brief.md` → `context-summary.json` |
|
|
22
22
|
| 1. Preparar | `houndsman` | skill | `classification.json` + `candidates.json` + `briefs/` + `manifest.json` |
|
|
23
23
|
| 2. Revisar | *(subagentes)* | skill (via `runSubagent`) | `findings/<watchdog>.json` (um por watchdog) |
|
|
24
|
-
| 3. Finalizar | `houndsman --finalize` | skill | `review.md` |
|
|
24
|
+
| 3. Finalizar | `houndsman --finalize` | skill | `review.md` + `state.json` + `run.json` |
|
|
25
25
|
|
|
26
26
|
> Por que comandos separados? Entre o passo 1 e o 3 acontece trabalho de LLM (os subagentes).
|
|
27
|
+
> Depois do passo 3, a correção dos achados é a capability **`fix`** — ver `fix.md`.
|
|
27
28
|
|
|
28
29
|
**Arquitetura:**
|
|
29
30
|
|
|
@@ -42,12 +43,6 @@ especialista por domínio que audita o diff (antigo "revisor"); **review/revisã
|
|
|
42
43
|
- Cada watchdog recebe apenas seus arquivos relevantes (brief pronto) — nunca o diff completo.
|
|
43
44
|
- Saída estruturada (JSON) por watchdog → consolidada e deduplicada automaticamente.
|
|
44
45
|
|
|
45
|
-
## Quando Usar
|
|
46
|
-
|
|
47
|
-
- Revisar PR antes de merge
|
|
48
|
-
- Code review de feature branch
|
|
49
|
-
- Validar mudanças antes de push
|
|
50
|
-
|
|
51
46
|
---
|
|
52
47
|
|
|
53
48
|
## Passo 0 — Contexto da PR (subagente)
|
|
@@ -79,16 +74,31 @@ Gera em `.houndsman/.runs/<branch-slug>/`:
|
|
|
79
74
|
|
|
80
75
|
| Artefato | Conteúdo |
|
|
81
76
|
|---|---|
|
|
82
|
-
| `classification.json` | Watchdogs ativados por arquivo + status (A/M/D/R) |
|
|
77
|
+
| `classification.json` | Watchdogs ativados por arquivo + status (A/M/D/R) + churn |
|
|
83
78
|
| `candidates.json` | Indícios da pré-análise Jev (regra + arquivo + confiança) |
|
|
84
|
-
| `briefs/<watchdog>.md` | Instruções prontas para cada subagente |
|
|
85
|
-
| `manifest.json` | Resumo: watchdogs, arquivos, deletados, status, contexto, Jev |
|
|
79
|
+
| `briefs/<watchdog>.md` | Instruções prontas para cada subagente (arquivos por risco) |
|
|
80
|
+
| `manifest.json` | Resumo: watchdogs, arquivos, deletados, status, contexto, Jev, orçamento |
|
|
86
81
|
|
|
87
82
|
**Excluídos automaticamente:** lock files, `dist/`, `build/`, `.env*`, imagens, source
|
|
88
83
|
maps (padrões do projeto em `.houndsman/exclusions.ts`).
|
|
89
84
|
**Deletados:** não entram como conteúdo; vão para o brief de watchdogs com
|
|
90
85
|
`breakingChange` como candidatos a **breaking change**.
|
|
91
86
|
|
|
87
|
+
### Orçamento por brief (PRs grandes)
|
|
88
|
+
|
|
89
|
+
O motor coleta o diff **uma única vez** (`git diff` + `git diff --numstat`) e classifica
|
|
90
|
+
com **churn** (linhas adicionadas/removidas) por arquivo — o custo não cresce com o nº de
|
|
91
|
+
arquivos da PR. Cada brief recebe no máximo `budgets.maxFilesPerBrief` arquivos (default 40),
|
|
92
|
+
**priorizados pelo maior churn**:
|
|
93
|
+
|
|
94
|
+
- O excedente vai para a seção **Fora do orçamento (NÃO revisar)** do brief e o watchdog deve
|
|
95
|
+
registrá-lo em `skipped` — a tabela de **Cobertura** mostra o que ficou de fora (nunca some
|
|
96
|
+
silenciosamente).
|
|
97
|
+
- Isso mantém o contexto do subagente limitado mesmo num PR de 10k linhas com centenas de
|
|
98
|
+
arquivos num único domínio.
|
|
99
|
+
- Ajuste em `houndsman.config.ts`: `budgets: { maxFilesPerBrief: 60 }` e
|
|
100
|
+
`concurrency: { jev: 8 }`. Valores não-positivos caem no default (o `doctor` avisa).
|
|
101
|
+
|
|
92
102
|
### Pré-análise Jev (Passo 1.5, opcional)
|
|
93
103
|
|
|
94
104
|
Se `TYPESAFE_API_KEY` estiver definida, cada arquivo é avaliado pelo modelo **Jev** contra
|
|
@@ -96,14 +106,29 @@ as regras atômicas dos watchdogs. Respostas acima do limiar viram **candidatos*
|
|
|
96
106
|
`candidates.json` e entram no brief como *warm start* — o subagente **confirma ou refuta**.
|
|
97
107
|
|
|
98
108
|
- **Não é achado**: candidatos não bloqueiam.
|
|
99
|
-
- **
|
|
109
|
+
- **Opcional**: sem chave / erro / timeout → `available:false`; a revisão segue idêntica.
|
|
100
110
|
- Desativar: `houndsman --no-jev`.
|
|
101
111
|
|
|
112
|
+
### Review incremental (da 2ª revisão em diante)
|
|
113
|
+
|
|
114
|
+
Cada `--finalize` grava o **commit revisado** (`reviewed.headSha` no `state.json`). No prepare
|
|
115
|
+
seguinte, se o `HEAD` descende desse commit (sem rebase), o motor revisa **só o delta** — os
|
|
116
|
+
arquivos alterados desde a última revisão — e **carrega** os findings dos arquivos inalterados
|
|
117
|
+
(carry-over), sem re-revisá-los. O `manifest.json` traz o bloco `incremental` (`from`,
|
|
118
|
+
`changedFiles`, `carried`) e o `review.md` abre com um aviso.
|
|
119
|
+
|
|
120
|
+
- Sem mudanças desde a última revisão → **no-op** (nada a revisar; o estado é preservado).
|
|
121
|
+
- Rebase/force-push (histórico reescrito) → cai automaticamente no **review completo**.
|
|
122
|
+
- Forçar completo: `houndsman --full` (ou `--clean`, que também descarta a triagem anterior).
|
|
123
|
+
|
|
124
|
+
> Custo: o LLM só é gasto nos arquivos que mudaram desde a última revisão — não na PR inteira.
|
|
125
|
+
|
|
102
126
|
---
|
|
103
127
|
|
|
104
128
|
## Passo 2 — Revisar (skill despacha os subagentes)
|
|
105
129
|
|
|
106
|
-
Um subagente por brief
|
|
130
|
+
Um subagente por brief. Despache em **ondas** (ex.: até 8 subagentes por bloco de tool
|
|
131
|
+
calls) — evita estourar limites de taxa quando há muitos watchdogs. O prompt é o próprio brief:
|
|
107
132
|
|
|
108
133
|
```
|
|
109
134
|
Leia e execute o brief: .houndsman/.runs/<branch-slug>/briefs/<watchdog-id>.md
|
|
@@ -111,7 +136,8 @@ Você é o watchdog <watchdog-id> do {{projectName}}.
|
|
|
111
136
|
```
|
|
112
137
|
|
|
113
138
|
Cada subagente grava `findings/<watchdog-id>.json` (schema `.houndsman/core/skill/OUTPUT-FORMAT.md`).
|
|
114
|
-
Sem achados → `"findings": []` (arquivo obrigatório).
|
|
139
|
+
Sem achados → `"findings": []` (arquivo obrigatório). Arquivos na seção **Fora do orçamento**
|
|
140
|
+
não são lidos: registre-os em `skipped`.
|
|
115
141
|
|
|
116
142
|
**NUNCA enviar:** `git diff` completo · histórico de commits · arquivos de outros domínios ·
|
|
117
143
|
`AGENTS.md` completo (já está no contexto global).
|
|
@@ -130,6 +156,14 @@ Falha com mensagem clara se faltar algum `findings/<watchdog>.json`. Quando todo
|
|
|
130
156
|
3. Agrupa por severidade: ❌ blocking > ⚠️ attention > 💡 suggestion > 🔎 nit
|
|
131
157
|
4. Grava `.houndsman/.runs/<branch-slug>/review.md` + tabela de cobertura
|
|
132
158
|
5. Anexa os candidatos Jev não confirmados em `🔎 Candidatos não verificados` (não bloqueiam)
|
|
159
|
+
6. Agrupa os achados **por arquivo** dentro de cada severidade (navegabilidade em PRs grandes)
|
|
160
|
+
7. Grava um `review.<watchdog>.md` por watchdog com achados e indexa no `review.md`
|
|
161
|
+
(**Relatórios por domínio**) — mantém o relatório consolidado enxuto
|
|
162
|
+
8. Grava `.houndsman/.runs/<branch-slug>/state.json` — a **triagem**: um `id` curto e um
|
|
163
|
+
`fingerprint` de conteúdo por finding, preservados entre execuções
|
|
164
|
+
|
|
165
|
+
Após finalizar, corrija os achados com a capability **`fix`** (`fix.md`): a UI ou os
|
|
166
|
+
comandos `findings` levam do achado à correção.
|
|
133
167
|
|
|
134
168
|
---
|
|
135
169
|
|
|
@@ -150,10 +184,17 @@ Falha com mensagem clara se faltar algum `findings/<watchdog>.json`. Quando todo
|
|
|
150
184
|
- ...
|
|
151
185
|
|
|
152
186
|
## ❌ blocking
|
|
153
|
-
|
|
187
|
+
### `src/routes/order-route.ts`
|
|
188
|
+
- **<regra>** — `src/routes/order-route.ts:5` · _<watchdogs>_
|
|
154
189
|
<mensagem>
|
|
155
190
|
**Ação:** <ação>
|
|
156
191
|
|
|
192
|
+
## 🔎 Candidatos não verificados (Jev) ← se houver
|
|
193
|
+
|
|
194
|
+
## Relatórios por domínio
|
|
195
|
+
| Watchdog | Achados | Revisados | Relatório |
|
|
196
|
+
|---|---|---|---|
|
|
197
|
+
|
|
157
198
|
## Cobertura
|
|
158
199
|
| Watchdog | Arquivos revisados | Findings |
|
|
159
200
|
|---|---|---|
|
|
@@ -175,7 +216,11 @@ git diff --name-status (base...head)
|
|
|
175
216
|
↓
|
|
176
217
|
[2] N subagentes em paralelo ──► findings/<watchdog>.json
|
|
177
218
|
↓
|
|
178
|
-
[3] houndsman --finalize ──► review.md
|
|
219
|
+
[3] houndsman --finalize ──► review.md + state.json + run.json (review_done)
|
|
220
|
+
↓
|
|
221
|
+
[4] server (UI) ──► validar a revisão + marcar decision: execute
|
|
222
|
+
↓
|
|
223
|
+
[5] fix ──► correções + state.json/run.json (fix_done)
|
|
179
224
|
```
|
|
180
225
|
|
|
181
226
|
---
|
|
@@ -184,23 +229,23 @@ git diff --name-status (base...head)
|
|
|
184
229
|
|
|
185
230
|
```
|
|
186
231
|
/houndsman
|
|
187
|
-
/houndsman
|
|
232
|
+
/houndsman hunt
|
|
233
|
+
/houndsman hunt feature/add-webhook-retry
|
|
188
234
|
```
|
|
189
235
|
|
|
190
236
|
Se a branch não for informada, detecta com `git branch --show-current`. Base do diff: `main`.
|
|
191
237
|
|
|
192
|
-
**Comandos do CLI
|
|
238
|
+
**Comandos do CLI usados no `hunt`:**
|
|
193
239
|
|
|
194
240
|
| Comando | Função |
|
|
195
241
|
|---|---|
|
|
196
242
|
| `houndsman context` | Passo 0 — contexto da PR via `gh` |
|
|
197
|
-
| `houndsman` | Passo 1 — preparar (briefs + manifesto) |
|
|
243
|
+
| `houndsman` | Passo 1 — preparar (briefs + manifesto; incremental quando possível) |
|
|
198
244
|
| `houndsman --finalize` | Passo 3 — gerar o relatório |
|
|
199
245
|
| `houndsman watchdog <id>` | Contexto de um watchdog (`--json`, `--rules`) |
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
| `houndsman test` | Suíte de testes da lib |
|
|
246
|
+
|
|
247
|
+
Flags do review: `--base` · `--head` · `--branch` · `--dir` · `--clean` · `--full` (força
|
|
248
|
+
completo) · `--no-jev` · `--fail-on-blocking` (com `--finalize`).
|
|
204
249
|
|
|
205
250
|
---
|
|
206
251
|
|
|
@@ -208,6 +253,7 @@ Se a branch não for informada, detecta com `git branch --show-current`. Base do
|
|
|
208
253
|
|
|
209
254
|
- ❌ Enviar git diff completo para qualquer watchdog
|
|
210
255
|
- ❌ Ativar watchdogs sem arquivos no seu domínio
|
|
256
|
+
- ❌ Revisar arquivos marcados como **Fora do orçamento** (registre-os em `skipped`)
|
|
211
257
|
- ❌ Carregar documentação que o watchdog não precisa
|
|
212
258
|
- ❌ Revisar arquivos gerados (lock files, builds, migrations)
|
|
213
259
|
- ❌ Escrever markdown livre em vez do JSON de `OUTPUT-FORMAT.md`
|
|
@@ -221,11 +267,11 @@ Se a branch não for informada, detecta com `git branch --show-current`. Base do
|
|
|
221
267
|
|
|
222
268
|
## Manutenção das Regras
|
|
223
269
|
|
|
224
|
-
> Alterar qualquer regra (adicionar, ajustar severidade, remover, corrigir escopo) →
|
|
225
|
-
>
|
|
270
|
+
> Alterar qualquer regra (adicionar, ajustar severidade, remover, corrigir escopo) → capability
|
|
271
|
+
> **`train`** (`/houndsman train`, doc `train.md`).
|
|
226
272
|
> Regra de ouro: só é regra o que o projeto **aplica hoje** — prove com evidência no código
|
|
227
273
|
> (regra negativa com 0 ocorrências = seguida → **manter**).
|
|
228
|
-
> Após qualquer alteração, rodar `houndsman doctor`
|
|
274
|
+
> Após qualquer alteração, rodar `houndsman doctor` + `houndsman test` + `ci:fix` + `ci`.
|
|
229
275
|
|
|
230
276
|
---
|
|
231
277
|
|
|
@@ -237,3 +283,7 @@ Se a branch não for informada, detecta com `git branch --show-current`. Base do
|
|
|
237
283
|
| Médio (5k linhas) | 4-7 | ~1-2 min |
|
|
238
284
|
| Grande (50k linhas) | 7-10 | ~3-5 min |
|
|
239
285
|
| Enorme (300k linhas) | 10-15 | ~5-8 min |
|
|
286
|
+
|
|
287
|
+
> O custo de coleta é **constante** (2 execuções de `git`), independente do nº de arquivos.
|
|
288
|
+
> Em PRs muito grandes, o limitante é o nº de subagentes (ondas) e o orçamento por brief —
|
|
289
|
+
> não o diff. Ajuste `budgets.maxFilesPerBrief` para revisar mais/menos arquivos por domínio.
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
#
|
|
1
|
+
# houndsman — {{projectName}} · `train` (atualização de regras)
|
|
2
2
|
|
|
3
|
-
> **Documento canônico do skill
|
|
4
|
-
> (`.agents/skills/houndsman
|
|
3
|
+
> **Documento canônico da capability `train`.** O entry point do skill é o `SKILL.md`
|
|
4
|
+
> (`.agents/skills/houndsman/SKILL.md` e `.claude/skills/houndsman/SKILL.md`).
|
|
5
5
|
|
|
6
6
|
> **Propósito:** manter os watchdogs do skill `houndsman` alinhados ao que o
|
|
7
7
|
> projeto **realmente aplica** — seja para adicionar/ajustar uma regra a pedido do
|
|
8
8
|
> usuário, seja para uma auditoria geral após mudanças de padrão no código.
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
que o `houndsman` usa.
|
|
10
|
+
Invocação: `/houndsman train`. Esta capability é a **mantenedora** do `houndsman`.
|
|
11
|
+
Ela não revisa PRs (isso é `hunt`); ela atualiza as regras que o `houndsman` usa.
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
@@ -86,7 +86,7 @@ Toda regra (nova ou alterada) deve passar por **todos** os itens:
|
|
|
86
86
|
- O projeto mudou de padrão (ex.: passou a usar uma lib, mudou autenticação, etc.).
|
|
87
87
|
- **Auditoria completa** dos watchdogs após revisão geral do código.
|
|
88
88
|
- **Regra confusa/ambígua** (humano ou IA não entende) — ver Modo C.
|
|
89
|
-
- O usuário invoca `/houndsman
|
|
89
|
+
- O usuário invoca `/houndsman train`.
|
|
90
90
|
|
|
91
91
|
---
|
|
92
92
|
|
|
@@ -108,7 +108,7 @@ Toda regra (nova ou alterada) deve passar por **todos** os itens:
|
|
|
108
108
|
| `src/core/config-loader.ts` | Descoberta/carregamento de `houndsman.config.ts` |
|
|
109
109
|
| `src/core/brief.ts` | Render do brief: `defaultRenderBrief` + `PROCEDURE` |
|
|
110
110
|
| `src/core/registry-check.ts` | Validação anti-drift (config-driven) |
|
|
111
|
-
| `src/skill/
|
|
111
|
+
| `src/skill/hunt.md` | Orquestração da revisão (capability `hunt`) |
|
|
112
112
|
| `src/tests/**` | Suíte da lib (project-agnóstica; usa `fixtures/fake-project.ts`) |
|
|
113
113
|
| `src/cli/index.ts` | **CLI único** — `houndsman [context, setup, doctor, test, watchdog, --finalize]` |
|
|
114
114
|
|
|
@@ -169,7 +169,7 @@ verificáveis por leitura local. Candidatos não confirmados pelo watchdog **nã
|
|
|
169
169
|
- Ajustar `scope` / `description` / `reviewFocus` / `exclude` / `contextFiles` se necessário.
|
|
170
170
|
- Se a regra muda para outro domínio (paths), ajustar o `classify` do watchdog.
|
|
171
171
|
5. **Watchdog novo?** criar `.houndsman/watchdogs/<id>.ts` e registrar em `.houndsman/watchdogs/index.ts` (o id é derivado das chaves).
|
|
172
|
-
6. **Atualizar `src/skill/
|
|
172
|
+
6. **Atualizar `src/skill/hunt.md`/`README.md`** se escopo/regra visível mudou (no motor).
|
|
173
173
|
7. **Atualizar a suíte da lib** se o comportamento do MOTOR mudou (a suíte é project-agnóstica).
|
|
174
174
|
8. **Verificar** (seção abaixo).
|
|
175
175
|
|
|
@@ -225,19 +225,19 @@ todos os itens — em especial: **geral/reutilizável** (não regra de negócio
|
|
|
225
225
|
## Verificação (obrigatória)
|
|
226
226
|
|
|
227
227
|
```bash
|
|
228
|
-
bun run houndsman doctor # config sem drift + ambiente
|
|
228
|
+
bun run houndsman doctor # config sem drift + ambiente + credencial Jev
|
|
229
229
|
bun run houndsman test # suíte da lib (project-agnóstica)
|
|
230
230
|
bun run ci:fix # formatação/imports/lint (no repo da lib)
|
|
231
|
-
bun run ci
|
|
231
|
+
bun run ci # tipagem (no repo da lib)
|
|
232
232
|
```
|
|
233
233
|
|
|
234
234
|
Checklist final:
|
|
235
235
|
|
|
236
236
|
- [ ] `bun run houndsman doctor` → sem problemas reportados.
|
|
237
237
|
- [ ] `bun run houndsman test` → **0 fail**.
|
|
238
|
-
- [ ] `ci:fix` + `ci
|
|
238
|
+
- [ ] `ci:fix` + `ci` → exit 0 (warnings pré-existentes não contam).
|
|
239
239
|
- [ ] `WATCHDOG_DEFINITIONS[<id>].id` bate com a chave e `description` não vazio.
|
|
240
|
-
- [ ] `src/skill/
|
|
240
|
+
- [ ] `src/skill/hunt.md` continua consistente com os watchdogs do projeto.
|
|
241
241
|
- [ ] Toda regra nova/alterada tem **evidência** registrada no PR/relatório
|
|
242
242
|
(`file:line` se afirmativa; `0 ocorrências do anti-padrão` se negativa).
|
|
243
243
|
- [ ] Nenhuma regra **negativa** foi removida por "0 ocorrências" (Regra de Ouro).
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# houndsman — {{projectName}} · `verify` (violações resolvidas?)
|
|
2
|
+
|
|
3
|
+
> **Documento canônico da capability `verify`.** O entry point do skill é o `SKILL.md`
|
|
4
|
+
> (`.agents/skills/houndsman/SKILL.md` e `.claude/skills/houndsman/SKILL.md`).
|
|
5
|
+
|
|
6
|
+
Confere se os findings de uma revisão **já finalizada** foram resolvidos — **sem re-revisar a
|
|
7
|
+
PR**. Invocação: `/houndsman verify`. Consome o `state.json` do `hunt`; não revisa nem altera
|
|
8
|
+
regras.
|
|
9
|
+
|
|
10
|
+
**Quando usar:**
|
|
11
|
+
|
|
12
|
+
- Depois de corrigir achados (`fix`), para confirmar que as violações sumiram.
|
|
13
|
+
- As violações foram resolvidas? · confere se ainda está lá · valida o fix.
|
|
14
|
+
|
|
15
|
+
> **Pré-requisito:** existe `.houndsman/.runs/<branch-slug>/state.json` (gerado no `--finalize`).
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Como funciona (2 tiers)
|
|
20
|
+
|
|
21
|
+
1. **Tier local (grátis, determinístico).** Para cada finding presente, reancora a âncora de
|
|
22
|
+
conteúdo contra o working tree (`core/finding-anchor.ts`):
|
|
23
|
+
- **âncora presente** (`ok`/`moved`) → **persiste** (a violação ainda está lá);
|
|
24
|
+
- **âncora sumida** (`stale`) → provável **resolvido** — mas o trecho pode ter sido reescrito;
|
|
25
|
+
- **arquivo ausente** → fora da verificação (deletado/movido).
|
|
26
|
+
|
|
27
|
+
2. **Tier Jev (opcional, só nos ambíguos).** Com `TYPESAFE_API_KEY`, os casos `stale` / sem
|
|
28
|
+
âncora são confirmados pelo LLM sobre um **diff focado** do arquivo (`foundAtSha..HEAD`), uma
|
|
29
|
+
pergunta `noul` por finding. Falha-aberto: sem chave/erro → vale o resultado local.
|
|
30
|
+
|
|
31
|
+
**Custo:** ~0 LLM quando o tier local decide; 1 chamada por arquivo ambíguo — nunca uma revisão
|
|
32
|
+
completa.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Procedimento
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
bun run houndsman findings verify # relatório (não altera o estado)
|
|
40
|
+
bun run houndsman findings verify --json # saída estruturada
|
|
41
|
+
bun run houndsman findings verify --apply # marca os resolvidos como done (ping no run.json)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
- Sem `--apply`: **só relatório** (grava `verify.md` na pasta da run). Nada muda no `state.json`.
|
|
45
|
+
- Com `--apply`: os findings com status **`resolved`** viram `execState: done` (histórico
|
|
46
|
+
`by: "verify"`). `persisting` e `uncertain` **não** são tocados.
|
|
47
|
+
|
|
48
|
+
Filtros (como no `findings list`): `--severity`, `--watchdog`, `--file`, `--decision`. `--all`
|
|
49
|
+
inclui ausentes. `--no-jev` desliga o tier LLM. `--fail-on-persisting` sai com código 1 se algum
|
|
50
|
+
`blocking` persistir (útil em CI).
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Status possíveis
|
|
55
|
+
|
|
56
|
+
| Status | Significado | `--apply`? |
|
|
57
|
+
|---|---|---|
|
|
58
|
+
| `resolved` | Violação não encontrada (âncora sumida; confirmada pelo Jev quando há chave). | ✅ vira `done` |
|
|
59
|
+
| `persisting` | Âncora ainda presente — a violação continua. | ❌ |
|
|
60
|
+
| `uncertain` | Sem âncora e sem confirmação do Jev (ou Jev indisponível). | ❌ |
|
|
61
|
+
| `file-missing` | Arquivo não está no working tree (deletado/movido). | ❌ |
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Anti-padrões
|
|
66
|
+
|
|
67
|
+
- ❌ Reexecutar o `hunt` inteiro só para conferir se um fix funcionou — use o `verify`.
|
|
68
|
+
- ❌ Esperar que o `verify` marque `done` sem `--apply` (sem a flag, nada muda no estado).
|
|
69
|
+
- ❌ Tratar `persisting` como resolvido — a âncora ainda está no arquivo.
|
|
70
|
+
- ❌ Esperar verificação 100% pelo LLM — o tier local resolve a maioria de graça.
|