@buoy-design/cli 0.1.0 → 0.1.2
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/dist/commands/audit.d.ts +3 -0
- package/dist/commands/audit.d.ts.map +1 -0
- package/dist/commands/audit.js +235 -0
- package/dist/commands/audit.js.map +1 -0
- package/dist/commands/baseline.d.ts +39 -0
- package/dist/commands/baseline.d.ts.map +1 -0
- package/dist/commands/baseline.js +298 -0
- package/dist/commands/baseline.js.map +1 -0
- package/dist/commands/check.d.ts +16 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +168 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/ci.d.ts +2 -2
- package/dist/commands/ci.d.ts.map +1 -1
- package/dist/commands/ci.js +124 -142
- package/dist/commands/ci.js.map +1 -1
- package/dist/commands/compare.d.ts +3 -0
- package/dist/commands/compare.d.ts.map +1 -0
- package/dist/commands/compare.js +170 -0
- package/dist/commands/compare.js.map +1 -0
- package/dist/commands/drift.d.ts +1 -1
- package/dist/commands/drift.d.ts.map +1 -1
- package/dist/commands/drift.js +79 -121
- package/dist/commands/drift.js.map +1 -1
- package/dist/commands/explain.d.ts +3 -0
- package/dist/commands/explain.d.ts.map +1 -0
- package/dist/commands/explain.js +212 -0
- package/dist/commands/explain.js.map +1 -0
- package/dist/commands/graph.d.ts +3 -0
- package/dist/commands/graph.d.ts.map +1 -0
- package/dist/commands/graph.js +430 -0
- package/dist/commands/graph.js.map +1 -0
- package/dist/commands/index.d.ts +14 -8
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +14 -8
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +404 -237
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/plugins.d.ts.map +1 -1
- package/dist/commands/plugins.js +32 -41
- package/dist/commands/plugins.js.map +1 -1
- package/dist/commands/scan.d.ts +1 -1
- package/dist/commands/scan.d.ts.map +1 -1
- package/dist/commands/scan.js +107 -219
- package/dist/commands/scan.js.map +1 -1
- package/dist/commands/status.d.ts +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +114 -122
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/tokens.d.ts +3 -0
- package/dist/commands/tokens.d.ts.map +1 -0
- package/dist/commands/tokens.js +261 -0
- package/dist/commands/tokens.js.map +1 -0
- package/dist/config/auto-detect.d.ts +21 -0
- package/dist/config/auto-detect.d.ts.map +1 -0
- package/dist/config/auto-detect.js +278 -0
- package/dist/config/auto-detect.js.map +1 -0
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +17 -0
- package/dist/config/loader.js.map +1 -1
- package/dist/config/schema.d.ts +63 -63
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +20 -2
- package/dist/config/schema.js.map +1 -1
- package/dist/constants.d.ts +36 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +37 -0
- package/dist/constants.js.map +1 -0
- package/dist/detect/frameworks.d.ts +11 -2
- package/dist/detect/frameworks.d.ts.map +1 -1
- package/dist/detect/frameworks.js +78 -78
- package/dist/detect/frameworks.js.map +1 -1
- package/dist/detect/index.d.ts +1 -0
- package/dist/detect/index.d.ts.map +1 -1
- package/dist/detect/index.js +3 -0
- package/dist/detect/index.js.map +1 -1
- package/dist/detect/monorepo-patterns.d.ts +54 -0
- package/dist/detect/monorepo-patterns.d.ts.map +1 -0
- package/dist/detect/monorepo-patterns.js +209 -0
- package/dist/detect/monorepo-patterns.js.map +1 -0
- package/dist/detect/project-detector.d.ts +1 -1
- package/dist/detect/project-detector.d.ts.map +1 -1
- package/dist/detect/project-detector.js +132 -0
- package/dist/detect/project-detector.js.map +1 -1
- package/dist/explain/agents.d.ts +31 -0
- package/dist/explain/agents.d.ts.map +1 -0
- package/dist/explain/agents.js +507 -0
- package/dist/explain/agents.js.map +1 -0
- package/dist/hooks/index.d.ts +26 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +283 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -7
- package/dist/index.js.map +1 -1
- package/dist/integrations/github-formatter.d.ts +55 -0
- package/dist/integrations/github-formatter.d.ts.map +1 -0
- package/dist/integrations/github-formatter.js +391 -0
- package/dist/integrations/github-formatter.js.map +1 -0
- package/dist/integrations/github.d.ts +95 -0
- package/dist/integrations/github.d.ts.map +1 -0
- package/dist/integrations/github.js +281 -0
- package/dist/integrations/github.js.map +1 -0
- package/dist/integrations/index.d.ts +4 -0
- package/dist/integrations/index.d.ts.map +1 -0
- package/dist/integrations/index.js +4 -0
- package/dist/integrations/index.js.map +1 -0
- package/dist/output/formatters.d.ts.map +1 -1
- package/dist/output/formatters.js +5 -10
- package/dist/output/formatters.js.map +1 -1
- package/dist/scan/orchestrator.d.ts +76 -0
- package/dist/scan/orchestrator.d.ts.map +1 -0
- package/dist/scan/orchestrator.js +247 -0
- package/dist/scan/orchestrator.js.map +1 -0
- package/dist/services/ai-analysis.d.ts +54 -0
- package/dist/services/ai-analysis.d.ts.map +1 -0
- package/dist/services/ai-analysis.js +239 -0
- package/dist/services/ai-analysis.js.map +1 -0
- package/dist/services/drift-analysis.d.ts +77 -0
- package/dist/services/drift-analysis.d.ts.map +1 -0
- package/dist/services/drift-analysis.js +145 -0
- package/dist/services/drift-analysis.js.map +1 -0
- package/package.json +17 -5
- package/dist/commands/__tests__/ci.test.d.ts +0 -2
- package/dist/commands/__tests__/ci.test.d.ts.map +0 -1
- package/dist/commands/__tests__/ci.test.js +0 -33
- package/dist/commands/__tests__/ci.test.js.map +0 -1
- package/dist/commands/bootstrap.d.ts +0 -3
- package/dist/commands/bootstrap.d.ts.map +0 -1
- package/dist/commands/bootstrap.js +0 -458
- package/dist/commands/bootstrap.js.map +0 -1
- package/dist/plugins/index.d.ts +0 -3
- package/dist/plugins/index.d.ts.map +0 -1
- package/dist/plugins/index.js +0 -3
- package/dist/plugins/index.js.map +0 -1
- package/dist/plugins/loader.d.ts +0 -11
- package/dist/plugins/loader.d.ts.map +0 -1
- package/dist/plugins/loader.js +0 -77
- package/dist/plugins/loader.js.map +0 -1
- package/dist/plugins/registry.d.ts +0 -15
- package/dist/plugins/registry.d.ts.map +0 -1
- package/dist/plugins/registry.js +0 -32
- package/dist/plugins/registry.js.map +0 -1
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized scanner orchestration for all CLI commands.
|
|
3
|
+
* Eliminates duplicate scanning logic across scan, status, ci, and drift commands.
|
|
4
|
+
*/
|
|
5
|
+
export class ScanOrchestrator {
|
|
6
|
+
config;
|
|
7
|
+
projectRoot;
|
|
8
|
+
constructor(config, projectRoot = process.cwd()) {
|
|
9
|
+
this.config = config;
|
|
10
|
+
this.projectRoot = projectRoot;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Get list of enabled sources from config
|
|
14
|
+
*/
|
|
15
|
+
getEnabledSources() {
|
|
16
|
+
const sources = [];
|
|
17
|
+
// JS Frameworks
|
|
18
|
+
if (this.config.sources.react?.enabled)
|
|
19
|
+
sources.push("react");
|
|
20
|
+
if (this.config.sources.vue?.enabled)
|
|
21
|
+
sources.push("vue");
|
|
22
|
+
if (this.config.sources.svelte?.enabled)
|
|
23
|
+
sources.push("svelte");
|
|
24
|
+
if (this.config.sources.angular?.enabled)
|
|
25
|
+
sources.push("angular");
|
|
26
|
+
if (this.config.sources.webcomponent?.enabled)
|
|
27
|
+
sources.push("webcomponent");
|
|
28
|
+
// Templates
|
|
29
|
+
if (this.config.sources.templates?.enabled)
|
|
30
|
+
sources.push("templates");
|
|
31
|
+
// Design tools
|
|
32
|
+
if (this.config.sources.figma?.enabled)
|
|
33
|
+
sources.push("figma");
|
|
34
|
+
if (this.config.sources.storybook?.enabled)
|
|
35
|
+
sources.push("storybook");
|
|
36
|
+
if (this.config.sources.tokens?.enabled)
|
|
37
|
+
sources.push("tokens");
|
|
38
|
+
return sources;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Scan all enabled sources or specific sources
|
|
42
|
+
*/
|
|
43
|
+
async scan(options = {}) {
|
|
44
|
+
const result = {
|
|
45
|
+
components: [],
|
|
46
|
+
tokens: [],
|
|
47
|
+
errors: [],
|
|
48
|
+
};
|
|
49
|
+
// Determine sources to scan
|
|
50
|
+
const sourcesToScan = options.sources && options.sources.length > 0
|
|
51
|
+
? options.sources
|
|
52
|
+
: this.getEnabledSources();
|
|
53
|
+
if (sourcesToScan.length === 0) {
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
// Import scanners dynamically (lazy load)
|
|
57
|
+
const scanners = await this.importScanners();
|
|
58
|
+
// Scan each source
|
|
59
|
+
for (const source of sourcesToScan) {
|
|
60
|
+
options.onProgress?.(`Scanning ${source}...`);
|
|
61
|
+
try {
|
|
62
|
+
const sourceResult = await this.scanSource(source, scanners);
|
|
63
|
+
result.components.push(...sourceResult.components);
|
|
64
|
+
result.tokens.push(...sourceResult.tokens);
|
|
65
|
+
result.errors.push(...sourceResult.errors);
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
69
|
+
result.errors.push({ source, message });
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Scan only component sources (no tokens)
|
|
76
|
+
*/
|
|
77
|
+
async scanComponents(options = {}) {
|
|
78
|
+
const result = await this.scan({
|
|
79
|
+
...options,
|
|
80
|
+
sources: options.sources?.filter((s) => s !== "tokens") ||
|
|
81
|
+
this.getEnabledSources().filter((s) => s !== "tokens"),
|
|
82
|
+
});
|
|
83
|
+
return {
|
|
84
|
+
components: result.components,
|
|
85
|
+
errors: result.errors,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Scan only token sources
|
|
90
|
+
*/
|
|
91
|
+
async scanTokens(options = {}) {
|
|
92
|
+
const result = await this.scan({
|
|
93
|
+
...options,
|
|
94
|
+
sources: ["tokens"],
|
|
95
|
+
});
|
|
96
|
+
return {
|
|
97
|
+
tokens: result.tokens,
|
|
98
|
+
errors: result.errors,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Import all scanner classes dynamically
|
|
103
|
+
*/
|
|
104
|
+
async importScanners() {
|
|
105
|
+
const { ReactComponentScanner, VueComponentScanner, SvelteComponentScanner, AngularComponentScanner, WebComponentScanner, TemplateScanner, TokenScanner, } = await import("@buoy-design/scanners/git");
|
|
106
|
+
return {
|
|
107
|
+
ReactComponentScanner,
|
|
108
|
+
VueComponentScanner,
|
|
109
|
+
SvelteComponentScanner,
|
|
110
|
+
AngularComponentScanner,
|
|
111
|
+
WebComponentScanner,
|
|
112
|
+
TemplateScanner,
|
|
113
|
+
TokenScanner,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Scan a specific source and return results
|
|
118
|
+
*/
|
|
119
|
+
async scanSource(source, scanners) {
|
|
120
|
+
const result = {
|
|
121
|
+
components: [],
|
|
122
|
+
tokens: [],
|
|
123
|
+
errors: [],
|
|
124
|
+
};
|
|
125
|
+
switch (source) {
|
|
126
|
+
case "react": {
|
|
127
|
+
const cfg = this.config.sources.react;
|
|
128
|
+
if (!cfg)
|
|
129
|
+
break;
|
|
130
|
+
const scanner = new scanners.ReactComponentScanner({
|
|
131
|
+
projectRoot: this.projectRoot,
|
|
132
|
+
include: cfg.include,
|
|
133
|
+
exclude: cfg.exclude,
|
|
134
|
+
designSystemPackage: cfg.designSystemPackage,
|
|
135
|
+
});
|
|
136
|
+
const scanResult = await scanner.scan();
|
|
137
|
+
result.components.push(...scanResult.items);
|
|
138
|
+
this.collectErrors(result.errors, source, scanResult.errors);
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
case "vue": {
|
|
142
|
+
const cfg = this.config.sources.vue;
|
|
143
|
+
if (!cfg)
|
|
144
|
+
break;
|
|
145
|
+
const scanner = new scanners.VueComponentScanner({
|
|
146
|
+
projectRoot: this.projectRoot,
|
|
147
|
+
include: cfg.include,
|
|
148
|
+
exclude: cfg.exclude,
|
|
149
|
+
});
|
|
150
|
+
const scanResult = await scanner.scan();
|
|
151
|
+
result.components.push(...scanResult.items);
|
|
152
|
+
this.collectErrors(result.errors, source, scanResult.errors);
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
case "svelte": {
|
|
156
|
+
const cfg = this.config.sources.svelte;
|
|
157
|
+
if (!cfg)
|
|
158
|
+
break;
|
|
159
|
+
const scanner = new scanners.SvelteComponentScanner({
|
|
160
|
+
projectRoot: this.projectRoot,
|
|
161
|
+
include: cfg.include,
|
|
162
|
+
exclude: cfg.exclude,
|
|
163
|
+
});
|
|
164
|
+
const scanResult = await scanner.scan();
|
|
165
|
+
result.components.push(...scanResult.items);
|
|
166
|
+
this.collectErrors(result.errors, source, scanResult.errors);
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
case "angular": {
|
|
170
|
+
const cfg = this.config.sources.angular;
|
|
171
|
+
if (!cfg)
|
|
172
|
+
break;
|
|
173
|
+
const scanner = new scanners.AngularComponentScanner({
|
|
174
|
+
projectRoot: this.projectRoot,
|
|
175
|
+
include: cfg.include,
|
|
176
|
+
exclude: cfg.exclude,
|
|
177
|
+
});
|
|
178
|
+
const scanResult = await scanner.scan();
|
|
179
|
+
result.components.push(...scanResult.items);
|
|
180
|
+
this.collectErrors(result.errors, source, scanResult.errors);
|
|
181
|
+
break;
|
|
182
|
+
}
|
|
183
|
+
case "webcomponent": {
|
|
184
|
+
const cfg = this.config.sources.webcomponent;
|
|
185
|
+
if (!cfg)
|
|
186
|
+
break;
|
|
187
|
+
const scanner = new scanners.WebComponentScanner({
|
|
188
|
+
projectRoot: this.projectRoot,
|
|
189
|
+
include: cfg.include,
|
|
190
|
+
exclude: cfg.exclude,
|
|
191
|
+
framework: cfg.framework,
|
|
192
|
+
});
|
|
193
|
+
const scanResult = await scanner.scan();
|
|
194
|
+
result.components.push(...scanResult.items);
|
|
195
|
+
this.collectErrors(result.errors, source, scanResult.errors);
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
case "templates": {
|
|
199
|
+
const cfg = this.config.sources.templates;
|
|
200
|
+
if (!cfg)
|
|
201
|
+
break;
|
|
202
|
+
const scanner = new scanners.TemplateScanner({
|
|
203
|
+
projectRoot: this.projectRoot,
|
|
204
|
+
include: cfg.include,
|
|
205
|
+
exclude: cfg.exclude,
|
|
206
|
+
templateType: cfg.type,
|
|
207
|
+
});
|
|
208
|
+
const scanResult = await scanner.scan();
|
|
209
|
+
result.components.push(...scanResult.items);
|
|
210
|
+
this.collectErrors(result.errors, source, scanResult.errors);
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
case "tokens": {
|
|
214
|
+
const cfg = this.config.sources.tokens;
|
|
215
|
+
if (!cfg)
|
|
216
|
+
break;
|
|
217
|
+
const scanner = new scanners.TokenScanner({
|
|
218
|
+
projectRoot: this.projectRoot,
|
|
219
|
+
files: cfg.files,
|
|
220
|
+
cssVariablePrefix: cfg.cssVariablePrefix,
|
|
221
|
+
});
|
|
222
|
+
const scanResult = await scanner.scan();
|
|
223
|
+
result.tokens.push(...scanResult.items);
|
|
224
|
+
this.collectErrors(result.errors, source, scanResult.errors);
|
|
225
|
+
break;
|
|
226
|
+
}
|
|
227
|
+
case "figma":
|
|
228
|
+
case "storybook":
|
|
229
|
+
// TODO: Implement figma and storybook scanners
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
return result;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Collect and format errors from scanner result
|
|
236
|
+
*/
|
|
237
|
+
collectErrors(target, source, errors) {
|
|
238
|
+
for (const err of errors) {
|
|
239
|
+
target.push({
|
|
240
|
+
source,
|
|
241
|
+
message: err.message,
|
|
242
|
+
file: err.file,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
//# sourceMappingURL=orchestrator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../src/scan/orchestrator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Analysis Service
|
|
3
|
+
*
|
|
4
|
+
* Uses Claude + the knowledge graph to provide intelligent drift analysis.
|
|
5
|
+
* The graph provides context, Claude provides understanding.
|
|
6
|
+
*/
|
|
7
|
+
import type { DriftSignal } from '@buoy-design/core';
|
|
8
|
+
export interface AnalysisContext {
|
|
9
|
+
projectRoot: string;
|
|
10
|
+
prNumber?: number;
|
|
11
|
+
prAuthor?: string;
|
|
12
|
+
filesChanged?: string[];
|
|
13
|
+
}
|
|
14
|
+
export interface DriftAnalysis {
|
|
15
|
+
signal: DriftSignal;
|
|
16
|
+
analysis: string;
|
|
17
|
+
isLikelyIntentional: boolean;
|
|
18
|
+
confidence: number;
|
|
19
|
+
suggestedAction: 'fix' | 'approve' | 'discuss';
|
|
20
|
+
relatedHistory: string[];
|
|
21
|
+
}
|
|
22
|
+
export interface PRAnalysisSummary {
|
|
23
|
+
overview: string;
|
|
24
|
+
criticalIssues: DriftAnalysis[];
|
|
25
|
+
warnings: DriftAnalysis[];
|
|
26
|
+
recommendations: string[];
|
|
27
|
+
riskLevel: 'low' | 'medium' | 'high';
|
|
28
|
+
}
|
|
29
|
+
export declare class AIAnalysisService {
|
|
30
|
+
private client;
|
|
31
|
+
private graph;
|
|
32
|
+
constructor(apiKey?: string);
|
|
33
|
+
get isEnabled(): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Build the knowledge graph for context
|
|
36
|
+
*/
|
|
37
|
+
buildGraph(projectRoot: string): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Get context from the graph for a specific file
|
|
40
|
+
*/
|
|
41
|
+
private getFileContext;
|
|
42
|
+
/**
|
|
43
|
+
* Analyze a single drift signal with AI
|
|
44
|
+
*/
|
|
45
|
+
analyzeDrift(signal: DriftSignal, context: AnalysisContext): Promise<DriftAnalysis>;
|
|
46
|
+
/**
|
|
47
|
+
* Analyze all drift signals and produce a PR summary
|
|
48
|
+
*/
|
|
49
|
+
analyzePR(signals: DriftSignal[], context: AnalysisContext): Promise<PRAnalysisSummary>;
|
|
50
|
+
private generateOverview;
|
|
51
|
+
private countBySeverity;
|
|
52
|
+
private generateRecommendations;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=ai-analysis.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-analysis.d.ts","sourceRoot":"","sources":["../../src/services/ai-analysis.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAQrD,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,WAAW,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,KAAK,GAAG,SAAS,GAAG,SAAS,CAAC;IAC/C,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,SAAS,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;CACtC;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,KAAK,CAAkC;gBAEnC,MAAM,CAAC,EAAE,MAAM;IAO3B,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED;;OAEG;IACG,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BpD;;OAEG;IACH,OAAO,CAAC,cAAc;IAgBtB;;OAEG;IACG,YAAY,CAChB,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,aAAa,CAAC;IAkFzB;;OAEG;IACG,SAAS,CACb,OAAO,EAAE,WAAW,EAAE,EACtB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,iBAAiB,CAAC;YA6Cf,gBAAgB;IAuC9B,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,uBAAuB;CAoChC"}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Analysis Service
|
|
3
|
+
*
|
|
4
|
+
* Uses Claude + the knowledge graph to provide intelligent drift analysis.
|
|
5
|
+
* The graph provides context, Claude provides understanding.
|
|
6
|
+
*/
|
|
7
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
8
|
+
import { GraphBuilder, collectGitHistory, findRepeatOffenders, } from '@buoy-design/core';
|
|
9
|
+
export class AIAnalysisService {
|
|
10
|
+
client = null;
|
|
11
|
+
graph = null;
|
|
12
|
+
constructor(apiKey) {
|
|
13
|
+
const key = apiKey || process.env.ANTHROPIC_API_KEY;
|
|
14
|
+
if (key) {
|
|
15
|
+
this.client = new Anthropic({ apiKey: key });
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
get isEnabled() {
|
|
19
|
+
return this.client !== null;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Build the knowledge graph for context
|
|
23
|
+
*/
|
|
24
|
+
async buildGraph(projectRoot) {
|
|
25
|
+
const builder = new GraphBuilder({ projectId: 'default' });
|
|
26
|
+
// Collect git history for context
|
|
27
|
+
const gitResult = await collectGitHistory(projectRoot, { maxCount: 500 });
|
|
28
|
+
for (const commit of gitResult.commits) {
|
|
29
|
+
const commitId = builder.addCommit(commit.sha, commit.message, commit.author, commit.authorEmail, commit.timestamp);
|
|
30
|
+
for (const file of commit.filesChanged) {
|
|
31
|
+
const fileId = builder.addFile(file.path, file.path);
|
|
32
|
+
builder.addEdge('CHANGED', commitId, fileId, {
|
|
33
|
+
createdAt: commit.timestamp,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
for (const dev of gitResult.developers) {
|
|
38
|
+
builder.addDeveloper(dev.id, dev.name, dev.email, undefined, dev.commitCount);
|
|
39
|
+
}
|
|
40
|
+
this.graph = builder.build();
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Get context from the graph for a specific file
|
|
44
|
+
*/
|
|
45
|
+
getFileContext(filePath) {
|
|
46
|
+
const context = [];
|
|
47
|
+
if (!this.graph)
|
|
48
|
+
return context;
|
|
49
|
+
// Find repeat offenders
|
|
50
|
+
const offenders = findRepeatOffenders(this.graph);
|
|
51
|
+
const isRepeatOffender = offenders.some(o => o.file === filePath);
|
|
52
|
+
if (isRepeatOffender) {
|
|
53
|
+
const offender = offenders.find(o => o.file === filePath);
|
|
54
|
+
context.push(`This file has ${offender?.driftCount || 0} previous drift signals (repeat offender)`);
|
|
55
|
+
}
|
|
56
|
+
return context;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Analyze a single drift signal with AI
|
|
60
|
+
*/
|
|
61
|
+
async analyzeDrift(signal, context) {
|
|
62
|
+
if (!this.client) {
|
|
63
|
+
// Fallback without AI
|
|
64
|
+
return {
|
|
65
|
+
signal,
|
|
66
|
+
analysis: signal.message,
|
|
67
|
+
isLikelyIntentional: false,
|
|
68
|
+
confidence: 0.5,
|
|
69
|
+
suggestedAction: signal.severity === 'critical' ? 'fix' : 'discuss',
|
|
70
|
+
relatedHistory: [],
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
// Get graph context
|
|
74
|
+
const fileContext = signal.source.location
|
|
75
|
+
? this.getFileContext(signal.source.location.split(':')[0] || '')
|
|
76
|
+
: [];
|
|
77
|
+
const prompt = `You are a design system expert analyzing code drift. Be concise.
|
|
78
|
+
|
|
79
|
+
Drift Signal:
|
|
80
|
+
- Type: ${signal.type}
|
|
81
|
+
- Severity: ${signal.severity}
|
|
82
|
+
- Component: ${signal.source.entityName}
|
|
83
|
+
- File: ${signal.source.location || 'unknown'}
|
|
84
|
+
- Message: ${signal.message}
|
|
85
|
+
- Found: ${signal.details.actual || 'N/A'}
|
|
86
|
+
- Expected: ${signal.details.expected || 'N/A'}
|
|
87
|
+
|
|
88
|
+
Context:
|
|
89
|
+
- PR Author: ${context.prAuthor || 'unknown'}
|
|
90
|
+
- Files in PR: ${context.filesChanged?.length || 0}
|
|
91
|
+
${fileContext.map(c => `- ${c}`).join('\n')}
|
|
92
|
+
|
|
93
|
+
Analyze this drift signal:
|
|
94
|
+
1. Is this likely intentional or accidental? (one sentence why)
|
|
95
|
+
2. What's the risk if merged? (low/medium/high + one sentence)
|
|
96
|
+
3. Recommended action: fix, approve, or discuss?
|
|
97
|
+
|
|
98
|
+
Be direct and practical. No fluff.`;
|
|
99
|
+
try {
|
|
100
|
+
const response = await this.client.messages.create({
|
|
101
|
+
model: 'claude-sonnet-4-20250514',
|
|
102
|
+
max_tokens: 300,
|
|
103
|
+
messages: [{ role: 'user', content: prompt }],
|
|
104
|
+
});
|
|
105
|
+
const analysisText = response.content[0]?.type === 'text'
|
|
106
|
+
? response.content[0].text
|
|
107
|
+
: '';
|
|
108
|
+
// Parse the response
|
|
109
|
+
const isIntentional = analysisText.toLowerCase().includes('intentional') &&
|
|
110
|
+
!analysisText.toLowerCase().includes('not intentional') &&
|
|
111
|
+
!analysisText.toLowerCase().includes('unintentional');
|
|
112
|
+
const suggestedAction = analysisText.toLowerCase().includes('fix') ? 'fix'
|
|
113
|
+
: analysisText.toLowerCase().includes('approve') ? 'approve'
|
|
114
|
+
: 'discuss';
|
|
115
|
+
return {
|
|
116
|
+
signal,
|
|
117
|
+
analysis: analysisText,
|
|
118
|
+
isLikelyIntentional: isIntentional,
|
|
119
|
+
confidence: 0.8,
|
|
120
|
+
suggestedAction,
|
|
121
|
+
relatedHistory: fileContext,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
// Fallback on error
|
|
126
|
+
return {
|
|
127
|
+
signal,
|
|
128
|
+
analysis: `Analysis unavailable: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
129
|
+
isLikelyIntentional: false,
|
|
130
|
+
confidence: 0,
|
|
131
|
+
suggestedAction: 'discuss',
|
|
132
|
+
relatedHistory: fileContext,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Analyze all drift signals and produce a PR summary
|
|
138
|
+
*/
|
|
139
|
+
async analyzePR(signals, context) {
|
|
140
|
+
// Build graph if not already built
|
|
141
|
+
if (!this.graph) {
|
|
142
|
+
await this.buildGraph(context.projectRoot);
|
|
143
|
+
}
|
|
144
|
+
// Analyze critical and warning signals
|
|
145
|
+
const criticals = signals.filter(s => s.severity === 'critical');
|
|
146
|
+
const warnings = signals.filter(s => s.severity === 'warning');
|
|
147
|
+
const criticalAnalyses = [];
|
|
148
|
+
const warningAnalyses = [];
|
|
149
|
+
// Analyze criticals (all of them)
|
|
150
|
+
for (const signal of criticals) {
|
|
151
|
+
const analysis = await this.analyzeDrift(signal, context);
|
|
152
|
+
criticalAnalyses.push(analysis);
|
|
153
|
+
}
|
|
154
|
+
// Analyze warnings (limit to top 5)
|
|
155
|
+
for (const signal of warnings.slice(0, 5)) {
|
|
156
|
+
const analysis = await this.analyzeDrift(signal, context);
|
|
157
|
+
warningAnalyses.push(analysis);
|
|
158
|
+
}
|
|
159
|
+
// Generate overall summary
|
|
160
|
+
const overview = await this.generateOverview(signals, context, criticalAnalyses);
|
|
161
|
+
// Determine risk level
|
|
162
|
+
const riskLevel = criticals.length > 0 ? 'high'
|
|
163
|
+
: warnings.length > 5 ? 'medium'
|
|
164
|
+
: 'low';
|
|
165
|
+
// Generate recommendations
|
|
166
|
+
const recommendations = this.generateRecommendations(criticalAnalyses, warningAnalyses);
|
|
167
|
+
return {
|
|
168
|
+
overview,
|
|
169
|
+
criticalIssues: criticalAnalyses,
|
|
170
|
+
warnings: warningAnalyses,
|
|
171
|
+
recommendations,
|
|
172
|
+
riskLevel,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
async generateOverview(signals, context, criticalAnalyses) {
|
|
176
|
+
if (!this.client) {
|
|
177
|
+
const { critical, warning, info } = this.countBySeverity(signals);
|
|
178
|
+
return `Found ${signals.length} drift signals: ${critical} critical, ${warning} warnings, ${info} info.`;
|
|
179
|
+
}
|
|
180
|
+
const prompt = `Summarize this PR's design system impact in 2-3 sentences:
|
|
181
|
+
|
|
182
|
+
- Total signals: ${signals.length}
|
|
183
|
+
- Critical: ${signals.filter(s => s.severity === 'critical').length}
|
|
184
|
+
- Warnings: ${signals.filter(s => s.severity === 'warning').length}
|
|
185
|
+
- Files affected: ${new Set(signals.map(s => s.source.location?.split(':')[0])).size}
|
|
186
|
+
- PR Author: ${context.prAuthor || 'unknown'}
|
|
187
|
+
|
|
188
|
+
Critical issues:
|
|
189
|
+
${criticalAnalyses.map(a => `- ${a.signal.message}`).join('\n') || 'None'}
|
|
190
|
+
|
|
191
|
+
Be direct. Focus on what matters for the reviewer.`;
|
|
192
|
+
try {
|
|
193
|
+
const response = await this.client.messages.create({
|
|
194
|
+
model: 'claude-sonnet-4-20250514',
|
|
195
|
+
max_tokens: 150,
|
|
196
|
+
messages: [{ role: 'user', content: prompt }],
|
|
197
|
+
});
|
|
198
|
+
return response.content[0]?.type === 'text'
|
|
199
|
+
? response.content[0].text
|
|
200
|
+
: 'Unable to generate overview.';
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
const { critical, warning, info } = this.countBySeverity(signals);
|
|
204
|
+
return `Found ${signals.length} drift signals: ${critical} critical, ${warning} warnings, ${info} info.`;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
countBySeverity(signals) {
|
|
208
|
+
return {
|
|
209
|
+
critical: signals.filter(s => s.severity === 'critical').length,
|
|
210
|
+
warning: signals.filter(s => s.severity === 'warning').length,
|
|
211
|
+
info: signals.filter(s => s.severity === 'info').length,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
generateRecommendations(criticals, warnings) {
|
|
215
|
+
const recommendations = [];
|
|
216
|
+
// Check for patterns
|
|
217
|
+
const needsFix = [...criticals, ...warnings].filter(a => a.suggestedAction === 'fix');
|
|
218
|
+
const canApprove = [...criticals, ...warnings].filter(a => a.suggestedAction === 'approve');
|
|
219
|
+
const needsDiscussion = [...criticals, ...warnings].filter(a => a.suggestedAction === 'discuss');
|
|
220
|
+
if (needsFix.length > 0) {
|
|
221
|
+
recommendations.push(`Fix ${needsFix.length} issue${needsFix.length === 1 ? '' : 's'} before merging`);
|
|
222
|
+
}
|
|
223
|
+
if (canApprove.length > 0) {
|
|
224
|
+
recommendations.push(`${canApprove.length} issue${canApprove.length === 1 ? ' appears' : 's appear'} intentional - consider approving with 👍`);
|
|
225
|
+
}
|
|
226
|
+
if (needsDiscussion.length > 0) {
|
|
227
|
+
recommendations.push(`${needsDiscussion.length} issue${needsDiscussion.length === 1 ? ' needs' : 's need'} team discussion`);
|
|
228
|
+
}
|
|
229
|
+
// Check for repeat offenders
|
|
230
|
+
const repeatFiles = new Set([...criticals, ...warnings]
|
|
231
|
+
.filter(a => a.relatedHistory.some(h => h.includes('repeat offender')))
|
|
232
|
+
.map(a => a.signal.source.location?.split(':')[0]));
|
|
233
|
+
if (repeatFiles.size > 0) {
|
|
234
|
+
recommendations.push(`Consider refactoring ${repeatFiles.size} file${repeatFiles.size === 1 ? '' : 's'} with recurring drift`);
|
|
235
|
+
}
|
|
236
|
+
return recommendations;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
//# sourceMappingURL=ai-analysis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-analysis.js","sourceRoot":"","sources":["../../src/services/ai-analysis.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DriftAnalysisService - Consolidated drift detection workflow
|
|
3
|
+
*
|
|
4
|
+
* Handles the common pattern of:
|
|
5
|
+
* 1. Scanning components via ScanOrchestrator
|
|
6
|
+
* 2. Running SemanticDiffEngine analysis
|
|
7
|
+
* 3. Applying ignore rules from config
|
|
8
|
+
* 4. Filtering against baseline
|
|
9
|
+
*/
|
|
10
|
+
import type { DriftSignal, Severity, Component } from "@buoy-design/core";
|
|
11
|
+
import type { BuoyConfig } from "../config/schema.js";
|
|
12
|
+
export interface DriftAnalysisOptions {
|
|
13
|
+
/** Callback for progress updates */
|
|
14
|
+
onProgress?: (message: string) => void;
|
|
15
|
+
/** Include baselined drifts (default: false) */
|
|
16
|
+
includeBaseline?: boolean;
|
|
17
|
+
/** Filter by minimum severity */
|
|
18
|
+
minSeverity?: Severity;
|
|
19
|
+
/** Filter by drift type */
|
|
20
|
+
filterType?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface DriftAnalysisResult {
|
|
23
|
+
/** All drifts after filtering */
|
|
24
|
+
drifts: DriftSignal[];
|
|
25
|
+
/** Components that were scanned */
|
|
26
|
+
components: Component[];
|
|
27
|
+
/** Number of drifts filtered out by baseline */
|
|
28
|
+
baselinedCount: number;
|
|
29
|
+
/** Summary counts by severity */
|
|
30
|
+
summary: {
|
|
31
|
+
total: number;
|
|
32
|
+
critical: number;
|
|
33
|
+
warning: number;
|
|
34
|
+
info: number;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Calculate summary counts for drift signals
|
|
39
|
+
*/
|
|
40
|
+
export declare function calculateDriftSummary(drifts: DriftSignal[]): {
|
|
41
|
+
total: number;
|
|
42
|
+
critical: number;
|
|
43
|
+
warning: number;
|
|
44
|
+
info: number;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Determine if drifts exceed a severity threshold
|
|
48
|
+
*/
|
|
49
|
+
export declare function hasDriftsAboveThreshold(drifts: DriftSignal[], failOn: Severity | "none"): boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Sort drifts by severity (critical first)
|
|
52
|
+
*/
|
|
53
|
+
export declare function sortDriftsBySeverity(drifts: DriftSignal[]): DriftSignal[];
|
|
54
|
+
/**
|
|
55
|
+
* Apply ignore rules from config to filter out matching drifts
|
|
56
|
+
*/
|
|
57
|
+
export declare function applyIgnoreRules(drifts: DriftSignal[], ignoreRules: BuoyConfig["drift"]["ignore"], onWarning?: (message: string) => void): DriftSignal[];
|
|
58
|
+
/**
|
|
59
|
+
* Apply severity filter to drifts
|
|
60
|
+
*/
|
|
61
|
+
export declare function filterBySeverity(drifts: DriftSignal[], minSeverity: Severity): DriftSignal[];
|
|
62
|
+
/**
|
|
63
|
+
* Apply type filter to drifts
|
|
64
|
+
*/
|
|
65
|
+
export declare function filterByType(drifts: DriftSignal[], type: string): DriftSignal[];
|
|
66
|
+
/**
|
|
67
|
+
* DriftAnalysisService - Main entry point for drift detection
|
|
68
|
+
*/
|
|
69
|
+
export declare class DriftAnalysisService {
|
|
70
|
+
private config;
|
|
71
|
+
constructor(config: BuoyConfig);
|
|
72
|
+
/**
|
|
73
|
+
* Run full drift analysis pipeline
|
|
74
|
+
*/
|
|
75
|
+
analyze(options?: DriftAnalysisOptions): Promise<DriftAnalysisResult>;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=drift-analysis.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drift-analysis.d.ts","sourceRoot":"","sources":["../../src/services/drift-analysis.ts"],"names":[],"mappings":"AACA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC1E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAItD,MAAM,WAAW,oBAAoB;IACnC,oCAAoC;IACpC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,gDAAgD;IAChD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,iCAAiC;IACjC,WAAW,CAAC,EAAE,QAAQ,CAAC;IACvB,2BAA2B;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,iCAAiC;IACjC,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,mCAAmC;IACnC,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,gDAAgD;IAChD,cAAc,EAAE,MAAM,CAAC;IACvB,iCAAiC;IACjC,OAAO,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAYD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG;IAC5D,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd,CAOA;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,WAAW,EAAE,EACrB,MAAM,EAAE,QAAQ,GAAG,MAAM,GACxB,OAAO,CAIT;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE,CAIzE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,WAAW,EAAE,EACrB,WAAW,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,EAC1C,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GACpC,WAAW,EAAE,CAqBf;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,WAAW,EAAE,EACrB,WAAW,EAAE,QAAQ,GACpB,WAAW,EAAE,CAGf;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,WAAW,EAAE,EACrB,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CAEf;AAED;;GAEG;AACH,qBAAa,oBAAoB;IACnB,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,UAAU;IAEtC;;OAEG;IACG,OAAO,CAAC,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,mBAAmB,CAAC;CA4DhF"}
|