@payconductor/houndsman 0.1.1 → 0.1.4
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 +32 -14
- package/package.json +1 -1
- package/src/cli/index.ts +22 -11
- package/src/core/assets.ts +3 -0
- package/src/core/brief.ts +2 -3
- package/src/core/commands/findings.ts +232 -4
- package/src/core/commands/review.ts +2 -0
- package/src/core/commands/scaffold.ts +13 -44
- package/src/core/diff-source.ts +4 -4
- package/src/core/findings-state.ts +20 -2
- 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-detector.ts +2 -2
- package/src/core/jev/jev-verify.ts +178 -0
- package/src/core/orchestrator.ts +202 -15
- package/src/core/paths.ts +6 -0
- package/src/core/registry-check.ts +53 -0
- package/src/core/report-builder.ts +5 -0
- package/src/core/run-status.ts +123 -0
- package/src/core/verify.ts +175 -0
- package/src/core/watchdog-registry.ts +1 -2
- package/src/index.ts +1 -1
- package/src/server/artifacts.ts +1 -0
- package/src/server/client/RunList.tsx +22 -13
- package/src/server/client/constants.ts +32 -1
- package/src/server/client/types.ts +4 -0
- package/src/server/index.ts +12 -1
- package/src/skill/AUDIT-PROTOCOL.md +7 -2
- package/src/skill/README.md +32 -6
- package/src/skill/SETUP.md +11 -2
- package/src/skill/SKILL.md +48 -0
- package/src/skill/fix.md +206 -0
- package/src/skill/{houndsman.md → hunt.md} +42 -68
- package/src/skill/{houndsman-update.md → train.md} +38 -17
- package/src/skill/verify.md +70 -0
- package/src/tests/findings-commands.test.ts +252 -2
- package/src/tests/findings-state.test.ts +52 -1
- package/src/tests/fix-batch.test.ts +257 -0
- package/src/tests/review-scripts.test.ts +36 -0
- package/src/tests/run-status.test.ts +147 -0
- package/src/tests/scaffold.test.ts +59 -0
- package/src/tests/server.test.ts +30 -0
- package/src/tests/verify.test.ts +170 -0
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)
|
|
@@ -114,6 +109,20 @@ as regras atômicas dos watchdogs. Respostas acima do limiar viram **candidatos*
|
|
|
114
109
|
- **Opcional**: sem chave / erro / timeout → `available:false`; a revisão segue idêntica.
|
|
115
110
|
- Desativar: `houndsman --no-jev`.
|
|
116
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
|
+
|
|
117
126
|
---
|
|
118
127
|
|
|
119
128
|
## Passo 2 — Revisar (skill despacha os subagentes)
|
|
@@ -151,46 +160,10 @@ Falha com mensagem clara se faltar algum `findings/<watchdog>.json`. Quando todo
|
|
|
151
160
|
7. Grava um `review.<watchdog>.md` por watchdog com achados e indexa no `review.md`
|
|
152
161
|
(**Relatórios por domínio**) — mantém o relatório consolidado enxuto
|
|
153
162
|
8. Grava `.houndsman/.runs/<branch-slug>/state.json` — a **triagem**: um `id` curto e um
|
|
154
|
-
`fingerprint` de conteúdo por finding
|
|
163
|
+
`fingerprint` de conteúdo por finding, preservados entre execuções
|
|
155
164
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
---
|
|
159
|
-
|
|
160
|
-
## Passo 4 — Triagem (opcional)
|
|
161
|
-
|
|
162
|
-
Cada finding recebe um `id` curto e um `fingerprint` de **conteúdo** no `--finalize`,
|
|
163
|
-
gravados em `.houndsman/.runs/<branch-slug>/state.json`. A triagem é feita pela UI ou
|
|
164
|
-
pelo agente — sem editar o JSON à mão. Duas dimensões independentes:
|
|
165
|
-
|
|
166
|
-
- **decision:** `pending` · `execute` · `ignore` (+ `comment` opcional).
|
|
167
|
-
- **execState:** `pending` · `in_progress` · `done` · `stale`.
|
|
168
|
-
|
|
169
|
-
### UI local
|
|
170
|
-
|
|
171
|
-
```bash
|
|
172
|
-
houndsman server --open
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
Abre a UI (Bun.serve + Preact): lista as runs, triar os findings por severidade, comentar,
|
|
176
|
-
marcar como feito e ler os artefatos (`manifest.json`, `classification.json`, `review.md`).
|
|
177
|
-
Bind em `127.0.0.1` (ferramenta local, sem auth).
|
|
178
|
-
|
|
179
|
-
### Auto-fix pelo agente
|
|
180
|
-
|
|
181
|
-
```bash
|
|
182
|
-
houndsman findings list --decision execute --json # pendentes marcados p/ corrigir
|
|
183
|
-
# ... o agente aplica as correções ...
|
|
184
|
-
houndsman findings sync # reancora por conteúdo
|
|
185
|
-
houndsman findings done <id> # confirma os concluídos
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
> **A linha não é a identidade.** O auto-fix desloca linhas; o motor reancora cada finding
|
|
189
|
-
> pelo **conteúdo** (trecho + contexto) e não perde itens que se movem. Se a âncora some
|
|
190
|
-
> (o trecho foi corrigido), o finding vira `done` automaticamente quando a decisão era
|
|
191
|
-
> `execute`, ou `stale` caso contrário.
|
|
192
|
-
> Ocorrências byte-idênticas (mesmo trecho E mesmo contexto) compartilham o id — são
|
|
193
|
-
> tratadas como um grupo (`×N`); limitação conhecida.
|
|
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.
|
|
194
167
|
|
|
195
168
|
---
|
|
196
169
|
|
|
@@ -243,9 +216,11 @@ git diff --name-status (base...head)
|
|
|
243
216
|
↓
|
|
244
217
|
[2] N subagentes em paralelo ──► findings/<watchdog>.json
|
|
245
218
|
↓
|
|
246
|
-
[3] houndsman --finalize ──► review.md + state.json
|
|
219
|
+
[3] houndsman --finalize ──► review.md + state.json + run.json (review_done)
|
|
247
220
|
↓
|
|
248
|
-
[4]
|
|
221
|
+
[4] server (UI) ──► validar a revisão + marcar decision: execute
|
|
222
|
+
↓
|
|
223
|
+
[5] fix ──► correções + state.json/run.json (fix_done)
|
|
249
224
|
```
|
|
250
225
|
|
|
251
226
|
---
|
|
@@ -254,25 +229,23 @@ git diff --name-status (base...head)
|
|
|
254
229
|
|
|
255
230
|
```
|
|
256
231
|
/houndsman
|
|
257
|
-
/houndsman
|
|
232
|
+
/houndsman hunt
|
|
233
|
+
/houndsman hunt feature/add-webhook-retry
|
|
258
234
|
```
|
|
259
235
|
|
|
260
236
|
Se a branch não for informada, detecta com `git branch --show-current`. Base do diff: `main`.
|
|
261
237
|
|
|
262
|
-
**Comandos do CLI
|
|
238
|
+
**Comandos do CLI usados no `hunt`:**
|
|
263
239
|
|
|
264
240
|
| Comando | Função |
|
|
265
241
|
|---|---|
|
|
266
242
|
| `houndsman context` | Passo 0 — contexto da PR via `gh` |
|
|
267
|
-
| `houndsman` | Passo 1 — preparar (briefs + manifesto) |
|
|
243
|
+
| `houndsman` | Passo 1 — preparar (briefs + manifesto; incremental quando possível) |
|
|
268
244
|
| `houndsman --finalize` | Passo 3 — gerar o relatório |
|
|
269
245
|
| `houndsman watchdog <id>` | Contexto de um watchdog (`--json`, `--rules`) |
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
| `houndsman update` | Sincroniza os arquivos auto-gerados (`.houndsman/core`) |
|
|
274
|
-
| `houndsman doctor` | Valida a configuração, o ambiente e a credencial Jev |
|
|
275
|
-
| `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`).
|
|
276
249
|
|
|
277
250
|
---
|
|
278
251
|
|
|
@@ -294,11 +267,12 @@ Se a branch não for informada, detecta com `git branch --show-current`. Base do
|
|
|
294
267
|
|
|
295
268
|
## Manutenção das Regras
|
|
296
269
|
|
|
297
|
-
> Alterar qualquer regra (adicionar, ajustar severidade, remover, corrigir escopo) →
|
|
298
|
-
>
|
|
270
|
+
> Alterar qualquer regra (adicionar, ajustar severidade, remover, corrigir escopo) → capability
|
|
271
|
+
> **`train`** (`/houndsman train`, doc `train.md`).
|
|
299
272
|
> Regra de ouro: só é regra o que o projeto **aplica hoje** — prove com evidência no código
|
|
300
273
|
> (regra negativa com 0 ocorrências = seguida → **manter**).
|
|
301
|
-
> Após qualquer alteração, rodar `houndsman doctor
|
|
274
|
+
> Após qualquer alteração, rodar `houndsman doctor`. (`houndsman test` e `ci:fix`/`ci` são
|
|
275
|
+
> comandos da **lib**, não do projeto consumidor.)
|
|
302
276
|
|
|
303
277
|
---
|
|
304
278
|
|
|
@@ -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
|
|
|
@@ -72,10 +72,29 @@ Toda regra (nova ou alterada) deve passar por **todos** os itens:
|
|
|
72
72
|
direta da afirmação). Aí o prefixo lidera o sentido dominante e o outro entra como oração
|
|
73
73
|
subordinada — nunca como segundo juízo coordenado.
|
|
74
74
|
9. **Escopo coerente** — a regra pertence ao domínio do watchdog.
|
|
75
|
-
10. **Sem duplicata** — nenhuma regra repetida
|
|
75
|
+
10. **Sem duplicata** — nenhuma regra repetida (texto normalizado) no mesmo watchdog.
|
|
76
|
+
11. **Lugar único** — a regra vive **apenas** em `rules`. Nunca repita o texto (nem o anti-padrão)
|
|
77
|
+
em `reviewFocus`, `contextFiles`, `scope`, `description` ou `exclude`.
|
|
76
78
|
|
|
77
79
|
> O `houndsman doctor` emite um **aviso** (não bloqueante) para regra sem polaridade explícita
|
|
78
|
-
> (`Promover:`, `Evitar:`, `Não` ou `Nunca`)
|
|
80
|
+
> (`Promover:`, `Evitar:`, `Não` ou `Nunca`), para regra duplicada e para texto de regra que
|
|
81
|
+
> vazou para `reviewFocus`/`contextFiles`/`exclude`.
|
|
82
|
+
|
|
83
|
+
### Onde cada coisa vive (não duplique a regra)
|
|
84
|
+
|
|
85
|
+
Cada informação tem o seu campo — não espelhe a regra em vários lugares:
|
|
86
|
+
|
|
87
|
+
| O que você quer expressar | Campo | Observação |
|
|
88
|
+
|---|---|---|
|
|
89
|
+
| A **regra** (o que DEVE/NÃO DEVE acontecer) | `rules[]` | Único lugar da regra: `{ severity, text, jev? }`. |
|
|
90
|
+
| **Quais arquivos** o watchdog cobre | `classify` | Regex de path (ou de conteúdo). |
|
|
91
|
+
| **Que arquivos** olhar primeiro | `reviewFocus` | **Paths/áreas** do código — não texto de regra. |
|
|
92
|
+
| **Que docs** consultar | `contextFiles` | Caminhos de **documentação** — não regra nem código. |
|
|
93
|
+
| O que **nunca** carregar | `exclude` | Paths a ignorar. |
|
|
94
|
+
| O **território** em prosa | `scope` / `description` | Contexto do domínio, não regra. |
|
|
95
|
+
|
|
96
|
+
> A regra aparece **uma única vez** no arquivo — em `rules`. Repeti-la em
|
|
97
|
+
> `reviewFocus`/`contextFiles`/`scope`/`description`/`exclude` só cria ruído no brief do subagente.
|
|
79
98
|
|
|
80
99
|
---
|
|
81
100
|
|
|
@@ -86,7 +105,7 @@ Toda regra (nova ou alterada) deve passar por **todos** os itens:
|
|
|
86
105
|
- O projeto mudou de padrão (ex.: passou a usar uma lib, mudou autenticação, etc.).
|
|
87
106
|
- **Auditoria completa** dos watchdogs após revisão geral do código.
|
|
88
107
|
- **Regra confusa/ambígua** (humano ou IA não entende) — ver Modo C.
|
|
89
|
-
- O usuário invoca `/houndsman
|
|
108
|
+
- O usuário invoca `/houndsman train`.
|
|
90
109
|
|
|
91
110
|
---
|
|
92
111
|
|
|
@@ -108,7 +127,7 @@ Toda regra (nova ou alterada) deve passar por **todos** os itens:
|
|
|
108
127
|
| `src/core/config-loader.ts` | Descoberta/carregamento de `houndsman.config.ts` |
|
|
109
128
|
| `src/core/brief.ts` | Render do brief: `defaultRenderBrief` + `PROCEDURE` |
|
|
110
129
|
| `src/core/registry-check.ts` | Validação anti-drift (config-driven) |
|
|
111
|
-
| `src/skill/
|
|
130
|
+
| `src/skill/hunt.md` | Orquestração da revisão (capability `hunt`) |
|
|
112
131
|
| `src/tests/**` | Suíte da lib (project-agnóstica; usa `fixtures/fake-project.ts`) |
|
|
113
132
|
| `src/cli/index.ts` | **CLI único** — `houndsman [context, setup, doctor, test, watchdog, --finalize]` |
|
|
114
133
|
|
|
@@ -166,10 +185,12 @@ verificáveis por leitura local. Candidatos não confirmados pelo watchdog **nã
|
|
|
166
185
|
`Evitar:`/`Não`/`Nunca` (NÃO DEVE), conforme as Convenções de escrita.
|
|
167
186
|
- Regra que mistura afirmação e negação (dois sentidos) → dividir em **duas entradas** (*Unipolar*, item 8).
|
|
168
187
|
- `jev` (opcional): `{ kind: "noul" }`, com `instructions` e/ou `criteria` — ver seção acima.
|
|
169
|
-
-
|
|
188
|
+
- **A regra vai só em `rules`** — não a repita em `reviewFocus`/`contextFiles`/`scope`/
|
|
189
|
+
`description`/`exclude`. Só toque nesses campos se o **domínio/paths** mudou (ver
|
|
190
|
+
*Onde cada coisa vive*), nunca para reafirmar a regra.
|
|
170
191
|
- Se a regra muda para outro domínio (paths), ajustar o `classify` do watchdog.
|
|
171
192
|
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/
|
|
193
|
+
6. **Atualizar `src/skill/hunt.md`/`README.md`** se escopo/regra visível mudou (no motor).
|
|
173
194
|
7. **Atualizar a suíte da lib** se o comportamento do MOTOR mudou (a suíte é project-agnóstica).
|
|
174
195
|
8. **Verificar** (seção abaixo).
|
|
175
196
|
|
|
@@ -226,24 +247,24 @@ todos os itens — em especial: **geral/reutilizável** (não regra de negócio
|
|
|
226
247
|
|
|
227
248
|
```bash
|
|
228
249
|
bun run houndsman doctor # config sem drift + ambiente + credencial Jev
|
|
229
|
-
bun run houndsman test # suíte da lib (project-agnóstica)
|
|
230
|
-
bun run ci:fix # formatação/imports/lint (no repo da lib)
|
|
231
|
-
bun run ci:check # tipagem (no repo da lib)
|
|
232
250
|
```
|
|
233
251
|
|
|
252
|
+
> `bun run houndsman test`, `bun run ci:fix` e `bun run ci` são comandos para **manter a lib** do
|
|
253
|
+
> houndsman (repo do pacote) — não para quem só usa o houndsman no projeto.
|
|
254
|
+
|
|
234
255
|
Checklist final:
|
|
235
256
|
|
|
236
257
|
- [ ] `bun run houndsman doctor` → sem problemas reportados.
|
|
237
|
-
- [ ] `bun run houndsman test` → **0 fail**.
|
|
238
|
-
- [ ] `ci:fix` + `ci:check` → exit 0 (warnings pré-existentes não contam).
|
|
239
258
|
- [ ] `WATCHDOG_DEFINITIONS[<id>].id` bate com a chave e `description` não vazio.
|
|
240
|
-
- [ ] `src/skill/
|
|
259
|
+
- [ ] `src/skill/hunt.md` continua consistente com os watchdogs do projeto.
|
|
241
260
|
- [ ] Toda regra nova/alterada tem **evidência** registrada no PR/relatório
|
|
242
261
|
(`file:line` se afirmativa; `0 ocorrências do anti-padrão` se negativa).
|
|
243
262
|
- [ ] Nenhuma regra **negativa** foi removida por "0 ocorrências" (Regra de Ouro).
|
|
244
263
|
- [ ] Brief de amostra não contém regra removida (dry-run abaixo).
|
|
245
264
|
- [ ] Toda regra passa nas convenções de escrita (geral/reutilizável, sem jargão abreviado,
|
|
246
265
|
sem qualificador vago, com polaridade explícita e **unipolar**) — conferir via grep.
|
|
266
|
+
- [ ] O texto de cada regra aparece **exatamente uma vez** no arquivo (só em `rules`) — nada em
|
|
267
|
+
`reviewFocus`/`contextFiles`/`scope`/`description`/`exclude`.
|
|
247
268
|
|
|
248
269
|
```bash
|
|
249
270
|
# Dry-run: gerar briefs e conferir ausência de regras removidas
|
|
@@ -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.
|