@payconductor/houndsman 0.3.0 → 0.5.0
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 +25 -39
- package/package.json +1 -1
- package/src/cli/commands/context-command.ts +11 -9
- package/src/cli/commands/doctor-command.ts +5 -0
- package/src/cli/commands/findings-command.ts +13 -3
- package/src/cli/commands/review-command.ts +1 -2
- package/src/cli/commands/status-command.ts +46 -0
- package/src/cli/help.ts +8 -3
- package/src/cli/index.ts +5 -2
- package/src/core/commands/context.ts +29 -13
- package/src/core/commands/findings.ts +216 -125
- package/src/core/commands/review.ts +7 -8
- package/src/core/commands/scaffold.ts +15 -16
- package/src/core/commands/status.ts +63 -0
- package/src/core/config.ts +16 -7
- package/src/core/engine/houndsman-engine.ts +15 -1
- package/src/core/engine/review-scope.ts +26 -8
- package/src/core/engine/review-session.ts +37 -9
- package/src/core/findings-state.ts +53 -75
- package/src/core/github-review.ts +620 -57
- package/src/core/jev/jev-candidates.ts +49 -35
- package/src/core/orchestrator.ts +271 -134
- package/src/core/paths.ts +26 -17
- package/src/core/pr-context.ts +19 -5
- package/src/core/project-config.ts +4 -5
- package/src/core/renderers/manifest-writer.ts +29 -18
- package/src/core/renderers/resume-renderer.ts +151 -0
- package/src/core/report-builder.ts +7 -4
- package/src/core/run-layout.ts +4 -104
- package/src/core/run-status.ts +59 -50
- package/src/core/services/git-repository.ts +16 -0
- package/src/core/services/project-files.ts +13 -1
- package/src/core/storage/factory.ts +24 -0
- package/src/core/storage/file/file-storage.ts +271 -0
- package/src/core/storage/paths.ts +64 -0
- package/src/core/storage/repo-identity.ts +70 -0
- package/src/core/storage/sqlite/mappers.ts +162 -0
- package/src/core/storage/sqlite/schema.ts +116 -0
- package/src/core/storage/sqlite/sqlite-storage.ts +431 -0
- package/src/core/storage/types.ts +152 -0
- package/src/core/storage/work-area.ts +191 -0
- package/src/index.ts +27 -6
- package/src/server/artifacts.ts +8 -61
- package/src/server/client/App.tsx +26 -9
- package/src/server/client/ArtifactsPanel.tsx +144 -23
- package/src/server/client/AutoRefresh.tsx +1 -1
- package/src/server/client/Filters.tsx +7 -2
- package/src/server/client/FindingCard.tsx +50 -15
- package/src/server/client/FindingsList.tsx +2 -2
- package/src/server/client/MarkdownText.tsx +181 -0
- package/src/server/client/ResumePanel.tsx +368 -0
- package/src/server/client/RunList.tsx +3 -3
- package/src/server/client/SubmitModal.tsx +58 -10
- package/src/server/client/SummaryBar.tsx +1 -1
- package/src/server/client/icons.tsx +17 -0
- package/src/server/client/utils/code-highlight.ts +422 -0
- package/src/server/client/utils/constants.ts +226 -0
- package/src/server/client/utils/json-highlight.ts +55 -0
- package/src/server/client/utils/markdown.ts +319 -0
- package/src/server/client/{types.ts → utils/types.ts} +81 -0
- package/src/server/index.ts +154 -16
- package/src/server/run-repository.ts +153 -136
- package/src/skill/OUTPUT-FORMAT.md +6 -4
- package/src/skill/README.md +22 -14
- package/src/skill/SETUP.md +4 -4
- package/src/skill/example-review.md +22 -14
- package/src/skill/fix.md +5 -5
- package/src/skill/hunt.md +55 -32
- package/src/skill/train.md +1 -1
- package/src/skill/verify.md +7 -6
- package/src/tests/__snapshots__/baseline.test.ts.snap +74 -61
- package/src/tests/baseline.test.ts +79 -34
- package/src/tests/cli.test.ts +40 -19
- package/src/tests/code-highlight.test.ts +123 -0
- package/src/tests/domain.test.ts +1 -1
- package/src/tests/findings-commands.test.ts +153 -131
- package/src/tests/findings-state.test.ts +56 -5
- package/src/tests/fixtures/fake-project.ts +0 -1
- package/src/tests/github-review.test.ts +409 -60
- package/src/tests/infrastructure.test.ts +33 -38
- package/src/tests/markdown.test.ts +149 -0
- package/src/tests/review-resume.test.ts +101 -0
- package/src/tests/review-scope.test.ts +302 -0
- package/src/tests/review-scripts.test.ts +81 -5
- package/src/tests/run-status-view.test.ts +94 -0
- package/src/tests/run-status.test.ts +86 -23
- package/src/tests/server.test.ts +184 -96
- package/src/tests/storage.test.ts +449 -0
- package/src/server/client/constants.ts +0 -91
- /package/src/server/client/{api.ts → utils/api.ts} +0 -0
- /package/src/server/client/{format.ts → utils/format.ts} +0 -0
package/README.md
CHANGED
|
@@ -26,8 +26,8 @@ diferente das PRs. O motor só coordena a caçada — as regras são problema se
|
|
|
26
26
|
|
|
27
27
|
- **Bun** — runtime obrigatório.
|
|
28
28
|
- **git** — o diff usa `git diff <base>...<head>`.
|
|
29
|
-
-
|
|
30
|
-
|
|
29
|
+
- **gh** (Opcional) — Obtém contexto da PR e dispara comentários para o GitHub
|
|
30
|
+
- **`TYPESAFE_API_KEY`** (Opcional) — Env a ser informada na raiz, usada em pré-analise com JEV
|
|
31
31
|
|
|
32
32
|
### 2. Instale o CLI (global)
|
|
33
33
|
|
|
@@ -74,8 +74,9 @@ No seu harness (Claude Code / agents), invoque o skill:
|
|
|
74
74
|
/houndsman hunt
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
-
O skill orquestra tudo e
|
|
78
|
-
|
|
77
|
+
O skill orquestra tudo e persiste o relatório no storage global (SQLite em
|
|
78
|
+
`<HOUNDSMAN_HOME>/houndsman.db`); a UI lê os artefatos direto do storage. Não precisa rodar
|
|
79
|
+
nenhum script à mão.
|
|
79
80
|
|
|
80
81
|
---
|
|
81
82
|
|
|
@@ -86,62 +87,49 @@ Não precisa rodar nenhum script à mão.
|
|
|
86
87
|
├─ Passo 0 contexto da PR (gh, opcional)
|
|
87
88
|
├─ Passo 1 classifica o diff → briefs por watchdog (incremental quando possível)
|
|
88
89
|
├─ Passo 2 N subagentes revisam em paralelo
|
|
89
|
-
├─ Passo 3 consolida em review.md +
|
|
90
|
+
├─ Passo 3 consolida em review.md + triagem no storage
|
|
90
91
|
├─ Passo 4 valida na UI (server) e marca os achados a executar
|
|
91
|
-
├─ Passo 5 fix corrige o grupo atual →
|
|
92
|
+
├─ Passo 5 fix corrige o grupo atual → status fix_done
|
|
92
93
|
└─ Passo 6 verify confere o que resolveu, sem re-revisar
|
|
93
94
|
```
|
|
94
95
|
|
|
95
96
|
O skill tem **4 capabilities**, todas em `/houndsman`:
|
|
96
97
|
|
|
97
|
-
- **`hunt`** — revisa a PR
|
|
98
|
+
- **`hunt`** — revisa a PR.
|
|
98
99
|
- **`train`** — mantém/atualiza as regras dos watchdogs.
|
|
99
|
-
- **`fix`** — corrige os findings marcados
|
|
100
|
-
- **`verify`** — confere se as violações foram resolvidas
|
|
100
|
+
- **`fix`** — corrige os findings marcados.
|
|
101
|
+
- **`verify`** — confere se as violações foram resolvidas, sem re-revisar.
|
|
101
102
|
|
|
102
|
-
- Revisão normal: `/houndsman` ou `/houndsman hunt` (a branch é detectada; base default `main`).
|
|
103
103
|
- Revisar outra branch: `/houndsman hunt feature/minha-branch`.
|
|
104
|
-
- Validar
|
|
105
|
-
- Manual (sem skill): `houndsman context` → `houndsman --base main` → *(subagentes)* →
|
|
106
|
-
`houndsman --finalize`.
|
|
107
|
-
- CI: `houndsman --finalize --fail-on-blocking` (exit 1 se houver bloqueantes).
|
|
104
|
+
- Validar na UI: `houndsman server --open` — marque os findings a executar (`execute`).
|
|
108
105
|
|
|
109
106
|
---
|
|
110
107
|
|
|
111
|
-
##
|
|
108
|
+
## Validando os findings (opcional)
|
|
112
109
|
|
|
113
|
-
|
|
114
|
-
no `.houndsman/.runs/<branch-slug>/state.json`. Você decide o que fazer com cada um — pela
|
|
115
|
-
**UI local** ou pelo **agente** (auto-fix) — sem abrir o JSON à mão:
|
|
110
|
+
Você decide o que fazer com cada finding pela **UI local**, informando se quer `Executar` ou `Ignorar`
|
|
116
111
|
|
|
117
112
|
```bash
|
|
118
113
|
bun run houndsman server --open # UI: triar, comentar, marcar feito, ler artefatos
|
|
119
114
|
```
|
|
120
115
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
**Auto-fix pelo agente** — as linhas mudam depois do fix, e o motor reancora por conteúdo:
|
|
125
|
-
|
|
126
|
-
```bash
|
|
127
|
-
bun run houndsman findings batch --json # grupo atual (agrupamento automático) + outros
|
|
128
|
-
# ... o agente corrige apenas esse grupo ...
|
|
129
|
-
bun run houndsman findings sync # reancora por conteúdo
|
|
130
|
-
bun run houndsman findings done <id>
|
|
131
|
-
bun run houndsman findings verify # confere o que resolveu (barato, sem re-revisar)
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
> A partir da 2ª revisão o `hunt` é **incremental**: revisa só os arquivos que mudaram desde
|
|
135
|
-
> o último `--finalize` e **carrega** os findings dos arquivos inalterados. `--full` força
|
|
136
|
-
> o review completo.
|
|
137
|
-
|
|
138
|
-
> A identidade do finding é o **conteúdo** (fingerprint), não a linha: itens deslocados
|
|
139
|
-
> pelo fix não se perdem. O estado é local e mora em `.runs/<slug>/state.json` (gitignored).
|
|
116
|
+
> A partir da 2ª revisão o `hunt` é **incremental**: revisa apenas os arquivos que mudaram desde
|
|
117
|
+
> a última revisão. `--full` força o review completo.
|
|
140
118
|
|
|
141
119
|
---
|
|
142
120
|
|
|
143
121
|
## Mantendo a configuração
|
|
144
122
|
|
|
123
|
+
- **Persistência** → por default, SQLite global em `<HOUNDSMAN_HOME>/houndsman.db`
|
|
124
|
+
(`HOUNDSMAN_HOME` sobrescreve o diretório de dados). Caso queira storage base em arquivos, na config, troque provider para `file`:
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
export const houndsmanConfig = {
|
|
128
|
+
// ...
|
|
129
|
+
storage: { provider: "file", path: "./houndsman/runs" },
|
|
130
|
+
};
|
|
131
|
+
```
|
|
132
|
+
|
|
145
133
|
- **Alterar regras** → use a capability **`train`** (`/houndsman train`). Ela prova no código
|
|
146
134
|
que o padrão existe (evidência) antes de editar e roda as validações.
|
|
147
135
|
- **Atualizou a lib?** Sincronize os arquivos auto-gerados sem tocar nas suas regras:
|
|
@@ -153,8 +141,6 @@ bun run houndsman findings verify # confere o que resolveu (barato, se
|
|
|
153
141
|
|
|
154
142
|
O `update` reescreve **só** `.houndsman/core/**` e `.houndsman/.gitignore`. Seus arquivos
|
|
155
143
|
(`watchdogs/`, `exclusions.ts`, `doc-mappings.ts`, `houndsman.config.ts`) nunca são tocados.
|
|
156
|
-
- **Recomeçar a camada do zero** → `houndsman setup --force` (sobrescreve só os arquivos do
|
|
157
|
-
usuário; sem `--force` o `setup` é idempotente).
|
|
158
144
|
|
|
159
145
|
---
|
|
160
146
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@payconductor/houndsman",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Orquestrador de revisão de Pull Requests: classifica o diff, despacha watchdogs especializados por domínio e consolida o relatório.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Comando `context` — coleta o contexto da PR via `gh` (Passo 0). */
|
|
2
2
|
|
|
3
3
|
import { runContextCommand } from "../../core/commands/context";
|
|
4
|
-
import {
|
|
4
|
+
import { displayPath } from "../../core/paths";
|
|
5
5
|
import { ArgParser } from "../arg-parser";
|
|
6
6
|
import type { CliContext, Command } from "./command";
|
|
7
7
|
|
|
@@ -11,10 +11,12 @@ export class ContextCommand implements Command {
|
|
|
11
11
|
async run(args: string[], context: CliContext): Promise<number> {
|
|
12
12
|
const engine = await context.engine();
|
|
13
13
|
const parser = ArgParser.from(args);
|
|
14
|
-
const { paths, context: pr } = runContextCommand(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
const { paths, context: pr } = runContextCommand(
|
|
15
|
+
engine.config,
|
|
16
|
+
engine.storage,
|
|
17
|
+
engine.repo,
|
|
18
|
+
{ branch: parser.value("--branch") },
|
|
19
|
+
);
|
|
18
20
|
|
|
19
21
|
if (pr.available) {
|
|
20
22
|
const src = pr.source;
|
|
@@ -24,14 +26,14 @@ export class ContextCommand implements Command {
|
|
|
24
26
|
context.out(
|
|
25
27
|
`[houndsman] PR ${label} (${src?.head} → ${src?.base}), ${pr.stats?.files ?? 0} arquivo(s).`,
|
|
26
28
|
);
|
|
27
|
-
context.out(`[houndsman] contexto: ${
|
|
28
|
-
context.out(`[houndsman] brief: ${
|
|
29
|
+
context.out(`[houndsman] contexto: ${displayPath(paths.context)}`);
|
|
30
|
+
context.out(`[houndsman] brief: ${displayPath(paths.brief)}`);
|
|
29
31
|
context.out(
|
|
30
|
-
`[houndsman] próximo passo: subagente resume em ${
|
|
32
|
+
`[houndsman] próximo passo: subagente resume em ${displayPath(paths.summary)}`,
|
|
31
33
|
);
|
|
32
34
|
} else {
|
|
33
35
|
context.out(`[houndsman] contexto indisponível (${pr.reason}): ${pr.detail}`);
|
|
34
|
-
context.out(`[houndsman] marcador: ${
|
|
36
|
+
context.out(`[houndsman] marcador: ${displayPath(paths.context)}`);
|
|
35
37
|
}
|
|
36
38
|
return 0;
|
|
37
39
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** Comando `doctor` (alias `check`) — valida config, ambiente e credencial Jev. */
|
|
2
2
|
|
|
3
3
|
import { checkRegistry } from "../../core/registry-check";
|
|
4
|
+
import { storageLocation } from "../../core/storage/paths";
|
|
4
5
|
import type { CliContext, Command } from "./command";
|
|
5
6
|
|
|
6
7
|
export class DoctorCommand implements Command {
|
|
@@ -28,6 +29,10 @@ export class DoctorCommand implements Command {
|
|
|
28
29
|
context.out("\n→ Ambiente:");
|
|
29
30
|
context.out(` ${Bun.which("git") ? "✅" : "❌"} git`);
|
|
30
31
|
context.out(` ${Bun.which("gh") ? "✅" : "⚠️ "} gh (opcional — contexto da PR)`);
|
|
32
|
+
context.out("\n→ Persistência:");
|
|
33
|
+
context.out(` provider: ${engine.storage.kind}`);
|
|
34
|
+
context.out(` ${storageLocation(engine.config)}`);
|
|
35
|
+
context.out(` repo: ${engine.repo.key}`);
|
|
31
36
|
await this.reportJevCredential(context);
|
|
32
37
|
return 0;
|
|
33
38
|
}
|
|
@@ -16,10 +16,20 @@ export class FindingsCommand implements Command {
|
|
|
16
16
|
const sub = ArgParser.from(args).command();
|
|
17
17
|
const result =
|
|
18
18
|
sub === "verify"
|
|
19
|
-
? await runVerifyCommand(engine.config, args)
|
|
19
|
+
? await runVerifyCommand(engine.config, engine.storage, engine.repo, args)
|
|
20
20
|
: sub === "submit"
|
|
21
|
-
? await runSubmitCommand(
|
|
22
|
-
|
|
21
|
+
? await runSubmitCommand(
|
|
22
|
+
engine.config,
|
|
23
|
+
engine.storage,
|
|
24
|
+
engine.repo,
|
|
25
|
+
args,
|
|
26
|
+
)
|
|
27
|
+
: runFindingsCommand(
|
|
28
|
+
engine.config,
|
|
29
|
+
engine.storage,
|
|
30
|
+
engine.repo,
|
|
31
|
+
args,
|
|
32
|
+
);
|
|
23
33
|
|
|
24
34
|
if (result.exitCode !== 0) context.err(result.output);
|
|
25
35
|
else context.out(result.output);
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/** Comando default — prepara ou finaliza a revisão. */
|
|
2
2
|
|
|
3
3
|
import { parseReviewArgs } from "../../core/commands/review";
|
|
4
|
-
import { resolveArtifactDir } from "../../core/config";
|
|
5
4
|
import type { CliContext, Command } from "./command";
|
|
6
5
|
|
|
7
6
|
export class ReviewCommand implements Command {
|
|
@@ -9,7 +8,7 @@ export class ReviewCommand implements Command {
|
|
|
9
8
|
|
|
10
9
|
async run(args: string[], context: CliContext): Promise<number> {
|
|
11
10
|
const engine = await context.engine();
|
|
12
|
-
const options = parseReviewArgs(args
|
|
11
|
+
const options = parseReviewArgs(args);
|
|
13
12
|
const result = await engine.session(options).run();
|
|
14
13
|
|
|
15
14
|
for (const message of result.messages) context.out(message);
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/** Comando `status` — mostra o status da run ou renova o heartbeat (`status ping`). */
|
|
2
|
+
|
|
3
|
+
import { pingStatus, readStatus } from "../../core/commands/status";
|
|
4
|
+
import { ArgParser } from "../arg-parser";
|
|
5
|
+
import type { CliContext, Command } from "./command";
|
|
6
|
+
|
|
7
|
+
export class StatusCommand implements Command {
|
|
8
|
+
readonly name = "status";
|
|
9
|
+
|
|
10
|
+
async run(args: string[], context: CliContext): Promise<number> {
|
|
11
|
+
const parser = ArgParser.from(args);
|
|
12
|
+
const action = parser.command();
|
|
13
|
+
const branch = parser.value("--branch");
|
|
14
|
+
|
|
15
|
+
if (action && action !== "ping" && action !== "show") {
|
|
16
|
+
context.err(
|
|
17
|
+
`Ação desconhecida em 'status': '${action}'. Use 'status' ou 'status ping'.`,
|
|
18
|
+
);
|
|
19
|
+
return 1;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const engine = await context.engine();
|
|
23
|
+
const result =
|
|
24
|
+
action === "ping"
|
|
25
|
+
? pingStatus(engine.storage, engine.repo, branch)
|
|
26
|
+
: readStatus(engine.storage, engine.repo, branch);
|
|
27
|
+
|
|
28
|
+
if (action === "ping") {
|
|
29
|
+
context.out(
|
|
30
|
+
result.heartbeatAt
|
|
31
|
+
? `Heartbeat atualizado — ${result.branch} · ${result.status ?? "sem status"} · ${result.heartbeatAt}`
|
|
32
|
+
: `Sem execução ativa — ${result.branch} · ${result.status ?? "sem status"}.`,
|
|
33
|
+
);
|
|
34
|
+
} else {
|
|
35
|
+
context.out(
|
|
36
|
+
[
|
|
37
|
+
`Branch: ${result.branch}`,
|
|
38
|
+
`Status: ${result.status ?? "—"}`,
|
|
39
|
+
`Heartbeat: ${result.heartbeatAt ?? "—"}`,
|
|
40
|
+
`Atualizado: ${result.updatedAt}`,
|
|
41
|
+
].join("\n"),
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
return 0;
|
|
45
|
+
}
|
|
46
|
+
}
|
package/src/cli/help.ts
CHANGED
|
@@ -6,6 +6,7 @@ Comandos:
|
|
|
6
6
|
--finalize Consolida os findings em review.md
|
|
7
7
|
context Coleta o contexto da PR via gh (Passo 0)
|
|
8
8
|
findings <sub> Triagem/correção dos findings (list · show · set · done · reset · sync · summary · batch · verify · submit · path)
|
|
9
|
+
status [ping] Mostra o status da run (ping renova o heartbeat da execução)
|
|
9
10
|
server Sobe a UI local de triagem (--port, --host, --open)
|
|
10
11
|
setup Cria a configuração inicial do projeto (config + skills)
|
|
11
12
|
update Sincroniza os arquivos auto-gerados (.houndsman/core)
|
|
@@ -18,8 +19,7 @@ Flags:
|
|
|
18
19
|
--base <branch> Base do diff (default: main)
|
|
19
20
|
--head <ref> Head do diff (default: HEAD)
|
|
20
21
|
--branch <nome> Branch alvo (default: detecta do git)
|
|
21
|
-
--
|
|
22
|
-
--clean Descarta findings anteriores
|
|
22
|
+
--clean Descarta findings brutos do staging anterior
|
|
23
23
|
--full Força review completo (ignora o modo incremental)
|
|
24
24
|
--no-jev Desativa a pré-análise Jev
|
|
25
25
|
--fail-on-blocking Exit 1 se houver bloqueantes (com --finalize)
|
|
@@ -40,4 +40,9 @@ Flags de findings:
|
|
|
40
40
|
--apply (verify) Marca os resolvidos como done
|
|
41
41
|
--fail-on-persisting (verify) Exit 1 se algum blocking persistir
|
|
42
42
|
--include-sent (submit) Reenvia findings já enviados à PR
|
|
43
|
-
--dry-run (submit) Só a prévia do envio, sem postar
|
|
43
|
+
--dry-run (submit) Só a prévia do envio, sem postar
|
|
44
|
+
|
|
45
|
+
Persistência:
|
|
46
|
+
Runs, findings e artefatos ficam no storage global (SQLite em
|
|
47
|
+
<HOUNDSMAN_HOME>/houndsman.db). Use storage.provider: "file" na config para
|
|
48
|
+
voltar ao backend de arquivos. Nada é gravado em .houndsman/.runs.`;
|
package/src/cli/index.ts
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* --finalize Passo 3 — consolidar os findings em review.md
|
|
16
16
|
* context Passo 0 — coletar o contexto da PR via `gh`
|
|
17
17
|
* findings <sub> Triagem/correção dos findings (list/set/done/sync/batch/verify/submit/...)
|
|
18
|
+
* status [ping] Mostra o status da run; `ping` renova o heartbeat da execução
|
|
18
19
|
* server Sobe a UI local de triagem (Bun.serve)
|
|
19
20
|
* setup Cria a configuração inicial do projeto (config + skills)
|
|
20
21
|
* update Sincroniza os arquivos auto-gerados (.houndsman/core)
|
|
@@ -22,8 +23,8 @@
|
|
|
22
23
|
* test Roda a suíte de testes da lib
|
|
23
24
|
* watchdog <id> Contexto de um watchdog (`--rules`, `--json`)
|
|
24
25
|
*
|
|
25
|
-
* Flags: `--base <b>` · `--head <ref>` · `--branch <b>` · `--
|
|
26
|
-
* `--
|
|
26
|
+
* Flags: `--base <b>` · `--head <ref>` · `--branch <b>` · `--config <path>` ·
|
|
27
|
+
* `--clean` · `--full` · `--no-jev` · `--fail-on-blocking`.
|
|
27
28
|
*/
|
|
28
29
|
|
|
29
30
|
import { loadConfig } from "../core/config-loader";
|
|
@@ -38,6 +39,7 @@ import { CommandRegistry } from "./commands/registry";
|
|
|
38
39
|
import { ReviewCommand } from "./commands/review-command";
|
|
39
40
|
import { ServerCommand } from "./commands/server-command";
|
|
40
41
|
import { SetupCommand, TestCommand, UpdateCommand } from "./commands/setup-command";
|
|
42
|
+
import { StatusCommand } from "./commands/status-command";
|
|
41
43
|
import { WatchdogCommand } from "./commands/watchdog-command";
|
|
42
44
|
import { HELP } from "./help";
|
|
43
45
|
|
|
@@ -53,6 +55,7 @@ function buildRegistry(): CommandRegistry {
|
|
|
53
55
|
.register(new HelpCommand())
|
|
54
56
|
.register(new ContextCommand())
|
|
55
57
|
.register(new FindingsCommand())
|
|
58
|
+
.register(new StatusCommand())
|
|
56
59
|
.register(new WatchdogCommand())
|
|
57
60
|
.register(new ServerCommand())
|
|
58
61
|
.register(new SetupCommand())
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Subcomando `context` — coleta o contexto da PR via `gh` (Passo 0).
|
|
3
3
|
*
|
|
4
|
-
* Biblioteca: grava
|
|
4
|
+
* Biblioteca: grava no staging da review + artefato no storage; o CLI faz o
|
|
5
|
+
* log/exit.
|
|
5
6
|
*/
|
|
6
7
|
|
|
7
|
-
import {
|
|
8
|
-
import { type HoundsmanConfig, resolveArtifactDir } from "../config";
|
|
8
|
+
import type { HoundsmanConfig } from "../config";
|
|
9
9
|
import {
|
|
10
|
-
type ContextPaths,
|
|
11
10
|
collectPrContext,
|
|
12
|
-
contextPaths,
|
|
13
11
|
currentBranch,
|
|
14
12
|
type PrContextRaw,
|
|
15
13
|
renderContextBrief,
|
|
16
14
|
} from "../pr-context";
|
|
15
|
+
import { sanitizeBranch } from "../report-builder";
|
|
16
|
+
import type { RepoIdentity, StorageProvider } from "../storage/types";
|
|
17
|
+
import { type ContextPaths, ReviewWorkArea } from "../storage/work-area";
|
|
17
18
|
|
|
18
19
|
export type ContextRunResult = {
|
|
19
20
|
paths: ContextPaths;
|
|
@@ -22,18 +23,33 @@ export type ContextRunResult = {
|
|
|
22
23
|
|
|
23
24
|
/** Coleta a PR atual e grava `context.json` + `context-brief.md`. */
|
|
24
25
|
export function runContextCommand(
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
_config: HoundsmanConfig,
|
|
27
|
+
storage: StorageProvider,
|
|
28
|
+
repo: RepoIdentity,
|
|
29
|
+
opts: { branch?: string } = {},
|
|
27
30
|
): ContextRunResult {
|
|
28
31
|
const branch = opts.branch ?? currentBranch();
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
const review = storage.getOrCreateReview({
|
|
33
|
+
repo,
|
|
34
|
+
branch,
|
|
35
|
+
slug: sanitizeBranch(branch),
|
|
36
|
+
});
|
|
37
|
+
const work = new ReviewWorkArea(review);
|
|
38
|
+
const paths = work.contextPaths;
|
|
33
39
|
|
|
34
40
|
const context = collectPrContext(branch);
|
|
35
|
-
|
|
36
|
-
|
|
41
|
+
const brief = renderContextBrief(context, branch, paths);
|
|
42
|
+
work.writeContext(context, brief);
|
|
43
|
+
storage.writeArtifact(review.id, {
|
|
44
|
+
name: "context.json",
|
|
45
|
+
kind: "context",
|
|
46
|
+
content: `${JSON.stringify(context, null, 2)}\n`,
|
|
47
|
+
});
|
|
48
|
+
storage.writeArtifact(review.id, {
|
|
49
|
+
name: "context-brief.md",
|
|
50
|
+
kind: "context-brief",
|
|
51
|
+
content: `${brief}\n`,
|
|
52
|
+
});
|
|
37
53
|
|
|
38
54
|
return { paths, context };
|
|
39
55
|
}
|