ghagga 2.4.1 ā 2.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 +48 -8
- package/dist/commands/__tests__/review-tui.test.d.ts +11 -0
- package/dist/commands/__tests__/review-tui.test.d.ts.map +1 -0
- package/dist/commands/__tests__/review-tui.test.js +256 -0
- package/dist/commands/__tests__/review-tui.test.js.map +1 -0
- package/dist/commands/health.d.ts +16 -0
- package/dist/commands/health.d.ts.map +1 -0
- package/dist/commands/health.js +139 -0
- package/dist/commands/health.js.map +1 -0
- package/dist/commands/review-output.test.d.ts +10 -0
- package/dist/commands/review-output.test.d.ts.map +1 -0
- package/dist/commands/review-output.test.js +222 -0
- package/dist/commands/review-output.test.js.map +1 -0
- package/dist/commands/review.d.ts +8 -1
- package/dist/commands/review.d.ts.map +1 -1
- package/dist/commands/review.js +139 -22
- package/dist/commands/review.js.map +1 -1
- package/dist/commands/review.test.js +29 -11
- package/dist/commands/review.test.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +45 -9
- package/dist/index.js.map +1 -1
- package/dist/lib/github-api.d.ts +69 -0
- package/dist/lib/github-api.d.ts.map +1 -0
- package/dist/lib/github-api.js +186 -0
- package/dist/lib/github-api.js.map +1 -0
- package/dist/lib/github-api.test.d.ts +2 -0
- package/dist/lib/github-api.test.d.ts.map +1 -0
- package/dist/lib/github-api.test.js +197 -0
- package/dist/lib/github-api.test.js.map +1 -0
- package/dist/lib/oauth.d.ts +2 -2
- package/dist/lib/oauth.d.ts.map +1 -1
- package/dist/lib/oauth.js +2 -2
- package/dist/lib/oauth.js.map +1 -1
- package/dist/lib/oauth.test.js +1 -1
- package/dist/lib/oauth.test.js.map +1 -1
- package/dist/ui/__tests__/tui-extensions.test.d.ts +9 -0
- package/dist/ui/__tests__/tui-extensions.test.d.ts.map +1 -0
- package/dist/ui/__tests__/tui-extensions.test.js +230 -0
- package/dist/ui/__tests__/tui-extensions.test.js.map +1 -0
- package/dist/ui/chalk.d.ts +17 -0
- package/dist/ui/chalk.d.ts.map +1 -0
- package/dist/ui/chalk.js +25 -0
- package/dist/ui/chalk.js.map +1 -0
- package/dist/ui/format.d.ts +21 -1
- package/dist/ui/format.d.ts.map +1 -1
- package/dist/ui/format.js +67 -1
- package/dist/ui/format.js.map +1 -1
- package/dist/ui/sarif.d.ts +6 -0
- package/dist/ui/sarif.d.ts.map +1 -0
- package/dist/ui/sarif.js +5 -0
- package/dist/ui/sarif.js.map +1 -0
- package/dist/ui/theme.d.ts +16 -0
- package/dist/ui/theme.d.ts.map +1 -1
- package/dist/ui/theme.js +16 -0
- package/dist/ui/theme.js.map +1 -1
- package/dist/ui/tui.d.ts +31 -0
- package/dist/ui/tui.d.ts.map +1 -1
- package/dist/ui/tui.js +91 -0
- package/dist/ui/tui.js.map +1 -1
- package/package.json +17 -15
- package/LICENSE +0 -21
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ GHAGGA is a multi-agent AI code reviewer that analyzes your code changes using L
|
|
|
17
17
|
|------|-------|-------|-----------|
|
|
18
18
|
| **simple** | ~2s | Single-pass review | 1 |
|
|
19
19
|
| **workflow** | ~15s | 5 specialist agents + synthesis | 6 |
|
|
20
|
-
| **consensus** | ~7s |
|
|
20
|
+
| **consensus** | ~7s | Same model, three perspectives + algorithmic vote | 3 |
|
|
21
21
|
|
|
22
22
|
## Quick Start
|
|
23
23
|
|
|
@@ -100,11 +100,13 @@ Options:
|
|
|
100
100
|
-p, --provider <provider> LLM provider: github, anthropic, openai, google, ollama, qwen
|
|
101
101
|
--model <model> LLM model identifier
|
|
102
102
|
--api-key <key> LLM provider API key
|
|
103
|
-
-
|
|
103
|
+
-o, --output <format> Output format: markdown, json, sarif (default: "markdown")
|
|
104
|
+
--enhance AI-powered post-analysis enhancement (groups findings, adds fix suggestions)
|
|
105
|
+
--issue <target> Create (new) or update (<number>) a GitHub issue with review results
|
|
104
106
|
-v, --verbose Show detailed progress during review
|
|
105
|
-
--
|
|
106
|
-
--
|
|
107
|
-
--
|
|
107
|
+
--enable-tool <name> Force-enable a specific tool (can be repeated)
|
|
108
|
+
--disable-tool <name> Force-disable a specific tool (can be repeated)
|
|
109
|
+
--list-tools Show all 15 available tools with status
|
|
108
110
|
--no-memory Disable review memory (skip search and persist)
|
|
109
111
|
--memory-backend <type> Memory backend: sqlite (default) or engram
|
|
110
112
|
--staged Review only staged files (for pre-commit hook)
|
|
@@ -142,6 +144,43 @@ ghagga memory clear [--repo <owner/repo>] [--force]
|
|
|
142
144
|
|
|
143
145
|
Memory is stored locally at `~/.config/ghagga/memory.db` (SQLite + FTS5). Observations are automatically extracted from reviews and used to provide context in future reviews.
|
|
144
146
|
|
|
147
|
+
### Deprecated Flags
|
|
148
|
+
|
|
149
|
+
The following flags still work but show deprecation warnings:
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
-f, --format <format> Use --output instead
|
|
153
|
+
--no-semgrep Use --disable-tool semgrep instead
|
|
154
|
+
--no-trivy Use --disable-tool trivy instead
|
|
155
|
+
--no-cpd Use --disable-tool cpd instead
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Health Command
|
|
159
|
+
|
|
160
|
+
Run a project health assessment with scoring, historical trends, and actionable recommendations:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
# Basic health check
|
|
164
|
+
ghagga health
|
|
165
|
+
|
|
166
|
+
# Health check on a specific path
|
|
167
|
+
ghagga health ./src
|
|
168
|
+
|
|
169
|
+
# Show top 10 issues
|
|
170
|
+
ghagga health --top 10
|
|
171
|
+
|
|
172
|
+
# JSON output for CI integration
|
|
173
|
+
ghagga health --output json
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Options:
|
|
177
|
+
|
|
178
|
+
| Option | Default | Description |
|
|
179
|
+
|--------|---------|-------------|
|
|
180
|
+
| `[path]` | `.` | Path to repository or subdirectory |
|
|
181
|
+
| `--top <n>` | `5` | Number of top issues to display |
|
|
182
|
+
| `--output <format>` | `markdown` | Output format (inherits global `--output`) |
|
|
183
|
+
|
|
145
184
|
## BYOK (Bring Your Own Key)
|
|
146
185
|
|
|
147
186
|
Use any supported LLM provider:
|
|
@@ -204,14 +243,15 @@ Create a `.ghagga.json` in your project root:
|
|
|
204
243
|
```json
|
|
205
244
|
{
|
|
206
245
|
"mode": "workflow",
|
|
207
|
-
"
|
|
208
|
-
"
|
|
209
|
-
"enableCpd": true,
|
|
246
|
+
"enabledTools": ["ruff", "bandit"],
|
|
247
|
+
"disabledTools": ["markdownlint"],
|
|
210
248
|
"ignorePatterns": ["*.test.ts", "*.spec.ts"],
|
|
211
249
|
"reviewLevel": "strict"
|
|
212
250
|
}
|
|
213
251
|
```
|
|
214
252
|
|
|
253
|
+
> The legacy fields `enableSemgrep`, `enableTrivy`, `enableCpd` still work but are deprecated. Use `enabledTools`/`disabledTools` arrays instead.
|
|
254
|
+
|
|
215
255
|
## How It Works
|
|
216
256
|
|
|
217
257
|
1. Gets your `git diff` (staged or uncommitted changes; `--staged` uses `git diff --cached`)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for TUI-polished review output.
|
|
3
|
+
*
|
|
4
|
+
* Validates formatBoxSummary, formatToolDivider, and formatMarkdownResult
|
|
5
|
+
* from ui/format.ts ā the pure functions behind the review command's
|
|
6
|
+
* box summary, tool section dividers, and markdown output.
|
|
7
|
+
*
|
|
8
|
+
* All functions are pure (string in, string out) ā no mocking needed.
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=review-tui.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-tui.test.d.ts","sourceRoot":"","sources":["../../../src/commands/__tests__/review-tui.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for TUI-polished review output.
|
|
3
|
+
*
|
|
4
|
+
* Validates formatBoxSummary, formatToolDivider, and formatMarkdownResult
|
|
5
|
+
* from ui/format.ts ā the pure functions behind the review command's
|
|
6
|
+
* box summary, tool section dividers, and markdown output.
|
|
7
|
+
*
|
|
8
|
+
* All functions are pure (string in, string out) ā no mocking needed.
|
|
9
|
+
*/
|
|
10
|
+
import { describe, expect, it } from 'vitest';
|
|
11
|
+
import { formatBoxSummary, formatMarkdownResult, formatToolDivider } from '../../ui/format.js';
|
|
12
|
+
// āāā Helpers āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
13
|
+
function mockResult(overrides) {
|
|
14
|
+
return {
|
|
15
|
+
status: 'PASSED',
|
|
16
|
+
summary: 'All good',
|
|
17
|
+
findings: [],
|
|
18
|
+
staticAnalysis: {
|
|
19
|
+
semgrep: { status: 'skipped', findings: [], executionTimeMs: 0 },
|
|
20
|
+
trivy: { status: 'skipped', findings: [], executionTimeMs: 0 },
|
|
21
|
+
cpd: { status: 'skipped', findings: [], executionTimeMs: 0 },
|
|
22
|
+
},
|
|
23
|
+
memoryContext: null,
|
|
24
|
+
metadata: {
|
|
25
|
+
mode: 'simple',
|
|
26
|
+
model: 'gpt-4o-mini',
|
|
27
|
+
provider: 'github',
|
|
28
|
+
executionTimeMs: 2500,
|
|
29
|
+
tokensUsed: 150,
|
|
30
|
+
toolsRun: ['semgrep', 'trivy'],
|
|
31
|
+
toolsSkipped: ['cpd'],
|
|
32
|
+
},
|
|
33
|
+
...overrides,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
// āāā formatBoxSummary āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
37
|
+
describe('formatBoxSummary', () => {
|
|
38
|
+
it('includes status, time, mode, and model', () => {
|
|
39
|
+
const lines = formatBoxSummary(mockResult());
|
|
40
|
+
const text = lines.join('\n');
|
|
41
|
+
expect(text).toContain('PASSED');
|
|
42
|
+
expect(text).toContain('2.5s');
|
|
43
|
+
expect(text).toContain('simple');
|
|
44
|
+
expect(text).toContain('gpt-4o-mini');
|
|
45
|
+
});
|
|
46
|
+
it('shows finding counts by severity', () => {
|
|
47
|
+
const result = mockResult({
|
|
48
|
+
findings: [
|
|
49
|
+
{ file: 'a.ts', severity: 'critical', category: 'sec', message: 'bad', source: 'semgrep' },
|
|
50
|
+
{ file: 'b.ts', severity: 'high', category: 'sec', message: 'bad', source: 'semgrep' },
|
|
51
|
+
{ file: 'c.ts', severity: 'medium', category: 'quality', message: 'meh', source: 'trivy' },
|
|
52
|
+
],
|
|
53
|
+
});
|
|
54
|
+
const lines = formatBoxSummary(result);
|
|
55
|
+
const text = lines.join('\n');
|
|
56
|
+
expect(text).toContain('3 total');
|
|
57
|
+
expect(text).toContain('critical');
|
|
58
|
+
expect(text).toContain('high');
|
|
59
|
+
expect(text).toContain('medium');
|
|
60
|
+
});
|
|
61
|
+
it('shows clean message when no findings', () => {
|
|
62
|
+
const lines = formatBoxSummary(mockResult());
|
|
63
|
+
const text = lines.join('\n');
|
|
64
|
+
expect(text).toContain('0');
|
|
65
|
+
expect(text).toContain('clean');
|
|
66
|
+
});
|
|
67
|
+
it('lists tools run', () => {
|
|
68
|
+
const lines = formatBoxSummary(mockResult());
|
|
69
|
+
const text = lines.join('\n');
|
|
70
|
+
expect(text).toContain('semgrep');
|
|
71
|
+
expect(text).toContain('trivy');
|
|
72
|
+
});
|
|
73
|
+
it('includes token count', () => {
|
|
74
|
+
const lines = formatBoxSummary(mockResult());
|
|
75
|
+
const text = lines.join('\n');
|
|
76
|
+
expect(text).toContain('150');
|
|
77
|
+
});
|
|
78
|
+
it('does not show tools line when no tools ran', () => {
|
|
79
|
+
const result = mockResult({
|
|
80
|
+
metadata: {
|
|
81
|
+
mode: 'simple',
|
|
82
|
+
model: 'gpt-4o-mini',
|
|
83
|
+
provider: 'github',
|
|
84
|
+
executionTimeMs: 1000,
|
|
85
|
+
tokensUsed: 50,
|
|
86
|
+
toolsRun: [],
|
|
87
|
+
toolsSkipped: [],
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
const lines = formatBoxSummary(result);
|
|
91
|
+
const text = lines.join('\n');
|
|
92
|
+
expect(text).not.toContain('Tools:');
|
|
93
|
+
});
|
|
94
|
+
it('shows all five severity levels when present', () => {
|
|
95
|
+
const result = mockResult({
|
|
96
|
+
findings: [
|
|
97
|
+
{ file: 'a.ts', severity: 'critical', category: 'sec', message: 'x', source: 'ai' },
|
|
98
|
+
{ file: 'b.ts', severity: 'high', category: 'sec', message: 'x', source: 'ai' },
|
|
99
|
+
{ file: 'c.ts', severity: 'medium', category: 'sec', message: 'x', source: 'ai' },
|
|
100
|
+
{ file: 'd.ts', severity: 'low', category: 'sec', message: 'x', source: 'ai' },
|
|
101
|
+
{ file: 'e.ts', severity: 'info', category: 'sec', message: 'x', source: 'ai' },
|
|
102
|
+
],
|
|
103
|
+
});
|
|
104
|
+
const lines = formatBoxSummary(result);
|
|
105
|
+
const text = lines.join('\n');
|
|
106
|
+
expect(text).toContain('5 total');
|
|
107
|
+
expect(text).toContain('critical');
|
|
108
|
+
expect(text).toContain('high');
|
|
109
|
+
expect(text).toContain('medium');
|
|
110
|
+
expect(text).toContain('low');
|
|
111
|
+
expect(text).toContain('info');
|
|
112
|
+
});
|
|
113
|
+
it('formats FAILED status correctly', () => {
|
|
114
|
+
const result = mockResult({ status: 'FAILED' });
|
|
115
|
+
const lines = formatBoxSummary(result);
|
|
116
|
+
const text = lines.join('\n');
|
|
117
|
+
expect(text).toContain('FAILED');
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
// āāā formatToolDivider āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
121
|
+
describe('formatToolDivider', () => {
|
|
122
|
+
it('contains the label and dash characters', () => {
|
|
123
|
+
const divider = formatToolDivider('Semgrep (3)');
|
|
124
|
+
expect(divider).toContain('Semgrep (3)');
|
|
125
|
+
expect(divider).toContain('ā');
|
|
126
|
+
});
|
|
127
|
+
it('has consistent structure with āāā prefix before label', () => {
|
|
128
|
+
const divider = formatToolDivider('Trivy');
|
|
129
|
+
expect(divider).toMatch(/āāā Trivy ā+$/);
|
|
130
|
+
});
|
|
131
|
+
it('pads to consistent width with trailing dashes', () => {
|
|
132
|
+
const short = formatToolDivider('A');
|
|
133
|
+
const long = formatToolDivider('A longer label here');
|
|
134
|
+
// Both should contain the āāā prefix pattern
|
|
135
|
+
expect(short).toContain('āāā A ');
|
|
136
|
+
expect(long).toContain('āāā A longer label here ');
|
|
137
|
+
// Short label gets more trailing dashes
|
|
138
|
+
const shortDashCount = (short.match(/ā/g) ?? []).length;
|
|
139
|
+
const longDashCount = (long.match(/ā/g) ?? []).length;
|
|
140
|
+
expect(shortDashCount).toBeGreaterThan(longDashCount);
|
|
141
|
+
});
|
|
142
|
+
it('starts with a newline for visual separation', () => {
|
|
143
|
+
const divider = formatToolDivider('Test');
|
|
144
|
+
expect(divider.startsWith('\n')).toBe(true);
|
|
145
|
+
});
|
|
146
|
+
it('handles empty label gracefully', () => {
|
|
147
|
+
const divider = formatToolDivider('');
|
|
148
|
+
expect(divider).toContain('ā');
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
// āāā formatMarkdownResult āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
152
|
+
describe('formatMarkdownResult', () => {
|
|
153
|
+
it('contains tool dividers when findings from multiple sources', () => {
|
|
154
|
+
const result = mockResult({
|
|
155
|
+
findings: [
|
|
156
|
+
{ file: 'a.ts', severity: 'high', category: 'sec', message: 'issue1', source: 'semgrep' },
|
|
157
|
+
{ file: 'b.ts', severity: 'medium', category: 'vuln', message: 'issue2', source: 'trivy' },
|
|
158
|
+
],
|
|
159
|
+
});
|
|
160
|
+
const output = formatMarkdownResult(result);
|
|
161
|
+
// Uses ā tool dividers (not markdown ### headings)
|
|
162
|
+
expect(output).toContain('ā');
|
|
163
|
+
// Both tool labels should appear
|
|
164
|
+
expect(output).toContain('Semgrep');
|
|
165
|
+
expect(output).toContain('Trivy');
|
|
166
|
+
});
|
|
167
|
+
it('shows no findings message when findings are empty', () => {
|
|
168
|
+
const output = formatMarkdownResult(mockResult());
|
|
169
|
+
expect(output).toContain('No findings');
|
|
170
|
+
});
|
|
171
|
+
it('includes header with status and review branding', () => {
|
|
172
|
+
const output = formatMarkdownResult(mockResult());
|
|
173
|
+
expect(output).toContain('GHAGGA Code Review');
|
|
174
|
+
expect(output).toContain('PASSED');
|
|
175
|
+
});
|
|
176
|
+
it('includes execution metadata', () => {
|
|
177
|
+
const output = formatMarkdownResult(mockResult());
|
|
178
|
+
expect(output).toContain('Mode: simple');
|
|
179
|
+
expect(output).toContain('Model: gpt-4o-mini');
|
|
180
|
+
expect(output).toContain('2.5s');
|
|
181
|
+
expect(output).toContain('150');
|
|
182
|
+
});
|
|
183
|
+
it('renders findings with severity, category, and message', () => {
|
|
184
|
+
const result = mockResult({
|
|
185
|
+
findings: [
|
|
186
|
+
{
|
|
187
|
+
file: 'src/app.ts',
|
|
188
|
+
line: 42,
|
|
189
|
+
severity: 'critical',
|
|
190
|
+
category: 'security',
|
|
191
|
+
message: 'SQL injection vulnerability',
|
|
192
|
+
source: 'semgrep',
|
|
193
|
+
},
|
|
194
|
+
],
|
|
195
|
+
});
|
|
196
|
+
const output = formatMarkdownResult(result);
|
|
197
|
+
expect(output).toContain('CRITICAL');
|
|
198
|
+
expect(output).toContain('security');
|
|
199
|
+
expect(output).toContain('SQL injection vulnerability');
|
|
200
|
+
expect(output).toContain('src/app.ts:42');
|
|
201
|
+
});
|
|
202
|
+
it('renders suggestions when present', () => {
|
|
203
|
+
const result = mockResult({
|
|
204
|
+
findings: [
|
|
205
|
+
{
|
|
206
|
+
file: 'x.ts',
|
|
207
|
+
severity: 'medium',
|
|
208
|
+
category: 'perf',
|
|
209
|
+
message: 'Slow query',
|
|
210
|
+
suggestion: 'Add an index',
|
|
211
|
+
source: 'ai',
|
|
212
|
+
},
|
|
213
|
+
],
|
|
214
|
+
});
|
|
215
|
+
const output = formatMarkdownResult(result);
|
|
216
|
+
expect(output).toContain('Add an index');
|
|
217
|
+
});
|
|
218
|
+
it('orders semgrep before trivy before ai findings', () => {
|
|
219
|
+
const result = mockResult({
|
|
220
|
+
findings: [
|
|
221
|
+
{ file: 'a.ts', severity: 'high', category: 'sec', message: 'ai issue', source: 'ai' },
|
|
222
|
+
{
|
|
223
|
+
file: 'b.ts',
|
|
224
|
+
severity: 'medium',
|
|
225
|
+
category: 'sec',
|
|
226
|
+
message: 'trivy issue',
|
|
227
|
+
source: 'trivy',
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
file: 'c.ts',
|
|
231
|
+
severity: 'low',
|
|
232
|
+
category: 'sec',
|
|
233
|
+
message: 'semgrep issue',
|
|
234
|
+
source: 'semgrep',
|
|
235
|
+
},
|
|
236
|
+
],
|
|
237
|
+
});
|
|
238
|
+
const output = formatMarkdownResult(result);
|
|
239
|
+
const semgrepIdx = output.indexOf('Semgrep');
|
|
240
|
+
const trivyIdx = output.indexOf('Trivy');
|
|
241
|
+
const aiIdx = output.indexOf('AI Review');
|
|
242
|
+
expect(semgrepIdx).toBeLessThan(trivyIdx);
|
|
243
|
+
expect(trivyIdx).toBeLessThan(aiIdx);
|
|
244
|
+
});
|
|
245
|
+
it('includes static analysis section when tools ran', () => {
|
|
246
|
+
const output = formatMarkdownResult(mockResult());
|
|
247
|
+
expect(output).toContain('Static Analysis');
|
|
248
|
+
expect(output).toContain('semgrep, trivy');
|
|
249
|
+
expect(output).toContain('cpd');
|
|
250
|
+
});
|
|
251
|
+
it('includes the powered-by footer', () => {
|
|
252
|
+
const output = formatMarkdownResult(mockResult());
|
|
253
|
+
expect(output).toContain('Powered by GHAGGA');
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
//# sourceMappingURL=review-tui.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-tui.test.js","sourceRoot":"","sources":["../../../src/commands/__tests__/review-tui.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Health command ā quick project health check with scoring and trends.
|
|
3
|
+
*
|
|
4
|
+
* Does NOT require authentication. Runs always-on static analysis
|
|
5
|
+
* tools locally and computes a health score with trends.
|
|
6
|
+
*/
|
|
7
|
+
export interface HealthOptions {
|
|
8
|
+
/** Output format: 'json' or default (styled TUI). */
|
|
9
|
+
output?: string;
|
|
10
|
+
/** Plain mode. */
|
|
11
|
+
plain?: boolean;
|
|
12
|
+
/** Number of top issues to show (default: 5). */
|
|
13
|
+
top?: number;
|
|
14
|
+
}
|
|
15
|
+
export declare function healthCommand(targetPath: string, options: HealthOptions): Promise<void>;
|
|
16
|
+
//# sourceMappingURL=health.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/commands/health.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAwBH,MAAM,WAAW,aAAa;IAC5B,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kBAAkB;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,iDAAiD;IACjD,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAaD,wBAAsB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA+F7F"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Health command ā quick project health check with scoring and trends.
|
|
3
|
+
*
|
|
4
|
+
* Does NOT require authentication. Runs always-on static analysis
|
|
5
|
+
* tools locally and computes a health score with trends.
|
|
6
|
+
*/
|
|
7
|
+
import { resolve } from 'node:path';
|
|
8
|
+
import { computeHealthScore, computeTrend, createNodeExecutionContext, formatTopIssues, generateRecommendations, initializeDefaultTools, loadHistory, resolveActivatedTools, runTools, saveHistory, toolRegistry, } from 'ghagga-core';
|
|
9
|
+
import { getConfigDir } from '../lib/config.js';
|
|
10
|
+
import { resolveProjectId } from '../lib/git.js';
|
|
11
|
+
import { formatHealthScore, formatSeverityLine } from '../ui/format.js';
|
|
12
|
+
import * as tui from '../ui/tui.js';
|
|
13
|
+
// āāā Constants āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
14
|
+
/** Direction arrows for trend display. */
|
|
15
|
+
const TREND_ARROWS = {
|
|
16
|
+
up: 'ā',
|
|
17
|
+
down: 'ā',
|
|
18
|
+
unchanged: 'ā',
|
|
19
|
+
};
|
|
20
|
+
// āāā Main Command āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
21
|
+
export async function healthCommand(targetPath, options) {
|
|
22
|
+
const repoPath = resolve(targetPath);
|
|
23
|
+
const top = options.top ?? 5;
|
|
24
|
+
try {
|
|
25
|
+
// Step 1: Initialize tool registry
|
|
26
|
+
initializeDefaultTools();
|
|
27
|
+
if (!options.output) {
|
|
28
|
+
tui.intro('š„ GHAGGA Health Check');
|
|
29
|
+
}
|
|
30
|
+
// Step 2: Run static analysis (always-on tools only)
|
|
31
|
+
if (!options.output) {
|
|
32
|
+
tui.log.step('Running static analysis...');
|
|
33
|
+
}
|
|
34
|
+
const alwaysOnTools = resolveActivatedTools({
|
|
35
|
+
registry: toolRegistry,
|
|
36
|
+
files: [],
|
|
37
|
+
enabledTools: toolRegistry
|
|
38
|
+
.getAll()
|
|
39
|
+
.filter((t) => t.tier === 'always-on')
|
|
40
|
+
.map((t) => t.name),
|
|
41
|
+
});
|
|
42
|
+
const ctx = createNodeExecutionContext();
|
|
43
|
+
const staticResult = await runTools(ctx, alwaysOnTools, repoPath, []);
|
|
44
|
+
// Step 3: Collect all findings
|
|
45
|
+
const allFindings = [];
|
|
46
|
+
const toolsRun = [];
|
|
47
|
+
for (const [toolName, toolResult] of Object.entries(staticResult)) {
|
|
48
|
+
if (toolResult.status === 'success' || toolResult.status === 'error') {
|
|
49
|
+
toolsRun.push(toolName);
|
|
50
|
+
}
|
|
51
|
+
allFindings.push(...toolResult.findings);
|
|
52
|
+
}
|
|
53
|
+
// Step 4: Compute health score
|
|
54
|
+
const healthScore = computeHealthScore(allFindings);
|
|
55
|
+
// Step 5: Load history and compute trend
|
|
56
|
+
const projectPath = resolveProjectId(repoPath);
|
|
57
|
+
const configDir = getConfigDir();
|
|
58
|
+
const history = loadHistory(configDir, projectPath);
|
|
59
|
+
const trend = computeTrend(healthScore.score, history);
|
|
60
|
+
// Step 6: Generate recommendations
|
|
61
|
+
const recommendations = generateRecommendations(allFindings, top);
|
|
62
|
+
// Step 7: Get top issues
|
|
63
|
+
const topIssues = formatTopIssues(allFindings, top);
|
|
64
|
+
// Step 8: Output
|
|
65
|
+
if (options.output === 'json') {
|
|
66
|
+
const result = {
|
|
67
|
+
score: healthScore,
|
|
68
|
+
trend,
|
|
69
|
+
recommendations,
|
|
70
|
+
topIssues: topIssues.map((f) => ({
|
|
71
|
+
file: f.file,
|
|
72
|
+
line: f.line,
|
|
73
|
+
severity: f.severity,
|
|
74
|
+
category: f.category,
|
|
75
|
+
message: f.message,
|
|
76
|
+
source: f.source,
|
|
77
|
+
})),
|
|
78
|
+
toolsRun,
|
|
79
|
+
timestamp: new Date().toISOString(),
|
|
80
|
+
};
|
|
81
|
+
console.log(JSON.stringify(result, null, 2));
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
renderStyledOutput(healthScore, trend, topIssues, recommendations, toolsRun);
|
|
85
|
+
}
|
|
86
|
+
// Step 9: Save history
|
|
87
|
+
const entry = {
|
|
88
|
+
timestamp: new Date().toISOString(),
|
|
89
|
+
score: healthScore.score,
|
|
90
|
+
findingCounts: { ...healthScore.findingCounts },
|
|
91
|
+
toolsRun,
|
|
92
|
+
projectPath,
|
|
93
|
+
};
|
|
94
|
+
saveHistory(configDir, entry);
|
|
95
|
+
if (!options.output) {
|
|
96
|
+
tui.outro('Health check complete');
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
101
|
+
tui.log.error(`\nā Health check failed: ${message}`);
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// āāā Styled Output āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
106
|
+
function renderStyledOutput(healthScore, trend, topIssues, recommendations, toolsRun) {
|
|
107
|
+
// Score box
|
|
108
|
+
const scoreLines = formatHealthScore(healthScore.score, healthScore.grade);
|
|
109
|
+
// Add trend info
|
|
110
|
+
if (trend.direction) {
|
|
111
|
+
const arrow = TREND_ARROWS[trend.direction] ?? '';
|
|
112
|
+
const deltaStr = trend.delta !== null ? (trend.delta > 0 ? `+${trend.delta}` : String(trend.delta)) : '';
|
|
113
|
+
scoreLines.push(`Trend: ${arrow} ${deltaStr} (previous: ${trend.previous})`);
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
scoreLines.push('Trend: First run ā no history yet');
|
|
117
|
+
}
|
|
118
|
+
scoreLines.push('');
|
|
119
|
+
scoreLines.push(`Tools: ${toolsRun.join(', ')}`);
|
|
120
|
+
tui.log.message(tui.box('Health Score', scoreLines));
|
|
121
|
+
// Top issues
|
|
122
|
+
if (topIssues.length > 0) {
|
|
123
|
+
tui.log.message('');
|
|
124
|
+
tui.log.message(tui.divider('Top Issues'));
|
|
125
|
+
for (const issue of topIssues) {
|
|
126
|
+
tui.log.message(` ${formatSeverityLine(issue)}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// Recommendations
|
|
130
|
+
if (recommendations.length > 0) {
|
|
131
|
+
tui.log.message('');
|
|
132
|
+
tui.log.message(tui.divider('Recommendations'));
|
|
133
|
+
for (const rec of recommendations) {
|
|
134
|
+
const impact = rec.impact === 'high' ? 'š“' : rec.impact === 'medium' ? 'š”' : 'š¢';
|
|
135
|
+
tui.log.message(` ${impact} [${rec.category}] ${rec.action}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=health.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/commands/health.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output format routing tests for the review command.
|
|
3
|
+
*
|
|
4
|
+
* Tests that --output json / sarif / markdown produce correct output
|
|
5
|
+
* and that TUI decorations are suppressed when --output is set.
|
|
6
|
+
*
|
|
7
|
+
* Uses the same mock patterns as review.test.ts.
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=review-output.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-output.test.d.ts","sourceRoot":"","sources":["../../src/commands/review-output.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
|