ghagga 3.2.0 → 3.4.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 +1 -1
- package/dist/commands/audit.js +6 -2
- package/dist/commands/audit.js.map +1 -1
- package/dist/commands/index-cmd.d.ts +49 -0
- package/dist/commands/index-cmd.d.ts.map +1 -0
- package/dist/commands/index-cmd.js +367 -0
- package/dist/commands/index-cmd.js.map +1 -0
- package/dist/commands/index-cmd.test.d.ts +17 -0
- package/dist/commands/index-cmd.test.d.ts.map +1 -0
- package/dist/commands/index-cmd.test.js +535 -0
- package/dist/commands/index-cmd.test.js.map +1 -0
- package/dist/commands/indexer-registry.d.ts +93 -0
- package/dist/commands/indexer-registry.d.ts.map +1 -0
- package/dist/commands/indexer-registry.js +342 -0
- package/dist/commands/indexer-registry.js.map +1 -0
- package/dist/commands/indexer-registry.test.d.ts +10 -0
- package/dist/commands/indexer-registry.test.d.ts.map +1 -0
- package/dist/commands/indexer-registry.test.js +538 -0
- package/dist/commands/indexer-registry.test.js.map +1 -0
- package/dist/commands/review-blast-radius.test.d.ts +13 -0
- package/dist/commands/review-blast-radius.test.d.ts.map +1 -0
- package/dist/commands/review-blast-radius.test.js +179 -0
- package/dist/commands/review-blast-radius.test.js.map +1 -0
- package/dist/commands/review.d.ts +136 -1
- package/dist/commands/review.d.ts.map +1 -1
- package/dist/commands/review.js +357 -2
- package/dist/commands/review.js.map +1 -1
- package/dist/commands/review.test.js +527 -1
- package/dist/commands/review.test.js.map +1 -1
- package/dist/commands/triage.d.ts +14 -0
- package/dist/commands/triage.d.ts.map +1 -0
- package/dist/commands/triage.js +248 -0
- package/dist/commands/triage.js.map +1 -0
- package/dist/commands/triage.test.d.ts +8 -0
- package/dist/commands/triage.test.d.ts.map +1 -0
- package/dist/commands/triage.test.js +272 -0
- package/dist/commands/triage.test.js.map +1 -0
- package/dist/index.js +38 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/cli-github-client-port.d.ts +2 -0
- package/dist/lib/cli-github-client-port.d.ts.map +1 -1
- package/dist/lib/cli-github-client-port.js +12 -0
- package/dist/lib/cli-github-client-port.js.map +1 -1
- package/dist/ui/__tests__/theme.test.js +3 -2
- package/dist/ui/__tests__/theme.test.js.map +1 -1
- package/dist/ui/theme.d.ts.map +1 -1
- package/dist/ui/theme.js +1 -0
- package/dist/ui/theme.js.map +1 -1
- package/package.json +11 -10
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the blast-radius pure seams extracted from `reviewCommand`
|
|
3
|
+
* (design v2 D9): `resolveBlastRadiusEnabled`, `checkGraphStaleness`,
|
|
4
|
+
* `computeUncoveredLanguages`.
|
|
5
|
+
*
|
|
6
|
+
* `resolveBlastRadiusEnabled` touches the real filesystem (existsSync) — a
|
|
7
|
+
* REAL temp dir (mkdtempSync) is used, NOT a mocked `node:fs`, so the actual
|
|
8
|
+
* repoPath-relative resolution is exercised (CRITICAL-2 regression guard).
|
|
9
|
+
* This file deliberately does NOT `vi.mock('node:fs')` (unlike review.test.ts)
|
|
10
|
+
* to keep that guarantee honest.
|
|
11
|
+
*/
|
|
12
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
13
|
+
import { tmpdir } from 'node:os';
|
|
14
|
+
import { join } from 'node:path';
|
|
15
|
+
import { GRAPH_VERSION } from 'ghagga-core';
|
|
16
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
17
|
+
import { checkGraphStaleness, computeUncoveredLanguages, resolveBlastRadiusEnabled, } from './review.js';
|
|
18
|
+
// ─── resolveBlastRadiusEnabled ───────────────────────────────────
|
|
19
|
+
describe('resolveBlastRadiusEnabled', () => {
|
|
20
|
+
let repoPath;
|
|
21
|
+
let otherCwd;
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
repoPath = mkdtempSync(join(tmpdir(), 'ghagga-blast-radius-repo-'));
|
|
24
|
+
otherCwd = mkdtempSync(join(tmpdir(), 'ghagga-blast-radius-cwd-'));
|
|
25
|
+
});
|
|
26
|
+
afterEach(() => {
|
|
27
|
+
rmSync(repoPath, { recursive: true, force: true });
|
|
28
|
+
rmSync(otherCwd, { recursive: true, force: true });
|
|
29
|
+
});
|
|
30
|
+
function withGraph() {
|
|
31
|
+
mkdirSync(join(repoPath, '.ghagga'), { recursive: true });
|
|
32
|
+
writeFileSync(join(repoPath, '.ghagga', 'graph.json'), '{}');
|
|
33
|
+
}
|
|
34
|
+
it('auto-enables when .ghagga/graph.json exists under repoPath', () => {
|
|
35
|
+
withGraph();
|
|
36
|
+
const result = resolveBlastRadiusEnabled(repoPath, {}, {});
|
|
37
|
+
expect(result).toBe(true);
|
|
38
|
+
});
|
|
39
|
+
it('stays off when no graph.json exists', () => {
|
|
40
|
+
const result = resolveBlastRadiusEnabled(repoPath, {}, {});
|
|
41
|
+
expect(result).toBe(false);
|
|
42
|
+
});
|
|
43
|
+
it('resolves against repoPath, NOT process.cwd() (CRITICAL-2)', () => {
|
|
44
|
+
withGraph();
|
|
45
|
+
const originalCwd = process.cwd();
|
|
46
|
+
try {
|
|
47
|
+
process.chdir(otherCwd);
|
|
48
|
+
// The graph lives under repoPath, not the (different) current cwd —
|
|
49
|
+
// the v1 bug used resolve('.') and would have returned false here.
|
|
50
|
+
const result = resolveBlastRadiusEnabled(repoPath, {}, {});
|
|
51
|
+
expect(result).toBe(true);
|
|
52
|
+
}
|
|
53
|
+
finally {
|
|
54
|
+
process.chdir(originalCwd);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
it('--no-blast-radius (blastRadius: false) wins over an existing graph', () => {
|
|
58
|
+
withGraph();
|
|
59
|
+
const result = resolveBlastRadiusEnabled(repoPath, { blastRadius: false }, {});
|
|
60
|
+
expect(result).toBe(false);
|
|
61
|
+
});
|
|
62
|
+
it('.ghagga.json enableBlastRadius: false wins over an existing graph', () => {
|
|
63
|
+
withGraph();
|
|
64
|
+
const result = resolveBlastRadiusEnabled(repoPath, {}, { enableBlastRadius: false });
|
|
65
|
+
expect(result).toBe(false);
|
|
66
|
+
});
|
|
67
|
+
it('.ghagga.json enableBlastRadius: true wins even without a graph', () => {
|
|
68
|
+
const result = resolveBlastRadiusEnabled(repoPath, {}, { enableBlastRadius: true });
|
|
69
|
+
expect(result).toBe(true);
|
|
70
|
+
});
|
|
71
|
+
it('explicit --no-blast-radius overrides .ghagga.json enableBlastRadius: true', () => {
|
|
72
|
+
const result = resolveBlastRadiusEnabled(repoPath, { blastRadius: false }, { enableBlastRadius: true });
|
|
73
|
+
expect(result).toBe(false);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
// ─── checkGraphStaleness ──────────────────────────────────────────
|
|
77
|
+
describe('checkGraphStaleness', () => {
|
|
78
|
+
function makeMetadata(overrides = {}) {
|
|
79
|
+
return {
|
|
80
|
+
lastIndexedCommit: 'abc123',
|
|
81
|
+
lastIndexedAt: new Date().toISOString(),
|
|
82
|
+
schemaVersion: GRAPH_VERSION,
|
|
83
|
+
fileCount: 1,
|
|
84
|
+
languages: ['typescript'],
|
|
85
|
+
indexDurationMs: 10,
|
|
86
|
+
...overrides,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
it('returns no warnings when metadata is fresh and HEAD matches', () => {
|
|
90
|
+
const metadata = makeMetadata({ lastIndexedCommit: 'abc123' });
|
|
91
|
+
expect(checkGraphStaleness(metadata, 'abc123')).toEqual([]);
|
|
92
|
+
});
|
|
93
|
+
it('warns on HEAD mismatch', () => {
|
|
94
|
+
const metadata = makeMetadata({ lastIndexedCommit: 'abc123' });
|
|
95
|
+
const warnings = checkGraphStaleness(metadata, 'def456');
|
|
96
|
+
expect(warnings.some((w) => w.kind === 'head-mismatch')).toBe(true);
|
|
97
|
+
});
|
|
98
|
+
it('skips the HEAD-mismatch check when currentHead is empty (non-git/detached)', () => {
|
|
99
|
+
const metadata = makeMetadata({ lastIndexedCommit: 'abc123' });
|
|
100
|
+
const warnings = checkGraphStaleness(metadata, '');
|
|
101
|
+
expect(warnings.some((w) => w.kind === 'head-mismatch')).toBe(false);
|
|
102
|
+
});
|
|
103
|
+
it('warns on age > 7 days', () => {
|
|
104
|
+
const thirtyDaysAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString();
|
|
105
|
+
const metadata = makeMetadata({ lastIndexedCommit: 'abc123', lastIndexedAt: thirtyDaysAgo });
|
|
106
|
+
const warnings = checkGraphStaleness(metadata, 'abc123');
|
|
107
|
+
expect(warnings.some((w) => w.kind === 'stale-age')).toBe(true);
|
|
108
|
+
});
|
|
109
|
+
it('warns distinctly when metadata is null (B-005)', () => {
|
|
110
|
+
const warnings = checkGraphStaleness(null, 'abc123');
|
|
111
|
+
expect(warnings).toHaveLength(1);
|
|
112
|
+
expect(warnings[0]?.kind).toBe('no-metadata');
|
|
113
|
+
});
|
|
114
|
+
it('warns on graphVersion mismatch (B-003)', () => {
|
|
115
|
+
const metadata = makeMetadata({ lastIndexedCommit: 'abc123', graphVersion: GRAPH_VERSION + 1 });
|
|
116
|
+
const warnings = checkGraphStaleness(metadata, 'abc123');
|
|
117
|
+
expect(warnings.some((w) => w.kind === 'version-mismatch')).toBe(true);
|
|
118
|
+
});
|
|
119
|
+
it('does not warn on graphVersion match', () => {
|
|
120
|
+
const metadata = makeMetadata({ lastIndexedCommit: 'abc123', graphVersion: GRAPH_VERSION });
|
|
121
|
+
const warnings = checkGraphStaleness(metadata, 'abc123');
|
|
122
|
+
expect(warnings.some((w) => w.kind === 'version-mismatch')).toBe(false);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
// ─── computeUncoveredLanguages ────────────────────────────────────
|
|
126
|
+
describe('computeUncoveredLanguages', () => {
|
|
127
|
+
function makeGraph(nodeLanguages) {
|
|
128
|
+
return {
|
|
129
|
+
version: GRAPH_VERSION,
|
|
130
|
+
rootDir: '.',
|
|
131
|
+
nodes: Object.fromEntries(Object.entries(nodeLanguages).map(([path, language]) => [
|
|
132
|
+
path,
|
|
133
|
+
{
|
|
134
|
+
hash: 'h',
|
|
135
|
+
// biome-ignore lint/suspicious/noExplicitAny: fixture language is dynamic
|
|
136
|
+
language: language,
|
|
137
|
+
imports: [],
|
|
138
|
+
exports: [],
|
|
139
|
+
calls: [],
|
|
140
|
+
isTest: false,
|
|
141
|
+
},
|
|
142
|
+
])),
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
it('flags a changed file whose language has zero graph coverage', () => {
|
|
146
|
+
const graph = makeGraph({ 'src/main.go': 'go' });
|
|
147
|
+
const uncovered = computeUncoveredLanguages(graph, ['app.py']);
|
|
148
|
+
expect(uncovered).toContain('python');
|
|
149
|
+
});
|
|
150
|
+
it('does not flag a changed file whose language IS covered', () => {
|
|
151
|
+
const graph = makeGraph({ 'src/main.go': 'go' });
|
|
152
|
+
const uncovered = computeUncoveredLanguages(graph, ['src/other.go']);
|
|
153
|
+
expect(uncovered).not.toContain('go');
|
|
154
|
+
});
|
|
155
|
+
it('regex-fallback graph (languages populated from real nodes) is NOT all-flagged (CRITICAL-1)', () => {
|
|
156
|
+
// A regex-fallback-built graph still has real per-file `language` on
|
|
157
|
+
// every node (unlike dispatch's `indexedLanguages`, which is empty for
|
|
158
|
+
// the regex path) — so coverage must be computed from graph CONTENTS.
|
|
159
|
+
const graph = makeGraph({ 'src/a.ts': 'typescript', 'src/b.py': 'python' });
|
|
160
|
+
const uncovered = computeUncoveredLanguages(graph, ['src/a.ts', 'src/b.py']);
|
|
161
|
+
expect(uncovered).toEqual([]);
|
|
162
|
+
});
|
|
163
|
+
it('flags a subpackage-only language not present anywhere in the graph', () => {
|
|
164
|
+
const graph = makeGraph({ 'src/main.go': 'go' });
|
|
165
|
+
const uncovered = computeUncoveredLanguages(graph, [
|
|
166
|
+
'packages/api/requirements.txt',
|
|
167
|
+
'src/main.go',
|
|
168
|
+
]);
|
|
169
|
+
// requirements.txt has no detectable language extension — must not crash
|
|
170
|
+
// and must not be spuriously flagged as a language.
|
|
171
|
+
expect(uncovered).toEqual([]);
|
|
172
|
+
});
|
|
173
|
+
it('flags multiple distinct uncovered languages without duplicates', () => {
|
|
174
|
+
const graph = makeGraph({ 'src/main.go': 'go' });
|
|
175
|
+
const uncovered = computeUncoveredLanguages(graph, ['a.py', 'b.py', 'c.rs']);
|
|
176
|
+
expect(uncovered.sort()).toEqual(['python', 'rust']);
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
//# sourceMappingURL=review-blast-radius.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-blast-radius.test.js","sourceRoot":"","sources":["../../src/commands/review-blast-radius.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EACL,mBAAmB,EACnB,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,aAAa,CAAC;AAErB,oEAAoE;AAEpE,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACzC,IAAI,QAAgB,CAAC;IACrB,IAAI,QAAgB,CAAC;IAErB,UAAU,CAAC,GAAG,EAAE;QACd,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,2BAA2B,CAAC,CAAC,CAAC;QACpE,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,0BAA0B,CAAC,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,MAAM,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,SAAS,SAAS;QAChB,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,YAAY,CAAC,EAAE,IAAI,CAAC,CAAC;IAC/D,CAAC;IAED,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,SAAS,EAAE,CAAC;QACZ,MAAM,MAAM,GAAG,yBAAyB,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;QAC3D,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,MAAM,GAAG,yBAAyB,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;QAC3D,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,SAAS,EAAE,CAAC;QACZ,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QAClC,IAAI,CAAC;YACH,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YACxB,oEAAoE;YACpE,mEAAmE;YACnE,MAAM,MAAM,GAAG,yBAAyB,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;YAC3D,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;gBAAS,CAAC;YACT,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oEAAoE,EAAE,GAAG,EAAE;QAC5E,SAAS,EAAE,CAAC;QACZ,MAAM,MAAM,GAAG,yBAAyB,CAAC,QAAQ,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;QAC/E,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mEAAmE,EAAE,GAAG,EAAE;QAC3E,SAAS,EAAE,CAAC;QACZ,MAAM,MAAM,GAAG,yBAAyB,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE,iBAAiB,EAAE,KAAK,EAAE,CAAC,CAAC;QACrF,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACxE,MAAM,MAAM,GAAG,yBAAyB,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC,CAAC;QACpF,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2EAA2E,EAAE,GAAG,EAAE;QACnF,MAAM,MAAM,GAAG,yBAAyB,CACtC,QAAQ,EACR,EAAE,WAAW,EAAE,KAAK,EAAE,EACtB,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAC5B,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,qEAAqE;AAErE,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,SAAS,YAAY,CAAC,YAAoC,EAAE;QAC1D,OAAO;YACL,iBAAiB,EAAE,QAAQ;YAC3B,aAAa,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACvC,aAAa,EAAE,aAAa;YAC5B,SAAS,EAAE,CAAC;YACZ,SAAS,EAAE,CAAC,YAAY,CAAC;YACzB,eAAe,EAAE,EAAE;YACnB,GAAG,SAAS;SACb,CAAC;IACJ,CAAC;IAED,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,MAAM,QAAQ,GAAG,YAAY,CAAC,EAAE,iBAAiB,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC/D,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAChC,MAAM,QAAQ,GAAG,YAAY,CAAC,EAAE,iBAAiB,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC/D,MAAM,QAAQ,GAAG,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACzD,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4EAA4E,EAAE,GAAG,EAAE;QACpF,MAAM,QAAQ,GAAG,YAAY,CAAC,EAAE,iBAAiB,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC/D,MAAM,QAAQ,GAAG,mBAAmB,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QACnD,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;QAC/B,MAAM,aAAa,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;QACpF,MAAM,QAAQ,GAAG,YAAY,CAAC,EAAE,iBAAiB,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,CAAC,CAAC;QAC7F,MAAM,QAAQ,GAAG,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACzD,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,QAAQ,GAAG,mBAAmB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACrD,MAAM,CAAC,QAAQ,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACjC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,QAAQ,GAAG,YAAY,CAAC,EAAE,iBAAiB,EAAE,QAAQ,EAAE,YAAY,EAAE,aAAa,GAAG,CAAC,EAAE,CAAC,CAAC;QAChG,MAAM,QAAQ,GAAG,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACzD,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,QAAQ,GAAG,YAAY,CAAC,EAAE,iBAAiB,EAAE,QAAQ,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC,CAAC;QAC5F,MAAM,QAAQ,GAAG,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACzD,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,qEAAqE;AAErE,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACzC,SAAS,SAAS,CAAC,aAAqC;QACtD,OAAO;YACL,OAAO,EAAE,aAAa;YACtB,OAAO,EAAE,GAAG;YACZ,KAAK,EAAE,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACtD,IAAI;gBACJ;oBACE,IAAI,EAAE,GAAG;oBACT,0EAA0E;oBAC1E,QAAQ,EAAE,QAAe;oBACzB,OAAO,EAAE,EAAE;oBACX,OAAO,EAAE,EAAE;oBACX,KAAK,EAAE,EAAE;oBACT,MAAM,EAAE,KAAK;iBACd;aACF,CAAC,CACH;SACF,CAAC;IACJ,CAAC;IAED,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACjD,MAAM,SAAS,GAAG,yBAAyB,CAAC,KAAK,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC/D,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAChE,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACjD,MAAM,SAAS,GAAG,yBAAyB,CAAC,KAAK,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC;QACrE,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4FAA4F,EAAE,GAAG,EAAE;QACpG,qEAAqE;QACrE,uEAAuE;QACvE,sEAAsE;QACtE,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC5E,MAAM,SAAS,GAAG,yBAAyB,CAAC,KAAK,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC;QAC7E,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oEAAoE,EAAE,GAAG,EAAE;QAC5E,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACjD,MAAM,SAAS,GAAG,yBAAyB,CAAC,KAAK,EAAE;YACjD,+BAA+B;YAC/B,aAAa;SACd,CAAC,CAAC;QACH,yEAAyE;QACzE,oDAAoD;QACpD,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACxE,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACjD,MAAM,SAAS,GAAG,yBAAyB,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QAC7E,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* environment, and optional .ghagga.json file, then runs the
|
|
6
6
|
* core review pipeline and formats the output.
|
|
7
7
|
*/
|
|
8
|
-
import type { LLMProvider, ReviewMode } from 'ghagga-core';
|
|
8
|
+
import type { DependencyGraph, GraphMetadata, LLMProvider, ReviewMode } from 'ghagga-core';
|
|
9
9
|
export interface ReviewOptions {
|
|
10
10
|
mode: ReviewMode;
|
|
11
11
|
provider: LLMProvider;
|
|
@@ -53,6 +53,141 @@ export interface ReviewOptions {
|
|
|
53
53
|
lenses?: string;
|
|
54
54
|
/** Path to custom lens definitions directory (from --lens-dir flag). */
|
|
55
55
|
lensDir?: string;
|
|
56
|
+
/**
|
|
57
|
+
* Fail-closed review anchor. When a hex SHA, HEAD must resolve to that
|
|
58
|
+
* commit before the pipeline runs. `"auto"` skips the mismatch check.
|
|
59
|
+
*/
|
|
60
|
+
anchor?: string;
|
|
61
|
+
/**
|
|
62
|
+
* Explicit blast-radius override from `--no-blast-radius`. `false` forces
|
|
63
|
+
* blast-radius off regardless of graph presence / config; `undefined`
|
|
64
|
+
* defers to `.ghagga.json`/auto-detection (see `resolveBlastRadiusEnabled`).
|
|
65
|
+
*/
|
|
66
|
+
blastRadius?: boolean;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* A single entry in the `.ghagga.json` `providerChain` array — routes ONE
|
|
70
|
+
* multi-voice reviewer (consensus vote / fan-out lens) to a specific
|
|
71
|
+
* cross-engine target via mcp-llm-bridge. Mirrors `ghagga-core`'s
|
|
72
|
+
* `ProviderChainEntry`, minus `apiKey`: the gateway token is resolved at
|
|
73
|
+
* runtime (CLI `--api-key` / stored login token), never stored in plaintext
|
|
74
|
+
* in the config file.
|
|
75
|
+
*/
|
|
76
|
+
interface GhaggaConfigProviderChainEntry {
|
|
77
|
+
/** Only 'gateway' entries are meaningful for cross-engine routing. */
|
|
78
|
+
provider: 'gateway';
|
|
79
|
+
/** Model identifier passed to the bridge (e.g. "claude-sonnet-4-6"). */
|
|
80
|
+
model: string;
|
|
81
|
+
/**
|
|
82
|
+
* Bridge-side provider id to route to (e.g. 'cli-claude', 'codex-cli').
|
|
83
|
+
* Short-circuits the bridge's model-based routing.
|
|
84
|
+
*/
|
|
85
|
+
targetProvider?: string;
|
|
86
|
+
/** Gateway base URL. Defaults to the first entry's / flat gateway config when omitted. */
|
|
87
|
+
gatewayUrl?: string;
|
|
88
|
+
/** OpenCode model in `provider/model` format (cli-bridge only — unused for gateway). */
|
|
89
|
+
cliModel?: string;
|
|
90
|
+
}
|
|
91
|
+
interface GhaggaConfig {
|
|
92
|
+
mode?: string;
|
|
93
|
+
provider?: string;
|
|
94
|
+
model?: string;
|
|
95
|
+
enableSemgrep?: boolean;
|
|
96
|
+
enableTrivy?: boolean;
|
|
97
|
+
enableCpd?: boolean;
|
|
98
|
+
customRules?: string[];
|
|
99
|
+
ignorePatterns?: string[];
|
|
100
|
+
reviewLevel?: string;
|
|
101
|
+
disabledTools?: string[];
|
|
102
|
+
enabledTools?: string[];
|
|
103
|
+
lenses?: string[];
|
|
104
|
+
/**
|
|
105
|
+
* When true, fan-out pins every lens to generateFns[0] (the first
|
|
106
|
+
* providerChain / generateFn entry). Default/omit keeps round-robin.
|
|
107
|
+
*/
|
|
108
|
+
pinLensesToFirst?: boolean;
|
|
109
|
+
/**
|
|
110
|
+
* Opt-in unlensed whole-diff contrarian voices in fan-out.
|
|
111
|
+
* When set, must be a JSON number that is an integer >= 1.
|
|
112
|
+
*/
|
|
113
|
+
contrarianCount?: number;
|
|
114
|
+
/**
|
|
115
|
+
* Opt-in batched 2-of-K refuters over critical fan-out findings.
|
|
116
|
+
* When set, must be a JSON number that is an integer >= 2.
|
|
117
|
+
*/
|
|
118
|
+
refuterCount?: number;
|
|
119
|
+
/**
|
|
120
|
+
* Per-voice cross-engine provider chain (BL-CLI-PROVIDER-CHAIN). When set,
|
|
121
|
+
* consensus (3-vote) and fan-out (N-lens) modes round-robin each voice
|
|
122
|
+
* across these gateway entries instead of hammering a single engine.
|
|
123
|
+
* Fan-out opt-in `pinLensesToFirst: true` pins every lens to generateFns[0]
|
|
124
|
+
* instead of round-robin.
|
|
125
|
+
*/
|
|
126
|
+
providerChain?: GhaggaConfigProviderChainEntry[];
|
|
127
|
+
/**
|
|
128
|
+
* Enable blast-radius filtering (design v2 D7). `true`/`false` override
|
|
129
|
+
* auto-detection (`.ghagga/graph.json` presence); omit to auto-detect.
|
|
130
|
+
* `--no-blast-radius` (ReviewOptions.blastRadius === false) always wins
|
|
131
|
+
* over this config key.
|
|
132
|
+
*/
|
|
133
|
+
enableBlastRadius?: boolean;
|
|
134
|
+
/** Fail-closed review anchor. Hex SHA or `"auto"`. CLI `--anchor` wins. */
|
|
135
|
+
anchor?: string;
|
|
56
136
|
}
|
|
57
137
|
export declare function reviewCommand(targetPath: string, options: ReviewOptions): Promise<void>;
|
|
138
|
+
/** One staleness/coverage signal for `checkGraphStaleness` — WARN, never block. */
|
|
139
|
+
export interface StalenessWarning {
|
|
140
|
+
kind: 'head-mismatch' | 'stale-age' | 'no-metadata' | 'version-mismatch';
|
|
141
|
+
message: string;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Resolve whether blast-radius should be enabled for this review run.
|
|
145
|
+
*
|
|
146
|
+
* Precedence (highest to lowest):
|
|
147
|
+
* 1. `--no-blast-radius` (options.blastRadius === false) → OFF
|
|
148
|
+
* 2. `.ghagga.json` `enableBlastRadius` (explicit true/false) → that value
|
|
149
|
+
* 3. Auto-ON when `<repoPath>/.ghagga/graph.json` exists
|
|
150
|
+
* 4. OFF (no graph, no override)
|
|
151
|
+
*
|
|
152
|
+
* CRITICAL-2 (JD B-001): the existence check is resolved against `repoPath`
|
|
153
|
+
* — the review target — NOT `process.cwd()`, so `ghagga review <other-dir>`
|
|
154
|
+
* from an unrelated cwd still auto-detects correctly.
|
|
155
|
+
*/
|
|
156
|
+
export declare function resolveBlastRadiusEnabled(repoPath: string, options: Pick<ReviewOptions, 'blastRadius'>, fileConfig: Pick<GhaggaConfig, 'enableBlastRadius'>): boolean;
|
|
157
|
+
/**
|
|
158
|
+
* Detect staleness/coverage-verification signals for the loaded graph.
|
|
159
|
+
* ALWAYS warn-and-continue (design v2 D2) — never blocks the review.
|
|
160
|
+
*
|
|
161
|
+
* - HEAD mismatch: `metadata.lastIndexedCommit` non-empty and differs from
|
|
162
|
+
* `currentHead`. An EMPTY `currentHead` (non-git/detached checkout) skips
|
|
163
|
+
* this specific check — there's nothing meaningful to compare against.
|
|
164
|
+
* - Age: delegates to `isGraphStale` (>`GRAPH_STALE_DAYS` days).
|
|
165
|
+
* - Metadata absent (B-005): `metadata === null` — graph.json loaded but no
|
|
166
|
+
* sibling metadata.json (e.g. pre-feature `ghagga index` run). Returns
|
|
167
|
+
* EARLY with only this warning — there's nothing else to check.
|
|
168
|
+
* - Version mismatch (B-003): `metadata.graphVersion` set and differs from
|
|
169
|
+
* the current `GRAPH_VERSION` (equivalent to comparing against the loaded
|
|
170
|
+
* graph's `version`, which `validateGraph` already pins to `GRAPH_VERSION`).
|
|
171
|
+
*/
|
|
172
|
+
export declare function checkGraphStaleness(metadata: GraphMetadata | null, currentHead: string): StalenessWarning[];
|
|
173
|
+
/**
|
|
174
|
+
* Compute the set of languages present among `changedFiles` that have ZERO
|
|
175
|
+
* coverage in the loaded graph — i.e. files whose blast-radius dependent
|
|
176
|
+
* count is unreliable (shows zero, not "no dependents").
|
|
177
|
+
*
|
|
178
|
+
* Coverage is derived from the graph's ACTUAL node contents (design v2 D8,
|
|
179
|
+
* JD CRITICAL-1), not from indexer-dispatch bookkeeping:
|
|
180
|
+
* - The regex-fallback path sets `indexedLanguages: []` even though every
|
|
181
|
+
* node has a real `language` — keying off dispatch state would flag
|
|
182
|
+
* every changed file as uncovered.
|
|
183
|
+
* - `detectPresentLanguages` is root-only — a language that only exists in
|
|
184
|
+
* a subpackage (e.g. `packages/api/requirements.txt`) is never detected
|
|
185
|
+
* or skipped, so dispatch state gives no signal at all.
|
|
186
|
+
*
|
|
187
|
+
* Files whose language cannot be detected (`detectLanguage` returns
|
|
188
|
+
* `undefined` — unknown extension) are silently excluded; there is no
|
|
189
|
+
* language identity to report as uncovered.
|
|
190
|
+
*/
|
|
191
|
+
export declare function computeUncoveredLanguages(graph: DependencyGraph, changedFiles: string[]): string[];
|
|
192
|
+
export {};
|
|
58
193
|
//# sourceMappingURL=review.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review.d.ts","sourceRoot":"","sources":["../../src/commands/review.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"review.d.ts","sourceRoot":"","sources":["../../src/commands/review.ts"],"names":[],"mappings":"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"}
|