@payconductor/houndsman 0.4.0 → 0.6.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 +35 -41
- package/assets/grammars/tree-sitter-javascript.wasm +0 -0
- package/assets/grammars/tree-sitter-tsx.wasm +0 -0
- package/assets/grammars/tree-sitter-typescript.wasm +0 -0
- package/assets/grammars/web-tree-sitter.wasm +0 -0
- package/package.json +11 -3
- package/src/cli/commands/command.ts +5 -0
- package/src/cli/commands/doctor-command.ts +116 -24
- package/src/cli/commands/hunt-command.ts +25 -0
- package/src/cli/commands/status-command.ts +46 -0
- package/src/cli/help.ts +18 -1
- package/src/cli/index.ts +13 -6
- package/src/core/ai/ai-client.ts +221 -0
- package/src/core/ai/ai-sdk-model-provider.ts +101 -0
- package/src/core/ai/errors.ts +36 -0
- package/src/core/ai/features/brief-enricher.ts +62 -0
- package/src/core/ai/features/classifier.ts +50 -0
- package/src/core/ai/features/context-summarizer.ts +31 -0
- package/src/core/ai/features/pre-analyzer.ts +51 -0
- package/src/core/ai/features/verifier.ts +45 -0
- package/src/core/ai/index.ts +56 -0
- package/src/core/ai/model-factory.ts +137 -0
- package/src/core/ai/prompts/base.ts +36 -0
- package/src/core/ai/prompts/brief.ts +87 -0
- package/src/core/ai/prompts/classification.ts +36 -0
- package/src/core/ai/prompts/context.ts +29 -0
- package/src/core/ai/prompts/pre-analysis.ts +49 -0
- package/src/core/ai/prompts/verify.ts +40 -0
- package/src/core/ai/schemas.ts +110 -0
- package/src/core/ai/types.ts +76 -0
- package/src/core/ai/usage-budget.ts +75 -0
- package/src/core/ai/usage-recorder.ts +79 -0
- package/src/core/assets.ts +16 -0
- package/src/core/ast/diff.ts +220 -0
- package/src/core/ast/impact.ts +127 -0
- package/src/core/ast/parser.ts +167 -0
- package/src/core/ast/service.ts +233 -0
- package/src/core/ast/symbols.ts +294 -0
- package/src/core/ast/types.ts +125 -0
- package/src/core/brief.ts +138 -0
- package/src/core/commands/findings.ts +120 -6
- package/src/core/commands/review.ts +2 -0
- package/src/core/commands/scaffold.ts +159 -10
- package/src/core/commands/status.ts +63 -0
- package/src/core/commands/update.ts +5 -3
- package/src/core/config.ts +85 -0
- package/src/core/defaults.ts +27 -0
- package/src/core/domain/watchdog.ts +43 -5
- package/src/core/engine/houndsman-engine.ts +16 -1
- package/src/core/engine/review-scope.ts +77 -13
- package/src/core/engine/review-session.ts +27 -2
- package/src/core/env.ts +101 -0
- package/src/core/file-classifier.ts +25 -4
- package/src/core/findings-state.ts +21 -4
- package/src/core/github-review.ts +620 -57
- package/src/core/jev/jev-client.ts +8 -7
- package/src/core/jev/jev-verify.ts +2 -1
- package/src/core/logging/index.ts +17 -0
- package/src/core/logging/logger.ts +187 -0
- package/src/core/orchestrator.ts +454 -16
- package/src/core/paths.ts +3 -0
- package/src/core/project-config.ts +123 -1
- package/src/core/registry-check.ts +148 -6
- package/src/core/renderers/manifest-writer.ts +33 -0
- package/src/core/renderers/resume-renderer.ts +151 -0
- package/src/core/report-builder.ts +7 -4
- package/src/core/rule-text.ts +97 -0
- package/src/core/run-status.ts +39 -5
- package/src/core/services/file-classifier.ts +10 -3
- package/src/core/services/verifier.ts +14 -3
- package/src/core/storage/file/file-storage.ts +2 -0
- package/src/core/storage/paths.ts +6 -5
- package/src/core/storage/sqlite/mappers.ts +2 -0
- package/src/core/storage/sqlite/schema.ts +9 -1
- package/src/core/storage/sqlite/sqlite-storage.ts +5 -1
- package/src/core/storage/types.ts +15 -0
- package/src/core/storage/work-area.ts +12 -0
- package/src/core/types.ts +37 -1
- package/src/core/verify.ts +17 -5
- package/src/harness/README.md +15 -0
- package/src/harness/agent/agent-context.ts +33 -0
- package/src/harness/agent/agent-errors.ts +30 -0
- package/src/harness/agent/agent-factory.ts +45 -0
- package/src/harness/agent/agent-reporter.ts +34 -0
- package/src/harness/agent/agent-result.ts +16 -0
- package/src/harness/agent/agent-runner.ts +32 -0
- package/src/harness/agent/agent-scheduler.ts +37 -0
- package/src/harness/agent/review-agent.ts +391 -0
- package/src/harness/config/harness-config.ts +84 -0
- package/src/harness/hunt/hunt-harness.ts +83 -0
- package/src/harness/hunt/hunt-options.ts +75 -0
- package/src/harness/hunt/hunt-result.ts +17 -0
- package/src/harness/hunt/hunt-session.ts +372 -0
- package/src/harness/hunt/review-planner.ts +98 -0
- package/src/harness/index.ts +36 -0
- package/src/harness/investigation/agent-state.ts +134 -0
- package/src/harness/investigation/evidence-verifier.ts +129 -0
- package/src/harness/investigation/evidence.ts +110 -0
- package/src/harness/investigation/finding-critic.ts +96 -0
- package/src/harness/investigation/investigation-planner.ts +118 -0
- package/src/harness/investigation/investigation-task.ts +10 -0
- package/src/harness/investigation/review-journal.ts +87 -0
- package/src/harness/investigation/rule-analyzer.ts +178 -0
- package/src/harness/investigation/rule-signals.ts +110 -0
- package/src/harness/prompts/agent-schemas.ts +57 -0
- package/src/harness/prompts/reviewer-prompt-builder.ts +101 -0
- package/src/harness/prompts/states/conclude-prompt.ts +16 -0
- package/src/harness/prompts/states/investigate-prompt.ts +37 -0
- package/src/harness/prompts/states/orient-prompt.ts +15 -0
- package/src/harness/prompts/states/verify-prompt.ts +22 -0
- package/src/harness/tools/agent-tool.ts +102 -0
- package/src/harness/tools/builtin/changed-symbols-tool.ts +48 -0
- package/src/harness/tools/builtin/doc-context-tool.ts +74 -0
- package/src/harness/tools/builtin/file-outline-tool.ts +66 -0
- package/src/harness/tools/builtin/find-references-tool.ts +66 -0
- package/src/harness/tools/builtin/find-symbol-tool.ts +91 -0
- package/src/harness/tools/builtin/helpers.ts +115 -0
- package/src/harness/tools/builtin/impact-tool.ts +48 -0
- package/src/harness/tools/builtin/imports-exports-tool.ts +53 -0
- package/src/harness/tools/builtin/index.ts +59 -0
- package/src/harness/tools/builtin/list-files-tool.ts +85 -0
- package/src/harness/tools/builtin/pr-context-tool.ts +41 -0
- package/src/harness/tools/builtin/read-file-range-tool.ts +73 -0
- package/src/harness/tools/builtin/rule-signals-tool.ts +36 -0
- package/src/harness/tools/builtin/search-code-tool.ts +65 -0
- package/src/harness/tools/builtin/symbol-context-tool.ts +106 -0
- package/src/harness/tools/builtin/tests-for-symbol-tool.ts +61 -0
- package/src/harness/tools/path-guard.ts +90 -0
- package/src/harness/tools/result-limiter.ts +49 -0
- package/src/harness/tools/secret-redactor.ts +54 -0
- package/src/harness/tools/tool-cache.ts +50 -0
- package/src/harness/tools/tool-call-budget.ts +60 -0
- package/src/harness/tools/tool-context.ts +5 -0
- package/src/harness/tools/tool-middleware.ts +105 -0
- package/src/harness/tools/tool-policy.ts +51 -0
- package/src/harness/tools/tool-registry.ts +112 -0
- package/src/harness/tools/tool-result.ts +15 -0
- package/src/harness/tools/toolbox.ts +36 -0
- package/src/harness/validation/finding-validator.ts +119 -0
- package/src/index.ts +46 -0
- package/src/server/client/App.tsx +26 -9
- package/src/server/client/ArtifactsPanel.tsx +12 -5
- package/src/server/client/AutoRefresh.tsx +1 -1
- package/src/server/client/Filters.tsx +7 -2
- package/src/server/client/FindingCard.tsx +14 -10
- package/src/server/client/FindingsList.tsx +2 -2
- package/src/server/client/MarkdownText.tsx +92 -12
- package/src/server/client/ResumePanel.tsx +368 -0
- package/src/server/client/RunList.tsx +3 -3
- package/src/server/client/SubmitModal.tsx +49 -6
- package/src/server/client/SummaryBar.tsx +1 -1
- package/src/server/client/icons.tsx +17 -0
- package/src/server/client/{constants.ts → utils/constants.ts} +61 -10
- package/src/server/client/utils/markdown.ts +319 -0
- package/src/server/client/{types.ts → utils/types.ts} +64 -0
- package/src/server/index.ts +66 -7
- package/src/server/run-repository.ts +9 -0
- package/src/skill/OUTPUT-FORMAT.md +12 -0
- package/src/skill/SETUP.md +6 -2
- package/src/skill/example-review.md +22 -14
- package/src/skill/hunt.md +45 -19
- package/src/skill/verify.md +3 -2
- package/src/tests/__snapshots__/baseline.test.ts.snap +126 -42
- package/src/tests/ai-core.test.ts +120 -0
- package/src/tests/ai-features.test.ts +183 -0
- package/src/tests/ast.test.ts +335 -0
- package/src/tests/baseline.test.ts +3 -0
- package/src/tests/code-highlight.test.ts +1 -1
- package/src/tests/env.test.ts +69 -0
- package/src/tests/fallback.test.ts +172 -0
- package/src/tests/findings-state.test.ts +50 -2
- package/src/tests/fixtures/fake-agent-tools.ts +69 -0
- package/src/tests/fixtures/fake-investigation.ts +64 -0
- package/src/tests/fixtures/fake-model-provider.ts +48 -0
- package/src/tests/github-review.test.ts +409 -60
- package/src/tests/harness-agent.test.ts +122 -0
- package/src/tests/harness-investigation.test.ts +206 -0
- package/src/tests/harness-tools.test.ts +148 -0
- package/src/tests/hunt-command.test.ts +212 -0
- package/src/tests/logger.test.ts +83 -0
- package/src/tests/markdown.test.ts +61 -1
- 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 +73 -0
- package/src/tests/rule-analyzer.test.ts +61 -0
- package/src/tests/run-status-view.test.ts +94 -0
- package/src/tests/run-status.test.ts +53 -0
- package/src/tests/server.test.ts +76 -21
- package/src/tests/storage.test.ts +63 -0
- package/src/tests/tool-contracts.test.ts +82 -0
- package/src/tests/verify.test.ts +1 -1
- package/src/server/client/markdown.ts +0 -153
- /package/src/server/client/{api.ts → utils/api.ts} +0 -0
- /package/src/server/client/{code-highlight.ts → utils/code-highlight.ts} +0 -0
- /package/src/server/client/{format.ts → utils/format.ts} +0 -0
- /package/src/server/client/{json-highlight.ts → utils/json-highlight.ts} +0 -0
package/src/server/index.ts
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
type GhRunner,
|
|
15
15
|
type SubmitSelection,
|
|
16
16
|
} from "../core/github-review";
|
|
17
|
+
import { logger } from "../core/logging";
|
|
17
18
|
import { createStorage } from "../core/storage/factory";
|
|
18
19
|
import { resolveRepoIdentity } from "../core/storage/repo-identity";
|
|
19
20
|
import type { RepoIdentity, StorageProvider } from "../core/storage/types";
|
|
@@ -190,8 +191,8 @@ export class HoundsmanServer {
|
|
|
190
191
|
try {
|
|
191
192
|
this.runs.maintain();
|
|
192
193
|
} catch (error) {
|
|
193
|
-
|
|
194
|
-
`
|
|
194
|
+
logger.warn(
|
|
195
|
+
`VACUUM falhou (seguindo sem compactar): ${
|
|
195
196
|
error instanceof Error ? error.message : String(error)
|
|
196
197
|
}`,
|
|
197
198
|
);
|
|
@@ -315,7 +316,7 @@ code, pre, .mono { font-family:var(--font-mono); tab-size:4; }
|
|
|
315
316
|
.btn:disabled { opacity:.55; cursor:not-allowed; }
|
|
316
317
|
.icon.spin { animation:spin .8s linear infinite; }
|
|
317
318
|
.content { width:100%; max-width:1180px; margin:0 auto; padding:22px 24px 64px; }
|
|
318
|
-
.page-header { display:flex; align-items:flex-start; justify-content:space-between; gap:18px; }
|
|
319
|
+
.page-header { display:flex; align-items:flex-start; justify-content:space-between; gap:18px; margin-bottom:16px; }
|
|
319
320
|
.page-header-text { min-width:0; }
|
|
320
321
|
.page-header-actions { display:flex; align-items:center; gap:10px; flex:none; }
|
|
321
322
|
.btn.submit-review { color:#1b1305; background:linear-gradient(180deg, var(--accent-strong), var(--accent)); border-color:transparent; box-shadow:0 4px 14px rgba(240,165,44,.22); }
|
|
@@ -412,12 +413,25 @@ code, pre, .mono { font-family:var(--font-mono); tab-size:4; }
|
|
|
412
413
|
.action-text p:last-child { margin-bottom:0; }
|
|
413
414
|
.md-list { margin:0 0 6px; padding-left:20px; font-size:13px; line-height:1.65; color:#f0ece6; }
|
|
414
415
|
.md-list li { margin:0 0 2px; }
|
|
415
|
-
.md-quote { margin:0 0 6px; padding:2px 0 2px 10px; border-left:2px solid var(--accent-line); color:var(--muted); font-size:13px; line-height:1.65; }
|
|
416
|
+
.md-quote { margin:0 0 6px; padding:2px 0 2px 10px; border-left:2px solid var(--accent-line); color:var(--muted); font-size:13px; line-height:1.65; white-space:pre-wrap; }
|
|
416
417
|
.action-text code, .md-code { font-family:var(--font-mono); font-size:11.5px; padding:1px 5px; color:#f0ece6; background:rgba(255,255,255,.06); border:1px solid var(--border); border-radius:5px; }
|
|
417
|
-
.
|
|
418
|
-
.action-text
|
|
419
|
-
.action-text
|
|
418
|
+
code.md-path { color:#8fc7ff; background:rgba(90,164,240,.1); border-color:rgba(90,164,240,.24); }
|
|
419
|
+
.action-text a, .md-p a, .md-list a, .md-quote a, .md-table a, .md-h a { color:var(--accent-strong); text-decoration:underline; text-underline-offset:2px; }
|
|
420
|
+
.action-text strong, .md-p strong, .md-list strong, .md-quote strong, .md-table strong, .md-h strong { color:#fff; font-weight:600; }
|
|
421
|
+
.action-text em, .md-p em, .md-list em, .md-quote em, .md-table em, .md-h em { color:#e9e4dc; }
|
|
420
422
|
.md-code-block { margin:6px 0; padding:10px 12px; max-height:320px; overflow:auto; white-space:pre; font-size:11.5px; line-height:1.6; color:#cdc7bf; background:#0b0b0e; border-radius:10px; }
|
|
423
|
+
.md-h { margin:16px 0 8px; font-size:14px; font-weight:700; line-height:1.35; letter-spacing:-.01em; color:#eee9e2; }
|
|
424
|
+
.md-h:first-child { margin-top:0; }
|
|
425
|
+
.md-h1 { font-size:19px; }
|
|
426
|
+
.md-h2 { font-size:16px; }
|
|
427
|
+
.md-h3 { font-size:14px; }
|
|
428
|
+
.md-h4, .md-h5, .md-h6 { font-size:13px; color:#e4dfd7; font-weight:600; }
|
|
429
|
+
.md-hr { margin:14px 0; border:0; border-top:1px solid var(--border); }
|
|
430
|
+
.md-table-wrap { margin:8px 0 12px; padding:4px; overflow-x:auto; border:1px solid rgba(255,255,255,.07); border-radius:10px; background:rgba(255,255,255,.012); }
|
|
431
|
+
.md-table { width:100%; border-collapse:separate; border-spacing:3px; font-size:12px; line-height:1.5; }
|
|
432
|
+
.md-table th, .md-table td { padding:6px 9px; text-align:left; vertical-align:top; border:1px solid rgba(255,255,255,.035); border-radius:6px; }
|
|
433
|
+
.md-table th { color:var(--muted); font-weight:600; background:rgba(255,255,255,.03); }
|
|
434
|
+
.md-table td { color:#d8d3cc; }
|
|
421
435
|
.decision-tags-block { display:flex; align-items:center; gap:8px; }
|
|
422
436
|
.evidence { margin:0; padding: 16px; white-space:break-spaces; font-size:12px; line-height:1.6; color:#cdc7bf;
|
|
423
437
|
background:#0b0b0e; border:1px solid var(--border); border-radius:var(--radius); }
|
|
@@ -476,6 +490,10 @@ code, pre, .mono { font-family:var(--font-mono); tab-size:4; }
|
|
|
476
490
|
border:1px solid var(--accent-line); border-radius:999px; }
|
|
477
491
|
.artifact-view { margin:0; padding:14px 16px; max-height:70vh; overflow:auto; font-size:12px; line-height:1.6; color:#cdc7bf;
|
|
478
492
|
background:#0b0b0e; border:1px solid var(--border); border-radius:var(--radius); }
|
|
493
|
+
.artifact-markdown { white-space:normal; }
|
|
494
|
+
.artifact-markdown .md-p, .artifact-markdown .md-list, .artifact-markdown .md-quote { font-size:12.5px; }
|
|
495
|
+
.artifact-markdown .md-p, .artifact-markdown .md-list { color:#d8d3cc; }
|
|
496
|
+
.artifact-markdown .md-code-block { border:1px solid var(--border); }
|
|
479
497
|
.json-view { white-space:pre; }
|
|
480
498
|
.json-key { color:var(--accent-strong); }
|
|
481
499
|
.json-string { color:#9ddc8a; }
|
|
@@ -486,6 +504,47 @@ code, pre, .mono { font-family:var(--font-mono); tab-size:4; }
|
|
|
486
504
|
.sent-tag { display:inline-flex; align-items:center; gap:5px; padding:2px 8px; font-size:10px; font-weight:700; letter-spacing:.06em; text-transform:uppercase;
|
|
487
505
|
color:var(--success); background:rgba(69,192,122,.12); border:1px solid rgba(69,192,122,.32); border-radius:999px; text-decoration:none; }
|
|
488
506
|
.sent-tag:hover { color:#fff; }
|
|
507
|
+
.sent-tag.gh { color:#b9c7d6; background:rgba(139,164,191,.12); border-color:rgba(139,164,191,.35); }
|
|
508
|
+
.sent-tag.gh:hover { color:#fff; background:rgba(139,164,191,.2); }
|
|
509
|
+
.resume { display:flex; flex-direction:column; }
|
|
510
|
+
.resume-hero { display:flex; align-items:flex-start; justify-content:space-between; gap:16px; padding:18px 20px;
|
|
511
|
+
background:linear-gradient(135deg, rgba(240,165,44,.08), rgba(255,255,255,.015) 55%);
|
|
512
|
+
border:1px solid var(--border); border-radius:var(--radius-lg); }
|
|
513
|
+
.resume-kicker { display:block; font-size:10px; font-weight:700; letter-spacing:.14em; text-transform:uppercase; color:var(--accent); }
|
|
514
|
+
.resume-title { margin:5px 0 7px; font-size:22px; font-weight:700; letter-spacing:-.02em; word-break:break-word; }
|
|
515
|
+
.resume-meta { display:flex; flex-wrap:wrap; align-items:center; gap:12px; margin:0; font-size:12px; color:var(--muted); }
|
|
516
|
+
.resume-pr { display:inline-flex; align-items:center; gap:5px; color:var(--accent-strong); text-decoration:none; }
|
|
517
|
+
.resume-pr:hover { text-decoration:underline; }
|
|
518
|
+
.resume-hero-side { display:flex; flex:none; flex-direction:column; align-items:flex-end; gap:10px; }
|
|
519
|
+
.resume-status { display:inline-flex; align-items:center; padding:5px 12px; font-size:11px; font-weight:700; letter-spacing:.04em; border-radius:999px; }
|
|
520
|
+
.resume-status.blocking { color:var(--blocking); background:rgba(242,89,94,.12); border:1px solid rgba(242,89,94,.35); }
|
|
521
|
+
.resume-status.attention { color:var(--attention); background:rgba(237,161,58,.12); border:1px solid rgba(237,161,58,.35); }
|
|
522
|
+
.resume-status.clean { color:var(--success); background:rgba(69,192,122,.12); border:1px solid rgba(69,192,122,.35); }
|
|
523
|
+
.resume-kpis { margin:14px 0 18px; }
|
|
524
|
+
.resume-kpis .kpi-value { font-size:24px; }
|
|
525
|
+
.churn-add { color:var(--success); }
|
|
526
|
+
.churn-del { color:var(--blocking); }
|
|
527
|
+
.churn-sep { margin:0 3px; color:var(--muted-2); font-weight:400; }
|
|
528
|
+
.kpi-blocking .kpi-value { color:var(--blocking); }
|
|
529
|
+
.kpi-attention .kpi-value { color:var(--attention); }
|
|
530
|
+
.kpi-total .kpi-value { color:var(--fg); }
|
|
531
|
+
.resume-grid { display:grid; grid-template-columns:minmax(0,1.35fr) minmax(0,1fr); gap:16px; align-items:start; }
|
|
532
|
+
.resume-card { min-width:0; padding:16px 18px; background:var(--card); border:1px solid var(--border); border-radius:var(--radius-lg); }
|
|
533
|
+
.resume-card-head { display:flex; align-items:center; justify-content:space-between; gap:10px; }
|
|
534
|
+
.resume-card-title { margin:0 0 10px; font-size:12px; font-weight:700; letter-spacing:.1em; text-transform:uppercase; color:var(--muted); }
|
|
535
|
+
.resume-card-count { display:inline-flex; align-items:center; justify-content:center; min-width:22px; height:22px; margin-bottom:10px; padding:0 7px;
|
|
536
|
+
font-family:var(--font-mono); font-size:11px; color:var(--accent); background:var(--accent-soft); border:1px solid var(--accent-line); border-radius:999px; }
|
|
537
|
+
.resume-narrative .md-p:last-child { margin-bottom:0; }
|
|
538
|
+
.resume-domains { display:flex; flex-direction:column; gap:8px; margin:0; padding:0; list-style:none; }
|
|
539
|
+
.resume-domain { display:flex; flex-direction:column; gap:7px; padding:10px 12px; background:var(--surface-2);
|
|
540
|
+
border:1px solid var(--border); border-radius:10px; }
|
|
541
|
+
.resume-domain-head { display:flex; align-items:baseline; justify-content:space-between; gap:10px; }
|
|
542
|
+
.resume-domain-name { font-size:12.5px; font-weight:600; color:var(--fg); }
|
|
543
|
+
.resume-domain-files { flex:none; font-family:var(--font-mono); font-size:10.5px; color:var(--muted-2); }
|
|
544
|
+
.resume-domain-sev { display:flex; flex-wrap:wrap; gap:6px; }
|
|
545
|
+
.resume-domain-sev .sev-badge { padding:2px 7px; font-size:9.5px; }
|
|
546
|
+
.resume-domain-ok { font-size:11.5px; color:var(--success); }
|
|
547
|
+
@media (max-width:900px) { .resume-grid { grid-template-columns:1fr; } .resume-hero { flex-direction:column; } .resume-hero-side { flex-direction:row; align-items:flex-start; } }
|
|
489
548
|
.modal-layer { position:fixed; inset:0; z-index:50; display:grid; place-items:center; padding:24px; }
|
|
490
549
|
.modal-backdrop { position:absolute; inset:0; width:100%; padding:0; background:rgba(5,5,7,.66); border:0; cursor:default; backdrop-filter:blur(5px); -webkit-backdrop-filter:blur(5px); }
|
|
491
550
|
.modal { position:relative; width:min(640px, 100%); max-height:min(78vh, 780px); display:flex; flex-direction:column; overflow:hidden;
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
resolvePrTarget,
|
|
31
31
|
type SubmitSelection,
|
|
32
32
|
submitFindings,
|
|
33
|
+
syncResolvedThreads,
|
|
33
34
|
} from "../core/github-review";
|
|
34
35
|
import { pingFindingsStatus } from "../core/run-status";
|
|
35
36
|
import { systemClock } from "../core/services/clock";
|
|
@@ -42,6 +43,8 @@ export type RunListItem = {
|
|
|
42
43
|
slug: string;
|
|
43
44
|
branch: string;
|
|
44
45
|
updatedAt?: string;
|
|
46
|
+
startedAt?: string;
|
|
47
|
+
heartbeatAt?: string;
|
|
45
48
|
status: ReviewRecord["status"];
|
|
46
49
|
summary: FindingsSummary;
|
|
47
50
|
};
|
|
@@ -94,6 +97,8 @@ export class RunRepository {
|
|
|
94
97
|
slug: review.slug,
|
|
95
98
|
branch: review.branch,
|
|
96
99
|
updatedAt: review.updatedAt,
|
|
100
|
+
startedAt: review.startedAt,
|
|
101
|
+
heartbeatAt: review.heartbeatAt,
|
|
97
102
|
status: review.status,
|
|
98
103
|
summary: summarize(state ?? emptyState(review.branch)),
|
|
99
104
|
};
|
|
@@ -211,6 +216,10 @@ export class RunRepository {
|
|
|
211
216
|
if (resolution.status !== "found") return null;
|
|
212
217
|
const finding = state.findings[resolution.id];
|
|
213
218
|
applyFindingUpdate(finding, body);
|
|
219
|
+
// "Done" na UI é resolução local: resolve a conversa no PR (fail-open).
|
|
220
|
+
if (body.execState === "done") {
|
|
221
|
+
syncResolvedThreads({ state, ids: [finding.id] });
|
|
222
|
+
}
|
|
214
223
|
reorder(state);
|
|
215
224
|
state.updatedAt = systemClock();
|
|
216
225
|
this.storage.writeFindings(review.id, state);
|
|
@@ -70,3 +70,15 @@ staging global da review:
|
|
|
70
70
|
- Um achado por regra violada; não agrupar regras diferentes.
|
|
71
71
|
- `file:line` sempre que possível; `evidence` quando o achado não é óbvio.
|
|
72
72
|
- Não inventar achados — se não houver violação, o array fica vazio.
|
|
73
|
+
|
|
74
|
+
## Findings emergentes (opt-in)
|
|
75
|
+
|
|
76
|
+
Quando o watchdog declara `allowEmergentFindings: true`, você pode reportar falhas de
|
|
77
|
+
**lógica** ou **domínio** que não correspondem a uma regra explícita usando os prefixos
|
|
78
|
+
reservados:
|
|
79
|
+
|
|
80
|
+
- `Lógica: <descrição>` — nome/contrato vs comportamento, fluxos, estados, bordas.
|
|
81
|
+
- `Domínio: <descrição>` — transições, idempotência, invariantes, arredondamento, timezone.
|
|
82
|
+
|
|
83
|
+
Esses findings continuam exigindo `evidence` e têm severidade máxima `attention`. Sem o
|
|
84
|
+
opt-in, todo finding precisa citar uma regra existente.
|
package/src/skill/SETUP.md
CHANGED
|
@@ -7,8 +7,11 @@ no seu projeto é **autocontida** — não exige nenhuma dependência local do p
|
|
|
7
7
|
|
|
8
8
|
- **Bun** — o CLI e o motor usam a runtime Bun (execução de TS, `Bun.spawnSync`).
|
|
9
9
|
- **git** — o diff usa `git diff <base>...<head> --name-status`.
|
|
10
|
-
- Opcional
|
|
11
|
-
|
|
10
|
+
- **gh** (Opcional) — Obtém contexto da PR e dispara comentários para o GitHub
|
|
11
|
+
- **`HOUNDSMAN_TYPE_SAFE_API_KEY`** (opcional) — pré-análise Jev.
|
|
12
|
+
- **`HOUNDSMAN_DEEP_SEEK_API_KEY`** (opcional) — IA própria do `hunt` nativo e das features de IA.
|
|
13
|
+
- **`HOUNDSMAN_OPENAI_API_KEY`** / **`HOUNDSMAN_ANTHROPIC_API_KEY`** (opcional) — apenas se
|
|
14
|
+
`ai.provider` for `openai`/`anthropic`.
|
|
12
15
|
|
|
13
16
|
## Instalação (global)
|
|
14
17
|
|
|
@@ -87,6 +90,7 @@ Definido em `src/core/config.ts` (pacote) e espelhado em `.houndsman/core/types.
|
|
|
87
90
|
| `alwaysIncludeDocs` | Docs sempre presentes nos briefs (default `["AGENTS.md"]`). |
|
|
88
91
|
| `budgets` | **Opcional** — teto de arquivos por brief (`maxFilesPerBrief`, default `40`); o excedente vira "fora do orçamento" (registrar em `skipped`). |
|
|
89
92
|
| `concurrency` | **Opcional** — chamadas Jev simultâneas (`jev`, default `5`). |
|
|
93
|
+
| `ast` | **Opcional** — AST determinístico para TS/JS (`enabled`, `maxFileBytes`, `maxImpactFiles`, `languages`, `aliases`). Default: ligado; falhas são fail-open. |
|
|
90
94
|
|
|
91
95
|
> O motor **não contém** ids, paths ou regras do projeto — tudo chega por `HoundsmanConfig`,
|
|
92
96
|
> carregado em runtime a partir de `houndsman.config.ts` (ou `--config <path>`).
|
|
@@ -14,6 +14,28 @@
|
|
|
14
14
|
- Novo endpoint interno para reprocessar eventos manualmente.
|
|
15
15
|
- Registro de tentativas no handler de envio.
|
|
16
16
|
|
|
17
|
+
## Relatórios por domínio
|
|
18
|
+
|
|
19
|
+
| Watchdog | Achados | Revisados | Relatório |
|
|
20
|
+
|---|---|---|---|
|
|
21
|
+
| Arquitetura Backend | 2 | 3/3 | [`review.backend-architecture.md`](review.backend-architecture.md) |
|
|
22
|
+
| Pagamentos & Integrações | 1 | 4/4 | [`review.payments-integrations.md`](review.payments-integrations.md) |
|
|
23
|
+
| Acquirer Integrations | 2 | 3/4 | [`review.acquirer-integrations.md`](review.acquirer-integrations.md) |
|
|
24
|
+
|
|
25
|
+
## Cobertura
|
|
26
|
+
|
|
27
|
+
| Watchdog | Arquivos revisados | Findings |
|
|
28
|
+
|---|---|---|
|
|
29
|
+
| API & Contratos | 2 | 0 |
|
|
30
|
+
| Arquitetura Backend | 3 | 2 |
|
|
31
|
+
| Pagamentos & Integrações | 4 | 1 |
|
|
32
|
+
| Acquirer Integrations | 3/4 (faltam 1) | 2 |
|
|
33
|
+
|
|
34
|
+
## Conclusão
|
|
35
|
+
|
|
36
|
+
**Status:** ❌ Mudanças Necessárias
|
|
37
|
+
**Resumo:** 2 violações bloqueantes, 1 ponto de atenção, 1 sugestão e 1 nit.
|
|
38
|
+
|
|
17
39
|
## ❌ blocking
|
|
18
40
|
|
|
19
41
|
- **Webhook handler sem verifySignature** — `server/src/services/integrations/acquirer/webhook/handle-charge-event.ts:15` · _Acquirer Integrations, Pagamentos & Integrações_
|
|
@@ -42,17 +64,3 @@
|
|
|
42
64
|
- **Ordem de membros** — `server/src/services/webhook/webhook-retry-service.ts:12` · _Arquitetura Backend_
|
|
43
65
|
Campo privado declarado antes do construtor público.
|
|
44
66
|
**Ação:** Reordenar membros (públicos primeiro).
|
|
45
|
-
|
|
46
|
-
## Cobertura
|
|
47
|
-
|
|
48
|
-
| Watchdog | Arquivos revisados | Findings |
|
|
49
|
-
|---|---|---|
|
|
50
|
-
| API & Contratos | 2 | 0 |
|
|
51
|
-
| Arquitetura Backend | 3 | 1 |
|
|
52
|
-
| Pagamentos & Integrações | 4 | 2 |
|
|
53
|
-
| Acquirer Integrations | 3/4 (faltam 1) | 2 |
|
|
54
|
-
|
|
55
|
-
## Conclusão
|
|
56
|
-
|
|
57
|
-
**Status:** ❌ Mudanças Necessárias
|
|
58
|
-
**Resumo:** 2 violações bloqueantes, 1 ponto de atenção, 1 sugestão.
|
package/src/skill/hunt.md
CHANGED
|
@@ -10,6 +10,11 @@ as regras do projeto ficam em `houndsman.config.ts` + `.houndsman/`.
|
|
|
10
10
|
**Quando usar:** revisar PR antes de merge · code review de feature branch · validar
|
|
11
11
|
mudanças antes de push.
|
|
12
12
|
|
|
13
|
+
> **Harness nativo (opcional):** além deste skill, o CLI tem `houndsman hunt` — o mesmo
|
|
14
|
+
> fluxo executado pelo próprio houndsman, com tools read-only, investigação por evidência
|
|
15
|
+
> e `VERIFY` obrigatório. Use `houndsman hunt --dry-run` para inspecionar sem IA. Detalhes
|
|
16
|
+
> em `docs/HARNESS.md`.
|
|
17
|
+
|
|
13
18
|
## Quem executa o quê
|
|
14
19
|
|
|
15
20
|
- **Você** só invoca o skill: `/houndsman [hunt]`. Não precisa rodar nenhum script à mão.
|
|
@@ -76,6 +81,8 @@ staging dos subagentes em `<HOUNDSMAN_HOME>/work/<reviewId>/`:
|
|
|
76
81
|
| Artefato | Conteúdo |
|
|
77
82
|
|---|---|
|
|
78
83
|
| `classification.json` | Watchdogs ativados por arquivo + status (A/M/D/R) + churn (storage) |
|
|
84
|
+
| `ast-summary.json` | Fatos estruturais + delta por arquivo (AST TS/JS) (storage) |
|
|
85
|
+
| `ast-impact.json` | Importadores reversos e exports públicos alterados (storage) |
|
|
79
86
|
| `candidates.json` | Indícios da pré-análise Jev (regra + arquivo + confiança) (storage) |
|
|
80
87
|
| `briefs/<watchdog>.md` | Instruções prontas para cada subagente (staging + storage, para auditoria) |
|
|
81
88
|
| `manifest.json` | Resumo: watchdogs, arquivos, deletados, status, contexto, Jev, orçamento (storage) |
|
|
@@ -83,6 +90,11 @@ staging dos subagentes em `<HOUNDSMAN_HOME>/work/<reviewId>/`:
|
|
|
83
90
|
> O prepare imprime o caminho absoluto do diretório de briefs e cada brief traz o
|
|
84
91
|
> `outputPath` do JSON que o subagente deve gravar. Briefs e contexto também ficam
|
|
85
92
|
> persistidos no storage para auditoria; o staging é limpo após o `--finalize`.
|
|
93
|
+
>
|
|
94
|
+
> **AST (TS/JS, ligado por padrão):** cada brief ganha a seção `Estrutura (AST)` com
|
|
95
|
+
> símbolos adicionados/removidos/alterados, assinaturas e imports; o impacto reverso
|
|
96
|
+
> (quem importa os arquivos alterados) aparece como mapa de leitura. É fail-open:
|
|
97
|
+
> sem grammar/ABI, a revisão segue só com regex. Desative com `--no-ast`.
|
|
86
98
|
|
|
87
99
|
**Excluídos automaticamente:** lock files, `dist/`, `build/`, `.env*`, imagens, source
|
|
88
100
|
maps (padrões do projeto em `.houndsman/exclusions.ts`).
|
|
@@ -106,7 +118,7 @@ arquivos da PR. Cada brief recebe no máximo `budgets.maxFilesPerBrief` arquivos
|
|
|
106
118
|
|
|
107
119
|
### Pré-análise Jev (Passo 1.5, opcional)
|
|
108
120
|
|
|
109
|
-
Se `
|
|
121
|
+
Se `HOUNDSMAN_TYPE_SAFE_API_KEY` estiver definida, cada arquivo é avaliado pelo modelo **Jev** contra
|
|
110
122
|
as regras atômicas dos watchdogs. Respostas acima do limiar viram **candidatos** em
|
|
111
123
|
`candidates.json` e entram no brief como *warm start* — o subagente **confirma ou refuta**.
|
|
112
124
|
|
|
@@ -122,11 +134,14 @@ arquivos alterados desde a última revisão — e **carrega** os findings dos ar
|
|
|
122
134
|
(carry-over), sem re-revisá-los. O `manifest.json` traz o bloco `incremental` (`from`,
|
|
123
135
|
`changedFiles`, `carried`) e o `review.md` abre com um aviso.
|
|
124
136
|
|
|
125
|
-
- Sem mudanças desde a última revisão → **no-op
|
|
137
|
+
- Sem mudanças desde a última revisão → **no-op**: o prepare não gera briefs nem reescreve
|
|
138
|
+
artefatos (classification, manifest, review.md), e o `--finalize` também vira no-op — pare o
|
|
139
|
+
fluxo aí (nenhum subagente é despachado).
|
|
126
140
|
- Rebase/force-push (histórico reescrito) → cai automaticamente no **review completo**.
|
|
127
141
|
- Forçar completo: `houndsman --full` (ou `--clean`, que também descarta a triagem anterior).
|
|
128
142
|
|
|
129
143
|
> Custo: o LLM só é gasto nos arquivos que mudaram desde a última revisão — não na PR inteira.
|
|
144
|
+
> Re-rodar `/houndsman` no mesmo commit **não** re-revisa a PR; use `--full` para isso.
|
|
130
145
|
|
|
131
146
|
---
|
|
132
147
|
|
|
@@ -135,6 +150,10 @@ arquivos alterados desde a última revisão — e **carrega** os findings dos ar
|
|
|
135
150
|
Um subagente por brief. Despache em **ondas** (ex.: até 8 subagentes por bloco de tool
|
|
136
151
|
calls) — evita estourar limites de taxa quando há muitos watchdogs. O prompt é o próprio brief:
|
|
137
152
|
|
|
153
|
+
> **Heartbeat:** antes de despachar cada onda, rode `houndsman status ping`. A UI usa esse
|
|
154
|
+
> sinal (e não `updatedAt`) para saber que a execução está viva; sem ping por 10 min ela
|
|
155
|
+
> mostra "Timeout na revisão".
|
|
156
|
+
|
|
138
157
|
```
|
|
139
158
|
Leia e execute o brief: <caminho absoluto impresso pelo prepare>/briefs/<watchdog-id>.md
|
|
140
159
|
Você é o watchdog <watchdog-id> do {{projectName}}.
|
|
@@ -158,15 +177,18 @@ houndsman --finalize
|
|
|
158
177
|
Falha com mensagem clara se faltar algum `findings/<watchdog>.json` no staging. Quando todos existem:
|
|
159
178
|
1. Valida o schema de cada JSON
|
|
160
179
|
2. Deduplica achados por `(file, line, rule)` mesclando watchdogs sobrepostos
|
|
161
|
-
3.
|
|
162
|
-
4. Grava o artefato `review.md` no storage + tabela de cobertura
|
|
163
|
-
5. Anexa os candidatos Jev não confirmados em `🔎 Candidatos não verificados` (não bloqueiam)
|
|
164
|
-
6. Agrupa os achados **por arquivo** dentro de cada severidade (navegabilidade em PRs grandes)
|
|
165
|
-
7. Grava um `review.<watchdog>.md` por watchdog com achados e indexa no `review.md`
|
|
180
|
+
3. Grava um `review.<watchdog>.md` por watchdog com achados e indexa no `review.md`
|
|
166
181
|
(**Relatórios por domínio**) — mantém o relatório consolidado enxuto
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
182
|
+
4. Grava o `review.md` abrindo pelo **sumário**: contexto, relatórios por domínio, cobertura e
|
|
183
|
+
conclusão — antes dos achados
|
|
184
|
+
5. Agrupa os achados por severidade (❌ blocking > ⚠️ attention > 💡 suggestion > 🔎 nit) e
|
|
185
|
+
**por arquivo** dentro de cada severidade (navegabilidade em PRs grandes)
|
|
186
|
+
6. Anexa os candidatos Jev não confirmados em `🔎 Candidatos não verificados` ao final
|
|
187
|
+
(não bloqueiam)
|
|
188
|
+
7. Persiste a **triagem** no storage — um `id` curto e um `fingerprint` de conteúdo por
|
|
189
|
+
finding, preservados entre execuções9. Marca como **`done`** os findings que sumiram do relatório (corrigidos manualmente entre
|
|
190
|
+
revisões) e **resolve as conversas correspondentes no GitHub** — só as ainda abertas, e
|
|
191
|
+
falha-aberto (sem `gh`/PR o relatório segue igual)
|
|
170
192
|
Após finalizar, corrija os achados com a capability **`fix`** (`fix.md`): a UI ou os
|
|
171
193
|
comandos `findings` levam do achado à correção.
|
|
172
194
|
|
|
@@ -188,14 +210,6 @@ comandos `findings` levam do achado à correção.
|
|
|
188
210
|
**Resumo das alterações:**
|
|
189
211
|
- ...
|
|
190
212
|
|
|
191
|
-
## ❌ blocking
|
|
192
|
-
### `src/routes/order-route.ts`
|
|
193
|
-
- **<regra>** — `src/routes/order-route.ts:5` · _<watchdogs>_
|
|
194
|
-
<mensagem>
|
|
195
|
-
**Ação:** <ação>
|
|
196
|
-
|
|
197
|
-
## 🔎 Candidatos não verificados (Jev) ← se houver
|
|
198
|
-
|
|
199
213
|
## Relatórios por domínio
|
|
200
214
|
| Watchdog | Achados | Revisados | Relatório |
|
|
201
215
|
|---|---|---|---|
|
|
@@ -206,8 +220,19 @@ comandos `findings` levam do achado à correção.
|
|
|
206
220
|
|
|
207
221
|
## Conclusão
|
|
208
222
|
**Status:** ✅ Aprovado / ⚠️ Aprovado com Ressalvas / ❌ Mudanças Necessárias
|
|
223
|
+
|
|
224
|
+
## ❌ blocking
|
|
225
|
+
### `src/routes/order-route.ts`
|
|
226
|
+
- **<regra>** — `src/routes/order-route.ts:5` · _<watchdogs>_
|
|
227
|
+
<mensagem>
|
|
228
|
+
**Ação:** <ação>
|
|
229
|
+
|
|
230
|
+
## 🔎 Candidatos não verificados (Jev) ← se houver, sempre ao final
|
|
209
231
|
```
|
|
210
232
|
|
|
233
|
+
> O **sumário** (relatórios por domínio, cobertura e conclusão) vem **antes** dos achados;
|
|
234
|
+
> os pontos específicos ficam no fim.
|
|
235
|
+
|
|
211
236
|
---
|
|
212
237
|
|
|
213
238
|
## Fluxo Completo
|
|
@@ -246,11 +271,12 @@ Se a branch não for informada, detecta com `git branch --show-current`. Base do
|
|
|
246
271
|
|---|---|
|
|
247
272
|
| `houndsman context` | Passo 0 — contexto da PR via `gh` |
|
|
248
273
|
| `houndsman` | Passo 1 — preparar (briefs + manifesto; incremental quando possível) |
|
|
274
|
+
| `houndsman status ping` | Passo 2 — heartbeat da execução (antes de cada onda) |
|
|
249
275
|
| `houndsman --finalize` | Passo 3 — gerar o relatório |
|
|
250
276
|
| `houndsman watchdog <id>` | Contexto de um watchdog (`--json`, `--rules`) |
|
|
251
277
|
|
|
252
278
|
Flags do review: `--base` · `--head` · `--branch` · `--clean` · `--full` (força
|
|
253
|
-
completo) · `--no-jev` · `--fail-on-blocking` (com `--finalize`).
|
|
279
|
+
completo) · `--no-jev` · `--no-ast` · `--fail-on-blocking` (com `--finalize`).
|
|
254
280
|
|
|
255
281
|
> Persistência: SQLite global em `<HOUNDSMAN_HOME>/houndsman.db`. O staging dos subagentes
|
|
256
282
|
> (`briefs/`, `findings/`, contexto) vive em `<HOUNDSMAN_HOME>/work/<reviewId>/` e é limpo
|
package/src/skill/verify.md
CHANGED
|
@@ -24,7 +24,7 @@ altera regras.
|
|
|
24
24
|
- **âncora sumida** (`stale`) → provável **resolvido** — mas o trecho pode ter sido reescrito;
|
|
25
25
|
- **arquivo ausente** → fora da verificação (deletado/movido).
|
|
26
26
|
|
|
27
|
-
2. **Tier Jev (opcional, só nos ambíguos).** Com `
|
|
27
|
+
2. **Tier Jev (opcional, só nos ambíguos).** Com `HOUNDSMAN_TYPE_SAFE_API_KEY`, os casos `stale` / sem
|
|
28
28
|
âncora são confirmados pelo LLM sobre um **diff focado** do arquivo (`foundAtSha..HEAD`), uma
|
|
29
29
|
pergunta `noul` por finding. Falha-aberto: sem chave/erro → vale o resultado local.
|
|
30
30
|
|
|
@@ -43,7 +43,8 @@ bun run houndsman findings verify --apply # marca os resolvidos como done (pi
|
|
|
43
43
|
|
|
44
44
|
- Sem `--apply`: **só relatório** (grava o artefato `verify.md` no storage). Nada muda na triagem.
|
|
45
45
|
- Com `--apply`: os findings com status **`resolved`** viram `execState: done` (histórico
|
|
46
|
-
`by: "verify"`)
|
|
46
|
+
`by: "verify"`) e a **thread correspondente é resolvida no GitHub** (quando há comentário e a
|
|
47
|
+
conversa ainda está aberta; fail-open). `persisting` e `uncertain` **não** são tocados.
|
|
47
48
|
|
|
48
49
|
Filtros (como no `findings list`): `--severity`, `--watchdog`, `--file`, `--decision`. `--all`
|
|
49
50
|
inclui ausentes. `--no-jev` desliga o tier LLM. `--fail-on-persisting` sai com código 1 se algum
|